fix(cerebras): trigger auto-compaction when context window exceeded

Previously, Cerebras/GLM models would fail with repeated "rate limit
exceeded" errors instead of auto-compacting when context was too large.
This happened because:

1. GLM models weren't in the "next-gen" family, so pre-flight compaction
   checks were skipped
2. HTTP 400 errors were wrapped in new Error objects, losing the status
   code needed for context window detection
3. HTTP 429 errors (which Cerebras returns for oversized context due to
   token-based rate limiting) were retried instead of triggering compaction
4. Context error detection used fragile exact string matching

Fixes:
- Add GLM to isNextGenModelFamily for pre-flight compaction checks
- Update isGLMModelFamily to match Cerebras patterns (zai-glm, glm-4.7)
- Preserve original errors for HTTP 400 responses
- Detect context-related 429 errors and reclassify as 400 for compaction
- Use robust regex patterns for Cerebras context error detection
This commit is contained in:
Saoud Rizwan
2026-02-04 16:09:05 -08:00
parent 7b09999fdf
commit 4fce944fba
3 changed files with 34 additions and 5 deletions
+15 -3
View File
@@ -192,7 +192,18 @@ export class CerebrasHandler implements ApiHandler {
} catch (error: any) {
// Enhanced error handling for Cerebras API
if (error?.status === 429 || error?.code === "rate_limit_exceeded") {
// Rate limit error - will be handled by retry decorator with patient backoff
// Check if this is actually a context window error disguised as rate limit
// Cerebras rate limiter counts input tokens, so oversized context can trigger 429
const errorMessage = String(error?.message || "")
const isContextRelated = /reduce.*length|context.*length|too.*many.*tokens|tokens.*exceed|input.*too.*long/i.test(
errorMessage,
)
if (isContextRelated) {
// Preserve original error so context window detection can catch it
error.status = 400 // Treat as bad request for context window detection
throw error
}
// Regular rate limit error - will be handled by retry decorator with patient backoff
const _limits = this.getRateLimits()
throw new Error(`Cerebras API rate limit exceeded.`)
} else if (error?.status === 401) {
@@ -203,8 +214,9 @@ export class CerebrasHandler implements ApiHandler {
// Server errors - retryable
throw new Error(`Cerebras API server error (${error.status}): ${error.message || "Unknown server error"}`)
} else if (error?.status === 400) {
// Client errors - not retryable
throw new Error(`Cerebras API bad request: ${error.message || "Invalid request parameters"}`)
// Client errors (including context window exceeded) - preserve original error
// so checkIsCerebrasContextWindowError can detect it and trigger compaction
throw error
}
// Re-throw original error for other cases
@@ -67,7 +67,21 @@ function checkIsCerebrasContextWindowError(response: any): boolean {
const status = response?.status ?? response?.code ?? response?.error?.status ?? response?.response?.status
const message: string = String(response?.message || response?.error?.message || "")
return String(status) === "400" && message.includes("Please reduce the length of the messages or completion")
if (String(status) !== "400") {
return false
}
// Known Cerebras context window error patterns
const CEREBRAS_CONTEXT_PATTERNS = [
/reduce.*length.*messages.*completion/i,
/\bcontext\s*(?:length|window)\b/i,
/\bmaximum\s*context\b/i,
/\b(?:input\s*)?tokens?\s*exceed/i,
/\btoo\s*many\s*tokens?\b/i,
/input is too long/i,
] as const
return CEREBRAS_CONTEXT_PATTERNS.some((pattern) => pattern.test(message))
} catch {
return false
}
+4 -1
View File
@@ -97,6 +97,8 @@ export function isGLMModelFamily(id: string): boolean {
return (
modelId.includes("glm-4.6") ||
modelId.includes("glm-4.5") ||
modelId.includes("glm-4.7") ||
modelId.includes("zai-glm") || // Cerebras pattern (e.g., zai-glm-4.7)
modelId.includes("z-ai/glm") ||
modelId.includes("zai-org/glm")
)
@@ -163,7 +165,8 @@ export function isNextGenModelFamily(id: string): boolean {
isGemini3ModelFamily(modelId) ||
isNextGenOpenSourceModelFamily(modelId) ||
isDeepSeek32ModelFamily(modelId) ||
isDeepSeekNativeModelFamily(modelId)
isDeepSeekNativeModelFamily(modelId) ||
isGLMModelFamily(modelId)
)
}