feat: surface model content-filter refusals as a blocked chat error - #27118
Merged
ethanndickson merged 2 commits intoJul 15, 2026
Merged
Conversation
Docs preview📖 View docs preview for |
ethanndickson
force-pushed
the
ethan/codagt-611-surface-refusal-errors-instead-of-blank-thinking-state
branch
2 times, most recently
from
July 9, 2026 08:33
81beeb8 to
6b41de7
Compare
ethanndickson
marked this pull request as ready for review
July 9, 2026 08:33
ethanndickson
force-pushed
the
ethan/codagt-611-surface-refusal-errors-instead-of-blank-thinking-state
branch
from
July 13, 2026 07:17
6b41de7 to
01cc89f
Compare
When a provider's real-time safety classifiers block a response (e.g. Anthropic stop_reason "refusal"), the turn previously ended silently: the fantasy SDK mapped the stop reason to unknown and the empty-content finish looked like a normal stop, leaving the UI stuck on "Thinking" with no output. Bump the fantasy fork to pick up refusal -> FinishReasonContentFilter mapping with stop_details carried as RefusalMetadata (fork change 15, coder/fantasy#41). chatloop now turns an empty content-filter finish into a terminal, non-retryable content_filter classified error, using the provider's explanation as the message and the refusal category as the detail, with a generic per-provider fallback message. The UI renders it as "Response blocked". Partial-content refusals (classifier blocks after some output) still persist the partial text and end the turn normally; surfacing those is a separate product decision. Coder Agents generated.
ethanndickson
force-pushed
the
ethan/codagt-611-surface-refusal-errors-instead-of-blank-thinking-state
branch
from
July 14, 2026 03:15
01cc89f to
69b79f3
Compare
…entFilterError Merge TestContentFilterMessage into TestContentFilterError as a table-driven test. contentFilterError routes through ContentFilterMessage for both the metadata and default-fallback paths, so asserting the classified message covers the verbatim category, default, whitespace, and unknown-provider cases without a separate test.
ibetitsmike
approved these changes
Jul 15, 2026
ethanndickson
deleted the
ethan/codagt-611-surface-refusal-errors-instead-of-blank-thinking-state
branch
July 15, 2026 06:36
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Blocked turns from a provider's content filter (Anthropic's
refusalstop reason with empty content) previously ended silently on the "Thinking" spinner. They now end as a terminalcontent_filtererror that renders as a "Response blocked" message with the provider's category and explanation.Closes CODAGT-611
Follow-ups will involve implementing fallbacks, but this alone is pretty important