opencode-anthropic-fix 0.2.0 → 0.3.0-beta.0
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 +31 -6
- package/cli.mjs +1 -0
- package/index.mjs +160 -231
- package/lib/backoff.mjs +1 -1
- package/lib/cc-credentials.mjs +1 -1
- package/lib/config.mjs +49 -27
- package/lib/mimicry/adapter-input.mjs +671 -0
- package/lib/mimicry/context-hint-threshold.mjs +127 -0
- package/lib/mimicry/headers.mjs +71 -66
- package/lib/mimicry/request-body.mjs +23 -24
- package/lib/mimicry/system-prompt.mjs +54 -23
- package/lib/mimicry/wire-compat.mjs +305 -0
- package/lib/rotation.mjs +16 -0
- package/package.json +3 -3
- package/lib/account-state.test.mjs +0 -109
- package/lib/accounts.test.mjs +0 -912
- package/lib/adaptive-thinking-models.test.mjs +0 -30
- package/lib/backoff.test.mjs +0 -411
- package/lib/cc-credentials.test.mjs +0 -391
- package/lib/config.test.mjs +0 -757
- package/lib/context-hint-persist.mjs +0 -68
- package/lib/diagnose.test.mjs +0 -122
- package/lib/env.test.mjs +0 -25
- package/lib/haiku-call.test.mjs +0 -72
- package/lib/message-transform.test.mjs +0 -173
- package/lib/mimicry/cache.test.mjs +0 -112
- package/lib/mimicry/headers.test.mjs +0 -50
- package/lib/mimicry/models.test.mjs +0 -132
- package/lib/mimicry/request-body.test.mjs +0 -34
- package/lib/mimicry/request-helpers.test.mjs +0 -155
- package/lib/mimicry/response-stream.test.mjs +0 -127
- package/lib/mimicry/system-prompt.test.mjs +0 -73
- package/lib/oauth.test.mjs +0 -343
- package/lib/redact.test.mjs +0 -154
- package/lib/refresh-lock.test.mjs +0 -131
- package/lib/request-headers.test.mjs +0 -164
- package/lib/retry/overload-loop.test.mjs +0 -107
- package/lib/rotation.test.mjs +0 -346
- package/lib/session-metrics.test.mjs +0 -67
- package/lib/storage.test.mjs +0 -696
- package/lib/token-economy/microcompact.test.mjs +0 -28
- package/lib/token-economy/transforms.test.mjs +0 -192
- package/lib/tuning.test.mjs +0 -89
package/lib/config.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { homedir } from "node:os";
|
|
|
4
4
|
import { randomBytes } from "node:crypto";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* @typedef {'sticky' | 'round-robin' | 'hybrid'} AccountSelectionStrategy
|
|
7
|
+
* @typedef {'sticky' | 'round-robin' | 'hybrid' | 'single'} AccountSelectionStrategy
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -103,7 +103,7 @@ import { randomBytes } from "node:crypto";
|
|
|
103
103
|
* @property {{ enabled: boolean, threshold_percent: number }} microcompact
|
|
104
104
|
* @property {{ enabled: boolean, default_cooldown_ms: number, poll_quota_on_overload: boolean }} overload_recovery
|
|
105
105
|
* @property {{ proactive_disabled: boolean }} account_management
|
|
106
|
-
* @property {{ enabled: boolean
|
|
106
|
+
* @property {{ enabled: boolean }} anti_verbosity
|
|
107
107
|
* @property {{ sdk_token_useragent: boolean }} oauth
|
|
108
108
|
*/
|
|
109
109
|
|
|
@@ -119,8 +119,9 @@ export const DEFAULT_CONFIG = {
|
|
|
119
119
|
/** Workload tag emitted in the `x-anthropic-billing-header` as
|
|
120
120
|
* `cc_workload=<tag>;`. Mirrors real CC's `--workload <tag>` flag — used
|
|
121
121
|
* by SDK daemon callers that spawn subprocesses for cron work, to tag
|
|
122
|
-
* billing attribution. Empty string => omit (default).
|
|
123
|
-
*
|
|
122
|
+
* billing attribution. Empty string => omit (default). Not provider-gated:
|
|
123
|
+
* the plugin is Anthropic first-party only, so this segment is emitted
|
|
124
|
+
* whenever a tag is set (see "Provider Scope" in README.md).
|
|
124
125
|
* Env var `CLAUDE_CODE_WORKLOAD` is a fallback when this is empty. */
|
|
125
126
|
workload: "",
|
|
126
127
|
},
|
|
@@ -211,15 +212,17 @@ export const DEFAULT_CONFIG = {
|
|
|
211
212
|
* server-side for lower bandwidth). On by default for non-Claude-3 models
|
|
212
213
|
* (CC v2.1.150+). Opt out via `/anthropic set redact-thinking off`. */
|
|
213
214
|
redact_thinking: true,
|
|
214
|
-
/**
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
|
|
215
|
+
/** [DEPRECATED — has no effect] context-hint-2026-04-09.
|
|
216
|
+
* The profile derived from the real Claude Code 2.1.195 binary sends
|
|
217
|
+
* neither the `context-hint-2026-04-09` beta nor the paired
|
|
218
|
+
* `context_hint: { enabled: true }` body field. Emitting either one made
|
|
219
|
+
* the request distinguishable from the genuine client, so both emissions
|
|
220
|
+
* were removed from every path (adapter and legacy alike). The effect
|
|
221
|
+
* cannot come back without breaking the mimicry, so this knob is not
|
|
222
|
+
* silently ignored: validateConfig emits a one-time deprecation warning
|
|
223
|
+
* when a user explicitly sets it to `true`. Retained only so an existing
|
|
224
|
+
* config file keeps loading. */
|
|
225
|
+
context_hint: false,
|
|
223
226
|
|
|
224
227
|
/** Dump outgoing request bodies to
|
|
225
228
|
* `~/.opencode/opencode-anthropic-fix/request-dumps/` (rotating, last 10).
|
|
@@ -300,17 +303,17 @@ export const DEFAULT_CONFIG = {
|
|
|
300
303
|
* thread is untouched. */
|
|
301
304
|
lean_system_non_main: true,
|
|
302
305
|
|
|
303
|
-
/** Simple system prompt mode (real CC v2.1.133+ `
|
|
306
|
+
/** Simple system prompt mode (real CC v2.1.133+ `tengu_velvet_cascade`
|
|
304
307
|
* equivalent). When enabled AND the request model is eligible
|
|
305
308
|
* (claude-opus-4-7, -eap variants — see `isSimpleSystemPromptEligible`),
|
|
306
|
-
* skip the anti-verbosity boilerplate (`ANTI_VERBOSITY_SYSTEM_PROMPT`
|
|
307
|
-
*
|
|
309
|
+
* skip the anti-verbosity boilerplate (`ANTI_VERBOSITY_SYSTEM_PROMPT`)
|
|
310
|
+
* that the plugin injects on Opus 4.x.
|
|
308
311
|
* Conservative implementation: gates ONLY anti-verbosity. Identity
|
|
309
312
|
* preamble, billing block, user instructions, and `<system-reminder>`
|
|
310
313
|
* blocks are all preserved so the CC fingerprint match still holds.
|
|
311
314
|
* Saves ~600-1500 tokens per request on eligible models. Default ON:
|
|
312
315
|
* gates ONLY the anti-verbosity boilerplate (which real CC v2.1.133+ also
|
|
313
|
-
* drops for eligible Opus 4.x via
|
|
316
|
+
* drops for eligible Opus 4.x via tengu_velvet_cascade); identity, billing
|
|
314
317
|
* and system-reminders are preserved, so the fingerprint match holds. */
|
|
315
318
|
simple_system_prompt: true,
|
|
316
319
|
|
|
@@ -426,14 +429,12 @@ export const DEFAULT_CONFIG = {
|
|
|
426
429
|
proactive_disabled: true,
|
|
427
430
|
},
|
|
428
431
|
/** Anti-verbosity: inject conciseness instructions into system prompt for Opus 4.6.
|
|
429
|
-
* Mirrors CC
|
|
432
|
+
* Mirrors the CC anti_verbosity section (gated on
|
|
430
433
|
* quiet_salted_ember A/B test in CC; unconditional here since we always want savings).
|
|
431
434
|
* Only activates when model is opus-4-6. */
|
|
432
435
|
anti_verbosity: {
|
|
433
436
|
/** Master switch: inject anti-verbosity communication style instructions. */
|
|
434
437
|
enabled: true,
|
|
435
|
-
/** Also inject numeric length anchors (≤25 words between tool calls, ≤100 words final). */
|
|
436
|
-
length_anchors: true,
|
|
437
438
|
},
|
|
438
439
|
/** OAuth token-endpoint request fingerprint. */
|
|
439
440
|
oauth: {
|
|
@@ -449,7 +450,7 @@ export const DEFAULT_CONFIG = {
|
|
|
449
450
|
},
|
|
450
451
|
};
|
|
451
452
|
|
|
452
|
-
export const VALID_STRATEGIES = ["sticky", "round-robin", "hybrid"];
|
|
453
|
+
export const VALID_STRATEGIES = ["sticky", "round-robin", "hybrid", "single"];
|
|
453
454
|
|
|
454
455
|
/** OpenCode's OAuth client ID for Anthropic console auth flows. */
|
|
455
456
|
export const CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
|
|
@@ -529,6 +530,13 @@ function clampNumber(value, min, max, fallback) {
|
|
|
529
530
|
* @param {Record<string, unknown>} raw
|
|
530
531
|
* @returns {AnthropicAuthConfig}
|
|
531
532
|
*/
|
|
533
|
+
/**
|
|
534
|
+
* One-shot latch for the `token_economy.context_hint` deprecation warning, so a
|
|
535
|
+
* long-running session does not repeat it on every config reload.
|
|
536
|
+
* @type {boolean}
|
|
537
|
+
*/
|
|
538
|
+
let contextHintDeprecationWarned = false;
|
|
539
|
+
|
|
532
540
|
function validateConfig(raw) {
|
|
533
541
|
const config = createDefaultConfig();
|
|
534
542
|
|
|
@@ -757,6 +765,21 @@ function validateConfig(raw) {
|
|
|
757
765
|
// Token economy sub-config
|
|
758
766
|
if (raw.token_economy && typeof raw.token_economy === "object") {
|
|
759
767
|
const te = /** @type {Record<string, unknown>} */ (raw.token_economy);
|
|
768
|
+
|
|
769
|
+
// Non-silent deprecation. Only an explicit `true` warns: the `false` default
|
|
770
|
+
// costs the user nothing and must stay quiet. See the DEFAULT_CONFIG comment
|
|
771
|
+
// on token_economy.context_hint for why the effect cannot be restored.
|
|
772
|
+
if (te.context_hint === true && !contextHintDeprecationWarned) {
|
|
773
|
+
contextHintDeprecationWarned = true;
|
|
774
|
+
|
|
775
|
+
console.warn(
|
|
776
|
+
"[anthropic-auth] token_economy.context_hint is deprecated and has no effect: " +
|
|
777
|
+
"the context-hint-2026-04-09 beta and the context_hint body field are no longer sent on any " +
|
|
778
|
+
"request path, because the genuine Claude Code client does not send them and emitting them " +
|
|
779
|
+
"would make requests fingerprintable. Remove the setting from your config to silence this warning.",
|
|
780
|
+
);
|
|
781
|
+
}
|
|
782
|
+
|
|
760
783
|
config.token_economy = {
|
|
761
784
|
token_efficient_tools:
|
|
762
785
|
typeof te.token_efficient_tools === "boolean"
|
|
@@ -764,6 +787,11 @@ function validateConfig(raw) {
|
|
|
764
787
|
: DEFAULT_CONFIG.token_economy.token_efficient_tools,
|
|
765
788
|
redact_thinking:
|
|
766
789
|
typeof te.redact_thinking === "boolean" ? te.redact_thinking : DEFAULT_CONFIG.token_economy.redact_thinking,
|
|
790
|
+
// DEPRECATED: the value is still normalized so an existing config file
|
|
791
|
+
// keeps loading, but nothing reads it any more — the context-hint beta and
|
|
792
|
+
// body field were removed from every request path because the genuine
|
|
793
|
+
// Claude Code 2.1.195 client does not send them. A user switch that turns
|
|
794
|
+
// into a silent no-op is not acceptable, so an explicit opt-in warns once.
|
|
767
795
|
context_hint: typeof te.context_hint === "boolean" ? te.context_hint : DEFAULT_CONFIG.token_economy.context_hint,
|
|
768
796
|
conservative: typeof te.conservative === "boolean" ? te.conservative : DEFAULT_CONFIG.token_economy.conservative,
|
|
769
797
|
debug_dump_bodies:
|
|
@@ -1011,8 +1039,6 @@ function validateConfig(raw) {
|
|
|
1011
1039
|
const av = /** @type {Record<string, unknown>} */ (raw.anti_verbosity);
|
|
1012
1040
|
config.anti_verbosity = {
|
|
1013
1041
|
enabled: typeof av.enabled === "boolean" ? av.enabled : DEFAULT_CONFIG.anti_verbosity.enabled,
|
|
1014
|
-
length_anchors:
|
|
1015
|
-
typeof av.length_anchors === "boolean" ? av.length_anchors : DEFAULT_CONFIG.anti_verbosity.length_anchors,
|
|
1016
1042
|
};
|
|
1017
1043
|
}
|
|
1018
1044
|
|
|
@@ -1128,10 +1154,6 @@ function applyEnvOverrides(config) {
|
|
|
1128
1154
|
if (env.OPENCODE_ANTHROPIC_ANTI_VERBOSITY === "0" || env.OPENCODE_ANTHROPIC_ANTI_VERBOSITY === "false") {
|
|
1129
1155
|
config.anti_verbosity.enabled = false;
|
|
1130
1156
|
}
|
|
1131
|
-
if (env.OPENCODE_ANTHROPIC_LENGTH_ANCHORS === "0" || env.OPENCODE_ANTHROPIC_LENGTH_ANCHORS === "false") {
|
|
1132
|
-
config.anti_verbosity.length_anchors = false;
|
|
1133
|
-
}
|
|
1134
|
-
|
|
1135
1157
|
return config;
|
|
1136
1158
|
}
|
|
1137
1159
|
|