fix(anthropic): scope refusal handling to Anthropic - #166
Conversation
🤖 CodeAnt AI — Review Status
|
Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: adaab6a0ab
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| // An Anthropic refusal finish is deterministic - the provider will | ||
| // return the same result for the same request - so it must not enter | ||
| // the retry loop. Content filters remain provider-neutral completions. | ||
| if finish_reason == Some(FinishReason::Refusal) && tool_calls.is_empty() { |
There was a problem hiding this comment.
Stop the orchestration loop on filtered completions
When OpenAI, Google, or Bedrock returns ContentFilter without tool calls, this branch now returns a successful completion, but Orchestrator::run only sets should_yield for FinishReason::Stop or a yielding tool call (crates/forge_app/src/orch.rs:373-381). It therefore appends the empty or partial filtered response and sends another paid model request; with no max_requests_per_turn configured this can continue indefinitely, and otherwise it repeats until the limit interrupt. If content filters are meant to remain successful completions, they also need to be treated as terminal by the orchestrator.
Useful? React with 👍 / 👎.
Code Review SummaryStatus: 2 Issues Found | Recommendation: Approve with notes — confirm the open content-filter termination thread before merge Overview
1. SummaryMaps Anthropic Verified positives:
2. Must FixNone in the changed lines. Assumption stated for transparency: 3. Should Fix — open thread, not duplicated here
4. Consider
Issue Details (click to expand)SUGGESTION
Files Reviewed (3 files)
5. Final RecommendationApprove with notes. Nothing in the diff blocks compilation, tests, or security. Both inline items are non-blocking, but the open content-filter termination question should be answered before merge because it can cost real money in a loop. Reply Fix these issues in Kilo Cloud Previous Review Summaries (3 snapshots, latest commit ecc662e)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit ecc662e)Status: 2 Issues Found | Recommendation: Approve with notes — confirm the open content-filter termination thread before merge Overview
1. SummaryMaps Anthropic Verified positives:
2. Must FixNone in the changed lines. Assumption stated for transparency: 3. Should Fix — open thread, not duplicated here
4. Consider
Issue Details (click to expand)SUGGESTION
Files Reviewed (3 files)
5. Final RecommendationApprove with notes. Nothing in the diff blocks compilation, tests, or security. Both inline items are non-blocking, but the open content-filter termination question should be answered before merge because it can cost real money in a loop. Reply Fix these issues in Kilo Cloud Previous review (commit 5d349e2)Status: No Issues Found | Recommendation: Merge Files Reviewed (3 files)
Previous review (commit adaab6a)Status: No Issues Found | Recommendation: Merge Files Reviewed (3 files)
Reviewed by free · Input: 37.4K · Output: 6.2K · Cached: 298.9K |
9e88217 to
5d349e2
Compare
Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
🏎️ Performance Benchmark ResultsPerformance regression gate: check above for regressions against baseline. |
5d349e2 to
ecc662e
Compare
🏎️ Performance Benchmark ResultsPerformance regression gate: check above for regressions against baseline. |
| /// violated filters. | ||
| #[strum(serialize = "content_filter")] | ||
| ContentFilter, | ||
| /// The Anthropic provider refused to generate a response. |
There was a problem hiding this comment.
SUGGESTION: Doc comment claims Anthropic scope, but this variant is provider-neutral
FinishReason lives in the provider-agnostic forge_domain crate, and Refusal is reachable well beyond Anthropic: every OpenAI-compatible provider parses the raw string through FinishReason::from_str(&s) (crates/forge_app/src/dto/openai/response.rs:345, :356, :421). With the new #[strum(serialize = "refusal")] on the next line, any provider that reports finish_reason: "refusal" (OpenRouter native reasons, Azure, gateways) now short-circuits into the non-retryable crate::Error::Refusal at crates/forge_domain/src/result_stream_ext.rs:265-267. So the PR title's "scope refusal handling to Anthropic" is not what the code does, and a reader relying on this doc will draw the wrong conclusion about which providers can produce it. Keep the doc provider-neutral (rustfmt comment_width = 80 applies).
| /// The Anthropic provider refused to generate a response. | |
| /// The model refused to generate a response (e.g. Anthropic refusal). |
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| ContentFilter, | ||
| /// The Anthropic provider refused to generate a response. | ||
| #[strum(serialize = "refusal")] | ||
| Refusal, |
There was a problem hiding this comment.
SUGGESTION: Adding a variant to this public enum is a source-breaking change for downstream consumers
FinishReason is pub and not #[non_exhaustive], so inserting Refusal breaks any exhaustive match in code that consumes forge_domain as an independent crate. I verified nothing in this workspace matches FinishReason exhaustively today (all call sites use == or from_str), so CI will not fail — but given the polyrepo goal of independently consumable crates, this is a semver-visible API change on a crate still published as 0.1.1 (crates/forge_domain/Cargo.toml:3).
Consider marking the enum #[non_exhaustive] (the idiom is already used at crates/forge_domain/src/node.rs:288) so future finish reasons are additive rather than breaking, and reflect this change in the crate version.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
Co-Authored-By: ForgeCode <noreply@forgecode.dev>
ecc662e to
230c199
Compare
🏎️ Performance Benchmark ResultsPerformance regression gate: check above for regressions against baseline. |
User description
Supersedes
Semantically replays the still-valid provider-scoped portion of #162 onto current v2.13.21-sync main (
cf3a3ef) without rewriting or deleting the original conflicting branch.Resolution
FinishReason::Refusalfor Anthropicstop_reason: refusal.content_filteras a normal completion, including partial-content behavior.Validation
cargo test -q -p forge_app dto::anthropic::response::tests --libcargo test -q -p forge_domain result_stream_ext::tests --libcargo test -q -p forge_domain message::tests --libcargo fmt --check -- crates/forge_app/src/dto/anthropic/response.rs crates/forge_domain/src/message.rs crates/forge_domain/src/result_stream_ext.rsgit diff fork/main..HEAD --checkCodeAnt-AI Description
Distinguish Anthropic refusals from content-filtered completions
What Changed
Impact
✅ Fewer pointless retries for Anthropic refusals✅ Clearer refusal errors✅ Content-filtered completions remain available💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.