opencode-anthropic-fix 0.0.45 → 0.0.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/index.mjs +39 -15
- package/lib/rotation.test.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -44,9 +44,9 @@ The [original plugin](https://github.com/anomalyco/opencode-anthropic-auth) prov
|
|
|
44
44
|
- **Configurable strategies** — sticky, round-robin, or hybrid account selection
|
|
45
45
|
- **Claude Code signature emulation** — full HTTP header, system prompt, beta flag, and metadata mimicry derived from Claude Code's open source code
|
|
46
46
|
- **OAuth endpoint fingerprint parity** — matches the real CLI's bundled axios 1.13.6 HTTP client signature (`Accept`, `User-Agent`, `Content-Type`) on all OAuth token endpoint calls, required since 2026-03-21 server-side enforcement
|
|
47
|
-
- **
|
|
47
|
+
- **Billing header fingerprint parity** — `cc_version` suffix uses the real CLI's 3-char fingerprint hash (SHA-256 of salt + first user message chars + version), `cch` matches the Bun native client attestation placeholder, and `X-Claude-Code-Session-Id` header is sent on all requests
|
|
48
48
|
- **Adaptive thinking for Opus/Sonnet 4.6** — automatically normalizes thinking to `{type: "adaptive"}` for supported models, with `effort-2025-11-24` beta
|
|
49
|
-
- **Upstream-aligned auto betas** — 13+ always-on betas matching Claude Code 2.1.
|
|
49
|
+
- **Upstream-aligned auto betas** — 13+ always-on betas matching Claude Code 2.1.92 (`redact-thinking-2026-02-12` available as opt-in to preserve thinking block visibility)
|
|
50
50
|
- **1M context limit override** — patches `model.limit.context` so OpenCode compacts at the right threshold while `models.dev` catches up
|
|
51
51
|
- **Runtime config + custom betas** — `/anthropic set`, `/anthropic config`, and `/anthropic betas` slash commands for live feature toggling without restarting OpenCode
|
|
52
52
|
- **Files API integration** — upload, list, download, and manage files via `/anthropic files` with endpoint/content-scoped `files-api-2025-04-14` beta injection
|
package/index.mjs
CHANGED
|
@@ -2780,6 +2780,7 @@ export async function AnthropicAuthPlugin({ client, project, directory, worktree
|
|
|
2780
2780
|
claudeCliVersion,
|
|
2781
2781
|
customBetas: config.custom_betas,
|
|
2782
2782
|
strategy: getEffectiveStrategy(),
|
|
2783
|
+
sessionId: signatureSessionId,
|
|
2783
2784
|
},
|
|
2784
2785
|
_adaptiveOverride,
|
|
2785
2786
|
_tokenEconomy,
|
|
@@ -4886,17 +4887,18 @@ process.once("beforeExit", _beforeExitHandler);
|
|
|
4886
4887
|
// Request building helpers (extracted from original fetch interceptor)
|
|
4887
4888
|
// ---------------------------------------------------------------------------
|
|
4888
4889
|
|
|
4889
|
-
const FALLBACK_CLAUDE_CLI_VERSION = "2.1.
|
|
4890
|
+
const FALLBACK_CLAUDE_CLI_VERSION = "2.1.92";
|
|
4890
4891
|
const CLAUDE_CODE_NPM_LATEST_URL = "https://registry.npmjs.org/@anthropic-ai/claude-code/latest";
|
|
4891
|
-
const CLAUDE_CODE_BUILD_TIME = "2026-04-
|
|
4892
|
+
const CLAUDE_CODE_BUILD_TIME = "2026-04-03T23:25:15Z";
|
|
4892
4893
|
|
|
4893
|
-
// The @anthropic-ai/sdk version bundled with Claude Code v2.1.
|
|
4894
|
+
// The @anthropic-ai/sdk version bundled with Claude Code v2.1.92.
|
|
4894
4895
|
// This is distinct from the CLI version and goes in X-Stainless-Package-Version.
|
|
4895
|
-
// Verified by extracting VERSION="0.208.0" from the bundled cli.js of all versions .80-.
|
|
4896
|
+
// Verified by extracting VERSION="0.208.0" from the bundled cli.js of all versions .80-.92.
|
|
4896
4897
|
const ANTHROPIC_SDK_VERSION = "0.208.0";
|
|
4897
4898
|
|
|
4898
4899
|
// Map of CLI version → bundled SDK version (update when CLI version changes)
|
|
4899
4900
|
const CLI_TO_SDK_VERSION = new Map([
|
|
4901
|
+
["2.1.92", "0.208.0"],
|
|
4900
4902
|
["2.1.91", "0.208.0"],
|
|
4901
4903
|
["2.1.90", "0.208.0"],
|
|
4902
4904
|
["2.1.89", "0.208.0"],
|
|
@@ -5552,19 +5554,34 @@ function buildRequestMetadata(input) {
|
|
|
5552
5554
|
|
|
5553
5555
|
/**
|
|
5554
5556
|
* Build the billing header block for Claude Code system prompt injection.
|
|
5555
|
-
* Claude Code v2.1.
|
|
5557
|
+
* Claude Code v2.1.92: cc_version includes 3-char fingerprint hash (not model ID).
|
|
5558
|
+
* cch is a static "00000" placeholder for Bun native client attestation.
|
|
5559
|
+
*
|
|
5560
|
+
* Real CC (system.ts:78): version = `${MACRO.VERSION}.${fingerprint}`
|
|
5561
|
+
* Real CC (system.ts:82): cch = feature('NATIVE_CLIENT_ATTESTATION') ? ' cch=00000;' : ''
|
|
5556
5562
|
*
|
|
5557
|
-
* @param {string} version - CLI version (e.g., "2.1.
|
|
5558
|
-
* @param {string} [
|
|
5559
|
-
* @param {string} [
|
|
5563
|
+
* @param {string} version - CLI version (e.g., "2.1.92")
|
|
5564
|
+
* @param {string} [firstUserMessage] - First user message text for fingerprint computation
|
|
5565
|
+
* @param {string} [provider] - API provider ("anthropic" | "bedrock" | "vertex" | "foundry")
|
|
5560
5566
|
* @returns {string}
|
|
5561
5567
|
*/
|
|
5562
|
-
function buildAnthropicBillingHeader(version,
|
|
5568
|
+
function buildAnthropicBillingHeader(version, firstUserMessage, provider) {
|
|
5563
5569
|
if (isFalsyEnv(process.env.CLAUDE_CODE_ATTRIBUTION_HEADER)) return "";
|
|
5564
5570
|
const entrypoint = process.env.CLAUDE_CODE_ENTRYPOINT || "unknown";
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5571
|
+
// Fix #1: cc_version suffix is the 3-char fingerprint hash, NOT the model ID.
|
|
5572
|
+
// computeBillingCacheHash() computes SHA256(salt + msg[4]+msg[7]+msg[20] + version)[:3]
|
|
5573
|
+
// which matches computeFingerprint() in the real CC source (utils/fingerprint.ts).
|
|
5574
|
+
// Always call the hash function — even for empty messages the real CC computes
|
|
5575
|
+
// the hash from "000" chars (indices 4,7,20 all missing → fallback "0").
|
|
5576
|
+
const fingerprint = computeBillingCacheHash(firstUserMessage || "", version);
|
|
5577
|
+
const ccVersion = `${version}.${fingerprint}`;
|
|
5578
|
+
// Fix #4: cch is a static "00000" placeholder for Bun's native client attestation.
|
|
5579
|
+
// Real CC v92: cch is included for all providers EXCEPT bedrock/anthropicAws.
|
|
5580
|
+
// The real Bun binary overwrites these zeros in the serialized body bytes.
|
|
5581
|
+
// For non-Bun runtimes, the server sees "00000" and skips attestation verification.
|
|
5582
|
+
const isBedrock = provider === "bedrock" || provider === "anthropicAws";
|
|
5583
|
+
const cchPart = isBedrock ? "" : " cch=00000;";
|
|
5584
|
+
let header = `x-anthropic-billing-header: cc_version=${ccVersion}; cc_entrypoint=${entrypoint};${cchPart}`;
|
|
5568
5585
|
const workload = process.env.CLAUDE_CODE_WORKLOAD;
|
|
5569
5586
|
if (workload) {
|
|
5570
5587
|
// QA fix M5: sanitize workload value to prevent header injection
|
|
@@ -5756,8 +5773,8 @@ function buildSystemPromptBlocks(system, signature) {
|
|
|
5756
5773
|
const blocks = [];
|
|
5757
5774
|
const billingHeader = buildAnthropicBillingHeader(
|
|
5758
5775
|
signature.claudeCliVersion,
|
|
5759
|
-
signature.modelId,
|
|
5760
5776
|
signature.firstUserMessage,
|
|
5777
|
+
signature.provider,
|
|
5761
5778
|
);
|
|
5762
5779
|
if (billingHeader) {
|
|
5763
5780
|
// Billing header: no cache_control (null scope — never cached)
|
|
@@ -6117,7 +6134,7 @@ async function fetchLatestClaudeCodeVersion(timeoutMs = 1200) {
|
|
|
6117
6134
|
* @param {string} accessToken
|
|
6118
6135
|
* @param {string | undefined} requestBody
|
|
6119
6136
|
* @param {URL | null} requestUrl
|
|
6120
|
-
* @param {{enabled: boolean, claudeCliVersion: string, strategy?: import('./lib/config.mjs').AccountSelectionStrategy, customBetas?: string[]}} signature
|
|
6137
|
+
* @param {{enabled: boolean, claudeCliVersion: string, strategy?: import('./lib/config.mjs').AccountSelectionStrategy, customBetas?: string[], sessionId?: string}} signature
|
|
6121
6138
|
* @returns {Headers}
|
|
6122
6139
|
*/
|
|
6123
6140
|
function buildRequestHeaders(
|
|
@@ -6181,7 +6198,14 @@ function buildRequestHeaders(
|
|
|
6181
6198
|
requestHeaders.set("user-agent", buildExtendedUserAgent(signature.claudeCliVersion));
|
|
6182
6199
|
if (signature.enabled) {
|
|
6183
6200
|
requestHeaders.set("anthropic-version", "2023-06-01");
|
|
6184
|
-
|
|
6201
|
+
// Fix #6: x-app is "cli" for interactive mode, "cli-bg" for background tasks.
|
|
6202
|
+
// Real CC (client.ts:106): 'x-app': 'cli' (foreground) or 'cli-bg' (background agent).
|
|
6203
|
+
requestHeaders.set("x-app", isTruthyEnv(process.env.CLAUDE_CODE_BACKGROUND) ? "cli-bg" : "cli");
|
|
6204
|
+
// Fix #3: X-Claude-Code-Session-Id — sent in ALL requests by real CC (client.ts:108).
|
|
6205
|
+
// Value matches metadata.user_id.session_id for server-side correlation.
|
|
6206
|
+
if (signature.sessionId) {
|
|
6207
|
+
requestHeaders.set("X-Claude-Code-Session-Id", signature.sessionId);
|
|
6208
|
+
}
|
|
6185
6209
|
requestHeaders.set("x-stainless-arch", getStainlessArch(process.arch));
|
|
6186
6210
|
requestHeaders.set("x-stainless-lang", "js");
|
|
6187
6211
|
requestHeaders.set("x-stainless-os", getStainlessOs(process.platform));
|
package/lib/rotation.test.mjs
CHANGED
|
@@ -119,7 +119,7 @@ describe("TokenBucketTracker", () => {
|
|
|
119
119
|
|
|
120
120
|
it("consume reduces tokens", () => {
|
|
121
121
|
tracker.consume(0);
|
|
122
|
-
expect(tracker.getTokens(0)).
|
|
122
|
+
expect(tracker.getTokens(0)).toBeCloseTo(49, 1);
|
|
123
123
|
});
|
|
124
124
|
|
|
125
125
|
it("consume returns false when insufficient tokens", () => {
|