opencode-anthropic-fix 0.1.8 → 0.1.9

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.
Files changed (3) hide show
  1. package/index.mjs +222 -27
  2. package/lib/config.mjs +2 -9
  3. package/package.json +1 -1
package/index.mjs CHANGED
@@ -666,6 +666,7 @@ export async function AnthropicAuthPlugin({ client, project, directory, worktree
666
666
  const secondary = (args[1] || "").toLowerCase();
667
667
  if (secondary === "reset") {
668
668
  sessionMetrics.turns = 0;
669
+ sessionMetrics.usedTools.clear();
669
670
  sessionMetrics.totalInput = 0;
670
671
  sessionMetrics.totalOutput = 0;
671
672
  sessionMetrics.totalCacheRead = 0;
@@ -1081,8 +1082,6 @@ export async function AnthropicAuthPlugin({ client, project, directory, worktree
1081
1082
  const enabled = value === "on" || value === "true" || value === "1";
1082
1083
  const te = config.token_economy || {
1083
1084
  token_efficient_tools: true,
1084
- redact_thinking: false,
1085
- connector_text_summarization: true,
1086
1085
  };
1087
1086
  te.token_efficient_tools = enabled;
1088
1087
  saveConfig({ token_economy: te });
@@ -1094,25 +1093,35 @@ export async function AnthropicAuthPlugin({ client, project, directory, worktree
1094
1093
  const enabled = value === "on" || value === "true" || value === "1";
1095
1094
  const te = config.token_economy || {
1096
1095
  token_efficient_tools: true,
1097
- redact_thinking: false,
1098
- connector_text_summarization: true,
1099
1096
  };
1100
1097
  te.redact_thinking = enabled;
1101
1098
  saveConfig({ token_economy: te });
1102
1099
  config.token_economy = te;
1103
1100
  betaLatchState.dirty = true;
1104
1101
  },
1105
- "connector-text": () => {
1102
+ "tool-deferral": () => {
1106
1103
  const enabled = value === "on" || value === "true" || value === "1";
1107
- const te = config.token_economy || {
1108
- token_efficient_tools: true,
1109
- redact_thinking: false,
1110
- connector_text_summarization: true,
1111
- };
1112
- te.connector_text_summarization = enabled;
1113
- saveConfig({ token_economy: te });
1114
- config.token_economy = te;
1115
- betaLatchState.dirty = true;
1104
+ saveConfig({ token_economy_strategies: { tool_deferral: enabled } });
1105
+ if (!config.token_economy_strategies) config.token_economy_strategies = {};
1106
+ config.token_economy_strategies.tool_deferral = enabled;
1107
+ },
1108
+ "tool-compaction": () => {
1109
+ const enabled = value === "on" || value === "true" || value === "1";
1110
+ saveConfig({ token_economy_strategies: { tool_description_compaction: enabled } });
1111
+ if (!config.token_economy_strategies) config.token_economy_strategies = {};
1112
+ config.token_economy_strategies.tool_description_compaction = enabled;
1113
+ },
1114
+ "adaptive-tools": () => {
1115
+ const enabled = value === "on" || value === "true" || value === "1";
1116
+ saveConfig({ token_economy_strategies: { adaptive_tool_set: enabled } });
1117
+ if (!config.token_economy_strategies) config.token_economy_strategies = {};
1118
+ config.token_economy_strategies.adaptive_tool_set = enabled;
1119
+ },
1120
+ "prompt-tailing": () => {
1121
+ const enabled = value === "on" || value === "true" || value === "1";
1122
+ saveConfig({ token_economy_strategies: { system_prompt_tailing: enabled } });
1123
+ if (!config.token_economy_strategies) config.token_economy_strategies = {};
1124
+ config.token_economy_strategies.system_prompt_tailing = enabled;
1116
1125
  },
1117
1126
  };
1118
1127
 
@@ -2785,11 +2794,19 @@ export async function AnthropicAuthPlugin({ client, project, directory, worktree
2785
2794
  cachePolicy: effectiveCachePolicy,
2786
2795
  fastMode: config.fast_mode || false,
2787
2796
  strategy: getEffectiveStrategy(),
2797
+ toolDeferral: config.token_economy_strategies?.tool_deferral,
2798
+ toolDescriptionCompaction: config.token_economy_strategies?.tool_description_compaction,
2799
+ adaptiveToolSet: config.token_economy_strategies?.adaptive_tool_set,
2800
+ systemPromptTailing: config.token_economy_strategies?.system_prompt_tailing,
2801
+ systemPromptTailTurns: config.token_economy_strategies?.system_prompt_tail_turns,
2802
+ systemPromptTailMaxChars: config.token_economy_strategies?.system_prompt_tail_max_chars,
2788
2803
  },
2789
2804
  {
2790
2805
  persistentUserId: signatureUserId,
2791
2806
  sessionId: signatureSessionId,
2792
2807
  accountId: getAccountIdentifier(account),
2808
+ turns: sessionMetrics.turns,
2809
+ usedTools: sessionMetrics.usedTools,
2793
2810
  },
2794
2811
  computedBetaHeader,
2795
2812
  config,
@@ -3908,6 +3925,8 @@ const sessionMetrics = {
3908
3925
  continuations: 0,
3909
3926
  outputHistory: [], // last 5 output token deltas
3910
3927
  },
3928
+ /** Tools used in this session (populated from assistant tool_use blocks in messages) */
3929
+ usedTools: new Set(),
3911
3930
  };
3912
3931
 
3913
3932
  // ---------------------------------------------------------------------------
@@ -5357,6 +5376,23 @@ const BEDROCK_UNSUPPORTED_BETAS = new Set([
5357
5376
  "context-1m-2025-08-07",
5358
5377
  "tool-search-tool-2025-10-19",
5359
5378
  ]);
5379
+ // OpenCode SDK betas that leak through the host's Anthropic SDK but are NOT
5380
+ // part of CC's beta vocabulary. Filtered out when signature emulation is on.
5381
+ // Core tool names (CC PascalCase) that are always eager-loaded.
5382
+ const CORE_TOOL_NAMES = new Set([
5383
+ "Bash",
5384
+ "Read",
5385
+ "Glob",
5386
+ "Grep",
5387
+ "Edit",
5388
+ "Write",
5389
+ "WebFetch",
5390
+ "TodoWrite",
5391
+ "Skill",
5392
+ "Task",
5393
+ "Compress",
5394
+ ]);
5395
+ const HOST_SDK_BETAS_BLOCKLIST = new Set(["fine-grained-tool-streaming-2025-05-14", "structured-outputs-2025-11-13"]);
5360
5396
  const EXPERIMENTAL_BETA_FLAGS = new Set([
5361
5397
  "adaptive-thinking-2026-01-28",
5362
5398
  "advanced-tool-use-2025-11-20",
@@ -5883,6 +5919,55 @@ function sanitizeSystemText(text) {
5883
5919
  * @param {'minimal' | 'off'} mode
5884
5920
  * @returns {string}
5885
5921
  */
5922
+ function tailSystemBlock(text, maxChars, turnThreshold) {
5923
+ const lines = text.split("\n");
5924
+ const kept = [];
5925
+ let charCount = 0;
5926
+ const importantRe = /\b(MUST|NEVER|CRITICAL|IMPORTANT|REQUIRED|DO NOT|ALWAYS|FORBIDDEN)\b/i;
5927
+ const headerRe = /^#{1,4}\s/;
5928
+ const listItemRe = /^\s*[-*]\s/;
5929
+ // Always keep the first paragraph (identity/role definition)
5930
+ let firstParaEnd = 0;
5931
+ for (let j = 0; j < lines.length; j++) {
5932
+ if (lines[j].trim() === "" && j > 0) {
5933
+ firstParaEnd = j;
5934
+ break;
5935
+ }
5936
+ }
5937
+ if (firstParaEnd === 0) firstParaEnd = Math.min(5, lines.length);
5938
+ for (let j = 0; j <= firstParaEnd; j++) {
5939
+ kept.push(lines[j]);
5940
+ charCount += (lines[j]?.length || 0) + 1;
5941
+ }
5942
+ // Scan remaining lines: keep headers, important constraints, short list items
5943
+ for (let j = firstParaEnd + 1; j < lines.length; j++) {
5944
+ const line = lines[j];
5945
+ const isHeader = headerRe.test(line);
5946
+ const isImportant = importantRe.test(line);
5947
+ const isShortListItem = listItemRe.test(line) && line.length < 120;
5948
+ if (isHeader || isImportant || isShortListItem) {
5949
+ if (charCount + line.length + 1 > maxChars) break;
5950
+ kept.push(line);
5951
+ charCount += line.length + 1;
5952
+ }
5953
+ }
5954
+ kept.push("", "[Verbose instructions trimmed after turn " + turnThreshold + ". Key constraints preserved above.]");
5955
+ return kept.join("\n");
5956
+ }
5957
+
5958
+ function compactToolDescription(text) {
5959
+ return text
5960
+ .replace(/<example[\s\S]*?<\/example>/gi, "")
5961
+ .replace(/\|[\s|:-]+\|/g, "")
5962
+ .replace(/^\|.*\|$/gm, "")
5963
+ .replace(/^(?:\s*[-*]\s+.{200,})$/gm, (m) => m.slice(0, 200) + "...")
5964
+ .replace(/^(#{1,3}\s+)/gm, "")
5965
+ .replace(/\*\*([^*]+)\*\*/g, "$1")
5966
+ .replace(/`([^`]+)`/g, "$1")
5967
+ .replace(/\n{3,}/g, "\n\n")
5968
+ .trim();
5969
+ }
5970
+
5886
5971
  function compactSystemText(text, mode) {
5887
5972
  const withoutDuplicateIdentityPrefix = text.startsWith(`${CLAUDE_CODE_IDENTITY_STRING}\n`)
5888
5973
  ? text.slice(CLAUDE_CODE_IDENTITY_STRING.length).trimStart()
@@ -6386,6 +6471,14 @@ function buildAnthropicBetaHeader(
6386
6471
  betas.push("web-search-2025-03-05");
6387
6472
  }
6388
6473
 
6474
+ // Advisor tool — in CC this is gated by server-side feature flag
6475
+ // (tengu_sage_compass2) and firstParty+isLoggedIn. Since we can't check
6476
+ // CC's feature flags, include it unconditionally for Claude 4+ models.
6477
+ // CC v108 sends it in MITM captures for Max/Pro users.
6478
+ if (!/claude-3-/i.test(model)) {
6479
+ betas.push("advisor-tool-2026-03-01");
6480
+ }
6481
+
6389
6482
  // Files API — scoped to file endpoints/references
6390
6483
  if (isFilesEndpoint || hasFileReferences) {
6391
6484
  betas.push("files-api-2025-04-14");
@@ -6396,16 +6489,15 @@ function buildAnthropicBetaHeader(
6396
6489
  betas.push(TOKEN_COUNTING_BETA_FLAG);
6397
6490
  }
6398
6491
 
6399
- // === TOKEN ECONOMY BETAS (config-controlled) ===
6492
+ // === TOKEN ECONOMY BETAS (on by default for token savings) ===
6400
6493
 
6401
6494
  // redact-thinking: suppresses thinking summaries server-side.
6402
- // When enabled, API returns redacted_thinking blocks instead of summaries.
6403
- // Saves bandwidth and tokens for users who don't inspect thinking.
6495
+ // CC v108 enables this by default but we keep it off so thinking is visible.
6496
+ // Users can opt in via `/anthropic set redact-thinking on`.
6404
6497
  if (te.redact_thinking && !disableExperimentalBetas) {
6405
6498
  betas.push("redact-thinking-2026-02-12");
6406
6499
  }
6407
6500
 
6408
- // summarize-connector-text-2026-03-13 was removed in v2.1.90 (dead slot njq="").
6409
6501
  // compact-2026-01-12 and mcp-client-2025-11-20 exist only in docs, not runtime.
6410
6502
 
6411
6503
  // afk-mode — NOT auto-included (requires user opt-in)
@@ -6418,8 +6510,11 @@ function buildAnthropicBetaHeader(
6418
6510
  }
6419
6511
  }
6420
6512
 
6421
- // Merge incoming betas from the original request
6422
- let mergedBetas = [...new Set([...betas, ...incomingBetasList])];
6513
+ // Merge incoming betas from the original request, filtering out host-injected
6514
+ // betas (e.g. fine-grained-tool-streaming-2025-05-14, structured-outputs-2025-11-13)
6515
+ // that OpenCode's Anthropic SDK adds but real Claude Code never sends.
6516
+ const filteredIncoming = incomingBetasList.filter((b) => !HOST_SDK_BETAS_BLOCKLIST.has(b));
6517
+ let mergedBetas = [...new Set([...betas, ...filteredIncoming])];
6423
6518
 
6424
6519
  // Add custom betas from config
6425
6520
  if (customBetas?.length) {
@@ -6713,7 +6808,7 @@ function resolveMaxTokens(body, config) {
6713
6808
  *
6714
6809
  * @param {string | undefined} body
6715
6810
  * @param {{enabled: boolean, claudeCliVersion: string, promptCompactionMode: 'minimal' | 'off', provider?: string}} signature
6716
- * @param {{persistentUserId: string, sessionId: string, accountId: string}} runtime
6811
+ * @param {{persistentUserId: string, sessionId: string, accountId: string, turns?: number, usedTools?: Set<string>}} runtime
6717
6812
  * @param {string} [betaHeader] - Pre-computed anthropic-beta header value to inject into the body.
6718
6813
  * @param {import('./lib/config.mjs').AnthropicAuthConfig} [config] - Plugin configuration for output cap
6719
6814
  * @returns {string | undefined}
@@ -6813,6 +6908,22 @@ function transformRequestBody(body, signature, runtime, betaHeader, config) {
6813
6908
  // Sanitize system prompt and optionally inject Claude Code identity/billing blocks.
6814
6909
  parsed.system = buildSystemPromptBlocks(normalizeSystemTextBlocks(parsed.system), signatureWithModel);
6815
6910
 
6911
+ // Strategy 5 — System prompt tailing: after N turns, trim large system blocks
6912
+ // to essential sections only. The model has internalized verbose instructions
6913
+ // (shell strategy, package manager tables, delegation protocols) by this point.
6914
+ // Preserves: first paragraph (identity/role), lines containing MUST/NEVER/CRITICAL/
6915
+ // IMPORTANT, section headers, and short blocks. Drops verbose body paragraphs.
6916
+ const tailThreshold = signature.systemPromptTailTurns ?? 6;
6917
+ if (signature.systemPromptTailing !== false && runtime.turns >= tailThreshold && Array.isArray(parsed.system)) {
6918
+ const maxChars = signature.systemPromptTailMaxChars ?? 2000;
6919
+ for (let i = 0; i < parsed.system.length; i++) {
6920
+ const block = parsed.system[i];
6921
+ if (block.type === "text" && block.text && block.text.length > maxChars * 2) {
6922
+ block.text = tailSystemBlock(block.text, maxChars, tailThreshold);
6923
+ }
6924
+ }
6925
+ }
6926
+
6816
6927
  // Token budget (A9): parse NL budget from last user message, inject status block
6817
6928
  if (config?.token_budget?.enabled && Array.isArray(parsed.messages)) {
6818
6929
  const budgetExpr = parseNaturalLanguageBudget(parsed.messages);
@@ -6864,10 +6975,12 @@ function transformRequestBody(body, signature, runtime, betaHeader, config) {
6864
6975
  // our system prompt ttl=1h). Then add our own 1h to the last user message
6865
6976
  // (matching real CC behavior seen in proxy capture).
6866
6977
  const ccTtl = signature.cachePolicy?.ttl || "1h";
6867
- if (Array.isArray(parsed.tools)) {
6978
+ if (Array.isArray(parsed.tools) && parsed.tools.length > 0) {
6868
6979
  for (const tool of parsed.tools) {
6869
6980
  if (tool.cache_control) delete tool.cache_control;
6870
6981
  }
6982
+ // Add cache_control to last tool as prompt-cache breakpoint (CC does this)
6983
+ parsed.tools[parsed.tools.length - 1].cache_control = { type: "ephemeral", ttl: ccTtl };
6871
6984
  }
6872
6985
  if (Array.isArray(parsed.messages)) {
6873
6986
  for (const msg of parsed.messages) {
@@ -6925,6 +7038,69 @@ function transformRequestBody(body, signature, runtime, betaHeader, config) {
6925
7038
  }
6926
7039
  }
6927
7040
  }
7041
+ // Track which tools the model has used (from assistant tool_use blocks).
7042
+ // Names are already CC PascalCase after renaming above.
7043
+ if (Array.isArray(parsed.messages)) {
7044
+ for (const msg of parsed.messages) {
7045
+ if (msg.role === "assistant" && Array.isArray(msg.content)) {
7046
+ for (const block of msg.content) {
7047
+ if (block.type === "tool_use" && block.name) {
7048
+ runtime.usedTools.add(block.name);
7049
+ }
7050
+ }
7051
+ }
7052
+ }
7053
+ }
7054
+
7055
+ // Strategy 4 — Adaptive tool set: after turn 3, defer non-core tools that
7056
+ // the model hasn't used yet. This saves schema bytes on turns where tools
7057
+ // are unlikely to be needed. Core tools stay eager. Resets on /clear.
7058
+ if (
7059
+ Array.isArray(parsed.tools) &&
7060
+ signature.adaptiveToolSet !== false &&
7061
+ runtime.turns >= 3 &&
7062
+ parsed.model &&
7063
+ !/claude-3-|haiku/i.test(parsed.model)
7064
+ ) {
7065
+ const used = runtime.usedTools;
7066
+ for (const tool of parsed.tools) {
7067
+ if (tool.name && !used.has(tool.name) && !CORE_TOOL_NAMES.has(tool.name)) {
7068
+ tool.defer_loading = true;
7069
+ }
7070
+ }
7071
+ }
7072
+
7073
+ // Tool description compaction: apply the same compaction logic used for
7074
+ // system prompts (strip examples, collapse whitespace, dedup lines) to tool
7075
+ // descriptions. The top 4 tools (Bash 10.6K, TodoWrite 9.7K, Task 5.5K,
7076
+ // Compress 4.5K) account for 30KB. Compaction typically saves 30-50%.
7077
+ if (Array.isArray(parsed.tools) && signature.toolDescriptionCompaction !== false) {
7078
+ for (const tool of parsed.tools) {
7079
+ if (tool.description && tool.description.length > 500) {
7080
+ tool.description = compactToolDescription(tool.description);
7081
+ }
7082
+ }
7083
+ }
7084
+
7085
+ // MCP tool deferral: mark non-core tools with defer_loading: true.
7086
+ // CC defers all MCP tools by default — the API omits their full schemas from token
7087
+ // counting, only sending the tool name. When the model needs a deferred tool, it uses
7088
+ // tool_reference to load the schema on demand. This saves ~20KB per turn.
7089
+ // Core tools (OC_TO_CC_TOOL_NAMES) are always eager-loaded.
7090
+ if (
7091
+ Array.isArray(parsed.tools) &&
7092
+ signature.toolDeferral !== false &&
7093
+ parsed.model &&
7094
+ !/claude-3-|haiku/i.test(parsed.model)
7095
+ ) {
7096
+ const coreToolNames = new Set(Object.values(OC_TO_CC_TOOL_NAMES));
7097
+ for (const tool of parsed.tools) {
7098
+ if (tool.name && !coreToolNames.has(tool.name)) {
7099
+ tool.defer_loading = true;
7100
+ }
7101
+ }
7102
+ }
7103
+
6928
7104
  // Task budgets: when the task-budgets beta is active, preserve or inject output_config.
6929
7105
  // The beta unlocks output_config.max_output_tokens for per-task budget control.
6930
7106
  // Model-router compatibility: the beta header + output_config body are forwarded as-is.
@@ -7019,6 +7195,22 @@ function transformRequestUrl(input) {
7019
7195
  }
7020
7196
  }
7021
7197
 
7198
+ // MITM proxy redirect: rewrite host/port/protocol when OPENCODE_MITM_BASE_URL is set.
7199
+ // This allows capturing the exact over-the-wire request for conformance testing.
7200
+ // Example: OPENCODE_MITM_BASE_URL=http://localhost:9999
7201
+ const mitmBase = process.env.OPENCODE_MITM_BASE_URL;
7202
+ if (mitmBase && requestUrl) {
7203
+ try {
7204
+ const mitmUrl = new URL(mitmBase);
7205
+ requestUrl.protocol = mitmUrl.protocol;
7206
+ requestUrl.hostname = mitmUrl.hostname;
7207
+ requestUrl.port = mitmUrl.port;
7208
+ requestInput = input instanceof Request ? new Request(requestUrl.toString(), input) : requestUrl;
7209
+ } catch {
7210
+ // Invalid MITM URL — ignore silently
7211
+ }
7212
+ }
7213
+
7022
7214
  return { requestInput, requestUrl };
7023
7215
  }
7024
7216
 
@@ -7189,10 +7381,10 @@ function stripMcpPrefixFromParsedEvent(parsed) {
7189
7381
 
7190
7382
  let modified = false;
7191
7383
 
7192
- // content_block_start: { content_block: { type: "tool_use", name: "..." } }
7384
+ // content_block_start: { content_block: { type: "tool_use"|"tool_reference", name: "..." } }
7193
7385
  if (
7194
7386
  parsed.content_block &&
7195
- parsed.content_block.type === "tool_use" &&
7387
+ (parsed.content_block.type === "tool_use" || parsed.content_block.type === "tool_reference") &&
7196
7388
  typeof parsed.content_block.name === "string"
7197
7389
  ) {
7198
7390
  const mapped = reverseMapToolName(parsed.content_block.name);
@@ -7202,10 +7394,10 @@ function stripMcpPrefixFromParsedEvent(parsed) {
7202
7394
  }
7203
7395
  }
7204
7396
 
7205
- // message_start: { message: { content: [{ type: "tool_use", name: "..." }] } }
7397
+ // message_start: { message: { content: [{ type: "tool_use"|"tool_reference", name: "..." }] } }
7206
7398
  if (parsed.message && Array.isArray(parsed.message.content)) {
7207
7399
  for (const block of parsed.message.content) {
7208
- if (block.type === "tool_use" && typeof block.name === "string") {
7400
+ if ((block.type === "tool_use" || block.type === "tool_reference") && typeof block.name === "string") {
7209
7401
  const mapped = reverseMapToolName(block.name);
7210
7402
  if (mapped !== block.name) {
7211
7403
  block.name = mapped;
@@ -7218,7 +7410,7 @@ function stripMcpPrefixFromParsedEvent(parsed) {
7218
7410
  // Top-level content array (non-streaming responses forwarded through SSE)
7219
7411
  if (Array.isArray(parsed.content)) {
7220
7412
  for (const block of parsed.content) {
7221
- if (block.type === "tool_use" && typeof block.name === "string") {
7413
+ if ((block.type === "tool_use" || block.type === "tool_reference") && typeof block.name === "string") {
7222
7414
  const mapped = reverseMapToolName(block.name);
7223
7415
  if (mapped !== block.name) {
7224
7416
  block.name = mapped;
@@ -7674,9 +7866,12 @@ function extractFileIds(body) {
7674
7866
  AnthropicAuthPlugin.__testing__ = {
7675
7867
  sanitizeSystemText,
7676
7868
  compactSystemText,
7869
+ compactToolDescription,
7677
7870
  dedupeSystemBlocks,
7678
7871
  normalizeSystemTextBlocks,
7679
7872
  buildSystemPromptBlocks,
7873
+ stripMcpPrefixFromParsedEvent,
7874
+ CORE_TOOL_NAMES,
7680
7875
  get cachedCCPrompt() {
7681
7876
  return cachedCCPrompt;
7682
7877
  },
package/lib/config.mjs CHANGED
@@ -190,12 +190,9 @@ export const DEFAULT_CONFIG = {
190
190
  * This flag is retained for config backward compatibility but has no effect. */
191
191
  token_efficient_tools: false,
192
192
  /** Enable redact-thinking-2026-02-12 beta (suppresses thinking summaries
193
- * server-side for lower bandwidth). Off by default u2014 set to true if you
194
- * don't need to inspect thinking blocks. */
193
+ * server-side for lower bandwidth). Off by default so thinking stays
194
+ * visible. Opt in via `/anthropic set redact-thinking on`. */
195
195
  redact_thinking: false,
196
- /** [DEPRECATED] summarize-connector-text-2026-03-13 was removed in CC v2.1.90.
197
- * This flag is retained for config backward compatibility but has no effect. */
198
- connector_text_summarization: false,
199
196
  },
200
197
  /** Output cap: default max_tokens to save context window. */
201
198
  output_cap: {
@@ -577,10 +574,6 @@ function validateConfig(raw) {
577
574
  : DEFAULT_CONFIG.token_economy.token_efficient_tools,
578
575
  redact_thinking:
579
576
  typeof te.redact_thinking === "boolean" ? te.redact_thinking : DEFAULT_CONFIG.token_economy.redact_thinking,
580
- connector_text_summarization:
581
- typeof te.connector_text_summarization === "boolean"
582
- ? te.connector_text_summarization
583
- : DEFAULT_CONFIG.token_economy.connector_text_summarization,
584
577
  };
585
578
  }
586
579
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-anthropic-fix",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "license": "GPL-3.0-or-later",
5
5
  "main": "./index.mjs",
6
6
  "files": [