import type { TaskNode } from "@/lib/types"; export interface TaskBranch { task: TaskNode; children: TaskBranch[]; } function pathParts(path: string) { return path.split(".").map((part) => Number.parseInt(part, 10)); } export function compareTaskPath(left: TaskNode, right: TaskNode) { const a = pathParts(left.display_path); const b = pathParts(right.display_path); const length = Math.max(a.length, b.length); for (let index = 0; index < length; index += 1) { const delta = (a[index] ?? -1) - (b[index] ?? -1); if (delta !== 0) return delta; } return 0; } export function buildTaskForest(tasks: TaskNode[], visibleIds?: Set): TaskBranch[] { const visible = tasks.filter((task) => !visibleIds || visibleIds.has(task.task_id)); const byParent = new Map(); for (const task of visible) { const siblings = byParent.get(task.parent_task_id) ?? []; siblings.push(task); byParent.set(task.parent_task_id, siblings); } for (const siblings of byParent.values()) siblings.sort(compareTaskPath); const walk = (task: TaskNode): TaskBranch => ({ task, children: (byParent.get(task.task_id) ?? []).map(walk), }); return (byParent.get(null) ?? []).map(walk); } export function taskKindLabel(kind: string) { const labels: Record = { root: "创作总目标", direction: "创作方向", "pattern-retrieval": "模式检索", "external-retrieval": "外部检索", "candidate-portfolio": "脚本候选集", compose: "整稿组合", structure: "脚本结构", paragraph: "脚本段落", "element-set": "内容元素", compare: "候选比较", }; return labels[kind] ?? kind; } export function statusLabel(status: string) { const labels: Record = { completed: "已验收", waiting_children: "等待子任务", needs_replan: "等待 Planner", in_progress: "执行中", pending: "待执行", awaiting_validation: "等待验收", awaiting_decision: "等待决策", blocked: "阶段边界", cancelled: "已取消", failed: "失败", stopped: "已停止", submitted: "已提交", passed: "通过", accept: "采用", }; return labels[status] ?? status; }