U4 第一步:Squad 依赖注入解耦(Options + 后端工厂),移除 config.Config 依赖 #4
@@ -10,6 +10,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"chat-agent-system/internal/agent"
|
||||||
"chat-agent-system/internal/app/uow"
|
"chat-agent-system/internal/app/uow"
|
||||||
"chat-agent-system/internal/authz"
|
"chat-agent-system/internal/authz"
|
||||||
"chat-agent-system/internal/config"
|
"chat-agent-system/internal/config"
|
||||||
@@ -192,7 +193,14 @@ func NewService(cfg *config.Config) (*Service, error) {
|
|||||||
svc := &Service{
|
svc := &Service{
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
kb: kb.NewClient(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,
|
ctxMgr: ctxMgr,
|
||||||
cas: casStore,
|
cas: casStore,
|
||||||
materialIndex: matIndex,
|
materialIndex: matIndex,
|
||||||
|
|||||||
+41
-12
@@ -10,7 +10,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"chat-agent-system/internal/agent"
|
"chat-agent-system/internal/agent"
|
||||||
"chat-agent-system/internal/config"
|
|
||||||
"chat-agent-system/internal/quote"
|
"chat-agent-system/internal/quote"
|
||||||
"chat-agent-system/internal/stream"
|
"chat-agent-system/internal/stream"
|
||||||
"chat-agent-system/internal/workflowdef"
|
"chat-agent-system/internal/workflowdef"
|
||||||
@@ -109,18 +108,42 @@ type SquadService interface {
|
|||||||
ResumeOrModifyWorkspace(ctx context.Context, req ModifyWorkflowRequest) (*SquadRunResult, error)
|
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 实现
|
// Service SquadService 实现
|
||||||
type Service struct {
|
type Service struct {
|
||||||
cfg *config.Config
|
opts Options
|
||||||
engine *WorkspaceEngine
|
engine *WorkspaceEngine
|
||||||
driver *WorkflowDriver
|
driver *WorkflowDriver
|
||||||
gate *QualityGate
|
gate *QualityGate
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewService(cfg *config.Config) *Service {
|
func NewService(opts Options) *Service {
|
||||||
engine := NewWorkspaceEngine()
|
engine := NewWorkspaceEngine()
|
||||||
return &Service{
|
return &Service{
|
||||||
cfg: cfg,
|
opts: opts.withDefaults(),
|
||||||
engine: engine,
|
engine: engine,
|
||||||
driver: NewWorkflowDriver(engine),
|
driver: NewWorkflowDriver(engine),
|
||||||
gate: NewQualityGate(),
|
gate: NewQualityGate(),
|
||||||
@@ -207,12 +230,12 @@ func (s *Service) ExecuteTask(ctx context.Context, req SquadRunRequest) (*SquadR
|
|||||||
workDir := req.WorkDir
|
workDir := req.WorkDir
|
||||||
if workDir == "" {
|
if workDir == "" {
|
||||||
ts := time.Now().UnixNano()
|
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
|
backendName := req.Backend
|
||||||
if backendName == "" {
|
if backendName == "" {
|
||||||
backendName = s.cfg.AgentBackend
|
backendName = s.opts.BackendName
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. 初始化工作区目录体系
|
// 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)
|
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
|
timeout := req.Timeout
|
||||||
if timeout <= 0 {
|
if timeout <= 0 {
|
||||||
timeout = s.cfg.AgentTimeout
|
timeout = s.opts.BackendTimeout
|
||||||
}
|
}
|
||||||
execOpts := ExecuteOptions{
|
execOpts := ExecuteOptions{
|
||||||
Timeout: timeout,
|
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) {
|
func (s *Service) ExecuteWorkflow(ctx context.Context, wsDir string, backendName string, opts ExecuteOptions) (*SquadRunResult, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
if backendName == "" {
|
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)
|
execRes, err := s.driver.Execute(ctx, wsDir, backend, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -491,12 +520,12 @@ func (s *Service) ResumeOrModifyWorkspace(ctx context.Context, req ModifyWorkflo
|
|||||||
|
|
||||||
backendName := req.Backend
|
backendName := req.Backend
|
||||||
if backendName == "" {
|
if backendName == "" {
|
||||||
backendName = s.cfg.AgentBackend
|
backendName = s.opts.BackendName
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout := req.Timeout
|
timeout := req.Timeout
|
||||||
if timeout <= 0 {
|
if timeout <= 0 {
|
||||||
timeout = s.cfg.AgentTimeout
|
timeout = s.opts.BackendTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := ExecuteOptions{
|
opts := ExecuteOptions{
|
||||||
|
|||||||
Reference in New Issue
Block a user