feat(conversations): Support reasoning/thinking message parts#117401
Conversation
|
🚨 Warning: This pull request contains Frontend and Backend changes! It's discouraged to make changes to Sentry's Frontend and Backend in a single pull request. The Frontend and Backend are not atomically deployed. If the changes are interdependent of each other, they must be separated into two pull requests and be made forward or backwards compatible, such that the Backend or Frontend can be safely deployed independently. Have questions? Please ask in the |
Add support for the OTel-aligned `reasoning` part type in both Python and TypeScript message normalizers. Reasoning content is separated from user-facing text so the Conversations UI can render it in a collapsed, dimmed section. Changes: - ai_message_normalizer.py: Add reasoning_parts bucket and reasoning_text to AIOutputResult - aiMessageNormalizer.ts: Mirror Python changes for reasoning parts - conversationMessages.ts: Extract reasoning into ConversationMessage, exclude from markdown export - messagesPanel.tsx: Add collapsible Thinking section with muted styling Refs TET-2453
d4adeb0 to
588b4c5
Compare
Render the reasoning 'Thinking...' label in muted monospace italic with a trailing collapse caret, and rebuild the section from core layout/text primitives (Button, Flex, Container, Text) instead of styled components. Use the link button variant to drop the hover background and vertically center the caret, and color the caret via the icon's muted variant. Refs TET-2453 Co-Authored-By: Claude <noreply@anthropic.com>
Replace the repeated inline turn objects in the turnsToMessages and mergeEmptyTurns specs with a makeTurn factory so new turn fields (like reasoning) only need a default in one place. Also cover reasoning flowing through to the assistant message. Refs TET-2453 Co-Authored-By: Claude <noreply@anthropic.com>
Merge the three agentName tests and two modelName tests into two attribute-driven cases via an assistantFromAttributes helper, and drop reasoning assertions that were duplicated across the parse, turn, and integration layers. Reasoning is now covered once at the unit (parse) layer, once at the turn layer, and via the markdown-exclusion test. Refs TET-2453 Co-Authored-By: Claude <noreply@anthropic.com>
…-messages-in-product
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 40ab2f1. Configure here.
| duration, | ||
| agentName: agentName || undefined, | ||
| modelName: modelName || undefined, | ||
| reasoning: turn.reasoning || undefined, |
There was a problem hiding this comment.
Reasoning-only turns omit assistant
Medium Severity
turnsToMessages only emits an assistant row when there is user-facing assistantContent or tool calls. A generation span with reasoning but no text and no tools never passes that gate, so parseAssistantContent can return reasoning that never reaches the UI or markdown pipeline.
Reviewed by Cursor Bugbot for commit 40ab2f1. Configure here.
There was a problem hiding this comment.
I'm not sure if we would even want to show said spans.


Adds support for the OTel-aligned
reasoningpart type ({"type": "reasoning", "content": "..."}) so the Conversations UI can show a model's thinking separately from its answer.Both the Python and TypeScript message normalizers now bucket
reasoningparts apart from user-facing text and expose them as a distinctreasoning_text/reasoningTextfield. Reasoning is excluded from the collapsed text output, the conversation listlastOutput, and the "Copy as Markdown" export, so it never leaks into the answer. In the chat view,messagesPanel.tsxrenders a collapsed-by-default "Thinking..." toggle above the assistant content.Given a message with
[{"type": "reasoning", ...}, {"type": "text", ...}], the answer shows only the text while the reasoning lives behind the toggle.Closes TET-2453