Repository navigation
feat(dashboard): agentic conversation tracking with live transcript view (v2, rebased+cleaned) - #10047
feat(dashboard): agentic conversation tracking with live transcript view (v2, rebased+cleaned)#10047hartmark wants to merge 1 commit into
Conversation
c1658ef to
c0489b3
Compare
Every agentic chat request now gets a conversation id (X-ConversationId
response header). OmniRoute detects when a follow-up request continues the
same conversation via fingerprint + bounded prefix-hash matching, with a
strict-growth invariant to prevent false merges between independent
single-shot requests that happen to share identical opening content.
Continuation detection excludes the system message from the identity
anchor, since real coding-agent CLIs commonly regenerate it every request
with live context (timestamp, cwd, git status) — without this, that
volatility alone broke every continuation check against real traffic.
- `/dashboard/logs`: new toggleable Conversation column.
- `/dashboard/logs/timeline`: requests sharing a conversation id share a
timeline lane, connected by an arrow, with a configurable lane-reuse
window.
- Request detail panel: new Full Conversation transcript above the raw SSE
event stream — Markdown rendering, per-turn timestamps, turn-relative
view, click-any-turn navigation, live auto-refresh building the
transcript in real time from the in-flight SSE chunk buffer while a
request is still streaming, auto-scroll-to-bottom as the live turn grows.
- New `/dashboard/conversations` page listing conversations with 2+ turns,
no-forking model (an edited/duplicated mid-history turn mints its own
independent conversation instead of merging), pagination, duplicate-
anchor fix.
- Configurable auto-refresh intervals on both the timeline and
conversations list pages.
- Responses API tool-call gap fix: turnsFromOpenAiMessages only handled
role-based Chat Completions messages, so bare {type:"function_call"} /
{type:"function_call_output"} / {type:"reasoning"} items (real Responses
API traffic) silently vanished from the Conversation Context panel.
- truncateForLog now counts input[] (Responses API), not just messages[]
(Chat Completions), so a truncated /v1/responses request still shows a
placeholder instead of nothing.
- RequestTimeline.tsx now reads the same debugEnabled/emailsVisible
settings RequestLoggerV2.tsx already used, instead of hardcoding both
false — the timeline view never showed SSE/stream-chunk events or
respected email-masking, regardless of the actual setting.
Migrations 147/148 (agentic_conversations, conversation_turn_nodes) — 135
and 136 are now taken upstream; 143-145 are documented KNOWN_GAPS, so this
uses the next free slot past upstream's current highest.
Test plan:
- npm run typecheck:core — clean
- npm run lint — clean
- node --import tsx/esm scripts/check/check-migration-numbering.mjs — OK, 0 collisions
- 109 unit tests across the conversation-tracking, migration-renumber, and
dashboard-wiring surface — 0 failures
c0489b3 to
4fee3b2
Compare
|
Note for later: while building Ended up not reusing this PR's tables as the reconstruction source — Worth considering for this PR itself, though: the call-log artifact system already stores the same full-fidelity content this feature's own turn matching needs ( Not blocking — just flagging so the two systems don't diverge on "where is the canonical copy of this conversation" going forward. |
|
Restacked and reworked as hartmark#4, per the storage-reuse note above. GitHub doesn't allow retargeting a cross-repo PR's base onto a branch that only exists in the head fork, and this PR now needs to sit on top of two other in-flight stacked branches (feat/openai-responses-store-toggle -> feat/responses-previous-response-id-virtualization) that live in Summary of the rework: Closing this one in favor of hartmark#4. |
Summary
Replaces #9439 — same feature, rebased onto the current
release/v3.8.50tip, squashed to a single commit, and trimmed to the minimal diff the feature actually needs.X-ConversationIdresponse header). OmniRoute detects when a follow-up request continues the same conversation via fingerprint + bounded prefix-hash matching, with a strict-growth invariant (turns.length <= candidate.lastMessageCount→ reject) to prevent false merges between independent single-shot requests that happen to share identical opening content./dashboard/logs: new toggleable Conversation column./dashboard/logs/timeline: requests sharing a conversation id share a timeline lane, connected by an arrow, with a configurable lane-reuse window./dashboard/conversationspage listing only conversations with 2+ turns, no-forking model with pagination and duplicate-anchor fix.What changed vs #9439
#9439 accumulated 23 commits across many rebases, including i18n-sync noise and fixes for bugs that were pre-existing on
release/v3.8.50itself, unrelated to this feature. This PR is a from-scratch minimal-diff pass:enlocale to upstream, then ranscripts/i18n/fill-missing-from-en.mjsto add only this feature's 3 new keys (sidebar.conversations,sidebar.conversationsSubtitle,logs.conversation) with their plain English fallback value — no reordering, no re-translation. Passesi18n-ui-coverage(fallback counts as present, not a placeholder) andi18n-vi-completeness(no__MISSING__markers).open-sse/utils/stream.ts,open-sse/utils/streamPayloadCollector.ts, its test) — orthogonal to conversation tracking, already covered by fix(sse): provider-response summary format bugs (dashboard Provider Response panel) #10037. Kept only the conversation-continuation half of that commit (excluding the system message from the identity anchor).OmniRouteLogo.tsxDark Reader hydration-warning suppression) that had been opportunistically bundled in — not needed for this feature.HARD_COMPAT_REASONSduplicate declaration (base-red 🔴 Release branch not green: release/v3.8.50 #9298, now closed, upstream restructured the file), a missingmergeResponseToolNameMapimport, and missing frontmatter inAGENTROUTER_WAF.md.KNOWN_GAPS(burned numbers), so used the next free slot past upstream's current highest (146).chatcore-log-truncation.test.ts) whose payload size assumed an 8KB truncation threshold; upstream's current default is 1MB, so bumped the test payload to match the sibling test's pattern.Test plan
npm run typecheck:core— cleannpm run lint— cleannode --import tsx/esm scripts/check/check-migration-numbering.mjs— OK, 0 collisionsagenticConversations.test.ts,conversationTracker.test.ts,request-timeline-lane-allocation.test.ts,conversations-tree-route-seq-param.test.ts,conversations-active-call-log-id.test.ts,logs-detail-partial-reasoning-chunk-split.test.ts,inspector-conversation-normalizer.test.ts,sidebar-monitoring-reorg.test.ts,sidebar-visibility.test.ts,chatcore-log-truncation.test.ts,migration-135-numbering-collision.test.ts,check-migration-numbering.test.ts,db-job-registry-migration-renumber-139.test.ts,i18n-vi-completeness.test.tsomniroute-devdeploy smoke) still applies unchanged — no feature behavior touched by this cleanup, only which diff carries it.