@xtruder/opencode-claude-max-plugin 0.2.2 → 0.2.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAiGjD,MAAM,WAAW,2BAA2B;IAC1C;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEhC;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IAE/B;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IAExB;;OAEG;IACH,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAAA;CAChD;AA4BD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,GAAE,2BAAgC,GACxC,oBAAoB,CAkItB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAoBhC,CAAA;AAID,eAAe,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAsJjD,MAAM,WAAW,2BAA2B;IAC1C;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEhC;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IAE/B;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IAExB;;OAEG;IACH,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAAA;CAChD;AA4BD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,GAAE,2BAAgC,GACxC,oBAAoB,CA6GtB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAwBhC,CAAA;AAID,eAAe,kBAAkB,CAAA"}
package/build/index.js CHANGED
@@ -1,20 +1,33 @@
1
- // src/usage.ts
2
- import {
3
- closeSync,
4
- constants as fsConstants,
5
- mkdirSync,
6
- openSync,
7
- readFileSync as readFileSync2,
8
- renameSync,
9
- unlinkSync,
10
- writeFileSync
11
- } from "node:fs";
12
- import { homedir as homedir2 } from "node:os";
13
- import { join as join2 } from "node:path";
1
+ // src/index.ts
2
+ import Anthropic from "@anthropic-ai/sdk";
3
+
4
+ // src/cch.ts
5
+ import xxhashInit from "xxhash-wasm";
6
+ var CCH_SEED = 0x6e52736ac806831en;
7
+ var CCH_PLACEHOLDER = "cch=00000";
8
+ var CCH_MASK = 0xfffffn;
9
+ var hasherPromise = null;
10
+ function getHasher() {
11
+ if (!hasherPromise) {
12
+ hasherPromise = xxhashInit();
13
+ }
14
+ return hasherPromise;
15
+ }
16
+ async function computeCch(body) {
17
+ const hasher = await getHasher();
18
+ const hash = hasher.h64Raw(new TextEncoder().encode(body), CCH_SEED);
19
+ return (hash & CCH_MASK).toString(16).padStart(5, "0");
20
+ }
21
+ function replaceCchPlaceholder(body, cch) {
22
+ return body.replace(CCH_PLACEHOLDER, `cch=${cch}`);
23
+ }
24
+ function hasCchPlaceholder(body) {
25
+ return body.includes(CCH_PLACEHOLDER);
26
+ }
14
27
 
15
28
  // src/credentials.ts
16
- import { existsSync, readFileSync } from "node:fs";
17
29
  import { execSync } from "node:child_process";
30
+ import { existsSync, readFileSync } from "node:fs";
18
31
  import { homedir } from "node:os";
19
32
  import { join } from "node:path";
20
33
  var CREDENTIAL_CACHE_TTL_MS = 30000;
@@ -93,121 +106,14 @@ function getCachedCredentials(path) {
93
106
  return cachedCreds;
94
107
  }
95
108
 
