fix(pi-task): serialize state updates and remind about open tasks
This commit is contained in:
parent
435823aa1b
commit
89bebe5610
4 changed files with 195 additions and 57 deletions
47
pi/extensions/pi-task/state.test.ts
Normal file
47
pi/extensions/pi-task/state.test.ts
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import { TaskStore, restoreTasks, type Task } from "./state.ts";
|
||||
|
||||
const active: Task[] = [{ text: "Build feature", status: "in_progress" }];
|
||||
const done: Task[] = [{ text: "Build feature", status: "completed" }];
|
||||
const result = (tasks: Task[], isError = false) => ({
|
||||
type: "message", message: { role: "toolResult", toolName: "task", isError, details: { tasks } },
|
||||
});
|
||||
|
||||
test("restores the last valid snapshot on the active branch, including a clear", () => {
|
||||
assert.deepEqual(restoreTasks([result(active), result(done, true), result(done)]), done);
|
||||
assert.deepEqual(restoreTasks([result(active), result([])]), []);
|
||||
assert.deepEqual(restoreTasks([result(active), {
|
||||
type: "message", message: { role: "toolResult", toolName: "task", details: { tasks: [{ text: "bad", status: "invalid" }] } },
|
||||
}]), active);
|
||||
});
|
||||
|
||||
test("serializes concurrent updates and returns independent snapshots", async () => {
|
||||
const store = new TaskStore();
|
||||
const first = store.call(active);
|
||||
const second = store.call(done);
|
||||
assert.deepEqual(await first, { tasks: active, wasComplete: false });
|
||||
assert.deepEqual(await second, { tasks: done, wasComplete: false });
|
||||
assert.deepEqual(store.read(), done);
|
||||
const snapshot = store.read();
|
||||
snapshot[0].text = "changed";
|
||||
assert.deepEqual(store.read(), done);
|
||||
});
|
||||
|
||||
test("rejects invalid and cancelled calls without changing state", async () => {
|
||||
const store = new TaskStore();
|
||||
await store.call(active);
|
||||
await assert.rejects(store.call([{ text: " ", status: "pending" }]), /empty/);
|
||||
const controller = new AbortController();
|
||||
controller.abort();
|
||||
await assert.rejects(store.call(done, controller.signal), /cancelled/);
|
||||
assert.deepEqual(store.read(), active);
|
||||
});
|
||||
|
||||
test("rejects queued calls after a branch change", async () => {
|
||||
const store = new TaskStore();
|
||||
const queued = store.call(done);
|
||||
store.restore([result(active)]);
|
||||
await assert.rejects(queued, /session changed/);
|
||||
assert.deepEqual(store.read(), active);
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue