mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-13 10:43:43 +03:00
Two independent bugs found during further live verification of the conversation-tracking feature: 1. (#9315) The dashboard's "Provider Response" panel showed a stale, incomplete snapshot for long streamed responses. Root cause: open-sse/utils/stream.ts reconstructed the summary from buildStreamSummaryFromEvents(providerPayloadCollector.getEvents(), ...) — but getEvents() only returns whatever survived the collector's maxEvents/maxBytes cap, so once a stream exceeded it (easy with a reasoning + tool-calling model), everything after the cutoff (final finish_reason, tool_calls, rest of reasoning_content, usage) was silently dropped from the reconstruction, even though the client actually received the correct, complete response. Fix: streamPayloadCollector.ts's per-format summary builders (buildOpenAISummary/buildResponsesSummary/buildClaudeSummary/ buildGeminiSummary) are now also available as incremental reducers (createXReducer: ingest one chunk at a time, finalize at the end). createStructuredSSECollector accepts a format + fallbackModel and feeds the reducer on every push() — including chunks that get dropped from the retained event array once the cap is hit — via a new getSummary() method. stream.ts's 3 call sites now use collector.getSummary() instead of reconstructing from the (possibly truncated) getEvents(). 2. Conversation continuation never actually worked for real agentic CLI traffic. Root cause: computeFingerprintHash/hashTurnsBounded anchored conversation identity partly on the system message's text — but real coding-agent CLIs (Claude Code, opencode, etc.) commonly regenerate the system prompt on every single request with live context (timestamp, cwd, git status...). That volatility alone broke both the fingerprint bucket lookup and the prefix-hash continuation check, so every request minted a brand new conversation id even though apiKeyId/model/toolNames and the actual user/assistant history were an unbroken, growing continuation. Confirmed live: 28 consecutive requests from one real, growing session, each recorded as its own turn_count=1 conversation — which is also why /dashboard/conversations appeared empty (nothing ever reached turn_count >= 2) and why an individual timeline/log entry only ever showed a single turn. Fix: both computeFingerprintHash's identity anchor and hashTurnsBounded's head/tail projection now exclude the system message entirely, so a regenerated-every-turn system prompt can no longer break continuation detection. New regression test reproduces the exact scenario (system prompt differs each turn, everything else constant) and confirms the second request is now recognized as a continuation. Also fixed while touching hashTurnsBounded: an accidental stray control character (SOH, 0x01) in the internal join() separator — cosmetic (any consistent separator produces a valid hash) but worth cleaning up since it was already being edited; no stored data depended on the old format since the continuation bug meant turn_count never reached 2 in production. Test plan: - New TDD regression tests for both bugs (stream-payload-collector.test.ts, conversationTracker.test.ts), confirmed failing before the fix and passing after - npm run typecheck:core / npm run lint — clean - npm run test:unit — 26983 tests, 18 failures, all independently confirmed pre-existing on release/v3.8.50 (reproduced identically against the clean base commit) - npm run test:vitest — 291/291 passed - Rebuilt and redeployed to omniroute-dev; health check + DB migration verified