96
- // src/usage.ts
97
- var cachedUsage = {};
98
- var XDG_STATE = process.env.XDG_STATE_HOME || join2(homedir2(), ".local", "state");
99
- var USAGE_CACHE_DIR = join2(XDG_STATE, "opencode");
100
- var USAGE_CACHE_FILE = join2(USAGE_CACHE_DIR, "usage-cache.json");
101
- function emptyCache() {
102
- return { api: null, headers: null, updatedAt: 0, apiFetchedAt: 0, apiRateLimitUntil: 0 };
103
- }
104
- var USAGE_LOCK_FILE = USAGE_CACHE_FILE + ".lock";
105
- var USAGE_TMP_FILE = USAGE_CACHE_FILE + ".tmp";
106
- var LOCK_STALE_MS = 5000;
107
- function acquireLock() {
108
- try {
109
- mkdirSync(USAGE_CACHE_DIR, { recursive: true });
110
- const fd = openSync(USAGE_LOCK_FILE, fsConstants.O_CREAT | fsConstants.O_EXCL | fsConstants.O_WRONLY);
111
- writeFileSync(fd, `${process.pid}
112
- ${Date.now()}`);
113
- closeSync(fd);
114
- return true;
115
- } catch (err) {
116
- if (err?.code !== "EEXIST")
117
- return false;
118
- try {
119
- const text = readFileSync2(USAGE_LOCK_FILE, "utf-8");
120
- const ts = parseInt(text.split(`
121
- `)[1] ?? "0");
122
- if (Date.now() - ts > LOCK_STALE_MS) {
123
- unlinkSync(USAGE_LOCK_FILE);
124
- return acquireLock();
125
- }
126
- } catch {
127
- try {
128
- unlinkSync(USAGE_LOCK_FILE);
129
- } catch {}
130
- return acquireLock();
131
- }
132
- return false;
133
- }
134
- }
135
- function releaseLock() {
136
- try {
137
- unlinkSync(USAGE_LOCK_FILE);
138
- } catch {}
139
- }
140
- function readUsageCache() {
141
- try {
142
- const text = readFileSync2(USAGE_CACHE_FILE, "utf-8");
143
- const data = JSON.parse(text);
144
- if (data && typeof data.updatedAt === "number")
145
- return data;
146
- } catch {}
147
- return emptyCache();
148
- }
149
- function writeUsageCache(update) {
150
- if (!acquireLock())
151
- return;
152
- try {
153
- const existing = readUsageCache();
154
- const merged = {
155
- ...existing,
156
- ...update,
157
- updatedAt: Date.now()
158
- };
159
- mkdirSync(USAGE_CACHE_DIR, { recursive: true });
160
- writeFileSync(USAGE_TMP_FILE, JSON.stringify(merged));
161
- renameSync(USAGE_TMP_FILE, USAGE_CACHE_FILE);
162
- } catch {
163
- try {
164
- unlinkSync(USAGE_TMP_FILE);
165
- } catch {}
166
- } finally {
167
- releaseLock();
168
- }
169
- }
170
- function persistCachedUsage() {
171
- if (cachedUsage.fiveHourUtil == null && cachedUsage.sevenDayUtil == null)
172
- return;
173
- writeUsageCache({ headers: { ...cachedUsage } });
174
- }
175
- var API_TTL_MS = 5 * 60000;
176
-
177
- // src/cch.ts
178
- import xxhashInit from "xxhash-wasm";
179
- var CCH_SEED = 0x6e52736ac806831en;
180
- var CCH_PLACEHOLDER = "cch=00000";
181
- var CCH_MASK = 0xfffffn;
182
- var hasherPromise = null;
183
- function getHasher() {
184
- if (!hasherPromise) {
185
- hasherPromise = xxhashInit();
186
- }
187
- return hasherPromise;
188
- }
189
- async function computeCch(body) {
190
- const hasher = await getHasher();
191
- const hash = hasher.h64Raw(new TextEncoder().encode(body), CCH_SEED);
192
- return (hash & CCH_MASK).toString(16).padStart(5, "0");
193
- }
194
- function replaceCchPlaceholder(body, cch) {
195
- return body.replace(CCH_PLACEHOLDER, `cch=${cch}`);
196
- }
197
- function hasCchPlaceholder(body) {
198
- return body.includes(CCH_PLACEHOLDER);
199
- }
200
-
201
- // src/index.ts
202
- import Anthropic from "@anthropic-ai/sdk";
203
-
204
109
  // src/model.ts
205
110
  import { APIError, RateLimitError } from "@anthropic-ai/sdk";
111
+ import { createHash, randomBytes } from "node:crypto";
206
112
 
207
113
  // src/tool-names.ts
