Files
smartmate/backend/newAgent/tools/quicknote.go
LoveLosita 73ab0f43aa Version: 0.9.34.dev.260421
后端:
1. 旧 Agent 管线(agent/)全面下线,共享逻辑迁移至 newAgent/
- 删除 backend/agent/ 整个目录(44 个 Go 文件),5 条旧专用流程已由 newAgent 统一 graph 取代
- 共享逻辑迁入 newAgent/:clone(shared/clone.go)、时间解析(shared/deadline.go)、优先级常量(shared/task_priority.go)、TaskQuery 类型(model/taskquery_types.go)、SystemPrompt(prompt/system.go)、Usage 合并(stream/usage.go)
2. service 层清除 agent/ 全部依赖
- 删除 4 个旧流程入口文件(agent_route / agent_quick_note / agent_schedule_plan / agent_schedule_refine)
- agent_task_query.go 删除 runTaskQueryFlow,参数类型切到 newagentmodel
- agent.go / agent_newagent.go / agent_schedule_preview.go / agent_schedule_state.go / cmd/start.go / quicknote.go:agent* 引用全部替换为 newagent*
3. 流式降级回退路径内联到 service 层(agent_stream_fallback.go),消除最后一条 agent/chat 依赖

前端:
1. ScheduleFineTuneModal 幂等键追加 classId 后缀,修复多任务类并行保存 key 重复
2026-04-21 20:10:16 +08:00

140 lines
5.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package newagenttools
import (
"encoding/json"
"fmt"
"strings"
"time"
newagentshared "github.com/LoveLosita/smartflow/backend/newAgent/shared"
"github.com/LoveLosita/smartflow/backend/newAgent/tools/schedule"
)
// QuickNoteDeps 描述随口记工具所需的外部依赖。
//
// 职责边界:
// 1. CreateTask 负责真正写库,工具层不直接依赖 DAO
// 2. UserID 由 execute 节点通过 args["_user_id"] 注入,工具层不自行解析会话身份。
type QuickNoteDeps struct {
// CreateTask 将解析后的任务字段写入数据库。
// 调用目的:解耦工具层与 DAO 层,方便测试和替换。
CreateTask func(userID int, title string, priorityGroup int, deadlineAt *time.Time) (taskID int, err error)
}
// QuickNoteCreateResult 是 quick_note_create 工具的结构化返回。
type QuickNoteCreateResult struct {
TaskID int `json:"task_id"`
Title string `json:"title"`
PriorityLabel string `json:"priority_label"`
DeadlineAt string `json:"deadline_at,omitempty"`
Message string `json:"message"`
}
// quickNoteFallbackPriority 根据截止时间推断默认优先级。
//
// 推断规则:
// 1. 有截止时间且距今 ≤48h → 1重要且紧急
// 2. 有截止时间且距今 >48h → 2重要不紧急
// 3. 无截止时间 → 3简单不重要
func quickNoteFallbackPriority(deadline *time.Time) int {
if deadline != nil {
if time.Until(*deadline) <= 48*time.Hour {
return newagentshared.QuickNotePriorityImportantUrgent
}
return newagentshared.QuickNotePriorityImportantNotUrgent
}
return newagentshared.QuickNotePrioritySimpleNotImportant
}
// NewQuickNoteToolHandler 创建 quick_note_create 工具的 handler 闭包。
//
// 职责边界:
// 1. 负责参数校验、时间解析、优先级推断、调 deps 写库、组装返回;
// 2. 不负责 LLM 交互和会话管理。
// 3. state 参数忽略——随口记不需要 ScheduleState已注册到 scheduleFreeTools。
func NewQuickNoteToolHandler(deps QuickNoteDeps) ToolHandler {
return func(state *schedule.ScheduleState, args map[string]any) string {
_ = state
// 1. 提取 _user_id由 execute 节点在调用前注入)。
userID := 0
if uid, ok := args["_user_id"].(int); ok {
userID = uid
}
if userID <= 0 {
return "工具调用失败:无法识别用户身份。"
}
// 2. 提取必填参数 title。
title := ""
if t, ok := args["title"].(string); ok {
title = strings.TrimSpace(t)
}
if title == "" {
return "工具调用失败:缺少必填参数 title任务标题。"
}
// 3. 提取可选参数 deadline_at复用旧链路时间解析能力。
var deadline *time.Time
if raw, ok := args["deadline_at"].(string); ok {
raw = strings.TrimSpace(raw)
if raw != "" {
// 调用目的:复用旧链路成熟的中文相对时间解析器,支持"明天下午3点"等格式。
parsed, err := newagentshared.ParseOptionalDeadline(raw)
if err != nil {
return fmt.Sprintf("工具调用失败:截止时间格式无法解析(%s。支持格式2026-04-20 18:00、明天下午3点、下周一上午9点。", err)
}
deadline = parsed
}
}
// 4. 提取可选参数 priority_group未提供时按截止时间自动推断。
priorityGroup := 0
if pg, ok := args["priority_group"].(float64); ok {
priorityGroup = int(pg)
}
if !newagentshared.IsValidTaskPriority(priorityGroup) {
priorityGroup = quickNoteFallbackPriority(deadline)
}
// 5. 调用依赖写库。
taskID, err := deps.CreateTask(userID, title, priorityGroup, deadline)
if err != nil {
return fmt.Sprintf("工具调用失败:写入任务时出错(%s。", err)
}
if taskID <= 0 {
return "工具调用失败:写入任务后未返回有效 task_id。"
}
// 6. 组装结构化返回,包含 banter 提示引导 LLM 自然生成调侃。
priorityLabel := newagentshared.PriorityLabelCN(priorityGroup)
deadlineStr := ""
if deadline != nil {
deadlineStr = deadline.In(newagentshared.ShanghaiLocation()).Format("2006-01-02 15:04")
}
result := QuickNoteCreateResult{
TaskID: taskID,
Title: title,
PriorityLabel: priorityLabel,
DeadlineAt: deadlineStr,
}
// 6.1 成功事实 + banter 提示:通过工具返回值引导 ReAct LLM 在 speak 中自然加入轻松跟进。
if deadlineStr != "" {
result.Message = fmt.Sprintf("已记录:%s%s截止 %s。回复时请用轻松友好的语气加一句与任务内容相关的俏皮话不超过30字。",
title, priorityLabel, deadlineStr)
} else {
result.Message = fmt.Sprintf("已记录:%s%s。回复时请用轻松友好的语气加一句与任务内容相关的俏皮话不超过30字。",
title, priorityLabel)
}
jsonBytes, marshalErr := json.Marshal(result)
if marshalErr != nil {
// 6.2 JSON 序列化失败时降级为纯文本,确保 LLM 仍能拿到关键信息。
return result.Message
}
return string(jsonBytes)
}
}