Skip to content

Commit 6305995

Browse files
committed
fix(agents): preserve precheck after context assembly failure
1 parent 14d361b commit 6305995

2 files changed

Lines changed: 44 additions & 1 deletion

File tree

src/agents/embedded-agent-runner/run/attempt.spawn-workspace.context-engine.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2106,6 +2106,46 @@ describe("runEmbeddedAttempt context engine sessionKey forwarding", () => {
21062106
expect(hoisted.preemptiveCompactionCalls).toHaveLength(0);
21072107
});
21082108

2109+
it("keeps the generic precheck active when owning context engine assembly fails", async () => {
2110+
const lockEvents = trackSessionWriteLocks();
2111+
let sawPrompt = false;
2112+
const hugeHistory = "large raw history ".repeat(2_000);
2113+
2114+
const result = await createContextEngineAttemptRunner({
2115+
contextEngine: createTestContextEngine({
2116+
info: {
2117+
id: "test-context-engine",
2118+
name: "Test Context Engine",
2119+
version: "0.0.1",
2120+
ownsCompaction: true,
2121+
},
2122+
assemble: async () => {
2123+
throw new Error("assembly failed");
2124+
},
2125+
}),
2126+
sessionKey,
2127+
tempPaths,
2128+
sessionMessages: [{ role: "user", content: hugeHistory, timestamp: 1 }] as AgentMessage[],
2129+
attemptOverrides: {
2130+
contextTokenBudget: 500,
2131+
},
2132+
sessionPrompt: async (session) => {
2133+
sawPrompt = true;
2134+
session.messages = [
2135+
...session.messages,
2136+
{ role: "assistant", content: "done", timestamp: 2 },
2137+
];
2138+
},
2139+
});
2140+
2141+
expect(sawPrompt).toBe(false);
2142+
expect(result.promptErrorSource).toBe("precheck");
2143+
expect(result.preflightRecovery?.route).toBe("compact_only");
2144+
expect(hoisted.preemptiveCompactionCalls).toHaveLength(1);
2145+
expect(hoisted.preemptiveCompactionCalls.at(-1)).not.toHaveProperty("unwindowedMessages");
2146+
expectInitialLockReleasedBeforePostTurnWrite(lockEvents);
2147+
});
2148+
21092149
it("repairs tool-result pairing after context engine assembly", async () => {
21102150
let promptMessages: AgentMessage[] = [];
21112151

src/agents/embedded-agent-runner/run/attempt.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2577,6 +2577,7 @@ export async function runEmbeddedAttempt(
25772577
let unwindowedContextEngineMessagesForPrecheck: AgentMessage[] | undefined;
25782578
let contextEnginePromptAuthority: NonNullable<AssembleResult["promptAuthority"]> =
25792579
"assembled";
2580+
let contextEngineAssemblySucceeded = false;
25802581
const inFlightPromptSettlePromises = new Set<Promise<void>>();
25812582
const inFlightAbortSettlePromises = new Set<Promise<void>>();
25822583
const trackSettlePromise = (
@@ -3334,6 +3335,7 @@ export async function runEmbeddedAttempt(
33343335
activeSession.agent.state.messages = assembledMessages;
33353336
}
33363337
contextEnginePromptAuthority = assembled.promptAuthority ?? "assembled";
3338+
contextEngineAssemblySucceeded = true;
33373339
if (contextEnginePromptAuthority === "preassembly_may_overflow") {
33383340
unwindowedContextEngineMessagesForPrecheck =
33393341
preassemblyContextEngineMessagesForPrecheck;
@@ -4604,7 +4606,8 @@ export async function runEmbeddedAttempt(
46044606
let preemptiveCompaction = null;
46054607
const shouldSkipPrecheck =
46064608
skipPromptSubmission ||
4607-
(activeContextEngine?.info.ownsCompaction &&
4609+
(contextEngineAssemblySucceeded &&
4610+
activeContextEngine?.info.ownsCompaction &&
46084611
contextEnginePromptAuthority !== "preassembly_may_overflow");
46094612

46104613
if (shouldSkipPrecheck && !skipPromptSubmission) {

0 commit comments

Comments
 (0)