Skip to content

feat(studio): coding agent chat polish - #592

Merged
dmariali merged 3 commits into
mainfrom
coding-agent-chat-polish
Jul 7, 2026
Merged

feat(studio): coding agent chat polish#592
dmariali merged 3 commits into
mainfrom
coding-agent-chat-polish

Conversation

@dmariali

@dmariali dmariali commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Session history items can now display concise, model-generated titles (instead of relying only on the original first prompt).
  • Bug Fixes
    • Assistant chat rendering is more consistent: whitespace-only text won’t create empty surfaces, and mixed text + tool-call streamed messages render cleanly (including correct running/skeleton behavior).
    • When collapsing Studio message history, richer summary content (like markdown tables) and tool-call ordering are preserved, and the session title is included.
  • UI/Styling
    • Removed the special “running” styling/animation for certain tool-call elements.
  • Tests
    • Updated/additional tests for title extraction and the new rendering expectations.

Signed-off-by: Danielle Ali <44468613+dmariali@users.noreply.github.com>
@dmariali
dmariali requested review from a team as code owners July 7, 2026 18:41
@github-actions github-actions Bot added the feat label Jul 7, 2026
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: c29e53a9-f693-4c84-b846-7c9e752234a8

📥 Commits

Reviewing files that changed from the base of the PR and between c0ebbc1 and d989f82.

📒 Files selected for processing (2)
  • web/packages/common/src/components/AssistantChat/AssistantChatMessageContent.tsx
  • web/packages/common/src/components/AssistantChat/index.test.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • web/packages/common/src/components/AssistantChat/AssistantChatMessageContent.tsx
  • web/packages/common/src/components/AssistantChat/index.test.tsx

📝 Walkthrough

Walkthrough

Adds session titles end-to-end, updates assistant message surface rendering, removes running-state tool-call styling, and splits Studio summary output into detail and final parts.

Changes

Session Title Feature

Layer / File(s) Summary
Backend title extraction and API exposure
services/studio/src/nmp/studio/coding_agents.py, services/studio/tests/unit/test_coding_agents.py
Adds title fields, parses title: from Studio summary blocks, stores it in history summaries, returns it in history listings, and updates prompt/test expectations.
Types and API parsing
web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/types.ts, .../api.ts, .../api.test.ts
Adds optional title to ClaudeCodeHistorySession and parses it from history-session responses.
Title derivation helpers
.../historyPanel/helpers.ts, .../historyPanel/helpers.test.ts
Adds getHistorySessionTitle fallback logic for explicit, prompt-derived, and artifact-derived titles.
History panel button rendering
.../historyPanel/HistorySessionButton.tsx, .../ClaudeCodeHistoryPanel.test.tsx
Renders the derived session title and builds tooltip text from timestamp plus trimmed prompt.

Assistant Message Surface Rendering

Layer / File(s) Summary
Content surface prop
web/packages/common/src/components/AssistantChat/AssistantChatMessageContent.tsx
Adds contentSurfaceClassName, skips whitespace-only text, and optionally wraps text/image parts in a surface div.
Renderable content check and wiring
web/packages/common/src/components/AssistantChat/AssistantMessage.tsx, .../index.test.tsx
Switches to renderable-content detection, passes the surface class prop, and updates assistant rendering tests for streaming and running states.

Running-State Styling Removal

Layer / File(s) Summary
CSS and component prop cleanup
web/packages/studio/src/index.css, .../ClaudeCodeToolCallPart.tsx, .../FileChangeToolCallCard.tsx, .../SubtleToolCallRow.tsx, .../toolCall/constants.ts, related tests
Removes claude-code-tool-call-running styling and isRunning/RUNNING_TOOL_CALL_CLASS usage from tool-call rendering and its tests.

Studio Summary Partitioning

Layer / File(s) Summary
Detail/final part split
web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/toolParts.ts, .../toolParts.test.ts
Adds finalParts to StudioSummaryBlock, recognizes title fields, partitions summary parts into detail and final sets, and appends final parts to completed output.

