refactor(squad): inject Options + backend factory, drop config.Config dependency
KTD1 first step (in-repo decoupling, behavior preserved):
- squad.Options{BackendName, BackendTimeout, DataDir, NewBackend} replaces
*config.Config; defaults applied in withDefaults
- backend construction injected by caller (bizdev assembly): credentials,
environment and concurrency stay product-side; nil factory fails closed
instead of silently degrading to Stub
- verified: go vet ./... clean, squad/bizdev short tests pass
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"chat-agent-system/internal/agent"
|
||||
"chat-agent-system/internal/app/uow"
|
||||
"chat-agent-system/internal/authz"
|
||||
"chat-agent-system/internal/config"
|
||||
@@ -192,7 +193,14 @@ func NewService(cfg *config.Config) (*Service, error) {
|
||||
svc := &Service{
|
||||
cfg: cfg,
|
||||
kb: kb.NewClient(cfg),
|
||||
squad: squad.NewService(cfg),
|
||||
squad: squad.NewService(squad.Options{
|
||||
BackendName: cfg.AgentBackend,
|
||||
BackendTimeout: cfg.AgentTimeout,
|
||||
DataDir: cfg.DataDir,
|
||||
NewBackend: func(name string) agent.Backend {
|
||||
return agent.NewBackend(name, cfg)
|
||||
},
|
||||
}),
|
||||
ctxMgr: ctxMgr,
|
||||
cas: casStore,
|
||||
materialIndex: matIndex,
|
||||
|
||||
+41
-12
@@ -10,7 +10,6 @@ import (
|
||||
"time"
|
||||
|
||||
"chat-agent-system/internal/agent"
|
||||
"chat-agent-system/internal/config"
|
||||
"chat-agent-system/internal/quote"
|
||||
"chat-agent-system/internal/stream"
|
||||
"chat-agent-system/internal/workflowdef"
|
||||
@@ -109,18 +108,42 @@ type SquadService interface {
|
||||
ResumeOrModifyWorkspace(ctx context.Context, req ModifyWorkflowRequest) (*SquadRunResult, error)
|
||||
}
|
||||
|
||||
// Options 是 Squad 依赖注入的唯一配置面;不反向依赖主仓 config.Config,
|
||||
// 为独立模块做准备(见多仓方案 KTD1)。
|
||||
type Options struct {
|
||||
// BackendName 为执行后端名(空 = 由调用方默认)。
|
||||
BackendName string
|
||||
// BackendTimeout 为单次执行超时;零值由调用方默认。
|
||||
BackendTimeout time.Duration
|
||||
// DataDir 为工作区根(任务目录挂在其下)。
|
||||
DataDir string
|
||||
// NewBackend 由调用方注入的后端工厂(Core 装配:凭证、环境、并发上限
|
||||
// 留在产品侧)。nil 时返回错误,不静默降级 Stub。
|
||||
NewBackend func(name string) agent.Backend
|
||||
}
|
||||
|
||||
func (o Options) withDefaults() Options {
|
||||
if o.BackendName == "" {
|
||||
o.BackendName = "pi-agent"
|
||||
}
|
||||
if o.BackendTimeout <= 0 {
|
||||
o.BackendTimeout = 10 * time.Minute
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
// Service SquadService 实现
|
||||
type Service struct {
|
||||
cfg *config.Config
|
||||
opts Options
|
||||
engine *WorkspaceEngine
|
||||
driver *WorkflowDriver
|
||||
gate *QualityGate
|
||||
}
|
||||
|
||||
func NewService(cfg *config.Config) *Service {
|
||||
func NewService(opts Options) *Service {
|
||||
engine := NewWorkspaceEngine()
|
||||
return &Service{
|
||||
cfg: cfg,
|
||||
opts: opts.withDefaults(),
|
||||
engine: engine,
|
||||
driver: NewWorkflowDriver(engine),
|
||||
gate: NewQualityGate(),
|
||||
@@ -207,12 +230,12 @@ func (s *Service) ExecuteTask(ctx context.Context, req SquadRunRequest) (*SquadR
|
||||
workDir := req.WorkDir
|
||||
if workDir == "" {
|
||||
ts := time.Now().UnixNano()
|
||||
workDir = filepath.Join(s.cfg.DataDir, "workspaces", "bizdev", fmt.Sprintf("%s_%d", req.TaskKey, ts))
|
||||
workDir = filepath.Join(s.opts.DataDir, "workspaces", "bizdev", fmt.Sprintf("%s_%d", req.TaskKey, ts))
|
||||
}
|
||||
|
||||
backendName := req.Backend
|
||||
if backendName == "" {
|
||||
backendName = s.cfg.AgentBackend
|
||||
backendName = s.opts.BackendName
|
||||
}
|
||||
|
||||
// 1. 初始化工作区目录体系
|
||||
@@ -258,10 +281,13 @@ func (s *Service) ExecuteTask(ctx context.Context, req SquadRunRequest) (*SquadR
|
||||
streamer.EmitPhase("squad_assembly", fmt.Sprintf("正在组建并启动【%s】智能体小队(后端: %s)...", TaskArtifactTitle(req.TaskKey), backendName), "leader", 0, 0, 5)
|
||||
}
|
||||
|
||||
backend := agent.NewBackend(backendName, s.cfg)
|
||||
if s.opts.NewBackend == nil {
|
||||
return nil, fmt.Errorf("squad: NewBackend factory not injected")
|
||||
}
|
||||
backend := s.opts.NewBackend(backendName)
|
||||
timeout := req.Timeout
|
||||
if timeout <= 0 {
|
||||
timeout = s.cfg.AgentTimeout
|
||||
timeout = s.opts.BackendTimeout
|
||||
}
|
||||
execOpts := ExecuteOptions{
|
||||
Timeout: timeout,
|
||||
@@ -397,9 +423,12 @@ func repairBudgetForSquadTask(req SquadRunRequest) int {
|
||||
func (s *Service) ExecuteWorkflow(ctx context.Context, wsDir string, backendName string, opts ExecuteOptions) (*SquadRunResult, error) {
|
||||
start := time.Now()
|
||||
if backendName == "" {
|
||||
backendName = s.cfg.AgentBackend
|
||||
backendName = s.opts.BackendName
|
||||
}
|
||||
backend := agent.NewBackend(backendName, s.cfg)
|
||||
if s.opts.NewBackend == nil {
|
||||
return nil, fmt.Errorf("squad: NewBackend factory not injected")
|
||||
}
|
||||
backend := s.opts.NewBackend(backendName)
|
||||
|
||||
execRes, err := s.driver.Execute(ctx, wsDir, backend, opts)
|
||||
if err != nil {
|
||||
@@ -491,12 +520,12 @@ func (s *Service) ResumeOrModifyWorkspace(ctx context.Context, req ModifyWorkflo
|
||||
|
||||
backendName := req.Backend
|
||||
if backendName == "" {
|
||||
backendName = s.cfg.AgentBackend
|
||||
backendName = s.opts.BackendName
|
||||
}
|
||||
|
||||
timeout := req.Timeout
|
||||
if timeout <= 0 {
|
||||
timeout = s.cfg.AgentTimeout
|
||||
timeout = s.opts.BackendTimeout
|
||||
}
|
||||
|
||||
opts := ExecuteOptions{
|
||||
|
||||
Reference in New Issue
Block a user