Rename task update tool to patch_tasks
This commit is contained in:
@@ -100,7 +100,7 @@ test("keeps task guidance short with planning after exploration", () => {
|
||||
assert.match(prompt, /then call set_tasks before implementation/);
|
||||
assert.match(prompt, /otherwise skip tracking/);
|
||||
assert.match(prompt, /Start one task in-progress/);
|
||||
assert.match(prompt, /update_task when tasks start, block, or finish/);
|
||||
assert.match(prompt, /patch_tasks when tasks start, block, or finish/);
|
||||
assert.match(prompt, /keep statuses accurate before the final response/);
|
||||
assert.ok(prompt.split(/\s+/).length < 40);
|
||||
});
|
||||
@@ -179,8 +179,8 @@ test("session_compact sends one hidden reminder only for unfinished tasks", asyn
|
||||
},
|
||||
]);
|
||||
|
||||
await tools.get("update_task").execute(
|
||||
"update",
|
||||
await tools.get("patch_tasks").execute(
|
||||
"patch",
|
||||
{ tasks: [{ id: 1, status: "done" }] },
|
||||
undefined,
|
||||
undefined,
|
||||
|
||||
+20
-1
@@ -353,7 +353,7 @@ test("loads the latest valid mutation snapshot from a session branch", () => {
|
||||
type: "message",
|
||||
message: {
|
||||
role: "toolResult",
|
||||
toolName: index === 0 ? "add_task" : "update_task",
|
||||
toolName: index === 0 ? "add_task" : "patch_tasks",
|
||||
details: { action: "add", snapshot, affected: [] },
|
||||
},
|
||||
}));
|
||||
@@ -362,6 +362,25 @@ test("loads the latest valid mutation snapshot from a session branch", () => {
|
||||
assert.deepEqual(state.list().map((task) => task.name), ["First", "Second"]);
|
||||
});
|
||||
|
||||
test("loads legacy update_task mutation snapshots", () => {
|
||||
const completed = new TaskState();
|
||||
completed.add([{ name: "Legacy completed task", status: "done" }]);
|
||||
const branch = [
|
||||
{
|
||||
type: "message",
|
||||
message: {
|
||||
role: "toolResult",
|
||||
toolName: "update_task",
|
||||
details: { action: "update", snapshot: completed.snapshot(), affected: [] },
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const state = new TaskState();
|
||||
state.loadFromSession({ sessionManager: { getBranch: () => branch } } as never);
|
||||
assert.deepEqual(state.list().map((task) => task.name), ["Legacy completed task"]);
|
||||
});
|
||||
|
||||
test("loads a persisted automatic clear after task tool snapshots", () => {
|
||||
const completed = new TaskState();
|
||||
completed.add([{ name: "Completed", status: "done" }]);
|
||||
|
||||
+24
-12
@@ -28,12 +28,13 @@ async function execute(tool: any, params: unknown) {
|
||||
|
||||
test("registers five focused tools without the old add_task alias", () => {
|
||||
const { tools } = registeredTools();
|
||||
assert.deepEqual([...tools.keys()], ["set_tasks", "update_task", "rm_task", "list_task", "get_task"]);
|
||||
assert.deepEqual([...tools.keys()], ["set_tasks", "patch_tasks", "rm_task", "list_task", "get_task"]);
|
||||
assert.deepEqual(Object.keys(tools.get("set_tasks").parameters.properties), ["mode", "tasks", "force"]);
|
||||
assert.deepEqual(Object.keys(tools.get("update_task").parameters.properties), ["tasks"]);
|
||||
assert.deepEqual(Object.keys(tools.get("patch_tasks").parameters.properties), ["tasks"]);
|
||||
assert.deepEqual(Object.keys(tools.get("rm_task").parameters.properties), ["ids", "reason"]);
|
||||
assert.deepEqual(Object.keys(tools.get("list_task").parameters.properties), []);
|
||||
assert.deepEqual(Object.keys(tools.get("get_task").parameters.properties), ["ids"]);
|
||||
assert.match(tools.get("patch_tasks").description, /do not recreate cleared completed tasks/);
|
||||
});
|
||||
|
||||
test("set_tasks schema hoists $defs to the root with #/$defs/ refs", () => {
|
||||
@@ -57,7 +58,7 @@ test("task schemas publish text and batch limits", () => {
|
||||
const { tools } = registeredTools();
|
||||
const setParams = tools.get("set_tasks").parameters;
|
||||
const addTask = setParams.$defs.AddTask;
|
||||
const updateTask = tools.get("update_task").parameters.properties.tasks.items;
|
||||
const updateTask = tools.get("patch_tasks").parameters.properties.tasks.items;
|
||||
|
||||
assert.equal(setParams.properties.tasks.maxItems, 50);
|
||||
assert.equal(addTask.properties.children.maxItems, 50);
|
||||
@@ -65,7 +66,7 @@ test("task schemas publish text and batch limits", () => {
|
||||
assert.match(addTask.properties.name.pattern, /061C/i);
|
||||
assert.equal(addTask.properties.description.anyOf[0].maxLength, 4_000);
|
||||
assert.match(addTask.properties.description.anyOf[0].pattern, /061C/i);
|
||||
assert.equal(tools.get("update_task").parameters.properties.tasks.maxItems, 50);
|
||||
assert.equal(tools.get("patch_tasks").parameters.properties.tasks.maxItems, 50);
|
||||
assert.equal(updateTask.properties.name.anyOf[0].maxLength, 200);
|
||||
assert.equal(updateTask.properties.description.anyOf[0].maxLength, 4_000);
|
||||
assert.equal(tools.get("rm_task").parameters.properties.ids.maxItems, 50);
|
||||
@@ -108,7 +109,7 @@ test("set_tasks preparation bounds hostile recursive input before validation", (
|
||||
/validation failed/i,
|
||||
);
|
||||
|
||||
const updateTool = tools.get("update_task");
|
||||
const updateTool = tools.get("patch_tasks");
|
||||
const oversizedUpdate = updateTool.prepareArguments({
|
||||
tasks: Array.from({ length: 1_000 }, (_, index) => ({ id: index + 1 })),
|
||||
});
|
||||
@@ -122,7 +123,7 @@ test("set_tasks preparation bounds hostile recursive input before validation", (
|
||||
test("strict task schemas normalize legacy optional arguments", () => {
|
||||
const { tools } = registeredTools();
|
||||
const setTool = tools.get("set_tasks");
|
||||
const updateTool = tools.get("update_task");
|
||||
const updateTool = tools.get("patch_tasks");
|
||||
|
||||
assert.deepEqual(updateTool.parameters.properties.tasks.items.required, [
|
||||
"id",
|
||||
@@ -171,7 +172,7 @@ test("strict task schemas normalize legacy optional arguments", () => {
|
||||
assert.equal(updateTool.prepareArguments({ tasks: [{ id: 1, parentId: null }] }).tasks[0].parentId, 0);
|
||||
|
||||
const validated = validateToolArguments(updateTool, {
|
||||
name: "update_task",
|
||||
name: "patch_tasks",
|
||||
arguments: updateTool.prepareArguments({ tasks: [{ id: 1, status: "done" }] }),
|
||||
} as never);
|
||||
assert.equal(validated.tasks[0].parentId, -1);
|
||||
@@ -188,16 +189,27 @@ test("validated update sentinels preserve order and map legacy null parent to ro
|
||||
],
|
||||
});
|
||||
|
||||
await execute(harness.tools.get("update_task"), { tasks: [{ id: 3, status: "blocked" }] });
|
||||
await execute(harness.tools.get("patch_tasks"), { tasks: [{ id: 3, status: "blocked" }] });
|
||||
assert.deepEqual(
|
||||
harness.state.list().filter((task) => task.parentId === null).map((task) => task.id),
|
||||
[1, 3],
|
||||
);
|
||||
|
||||
await execute(harness.tools.get("update_task"), { tasks: [{ id: 2, parentId: null }] });
|
||||
await execute(harness.tools.get("patch_tasks"), { tasks: [{ id: 2, parentId: null }] });
|
||||
assert.equal(harness.state.get([2])[0]?.parentId, null);
|
||||
});
|
||||
|
||||
test("patch_tasks explains an auto-cleared empty tree without recreating tasks", async () => {
|
||||
const harness = registeredTools();
|
||||
|
||||
await assert.rejects(
|
||||
execute(harness.tools.get("patch_tasks"), { tasks: [{ id: 1, status: "done" }] }),
|
||||
/Patch failed · 1 validation error\n- task tree is empty and may have auto-cleared after completion; do not recreate completed tasks\. Use set_tasks only for genuinely new or remaining work/,
|
||||
);
|
||||
assert.deepEqual(harness.state.list(), []);
|
||||
assert.equal(harness.changes(), 0);
|
||||
});
|
||||
|
||||
test("set_tasks appends optional-description tasks and persists a complete snapshot", async () => {
|
||||
const harness = registeredTools();
|
||||
const result = await execute(harness.tools.get("set_tasks"), {
|
||||
@@ -247,8 +259,8 @@ test("tool validation errors preserve atomic state", async () => {
|
||||
const before = harness.state.snapshot();
|
||||
|
||||
await assert.rejects(
|
||||
execute(harness.tools.get("update_task"), { tasks: [{ id: 1, parentId: 2 }] }),
|
||||
/Update failed · 1 validation error\n- task [12]: parentId creates a cycle/,
|
||||
execute(harness.tools.get("patch_tasks"), { tasks: [{ id: 1, parentId: 2 }] }),
|
||||
/Patch failed · 1 validation error\n- task [12]: parentId creates a cycle/,
|
||||
);
|
||||
assert.deepEqual(harness.state.snapshot(), before);
|
||||
assert.equal(harness.changes(), 1);
|
||||
@@ -310,7 +322,7 @@ test("get_task exposes cumulative timing while list output stays compact", async
|
||||
});
|
||||
|
||||
now += 568;
|
||||
const updated = await execute(harness.tools.get("update_task"), {
|
||||
const updated = await execute(harness.tools.get("patch_tasks"), {
|
||||
tasks: [{ id: 1, status: "blocked" }],
|
||||
});
|
||||
assert.equal(updated.content[0].text, "Updated 1 task: 1. 0/1 done.");
|
||||
|
||||
Reference in New Issue
Block a user