- #1712: Strip existing billing headers before injecting to fix prompt cache misses
- #1719: Strip output_config.format for non-Anthropic Claude endpoints
- #1707: Set terminal error state on quality validation failure (false ALL_ACCOUNTS_INACTIVE)
- #1706: Wrap proxy_assignments queries in try-catch for missing table on Electron
- #1704: Fix Windows file URL path resolution in migration runner with cwd fallback
GLM/ZhipuAI rejects system role messages with 422 'Input should be
user or assistant'. When memory injection adds a system-role message,
GLM combo targets fail because the system message survives into the
upstream request.
Fix:
- injection.ts: add glm, glmt, glm-cn, zai, qianfan to
PROVIDERS_WITHOUT_SYSTEM_MESSAGE so memory is injected as user role
- roleNormalizer.ts: add exact 'glm' model match to
MODELS_WITHOUT_SYSTEM_ROLE for Pollinations and bare model ids
Test: 22 new unit tests covering all GLM variants + regression checks
for openai/anthropic providers.
Closes#1701
Add 'Invalid signature in thinking block' to COMBO_BAD_REQUEST_FALLBACK_PATTERNS
so combo routing falls through to the next target instead of returning 400 directly.
This error occurs when extended thinking signatures expire between turns,
which is a model-specific issue that won't be fixed by retrying the same provider.
Closes#1696
The previous 90% default treated Codex accounts as unavailable while they
still had ~10% quota remaining. A 99% threshold reserves only a minimal
safety margin near true exhaustion while preserving usable quota.
- Export DEFAULT_QUOTA_THRESHOLD_PERCENT=99 from quotaCache.ts
- Replace CODEX_QUOTA_THRESHOLD_PERCENT in auth.ts with shared constant
- Update quota policy tests to match new default
Co-authored-by: dhaern <manker_lol@hotmail.com>
The stream readiness gate from PR #1693 validates SSE body content.
The test harness checked only `headers.accept` (lowercase) but executors
set `Accept` (capital A), causing the harness to return JSON instead of
SSE for streaming requests. Fixed by checking both header casings.
- Replace polynomial regex /\/+$/ with loop-based stripTrailingSlashes()
across 8 enterprise provider configs (azure-openai, azureAi, bedrock,
datarobot, oci, sap, watsonx, audioSpeech) — fixes js/polynomial-redos
- Add prototype-pollution denylist guard in usageHistory.ts to reject
__proto__/constructor/prototype as model keys — fixes
js/prototype-polluting-assignment (#167, #168)
- Suppress 3 false-positive js/insufficient-password-hash alerts in
chatgpt-web.ts and builtins.ts where SHA-256 is used for cache-key
derivation, not password storage (#176, #177, #178)
- Add stripTrailingSlashes unit tests with ReDoS regression check
4 fixes from Gemini Code Assist PR #1689 review:
1. HIGH: Multi-part message content duplication — skip array-content
messages instead of joining+replacing all text parts with compressed
result, which caused content duplication (e.g., [A,B] → [comp(A+B), comp(A+B)])
2. HIGH: String.prototype.replace $& vulnerability — use arrow function
callback instead of string arg in restorePreservedBlocks() to prevent
special replacement patterns ($&, , etc.) from corrupting restored
content containing code, URLs, or file paths
3. HIGH: UI/backend rule name mismatch — ALL_CAVEMAN_RULES in
CompressionSettingsTab.tsx now uses actual backend rule names
(polite_framing, hedging, verbose_instructions, etc.) instead of
fabricated names (hedging_disclaimer, redundant_please, etc.)
that would break the skip-rules feature
4. MEDIUM: Remove no-op turn_marker rule — pattern /^$/g matches only
empty strings and replaces with empty string, achieving nothing.
Removed from CAVEMAN_RULES; total count now 29 (was 30).
Tests: 72/72 pass, typecheck: 0 errors, lint: 0 errors
Update the deterministic fallback API key to use hyphens instead of
underscores so generated keys match the expected format.
Also set API_KEY_SECRET in unit tests that exercise API key creation to
ensure consistent resolver behavior under test.
The JSDoc comment in cors.ts explains why Access-Control-Allow-Origin
is intentionally excluded from CORS_HEADERS. The test regex was
matching the comment text, causing a false failure.
- api-keys: remove flaky console.log assertion (route now uses Pino
structured logger via console.error, not console.log)
- chat-pipeline: update REQUIRE_API_KEY test to reflect authz pipeline
enforcement moved to route layer (handleChat no longer checks it)
- chat-pipeline: accept both 'Invalid'/'Incorrect' API key error formats
- CodexExecutor: isCodexResponsesWebSocketRequired now defaults to HTTP
unless codexTransport='websocket' is set in providerSpecificData
- CodexExecutor: store defaults to false unless openaiStoreEnabled=true
- CodexExecutor: WS unavailable now falls back to HTTP via super.execute()
instead of returning 503 (dead code path after guard refactor)
- Meta AI: X-FB-Friendly-Name updated from useAbraSendMessageMutation
to useEctoSendMessageSubscription
- Proxy middleware: tests now verify authz/pipeline.ts (refactored from proxy.ts)
- Chat pipeline: accept both 'Invalid'/'Incorrect' API key error messages
- Qwen retry: selective setTimeout mock to avoid tripping body read timeout
- Treat status 499 as terminal non-retryable error in both priority and
round-robin combo loops — no fallback to other models when client is gone
- Propagate AbortSignal from request into handleComboChat so the combo
loop can detect client disconnects before starting new model attempts
- Make retry/fallback delays abort-aware via signal.addEventListener
- Add 5 unit tests covering 499 early-exit, signal.aborted pre-check,
multi-model abort, 502 contrast behavior, and abort-during-wait
Integrated into release/v3.7.2 — implements conversation continuity for muse-spark-web executor with SHA-256 prefix hashing, TTL cache, and eviction-on-error
- Fix question_to_directive rule: trim trailing whitespace before lookup
- Fix DB import path: correct relative path from src/lib/db to open-sse
- Add test DB cleanup beforeEach for isolation
- Add 4 unit test files: caveman-db, hedging, dedup, structural (28 tests)
- Add golden set quality test (4 tests, 99.3% key phrase preservation)
- Add golden set savings test (3 tests, performance + savings verification)
- Add golden set data (20 verbose coding prompts with key phrases)
- Add migration 028 for new test suite acknowledgment
67 tests pass across 9 files. typecheck:core clean.
Centralize remote image downloads behind a shared helper that
validates outbound URLs, enforces redirect and size limits, and
applies request timeouts before bytes are read.
Wire the helper into image generation and vision bridge flows so
remote image inputs and result URLs follow the same fetch policy and
block redirects to private hosts. Update key management routes to use
structured logging and document the WebSocket bridge secret in the
example environment file.
The billing header fingerprint was computed from the first user message text
via computeFingerprint(), which changes every conversation turn. This mutated
the system[] prefix on each request, invalidating Anthropic's prompt-cache
prefix and forcing ~100% cache_create (vs 96% cache_read with stable prefix).
Now uses a per-day SHA-256 hash of the date + ccVersion, keeping the billing
header format while preserving prompt-cache prefix stability across turns.
Includes 6 unit tests.
The prompt_cache_key was derived from the account-wide workspaceId, meaning
all conversations from the same OAuth account shared one cache partition.
The official Codex CLI uses conversation_id (a unique UUID per session).
Priority: body.session_id > body.conversation_id > workspaceId.
Session IDs are captured BEFORE deletion from the body.
Includes 10 unit tests.