fix(agent): surface the real LLM failure cause and hint an unavailable model - #220
Merged
Merged
Conversation
…e model pr-agent's retry_with_fallback_models logs the underlying exception into loguru's `artifact=` field, which the default format never prints, so a failed LLM call reached the run card as nothing but "all fallback models failed". For the local CLI providers this was compounded twice over: codex reports its failures on stdout (turn.failed / error events in the JSONL stream) and leaves stderr empty, while a turn that dies on a tool failure exits 0 with no assistant message at all, which then failed downstream as an unexplained empty prompt. - shim: extract the cause from the codex event stream on a non-zero exit, and raise explicitly when a zero exit carries an empty reply; - shim: emit `@@MEEBOX_LLM_ERROR@@` on stderr, alongside the usage sentinel, so the cause travels past pr-agent's lossy retry log; - main: prefer that sentinel over the generic marker for errorMessage, and classify it into errorHint (currently `model-unavailable`); - renderer: render one localized remedy line under the raw cause, since a local CLI provider's model lives in that CLI's own configuration. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Problem
A review failing on the LLM call itself showed up as nothing but
所有备选模型均调用失败 (Failed to generate prediction with any model). The actual cause never reached the run card, because pr-agent''sretry_with_fallback_modelslogs the underlying exception into loguru''sartifact=field, which the default format does not print.For the local CLI providers this was compounded twice over:
turn.failed/errorevents inside its JSONL stream, with stderr left empty. The shim only read stderr on a non-zero exit, so it raised with an empty reason.load_yamland failed there instead, with no trace of why.Found while diagnosing a real failure: codex was pinned to a model the account no longer had access to (
404 ... The model \x` does not exist or you do not have access to it`), which is precisely the class of failure a user can fix — but only if they are told about it.Changes
turn.failed→ lasterror→ error item), via a new optionalerror_extractorspec key; commands without one keep the stderr fallback.@@MEEBOX_LLM_ERROR@@ {json}on stderr alongside the usage sentinel, so the cause travels past pr-agent''s lossy retry log. Purely additive: the exception still raises and the fallback retry still runs.errorMessage, and classify it into a newerrorHint(currently onlymodel-unavailable).Verification
lint/typecheck/test/buildall pass; four new tests cover the classification, including the negative cases (auth errors, timeouts and empty replies stay unclassified, so no misleading remedy is shown).404 model does not existrun raises with the full cause and emits the sentinel; after switching to an available model the same path succeeds and the usage sentinel is unaffected.🤖 Generated with Claude Code