refactor: extract orchestration tool registration to loop_ext.go
Move the 67-line spawn/subagent/answer/review_plan tool registration block from registerSharedTools into registerOrchestrationTools() in loop_ext.go. The upstream-shared registerSharedTools now has a single 1-line call to the extracted function. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9387263dfd
commit
710b703f35
2 changed files with 74 additions and 77 deletions
|
|
@ -298,86 +298,11 @@ func registerSharedTools(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spawn tool — only registered when orchestration is explicitly enabled.
|
// Orchestration tools (spawn, subagent, answer, review_plan)
|
||||||
|
registerOrchestrationTools(cfg, agent, agentID, registry, provider, msgBus, al)
|
||||||
if agent.Subagents != nil && agent.Subagents.Enabled {
|
|
||||||
webSearchOpts := tools.WebSearchToolOptions{
|
|
||||||
BraveAPIKeys: config.MergeAPIKeys(cfg.Tools.Web.Brave.APIKey, cfg.Tools.Web.Brave.APIKeys),
|
|
||||||
BraveMaxResults: cfg.Tools.Web.Brave.MaxResults,
|
|
||||||
BraveEnabled: cfg.Tools.Web.Brave.Enabled,
|
|
||||||
TavilyAPIKeys: config.MergeAPIKeys(cfg.Tools.Web.Tavily.APIKey, cfg.Tools.Web.Tavily.APIKeys),
|
|
||||||
TavilyBaseURL: cfg.Tools.Web.Tavily.BaseURL,
|
|
||||||
TavilyMaxResults: cfg.Tools.Web.Tavily.MaxResults,
|
|
||||||
TavilyEnabled: cfg.Tools.Web.Tavily.Enabled,
|
|
||||||
DuckDuckGoMaxResults: cfg.Tools.Web.DuckDuckGo.MaxResults,
|
|
||||||
DuckDuckGoEnabled: cfg.Tools.Web.DuckDuckGo.Enabled,
|
|
||||||
PerplexityAPIKeys: config.MergeAPIKeys(
|
|
||||||
cfg.Tools.Web.Perplexity.APIKey,
|
|
||||||
cfg.Tools.Web.Perplexity.APIKeys,
|
|
||||||
),
|
|
||||||
PerplexityMaxResults: cfg.Tools.Web.Perplexity.MaxResults,
|
|
||||||
PerplexityEnabled: cfg.Tools.Web.Perplexity.Enabled,
|
|
||||||
}
|
|
||||||
|
|
||||||
subagentManager := tools.NewSubagentManager(
|
|
||||||
|
|
||||||
provider,
|
|
||||||
|
|
||||||
agent.Model,
|
|
||||||
|
|
||||||
agent.Workspace,
|
|
||||||
|
|
||||||
msgBus,
|
|
||||||
|
|
||||||
al.reporter(),
|
|
||||||
|
|
||||||
webSearchOpts,
|
|
||||||
)
|
|
||||||
|
|
||||||
subagentManager.SetLLMOptions(agent.MaxTokens, agent.Temperature)
|
|
||||||
|
|
||||||
// Wire session recorder for DAG persistence.
|
|
||||||
|
|
||||||
recorder := newSessionRecorder(agent.Sessions)
|
|
||||||
|
|
||||||
conductorKey := routing.BuildAgentMainSessionKey(agent.ID)
|
|
||||||
|
|
||||||
subagentManager.SetSessionRecorder(recorder, conductorKey)
|
|
||||||
|
|
||||||
agent.SubagentMgr = subagentManager
|
|
||||||
|
|
||||||
spawnTool := tools.NewSpawnTool(subagentManager)
|
|
||||||
|
|
||||||
currentAgentID := agentID
|
|
||||||
|
|
||||||
spawnTool.SetAllowlistChecker(func(targetAgentID string) bool {
|
|
||||||
return registry.CanSpawnSubagent(currentAgentID, targetAgentID)
|
|
||||||
})
|
|
||||||
|
|
||||||
agent.Tools.Register(spawnTool)
|
|
||||||
|
|
||||||
// Register blocking subagent tool alongside spawn
|
|
||||||
|
|
||||||
subagentTool := tools.NewSubagentTool(subagentManager)
|
|
||||||
|
|
||||||
agent.Tools.Register(subagentTool)
|
|
||||||
|
|
||||||
// Register conductor-side escalation tools (answer questions, review plans)
|
|
||||||
|
|
||||||
agent.Tools.Register(tools.NewAnswerSubagentTool(subagentManager))
|
|
||||||
|
|
||||||
agent.Tools.Register(tools.NewReviewSubagentPlanTool(subagentManager))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update context builder with the complete tools registry
|
// Update context builder with the complete tools registry
|
||||||
|
|
||||||
agent.ContextBuilder.SetToolsRegistry(agent.Tools)
|
agent.ContextBuilder.SetToolsRegistry(agent.Tools)
|
||||||
|
|
||||||
// Set orchestration mode if enabled
|
|
||||||
|
|
||||||
if agent.Subagents != nil && agent.Subagents.Enabled {
|
|
||||||
agent.ContextBuilder.SetOrchestrationEnabled(true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,10 @@ import (
|
||||||
"github.com/sipeed/picoclaw/pkg/config"
|
"github.com/sipeed/picoclaw/pkg/config"
|
||||||
"github.com/sipeed/picoclaw/pkg/logger"
|
"github.com/sipeed/picoclaw/pkg/logger"
|
||||||
"github.com/sipeed/picoclaw/pkg/orch"
|
"github.com/sipeed/picoclaw/pkg/orch"
|
||||||
|
"github.com/sipeed/picoclaw/pkg/providers"
|
||||||
|
"github.com/sipeed/picoclaw/pkg/routing"
|
||||||
"github.com/sipeed/picoclaw/pkg/stats"
|
"github.com/sipeed/picoclaw/pkg/stats"
|
||||||
|
"github.com/sipeed/picoclaw/pkg/tools"
|
||||||
"github.com/sipeed/picoclaw/pkg/utils"
|
"github.com/sipeed/picoclaw/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -82,6 +85,75 @@ func (al *AgentLoop) SetHeartbeatThreadUpdater(fn func(int)) {
|
||||||
al.onHeartbeatThreadUpdate = fn
|
al.onHeartbeatThreadUpdate = fn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// registerOrchestrationTools registers spawn, subagent, answer, and review_plan
|
||||||
|
// tools for agents with orchestration enabled.
|
||||||
|
func registerOrchestrationTools(
|
||||||
|
cfg *config.Config,
|
||||||
|
agent *AgentInstance,
|
||||||
|
agentID string,
|
||||||
|
registry *AgentRegistry,
|
||||||
|
provider providers.LLMProvider,
|
||||||
|
msgBus *bus.MessageBus,
|
||||||
|
al *AgentLoop,
|
||||||
|
) {
|
||||||
|
if agent.Subagents == nil || !agent.Subagents.Enabled {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
webSearchOpts := tools.WebSearchToolOptions{
|
||||||
|
BraveAPIKeys: config.MergeAPIKeys(cfg.Tools.Web.Brave.APIKey, cfg.Tools.Web.Brave.APIKeys),
|
||||||
|
BraveMaxResults: cfg.Tools.Web.Brave.MaxResults,
|
||||||
|
BraveEnabled: cfg.Tools.Web.Brave.Enabled,
|
||||||
|
TavilyAPIKeys: config.MergeAPIKeys(cfg.Tools.Web.Tavily.APIKey, cfg.Tools.Web.Tavily.APIKeys),
|
||||||
|
TavilyBaseURL: cfg.Tools.Web.Tavily.BaseURL,
|
||||||
|
TavilyMaxResults: cfg.Tools.Web.Tavily.MaxResults,
|
||||||
|
TavilyEnabled: cfg.Tools.Web.Tavily.Enabled,
|
||||||
|
DuckDuckGoMaxResults: cfg.Tools.Web.DuckDuckGo.MaxResults,
|
||||||
|
DuckDuckGoEnabled: cfg.Tools.Web.DuckDuckGo.Enabled,
|
||||||
|
PerplexityAPIKeys: config.MergeAPIKeys(
|
||||||
|
cfg.Tools.Web.Perplexity.APIKey,
|
||||||
|
cfg.Tools.Web.Perplexity.APIKeys,
|
||||||
|
),
|
||||||
|
PerplexityMaxResults: cfg.Tools.Web.Perplexity.MaxResults,
|
||||||
|
PerplexityEnabled: cfg.Tools.Web.Perplexity.Enabled,
|
||||||
|
}
|
||||||
|
|
||||||
|
subagentManager := tools.NewSubagentManager(
|
||||||
|
provider,
|
||||||
|
agent.Model,
|
||||||
|
agent.Workspace,
|
||||||
|
msgBus,
|
||||||
|
al.reporter(),
|
||||||
|
webSearchOpts,
|
||||||
|
)
|
||||||
|
|
||||||
|
subagentManager.SetLLMOptions(agent.MaxTokens, agent.Temperature)
|
||||||
|
|
||||||
|
// Wire session recorder for DAG persistence.
|
||||||
|
recorder := newSessionRecorder(agent.Sessions)
|
||||||
|
conductorKey := routing.BuildAgentMainSessionKey(agent.ID)
|
||||||
|
subagentManager.SetSessionRecorder(recorder, conductorKey)
|
||||||
|
|
||||||
|
agent.SubagentMgr = subagentManager
|
||||||
|
|
||||||
|
spawnTool := tools.NewSpawnTool(subagentManager)
|
||||||
|
currentAgentID := agentID
|
||||||
|
spawnTool.SetAllowlistChecker(func(targetAgentID string) bool {
|
||||||
|
return registry.CanSpawnSubagent(currentAgentID, targetAgentID)
|
||||||
|
})
|
||||||
|
agent.Tools.Register(spawnTool)
|
||||||
|
|
||||||
|
// Register blocking subagent tool alongside spawn
|
||||||
|
agent.Tools.Register(tools.NewSubagentTool(subagentManager))
|
||||||
|
|
||||||
|
// Register conductor-side escalation tools (answer questions, review plans)
|
||||||
|
agent.Tools.Register(tools.NewAnswerSubagentTool(subagentManager))
|
||||||
|
agent.Tools.Register(tools.NewReviewSubagentPlanTool(subagentManager))
|
||||||
|
|
||||||
|
// Set orchestration mode on context builder
|
||||||
|
agent.ContextBuilder.SetOrchestrationEnabled(true)
|
||||||
|
}
|
||||||
|
|
||||||
// handleTaskIntervention checks if a message is a reply to an active task and
|
// handleTaskIntervention checks if a message is a reply to an active task and
|
||||||
// either cancels the task or injects a user intervention. Returns (response, handled).
|
// either cancels the task or injects a user intervention. Returns (response, handled).
|
||||||
func (al *AgentLoop) handleTaskIntervention(msg bus.InboundMessage) (string, bool) {
|
func (al *AgentLoop) handleTaskIntervention(msg bus.InboundMessage) (string, bool) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue