Version: 0.9.31.dev.260419
后端: 1. 日程暂存接口——前端拖拽调整后保存到 Redis 快照 - api/agent.go:新增 SaveScheduleState handler,解析绝对时间格式请求体,3 秒超时保护 - routers/routers.go:注册 POST /schedule-state - model/agent.go:新增 SaveScheduleStatePlacedItem / SaveScheduleStateRequest 结构体 - respond/respond.go:新增 5 个排程状态错误码(40058~40062) - 新增 service/agentsvc/agent_schedule_state.go:Load 快照 → ApplyPlacedItems → Save 回 Redis,校验归属 - 新增 newAgent/conv/schedule_state_apply.go:ApplyPlacedItems 绝对坐标→相对 day_index 转换,去重/坐标/嵌入关系校验 2. SchedulePersistor 持久化层全面下线 - 删除 newAgent/conv/schedule_persist.go(280 行,DiffScheduleState → applyChange → 事务写库整条链路) - model/state_store.go:移除 SchedulePersistor 接口 - model/graph_run_state.go / node/execute.go / node/agent_nodes.go / service/agent.go / service/agent_newagent.go / cmd/start.go:移除 SchedulePersistor 字段、参数、注入六处 3. schedule_completed 事件推送——deliver 节点排程完毕信号 - model/common_state.go:新增 HasScheduleChanges 标记,ResetForNextRun 清理 - node/execute.go / node/rough_build.go:写工具和粗排成功后置 HasScheduleChanges=true - node/deliver.go:IsCompleted && HasScheduleChanges 时调用 EmitScheduleCompleted - stream/emitter.go:新增 EmitScheduleCompleted 方法 - stream/openai.go:新增 StreamExtraKindScheduleCompleted + NewScheduleCompletedExtra 4. 预览接口补全 task_class_id - model/agent.go:GetSchedulePlanPreviewResponse 新增 TaskClassIDs - model/schedule.go:HybridScheduleEntry 新增 TaskClassID - conv/schedule_preview.go / service/agent_schedule_preview.go / service/schedule.go:三处透传填充 前端: 5. 排程完毕卡片 + 精排弹窗集成 - 新增 api/schedule_agent.ts:getSchedulePreview / saveScheduleState / applyBatchIntoSchedule - types/dashboard.ts:新增 HybridScheduleEntry / SchedulePreviewData / PlacedItem 类型 - components/dashboard/AssistantPanel.vue:监听 schedule_completed 事件异步拉取排程渲染卡片,集成 ScheduleResultCard + ScheduleFineTuneModal;confirm 交互从文本消息改为 resume 协议(approve/reject/cancel) 6. ToolTracePrototypeView 原型页新增日程小卡片 + 拖拽编排弹窗演示 7. DashboardView import 区域尺寸微调
This commit is contained in:
@@ -51,15 +51,14 @@ type AgentService struct {
|
||||
ResolvePlanningWindowFunc func(ctx context.Context, userID int, taskClassIDs []int) (startWeek, startDay, endWeek, endDay int, err error)
|
||||
|
||||
// ── newAgent 依赖(由 cmd/start.go 通过 Set* 方法注入)──
|
||||
toolRegistry *newagenttools.ToolRegistry
|
||||
scheduleProvider newagentmodel.ScheduleStateProvider
|
||||
schedulePersistor newagentmodel.SchedulePersistor
|
||||
agentStateStore newagentmodel.AgentStateStore
|
||||
compactionStore newagentmodel.CompactionStore
|
||||
memoryReader MemoryReader
|
||||
memoryCfg memorymodel.Config
|
||||
memoryObserver memoryobserve.Observer
|
||||
memoryMetrics memoryobserve.MetricsRecorder
|
||||
toolRegistry *newagenttools.ToolRegistry
|
||||
scheduleProvider newagentmodel.ScheduleStateProvider
|
||||
agentStateStore newagentmodel.AgentStateStore
|
||||
compactionStore newagentmodel.CompactionStore
|
||||
memoryReader MemoryReader
|
||||
memoryCfg memorymodel.Config
|
||||
memoryObserver memoryobserve.Observer
|
||||
memoryMetrics memoryobserve.MetricsRecorder
|
||||
}
|
||||
|
||||
// NewAgentService 构造 AgentService。
|
||||
|
||||
@@ -192,7 +192,6 @@ func (s *AgentService) runNewAgentGraph(
|
||||
StateStore: s.agentStateStore,
|
||||
ToolRegistry: s.toolRegistry,
|
||||
ScheduleProvider: s.scheduleProvider,
|
||||
SchedulePersistor: s.schedulePersistor,
|
||||
CompactionStore: s.compactionStore,
|
||||
RoughBuildFunc: s.makeRoughBuildFunc(),
|
||||
WriteSchedulePreview: s.makeWriteSchedulePreviewFunc(),
|
||||
@@ -660,11 +659,6 @@ func (s *AgentService) SetScheduleProvider(provider newagentmodel.ScheduleStateP
|
||||
s.scheduleProvider = provider
|
||||
}
|
||||
|
||||
// schedulePersistor 由 cmd/start.go 注入
|
||||
func (s *AgentService) SetSchedulePersistor(persistor newagentmodel.SchedulePersistor) {
|
||||
s.schedulePersistor = persistor
|
||||
}
|
||||
|
||||
// agentStateStore 由 cmd/start.go 注入
|
||||
func (s *AgentService) SetAgentStateStore(store newagentmodel.AgentStateStore) {
|
||||
s.agentStateStore = store
|
||||
|
||||
@@ -102,6 +102,7 @@ func (s *AgentService) GetSchedulePlanPreview(ctx context.Context, userID int, c
|
||||
Summary: strings.TrimSpace(preview.Summary),
|
||||
CandidatePlans: plans,
|
||||
HybridEntries: cloneHybridEntries(preview.HybridEntries),
|
||||
TaskClassIDs: preview.TaskClassIDs,
|
||||
GeneratedAt: preview.GeneratedAt,
|
||||
}, nil
|
||||
}
|
||||
@@ -214,6 +215,7 @@ func snapshotToSchedulePlanPreviewResponse(snapshot *model.SchedulePlanStateSnap
|
||||
Summary: schedulePlanSummaryOrFallback(strings.TrimSpace(snapshot.FinalSummary)),
|
||||
CandidatePlans: plans,
|
||||
HybridEntries: cloneHybridEntries(snapshot.HybridEntries),
|
||||
TaskClassIDs: snapshot.TaskClassIDs,
|
||||
GeneratedAt: generatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
62
backend/service/agentsvc/agent_schedule_state.go
Normal file
62
backend/service/agentsvc/agent_schedule_state.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package agentsvc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/LoveLosita/smartflow/backend/model"
|
||||
newagentconv "github.com/LoveLosita/smartflow/backend/newAgent/conv"
|
||||
"github.com/LoveLosita/smartflow/backend/respond"
|
||||
)
|
||||
|
||||
// SaveScheduleState 前端暂存日程调整到 Redis 快照。
|
||||
//
|
||||
// 职责边界:
|
||||
// 1. 只负责更新 Redis 中的 ScheduleState 中 source=task_item 的任务;
|
||||
// 2. 接受绝对时间格式(与 apply-batch 统一),由 conv 层转换为内部相对坐标;
|
||||
// 3. source=event 的课程保持快照原值不变;
|
||||
// 4. 不负责写 MySQL、不负责刷新预览缓存;
|
||||
// 5. 不负责触发 graph 执行(由 confirm_action=accept 驱动)。
|
||||
func (s *AgentService) SaveScheduleState(
|
||||
ctx context.Context,
|
||||
userID int,
|
||||
conversationID string,
|
||||
items []model.SaveScheduleStatePlacedItem,
|
||||
) error {
|
||||
// 1. 加载快照。
|
||||
if s.agentStateStore == nil {
|
||||
return errors.New("agent state store 未初始化")
|
||||
}
|
||||
snapshot, ok, err := s.agentStateStore.Load(ctx, conversationID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("加载快照失败: %w", err)
|
||||
}
|
||||
|
||||
if !ok || snapshot == nil || snapshot.ScheduleState == nil {
|
||||
return respond.ScheduleStateSnapshotNotFound
|
||||
}
|
||||
|
||||
// 2. 校验归属。
|
||||
if snapshot.RuntimeState != nil {
|
||||
cs := snapshot.RuntimeState.EnsureCommonState()
|
||||
if cs.UserID != 0 && cs.UserID != userID {
|
||||
return fmt.Errorf("会话归属校验失败:快照 user_id=%d,请求 user_id=%d", cs.UserID, userID)
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 调用 conv 层将绝对时间放置项应用到 ScheduleState。
|
||||
if err := newagentconv.ApplyPlacedItems(snapshot.ScheduleState, items); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 4. 写回 Redis。
|
||||
if err := s.agentStateStore.Save(ctx, conversationID, snapshot); err != nil {
|
||||
return fmt.Errorf("保存快照失败: %w", err)
|
||||
}
|
||||
|
||||
log.Printf("[INFO] schedule state saved chat=%s user=%d item_count=%d",
|
||||
conversationID, userID, len(items))
|
||||
return nil
|
||||
}
|
||||
@@ -860,9 +860,17 @@ func buildHybridEntriesFromSchedulesAndAllocated(
|
||||
Type: "task",
|
||||
Status: "suggested",
|
||||
TaskItemID: item.ID,
|
||||
TaskClassID: derefInt(item.CategoryID),
|
||||
BlockForSuggested: true,
|
||||
})
|
||||
}
|
||||
|
||||
return entries
|
||||
}
|
||||
|
||||
func derefInt(p *int) int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return *p
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user