feat(agentic): add brain recall CLI command

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-01 21:14:02 +00:00
parent b0662c282b
commit d6a03be140
2 changed files with 169 additions and 0 deletions

View file

@ -39,6 +39,8 @@ func (s *PrepSubsystem) registerCommands(ctx context.Context) {
c.Command("agentic:mirror", core.Command{Description: "Mirror Forge repos to GitHub", Action: s.cmdMirror})
c.Command("brain/ingest", core.Command{Description: "Bulk ingest memories into OpenBrain", Action: s.cmdBrainIngest})
c.Command("brain:ingest", core.Command{Description: "Bulk ingest memories into OpenBrain", Action: s.cmdBrainIngest})
c.Command("brain/recall", core.Command{Description: "Recall memories from OpenBrain", Action: s.cmdBrainRecall})
c.Command("brain:recall", core.Command{Description: "Recall memories from OpenBrain", Action: s.cmdBrainRecall})
c.Command("brain/seed-memory", core.Command{Description: "Import markdown memories into OpenBrain from a project memory directory", Action: s.cmdBrainSeedMemory})
c.Command("brain:seed-memory", core.Command{Description: "Import markdown memories into OpenBrain from a project memory directory", Action: s.cmdBrainSeedMemory})
c.Command("brain/list", core.Command{Description: "List memories in OpenBrain", Action: s.cmdBrainList})
@ -463,6 +465,59 @@ func (s *PrepSubsystem) cmdBrainList(options core.Options) core.Result {
return core.Result{Value: output, OK: true}
}
// result := c.Command("brain/recall").Run(ctx, core.NewOptions(
//
// core.Option{Key: "query", Value: "workspace handoff context"},
//
// ))
func (s *PrepSubsystem) cmdBrainRecall(options core.Options) core.Result {
query := optionStringValue(options, "query", "_arg")
if query == "" {
core.Print(nil, "usage: core-agent brain recall <query> [--top-k=10] [--project=agent] [--type=architecture] [--agent=virgil] [--min-confidence=0.7]")
return core.Result{Value: core.E("agentic.cmdBrainRecall", "query is required", nil), OK: false}
}
result := s.Core().Action("brain.recall").Run(s.commandContext(), core.NewOptions(
core.Option{Key: "query", Value: query},
core.Option{Key: "top_k", Value: optionIntValue(options, "top_k", "top-k")},
core.Option{Key: "project", Value: optionStringValue(options, "project")},
core.Option{Key: "type", Value: optionStringValue(options, "type")},
core.Option{Key: "agent_id", Value: optionStringValue(options, "agent_id", "agent")},
core.Option{Key: "min_confidence", Value: optionStringValue(options, "min_confidence", "min-confidence")},
))
if !result.OK {
err := commandResultError("agentic.cmdBrainRecall", result)
core.Print(nil, "error: %v", err)
return core.Result{Value: err, OK: false}
}
output, ok := brainRecallOutputFromResult(result.Value)
if !ok {
err := core.E("agentic.cmdBrainRecall", "invalid brain recall output", nil)
core.Print(nil, "error: %v", err)
return core.Result{Value: err, OK: false}
}
core.Print(nil, "count: %d", output.Count)
if len(output.Memories) == 0 {
core.Print(nil, "no memories")
return core.Result{Value: output, OK: true}
}
for _, memory := range output.Memories {
if memory.Project != "" || memory.AgentID != "" || memory.Confidence != 0 {
core.Print(nil, " %s %-12s %s %s %.2f", memory.ID, memory.Type, memory.Project, memory.AgentID, memory.Confidence)
} else {
core.Print(nil, " %s %-12s", memory.ID, memory.Type)
}
if memory.Content != "" {
core.Print(nil, " %s", memory.Content)
}
}
return core.Result{Value: output, OK: true}
}
// result := c.Command("brain/forget").Run(ctx, core.NewOptions(core.Option{Key: "_arg", Value: "mem-1"}))
func (s *PrepSubsystem) cmdBrainForget(options core.Options) core.Result {
id := optionStringValue(options, "id", "_arg")
@ -488,6 +543,43 @@ func (s *PrepSubsystem) cmdBrainForget(options core.Options) core.Result {
return core.Result{Value: result.Value, OK: true}
}
type brainRecallOutput struct {
Count int `json:"count"`
Memories []brainRecallMemory `json:"memories"`
}
type brainRecallMemory struct {
ID string `json:"id"`
Type string `json:"type"`
Content string `json:"content"`
Project string `json:"project"`
AgentID string `json:"agent_id"`
Confidence float64 `json:"confidence"`
Tags []string `json:"tags"`
}
func brainRecallOutputFromResult(value any) (brainRecallOutput, bool) {
switch typed := value.(type) {
case brainRecallOutput:
return typed, true
case *brainRecallOutput:
if typed == nil {
return brainRecallOutput{}, false
}
return *typed, true
default:
jsonResult := core.JSONMarshalString(value)
if jsonResult == "" {
return brainRecallOutput{}, false
}
var output brainRecallOutput
if parseResult := core.JSONUnmarshalString(jsonResult, &output); !parseResult.OK {
return brainRecallOutput{}, false
}
return output, true
}
}
func (s *PrepSubsystem) cmdStatus(options core.Options) core.Result {
workspaceRoot := WorkspaceRoot()
filesystem := s.Core().Fs()

View file

@ -225,6 +225,15 @@ func TestCommandsforge_CmdIssueCreate_Good_WithLabelsAndMilestone(t *testing.T)
assert.True(t, r.OK)
}
func TestCommands_RegisterCommands_Good_BrainRecall(t *testing.T) {
s, c := testPrepWithCore(t, nil)
s.registerCommands(context.Background())
assert.Contains(t, c.Commands(), "brain/recall")
assert.Contains(t, c.Commands(), "brain:recall")
}
func TestCommands_CmdBrainList_Good(t *testing.T) {
s, c := testPrepWithCore(t, nil)
c.Action("brain.list", func(_ context.Context, options core.Options) core.Result {
@ -287,6 +296,74 @@ func TestCommands_CmdBrainList_Ugly_InvalidOutput(t *testing.T) {
assert.Contains(t, err.Error(), "invalid brain list output")
}
func TestCommands_CmdBrainRecall_Good(t *testing.T) {
s, c := testPrepWithCore(t, nil)
c.Action("brain.recall", func(_ context.Context, options core.Options) core.Result {
assert.Equal(t, "workspace handoff context", options.String("query"))
assert.Equal(t, 3, options.Int("top_k"))
assert.Equal(t, "agent", options.String("project"))
assert.Equal(t, "architecture", options.String("type"))
assert.Equal(t, "virgil", options.String("agent_id"))
assert.Equal(t, "0.75", options.String("min_confidence"))
return core.Result{Value: map[string]any{
"success": true,
"count": 1,
"memories": []any{
map[string]any{
"id": "mem-1",
"type": "architecture",
"content": "Use named actions.",
"project": "agent",
"agent_id": "virgil",
"confidence": 0.75,
"tags": []any{"architecture", "convention"},
},
},
}, OK: true}
})
output := captureStdout(t, func() {
result := s.cmdBrainRecall(core.NewOptions(
core.Option{Key: "_arg", Value: "workspace handoff context"},
core.Option{Key: "top_k", Value: 3},
core.Option{Key: "project", Value: "agent"},
core.Option{Key: "type", Value: "architecture"},
core.Option{Key: "agent", Value: "virgil"},
core.Option{Key: "min_confidence", Value: "0.75"},
))
require.True(t, result.OK)
})
assert.Contains(t, output, "count: 1")
assert.Contains(t, output, "mem-1 architecture")
assert.Contains(t, output, "Use named actions.")
}
func TestCommands_CmdBrainRecall_Bad_MissingQuery(t *testing.T) {
s, _ := testPrepWithCore(t, nil)
result := s.cmdBrainRecall(core.NewOptions())
require.False(t, result.OK)
err, ok := result.Value.(error)
require.True(t, ok)
assert.Contains(t, err.Error(), "query is required")
}
func TestCommands_CmdBrainRecall_Ugly_InvalidOutput(t *testing.T) {
s, c := testPrepWithCore(t, nil)
c.Action("brain.recall", func(_ context.Context, _ core.Options) core.Result {
return core.Result{Value: 123, OK: true}
})
result := s.cmdBrainRecall(core.NewOptions(core.Option{Key: "_arg", Value: "workspace handoff context"}))
require.False(t, result.OK)
err, ok := result.Value.(error)
require.True(t, ok)
assert.Contains(t, err.Error(), "invalid brain recall output")
}
func TestCommands_CmdBrainForget_Good(t *testing.T) {
s, c := testPrepWithCore(t, nil)
c.Action("brain.forget", func(_ context.Context, options core.Options) core.Result {