Repository navigation
🔐 fix: Skip Reasoning Labels for Encrypted Reasoning #17100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1c26b00
cb8ec47
5da1460
f53984b
79a194d
b2d7c79
e74afd6
a334a99
d68368e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,7 @@ import { | |
| ContentTypes, | ||
| ToolCallTypes, | ||
| imageGenTools, | ||
| isOpaqueReasoning, | ||
| isImageVisionTool, | ||
| hasToolCallPreview, | ||
| getToolCallPreviewRevision, | ||
|
|
@@ -646,6 +647,9 @@ const renderers: PartRenderers = { | |
| if (reasoning.trim() === '' && part.reasoning_unavailable === true) { | ||
| return <ReasoningMarker label={part.reasoning_label} />; | ||
| } | ||
| if (isOpaqueReasoning(reasoning)) { | ||
| return <ReasoningMarker encrypted />; | ||
| } | ||
|
Comment on lines
+650
to
+652
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a THINK part contains readable prose alongside an encrypted provider payload, Useful? React with 👍 / 👎.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in 5da1460. |
||
| return ( | ||
| <Reasoning | ||
| partKeyIndex={getPartKeyIndex(part, partIndex ?? 0)} | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| import React from 'react'; | ||
| import { render, screen } from '@testing-library/react'; | ||
| import { ReasoningMarker } from '../Reasoning'; | ||
|
|
||
| jest.mock('~/hooks', () => ({ | ||
| useLocalize: () => (key: string) => key, | ||
| })); | ||
|
|
||
| jest.mock('../Thinking', () => ({ | ||
| ThinkingLabel: ({ label, title }: { label: string; title?: string }) => ( | ||
| <div data-testid="thinking-label" title={title}> | ||
| {label} | ||
| </div> | ||
| ), | ||
| })); | ||
|
|
||
| describe('ReasoningMarker', () => { | ||
| it('shows the generated label for reasoning this view cannot show', () => { | ||
| render(<ReasoningMarker label="Planning the answer" />); | ||
|
|
||
| const marker = screen.getByTestId('thinking-label'); | ||
| expect(marker).toHaveTextContent('Planning the answer'); | ||
| expect(marker).toHaveAttribute('title', 'com_ui_thoughts_unavailable'); | ||
| }); | ||
|
|
||
| it('shows a neutral encrypted state and ignores any label', () => { | ||
| render(<ReasoningMarker encrypted label="Inspecting an encoded data snapshot" />); | ||
|
|
||
| const marker = screen.getByTestId('thinking-label'); | ||
| expect(marker).toHaveTextContent('com_ui_reasoning_encrypted'); | ||
| expect(marker).toHaveAttribute('title', 'com_ui_reasoning_encrypted_description'); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When encrypted reasoning is streamed in small deltas,
isOpaqueReasoningremains false until the accumulated unbroken run reaches 128 characters, so the first 1–127 ciphertext characters are passed toReasoning, rendered in the live thought panel, and exposed to its copy control before being replaced by the encrypted marker. Defer the undecided payload-alphabet prefix during streaming, rather than rendering it while classification is pending.Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 79a194d. A new
readableReasoning(text, streaming)runs the streaming classifier over the text. While a part is streaming, it withholds a trailing payload-alphabet run longer than a word (32 chars) until the run is classified.Reasoning(when submitting and last),ReasoningCompact(isStreaming) and the live header use it, so the first characters of a streaming payload are never rendered or copyable. A pure prefix renders nothing until it becomes the encrypted marker. Covered inReasoningCompact.test.tsx,LiveParity.test.tsxandreasoning.spec.ts.