Version: 0.9.19.dev.260415
后端: 1. 移除 list_tasks 读工具,消除与 query_target_tasks 的功能重叠 - 删除backend/newAgent/tools/registry.go 中 list_tools 注册 - 删除 backend/newAgent/tools/schedule/read_tools.go 中 ListTasks 函数及 6个独有辅助函数(formatExistingList / formatSuggestedList / formatPendingList / formatListTasksEmptyResult / looksLikeTaskClassIDList / validateListTasksStatus) - 更新 backend/newAgent/prompt/execute.go:清理全部 list_tasks 相关规则约束并重新编号,统一工具引用为query_target_tasks - 更新 backend/newAgent/prompt/execute_context.go:删除 list_tasks 返回值示例 case 分支 - 更新backend/newAgent/tools/schedule/read_helpers.go / status.go:清理注释中的 list_tasks 引用 2. 新增 execute 历史消息注入改造 handoff 文档 -新建 backend/newAgent/HANDOFF_execute_history_reform.md:记录 msg1 从人工摘要改为真实对话流(user + assistant speak)的改造方案,待后续实施 前端:无 仓库:无
This commit is contained in:
@@ -177,14 +177,6 @@ func NewDefaultRegistryWithDeps(deps DefaultRegistryDeps) *ToolRegistry {
|
||||
},
|
||||
)
|
||||
|
||||
r.Register("list_tasks",
|
||||
"列出任务清单,可按类别和状态过滤。category 传任务类名称,status 仅支持单值 all/existing/suggested/pending。",
|
||||
`{"name":"list_tasks","parameters":{"category":{"type":"string"},"status":{"type":"string","enum":["all","existing","suggested","pending"]}}}`,
|
||||
func(state *schedule.ScheduleState, args map[string]any) string {
|
||||
return schedule.ListTasks(state, schedule.ArgsStringPtr(args, "category"), schedule.ArgsStringPtr(args, "status"))
|
||||
},
|
||||
)
|
||||
|
||||
r.Register("get_task_info",
|
||||
"查询单个任务详细信息,包括类别、状态、占用时段、嵌入关系。",
|
||||
`{"name":"get_task_info","parameters":{"task_id":{"type":"int","required":true}}}`,
|
||||
|
||||
@@ -42,7 +42,7 @@ func formatTaskLabel(task ScheduleTask) string {
|
||||
|
||||
// formatTaskLabelWithCategory 输出带类别和锁定标记的标签。
|
||||
// 如 "[1]高等数学(课程,固定)" 或 "[2]英语(课程)"。
|
||||
// 用于 get_overview 和 list_tasks 的概要输出。
|
||||
// 用于 get_overview 的概要输出。
|
||||
func formatTaskLabelWithCategory(task ScheduleTask) string {
|
||||
label := fmt.Sprintf("[%d]%s(%s", task.StateID, task.Name, task.Category)
|
||||
if task.Locked {
|
||||
|
||||
@@ -500,176 +500,6 @@ func findFirstEmbeddablePosition(state *ScheduleState, day, duration int) (*Sche
|
||||
return best.task, best.slotStart, best.slotEnd
|
||||
}
|
||||
|
||||
// ListTasks 列出任务清单,可按类别和状态过滤。
|
||||
// category 选填(nil 不过滤),status 选填(nil 默认 "all")。
|
||||
// 输出按状态分组:已安排 -> 已预排 -> 待安排,组内按 stateID 升序。
|
||||
func ListTasks(state *ScheduleState, category, status *string) string {
|
||||
// 1. 确定过滤状态。
|
||||
statusFilter := "all"
|
||||
if status != nil {
|
||||
statusFilter = *status
|
||||
}
|
||||
statusFilter = strings.ToLower(strings.TrimSpace(statusFilter))
|
||||
if statusFilter == "" {
|
||||
statusFilter = "all"
|
||||
}
|
||||
if err := validateListTasksStatus(statusFilter); err != nil {
|
||||
return fmt.Sprintf("查询失败:%s", err.Error())
|
||||
}
|
||||
categoryFilter := ""
|
||||
if category != nil {
|
||||
categoryFilter = strings.TrimSpace(*category)
|
||||
}
|
||||
hasCategoryFilter := categoryFilter != ""
|
||||
|
||||
// 2. 过滤 + 分组。
|
||||
var existingTasks, suggestedTasks, pendingTasks []ScheduleTask
|
||||
for i := range state.Tasks {
|
||||
t := state.Tasks[i]
|
||||
// 类别过滤。
|
||||
if hasCategoryFilter && t.Category != categoryFilter {
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case IsPendingTask(t):
|
||||
if statusFilter != "all" && statusFilter != "pending" {
|
||||
continue
|
||||
}
|
||||
pendingTasks = append(pendingTasks, t)
|
||||
case IsSuggestedTask(t):
|
||||
if statusFilter != "all" && statusFilter != "suggested" {
|
||||
continue
|
||||
}
|
||||
suggestedTasks = append(suggestedTasks, t)
|
||||
default:
|
||||
if statusFilter != "all" && statusFilter != "existing" {
|
||||
continue
|
||||
}
|
||||
existingTasks = append(existingTasks, t)
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 按 stateID 排序。
|
||||
sort.Slice(existingTasks, func(i, j int) bool { return existingTasks[i].StateID < existingTasks[j].StateID })
|
||||
sort.Slice(suggestedTasks, func(i, j int) bool { return suggestedTasks[i].StateID < suggestedTasks[j].StateID })
|
||||
sort.Slice(pendingTasks, func(i, j int) bool { return pendingTasks[i].StateID < pendingTasks[j].StateID })
|
||||
|
||||
// 4. 纯待安排模式:只输出待安排任务。
|
||||
if statusFilter == "pending" {
|
||||
if len(pendingTasks) == 0 {
|
||||
return formatListTasksEmptyResult(statusFilter, categoryFilter)
|
||||
}
|
||||
return formatPendingList(pendingTasks)
|
||||
}
|
||||
|
||||
// 5. 纯已预排模式:只输出已预排任务。
|
||||
if statusFilter == "suggested" {
|
||||
if len(suggestedTasks) == 0 {
|
||||
return formatListTasksEmptyResult(statusFilter, categoryFilter)
|
||||
}
|
||||
return formatSuggestedList(state, suggestedTasks)
|
||||
}
|
||||
|
||||
// 6. 纯已安排模式:只输出已安排任务。
|
||||
if statusFilter == "existing" {
|
||||
if len(existingTasks) == 0 {
|
||||
return formatListTasksEmptyResult(statusFilter, categoryFilter)
|
||||
}
|
||||
return formatExistingList(state, existingTasks)
|
||||
}
|
||||
|
||||
// 7. 全部模式:统计 + 分组输出。
|
||||
total := len(existingTasks) + len(suggestedTasks) + len(pendingTasks)
|
||||
var sb strings.Builder
|
||||
sb.WriteString(fmt.Sprintf("共%d个任务,已安排(existing)%d个,已预排(suggested)%d个,待安排(pending)%d个。\n", total, len(existingTasks), len(suggestedTasks), len(pendingTasks)))
|
||||
|
||||
if len(existingTasks) > 0 {
|
||||
sb.WriteString("\n已安排(existing):\n")
|
||||
sb.WriteString(formatExistingList(state, existingTasks))
|
||||
}
|
||||
if len(suggestedTasks) > 0 {
|
||||
sb.WriteString("\n已预排(suggested):\n")
|
||||
sb.WriteString(formatSuggestedList(state, suggestedTasks))
|
||||
}
|
||||
if len(pendingTasks) > 0 {
|
||||
sb.WriteString("\n待安排(pending):\n")
|
||||
sb.WriteString(formatPendingList(pendingTasks))
|
||||
}
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// formatListTasksEmptyResult 统一构造 list_tasks 空结果文案。
|
||||
//
|
||||
// 设计意图:
|
||||
// 1. 明确告诉模型“为什么为空”,避免把空字符串误解为工具异常或上下文缺失;
|
||||
// 2. 对常见误用 category=ID 列表给出直接纠偏提示,减少死循环重试。
|
||||
func formatListTasksEmptyResult(statusFilter, categoryFilter string) string {
|
||||
statusLabel := map[string]string{
|
||||
"all": "任意状态",
|
||||
"existing": "已安排(existing)",
|
||||
"suggested": "已预排(suggested)",
|
||||
"pending": "待安排(pending)",
|
||||
}
|
||||
target := statusLabel[statusFilter]
|
||||
if target == "" {
|
||||
target = statusFilter
|
||||
}
|
||||
|
||||
if strings.TrimSpace(categoryFilter) == "" {
|
||||
return fmt.Sprintf("查询结果为空:当前没有%s任务。", target)
|
||||
}
|
||||
if looksLikeTaskClassIDList(categoryFilter) {
|
||||
return fmt.Sprintf("查询结果为空:category=%q 未匹配到任务。category 参数按任务类名称匹配,不支持 task_class_ids 列表。", categoryFilter)
|
||||
}
|
||||
return fmt.Sprintf("查询结果为空:category=%q 下没有%s任务。", categoryFilter, target)
|
||||
}
|
||||
|
||||
// looksLikeTaskClassIDList 判断 category 文本是否像“逗号分隔的数字 ID 列表”。
|
||||
func looksLikeTaskClassIDList(value string) bool {
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" {
|
||||
return false
|
||||
}
|
||||
parts := strings.Split(value, ",")
|
||||
if len(parts) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, part := range parts {
|
||||
part = strings.TrimSpace(part)
|
||||
if part == "" {
|
||||
return false
|
||||
}
|
||||
for _, r := range part {
|
||||
if r < '0' || r > '9' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// validateListTasksStatus 校验 list_tasks.status 的输入值。
|
||||
//
|
||||
// 职责边界:
|
||||
// 1. 负责拦截非法 status,避免“静默返回 0 条”误导模型;
|
||||
// 2. 不负责自动拆分或容错纠偏(如 existing,suggested),统一要求调用方改成合法单值。
|
||||
func validateListTasksStatus(status string) error {
|
||||
// 1. status 已在调用方归一化为小写并去空格。
|
||||
// 2. 合法值仅允许 all / existing / suggested / pending。
|
||||
switch status {
|
||||
case "all", "existing", "suggested", "pending":
|
||||
return nil
|
||||
}
|
||||
|
||||
// 3. 对最常见误用给出明确修复建议,避免模型继续循环错误调用。
|
||||
if strings.Contains(status, ",") {
|
||||
return fmt.Errorf("status 只支持单值 all/existing/suggested/pending,不支持 \"%s\"。如需同时查看 existing+suggested,请使用 all", status)
|
||||
}
|
||||
return fmt.Errorf("status=%q 非法,仅支持 all/existing/suggested/pending", status)
|
||||
}
|
||||
|
||||
// GetTaskInfo 查询单个任务的详细信息。
|
||||
// taskID 必填,为 state 内的 state_id。
|
||||
// 不存在时返回错误信息字符串。
|
||||
|
||||
@@ -50,7 +50,7 @@ func IsSuggestedTask(task ScheduleTask) bool {
|
||||
//
|
||||
// 说明:
|
||||
// 1. 这里会主动排除 suggested 兼容形态,避免旧快照里的 existing+Duration>0 被误当成已确定任务;
|
||||
// 2. 这样 list_tasks / get_overview 才能稳定区分“事实层 existing”和“建议层 suggested”。
|
||||
// 2. 这样 get_overview 等工具才能稳定区分”事实层 existing”和”建议层 suggested”。
|
||||
func IsExistingTask(task ScheduleTask) bool {
|
||||
return task.Status == TaskStatusExisting && !IsSuggestedTask(task)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user