@@ -23,6 +23,7 @@ import {
|
23 | 23 | mockedExtractObservedOverflowTokenCount, |
24 | 24 | mockedGlobalHookRunner, |
25 | 25 | mockedGetApiKeyForModel, |
| 26 | +mockedIsLikelyContextOverflowError, |
26 | 27 | mockedMarkAuthProfileSuccess, |
27 | 28 | mockedPickFallbackThinkingLevel, |
28 | 29 | mockedResolveAuthProfileOrder, |
@@ -1543,6 +1544,39 @@ describe("runEmbeddedPiAgent overflow compaction trigger routing", () => {
|
1543 | 1544 | expect(result.meta.error).toBeUndefined(); |
1544 | 1545 | }); |
1545 | 1546 | |
| 1547 | +it("surfaces a visible blocked payload for Codex promptError overflow without assistant text", async () => { |
| 1548 | +const promptError = new Error( |
| 1549 | +"Codex ran out of room in the model's context window. Start a new thread or clear earlier history before retrying.", |
| 1550 | +); |
| 1551 | +const terminalLifecycleMeta: Array<Record<string, unknown>> = []; |
| 1552 | +mockedRunEmbeddedAttempt.mockResolvedValueOnce( |
| 1553 | +makeAttemptResult({ |
| 1554 | + promptError, |
| 1555 | +promptErrorSource: "prompt", |
| 1556 | +assistantTexts: [], |
| 1557 | +attemptUsage: { input: 0, output: 0, total: 0 }, |
| 1558 | +setTerminalLifecycleMeta: (meta) => { |
| 1559 | +terminalLifecycleMeta.push(meta); |
| 1560 | +}, |
| 1561 | +}), |
| 1562 | +); |
| 1563 | + |
| 1564 | +const result = await runEmbeddedPiAgent(overflowBaseRunParams); |
| 1565 | + |
| 1566 | +expect(mockedIsLikelyContextOverflowError).toHaveBeenCalledWith(promptError.message); |
| 1567 | +expect(mockedCompactDirect).toHaveBeenCalledTimes(1); |
| 1568 | +expect(result.payloads?.[0]).toMatchObject({ |
| 1569 | +isError: true, |
| 1570 | +text: expect.stringContaining("Context overflow"), |
| 1571 | +}); |
| 1572 | +expect(result.payloads?.[0]?.text).toContain("/reset"); |
| 1573 | +expect(result.payloads?.[0]?.text).toContain("/new"); |
| 1574 | +expect(result.meta.error?.kind).toBe("context_overflow"); |
| 1575 | +expect(result.meta.livenessState).toBe("blocked"); |
| 1576 | +expect(result.meta.finalAssistantVisibleText).toBe(result.payloads?.[0]?.text); |
| 1577 | +expect(terminalLifecycleMeta.at(-1)).toMatchObject({ livenessState: "blocked" }); |
| 1578 | +}); |
| 1579 | + |
1546 | 1580 | it("does not reset compaction attempt budget after successful tool-result truncation", async () => { |
1547 | 1581 | const overflowError = queueOverflowAttemptWithOversizedToolOutput( |
1548 | 1582 | mockedRunEmbeddedAttempt, |
|