Possibly related PRs

Suggested reviewers: htolentino-nvidia

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is broad, but it is clearly related to the coding agent chat UI and polish changes in this PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch coding-agent-chat-polish

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/toolParts.ts (1)

199-218: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Wire title through or drop it from the parser

title is accepted by StudioSummaryField and matched by the regex, but getStudioSummaryFields never returns it. That silently discards the parsed value; either expose it from this helper or remove it from the matcher/type.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/toolParts.ts`
around lines 199 - 218, The `getStudioSummaryFields` parser currently accepts
and matches `title` via `StudioSummaryField` and the regex, but then drops it by
never returning it. Update the helper in `toolParts.ts` to either include
`title` in the returned object using the existing parsed `fields.title`, or
remove `title` from both `StudioSummaryField` and the matcher if it is not meant
to be supported, so the parser behavior stays consistent.
♻️ Duplicate comments (1)
web/packages/common/src/components/AssistantChat/AssistantMessage.tsx (1)

32-34: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Message-level gate doesn't prevent per-part empty surfaces.

hasRenderableContent only decides whether to render AssistantChatMessageContent at all; it doesn't stop individual empty text parts inside a multi-part message from being wrapped in ASSISTANT_MESSAGE_SURFACE_CLASS by the Text renderer (see companion file). Root-cause fix belongs in AssistantChatMessageContent.tsx's Text closure.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/packages/common/src/components/AssistantChat/AssistantMessage.tsx` around
lines 32 - 34, The current message-level check in AssistantMessage only gates
the whole AssistantChatMessageContent, but empty text parts can still be wrapped
by the Text renderer inside AssistantChatMessageContent.tsx. Move the fix into
the Text closure there by skipping rendering for text parts whose trimmed
content is empty, so only non-empty text parts get
ASSISTANT_MESSAGE_SURFACE_CLASS while non-text parts continue to render
normally.
🧹 Nitpick comments (4)
web/packages/common/src/components/AssistantChat/AssistantChatMessageContent.tsx (1)

19-46: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicate wrap logic between Text and Image.

Both renderers repeat the same contentSurfaceClassName ? <div>...</div> : content pattern. Extract a small helper (e.g., wrapInSurface(content, className)) to avoid drift.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@web/packages/common/src/components/AssistantChat/AssistantChatMessageContent.tsx`
around lines 19 - 46, The Text and Image renderers in
AssistantChatMessageContent both duplicate the same contentSurfaceClassName
wrapping logic, so extract a shared helper to keep behavior consistent and avoid
drift. Create a small reusable wrapper function near MessagePrimitive.Parts (for
example, one that takes the rendered content and contentSurfaceClassName) and
use it in both the Text and Image branches so they both delegate to the same
surface-wrapping path.
web/packages/common/src/components/AssistantChat/index.test.tsx (1)

300-341: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add coverage for mixed empty/non-empty text parts.

No test exercises a message with an empty text part alongside a non-empty part or tool-call — the scenario where the empty-surface bug (flagged in AssistantChatMessageContent.tsx) would manifest.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/packages/common/src/components/AssistantChat/index.test.tsx` around lines
300 - 341, Add a test case in AssistantChat index tests that covers a mixed
assistant message with an empty text part plus a non-empty text part and/or a
tool-call, since the current coverage only checks fully populated text segments.
Update the AssistantChatMessageContent rendering expectations to verify that
empty text parts do not produce an empty message surface, while adjacent
non-empty parts and tool-call content still render correctly; use the existing
StaticAssistantChatThread, assistant-chat-message-surface, and
assistant-chat-tool-pill assertions as the locating points.
web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/historyPanel/helpers.ts (1)

139-171: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicated finalize-title logic between getSmartPromptHistoryTitle and getPromptHistoryTitle.

