opencode-anthropic-fix 0.1.25 → 0.1.27

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/index.mjs CHANGED
@@ -6481,6 +6481,26 @@ function isOpus47Model(model) {
6481
6481
  return /claude-opus-4[._-]7|opus[._-]4[._-]7/i.test(model);
6482
6482
  }
6483
6483
 
6484
+ /**
6485
+ * Models eligible for the "simple system prompt" mode that real CC ships in
6486
+ * v2.1.133+ under GrowthBook flag `tengu_vellum_lantern` (or forced via
6487
+ * `CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT=1`).
6488
+ *
6489
+ * Real CC's `sR9` matches: `claude-opus-4-7`, any model with `-eap` (early
6490
+ * access) suffix, plus a small GrowthBook-controlled allowlist we can't read.
6491
+ * Plugin mirrors the deterministic subset only.
6492
+ *
6493
+ * @param {string | undefined} model
6494
+ * @returns {boolean}
6495
+ */
6496
+ function isSimpleSystemPromptEligible(model) {
6497
+ if (!model) return false;
6498
+ if (isOpus47Model(model)) return true;
6499
+ // -eap suffix variant, e.g. "claude-opus-4-7-eap" or "claude-opus-4-7-eap[1m]"
6500
+ if (/-eap(?:\[|$|-)/i.test(model)) return true;
6501
+ return false;
6502
+ }
6503
+
6484
6504
  /**
6485
6505
  * Detects claude-sonnet-4.6 / claude-sonnet-4-6 model IDs.
6486
6506
  * @param {string | undefined} body
@@ -6724,9 +6744,11 @@ function buildRequestMetadata(input) {
6724
6744
  * @param {string} version - CLI version (e.g., "2.1.97")
6725
6745
  * @param {string} [firstUserMessage] - First user message text for fingerprint computation
6726
6746
  * @param {string} [provider] - API provider ("anthropic" | "bedrock" | "vertex" | "foundry" | "anthropicAws" | "mantle")
6747
+ * @param {string} [workloadOverride] - Explicit workload tag from config (`signature_emulation.workload`).
6748
+ * Takes precedence over `CLAUDE_CODE_WORKLOAD` env var. Mirrors real CC's `--workload <tag>` flag.
6727
6749
  * @returns {string}
6728
6750
  */
6729
- function buildAnthropicBillingHeader(version, firstUserMessage, provider) {
6751
+ function buildAnthropicBillingHeader(version, firstUserMessage, provider, workloadOverride) {
6730
6752
  if (isFalsyEnv(process.env.CLAUDE_CODE_ATTRIBUTION_HEADER)) return "";
6731
6753
  // Real CC sends cc_entrypoint=cli (confirmed via proxy capture).
6732
6754
  const entrypoint = process.env.CLAUDE_CODE_ENTRYPOINT || "cli";
@@ -6741,13 +6763,15 @@ function buildAnthropicBillingHeader(version, firstUserMessage, provider) {
6741
6763
  // The server uses the PRESENCE of cch=00000 as a CC identification signal.
6742
6764
  const cchDisabled = provider === "bedrock" || provider === "anthropicAws" || provider === "mantle";
6743
6765
  const cchPart = cchDisabled ? "" : " cch=00000;";
6744
- // Build workload part (upstream concatenates directly, no regex replace)
6766
+ // Build workload part (upstream concatenates directly, no regex replace).
6767
+ // Config wins over env so `signature_emulation.workload` is portable across hosts.
6745
6768
  let workloadPart = "";
6746
- const workload = process.env.CLAUDE_CODE_WORKLOAD;
6747
- if (workload) {
6748
- // QA fix M5: sanitize workload value to prevent header injection
6749
- const safeWorkload = workload.replace(/[;\s\r\n]/g, "_");
6750
- workloadPart = ` cc_workload=${safeWorkload};`;
6769
+ const workload = workloadOverride || process.env.CLAUDE_CODE_WORKLOAD;
6770
+ if (workload && !cchDisabled) {
6771
+ // QA fix M5: sanitize workload value to prevent header injection.
6772
+ // Real CC skips cc_workload on bedrock/anthropicAws/mantle (same gate as cch).
6773
+ const safeWorkload = String(workload).replace(/[;\s\r\n]/g, "_");
6774
+ if (safeWorkload) workloadPart = ` cc_workload=${safeWorkload};`;
6751
6775
  }
6752
6776
  return `x-anthropic-billing-header: cc_version=${ccVersion}; cc_entrypoint=${entrypoint};${cchPart}${workloadPart}`;
6753
6777
  }
@@ -7195,8 +7219,20 @@ function buildSystemPromptBlocks(system, signature) {
7195
7219
 
7196
7220
  // Anti-verbosity injection (CC v2.1.100 quiet_salted_ember equivalent).
7197
7221
  // Applies to Opus 4.6 / 4.7 for non-title-generator requests.
7222
+ //
7223
+ // Simple-system-prompt gate (CC v2.1.133+ `tengu_vellum_lantern` equivalent):
7224
+ // when `signature.simpleSystemPrompt` is true AND the model is eligible
7225
+ // (Opus 4.7, -eap variants), skip the anti-verbosity boilerplate. Real CC's
7226
+ // simple-prompt mode strips this kind of post-hoc behavioral hand-holding on
7227
+ // models that don't need it. Conservative implementation: gates ONLY the
7228
+ // anti-verbosity push, not the identity / billing / sanitized blocks. Saves
7229
+ // ~600-1500 tokens per request on eligible models without touching the CC
7230
+ // fingerprint markers the server checks.
7231
+ const skipAntiVerbosity = signature.simpleSystemPrompt === true && isSimpleSystemPromptEligible(signature.modelId);
7232
+
7198
7233
  if (
7199
7234
  !titleGeneratorRequest &&
7235
+ !skipAntiVerbosity &&
7200
7236
  signature.modelId &&
7201
7237
  (isOpus46Model(signature.modelId) || isOpus47Model(signature.modelId))
7202
7238
  ) {
@@ -7233,6 +7269,7 @@ function buildSystemPromptBlocks(system, signature) {
7233
7269
  signature.claudeCliVersion,
7234
7270
  signature.firstUserMessage,
7235
7271
  signature.provider,
7272
+ signature.workload,
7236
7273
  );
7237
7274
 
7238
7275
  // Select the identity string (matches real CC getCLISyspromptPrefix())
@@ -7408,6 +7445,12 @@ function buildAnthropicBetaHeader(
7408
7445
  betas.push("context-hint-2026-04-09");
7409
7446
  }
7410
7447
 
7448
+ // extended-cache-ttl-2025-04-11 — found in CC v2.1.143. Extends server-side
7449
+ // prompt cache TTL. Auto-on for 1P + Claude 4+ to improve cache hit rates.
7450
+ if (isFirstPartyProvider && !/claude-3-/i.test(model)) {
7451
+ betas.push("extended-cache-ttl-2025-04-11");
7452
+ }
7453
+
7411
7454
  // Files API — scoped to file endpoints/references
7412
7455
  if (isFilesEndpoint || hasFileReferences) {
7413
7456
  betas.push("files-api-2025-04-14");
@@ -7798,6 +7841,18 @@ function transformRequestBody(body, signature, runtime, betaHeader, config) {
7798
7841
  delete parsed.effort;
7799
7842
  }
7800
7843
 
7844
+ // Claude Code v2.1.117+: default effort for Pro/Max on adaptive models is
7845
+ // "high" (was "medium"). If the host omits effort entirely, inject the
7846
+ // default so the wire shape matches real CC.
7847
+ if (parsed.model && isAdaptiveThinkingModel(parsed.model)) {
7848
+ if (!parsed.output_config || typeof parsed.output_config !== "object") {
7849
+ parsed.output_config = {};
7850
+ }
7851
+ if (!("effort" in parsed.output_config)) {
7852
+ parsed.output_config.effort = "high";
7853
+ }
7854
+ }
7855
+
7801
7856
  // Claude Code temperature rule: when extended thinking is active (any type),
7802
7857
  // temperature must be omitted (undefined). Otherwise default to 1.
7803
7858
  const thinkingActive =
@@ -7949,6 +8004,15 @@ function transformRequestBody(body, signature, runtime, betaHeader, config) {
7949
8004
  // Default off — opt-in via `token_economy.lean_system_non_main: true`.
7950
8005
  requestRole: runtime?.requestRole,
7951
8006
  leanNonMain: config?.token_economy?.lean_system_non_main === true,
8007
+ // Simple-system-prompt mode for Opus 4.7+ (CC v2.1.133+ parity, gated by
8008
+ // GrowthBook `tengu_vellum_lantern` in real CC). Plugin gate: model
8009
+ // eligibility + opt-in flag. See buildSystemPromptBlocks for what it
8010
+ // strips (anti-verbosity boilerplate only; identity/billing untouched).
8011
+ simpleSystemPrompt: config?.token_economy?.simple_system_prompt === true,
8012
+ // Workload tag for x-anthropic-billing-header `cc_workload=` segment.
8013
+ // Mirrors real CC's `--workload <tag>` CLI flag (process-scoped, used by
8014
+ // SDK daemon callers spawning cron subprocesses). Empty string -> omit.
8015
+ workload: typeof config?.signature_emulation?.workload === "string" ? config.signature_emulation.workload : "",
7952
8016
  };
7953
8017
  // Sanitize system prompt and optionally inject Claude Code identity/billing blocks.
7954
8018
  parsed.system = buildSystemPromptBlocks(normalizeSystemTextBlocks(parsed.system), signatureWithModel);
package/lib/config.mjs CHANGED
@@ -80,7 +80,7 @@ import { randomBytes } from "node:crypto";
80
80
  * @property {AccountSelectionStrategy} account_selection_strategy
81
81
  * @property {number} failure_ttl_seconds
82
82
  * @property {boolean} debug
83
- * @property {{ enabled: boolean, fetch_claude_code_version_on_startup: boolean, prompt_compaction: 'minimal' | 'off' }} signature_emulation
83
+ * @property {{ enabled: boolean, fetch_claude_code_version_on_startup: boolean, prompt_compaction: 'minimal' | 'off', workload: string }} signature_emulation
84
84
  * @property {OverrideModelLimitsConfig} override_model_limits
85
85
  * @property {string[]} custom_betas
86
86
  * @property {HealthScoreConfig} health_score
@@ -115,6 +115,13 @@ export const DEFAULT_CONFIG = {
115
115
  enabled: true,
116
116
  fetch_claude_code_version_on_startup: true,
117
117
  prompt_compaction: "minimal",
118
+ /** Workload tag emitted in the `x-anthropic-billing-header` as
119
+ * `cc_workload=<tag>;`. Mirrors real CC's `--workload <tag>` flag — used
120
+ * by SDK daemon callers that spawn subprocesses for cron work, to tag
121
+ * billing attribution. Empty string => omit (default). Provider-gated:
122
+ * bedrock/anthropicAws/mantle skip this segment (same gate as `cch`).
123
+ * Env var `CLAUDE_CODE_WORKLOAD` is a fallback when this is empty. */
124
+ workload: "",
118
125
  },
119
126
  override_model_limits: {
120
127
  enabled: false,
@@ -279,6 +286,17 @@ export const DEFAULT_CONFIG = {
279
286
  * enable deliberately rather than by default. */
280
287
  lean_system_non_main: false,
281
288
 
289
+ /** Simple system prompt mode (real CC v2.1.133+ `tengu_vellum_lantern`
290
+ * equivalent). When enabled AND the request model is eligible
291
+ * (claude-opus-4-7, -eap variants — see `isSimpleSystemPromptEligible`),
292
+ * skip the anti-verbosity boilerplate (`ANTI_VERBOSITY_SYSTEM_PROMPT` +
293
+ * `NUMERIC_LENGTH_ANCHORS_PROMPT`) that the plugin injects on Opus 4.x.
294
+ * Conservative implementation: gates ONLY anti-verbosity. Identity
295
+ * preamble, billing block, user instructions, and `<system-reminder>`
296
+ * blocks are all preserved so the CC fingerprint match still holds.
297
+ * Saves ~600-1500 tokens per request on eligible models. Opt-in. */
298
+ simple_system_prompt: false,
299
+
282
300
  // NOTE: identical-tool-call short-circuit was considered but requires SSE
283
301
  // response-stream rewriting that breaks normal tool-execution semantics.
284
302
  // Tracked as future work — not exposed as a config flag here.
@@ -496,6 +514,7 @@ function validateConfig(raw) {
496
514
  se.prompt_compaction === "off" || se.prompt_compaction === "minimal"
497
515
  ? se.prompt_compaction
498
516
  : DEFAULT_CONFIG.signature_emulation.prompt_compaction,
517
+ workload: typeof se.workload === "string" ? se.workload.trim() : DEFAULT_CONFIG.signature_emulation.workload,
499
518
  };
500
519
  }
501
520
 
@@ -759,6 +778,10 @@ function validateConfig(raw) {
759
778
  typeof te.lean_system_non_main === "boolean"
760
779
  ? te.lean_system_non_main
761
780
  : DEFAULT_CONFIG.token_economy.lean_system_non_main,
781
+ simple_system_prompt:
782
+ typeof te.simple_system_prompt === "boolean"
783
+ ? te.simple_system_prompt
784
+ : DEFAULT_CONFIG.token_economy.simple_system_prompt,
762
785
  };
763
786
  }
764
787
 
@@ -16,20 +16,45 @@
16
16
  // Version / build / SDK constants
17
17
  // ---------------------------------------------------------------------------
18
18
 
19
- export const FALLBACK_CLAUDE_CLI_VERSION = "2.1.119";
19
+ export const FALLBACK_CLAUDE_CLI_VERSION = "2.1.143";
20
20
  export const CLAUDE_CODE_NPM_LATEST_URL = "https://registry.npmjs.org/@anthropic-ai/claude-code/latest";
21
- export const CLAUDE_CODE_BUILD_TIME = "2026-04-23T19:08:52Z";
21
+ export const CLAUDE_CODE_BUILD_TIME = "2026-05-15T17:39:39Z";
22
22
 
23
23
  // The @anthropic-ai/sdk version bundled with Claude Code.
24
24
  // This is distinct from the CLI version and goes in X-Stainless-Package-Version.
25
25
  // v2.1.107 switched from @anthropic-ai/sdk v0.208.0 to v0.81.0 (confirmed via bundle var x$H="0.81.0").
26
- // Still 0.81.0 in v2.1.119 (verified via strings extraction from native Bun binary;
27
- // adds cache-diagnosis-2026-04-07 beta gated by GrowthBook tengu_prompt_cache_diagnostics;
28
- // no other beta additions/removals vs 2.1.117; OAuth flow unchanged).
26
+ // Still 0.81.0 in v2.1.143 (verified by binary string extraction of win32-x64 native binary:
27
+ // 2.1.134-2.1.143 are telemetry / subagent-header / mid-conversation-system additions with
28
+ // no SDK version bump; mid-conversation-system-2026-04-07 registered in 2.1.143 but not
29
+ // auto-emitted; two new conditional x- headers x-claude-code-agent-id /
30
+ // x-claude-code-parent-agent-id are only emitted in subagent dispatch contexts).
29
31
  export const ANTHROPIC_SDK_VERSION = "0.81.0";
30
32
 
31
33
  // Map of CLI version to bundled SDK version (update when CLI version changes)
32
34
  export const CLI_TO_SDK_VERSION = new Map([
35
+ ["2.1.143", "0.81.0"],
36
+ ["2.1.142", "0.81.0"],
37
+ ["2.1.141", "0.81.0"],
38
+ ["2.1.140", "0.81.0"],
39
+ ["2.1.139", "0.81.0"],
40
+ ["2.1.138", "0.81.0"],
41
+ ["2.1.137", "0.81.0"],
42
+ ["2.1.136", "0.81.0"],
43
+ ["2.1.134", "0.81.0"],
44
+ ["2.1.133", "0.81.0"],
45
+ ["2.1.132", "0.81.0"],
46
+ ["2.1.131", "0.81.0"],
47
+ ["2.1.130", "0.81.0"],
48
+ ["2.1.129", "0.81.0"],
49
+ ["2.1.128", "0.81.0"],
50
+ ["2.1.127", "0.81.0"],
51
+ ["2.1.126", "0.81.0"],
52
+ ["2.1.125", "0.81.0"],
53
+ ["2.1.124", "0.81.0"],
54
+ ["2.1.123", "0.81.0"],
55
+ ["2.1.122", "0.81.0"],
56
+ ["2.1.121", "0.81.0"],
57
+ ["2.1.120", "0.81.0"],
33
58
  ["2.1.119", "0.81.0"],
34
59
  ["2.1.117", "0.81.0"],
35
60
  ["2.1.116", "0.81.0"],
@@ -93,14 +118,24 @@ export const EXPERIMENTAL_BETA_FLAGS = new Set([
93
118
  "context-1m-2025-08-07",
94
119
  "context-hint-2026-04-09",
95
120
  "context-management-2025-06-27",
121
+ "environments-2025-11-01",
122
+ "extended-cache-ttl-2025-04-11",
96
123
  "fast-mode-2026-02-01",
97
124
  "files-api-2025-04-14",
98
125
  "interleaved-thinking-2025-05-14",
126
+ // Registered in CC v2.1.143 but NOT in real CC's always-on emission set
127
+ // (master registry only, not in the always-on subset). Likely GrowthBook-gated
128
+ // pending server rollout. Paired telemetry: tengu_mid_conv_system_fallback_retry.
129
+ "mid-conversation-system-2026-04-07",
99
130
  "prompt-caching-scope-2026-01-05",
100
131
  "redact-thinking-2026-02-12",
101
132
  "structured-outputs-2025-12-15",
102
133
  "task-budgets-2026-03-13",
103
134
  "tool-search-tool-2025-10-19",
135
+ // SDK admin route beta (used for /v1/user_profiles* endpoints). Registered for
136
+ // forward-compat; the plugin proxies /v1/messages only and does NOT emit this
137
+ // on chat completions.
138
+ "user-profiles-2026-03-24",
104
139
  "web-search-2025-03-05",
105
140
  ]);
106
141
 
@@ -111,7 +146,10 @@ export const BETA_SHORTCUTS = new Map([
111
146
  ["context-1m", "context-1m-2025-08-07"],
112
147
  ["cache-diagnosis", "cache-diagnosis-2026-04-07"],
113
148
  ["cache-diag", "cache-diagnosis-2026-04-07"],
149
+ ["cache-ttl", "extended-cache-ttl-2025-04-11"],
114
150
  ["context-hint", "context-hint-2026-04-09"],
151
+ ["environments", "environments-2025-11-01"],
152
+ ["extended-cache-ttl", "extended-cache-ttl-2025-04-11"],
115
153
  ["hint", "context-hint-2026-04-09"],
116
154
  ["fast", "fast-mode-2026-02-01"],
117
155
  ["fast-mode", "fast-mode-2026-02-01"],
@@ -119,6 +157,8 @@ export const BETA_SHORTCUTS = new Map([
119
157
  ["task-budgets", "task-budgets-2026-03-13"],
120
158
  ["budgets", "task-budgets-2026-03-13"],
121
159
  ["redact-thinking", "redact-thinking-2026-02-12"],
160
+ ["mid-conv-system", "mid-conversation-system-2026-04-07"],
161
+ ["mid-system", "mid-conversation-system-2026-04-07"],
122
162
  ]);
123
163
 
124
164
  // ---------------------------------------------------------------------------
@@ -13,8 +13,8 @@ import {
13
13
  } from "./request-headers.mjs";
14
14
 
15
15
  describe("request-headers constants", () => {
16
- it("FALLBACK_CLAUDE_CLI_VERSION is 2.1.119", () => {
17
- expect(FALLBACK_CLAUDE_CLI_VERSION).toBe("2.1.119");
16
+ it("FALLBACK_CLAUDE_CLI_VERSION is 2.1.143", () => {
17
+ expect(FALLBACK_CLAUDE_CLI_VERSION).toBe("2.1.143");
18
18
  });
19
19
 
20
20
  it("ANTHROPIC_SDK_VERSION matches expected value", () => {
@@ -24,9 +24,9 @@ describe("request-headers constants", () => {
24
24
  });
25
25
 
26
26
  describe("getSdkVersion", () => {
27
- it("returns known SDK version for CLI version 2.1.119", () => {
28
- // 2.1.119 is in the VERSION_TO_SDK_MAP
29
- const v = getSdkVersion("2.1.119");
27
+ it("returns known SDK version for CLI version 2.1.143", () => {
28
+ // 2.1.143 is in the VERSION_TO_SDK_MAP
29
+ const v = getSdkVersion("2.1.143");
30
30
  expect(typeof v).toBe("string");
31
31
  expect(v).toMatch(/^\d+\.\d+\.\d+$/);
32
32
  });
@@ -95,26 +95,26 @@ describe("buildExtendedUserAgent", () => {
95
95
  delete process.env.CLAUDE_CODE_ENTRYPOINT;
96
96
  delete process.env.CLAUDE_AGENT_SDK_VERSION;
97
97
  delete process.env.CLAUDE_AGENT_SDK_CLIENT_APP;
98
- const ua = buildExtendedUserAgent("2.1.119");
99
- expect(ua).toBe("claude-cli/2.1.119 (external, cli)");
98
+ const ua = buildExtendedUserAgent("2.1.143");
99
+ expect(ua).toBe("claude-cli/2.1.143 (external, cli)");
100
100
  });
101
101
 
102
102
  it("uses CLAUDE_CODE_ENTRYPOINT when set", () => {
103
103
  process.env.CLAUDE_CODE_ENTRYPOINT = "vscode";
104
- const ua = buildExtendedUserAgent("2.1.119");
105
- expect(ua).toBe("claude-cli/2.1.119 (external, vscode)");
104
+ const ua = buildExtendedUserAgent("2.1.143");
105
+ expect(ua).toBe("claude-cli/2.1.143 (external, vscode)");
106
106
  });
107
107
 
108
108
  it("appends agent-sdk suffix when CLAUDE_AGENT_SDK_VERSION is set", () => {
109
109
  process.env.CLAUDE_AGENT_SDK_VERSION = "1.2.3";
110
- const ua = buildExtendedUserAgent("2.1.119");
110
+ const ua = buildExtendedUserAgent("2.1.143");
111
111
  expect(ua).toContain("agent-sdk/1.2.3");
112
- expect(ua).toMatch(/^claude-cli\/2\.1\.119/);
112
+ expect(ua).toMatch(/^claude-cli\/2\.1\.143/);
113
113
  });
114
114
 
115
115
  it("appends client-app suffix when CLAUDE_AGENT_SDK_CLIENT_APP is set", () => {
116
116
  process.env.CLAUDE_AGENT_SDK_CLIENT_APP = "myapp";
117
- const ua = buildExtendedUserAgent("2.1.119");
117
+ const ua = buildExtendedUserAgent("2.1.143");
118
118
  expect(ua).toContain("client-app/myapp");
119
119
  });
120
120
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-anthropic-fix",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
4
4
  "license": "GPL-3.0-or-later",
5
5
  "repository": {
6
6
  "type": "git",