Version: 0.9.15.dev.260412

后端:
1. 排程工具从 tools/ 根目录拆分为 tools/schedule 独立子包
- 12 个排程工具文件等价迁入 tools/schedule/,tools/ 根目录仅保留 registry.go 作为统一注册入口
- 所有依赖方(conv / model / node / prompt / service)import 统一切到 schedule 子包
2. Web 搜索工具链落地(tools/web 子包)
- 新增 web_search(结构化检索)与 web_fetch(正文抓取)两个读工具,支持博查 API / mock 降级
- 启动流程按配置选择 provider,未识别类型自动降级为 mock,不阻断主流程
- 执行提示补齐 web 工具使用约束与返回值示例
- config.example.yaml 补齐 websearch 配置段
前端:无
仓库:无
This commit is contained in:
Losita
2026-04-12 19:02:54 +08:00
parent bf1f1defa5
commit 070d4c3459
34 changed files with 1033 additions and 205 deletions

View File

@@ -3,7 +3,7 @@ package model
import (
"strings"
newagenttools "github.com/LoveLosita/smartflow/backend/newAgent/tools"
schedule "github.com/LoveLosita/smartflow/backend/newAgent/tools/schedule"
)
// Phase 表示 agent 主循环当前所处的大阶段。
@@ -92,7 +92,7 @@ type CommonState struct {
TaskClassIDs []int `json:"task_class_ids,omitempty"`
// TaskClasses 本次排课涉及的任务类约束元数据(含日期、策略、时段预算等),
// 在 Service 层从 DB 加载并注入,供 Plan prompt 直接消费,避免 LLM 因信息不足而追问用户。
TaskClasses []newagenttools.TaskClassMeta `json:"task_classes,omitempty"`
TaskClasses []schedule.TaskClassMeta `json:"task_classes,omitempty"`
// NeedsRoughBuild 由 Plan 节点在 plan_done 时写入,标记 Confirm 后是否需要走粗排节点。
// 粗排节点执行完毕后会将此字段重置为 false。

View File

@@ -7,6 +7,7 @@ import (
infrallm "github.com/LoveLosita/smartflow/backend/infra/llm"
newagentstream "github.com/LoveLosita/smartflow/backend/newAgent/stream"
newagenttools "github.com/LoveLosita/smartflow/backend/newAgent/tools"
schedule "github.com/LoveLosita/smartflow/backend/newAgent/tools/schedule"
)
// AgentGraphRequest 描述一次 agent graph 运行的请求级输入。
@@ -48,7 +49,7 @@ type RoughBuildFunc func(ctx context.Context, userID int, taskClassIDs []int) ([
// 由 service 层封装 cacheDAO 后注入execute/deliver 节点可按需调用:
// 1. execute 写工具后可实时刷新,保障前端及时看到最新调整;
// 2. deliver 结束时再做最终覆盖写,保障收口状态一致。
type WriteSchedulePreviewFunc func(ctx context.Context, state *newagenttools.ScheduleState, userID int, conversationID string, taskClassIDs []int) error
type WriteSchedulePreviewFunc func(ctx context.Context, state *schedule.ScheduleState, userID int, conversationID string, taskClassIDs []int) error
// AgentGraphDeps 描述 graph/node 层运行时真正依赖的可插拔能力。
//
@@ -151,8 +152,8 @@ func (d *AgentGraphDeps) ResolveDeliverClient() *infrallm.Client {
type AgentGraphRunInput struct {
RuntimeState *AgentRuntimeState
ConversationContext *ConversationContext
ScheduleState *newagenttools.ScheduleState
OriginalScheduleState *newagenttools.ScheduleState
ScheduleState *schedule.ScheduleState
OriginalScheduleState *schedule.ScheduleState
Request AgentGraphRequest
Deps AgentGraphDeps
}
@@ -168,8 +169,8 @@ type AgentGraphState struct {
ConversationContext *ConversationContext
Request AgentGraphRequest
Deps AgentGraphDeps
ScheduleState *newagenttools.ScheduleState // 工具操作的内存数据源Execute 节点按需加载
OriginalScheduleState *newagenttools.ScheduleState // 首次加载时的原始快照,供 diff 用
ScheduleState *schedule.ScheduleState // 工具操作的内存数据源Execute 节点按需加载
OriginalScheduleState *schedule.ScheduleState // 首次加载时的原始快照,供 diff 用
}
// NewAgentGraphState 把入口参数整理成 graph 内部状态。
@@ -239,7 +240,7 @@ func (s *AgentGraphState) ResolveToolRegistry() *newagenttools.ToolRegistry {
// EnsureScheduleState 确保 ScheduleState 已加载。
// 首次调用时通过 ScheduleProvider 从 DB 加载,后续复用内存中的 state。
func (s *AgentGraphState) EnsureScheduleState(ctx context.Context) (*newagenttools.ScheduleState, error) {
func (s *AgentGraphState) EnsureScheduleState(ctx context.Context) (*schedule.ScheduleState, error) {
if s == nil {
return nil, nil
}
@@ -251,8 +252,8 @@ func (s *AgentGraphState) EnsureScheduleState(ctx context.Context) (*newagenttoo
// 3. 因此这里在“已恢复出 ScheduleState、但缺 original”时补一份克隆兜底。
s.OriginalScheduleState = s.ScheduleState.Clone()
}
newagenttools.FilterScheduleStateForTaskClassScope(s.ScheduleState, flowState.TaskClassIDs)
newagenttools.FilterScheduleStateForTaskClassScope(s.OriginalScheduleState, flowState.TaskClassIDs)
schedule.FilterScheduleStateForTaskClassScope(s.ScheduleState, flowState.TaskClassIDs)
schedule.FilterScheduleStateForTaskClassScope(s.OriginalScheduleState, flowState.TaskClassIDs)
return s.ScheduleState, nil
}
if s.Deps.ScheduleProvider == nil {
@@ -260,7 +261,7 @@ func (s *AgentGraphState) EnsureScheduleState(ctx context.Context) (*newagenttoo
}
userID := flowState.UserID
var (
state *newagenttools.ScheduleState
state *schedule.ScheduleState
err error
)
// 1. 若 provider 支持按 task_class_ids 精确加载,则优先走 scoped 入口。
@@ -277,7 +278,7 @@ func (s *AgentGraphState) EnsureScheduleState(ctx context.Context) (*newagenttoo
s.ScheduleState = state
// 保存原始快照,供后续 diff 使用。
s.OriginalScheduleState = state.Clone()
newagenttools.FilterScheduleStateForTaskClassScope(s.ScheduleState, flowState.TaskClassIDs)
newagenttools.FilterScheduleStateForTaskClassScope(s.OriginalScheduleState, flowState.TaskClassIDs)
schedule.FilterScheduleStateForTaskClassScope(s.ScheduleState, flowState.TaskClassIDs)
schedule.FilterScheduleStateForTaskClassScope(s.OriginalScheduleState, flowState.TaskClassIDs)
return state, nil
}

View File

@@ -3,7 +3,7 @@ package model
import (
"context"
newagenttools "github.com/LoveLosita/smartflow/backend/newAgent/tools"
schedule "github.com/LoveLosita/smartflow/backend/newAgent/tools/schedule"
)
// AgentStateSnapshot 是需要持久化的 agent 运行态最小快照。
@@ -14,10 +14,10 @@ import (
// 3. 不保存 Deps依赖注入每次由 Service 层重建);
// 4. 不保存 ToolSchemas每次请求由 Service 层重新注入)。
type AgentStateSnapshot struct {
RuntimeState *AgentRuntimeState `json:"runtime_state"`
ConversationContext *ConversationContext `json:"conversation_context"`
ScheduleState *newagenttools.ScheduleState `json:"schedule_state,omitempty"`
OriginalScheduleState *newagenttools.ScheduleState `json:"original_schedule_state,omitempty"`
RuntimeState *AgentRuntimeState `json:"runtime_state"`
ConversationContext *ConversationContext `json:"conversation_context"`
ScheduleState *schedule.ScheduleState `json:"schedule_state,omitempty"`
OriginalScheduleState *schedule.ScheduleState `json:"original_schedule_state,omitempty"`
}
// AgentStateStore 定义 agent 状态持久化的最小接口。
@@ -58,9 +58,9 @@ type AgentStateStore interface {
// 由 DAO 层或 Service 层实现,注入到 AgentGraphDeps 中。
// 使用接口而非具体 DAO 类型,避免 model → dao 的循环依赖。
type ScheduleStateProvider interface {
LoadScheduleState(ctx context.Context, userID int) (*newagenttools.ScheduleState, error)
LoadScheduleState(ctx context.Context, userID int) (*schedule.ScheduleState, error)
// LoadTaskClassMetas 只加载指定任务类的约束元数据,供 Plan 节点提前消费。
LoadTaskClassMetas(ctx context.Context, userID int, taskClassIDs []int) ([]newagenttools.TaskClassMeta, error)
LoadTaskClassMetas(ctx context.Context, userID int, taskClassIDs []int) ([]schedule.TaskClassMeta, error)
}
// ScopedScheduleStateProvider 定义“按本轮任务类范围加载 ScheduleState”的可选增强接口。
@@ -70,12 +70,12 @@ type ScheduleStateProvider interface {
// 2. 不负责:改变既有 ScheduleStateProvider 的基础能力,老实现仍可只实现 LoadScheduleState
// 3. 兜底策略:若调用方拿到的 provider 不实现该接口,则回退到全量 LoadScheduleState再走工具层 scope 裁剪。
type ScopedScheduleStateProvider interface {
LoadScheduleStateForTaskClasses(ctx context.Context, userID int, taskClassIDs []int) (*newagenttools.ScheduleState, error)
LoadScheduleStateForTaskClasses(ctx context.Context, userID int, taskClassIDs []int) (*schedule.ScheduleState, error)
}
// SchedulePersistor 定义持久化 ScheduleState 变更的接口。
// 由 Service 层或 DAO 层实现,注入到 AgentGraphDeps 中。
// 使用接口而非具体 DAO 类型,避免 model → dao 的循环依赖。
type SchedulePersistor interface {
PersistScheduleChanges(ctx context.Context, original, modified *newagenttools.ScheduleState, userID int) error
PersistScheduleChanges(ctx context.Context, original, modified *schedule.ScheduleState, userID int) error
}