



























@@ -322,6 +322,118 @@ describe("runEmbeddedAttempt context engine sessionKey forwarding", () => {
322322);
323323});
324324325+it("uses assembled context as the default precheck authority", async () => {
326+let sawPrompt = false;
327+const hugeHistory = "large raw history ".repeat(25_000);
328+329+const result = await createContextEngineAttemptRunner({
330+contextEngine: createTestContextEngine({
331+assemble: async () => ({
332+messages: [
333+{ role: "user", content: "small assembled context", timestamp: 1 },
334+] as AgentMessage[],
335+estimatedTokens: 8,
336+}),
337+}),
338+ sessionKey,
339+ tempPaths,
340+sessionMessages: [{ role: "user", content: hugeHistory, timestamp: 1 }] as AgentMessage[],
341+attemptOverrides: {
342+contextTokenBudget: 500,
343+},
344+sessionPrompt: async (session) => {
345+sawPrompt = true;
346+session.messages = [
347+ ...session.messages,
348+{ role: "assistant", content: "done", timestamp: 2 },
349+];
350+},
351+});
352+353+expect(sawPrompt).toBe(true);
354+expect(result.promptError).toBeNull();
355+expect(result.promptErrorSource).toBeNull();
356+expect(hoisted.preemptiveCompactionCalls.at(-1)).not.toHaveProperty("unwindowedMessages");
357+});
358+359+it("honors context engines that opt into preassembly overflow authority", async () => {
360+let sawPrompt = false;
361+const hugeHistory = "large raw history ".repeat(25_000);
362+363+const result = await createContextEngineAttemptRunner({
364+contextEngine: createTestContextEngine({
365+assemble: async () => ({
366+messages: [
367+{ role: "user", content: "small assembled context", timestamp: 1 },
368+] as AgentMessage[],
369+estimatedTokens: 8,
370+promptAuthority: "preassembly_may_overflow",
371+}),
372+}),
373+ sessionKey,
374+ tempPaths,
375+sessionMessages: [{ role: "user", content: hugeHistory, timestamp: 1 }] as AgentMessage[],
376+attemptOverrides: {
377+contextTokenBudget: 500,
378+},
379+sessionPrompt: async (session) => {
380+sawPrompt = true;
381+session.messages = [
382+ ...session.messages,
383+{ role: "assistant", content: "done", timestamp: 2 },
384+];
385+},
386+});
387+388+expect(sawPrompt).toBe(false);
389+expect(result.promptErrorSource).toBe("precheck");
390+expect(result.preflightRecovery?.route).toBe("compact_only");
391+expect(hoisted.preemptiveCompactionCalls.at(-1)).toHaveProperty("unwindowedMessages");
392+});
393+394+it("snapshots pre-assembly messages before assemble even when the engine windows in place", async () => {
395+const hugeHistory = "large raw history ".repeat(25_000);
396+const preassemblyMarker = { role: "user", content: hugeHistory, timestamp: 1 } as AgentMessage;
397+398+await createContextEngineAttemptRunner({
399+contextEngine: createTestContextEngine({
400+assemble: async ({ messages }: { messages: AgentMessage[] }) => {
401+// Simulate an engine that windows the input array IN PLACE.
402+// The assemble contract does not require immutability, so the
403+// runner must have already snapshotted before calling us.
404+messages.length = 0;
405+messages.push({ role: "user", content: "windowed", timestamp: 2 } as AgentMessage);
406+return {
407+messages: [
408+{ role: "user", content: "small assembled context", timestamp: 1 },
409+] as AgentMessage[],
410+estimatedTokens: 8,
411+promptAuthority: "preassembly_may_overflow",
412+};
413+},
414+}),
415+ sessionKey,
416+ tempPaths,
417+sessionMessages: [preassemblyMarker],
418+attemptOverrides: {
419+contextTokenBudget: 500,
420+},
421+sessionPrompt: async (session) => {
422+session.messages = [
423+ ...session.messages,
424+{ role: "assistant", content: "done", timestamp: 3 },
425+];
426+},
427+});
428+429+const lastCall = hoisted.preemptiveCompactionCalls.at(-1);
430+expect(lastCall).toHaveProperty("unwindowedMessages");
431+const unwindowed = (lastCall as { unwindowedMessages?: AgentMessage[] }).unwindowedMessages;
432+// The snapshot must reflect the true pre-assembly state, not the in-place
433+// windowed array that assemble mutated.
434+expect(unwindowed).toEqual([preassemblyMarker]);
435+});
436+325437it("keeps gateway model runs independent from agent context and session history", async () => {
326438const bootstrap = vi.fn(async () => ({ bootstrapped: true }));
327439const assemble = vi.fn(async ({ messages }: { messages: AgentMessage[] }) => ({
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。