fix(ai): detect Ollama overflow errors closes #2626
This commit is contained in:
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed context overflow detection to recognize Ollama error responses like `prompt too long; exceeded max context length ...`, so callers can trigger compaction and retry instead of surfacing the raw overflow error ([#2626](https://github.com/badlogic/pi-mono/issues/2626))
|
||||||
|
|
||||||
## [0.63.0] - 2026-03-27
|
## [0.63.0] - 2026-03-27
|
||||||
|
|
||||||
### Breaking Changes
|
### Breaking Changes
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import type { AssistantMessage } from "../types.js";
|
|||||||
* - Cerebras: Returns "400/413 status code (no body)" - handled separately below
|
* - Cerebras: Returns "400/413 status code (no body)" - handled separately below
|
||||||
* - Mistral: "Prompt contains X tokens ... too large for model with Y maximum context length"
|
* - Mistral: "Prompt contains X tokens ... too large for model with Y maximum context length"
|
||||||
* - z.ai: Does NOT error, accepts overflow silently - handled via usage.input > contextWindow
|
* - z.ai: Does NOT error, accepts overflow silently - handled via usage.input > contextWindow
|
||||||
* - Ollama: Silently truncates input - not detectable via error message
|
* - Ollama: Some deployments truncate silently, others return errors like "prompt too long; exceeded max context length by X tokens"
|
||||||
*/
|
*/
|
||||||
const OVERFLOW_PATTERNS = [
|
const OVERFLOW_PATTERNS = [
|
||||||
/prompt is too long/i, // Anthropic
|
/prompt is too long/i, // Anthropic
|
||||||
@@ -39,6 +39,7 @@ const OVERFLOW_PATTERNS = [
|
|||||||
/exceeded model token limit/i, // Kimi For Coding
|
/exceeded model token limit/i, // Kimi For Coding
|
||||||
/too large for model with \d+ maximum context length/i, // Mistral
|
/too large for model with \d+ maximum context length/i, // Mistral
|
||||||
/model_context_window_exceeded/i, // z.ai non-standard finish_reason surfaced as error text
|
/model_context_window_exceeded/i, // z.ai non-standard finish_reason surfaced as error text
|
||||||
|
/prompt too long; exceeded (?:max )?context length/i, // Ollama explicit overflow error
|
||||||
/context[_ ]length[_ ]exceeded/i, // Generic fallback
|
/context[_ ]length[_ ]exceeded/i, // Generic fallback
|
||||||
/too many tokens/i, // Generic fallback
|
/too many tokens/i, // Generic fallback
|
||||||
/token limit exceeded/i, // Generic fallback
|
/token limit exceeded/i, // Generic fallback
|
||||||
@@ -71,8 +72,9 @@ const OVERFLOW_PATTERNS = [
|
|||||||
* **Unreliable detection:**
|
* **Unreliable detection:**
|
||||||
* - z.ai: Sometimes accepts overflow silently (detectable via usage.input > contextWindow),
|
* - z.ai: Sometimes accepts overflow silently (detectable via usage.input > contextWindow),
|
||||||
* sometimes returns rate limit errors. Pass contextWindow param to detect silent overflow.
|
* sometimes returns rate limit errors. Pass contextWindow param to detect silent overflow.
|
||||||
* - Ollama: Silently truncates input without error. Cannot be detected via this function.
|
* - Ollama: May truncate input silently for some setups, but may also return explicit
|
||||||
* The response will have usage.input < expected, but we don't know the expected value.
|
* overflow errors that match the patterns above. Silent truncation still cannot be
|
||||||
|
* detected here because we do not know the expected token count.
|
||||||
*
|
*
|
||||||
* ## Custom Providers
|
* ## Custom Providers
|
||||||
*
|
*
|
||||||
|
|||||||
42
packages/ai/test/overflow.test.ts
Normal file
42
packages/ai/test/overflow.test.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import type { AssistantMessage } from "../src/types.js";
|
||||||
|
import { isContextOverflow } from "../src/utils/overflow.js";
|
||||||
|
|
||||||
|
function createErrorMessage(errorMessage: string): AssistantMessage {
|
||||||
|
return {
|
||||||
|
role: "assistant",
|
||||||
|
content: [],
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "ollama",
|
||||||
|
model: "qwen3.5:35b",
|
||||||
|
usage: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
totalTokens: 0,
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
total: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
stopReason: "error",
|
||||||
|
errorMessage,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("isContextOverflow", () => {
|
||||||
|
it("detects explicit Ollama prompt-too-long errors", () => {
|
||||||
|
const message = createErrorMessage("400 `prompt too long; exceeded max context length by 100918 tokens`");
|
||||||
|
expect(isContextOverflow(message, 32768)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not treat generic non-overflow Ollama errors as overflow", () => {
|
||||||
|
const message = createErrorMessage("500 `model runner crashed unexpectedly`");
|
||||||
|
expect(isContextOverflow(message, 32768)).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed auto-compaction overflow recovery for Ollama models when the backend returns explicit `prompt too long; exceeded max context length ...` errors instead of silently truncating input ([#2626](https://github.com/badlogic/pi-mono/issues/2626))
|
||||||
|
|
||||||
## [0.63.0] - 2026-03-27
|
## [0.63.0] - 2026-03-27
|
||||||
|
|
||||||
### Breaking Changes
|
### Breaking Changes
|
||||||
|
|||||||
Reference in New Issue
Block a user