Skip to content

Commit a86eda1

Browse files
committed
refactor(session): drop the unread prompt checkpoint
1 parent 8b1a29e commit a86eda1

2 files changed

Lines changed: 24 additions & 422 deletions

File tree

‎src/session/optimized-context-store.test.ts‎

Lines changed: 1 addition & 242 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { defined } from "../../testkit/defined.js";
2-
import { withMockedModuleDuring } from "../../testkit/mock-module.js";
32
import { describe, test, expect } from "bun:test";
43
import fs from "node:fs";
54
import os from "node:os";
@@ -594,7 +593,7 @@ describe("createOptimizedContextStore checkpoint", () => {
594593
const dir = tempDir();
595594
const store = await createOptimizedContextStore(dir);
596595
await store.writeTurns([turn("a")]);
597-
await store.writePrompt([turn("p0")]);
596+
fs.writeFileSync(path.join(dir, "prompt.jsonl"), jsonl([turn("p0")]));
598597
await store.writeMetadata(EMPTY_CHECKPOINT_METADATA);
599598
const first = await store.commit({ message: "base" });
600599

@@ -1210,43 +1209,6 @@ describe("concurrent sessions write disjoint transcripts", () => {
12101209
expect(turnTexts((await resumed.load()).turns)).not.toContain("from-B");
12111210
});
12121211

1213-
test("a prompt is not written to the shared file before ownership is decided", async () => {
1214-
const dir = tempDir();
1215-
const promptFile = "prompt.jsonl";
1216-
const sessionA = await createOptimizedContextStore(dir, {
1217-
ownerId: "session-A",
1218-
});
1219-
await sessionA.writeTurns([turn("a"), turn("b")]);
1220-
await sessionA.writePrompt([turn("a"), turn("b"), turn("ephemeral-A")]);
1221-
await sessionA.writeMetadata(EMPTY_CHECKPOINT_METADATA);
1222-
await sessionA.commit({ message: "session A" });
1223-
const promptPath = path.join(dir, promptFile);
1224-
const ownedPrompt = fs.readFileSync(promptPath, "utf8");
1225-
1226-
const sessionB = await createOptimizedContextStore(dir, {
1227-
ownerId: "session-B",
1228-
});
1229-
await sessionB.writePrompt([turn("foreign-prompt")]);
1230-
expect(fs.readFileSync(promptPath, "utf8")).toBe(ownedPrompt);
1231-
await sessionB.writeTurns([turn("x"), turn("y")]);
1232-
expect(fs.readFileSync(promptPath, "utf8")).toBe(ownedPrompt);
1233-
await sessionB.writeMetadata(EMPTY_CHECKPOINT_METADATA);
1234-
await sessionB.commit({ message: "session B" });
1235-
1236-
expect(fs.readFileSync(promptPath, "utf8")).toBe(ownedPrompt);
1237-
expect(turnTexts(readTurnsFromFile(path.join(dir, TURNS_FILE)))).toEqual([
1238-
"a",
1239-
"b",
1240-
]);
1241-
const versionedPrompts = fs
1242-
.readdirSync(dir)
1243-
.filter((name) => /^prompt-\d+-[0-9a-f]+\.jsonl$/.test(name));
1244-
expect(versionedPrompts).toHaveLength(1);
1245-
expect(
1246-
fs.readFileSync(path.join(dir, defined(versionedPrompts[0])), "utf8"),
1247-
).toContain("foreign-prompt");
1248-
});
1249-
12501212
test(
12511213
"two processes cannot both claim an empty session directory",
12521214
async () => {
@@ -1619,209 +1581,6 @@ describe("createOptimizedContextStore unpublished rewrite", () => {
16191581
});
16201582
});
16211583

1622-
describe("createOptimizedContextStore prompt dedupe (CL-9026)", () => {
1623-
const PROMPT_FILE = "prompt.jsonl";
1624-
1625-
function toolResultTurn(body: string): ConversationTurn {
1626-
return {
1627-
role: "user",
1628-
content: [
1629-
{
1630-
type: "tool_result",
1631-
callId: "call-1",
1632-
content: [{ type: "text", text: body }],
1633-
},
1634-
],
1635-
timestamp: 1,
1636-
};
1637-
}
1638-
1639-
function cloneTurns(turns: ConversationTurn[]): ConversationTurn[] {
1640-
return turns.map((t) => JSON.parse(JSON.stringify(t)) as ConversationTurn);
1641-
}
1642-
1643-
test("identical writePrompt writes no prompt segment", async () => {
1644-
const dir = tempDir();
1645-
const store = await createOptimizedContextStore(dir);
1646-
const turns = [turn("a"), turn("b")];
1647-
await store.writeTurns([...turns]);
1648-
await store.writePrompt([...turns]);
1649-
await store.writePrompt(cloneTurns(turns));
1650-
1651-
expect(fs.existsSync(path.join(dir, PROMPT_FILE))).toBe(false);
1652-
expect(await listSegmentFiles(dir, PROMPT_FILE)).toEqual([]);
1653-
1654-
await store.writeMetadata(EMPTY_CHECKPOINT_METADATA);
1655-
await store.commit({ message: "identical prompt is a no-op" });
1656-
expect(await gitLsTree(dir)).not.toContain(PROMPT_FILE);
1657-
1658-
// A fresh instance compares against on-disk live turns and also skips.
1659-
const fresh = await createOptimizedContextStore(dir);
1660-
await fresh.writePrompt(cloneTurns(turns));
1661-
expect(fs.existsSync(path.join(dir, PROMPT_FILE))).toBe(false);
1662-
});
1663-
1664-
test("differing writePrompt still writes the prompt snapshot", async () => {
1665-
const dir = tempDir();
1666-
const store = await createOptimizedContextStore(dir);
1667-
const live = [turn("a"), toolResultTurn("x".repeat(1000))];
1668-
await store.writeTurns([...live]);
1669-
1670-
const shrunk = [turn("a"), toolResultTurn("summarized")];
1671-
await store.writePrompt(shrunk);
1672-
expect(fs.existsSync(path.join(dir, PROMPT_FILE))).toBe(true);
1673-
expect(fs.readFileSync(path.join(dir, PROMPT_FILE), "utf-8")).toBe(
1674-
jsonl(shrunk),
1675-
);
1676-
1677-
// An appended ephemeral turn also changes the prompt and still writes.
1678-
const ephemeralDir = tempDir();
1679-
const ephemeralStore = await createOptimizedContextStore(ephemeralDir);
1680-
await ephemeralStore.writeTurns([...live]);
1681-
const withEphemeral = [...cloneTurns(live), turn("ephemeral")];
1682-
await ephemeralStore.writePrompt(withEphemeral);
1683-
expect(fs.readFileSync(path.join(ephemeralDir, PROMPT_FILE), "utf-8")).toBe(
1684-
jsonl(withEphemeral),
1685-
);
1686-
});
1687-
1688-
test("turns-only store loads live turns and commits no prompt file", async () => {
1689-
const dir = tempDir();
1690-
const store = await createOptimizedContextStore(dir);
1691-
await store.writeTurns([turn("a"), turn("b")]);
1692-
await store.writeMetadata(EMPTY_CHECKPOINT_METADATA);
1693-
const first = await store.commit({ message: "turns only" });
1694-
1695-
expect(turnTexts((await store.load()).turns)).toEqual(["a", "b"]);
1696-
1697-
const fresh = await createOptimizedContextStore(dir);
1698-
expect(turnTexts((await fresh.load()).turns)).toEqual(["a", "b"]);
1699-
const second = await fresh.commit({ message: "turns-only no-op" });
1700-
expect(second.hash).toBe(first.hash);
1701-
expect(fs.existsSync(path.join(dir, PROMPT_FILE))).toBe(false);
1702-
expect(await gitLsTree(dir)).not.toContain(PROMPT_FILE);
1703-
});
1704-
1705-
test("identical writePrompt after a differing one removes stale prompt segments", async () => {
1706-
const dir = tempDir();
1707-
const store = await createOptimizedContextStore(dir);
1708-
const live = [turn("a"), turn("b")];
1709-
await store.writeTurns([...live]);
1710-
await store.writePrompt([turn("a")]);
1711-
expect(fs.existsSync(path.join(dir, PROMPT_FILE))).toBe(true);
1712-
1713-
await store.writePrompt(cloneTurns(live));
1714-
expect(fs.existsSync(path.join(dir, PROMPT_FILE))).toBe(false);
1715-
expect(await listSegmentFiles(dir, PROMPT_FILE)).toEqual([]);
1716-
1717-
await store.writeMetadata(EMPTY_CHECKPOINT_METADATA);
1718-
await store.commit({ message: "stale prompt removed" });
1719-
expect(await gitLsTree(dir)).not.toContain(PROMPT_FILE);
1720-
expect(turnTexts((await store.load()).turns)).toEqual(["a", "b"]);
1721-
});
1722-
1723-
test("committed then identical writePrompt drops prompt.jsonl from HEAD", async () => {
1724-
const dir = tempDir();
1725-
const store = await createOptimizedContextStore(dir);
1726-
const live = [turn("a"), turn("b")];
1727-
await store.writeTurns([...live]);
1728-
await store.writePrompt([turn("a")]);
1729-
await store.writeMetadata(EMPTY_CHECKPOINT_METADATA);
1730-
await store.commit({ message: "differing prompt" });
1731-
expect(await gitLsTree(dir)).toContain(PROMPT_FILE);
1732-
1733-
await store.writePrompt(cloneTurns(live));
1734-
await store.writeMetadata(EMPTY_CHECKPOINT_METADATA);
1735-
const afterIdentical = await store.commit({ message: "identical prompt" });
1736-
expect(await gitLsTree(dir)).not.toContain(PROMPT_FILE);
1737-
expect(turnTexts((await store.load()).turns)).toEqual(["a", "b"]);
1738-
1739-
await store.writeMetadata(EMPTY_CHECKPOINT_METADATA);
1740-
const empty = await store.commit({ message: "empty checkpoint" });
1741-
expect(empty.hash).toBe(afterIdentical.hash);
1742-
});
1743-
1744-
test("identical writePrompt after multi-segment differing prompt drops all prompt files from HEAD", async () => {
1745-
const dir = tempDir();
1746-
const store = await createOptimizedContextStore(dir);
1747-
const live: ConversationTurn[] = [];
1748-
const big = "x".repeat(20_000);
1749-
for (let i = 0; i < 18; i++) {
1750-
live.push(turn(`${i}-${big}`));
1751-
}
1752-
await store.writeTurns([...live]);
1753-
1754-
const differing: ConversationTurn[] = [];
1755-
for (let i = 0; i < 18; i++) {
1756-
differing.push(turn(`p-${i}-${big}`));
1757-
}
1758-
await store.writePrompt(differing);
1759-
const extraPrompt = segmentFileName(PROMPT_FILE, 1);
1760-
expect(fs.existsSync(path.join(dir, PROMPT_FILE))).toBe(true);
1761-
expect(fs.existsSync(path.join(dir, extraPrompt))).toBe(true);
1762-
1763-
await store.writeMetadata(EMPTY_CHECKPOINT_METADATA);
1764-
await store.commit({ message: "multi-segment prompt" });
1765-
const treeAfterDiffering = await gitLsTree(dir);
1766-
expect(treeAfterDiffering).toContain(PROMPT_FILE);
1767-
expect(treeAfterDiffering).toContain(extraPrompt);
1768-
1769-
await store.writePrompt(cloneTurns(live));
1770-
await store.writeMetadata(EMPTY_CHECKPOINT_METADATA);
1771-
await store.commit({ message: "identical drops prompt segments" });
1772-
const tree = await gitLsTree(dir);
1773-
expect(tree).not.toContain(PROMPT_FILE);
1774-
expect(tree).not.toContain(extraPrompt);
1775-
expect(turnTexts((await store.load()).turns)).toEqual(turnTexts(live));
1776-
});
1777-
1778-
test("one remove failure still unstages the other paths in one index write", async () => {
1779-
const dir = tempDir();
1780-
const store = await createOptimizedContextStore(dir);
1781-
const huge = "x".repeat(300_000);
1782-
const live = [turn(`live-${huge}`), turn("live-tail")];
1783-
await store.writeTurns([...live]);
1784-
await store.writePrompt([turn(`prompt-${huge}`), turn("prompt-tail")]);
1785-
await store.writeMetadata(EMPTY_CHECKPOINT_METADATA);
1786-
await store.commit({ message: "two prompt segments" });
1787-
const extraPrompt = segmentFileName(PROMPT_FILE, 1);
1788-
expect(await gitLsTree(dir)).toEqual(
1789-
expect.arrayContaining([PROMPT_FILE, extraPrompt]),
1790-
);
1791-
1792-
await store.writePrompt(cloneTurns(live));
1793-
await store.writeMetadata(EMPTY_CHECKPOINT_METADATA);
1794-
1795-
const removeCalls: (string | string[])[] = [];
1796-
await withMockedModuleDuring(
1797-
import.meta.resolve("isomorphic-git"),
1798-
(real: typeof import("isomorphic-git")) => {
1799-
const remove: typeof real.default.remove = async (args) => {
1800-
removeCalls.push(args.filepath);
1801-
const paths = Array.isArray(args.filepath)
1802-
? args.filepath
1803-
: [args.filepath];
1804-
if (paths.includes(extraPrompt)) {
1805-
throw new Error("index write failed");
1806-
}
1807-
return real.default.remove(args);
1808-
};
1809-
return { ...real, default: { ...real.default, remove } };
1810-
},
1811-
() => store.commit({ message: "drop prompt segments" }),
1812-
);
1813-
1814-
const tree = await gitLsTree(dir);
1815-
expect(tree).not.toContain(PROMPT_FILE);
1816-
expect(tree).toContain(extraPrompt);
1817-
const written = removeCalls.filter((filepath) => {
1818-
const paths = Array.isArray(filepath) ? filepath : [filepath];
1819-
return !paths.includes(extraPrompt);
1820-
});
1821-
expect(written).toEqual([[PROMPT_FILE]]);
1822-
});
1823-
});
1824-
18251584
describe("createOptimizedContextStore per-turn perf (CL-10666)", () => {
18261585
const SEGMENT_MANIFEST_FILE = "segment-manifest.json";
18271586

0 commit comments

Comments
 (0)