Version: 0.9.59.dev.260430
后端: 1. 主动调度预览确认主链路落地——新增主动调度数据模型、DAO 与事件契约;接入 dry-run pipeline 与任务触发的 job upsert/cancel;新增 preview 查询与 confirm API,支持 apply_id 幂等确认并同步写入 task_pool 日程 2. 同步更新主动调度实施文档的阶段状态与验收记录 前端: 3. AssistantPanel 脚本层继续解耦——私有类型迁移到独立类型文件,并抽离会话、工具轨迹、思考摘要、任务表单等纯函数辅助逻辑;保持助手面板模板与样式不变,降低表现层回归风险
This commit is contained in:
92
backend/active_scheduler/service/dry_run.go
Normal file
92
backend/active_scheduler/service/dry_run.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/LoveLosita/smartflow/backend/active_scheduler/candidate"
|
||||
schedulercontext "github.com/LoveLosita/smartflow/backend/active_scheduler/context"
|
||||
"github.com/LoveLosita/smartflow/backend/active_scheduler/observe"
|
||||
"github.com/LoveLosita/smartflow/backend/active_scheduler/ports"
|
||||
"github.com/LoveLosita/smartflow/backend/active_scheduler/trigger"
|
||||
)
|
||||
|
||||
// DryRunResult 是 API dry-run / worker 测试入口可直接消费的同步结果。
|
||||
type DryRunResult struct {
|
||||
Context *schedulercontext.ActiveScheduleContext
|
||||
Observation observe.Result
|
||||
Candidates []candidate.Candidate
|
||||
}
|
||||
|
||||
// DryRunService 编排主动调度 dry-run 主链路。
|
||||
//
|
||||
// 职责边界:
|
||||
// 1. 固定执行 BuildContext -> Observe -> GenerateCandidates;
|
||||
// 2. 不调用 LLM、不写 preview、不发 notification、不正式写日程;
|
||||
// 3. 后续 API / worker 应复用该入口,避免出现第二套 dry-run 诊断逻辑。
|
||||
type DryRunService struct {
|
||||
builder *schedulercontext.Builder
|
||||
analyzer *observe.Analyzer
|
||||
generator *candidate.Generator
|
||||
}
|
||||
|
||||
// NewDryRunService 创建主动调度 dry-run 服务。
|
||||
func NewDryRunService(readers ports.Readers) (*DryRunService, error) {
|
||||
builder, err := schedulercontext.NewBuilder(readers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &DryRunService{
|
||||
builder: builder,
|
||||
analyzer: observe.NewAnalyzer(),
|
||||
generator: candidate.NewGenerator(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SetClock 注入测试时钟。
|
||||
func (s *DryRunService) SetClock(clock func() time.Time) {
|
||||
if s != nil && s.builder != nil {
|
||||
s.builder.SetClock(clock)
|
||||
}
|
||||
}
|
||||
|
||||
// DryRun 执行主动调度同步诊断。
|
||||
func (s *DryRunService) DryRun(ctx context.Context, trig trigger.ActiveScheduleTrigger) (*DryRunResult, error) {
|
||||
if s == nil || s.builder == nil || s.analyzer == nil || s.generator == nil {
|
||||
return nil, errors.New("DryRunService 尚未正确初始化")
|
||||
}
|
||||
|
||||
// 1. 构造上下文:读取 task / schedule / feedback 的只读事实快照。
|
||||
activeContext, err := s.builder.BuildContext(ctx, trig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 2. 主动观测:生成 metrics、issues 和初步裁决,不生成正式变更。
|
||||
observation := s.analyzer.Observe(activeContext)
|
||||
|
||||
// 3. 候选生成:只枚举第一版允许的确定性候选,压缩融合保持关闭。
|
||||
candidates := s.generator.GenerateCandidates(activeContext, observation)
|
||||
fallbackCandidateID := ""
|
||||
if len(candidates) > 0 {
|
||||
fallbackCandidateID = candidates[0].CandidateID
|
||||
}
|
||||
observation = s.analyzer.FinalizeDecision(observation, len(applicableCandidates(candidates)), fallbackCandidateID)
|
||||
|
||||
return &DryRunResult{
|
||||
Context: activeContext,
|
||||
Observation: observation,
|
||||
Candidates: candidates,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func applicableCandidates(candidates []candidate.Candidate) []candidate.Candidate {
|
||||
result := make([]candidate.Candidate, 0, len(candidates))
|
||||
for _, item := range candidates {
|
||||
if item.CandidateType == candidate.TypeAddTaskPoolToSchedule || item.CandidateType == candidate.TypeCreateMakeup {
|
||||
result = append(result, item)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user