Repository navigation
Conversation
8a5fb34 to
4101e4a
Compare
There was a problem hiding this comment.
The fix looks correct to me and I found nothing blocking. I ran the two new tests against the base: both fail there with StepFailedError, and the session.retry hook is never called. With this PR, all 245 tests in session-runner.test.ts pass. Type-checking packages/core with tsc -b tsconfig.tests.json is clean. I couldn't get an end-to-end TUI check working, because the simulated model's first response went to the session title.
I also checked the paths around the change. Without a hook, behaviour is unchanged: the proposal stays retry: false and the content-filter failure is still recorded and reported once, as before. If a hook retries before any output, the step returns before step.failed is published. If a hook continues after partial output, the existing Continue path is used.
Public API: no signatures change. One behaviour change for plugins: the session.retry hook now also fires for content-filter finishes, with error type provider.content-filter and a default decision of retry: false. This is backwards compatible, but a hook that sets retry: true for every error will now also retry refusals.
Related: #60586
There was a problem hiding this comment.
The new commit only re-wraps lines in step.ts; the behaviour is unchanged. I re-ran session-runner.test.ts (245 pass) and the packages/core type check (clean). The public API impact is the same as before: the session.retry hook now also fires for content-filter finishes, with a default decision of retry: false. This is backwards compatible. I have no new concerns.
Offer content-filter finishes to retry hooks as content-policy failures while preserving the default terminal behavior. Reuse the existing retry or continuation path when a hook overrides the decision.
4101e4a to
41905e2
Compare
There was a problem hiding this comment.
The new commit only renames the commit message and doesn't change any code, so my previous review still holds and I have no new concerns. As before, the session.retry hook now also fires for content-filter finishes, with a default decision of retry: false. This is backwards compatible.
GiuseppeBellamacina
left a comment
There was a problem hiding this comment.
Question on step.ts: the content-filter failure is rebuilt as a ContentPolicyError carrying only the message, and the retry path is gated on !recorded.outputStarted. Does outputStarted cover tool calls that already ran before the content-filter finish? If not, a hook-driven retry could run those tools again.
|
@GiuseppeBellamacina yep, that's covered. |
|
@rekram1-node you added the |
|
60836
Sent from Outlook for Android<https://aka.ms/AAb9ysg>
…________________________________
From: Raxxoor ***@***.***>
Sent: Monday, 02 November 2026 00:45:23
To: anomalyco/opencode ***@***.***>
Cc: Subscribed ***@***.***>
Subject: Re: [anomalyco/opencode] fix(core): let retry hooks handle content-filter finishes (PR #60836)
[https://avatars.githubusercontent.com/u/7317522?s=20&v=4]dhaern left a comment (anomalyco/opencode#60836)<#60836 (comment)>
@rekram1-node<https://github.com/rekram1-node> you added the session.retry hook in #45999<#45999>, could you take a look?
—
Reply to this email directly, view it on GitHub<#60836?email_source=notifications&email_token=BVRSBAGPXBHWKHB3MN3TF535W6VHHA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTMNJWGQZDSNJYHE3KM4TFMFZW63VKON2WE43DOJUWEZLEUVSXMZLOOSWGM33PORSXEX3DNRUWG2Y#issuecomment-6564295896>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/BVRSBAA5THAX4B5PRVH4SGD5W6VHHAVCNFSNUABFKJSXA33TNF2G64TZHM4TONJXGM2DGMJZHNEXG43VMU5TMMJTGI2DENZQGY2KC5QC>.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS<https://github.com/notifications/mobile/ios/BVRSBAB5LBNYVELFHQNATH35W6VHHA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTMNJWGQZDSNJYHE3KM4TFMFZW63VKON2WE43DOJUWEZLEUVSXMZLOOSVGM33PORSXEX3JN5ZQ> and Android<https://github.com/notifications/mobile/android/BVRSBAFGJ3L3STWYUPTXJGD5W6VHHA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTMNJWGQZDSNJYHE3KM4TFMFZW63VKON2WE43DOJUWEZLEUVSXMZLOOSXGM33PORSXEX3BNZSHE33JMQ>. Download it today!
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
…ry-hook # Conflicts: # packages/core/src/session/runner/step.ts
There was a problem hiding this comment.
The new commit only merges dev into the branch; the fix is unchanged and still applies cleanly after the reworked overflow handling. With the merge, session-runner.test.ts passes (246 tests), including the compaction content-filter test added on dev, and the packages/core type check is clean. The public API impact is the same as before: the session.retry hook now also fires for content-filter finishes, with a default decision of retry: false. This is backwards compatible. I have no new concerns.
|
Thanks for your explanation.
…On Mon, Nov 2, 2026, 2:05 AM opencodejr[bot] ***@***.***> wrote:
***@***.***[bot]* commented on this pull request.
The new commit only merges dev into the branch; the fix is unchanged and
still applies cleanly after the reworked overflow handling. With the merge,
session-runner.test.ts passes (246 tests), including the compaction
content-filter test added on dev, and the packages/core type check is
clean. The public API impact is the same as before: the session.retry
hook now also fires for content-filter finishes, with a default decision
of retry: false. This is backwards compatible. I have no new concerns.
—
Reply to this email directly, view it on GitHub
<#60836?email_source=notifications&email_token=BVRSBAG6AWF7A5FXXSLDP5L5W66TPA5CNFSNUABKM5UWIORPF5TWS5BNNB2WEL2QOVWGYUTFOF2WK43UKJSXM2LFO4XTKNZTGA3TAMJSGYZ2M4TFMFZW63VHMNXW23LFNZ2KKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#pullrequestreview-5730701263>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/BVRSBAC5FVMPIVLWSD3FDUD5W66TPAVCNFSNUABFKJSXA33TNF2G64TZHM4TONJXGM2DGMJZHNEXG43VMU5TMMJTGI2DENZQGY2KC5QC>
.
Triage notifications, keep track of coding agent tasks and review pull
requests on the go with GitHub Mobile for iOS
<https://github.com/notifications/mobile/ios/BVRSBAFY7E7UH7VJQWEM7ST5W66TPA5CNFSNUABKM5UWIORPF5TWS5BNNB2WEL2QOVWGYUTFOF2WK43UKJSXM2LFO4XTKNZTGA3TAMJSGYZ2M4TFMFZW63VHMNXW23LFNZ2KKZLWMVXHJKTGN5XXIZLSL5UW64Y>
and Android
<https://github.com/notifications/mobile/android/BVRSBAFQOBXGKI4ABO5GHK35W66TPA5CNFSNUABKM5UWIORPF5TWS5BNNB2WEL2QOVWGYUTFOF2WK43UKJSXM2LFO4XTKNZTGA3TAMJSGYZ2M4TFMFZW63VHMNXW23LFNZ2KKZLWMVXHJLTGN5XXIZLSL5QW4ZDSN5UWI>.
Download it today!
You are receiving this because you commented.Message ID:
***@***.***>
|
|
Yeah good idea |
Issue for this PR
Closes #60822
Type of change
What does this PR do?
A step that ends with
finish: "content-filter"setsproviderFailed, sostep.tsnever buildsllmErrorand thesession.retryhook is skipped. The same refusal sent back as an HTTPContentPolicyerror does reach the hook, which is why a fallback plugin can recover one but not the other, and why a refused subagent job ends aserror. In v1 both cases ended up on the same path (prompt.tsturned a content-filter finish intoContentFilterErrorand publishedSession.Event.Error, like any API error), so plugins could treat them the same way.This isn't tied to one provider.
content-filteris the normalized finish the protocols already produce for Anthropicrefusal, OpenAI Chat and Responsescontent_filter, Gemini safety blocks, Bedrock guardrails and Mistral, so all of them go through the same branch. The change wraps that finish in aContentPolicyErrorand sends it through the retry decision like other provider failures. The hook receives the sameprovider.content-filtererror thatstep.failedcarries today.ContentPolicyisn't retryable, so the proposal staysretry: falseand nothing changes without a hook. If a hook switches the model and returnsretry: true, the runner reuses the existingRetryoutcome when no output was produced, orContinuewhen part of the answer was already streamed, the same way it handles a mid-stream rate limit. It's 10 lines instep.ts.How did you verify your code works?
Added two tests in
session-runner.test.ts, modeled on "retries an unknown finish before output" and "continues after a mid-stream rate limit": a hook turns a content-filter finish into a retry before output and into a continuation after partial output. Both fail without the change. The existing content-filter tests pass unchanged,bun test test/session-runner.test.tsis green andbun run typecheckinpackages/coreis clean.I also ran it on v2.2.4 with the patch cherry-picked and a local OpenAI-compatible stub returning
finish_reason: "content_filter", using oh-my-opencode-slim's retry hook. A root session and a background subagent both switched model and finished on the fallback, and the parent gotstate="completed"instead ofstate="error". With no fallback configured the step still fails as before.Checklist
Added by the opencode bot (AI-generated).
Related: #60586
Public API: session.retry plugin hook now also fires for content-filter finishes (default retry: false; backwards compatible)