208
- import { existsSync as existsSync2, readFileSync as readFileSync3 } from "node:fs";
209
- import { homedir as homedir3 } from "node:os";
210
- import { join as join3 } from "node:path";
114
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
115
+ import { homedir as homedir2 } from "node:os";
116
+ import { join as join2 } from "node:path";
211
117
  var BUILTIN_OPENCODE_TO_CLAUDE = {
212
118
  task: "Agent",
213
119
  question: "AskUserQuestion",
@@ -239,15 +145,15 @@ var mcpServerNames = null;
239
145
  function detectMcpServers() {
240
146
  const servers = new Set;
241
147
  const paths = [
242
- join3(process.cwd(), ".opencode", "opencode.json"),
243
- join3(homedir3(), ".config", "opencode", "opencode.json"),
244
- join3(homedir3(), ".config", "opencode", "opencode.jsonc")
148
+ join2(process.cwd(), ".opencode", "opencode.json"),
149
+ join2(homedir2(), ".config", "opencode", "opencode.json"),
150
+ join2(homedir2(), ".config", "opencode", "opencode.jsonc")
245
151
  ];
246
152
  for (const p of paths) {
247
153
  try {
248
154
  if (!existsSync2(p))
249
155
  continue;
250
- let raw = readFileSync3(p, "utf-8");
156
+ let raw = readFileSync2(p, "utf-8");
251
157
  raw = raw.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
252
158
  const config = JSON.parse(raw);
253
159
  if (config.mcp && typeof config.mcp === "object") {
@@ -333,50 +239,6 @@ function rewriteToolNamesInText(text) {
333
239
  return result;
334
240
  }
335
241
 
336
- // src/tools.ts
337
- function cleanSchema(schema) {
338
- const cleaned = {};
339
- for (const [key, value] of Object.entries(schema)) {
340
- if (key === "custom")
341
- continue;
342
- if (value && typeof value === "object" && !Array.isArray(value)) {
343
- cleaned[key] = cleanSchema(value);
344
- } else {
345
- cleaned[key] = value;
346
- }
347
- }
348
- if (cleaned.properties && !cleaned.type) {
349
- cleaned.type = "object";
350
- }
351
- return cleaned;
352
- }
353
- function convertTools(tools) {
354
- if (!tools || tools.length === 0)
355
- return;
356
- return tools.filter((t) => t.type === "function").map((tool) => ({
357
- name: toClaudeToolName(tool.name),
358
- description: tool.description ?? "",
359
- input_schema: cleanSchema(tool.inputSchema)
360
- }));
361
- }
362
- function convertToolChoice(toolChoice) {
363
- if (!toolChoice)
364
- return;
365
- switch (toolChoice.type) {
366
- case "auto":
367
- return { type: "auto" };
368
- case "required":
369
- return { type: "any" };
370
- case "none":
371
- return;
372
- case "tool":
373
- return { type: "tool", name: toClaudeToolName(toolChoice.toolName) };
374
- }
375
- }
376
-
377
- // src/model.ts
378
- import { createHash, randomBytes } from "node:crypto";
379
-
380
242
  // src/prompt.ts
381
243
  function convertPrompt(prompt) {
382
244
  const systemParts = [];
@@ -566,8 +428,8 @@ function convertStream(anthropicStream, modelId) {
566
428
  finishReason,
567
429
  usage: {
568
430
  inputTokens: {
569
- total: inputTokens ?? 0,
570
- noCache: undefined,
431
+ total: (inputTokens ?? 0) + (cachedInputTokens ?? 0) + (cacheCreationTokens ?? 0),
432
+ noCache: inputTokens ?? 0,
571
433
  cacheRead: cachedInputTokens ?? 0,
572
434
  cacheWrite: cacheCreationTokens ?? 0
573
435
  },
@@ -698,6 +560,47 @@ function processEvent(event, blockStates, modelId) {
698
560
  return parts;
699
561
  }
700
562
 
563
+ // src/tools.ts
564
+ function cleanSchema(schema) {
565
+ const cleaned = {};
566
+ for (const [key, value] of Object.entries(schema)) {
567
+ if (key === "custom")
568
+ continue;
569
+ if (value && typeof value === "object" && !Array.isArray(value)) {
570
+ cleaned[key] = cleanSchema(value);
571
+ } else {
572
+ cleaned[key] = value;
573
+ }
574
+ }
575
+ if (cleaned.properties && !cleaned.type) {
576
+ cleaned.type = "object";
577
+ }
578
+ return cleaned;
579
+ }
580
+ function convertTools(tools) {
581
+ if (!tools || tools.length === 0)
582
+ return;
583
+ return tools.filter((t) => t.type === "function").map((tool) => ({
584
+ name: toClaudeToolName(tool.name),
585
+ description: tool.description ?? "",
586
+ input_schema: cleanSchema(tool.inputSchema)
587
+ }));
588
+ }
589
+ function convertToolChoice(toolChoice) {
590
+ if (!toolChoice)
591
+ return;
592
+ switch (toolChoice.type) {
593
+ case "auto":
594
+ return { type: "auto" };
595
+ case "required":
596
+ return { type: "any" };
597
+ case "none":
598
+ return;
599
+ case "tool":
600
+ return { type: "tool", name: toClaudeToolName(toolChoice.toolName) };
601
+ }
602
+ }
603
+
701
604
  // src/model.ts
702
605
  function handleApiError(error) {
703
606
  if (error instanceof RateLimitError || error instanceof APIError && error.status === 429) {
@@ -748,6 +651,9 @@ function buildMetadata() {
748
651
  user_id: JSON.stringify({ device_id: DEVICE_ID })
749
652
  };
750
653
  }
654
+ function supportsContextManagement(apiModelId) {
655
+ return !apiModelId.includes("claude-3-");
656
+ }
751
657
 
752
658
  class AnthropicSDKModel {
753
659
  client;
@@ -757,12 +663,16 @@ class AnthropicSDKModel {
757
663
  provider;
758
664
  modelId;
759
665
  supportedUrls = {};
666
+ apiModelId;
667
+ is1MContext;
760
668
  constructor(modelId, client, providerName, isOAuth = false) {
761
669
  this.client = client;
762
670
  this.providerName = providerName;
763
671
  this.isOAuth = isOAuth;
764
672
  this.modelId = modelId;
765
673
  this.provider = providerName;
674
+ this.is1MContext = modelId.endsWith("-1m");
675
+ this.apiModelId = this.is1MContext ? modelId.replace(/-1m$/, "") : modelId;
766
676
  }
767
677
  buildParams(options) {
768
678
  const { system, messages } = convertPrompt(options.prompt);
@@ -779,7 +689,7 @@ class AnthropicSDKModel {
779
689
  const tools = options.toolChoice?.type === "none" ? undefined : convertTools(options.tools);
780
690
  const toolChoice = options.toolChoice?.type === "none" ? undefined : convertToolChoice(options.toolChoice);
781
691
  const params = {
782
- model: this.modelId,
692
+ model: this.apiModelId,
783
693
  max_tokens: options.maxOutputTokens ?? 64000,
784
694
  messages
785
695
  };
@@ -797,7 +707,7 @@ class AnthropicSDKModel {
797
707
  params.system = [BILLING_SYSTEM_BLOCK, IDENTITY_SYSTEM_BLOCK];
798
708
  }
799
709
  params.metadata = buildMetadata();
800
- const supportsEffort = !this.modelId.includes("haiku") && !this.modelId.includes("claude-3-");
710
+ const supportsEffort = !this.apiModelId.includes("haiku") && !this.apiModelId.includes("claude-3-");
801
711
  if (supportsEffort) {
802
712
  if (options.temperature == null) {
803
713
  params.temperature = 1;
@@ -885,8 +795,27 @@ class AnthropicSDKModel {
885
795
  if (anthropicOptions.metadata)
886
796
  params.metadata = anthropicOptions.metadata;
887
797
  }
798
+ if (this.isOAuth && supportsContextManagement(this.apiModelId)) {
799
+ const edits = [];
800
+ const hasThinking = params.thinking?.type === "enabled";
801
+ if (hasThinking) {
802
+ edits.push({
803
+ type: "clear_thinking_20251015",
804
+ keep: "all"
805
+ });
806
+ }
807
+ if (edits.length > 0) {
808
+ params.context_management = { edits };
809
+ }
810
+ }
888
811
  return { params, warnings };
889
812
  }
813
+ buildRequestOptions(signal) {
814
+ const opts = {};
815
+ if (signal)
816
+ opts.signal = signal;
817
+ return opts;
818
+ }
890
819
  async doGenerate(options) {
891
820
  const { params, warnings } = this.buildParams(options);
892
821
  if (!options.maxOutputTokens && params.max_tokens > 4096) {
@@ -897,7 +826,7 @@ class AnthropicSDKModel {
897
826
  response = await this.client.messages.create({
898
827
  ...params,
899
828
  stream: false
900
- }, { signal: options.abortSignal });
829
+ }, this.buildRequestOptions(options.abortSignal));
901
830
  } catch (error) {
902
831
  handleApiError(error);
903
832
  }
@@ -935,8 +864,8 @@ class AnthropicSDKModel {
935
864
  finishReason: mapFinishReason2(response.stop_reason),
936
865
  usage: {
937
866
  inputTokens: {
938
- total: response.usage.input_tokens,
939
- noCache: undefined,
867
+ total: response.usage.input_tokens + cacheReadTokens + cacheCreateTokens,
868
+ noCache: response.usage.input_tokens,
940
869
  cacheRead: cacheReadTokens,
941
870
  cacheWrite: cacheCreateTokens
942
871
  },
@@ -966,7 +895,7 @@ class AnthropicSDKModel {
966
895
  anthropicStream = await this.client.messages.create({
967
896
  ...params,
968
897
  stream: true
969
- }, { signal: options.abortSignal });
898
+ }, this.buildRequestOptions(options.abortSignal));
970
899
  } catch (error) {
971
900
  if (error instanceof APIError && error.status === 400 && error.message?.includes("must end with a user message")) {
972
901
  return {
@@ -1022,6 +951,99 @@ class AnthropicSDKModel {
1022
951
  }
1023
952
  }
1024
953
 
954
+ // src/usage.ts
955
+ import {
956
+ closeSync,
957
+ constants as fsConstants,
958
+ mkdirSync,
959
+ openSync,
960
+ readFileSync as readFileSync3,
961
+ renameSync,
962
+ unlinkSync,
963
+ writeFileSync
964
+ } from "node:fs";
965
+ import { homedir as homedir3 } from "node:os";
966
+ import { join as join3 } from "node:path";
967
+ var cachedUsage = {};
968
+ var XDG_STATE = process.env.XDG_STATE_HOME || join3(homedir3(), ".local", "state");
969
+ var USAGE_CACHE_DIR = join3(XDG_STATE, "opencode");
970
+ var USAGE_CACHE_FILE = join3(USAGE_CACHE_DIR, "usage-cache.json");
971
+ function emptyCache() {
972
+ return { api: null, headers: null, updatedAt: 0, apiFetchedAt: 0, apiRateLimitUntil: 0 };
973
+ }
974
+ var USAGE_LOCK_FILE = USAGE_CACHE_FILE + ".lock";
975
+ var USAGE_TMP_FILE = USAGE_CACHE_FILE + ".tmp";
976
+ var LOCK_STALE_MS = 5000;
977
+ function acquireLock() {
978
+ try {
979
+ mkdirSync(USAGE_CACHE_DIR, { recursive: true });
980
+ const fd = openSync(USAGE_LOCK_FILE, fsConstants.O_CREAT | fsConstants.O_EXCL | fsConstants.O_WRONLY);
981
+ writeFileSync(fd, `${process.pid}
982
+ ${Date.now()}`);
983
+ closeSync(fd);
984
+ return true;
985
+ } catch (err) {
986
+ if (err?.code !== "EEXIST")
987
+ return false;
988
+ try {
989
+ const text = readFileSync3(USAGE_LOCK_FILE, "utf-8");
990
+ const ts = parseInt(text.split(`
991
+ `)[1] ?? "0");
992
+ if (Date.now() - ts > LOCK_STALE_MS) {
993
+ unlinkSync(USAGE_LOCK_FILE);
994
+ return acquireLock();
995
+ }
996
+ } catch {
997
+ try {
998
+ unlinkSync(USAGE_LOCK_FILE);
999
+ } catch {}
1000
+ return acquireLock();
1001
+ }
1002
+ return false;
1003
+ }
1004
+ }
1005
+ function releaseLock() {
1006
+ try {
1007
+ unlinkSync(USAGE_LOCK_FILE);
1008
+ } catch {}
1009
+ }
1010
+ function readUsageCache() {
1011
+ try {
1012
+ const text = readFileSync3(USAGE_CACHE_FILE, "utf-8");
1013
+ const data = JSON.parse(text);
1014
+ if (data && typeof data.updatedAt === "number")
1015
+ return data;
1016
+ } catch {}
1017
+ return emptyCache();
1018
+ }
1019
+ function writeUsageCache(update) {
1020
+ if (!acquireLock())
1021
+ return;
1022
+ try {
1023
+ const existing = readUsageCache();
1024
+ const merged = {
1025
+ ...existing,
1026
+ ...update,
1027
+ updatedAt: Date.now()
1028
+ };
1029
+ mkdirSync(USAGE_CACHE_DIR, { recursive: true });
1030
+ writeFileSync(USAGE_TMP_FILE, JSON.stringify(merged));
1031
+ renameSync(USAGE_TMP_FILE, USAGE_CACHE_FILE);
1032
+ } catch {
1033
+ try {
1034
+ unlinkSync(USAGE_TMP_FILE);
1035
+ } catch {}
1036
+ } finally {
1037
+ releaseLock();
1038
+ }
1039
+ }
1040
+ function persistCachedUsage() {
1041
+ if (cachedUsage.fiveHourUtil == null && cachedUsage.sevenDayUtil == null)
1042
+ return;
1043
+ writeUsageCache({ headers: { ...cachedUsage } });
1044
+ }
1045
+ var API_TTL_MS = 5 * 60000;
1046
+
1025
1047
  // src/index.ts
1026
1048
  var CLAUDE_CODE_VERSION = "2.1.81";
1027
1049
  var OAUTH_BETAS = [
@@ -1032,63 +1054,90 @@ var OAUTH_BETAS = [
1032
1054
  "prompt-caching-scope-2026-01-05",
1033
1055
  "effort-2025-11-24"
1034
1056
  ];
1035
- var CONTEXT_1M_BETA = "context-1m-2025-08-07";
1036
1057
  var API_KEY_BETAS = ["interleaved-thinking-2025-05-14", "fine-grained-tool-streaming-2025-05-14"];
1037
1058
  var PACKAGE_NAME = "@xtruder/opencode-claude-max-plugin";
1038
1059
  var PROVIDER_ID = "anthropic-sdk";
1039
- var PLUGIN_MODELS = {
1040
- "claude-haiku-4-5": {
1041
- name: "Claude Haiku 4.5",
1042
- reasoning: false,
1043
- tool_call: true,
1044
- attachment: true,
1045
- temperature: true,
1046
- limit: { context: 200000, output: 8192 },
1047
- cost: { input: 0.8, output: 4, cache_read: 0.08, cache_write: 1 },
1048
- modalities: {
1049
- input: ["text", "image"],
1050
- output: ["text"]
1051
- }
1052
- },
1053
- "claude-sonnet-4-6": {
1054
- name: "Claude Sonnet 4.6",
1055
- reasoning: true,
1056
- tool_call: true,
1057
- attachment: true,
1058
- temperature: true,
1059
- limit: { context: 200000, output: 16000 },
1060
- cost: { input: 3, output: 15, cache_read: 0.3, cache_write: 3.75 },
1061
- modalities: {
1062
- input: ["text", "image", "pdf"],
1063
- output: ["text"]
1064
- },
1065
- options: { effort: "medium" },
1060
+ var API_KEY_COSTS = {
1061
+ haiku: { input: 1, output: 5, cache_read: 0.1, cache_write: 1.25 },
1062
+ sonnet: { input: 3, output: 15, cache_read: 0.3, cache_write: 3.75 },
1063
+ opus: { input: 5, output: 25, cache_read: 0.5, cache_write: 6.25 }
1064
+ };
1065
+ var ZERO_COST = { input: 0, output: 0, cache_read: 0, cache_write: 0 };
1066
+ function buildPluginModels(isOAuth) {
1067
+ const cost = (tier) => isOAuth ? ZERO_COST : API_KEY_COSTS[tier];
1068
+ const opusVariants = {
1066
1069
  variants: {
1067
1070
  low: { effort: "low" },
1068
1071
  medium: { effort: "medium" },
1069
- high: { effort: "high" }
1072
+ high: { effort: "high" },
1073
+ max: { effort: "max" }
1070
1074
  }
1071
- },
1072
- "claude-opus-4-6": {
1073
- name: "Claude Opus 4.6",
1074
- reasoning: true,
1075
- tool_call: true,
1076
- attachment: true,
1077
- temperature: true,
1078
- limit: { context: 200000, output: 32000 },
1079
- cost: { input: 15, output: 75, cache_read: 1.5, cache_write: 18.75 },
1080
- modalities: {
1081
- input: ["text", "image", "pdf"],
1082
- output: ["text"]
1075
+ };
1076
+ return {
1077
+ "claude-haiku-4-5": {
1078
+ name: "Claude Haiku 4.5",
1079
+ reasoning: false,
1080
+ tool_call: true,
1081
+ attachment: true,
1082
+ temperature: true,
1083
+ limit: { context: 200000, output: 64000 },
1084
+ cost: cost("haiku"),
1085
+ modalities: {
1086
+ input: ["text", "image"],
1087
+ output: ["text"]
1088
+ }
1083
1089
  },
1084
- options: { effort: "medium" },
1085
- variants: {
1086
- low: { effort: "low" },
1087
- medium: { effort: "medium" },
1088
- high: { effort: "high" }
1090
+ "claude-sonnet-4-6": {
1091
+ name: "Claude Sonnet 4.6",
1092
+ reasoning: true,
1093
+ tool_call: true,
1094
+ attachment: true,
1095
+ temperature: true,
1096
+ limit: { context: 200000, output: 64000 },
1097
+ cost: cost("sonnet"),
1098
+ modalities: {
1099
+ input: ["text", "image", "pdf"],
1100
+ output: ["text"]
1101
+ },
1102
+ options: { effort: "medium" },
1103
+ variants: {
1104
+ low: { effort: "low" },
1105
+ medium: { effort: "medium" },
1106
+ high: { effort: "high" }
1107
+ }
1108
+ },
1109
+ "claude-opus-4-6": {
1110
+ name: "Claude Opus 4.6",
1111
+ reasoning: true,
1112
+ tool_call: true,
1113
+ attachment: true,
1114
+ temperature: true,
1115
+ limit: { context: 200000, output: 128000 },
1116
+ cost: cost("opus"),
1117
+ modalities: {
1118
+ input: ["text", "image", "pdf"],
1119
+ output: ["text"]
1120
+ },
1121
+ options: { effort: "medium" },
1122
+ ...opusVariants
1123
+ },
1124
+ "claude-opus-4-6-1m": {
1125
+ name: "Claude Opus 4.6 (1M)",
1126
+ reasoning: true,
1127
+ tool_call: true,
1128
+ attachment: true,
1129
+ temperature: true,
1130
+ limit: { context: 1e6, output: 128000 },
1131
+ cost: cost("opus"),
1132
+ modalities: {
1133
+ input: ["text", "image", "pdf"],
1134
+ output: ["text"]
1135
+ },
1136
+ options: { effort: "medium" },
1137
+ ...opusVariants
1089
1138
  }
1090
- }
1091
- };
1139
+ };
1140
+ }
1092
1141
  function resolveAuth(options) {
1093
1142
  if (options.apiKey) {
1094
1143
  return { apiKey: options.apiKey, isOAuth: false };
@@ -1117,7 +1166,6 @@ function createAnthropicSDK(options = {}) {
1117
1166
  defaultHeaders["anthropic-dangerous-direct-browser-access"] = "true";
1118
1167
  defaultHeaders["x-stainless-package-version"] = "0.74.0";
1119
1168
  }
1120
- const CONTEXT_1M_BODY_THRESHOLD = 600000;
1121
1169
  const baseFetch = customFetch ?? globalThis.fetch;
1122
1170
  const wrappedFetch = async (url, init) => {
1123
1171
  if (auth.isOAuth && init) {
@@ -1128,14 +1176,6 @@ function createAnthropicSDK(options = {}) {
1128
1176
  init = { ...init, headers: reqHeaders };
1129
1177
  }
1130
1178
  }
1131
- if (init?.body && typeof init.body === "string" && init.body.length > CONTEXT_1M_BODY_THRESHOLD) {
1132
- const betaHeaders = new Headers(init.headers);
1133
- const existingBetas = betaHeaders.get("anthropic-beta") ?? "";
1134
- if (!existingBetas.includes(CONTEXT_1M_BETA)) {
1135
- betaHeaders.set("anthropic-beta", existingBetas + "," + CONTEXT_1M_BETA);
1136
- init = { ...init, headers: betaHeaders };
1137
- }
1138
- }
1139
1179
  if (auth.isOAuth && init?.body && typeof init.body === "string" && hasCchPlaceholder(init.body)) {
1140
1180
  try {
1141
1181
  const cch = await computeCch(init.body);
@@ -1184,6 +1224,7 @@ function createAnthropicSDK(options = {}) {
1184
1224
  };
1185
1225
  }
1186
1226
  var anthropicSDKPlugin = async () => {
1227
+ const isOAuth = resolveAuth({}).isOAuth;
1187
1228
  return {
1188
1229
  config: async (cfg) => {
1189
1230
  if (!cfg.provider) {
@@ -1191,7 +1232,7 @@ var anthropicSDKPlugin = async () => {
1191
1232
  }
1192
1233
  cfg.provider[PROVIDER_ID] = {
1193
1234
  npm: PACKAGE_NAME,
1194
- models: PLUGIN_MODELS,
1235
+ models: buildPluginModels(isOAuth),
1195
1236
  ...cfg.provider[PROVIDER_ID]
1196
1237
  };
1197
1238
  }