refactor: extract instance.go fork initialization to initInstanceExt

Move subagents config, skills filter, orchestration flag, plan model
resolution, and worktree pruning into initInstanceExt() in
instance_ext.go. NewAgentInstance calls initInstanceExt() after
constructing the base struct.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
dj-oyu 2026-03-15 18:41:42 +09:00
parent 210608b20f
commit bbe618a095
2 changed files with 49 additions and 41 deletions

View file

@ -9,7 +9,6 @@ import (
"strings" "strings"
"github.com/sipeed/picoclaw/pkg/config" "github.com/sipeed/picoclaw/pkg/config"
"github.com/sipeed/picoclaw/pkg/git"
"github.com/sipeed/picoclaw/pkg/providers" "github.com/sipeed/picoclaw/pkg/providers"
"github.com/sipeed/picoclaw/pkg/routing" "github.com/sipeed/picoclaw/pkg/routing"
"github.com/sipeed/picoclaw/pkg/session" "github.com/sipeed/picoclaw/pkg/session"
@ -141,23 +140,10 @@ func NewAgentInstance(
agentID := routing.DefaultAgentID agentID := routing.DefaultAgentID
agentName := "" agentName := ""
var subagents *config.SubagentsConfig
var skillsFilter []string
if agentCfg != nil { if agentCfg != nil {
agentID = routing.NormalizeAgentID(agentCfg.ID) agentID = routing.NormalizeAgentID(agentCfg.ID)
agentName = agentCfg.Name agentName = agentCfg.Name
subagents = agentCfg.Subagents
skillsFilter = agentCfg.Skills
}
// Apply defaults.Orchestration: if the flag is set, ensure orchestration is enabled.
if defaults.Orchestration {
if subagents == nil {
subagents = &config.SubagentsConfig{Enabled: true}
} else {
subagents.Enabled = true
}
} }
maxIter := defaults.MaxToolIterations maxIter := defaults.MaxToolIterations
@ -243,19 +229,6 @@ func NewAgentInstance(
candidates := providers.ResolveCandidatesWithLookup(modelCfg, defaults.Provider, resolveFromModelList) candidates := providers.ResolveCandidatesWithLookup(modelCfg, defaults.Provider, resolveFromModelList)
// Resolve plan model (for interviewing/review phases)
planModel := resolvePlanModel(agentCfg, defaults)
planFallbacks := resolvePlanFallbacks(agentCfg, defaults)
var planCandidates []providers.FallbackCandidate
if planModel != "" {
planModelCfg := providers.ModelConfig{
Primary: planModel,
Fallbacks: planFallbacks,
}
planCandidates = providers.ResolveCandidates(planModelCfg, defaults.Provider)
}
// Model routing setup: pre-resolve light model candidates at creation time // Model routing setup: pre-resolve light model candidates at creation time
// to avoid repeated model_list lookups on every incoming message. // to avoid repeated model_list lookups on every incoming message.
var router *routing.Router var router *routing.Router
@ -275,17 +248,7 @@ func NewAgentInstance(
} }
} }
// Startup cleanup: prune orphaned worktrees agent := &AgentInstance{
worktreesDir := filepath.Join(workspace, ".worktrees")
if repoRoot := git.FindRepoRoot(workspace); repoRoot != "" {
git.PruneOrphaned(repoRoot, worktreesDir)
}
return &AgentInstance{
instanceExt: instanceExt{
Subagents: subagents,
SkillsFilter: skillsFilter,
},
ID: agentID, ID: agentID,
Name: agentName, Name: agentName,
Model: model, Model: model,
@ -304,12 +267,14 @@ func NewAgentInstance(
ContextBuilder: contextBuilder, ContextBuilder: contextBuilder,
Tools: toolsRegistry, Tools: toolsRegistry,
Candidates: candidates, Candidates: candidates,
PlanModel: planModel,
PlanFallbacks: planFallbacks,
PlanCandidates: planCandidates,
Router: router, Router: router,
LightCandidates: lightCandidates, LightCandidates: lightCandidates,
} }
// Initialize fork-specific fields (subagents, plan model, worktree pruning).
agent.initInstanceExt(agentCfg, defaults, cfg)
return agent
} }
// resolveAgentWorkspace determines the workspace directory for an agent. // resolveAgentWorkspace determines the workspace directory for an agent.

View file

@ -2,10 +2,12 @@ package agent
import ( import (
"fmt" "fmt"
"path/filepath"
"sync" "sync"
"github.com/sipeed/picoclaw/pkg/config" "github.com/sipeed/picoclaw/pkg/config"
"github.com/sipeed/picoclaw/pkg/git" "github.com/sipeed/picoclaw/pkg/git"
"github.com/sipeed/picoclaw/pkg/providers"
"github.com/sipeed/picoclaw/pkg/tools" "github.com/sipeed/picoclaw/pkg/tools"
) )
@ -28,6 +30,47 @@ type instanceExt struct {
worktreeMu sync.RWMutex worktreeMu sync.RWMutex
} }
// initInstanceExt initializes fork-specific fields: subagents config,
// skills filter, plan model resolution, and worktree pruning.
func (ai *AgentInstance) initInstanceExt(
agentCfg *config.AgentConfig,
defaults *config.AgentDefaults,
cfg *config.Config,
) {
// Extract subagents and skills filter from agent config
if agentCfg != nil {
ai.Subagents = agentCfg.Subagents
ai.SkillsFilter = agentCfg.Skills
}
// Apply defaults.Orchestration: if the flag is set, ensure orchestration is enabled.
if defaults.Orchestration {
if ai.Subagents == nil {
ai.Subagents = &config.SubagentsConfig{Enabled: true}
} else {
ai.Subagents.Enabled = true
}
}
// Resolve plan model (for interviewing/review phases)
ai.PlanModel = resolvePlanModel(agentCfg, defaults)
ai.PlanFallbacks = resolvePlanFallbacks(agentCfg, defaults)
if ai.PlanModel != "" {
planModelCfg := providers.ModelConfig{
Primary: ai.PlanModel,
Fallbacks: ai.PlanFallbacks,
}
ai.PlanCandidates = providers.ResolveCandidates(planModelCfg, defaults.Provider)
}
// Startup cleanup: prune orphaned worktrees
worktreesDir := filepath.Join(ai.Workspace, ".worktrees")
if repoRoot := git.FindRepoRoot(ai.Workspace); repoRoot != "" {
git.PruneOrphaned(repoRoot, worktreesDir)
}
}
// ActivateWorktree creates a worktree for a session. // ActivateWorktree creates a worktree for a session.
// projectDir is the git repository to create the worktree in. // projectDir is the git repository to create the worktree in.
// If empty, falls back to ai.Workspace. // If empty, falls back to ai.Workspace.