Skip to content

fix: rewrite cached system prompt model identity to match requested model#14

Merged
dotCipher merged 1 commit intodotCipher:mainfrom
BNasraoui:fix/model-identity-rewrite
Apr 23, 2026
Merged

fix: rewrite cached system prompt model identity to match requested model#14
dotCipher merged 1 commit intodotCipher:mainfrom
BNasraoui:fix/model-identity-rewrite

Conversation

@BNasraoui
Copy link
Copy Markdown
Contributor

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.model on the outbound request, without changing the rest of the prompt (so Claude Code traffic classification remains intact).

Approach

  • New helper deriveModelDisplayName(modelId) parses the claude-{family}-{major}-{minor}[-{date}] convention and renders Opus 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.
  • New helper rewriteSystemBlocksForModel(blocks, modelId) rewrites the "You are powered by the model named X. The exact model ID is Y." line in each text block.
  • Injection site (src/index.ts:641-650) now passes the cached prompt through rewriteSystemBlocksForModel before 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:

  • deriveModelDisplayName on claude-opus-4-7, claude-sonnet-4-6, dated claude-haiku-4-5-20251001, and non-matching IDs
  • rewriteSystemBlocksForModel identity rewrite, no-op when model is undefined, dated variant handling, non-text blocks left untouched

89/89 tests pass (npm test).

End-to-end verification:

$ opencode run --model anthropic/claude-opus-4-7 "What is your exact model ID? Reply with ONLY the model ID."
claude-opus-4-7

$ opencode run --model anthropic/claude-haiku-4-5-20251001 "What is your exact model ID? Reply with ONLY the model ID."
claude-haiku-4-5-20251001

Before this fix both of those returned claude-sonnet-4-6.

…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)
@dotCipher dotCipher force-pushed the fix/model-identity-rewrite branch from 057169a to af3b4bb Compare April 23, 2026 19:04
Copy link
Copy Markdown
Owner

@dotCipher dotCipher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@dotCipher dotCipher merged commit 6911411 into dotCipher:main Apr 23, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cached system prompt always tells model it is Sonnet 4.6, regardless of selected model

2 participants