Conversation
… is unavailable One-shot commit, PR, branch, and title generation still send the product slug first. A configured custom model is used only when that attempt reports the model itself is unavailable. Content and prompt guardrail failures stay failed. CLI errors expose a bounded category, and the process exit is kept as cause. Refs pingdotgg#12651 Co-authored-by: maco <macodev00@users.noreply.github.com>
Owner
Author
|
Not opening upstream: redo cap exceeded for pingdotgg#12651. |
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
One-shot text generation (commit, PR, branch, and title) uses the product slug when
textGenerationModelSelectionis unset and the stored instance is disabled. For Claude that slug isclaude-haiku-4-5. A backend that refuses that slug, such as an OpenRouter workspace whose guardrails block Anthropic models, fails the spawn even when the Claude instance has a working custom model.The product slug is still the right default when that model works. Selecting a configured custom model in its place would change commit, PR, branch, and title generation for healthy setups.
A content or prompt guardrail failure is a different failure. Retrying it with a custom model would hide the original result.
Change
fallbackTextGenerationProviderstill writes the product text-generation slug. Settings, and the first one-shot attempt, stay on that slug when a custom model is configured.Claude one-shot generation retries once with the instance's first configured custom model only after the product-slug attempt exits non-zero and the CLI output says the model itself is unavailable (
unknown model,model not found,model blocked by guardrail, the OpenRouter "N endpoints out of M" plus "endpoints excluded" pair, and the same class of failure). A bareguardrailmatch does not qualify, so a content or prompt guardrail stays on the original attempt.A successful product-slug attempt is unchanged. An explicit non-product model, an instance with no other custom model, and a non-model failure do not retry.
When the CLI exits non-zero,
TextGenerationError.detailis a bounded category (model_unavailableorcli_failed), the exit code, andapi_statusonly when stdout JSON carries an integer HTTP status from 100 through 599. Stdout and stderr are not copied intodetail. The process exit is retained ascause(Claude CLI process exited with code N) and that message does not include process output. The retry log recordsoperationand the product model. It does not recordcustomModel.Commit, PR, branch, and title generation share
runClaudeJson, so the same rule covers all four.Addresses pingdotgg#12651
Scope and approval
pingdotgg#12651 is an accepted server bug. Julius confirmed the fallback sends
claude-haiku-4-5and does not consult the instance's configured custom model: pingdotgg#12651 (comment)The accepted direction is to keep the cheap product slug when it is available, and not to send it when that slug is what the backend refuses. This PR does the second half only after the product attempt reports the model itself is unavailable, so healthy defaults stay on the product slug.
This replaces the closed approach in pingdotgg#14747. That review required a bounded failure category (with the process exit kept as
cause), nocustomModellog annotation, and a fallback predicate that does not treat everyguardrailstring as a missing model.Verification
From
/workspaceat17fdefbfd, Node v24.13.1, workspacevp1.0.0 (/workspace/node_modules/.binahead ofPATH):Result: 3 files passed, 94 tests passed (3.89s). Coverage includes a healthy product-slug success while a custom model is configured (one spawn, product slug only), a model-blocked
claude-haiku-4-5followed by one retry onz-ai/glm-5.3-flash, a content-guardrail failure that does not retry and whosedetailandcauseomit the CLI payload, a non-model product-slug failure that does not retry, an unavailable product slug with no custom model that reportsmodel_unavailablewithout the CLI text, an explicit non-product model that does not retry, and settings resolution that still returns the Claude product slug when a custom model and a custom thread default are configured.Result: exit 0. The command printed pre-existing effect suggestions in
CodexInstallation.ts,CodexAdapter.test.ts,CodexProvider.ts,GitHubCli.test.ts, andws.ts. None of those files are in this diff.Result: exit 0. The only output was two existing
no-inline-schema-compilewarnings inserverSettings.test.tsaround the pre-existing inline schema helpers, not in this diff.Result: finished on the touched files with no further edits.
Limitations
Linux only. The unavailable product slug is attempted once before the custom model, so a broken fallback pays for one failed CLI spawn. The substitute is the first configured custom model on that Claude instance other than the product slug; a built-in thread default is not used. Codex, Cursor, Grok, OpenCode, and Antigravity still send their product slug and do not retry. The surfaced error is the bounded category, exit code, and optional HTTP status. The raw stdout API sentence is not included, because that text can carry credentials or arbitrary payloads. A live OpenRouter spawn was not run.
UI Changes
None. This only changes server-side model selection and CLI failure reporting for one-shot commit, PR, branch, and title generation.
Grok 4.7, Cursor cloud agent.