Phase 15: add mid-turn steer and before_agent_start dedup tests
Cover steer delivery clearing pending, empty pending no-op, and skip consume when steer already ran for the same compaction entry id. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "fs";
|
||||
import { tmpdir } from "os";
|
||||
import { join } from "path";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { createCompactionRuntime } from "../src/compaction";
|
||||
import { DEFERRED_REINJECT_CUSTOM_TYPE, deliverDeferredReinjectSteer, tryConsumeDeferredReinject } from "../src/reinject";
|
||||
import { createDefaultSettings } from "../src/settings";
|
||||
import { createInitialState, trackSkill } from "../src/state";
|
||||
|
||||
const tempDirs: string[] = [];
|
||||
|
||||
afterEach(() => {
|
||||
for (const dir of tempDirs.splice(0)) {
|
||||
rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
function tempSkillDir(name: string): { filePath: string; baseDir: string } {
|
||||
const root = mkdtempSync(join(tmpdir(), "pi-skill-reinject-mid-turn-"));
|
||||
tempDirs.push(root);
|
||||
const baseDir = join(root, name);
|
||||
mkdirSync(baseDir, { recursive: true });
|
||||
const filePath = join(baseDir, "SKILL.md");
|
||||
writeFileSync(filePath, `---\nname: ${name}\n---\n# body\n`, "utf8");
|
||||
return { filePath, baseDir };
|
||||
}
|
||||
|
||||
describe("deliverDeferredReinjectSteer", () => {
|
||||
it("sends steer message and clears pending when skills resolve", () => {
|
||||
const { filePath, baseDir } = tempSkillDir("alpha");
|
||||
const runtime = createCompactionRuntime();
|
||||
const state = createInitialState();
|
||||
trackSkill(state, { name: "alpha", filePath, baseDir, source: "slash" });
|
||||
state.pendingReinject = ["alpha"];
|
||||
const sendMessage = vi.fn();
|
||||
const pi = { sendMessage } as never;
|
||||
const registered = [{ name: "alpha", filePath, baseDir }];
|
||||
|
||||
const delivered = deliverDeferredReinjectSteer(
|
||||
pi,
|
||||
state,
|
||||
createDefaultSettings(),
|
||||
registered,
|
||||
runtime,
|
||||
"compact-1",
|
||||
);
|
||||
|
||||
expect(delivered).toBe(true);
|
||||
expect(state.pendingReinject).toEqual([]);
|
||||
expect(runtime.deferredDeliveredForCompactionId).toBe("compact-1");
|
||||
expect(sendMessage).toHaveBeenCalledOnce();
|
||||
expect(sendMessage).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
customType: DEFERRED_REINJECT_CUSTOM_TYPE,
|
||||
display: true,
|
||||
content: expect.stringContaining('<skill name="alpha"'),
|
||||
}),
|
||||
{ deliverAs: "steer" },
|
||||
);
|
||||
});
|
||||
|
||||
it("returns false without sendMessage when pending is empty", () => {
|
||||
const runtime = createCompactionRuntime();
|
||||
const state = createInitialState();
|
||||
const sendMessage = vi.fn();
|
||||
const pi = { sendMessage } as never;
|
||||
|
||||
expect(
|
||||
deliverDeferredReinjectSteer(pi, state, createDefaultSettings(), [], runtime, "compact-1"),
|
||||
).toBe(false);
|
||||
expect(sendMessage).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("tryConsumeDeferredReinject after mid-turn steer", () => {
|
||||
it("skips before_agent_start inject when steer already delivered for compaction", () => {
|
||||
const { filePath, baseDir } = tempSkillDir("beta");
|
||||
const runtime = createCompactionRuntime();
|
||||
runtime.lastCompactionEntryId = "compact-2";
|
||||
runtime.deferredDeliveredForCompactionId = "compact-2";
|
||||
const state = createInitialState();
|
||||
trackSkill(state, { name: "beta", filePath, baseDir, source: "slash" });
|
||||
state.pendingReinject = ["beta"];
|
||||
|
||||
expect(
|
||||
tryConsumeDeferredReinject(
|
||||
state,
|
||||
createDefaultSettings(),
|
||||
[{ name: "beta", filePath, baseDir }],
|
||||
undefined,
|
||||
runtime,
|
||||
),
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it("consumes pending on before_agent_start when steer did not run (idle path)", () => {
|
||||
const { filePath, baseDir } = tempSkillDir("gamma");
|
||||
const runtime = createCompactionRuntime();
|
||||
runtime.lastCompactionEntryId = "compact-3";
|
||||
const state = createInitialState();
|
||||
trackSkill(state, { name: "gamma", filePath, baseDir, source: "slash" });
|
||||
state.pendingReinject = ["gamma"];
|
||||
|
||||
const result = tryConsumeDeferredReinject(
|
||||
state,
|
||||
createDefaultSettings(),
|
||||
[{ name: "gamma", filePath, baseDir }],
|
||||
undefined,
|
||||
runtime,
|
||||
);
|
||||
|
||||
expect(result?.message.customType).toBe(DEFERRED_REINJECT_CUSTOM_TYPE);
|
||||
expect(state.pendingReinject).toEqual([]);
|
||||
expect(runtime.deferredDeliveredForCompactionId).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user