feat(dashboard): AI Discuss panel + per-row Analyze button (#419) - #431
Closed
jonathaneoliver wants to merge 1 commit into
Closed
feat(dashboard): AI Discuss panel + per-row Analyze button (#419)#431jonathaneoliver wants to merge 1 commit into
jonathaneoliver wants to merge 1 commit into
Conversation
The user-facing surface for AI session analysis (epic #412 MVP). content/shared/llm-chat.js DOM-free SSE consumer + helpers. window.LLMChat surface: chat({profile, messages, sessionId, sessions, range, oneShot}) → {on, cancel}; events: tool_call, tool_result, assistant_message, usage, error, done, cancelled. loadProfiles() / loadBudget() — wrap the read endpoints. formatTimestamp / parseTimestamp / linkifyTimestamps — used to turn cited mm:ss.ms timestamps into click-to-seek anchors. content/dashboard/llm-discuss-panel.js For session-viewer.html. Floating 💬 toggle (bottom-right), right-side slide-out panel with model picker, budget meter, scrollable history (per-session localStorage, last 50 msgs), textarea + Send + Cancel. Cmd/Ctrl+Enter sends, Escape closes when no stream is active. ARIA roles, focus returns to the toggle on close. Click on linkified timestamp dispatches a `llm:seek` CustomEvent — page-level glue can wire it to the chart cursor in a follow-up. content/dashboard/llm-analyze-modal.js For sessions.html (the picker). MutationObserver watches #sessionsContainer for span[data-star-cell][data-session-id] elements (the canonical per-row session_id hook in the table rendered by session-replay.js) and injects an Analyze button next to each row's star with z-index above the row's stretched-link overlay. Click opens a modal that streams a one-shot overview using the same shared module. Escape + backdrop both close; focus returns to the trigger row. content/dashboard/session-viewer.html, sessions.html +2 script tags each — load shared llm-chat.js then the page- specific UI module. Pre-commit code-review fixes (Sonnet pass on the staged diff): - **Critical:** the picker on sessions.html renders rows as <tr> with the session_id on a child star span — not as .session-card divs. Initial selector queried the wrong shape and would never have found a row. Fixed: target the star span and inject into its cell at z-index:3 above the row's stretched-link overlay. - SSE parser now tolerates spec-conformant `event:foo` (no space after colon) in addition to the forwarder's `event: foo`. Per W3C EventSource: a single optional space after the colon. - Profile-select race: Send button starts disabled ("Loading models…"), enables only after populateProfileSelect resolves. Guards sendMessage so a fast Cmd+Enter no-ops instead of submitting with an empty profile. - Modal Esc handler now removes itself on every close path (backdrop click, X button, Escape) so opening many modals doesn't leak listeners. Same pattern in the Discuss panel. - Discuss panel: Esc closes when no stream is active; focus returns to the toggle button after close (WCAG 2.4.3). - CSS namespace tightened: .llm-msg/.llm-ts → .llmchat-msg/ .llmchat-ts to avoid future collision with generic class names (e.g. "license message"). - Removed duplicate id="llm-profile-select" — label now wraps the select directly so no id is needed. - inputEl uses readOnly during streaming so users can still select / copy their own pending text. Cross-compare per memory rule: testing-session.html (LIVE control plane) is intentionally NOT touched. Analytical AI is for archived replay; the live-session control AI surface is sub-issues #424 (read-only inspection tools) and #425 (HITL mutation tools), both planned for after the analytical MVP ships. What still needs browser verification: - 💬 toggle position vs existing bottom-right chart-expand controls on session-viewer (visual collision check). - The per-row Analyze button placement in the picker's first cell — does it look right next to the star, does it stay clickable above the stretched-link overlay? - Click-to-seek custom event — currently fires document-level `llm:seek`; page-level handler that drives the chart cursor is a documented follow-up, not in this PR. - Real session_id end-to-end: pick an archived session, click Analyze, confirm streamed answer with timestamps. Three files, all node --check syntax-clean. The forwarder side is fully covered by the existing 67-test suite (unchanged here). Part of epic #412. Closes #419. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
Owner
Author
|
Closing — superseded by the v2.0.0 release.
This stale stacked-PR chain (epic #412) has no salvageable diff against current |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
session-viewer.html(multi-turn chat about the loaded session) + per-row Analyze button onsessions.html(one-shot overview modal).Closes #419.What's new
content/shared/llm-chat.jswindow.LLMChatAPIcontent/dashboard/llm-discuss-panel.jssession-viewer.htmlcontent/dashboard/llm-analyze-modal.jssessions.htmlcontent/dashboard/session-viewer.htmlcontent/dashboard/sessions.htmlBehaviour
Discuss panel (session-viewer.html):
session=<id>parameter./api/llm_profiles./api/llm_budgetevery 30s while open.mm:ss.mstimestamps render as click-to-seek anchors that dispatchdocument.dispatchEvent(new CustomEvent('llm:seek')). Wiring to the chart cursor is a follow-up.Analyze button (sessions.html):
[data-star-cell][data-session-id]hook).Pre-commit code-review fixes (this is the meaningful section)
The Sonnet pass caught one critical bug: my initial implementation queried
.session-carddivs for the picker — butsessions.htmlactually renders rows as<tr>with the session_id on a child<span data-star-cell>. The button would never have appeared. Fixed to target the real DOM shape, with z-index above the row overlay.Plus important polish:
event:foo(no space) per W3C EventSource. Original required the literalevent:(with space). Forwarder happens to emit the spaced form, but a future emit site or rewriting proxy would have silently dropped events.sendMessageuntil the profile fetch resolves. Stops a fast Cmd+Enter from sending with an empty profile..llm-msg/.llm-ts→.llmchat-msg/.llmchat-tsto avoid future collision with generic class names.readOnlyduring streaming instead ofdisabledso users can still select / copy their own pending text.Cross-compare per memory rule
testing-session.html(the LIVE control plane) is intentionally NOT touched. Analytical AI is for archived replay; the live-session control AI surface is sub-issues #424 (read-only inspection tools —get_session_state,get_failure_settings) and #425 (HITL mutation tools with propose/apply UX), both planned for after the analytical MVP ships.What needs your hands-on browser verification before merge
(I'm a CLI agent — these are the gaps the reviewer + I flagged that only show up in a real browser.)
session-viewer.html— visual collision check.LLM_DAILY_BUDGET_USD=0and confirm the budget meter renders as exhausted + the chat refuses with a 429 message inline.llm_calls.status='cancelled')?Three files, all
node --checksyntax-clean. The forwarder side is fully covered by the existing 67-test suite (unchanged in this PR).🤖 Generated with Claude Code