journey.ts 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import type { JourneyEdge, JourneyStep, TaskCycle } from "@/lib/types";
  2. export function buildTaskCycles(steps: JourneyStep[], edges: JourneyEdge[]): TaskCycle[] {
  3. const groups = new Map<string, JourneyStep[]>();
  4. for (const step of steps) {
  5. const values = groups.get(step.task_id) ?? [];
  6. values.push(step);
  7. groups.set(step.task_id, values);
  8. }
  9. return [...groups.entries()]
  10. .map(([taskId, values]) => {
  11. const plan = values.find((step) => step.step_type === "plan");
  12. const last = values.at(-1)!;
  13. return {
  14. taskId,
  15. title: plan?.contract?.output ?? plan?.title.replace("Planner 规划·", "") ?? last.title,
  16. status: last.status,
  17. steps: values,
  18. goals: plan?.contract?.goals ?? [],
  19. loopCount: edges.filter(
  20. (edge) =>
  21. edge.relation === "loop" && values.some((step) => step.step_id === edge.source),
  22. ).length,
  23. parallel: values.some((step) => Boolean(step.parallel_group_id)),
  24. };
  25. })
  26. .sort((left, right) => left.steps[0].sequence - right.steps[0].sequence);
  27. }
  28. export type StepGroup =
  29. | { kind: "single"; id: string; steps: [JourneyStep] }
  30. | { kind: "parallel"; id: string; steps: JourneyStep[] };
  31. export function groupParallelSteps(steps: JourneyStep[]): StepGroup[] {
  32. const ordered = [...steps].sort((left, right) => left.sequence - right.sequence);
  33. const output: StepGroup[] = [];
  34. const consumed = new Set<string>();
  35. for (const step of ordered) {
  36. if (consumed.has(step.step_id)) continue;
  37. if (step.parallel_group_id && step.step_type === "execute") {
  38. const parallel = ordered.filter(
  39. (candidate) =>
  40. candidate.step_type === "execute" &&
  41. candidate.parallel_group_id === step.parallel_group_id,
  42. );
  43. parallel.forEach((candidate) => consumed.add(candidate.step_id));
  44. output.push({ kind: "parallel", id: step.parallel_group_id, steps: parallel });
  45. continue;
  46. }
  47. consumed.add(step.step_id);
  48. output.push({ kind: "single", id: step.step_id, steps: [step] });
  49. }
  50. return output;
  51. }
  52. export function statusLabel(status: string): string {
  53. return {
  54. accept: "已接受",
  55. accepted: "已接受",
  56. completed: "已完成",
  57. passed: "已通过",
  58. failed: "未通过",
  59. retry: "重新执行",
  60. revise: "正在修订",
  61. split: "已拆分",
  62. block: "阶段等待",
  63. blocked: "阶段等待",
  64. running: "进行中",
  65. submitted: "已提交",
  66. needs_replan: "等待决策",
  67. }[status.toLowerCase()] ?? status;
  68. }