Add Container Model for subagent↔conductor communication: - ContainerMessage + channel-based escalation (ask_conductor, submit_plan) - Deliberate vs Exploratory preset workflows with SubagentPlanState - AnswerSubagentTool + ReviewSubagentPlanTool for conductor side - SessionRecorder extensions (RecordQuestion, RecordPlanSubmit) - Environment context injection (MEMORY.md extraction, plan context) - Orchestration guidance with escalation tools documentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
77 lines
1.8 KiB
Go
77 lines
1.8 KiB
Go
package tools
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestAskConductorTool_Execute(t *testing.T) {
|
|
outCh := make(chan ContainerMessage, 4)
|
|
|
|
inCh := make(chan string, 1)
|
|
|
|
tool := NewAskConductorTool("subagent-1", "conductor:main", "subagent:subagent-1", outCh, inCh, nil)
|
|
|
|
if tool.Name() != "ask_conductor" {
|
|
t.Errorf("Name() = %q, want %q", tool.Name(), "ask_conductor")
|
|
}
|
|
|
|
// Simulate conductor answering in background.
|
|
|
|
go func() {
|
|
msg := <-outCh
|
|
|
|
if msg.Type != "question" {
|
|
t.Errorf("msg.Type = %q, want %q", msg.Type, "question")
|
|
}
|
|
|
|
if msg.Content != "What port?" {
|
|
t.Errorf("msg.Content = %q, want %q", msg.Content, "What port?")
|
|
}
|
|
|
|
inCh <- "Use port 8080"
|
|
}()
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
|
|
defer cancel()
|
|
|
|
result := tool.Execute(ctx, map[string]any{"question": "What port?"})
|
|
|
|
if result.IsError {
|
|
t.Fatalf("unexpected error: %s", result.ForLLM)
|
|
}
|
|
|
|
if result.ForUser != "Use port 8080" {
|
|
t.Errorf("ForUser = %q, want %q", result.ForUser, "Use port 8080")
|
|
}
|
|
}
|
|
|
|
func TestAskConductorTool_MissingQuestion(t *testing.T) {
|
|
tool := NewAskConductorTool("subagent-1", "conductor:main", "subagent:subagent-1", nil, nil, nil)
|
|
|
|
result := tool.Execute(context.Background(), map[string]any{})
|
|
|
|
if !result.IsError {
|
|
t.Error("expected error for missing question")
|
|
}
|
|
}
|
|
|
|
func TestAskConductorTool_ContextCanceled(t *testing.T) {
|
|
outCh := make(chan ContainerMessage) // unbuffered, will block
|
|
|
|
inCh := make(chan string)
|
|
|
|
tool := NewAskConductorTool("subagent-1", "conductor:main", "subagent:subagent-1", outCh, inCh, nil)
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
cancel() // cancel immediately
|
|
|
|
result := tool.Execute(ctx, map[string]any{"question": "test?"})
|
|
|
|
if !result.IsError {
|
|
t.Error("expected error on canceled context")
|
|
}
|
|
}
|