fix: rewrite cached system prompt model identity to match requested model#14
Merged
dotCipher merged 1 commit intodotCipher:mainfrom Apr 23, 2026
Merged
Conversation
…odel
The bridge injects a cached Claude Code system prompt on every Anthropic
request so traffic is classified as Claude Code (plan quota) rather than
third-party OAuth (extra usage). The prompt is captured via the validator
script with whatever model was used at capture time — typically
claude-sonnet-4-6.
The prompt contains a self-identity line:
"You are powered by the model named Sonnet 4.6. The exact model ID is
claude-sonnet-4-6."
Without this fix, every request — regardless of the selected model —
receives that line, so Opus 4.7 / Haiku 4.5 / any future model is told
it is Sonnet 4.6. This can bias behavior: response length, tool-use
preferences, and confidence calibration that are tuned per model family.
Fix rewrites just the identity line in-place before injection, using the
`parsed.model` value from the outbound request body. The display name is
derived from the model ID (`claude-opus-4-7` → `Opus 4.7`) instead of a
hardcoded map, so new models don't need plugin updates. Falls back to the
raw model ID when the `claude-{family}-{major}-{minor}` convention does
not match, surfacing naming changes truthfully rather than silently.
Tests cover:
- ID parsing (normal, dated variant, unknown convention)
- Identity rewrite (match, no model, dated variant, non-matching blocks)
057169a to
af3b4bb
Compare
dotCipher
approved these changes
Apr 23, 2026
Owner
dotCipher
left a comment
There was a problem hiding this comment.
Rebased onto current main and re-ran the branch locally. The change is narrowly scoped and the tests are covering the prompt rewrite behavior well.
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.
Summary
Fixes #13.
The cached Claude Code system prompt contains a self-identity line that names the model used when the prompt was captured (typically Sonnet 4.6). Because the bridge injects this prompt on every request regardless of which model the user selected, Opus 4.7 / Haiku 4.5 / any other model ends up being told it is Sonnet 4.6. That can bias response length, tool-use, and confidence calibration that is tuned per model family.
This PR rewrites just the identity lines in the cached prompt to match
parsed.modelon the outbound request, without changing the rest of the prompt (so Claude Code traffic classification remains intact).Approach
deriveModelDisplayName(modelId)parses theclaude-{family}-{major}-{minor}[-{date}]convention and rendersOpus 4.7,Haiku 4.5, etc. Falls back to the raw ID when the convention doesn't match, so future naming changes surface truthfully rather than silently.rewriteSystemBlocksForModel(blocks, modelId)rewrites the"You are powered by the model named X. The exact model ID is Y."line in each text block.src/index.ts:641-650) now passes the cached prompt throughrewriteSystemBlocksForModelbefore prepending the billing header.No hardcoded model list — any current or future
claude-*-{major}-{minor}model works automatically.Test plan
Added 8 unit tests covering:
deriveModelDisplayNameonclaude-opus-4-7,claude-sonnet-4-6, datedclaude-haiku-4-5-20251001, and non-matching IDsrewriteSystemBlocksForModelidentity rewrite, no-op when model is undefined, dated variant handling, non-text blocks left untouched89/89 tests pass (
npm test).End-to-end verification:
Before this fix both of those returned
claude-sonnet-4-6.