feat(skills): inject brain context into review, debug, spec, tdd before spawning workers
This commit is contained in:
@@ -113,11 +113,12 @@ func main() {
|
|||||||
|
|
||||||
reg := registry.New()
|
reg := registry.New()
|
||||||
reg.Register(tdd.New(tdd.Config{
|
reg.Register(tdd.New(tdd.Config{
|
||||||
SystemPrompt: string(systemPrompt),
|
SystemPrompt: string(systemPrompt),
|
||||||
SkillPrompt: string(tddPrompt),
|
SkillPrompt: string(tddPrompt),
|
||||||
DefaultModel: models.ChainFor("tdd", "")[0],
|
DefaultModel: models.ChainFor("tdd", "")[0],
|
||||||
ExecutorFn: buildOrch("tdd"),
|
ExecutorFn: buildOrch("tdd"),
|
||||||
SessionsDir: cfg.SessionsDir,
|
SessionsDir: cfg.SessionsDir,
|
||||||
|
IngestBaseURL: cfg.IngestBaseURL,
|
||||||
}))
|
}))
|
||||||
reg.Register(brain.New(brain.Config{
|
reg.Register(brain.New(brain.Config{
|
||||||
IngestBaseURL: cfg.IngestBaseURL,
|
IngestBaseURL: cfg.IngestBaseURL,
|
||||||
@@ -135,22 +136,25 @@ func main() {
|
|||||||
ExecutorFn: buildOrch("retrospective"),
|
ExecutorFn: buildOrch("retrospective"),
|
||||||
}))
|
}))
|
||||||
reg.Register(review.New(review.Config{
|
reg.Register(review.New(review.Config{
|
||||||
SkillPrompt: string(reviewPrompt),
|
SkillPrompt: string(reviewPrompt),
|
||||||
DefaultModel: models.ChainFor("review", "")[0],
|
DefaultModel: models.ChainFor("review", "")[0],
|
||||||
ExecutorFn: buildOrch("review"),
|
ExecutorFn: buildOrch("review"),
|
||||||
SessionsDir: cfg.SessionsDir,
|
SessionsDir: cfg.SessionsDir,
|
||||||
|
IngestBaseURL: cfg.IngestBaseURL,
|
||||||
}))
|
}))
|
||||||
reg.Register(skilldebug.New(skilldebug.Config{
|
reg.Register(skilldebug.New(skilldebug.Config{
|
||||||
SkillPrompt: string(debugPrompt),
|
SkillPrompt: string(debugPrompt),
|
||||||
DefaultModel: models.ChainFor("debug", "")[0],
|
DefaultModel: models.ChainFor("debug", "")[0],
|
||||||
ExecutorFn: buildOrch("debug"),
|
ExecutorFn: buildOrch("debug"),
|
||||||
SessionsDir: cfg.SessionsDir,
|
SessionsDir: cfg.SessionsDir,
|
||||||
|
IngestBaseURL: cfg.IngestBaseURL,
|
||||||
}))
|
}))
|
||||||
reg.Register(spec.New(spec.Config{
|
reg.Register(spec.New(spec.Config{
|
||||||
SkillPrompt: string(specPrompt),
|
SkillPrompt: string(specPrompt),
|
||||||
DefaultModel: models.ChainFor("spec", "")[0],
|
DefaultModel: models.ChainFor("spec", "")[0],
|
||||||
ExecutorFn: buildOrch("spec"),
|
ExecutorFn: buildOrch("spec"),
|
||||||
SessionsDir: cfg.SessionsDir,
|
SessionsDir: cfg.SessionsDir,
|
||||||
|
IngestBaseURL: cfg.IngestBaseURL,
|
||||||
}))
|
}))
|
||||||
reg.Register(trainer.New(trainer.Config{
|
reg.Register(trainer.New(trainer.Config{
|
||||||
ReaderPrompt: string(trainerReaderPrompt),
|
ReaderPrompt: string(trainerReaderPrompt),
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/mathiasbq/supervisor/internal/brain"
|
||||||
iexec "github.com/mathiasbq/supervisor/internal/exec"
|
iexec "github.com/mathiasbq/supervisor/internal/exec"
|
||||||
"github.com/mathiasbq/supervisor/internal/session"
|
"github.com/mathiasbq/supervisor/internal/session"
|
||||||
)
|
)
|
||||||
@@ -40,11 +41,16 @@ func (s *Skill) Handle(ctx context.Context, tool string, args json.RawMessage) (
|
|||||||
model = s.cfg.DefaultModel
|
model = s.cfg.DefaultModel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
brainCtx, _ := brain.Query(ctx, s.cfg.IngestBaseURL, a.Error+" "+a.Context, 3)
|
||||||
|
|
||||||
task := fmt.Sprintf(
|
task := fmt.Sprintf(
|
||||||
"phase: debug\nproject_root: %s\nerror: %s\ncontext: %s\nmodel: %s",
|
"phase: debug\nproject_root: %s\nerror: %s\ncontext: %s\nmodel: %s",
|
||||||
a.ProjectRoot, a.Error, a.Context, model,
|
a.ProjectRoot, a.Error, a.Context, model,
|
||||||
)
|
)
|
||||||
task = session.PrependHistory(s.cfg.SessionsDir, a.SessionID, "debug", task)
|
task = session.PrependHistory(s.cfg.SessionsDir, a.SessionID, "debug", task)
|
||||||
|
if brainCtx != "" {
|
||||||
|
task = brainCtx + "\n---\n\n" + task
|
||||||
|
}
|
||||||
|
|
||||||
if s.cfg.ExecutorFn == nil {
|
if s.cfg.ExecutorFn == nil {
|
||||||
return nil, fmt.Errorf("no executor configured")
|
return nil, fmt.Errorf("no executor configured")
|
||||||
|
|||||||
@@ -14,10 +14,11 @@ type ExecutorFn func(ctx context.Context, req iexec.Request) (iexec.Result, erro
|
|||||||
|
|
||||||
// Config holds dependencies for the debug skill.
|
// Config holds dependencies for the debug skill.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
SkillPrompt string
|
SkillPrompt string
|
||||||
DefaultModel string
|
DefaultModel string
|
||||||
ExecutorFn ExecutorFn
|
ExecutorFn ExecutorFn
|
||||||
SessionsDir string
|
SessionsDir string
|
||||||
|
IngestBaseURL string // optional: base URL of ingestion server for brain context
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skill implements the debug MCP tool.
|
// Skill implements the debug MCP tool.
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/mathiasbq/supervisor/internal/brain"
|
||||||
iexec "github.com/mathiasbq/supervisor/internal/exec"
|
iexec "github.com/mathiasbq/supervisor/internal/exec"
|
||||||
"github.com/mathiasbq/supervisor/internal/session"
|
"github.com/mathiasbq/supervisor/internal/session"
|
||||||
)
|
)
|
||||||
@@ -41,11 +42,16 @@ func (s *Skill) Handle(ctx context.Context, tool string, args json.RawMessage) (
|
|||||||
model = s.cfg.DefaultModel
|
model = s.cfg.DefaultModel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
brainCtx, _ := brain.Query(ctx, s.cfg.IngestBaseURL, strings.Join(a.Files, " ")+" "+a.Context, 3)
|
||||||
|
|
||||||
task := fmt.Sprintf(
|
task := fmt.Sprintf(
|
||||||
"phase: review\nproject_root: %s\nfiles: %s\ncontext: %s\nmodel: %s",
|
"phase: review\nproject_root: %s\nfiles: %s\ncontext: %s\nmodel: %s",
|
||||||
a.ProjectRoot, strings.Join(a.Files, ", "), a.Context, model,
|
a.ProjectRoot, strings.Join(a.Files, ", "), a.Context, model,
|
||||||
)
|
)
|
||||||
task = session.PrependHistory(s.cfg.SessionsDir, a.SessionID, "review", task)
|
task = session.PrependHistory(s.cfg.SessionsDir, a.SessionID, "review", task)
|
||||||
|
if brainCtx != "" {
|
||||||
|
task = brainCtx + "\n---\n\n" + task
|
||||||
|
}
|
||||||
|
|
||||||
if s.cfg.ExecutorFn == nil {
|
if s.cfg.ExecutorFn == nil {
|
||||||
return nil, fmt.Errorf("no executor configured")
|
return nil, fmt.Errorf("no executor configured")
|
||||||
|
|||||||
@@ -14,10 +14,11 @@ type ExecutorFn func(ctx context.Context, req iexec.Request) (iexec.Result, erro
|
|||||||
|
|
||||||
// Config holds dependencies for the review skill.
|
// Config holds dependencies for the review skill.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
SkillPrompt string
|
SkillPrompt string
|
||||||
DefaultModel string
|
DefaultModel string
|
||||||
ExecutorFn ExecutorFn
|
ExecutorFn ExecutorFn
|
||||||
SessionsDir string
|
SessionsDir string
|
||||||
|
IngestBaseURL string // optional: base URL of ingestion server for brain context
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skill implements the review MCP tool.
|
// Skill implements the review MCP tool.
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/mathiasbq/supervisor/internal/brain"
|
||||||
iexec "github.com/mathiasbq/supervisor/internal/exec"
|
iexec "github.com/mathiasbq/supervisor/internal/exec"
|
||||||
"github.com/mathiasbq/supervisor/internal/session"
|
"github.com/mathiasbq/supervisor/internal/session"
|
||||||
)
|
)
|
||||||
@@ -45,11 +46,16 @@ func (s *Skill) Handle(ctx context.Context, tool string, args json.RawMessage) (
|
|||||||
model = s.cfg.DefaultModel
|
model = s.cfg.DefaultModel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
brainCtx, _ := brain.Query(ctx, s.cfg.IngestBaseURL, a.Requirements+" "+a.Context, 3)
|
||||||
|
|
||||||
task := fmt.Sprintf(
|
task := fmt.Sprintf(
|
||||||
"phase: spec\nproject_root: %s\nrequirements: %s\noutput_path: %s\ncontext: %s\nmodel: %s",
|
"phase: spec\nproject_root: %s\nrequirements: %s\noutput_path: %s\ncontext: %s\nmodel: %s",
|
||||||
a.ProjectRoot, a.Requirements, outputPath, a.Context, model,
|
a.ProjectRoot, a.Requirements, outputPath, a.Context, model,
|
||||||
)
|
)
|
||||||
task = session.PrependHistory(s.cfg.SessionsDir, a.SessionID, "spec", task)
|
task = session.PrependHistory(s.cfg.SessionsDir, a.SessionID, "spec", task)
|
||||||
|
if brainCtx != "" {
|
||||||
|
task = brainCtx + "\n---\n\n" + task
|
||||||
|
}
|
||||||
|
|
||||||
if s.cfg.ExecutorFn == nil {
|
if s.cfg.ExecutorFn == nil {
|
||||||
return nil, fmt.Errorf("no executor configured")
|
return nil, fmt.Errorf("no executor configured")
|
||||||
|
|||||||
@@ -14,10 +14,11 @@ type ExecutorFn func(ctx context.Context, req iexec.Request) (iexec.Result, erro
|
|||||||
|
|
||||||
// Config holds dependencies for the spec skill.
|
// Config holds dependencies for the spec skill.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
SkillPrompt string
|
SkillPrompt string
|
||||||
DefaultModel string
|
DefaultModel string
|
||||||
ExecutorFn ExecutorFn
|
ExecutorFn ExecutorFn
|
||||||
SessionsDir string
|
SessionsDir string
|
||||||
|
IngestBaseURL string // optional: base URL of ingestion server for brain context
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skill implements the spec MCP tool.
|
// Skill implements the spec MCP tool.
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/mathiasbq/supervisor/internal/brain"
|
||||||
iexec "github.com/mathiasbq/supervisor/internal/exec"
|
iexec "github.com/mathiasbq/supervisor/internal/exec"
|
||||||
"github.com/mathiasbq/supervisor/internal/session"
|
"github.com/mathiasbq/supervisor/internal/session"
|
||||||
)
|
)
|
||||||
@@ -41,10 +42,15 @@ func (s *Skill) handleRed(ctx context.Context, raw json.RawMessage) (json.RawMes
|
|||||||
if args.Spec == "" {
|
if args.Spec == "" {
|
||||||
return nil, fmt.Errorf("spec is required")
|
return nil, fmt.Errorf("spec is required")
|
||||||
}
|
}
|
||||||
|
brainCtx, _ := brain.Query(ctx, s.cfg.IngestBaseURL, args.Spec, 3)
|
||||||
|
|
||||||
task := fmt.Sprintf(
|
task := fmt.Sprintf(
|
||||||
"phase: red\nproject_root: %s\nspec: %s\nmodel: %s\ntest_cmd: %s",
|
"phase: red\nproject_root: %s\nspec: %s\nmodel: %s\ntest_cmd: %s",
|
||||||
args.ProjectRoot, args.Spec, s.resolveModel(args.Model), args.TestCmd,
|
args.ProjectRoot, args.Spec, s.resolveModel(args.Model), args.TestCmd,
|
||||||
)
|
)
|
||||||
|
if brainCtx != "" {
|
||||||
|
task = brainCtx + "\n---\n\n" + task
|
||||||
|
}
|
||||||
return s.execute(ctx, task)
|
return s.execute(ctx, task)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,11 +12,12 @@ import (
|
|||||||
type ExecutorFn func(ctx context.Context, req iexec.Request) (iexec.Result, error)
|
type ExecutorFn func(ctx context.Context, req iexec.Request) (iexec.Result, error)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
SystemPrompt string
|
SystemPrompt string
|
||||||
SkillPrompt string
|
SkillPrompt string
|
||||||
ExecutorFn ExecutorFn // nil = no executor (tests that don't reach execute())
|
ExecutorFn ExecutorFn // nil = no executor (tests that don't reach execute())
|
||||||
DefaultModel string
|
DefaultModel string
|
||||||
SessionsDir string // optional: path to brain/sessions/ for history injection
|
SessionsDir string // optional: path to brain/sessions/ for history injection
|
||||||
|
IngestBaseURL string // optional: base URL of ingestion server for brain context
|
||||||
}
|
}
|
||||||
|
|
||||||
type Skill struct {
|
type Skill struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user