From f1deedd39d125c56b72b5c1f4c09fd15b20d7429 Mon Sep 17 00:00:00 2001 From: Mathias Bergqvist Date: Mon, 20 Apr 2026 11:28:10 +0200 Subject: [PATCH] feat(main): wire per-skill Orchestrators replacing single executor.Run Each skill now gets its own Orchestrator built from its ChainFor entry, with LiteLLM for local tiers and Claude for cloud tiers. Removes the defunct models.Resolve calls and single shared executor.Run pattern. Co-Authored-By: Claude Sonnet 4.6 --- cmd/supervisor/main.go | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/cmd/supervisor/main.go b/cmd/supervisor/main.go index 14672d0..da41e8f 100644 --- a/cmd/supervisor/main.go +++ b/cmd/supervisor/main.go @@ -84,11 +84,23 @@ func main() { os.Exit(1) } - executor := iexec.New(iexec.Config{ + claudeExec := iexec.New(iexec.Config{ SystemPrompt: string(systemPrompt), LiteLLMBaseURL: cfg.LiteLLMBaseURL, LiteLLMAPIKey: cfg.LiteLLMAPIKey, }) + litellmExec := iexec.NewLiteLLM(cfg.LiteLLMBaseURL, cfg.LiteLLMAPIKey, 0) + verifier := iexec.NewVerifier("", models.Verifier(), 0) + + buildOrch := func(skill string) *iexec.Orchestrator { + rawChain := models.ChainFor(skill, "") + chain := make([]iexec.ChainEntry, len(rawChain)) + for i, m := range rawChain { + chain[i] = iexec.EntryFor(m) + } + attempts := make([]iexec.AttemptRecord, 0, len(chain)) + return iexec.NewOrchestrator(chain, litellmExec.Run, claudeExec.Run, verifier, models.LlamaSwapURL(), &attempts) + } tierFn := func(ctx context.Context) tier.Info { return tier.Detect(ctx, "https://api.anthropic.com", cfg.LiteLLMBaseURL) @@ -98,8 +110,8 @@ func main() { reg.Register(tdd.New(tdd.Config{ SystemPrompt: string(systemPrompt), SkillPrompt: string(tddPrompt), - DefaultModel: models.Resolve("tdd", ""), - ExecutorFn: executor.Run, + DefaultModel: models.ChainFor("tdd", "")[0], + ExecutorFn: buildOrch("tdd").Run, SessionsDir: cfg.SessionsDir, })) reg.Register(brain.New(brain.Config{ @@ -113,33 +125,33 @@ func main() { })) reg.Register(retrospective.New(retrospective.Config{ SkillPrompt: string(retroPrompt), - DefaultModel: models.Resolve("retrospective", ""), + DefaultModel: models.ChainFor("retrospective", "")[0], SessionsDir: cfg.SessionsDir, - ExecutorFn: executor.Run, + ExecutorFn: buildOrch("retrospective").Run, })) reg.Register(review.New(review.Config{ SkillPrompt: string(reviewPrompt), - DefaultModel: models.Resolve("review", ""), - ExecutorFn: executor.Run, + DefaultModel: models.ChainFor("review", "")[0], + ExecutorFn: buildOrch("review").Run, SessionsDir: cfg.SessionsDir, })) reg.Register(skilldebug.New(skilldebug.Config{ SkillPrompt: string(debugPrompt), - DefaultModel: models.Resolve("debug", ""), - ExecutorFn: executor.Run, + DefaultModel: models.ChainFor("debug", "")[0], + ExecutorFn: buildOrch("debug").Run, SessionsDir: cfg.SessionsDir, })) reg.Register(spec.New(spec.Config{ SkillPrompt: string(specPrompt), - DefaultModel: models.Resolve("spec", ""), - ExecutorFn: executor.Run, + DefaultModel: models.ChainFor("spec", "")[0], + ExecutorFn: buildOrch("spec").Run, SessionsDir: cfg.SessionsDir, })) reg.Register(trainer.New(trainer.Config{ ReaderPrompt: string(trainerReaderPrompt), WriterPrompt: string(trainerWriterPrompt), - DefaultModel: models.Resolve("trainer", ""), - ExecutorFn: executor.Run, + DefaultModel: models.ChainFor("trainer", "")[0], + ExecutorFn: buildOrch("trainer").Run, SessionsDir: cfg.SessionsDir, BrainDir: cfg.BrainDir, }))