Skip to content

feat(dashboard): redesign LLM Calls tab with activity visibility#1011

Merged
zbigniewsobiecki merged 2 commits intodevfrom
feat/llm-calls-tab-redesign
Mar 23, 2026
Merged

feat(dashboard): redesign LLM Calls tab with activity visibility#1011
zbigniewsobiecki merged 2 commits intodevfrom
feat/llm-calls-tab-redesign

Conversation

@zbigniewsobiecki
Copy link
Copy Markdown
Member

Summary

  • Parser layer: New parseLlmResponse utility normalizes all four engine formats (Claude Code/OpenCode JSON arrays, Codex, LLMist !!!GADGET_START markup, raw text fallback) into a canonical { blocks[], toolNames[], textPreview }. Extracted to src/utils/llmResponseParser.ts (backend) + web/src/lib/llm-response-parser.ts (frontend twin, kept in sync via comment). Tool input summaries extracted with consistent 100-char truncation.
  • API: listLlmCalls runs the parser server-side and returns toolNames + textPreview per call. Raw response payloads are not forwarded to the client.
  • List view: Activity column with colored tool-name badges (sky=read, amber=bash, emerald=write, violet=web/agent) + ×N repeat counts + truncated text preview. Summary stat cards, inter-call Δ Time column, keyboard-accessible rows, isError guard.
  • Detail view: Structured blocks (text, tool_use with input summary, collapsible thinking). Lazy raw JSON toggle, typed metadata bar, isError guard.
  • Code quality: getToolStyle extracted to shared tool-style.ts; buildMetaItems extracted to reduce component complexity; all parser helper functions lifted to module scope; Fragment key fixes; noArrayIndexKey fixes; all biome complexity violations resolved.

Test plan

  • New tests/unit/utils/llmResponseParser.test.ts — all five format branches (Claude Code, Codex, LLMist, fallback, null/empty) + edge cases (dedup, truncation, multi-line args, unknown blocks)
  • Updated tests/unit/api/routers/runs.test.ts — new test verifies toolNames/textPreview extraction from a real Claude Code payload
  • npm run lint — clean (0 errors)
  • npm run typecheck + cd web && npx tsc --noEmit — clean
  • npm run test:unit — 6415 tests pass
  • Open a Claude Code run in the dashboard → Activity column shows tool badges with ×N counts
  • Open an LLMist run → tool badges + inputSummary populate correctly in expanded view
  • DevTools console → no React key warnings

🤖 Generated with Claude Code

Add a rich Activity column to the LLM Calls table so users can see
what each call was doing at a glance — without expanding every row.

**Parser layer (new)**
- Add `src/utils/llmResponseParser.ts` and frontend twin
  `web/src/lib/llm-response-parser.ts` that normalize all four engine
  response formats (Claude Code/OpenCode JSON arrays, Codex JSON object,
  LLMist gadget markup, raw text fallback) into a canonical
  `ParsedLlmResponse` with `blocks[]`, `toolNames[]`, and `textPreview`.
- `toolNames` carries one entry per invocation (NOT deduplicated) so
  ×N badge counts reflect actual call frequency.
- `summarizeInput` extracts human-readable summaries for well-known tools
  (Read/Write/Edit → file_path, Bash → command, Glob/Grep → pattern, etc.)
  with consistent 100-char truncation.
- Internal helpers (`flushGadgetArg`, `finalizeGadget`, `handleGadgetStart`,
  `processLlmistLine`, `processClaudeBlock`) extracted to module scope so
  each function stays under the cognitive complexity limit.

**API layer**
- `listLlmCallsMeta` now selects `response` alongside token/cost metadata.
- `listLlmCalls` router runs the parser server-side and returns `toolNames`
  + `textPreview` per call; raw `response` payloads are NOT forwarded to
  the client.

**UI — list view**
- New Activity column: colored tool-name badges (sky=read, amber=bash,
  emerald=write, violet=web/agent) with ×N counts + truncated text preview.
- `getToolStyle` extracted to `web/src/lib/tool-style.ts` (was duplicated
  in two components).
- Inter-call Δ Time column computed from `createdAt` timestamps.
- Summary stat cards (Total Calls, Input Tokens, Output Tokens, Cached %).
- Row expansion uses `<Fragment key>` to avoid React key warnings.
- Keyboard-accessible rows (`tabIndex={0}`, Enter/Space toggles).
- `isError` guard added alongside the existing `isLoading` guard.

**UI — detail view**
- Structured blocks view: text (muted bg), tool_use (colored badge +
  monospace inputSummary), thinking (collapsible `<details>`).
- "Raw" / "Structured" toggle; raw JSON parse is lazy (only runs when
  the pane is shown).
- Metadata bar with model (font-mono), time, tokens, cached, cost.
- `buildMetaItems` extracted to reduce component complexity; `MetaItem`
  type replaces fragile string-identity check for `font-mono`.
- `isError` guard added.

**Tests**
- New `tests/unit/utils/llmResponseParser.test.ts` covering all five
  format branches (Claude Code, Codex, LLMist, fallback, empty/null)
  plus edge cases (dedup, truncation, multi-line args, unknown blocks).
- New router test verifies `toolNames` and `textPreview` are extracted
  from a real Claude Code response payload, not just from `null` responses.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 23, 2026

Codecov Report

❌ Patch coverage is 89.90826% with 22 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/utils/llmResponseParser.ts 89.34% 21 Missing ⚠️
src/api/routers/runs.ts 95.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

The test asserted response was excluded from listLlmCallsMeta, but the
router now needs response to extract toolNames/textPreview server-side.
Update the test to reflect the new contract: request is still excluded,
response is now included.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@zbigniewsobiecki zbigniewsobiecki merged commit 0403207 into dev Mar 23, 2026
8 checks passed
@zbigniewsobiecki zbigniewsobiecki deleted the feat/llm-calls-tab-redesign branch March 23, 2026 20:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant