diff --git a/CHANGELOG.md b/CHANGELOG.md index 4be3ab58a2..c51d604c87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- Errors: prevent false positive context overflow detection when conversation mentions "context overflow" topic. (#2078) Thanks @sbking. - Model failover: treat HTTP 400 errors as failover-eligible, enabling automatic model fallback when providers return bad request errors. (#1879) Thanks @orenyomtov. - Exec approvals: format forwarded command text as inline/fenced monospace for safer approval scanning across channels. (#11937) - Config: clamp `maxTokens` to `contextWindow` to prevent invalid model configs. (#5516) Thanks @lailoo. diff --git a/src/agents/pi-embedded-helpers.iscontextoverflowerror.test.ts b/src/agents/pi-embedded-helpers.iscontextoverflowerror.test.ts index 19165caa51..79a1973264 100644 --- a/src/agents/pi-embedded-helpers.iscontextoverflowerror.test.ts +++ b/src/agents/pi-embedded-helpers.iscontextoverflowerror.test.ts @@ -46,4 +46,12 @@ describe("isContextOverflowError", () => { expect(isContextOverflowError("model not found")).toBe(false); expect(isContextOverflowError("authentication failed")).toBe(false); }); + + it("ignores normal conversation text mentioning context overflow", () => { + // These are legitimate conversation snippets, not error messages + expect(isContextOverflowError("Let's investigate the context overflow bug")).toBe(false); + expect(isContextOverflowError("The mystery context overflow errors are strange")).toBe(false); + expect(isContextOverflowError("We're debugging context overflow issues")).toBe(false); + expect(isContextOverflowError("Something is causing context overflow messages")).toBe(false); + }); }); diff --git a/src/agents/pi-embedded-helpers/errors.ts b/src/agents/pi-embedded-helpers/errors.ts index 9111020753..6c69c59392 100644 --- a/src/agents/pi-embedded-helpers/errors.ts +++ b/src/agents/pi-embedded-helpers/errors.ts @@ -24,7 +24,7 @@ export function isContextOverflowError(errorMessage?: string): boolean { lower.includes("prompt is too long") || lower.includes("exceeds model context window") || (hasRequestSizeExceeds && hasContextWindow) || - lower.includes("context overflow") || + lower.includes("context overflow:") || (lower.includes("413") && lower.includes("too large")) ); } diff --git a/src/agents/tools/web-search.ts b/src/agents/tools/web-search.ts index d6d1958e5d..5653952a96 100644 --- a/src/agents/tools/web-search.ts +++ b/src/agents/tools/web-search.ts @@ -278,15 +278,21 @@ function resolvePerplexityModel(perplexity?: PerplexityConfig): string { } function resolveGrokConfig(search?: WebSearchConfig): GrokConfig { - if (!search || typeof search !== "object") return {}; + if (!search || typeof search !== "object") { + return {}; + } const grok = "grok" in search ? search.grok : undefined; - if (!grok || typeof grok !== "object") return {}; + if (!grok || typeof grok !== "object") { + return {}; + } return grok as GrokConfig; } function resolveGrokApiKey(grok?: GrokConfig): string | undefined { const fromConfig = normalizeApiKey(grok?.apiKey); - if (fromConfig) return fromConfig; + if (fromConfig) { + return fromConfig; + } const fromEnv = normalizeApiKey(process.env.XAI_API_KEY); return fromEnv || undefined; } @@ -474,9 +480,7 @@ async function runWebSearch(params: { ? `${params.provider}:${params.query}:${params.count}:${params.country || "default"}:${params.search_lang || "default"}:${params.ui_lang || "default"}:${params.freshness || "default"}` : params.provider === "perplexity" ? `${params.provider}:${params.query}:${params.perplexityBaseUrl ?? DEFAULT_PERPLEXITY_BASE_URL}:${params.perplexityModel ?? DEFAULT_PERPLEXITY_MODEL}` - : params.provider === "grok" - ? `${params.provider}:${params.query}:${params.grokModel ?? DEFAULT_GROK_MODEL}:${params.grokInlineCitations ?? false}` - : `${params.provider}:${params.query}:${params.count}:${params.country || "default"}:${params.search_lang || "default"}:${params.ui_lang || "default"}`, + : `${params.provider}:${params.query}:${params.grokModel ?? DEFAULT_GROK_MODEL}:${String(params.grokInlineCitations ?? false)}`, ); const cached = readCache(SEARCH_CACHE, cacheKey); if (cached) {