Both apply capitalizeTitle(stripRequestPrefix(...).replace(/[,:;\s-]+$/g, '').trim()) then limitTitleLength. Consider extracting a shared finalizeTitle(text) helper.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/historyPanel/helpers.ts`
around lines 139 - 171, There is duplicated title-finalization logic in
getSmartPromptHistoryTitle and getPromptHistoryTitle. Extract the shared
stripRequestPrefix/trim/trailing-punctuation/capitalizeTitle/limitTitleLength
flow into a reusable helper such as finalizeTitle, then have both functions call
it so the formatting behavior stays consistent in helpers.ts.
web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/toolParts.ts (1)

391-434: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Table extraction ignores fenced code blocks.

extractMarkdownTableParts scans raw lines for table-shaped pipe/dash patterns without tracking ``` fences. Pipe/dash content inside a code fence (e.g. an ASCII table or CSV sample shown as code) would be misdetected as a real table and yanked out into finalParts, breaking the code block's formatting.

♻️ Proposed fix: skip lines inside code fences
 const extractMarkdownTableParts = (
   text: string
 ): {
   readonly remainingText: string;
   readonly tableParts: readonly ThreadAssistantMessagePart[];
 } => {
   const lines = text.split('\n');
   const tableLines = new Set<number>();
   const tableParts: ThreadAssistantMessagePart[] = [];
+  let inCodeFence = false;

   for (let index = 1; index < lines.length; index += 1) {
+    if (/^\s*```/.test(lines[index - 1]!)) inCodeFence = !inCodeFence;
+    if (inCodeFence) continue;
     if (!MARKDOWN_TABLE_DELIMITER_ROW.test(lines[index]!) || !lines[index - 1]!.includes('|')) {
       continue;
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/toolParts.ts`
around lines 391 - 434, extractMarkdownTableParts currently detects markdown
tables from raw lines without accounting for fenced code blocks, so pipe/dash
patterns inside code samples can be pulled out incorrectly. Update this helper
to track whether the scan is inside a ``` fence while iterating lines, and skip
table detection and table line collection whenever inCodeFence is true. Keep the
existing table parsing behavior for real markdown tables outside fences, and
preserve the current remainingText/tableParts handling in
ClaudeCodeChatRoute/toolParts.ts.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@web/packages/common/src/components/AssistantChat/AssistantChatMessageContent.tsx`:
- Around line 21-30: The Text renderer in AssistantChatMessageContent should
skip whitespace-only parts before adding the content surface wrapper. Update the
Text branch in AssistantChatMessageContent so it checks text.trim() and returns
the raw content (or nothing) when the text is blank, while still using
MessageContent and the contentSurfaceClassName wrapper for real text.

---

Outside diff comments:
In `@web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/toolParts.ts`:
- Around line 199-218: The `getStudioSummaryFields` parser currently accepts and
matches `title` via `StudioSummaryField` and the regex, but then drops it by
never returning it. Update the helper in `toolParts.ts` to either include
`title` in the returned object using the existing parsed `fields.title`, or
remove `title` from both `StudioSummaryField` and the matcher if it is not meant
to be supported, so the parser behavior stays consistent.

---

Duplicate comments:
In `@web/packages/common/src/components/AssistantChat/AssistantMessage.tsx`:
- Around line 32-34: The current message-level check in AssistantMessage only
gates the whole AssistantChatMessageContent, but empty text parts can still be
wrapped by the Text renderer inside AssistantChatMessageContent.tsx. Move the
fix into the Text closure there by skipping rendering for text parts whose
trimmed content is empty, so only non-empty text parts get
ASSISTANT_MESSAGE_SURFACE_CLASS while non-text parts continue to render
normally.

---

Nitpick comments:
In
`@web/packages/common/src/components/AssistantChat/AssistantChatMessageContent.tsx`:
- Around line 19-46: The Text and Image renderers in AssistantChatMessageContent
both duplicate the same contentSurfaceClassName wrapping logic, so extract a
shared helper to keep behavior consistent and avoid drift. Create a small
reusable wrapper function near MessagePrimitive.Parts (for example, one that
takes the rendered content and contentSurfaceClassName) and use it in both the
Text and Image branches so they both delegate to the same surface-wrapping path.

In `@web/packages/common/src/components/AssistantChat/index.test.tsx`:
- Around line 300-341: Add a test case in AssistantChat index tests that covers
a mixed assistant message with an empty text part plus a non-empty text part
and/or a tool-call, since the current coverage only checks fully populated text
segments. Update the AssistantChatMessageContent rendering expectations to
verify that empty text parts do not produce an empty message surface, while
adjacent non-empty parts and tool-call content still render correctly; use the
existing StaticAssistantChatThread, assistant-chat-message-surface, and
assistant-chat-tool-pill assertions as the locating points.

In
`@web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/historyPanel/helpers.ts`:
- Around line 139-171: There is duplicated title-finalization logic in
getSmartPromptHistoryTitle and getPromptHistoryTitle. Extract the shared
stripRequestPrefix/trim/trailing-punctuation/capitalizeTitle/limitTitleLength
flow into a reusable helper such as finalizeTitle, then have both functions call
it so the formatting behavior stays consistent in helpers.ts.

In `@web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/toolParts.ts`:
- Around line 391-434: extractMarkdownTableParts currently detects markdown
tables from raw lines without accounting for fenced code blocks, so pipe/dash
patterns inside code samples can be pulled out incorrectly. Update this helper
to track whether the scan is inside a ``` fence while iterating lines, and skip
table detection and table line collection whenever inCodeFence is true. Keep the
existing table parsing behavior for real markdown tables outside fences, and
preserve the current remainingText/tableParts handling in
ClaudeCodeChatRoute/toolParts.ts.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: e3cf1146-1fb3-4ca7-b209-bf9b48064c8e

📥 Commits

Reviewing files that changed from the base of the PR and between 8765450 and c0ebbc1.

📒 Files selected for processing (20)
  • services/studio/src/nmp/studio/coding_agents.py
  • services/studio/tests/unit/test_coding_agents.py
  • web/packages/common/src/components/AssistantChat/AssistantChatMessageContent.tsx
  • web/packages/common/src/components/AssistantChat/AssistantMessage.tsx
  • web/packages/common/src/components/AssistantChat/index.test.tsx
  • web/packages/studio/src/index.css
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/ClaudeCodeHistoryPanel.test.tsx
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/ClaudeCodeToolCallPart.test.tsx
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/ClaudeCodeToolCallPart.tsx
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/api.test.ts
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/api.ts
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/historyPanel/HistorySessionButton.tsx
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/historyPanel/helpers.test.ts
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/historyPanel/helpers.ts
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/toolCall/FileChangeToolCallCard.tsx
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/toolCall/SubtleToolCallRow.tsx
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/toolCall/constants.ts
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/toolParts.test.ts
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/toolParts.ts
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/types.ts
💤 Files with no reviewable changes (2)
  • web/packages/studio/src/index.css
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/toolCall/constants.ts

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 23273/30443 76.4% 61.2%
Integration Tests 13617/29123 46.8% 20.0%

Signed-off-by: Danielle Ali <44468613+dmariali@users.noreply.github.com>

@htolentino-nvidia htolentino-nvidia left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ship it!

@dmariali
dmariali added this pull request to the merge queue Jul 7, 2026
Merged via the queue into main with commit 0d5ad27 Jul 7, 2026
55 checks passed
@dmariali
dmariali deleted the coding-agent-chat-polish branch July 7, 2026 20:36
arpitsardhana pushed a commit that referenced this pull request Jul 9, 2026
* feat(studio): coding agent chat polish

Signed-off-by: Danielle Ali <44468613+dmariali@users.noreply.github.com>

* hide empty text box

Signed-off-by: Danielle Ali <44468613+dmariali@users.noreply.github.com>

---------

Signed-off-by: Danielle Ali <44468613+dmariali@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants