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:
LoveLosita
2026-04-15 11:52:50 +08:00
parent 21eed5af75
commit e77d42fce5
7 changed files with 129 additions and 222 deletions

View File

@@ -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}}}`,

View File

@@ -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 {

View File

@@ -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。
// 不存在时返回错误信息字符串。

View File

@@ -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)
}