120 lines
4.1 KiB
JavaScript
120 lines
4.1 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
|
|
import {
|
|
applyProgressAction,
|
|
enforceMonotonicProgress,
|
|
progressActionsFromToolCalls,
|
|
} from "../web/static/js/progress.js";
|
|
|
|
test("update_step without title preserves title from the existing plan", () => {
|
|
const initial = applyProgressAction([], {
|
|
action: "set_plan",
|
|
steps: [
|
|
{ id: "s1", title: "理解需求", status: "in_progress" },
|
|
{ id: "s2", title: "实现功能", status: "pending" },
|
|
],
|
|
});
|
|
|
|
const updated = applyProgressAction(initial, {
|
|
action: "update_step",
|
|
step: { id: "s1", status: "completed" },
|
|
});
|
|
|
|
assert.deepEqual(updated, [
|
|
{ id: "s1", title: "理解需求", status: "completed" },
|
|
{ id: "s2", title: "实现功能", status: "pending" },
|
|
]);
|
|
});
|
|
|
|
test("tool calls can apply progress updates on top of previous task progress", () => {
|
|
const previous = [
|
|
{ id: "s1", title: "理解需求", status: "in_progress" },
|
|
{ id: "s2", title: "实现功能", status: "pending" },
|
|
];
|
|
const toolCalls = [{
|
|
function: {
|
|
name: "task_progress",
|
|
arguments: JSON.stringify({
|
|
action: "update_step",
|
|
step: { id: "s1", status: "completed" },
|
|
}),
|
|
},
|
|
}];
|
|
|
|
const result = progressActionsFromToolCalls(toolCalls, previous);
|
|
|
|
assert.equal(result.sawProgress, true);
|
|
assert.deepEqual(result.steps, [
|
|
{ id: "s1", title: "理解需求", status: "completed" },
|
|
{ id: "s2", title: "实现功能", status: "pending" },
|
|
]);
|
|
});
|
|
|
|
test("a completed step force-completes earlier dangling steps (monotonic heal)", () => {
|
|
const steps = [
|
|
{ id: "s1", title: "摄取素材", status: "in_progress" },
|
|
{ id: "s2", title: "策略", status: "completed" },
|
|
{ id: "s3", title: "配图", status: "pending" },
|
|
];
|
|
assert.deepEqual(enforceMonotonicProgress(steps), [
|
|
{ id: "s1", title: "摄取素材", status: "completed" },
|
|
{ id: "s2", title: "策略", status: "completed" },
|
|
{ id: "s3", title: "配图", status: "pending" },
|
|
]);
|
|
});
|
|
|
|
test("update_step marking a later step completed heals the earlier in_progress step", () => {
|
|
const initial = applyProgressAction([], {
|
|
action: "set_plan",
|
|
steps: [
|
|
{ id: "s1", title: "摄取素材", status: "in_progress" },
|
|
{ id: "s2", title: "策略", status: "pending" },
|
|
{ id: "s3", title: "配图", status: "pending" },
|
|
],
|
|
});
|
|
|
|
const updated = applyProgressAction(initial, {
|
|
action: "update_step",
|
|
step: { id: "s2", status: "completed" },
|
|
});
|
|
|
|
assert.deepEqual(updated, [
|
|
{ id: "s1", title: "摄取素材", status: "completed" },
|
|
{ id: "s2", title: "策略", status: "completed" },
|
|
{ id: "s3", title: "配图", status: "pending" },
|
|
]);
|
|
});
|
|
|
|
// Replay the exact d1285247 task_progress sequence that produced the reported
|
|
// "green check below, red dot above" bug; the heal must yield a clean 6/6.
|
|
test("replays the d1285247 skip-ahead sequence to a fully completed plan", () => {
|
|
const call = (args) => ({
|
|
function: { name: "task_progress", arguments: JSON.stringify(args) },
|
|
});
|
|
const seq = [
|
|
call({
|
|
action: "set_plan",
|
|
steps: [
|
|
{ id: "s1", title: "摄取素材", status: "in_progress" },
|
|
{ id: "s2", title: "策略", status: "pending" },
|
|
{ id: "s3", title: "配图", status: "pending" },
|
|
{ id: "s4", title: "执行", status: "pending" },
|
|
{ id: "s5", title: "质检", status: "pending" },
|
|
{ id: "s6", title: "导出", status: "pending" },
|
|
],
|
|
}),
|
|
call({ action: "update_step", step: { id: "s2", status: "completed" } }),
|
|
call({ action: "update_step", step: { id: "s3", status: "in_progress" } }),
|
|
call({ action: "update_step", step: { id: "s4", status: "completed" } }),
|
|
call({ action: "update_step", step: { id: "s5", status: "in_progress" } }),
|
|
call({ action: "update_step", step: { id: "s5", status: "completed" } }),
|
|
call({ action: "update_step", step: { id: "s6", status: "completed" } }),
|
|
];
|
|
|
|
const { steps } = progressActionsFromToolCalls(seq, []);
|
|
assert.deepEqual(steps.map(s => s.status), [
|
|
"completed", "completed", "completed", "completed", "completed", "completed",
|
|
]);
|
|
});
|