@xtruder/opencode-claude-max-plugin 0.2.0 → 0.2.3

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/build/server.js CHANGED
@@ -1,10 +1,119 @@
1
1
  // src/index.ts
2
2
  import Anthropic from "@anthropic-ai/sdk";
3
3
 
4
- // src/tool-names.ts
5
- import { readFileSync, existsSync } from "node:fs";
6
- import { join } from "node:path";
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
+ }
27
+
28
+ // src/credentials.ts
29
+ import { execSync } from "node:child_process";
30
+ import { existsSync, readFileSync } from "node:fs";
7
31
  import { homedir } from "node:os";
32
+ import { join } from "node:path";
33
+ var CREDENTIAL_CACHE_TTL_MS = 30000;
34
+ var EXPIRY_BUFFER_MS = 60000;
35
+ var cachedCreds = null;
36
+ var cachedAt = 0;
37
+ var cachedPath;
38
+ function getCredentialsPath() {
39
+ return join(homedir(), ".claude", ".credentials.json");
40
+ }
41
+ function readClaudeCredentials(path) {
42
+ const credPath = path ?? getCredentialsPath();
43
+ if (!existsSync(credPath))
44
+ return null;
45
+ try {
46
+ const raw = readFileSync(credPath, "utf-8");
47
+ const parsed = JSON.parse(raw);
48
+ if (!parsed.claudeAiOauth?.accessToken)
49
+ return null;
50
+ return parsed.claudeAiOauth;
51
+ } catch {
52
+ return null;
53
+ }
54
+ }
55
+ function isExpired(creds) {
56
+ return Date.now() > creds.expiresAt - EXPIRY_BUFFER_MS;
57
+ }
58
+ function refreshViaCli() {
59
+ const maxAttempts = 2;
60
+ for (let i = 0;i < maxAttempts; i++) {
61
+ try {
62
+ execSync("claude -p . --model haiku", {
63
+ timeout: 60000,
64
+ encoding: "utf-8",
65
+ env: { ...process.env, TERM: "dumb" },
66
+ stdio: "ignore"
67
+ });
68
+ return true;
69
+ } catch {}
70
+ }
71
+ return false;
72
+ }
73
+ function refreshIfNeeded(path) {
74
+ const creds = readClaudeCredentials(path);
75
+ if (!creds)
76
+ return null;
77
+ if (!isExpired(creds))
78
+ return creds;
79
+ console.warn("[anthropic-sdk-provider] OAuth token near expiry, refreshing via Claude CLI...");
80
+ const refreshed = refreshViaCli();
81
+ if (!refreshed) {
82
+ console.warn("[anthropic-sdk-provider] CLI refresh failed. Token may be expired.");
83
+ return creds;
84
+ }
85
+ const fresh = readClaudeCredentials(path);
86
+ if (fresh && !isExpired(fresh)) {
87
+ console.warn("[anthropic-sdk-provider] Token refreshed successfully.");
88
+ return fresh;
89
+ }
90
+ return fresh ?? creds;
91
+ }
92
+ function getCachedCredentials(path) {
93
+ const now = Date.now();
94
+ const resolvedPath = path ?? cachedPath;
95
+ if (cachedCreds && now - cachedAt < CREDENTIAL_CACHE_TTL_MS && !isExpired(cachedCreds)) {
96
+ return cachedCreds;
97
+ }
98
+ const fresh = refreshIfNeeded(resolvedPath);
99
+ if (fresh) {
100
+ cachedCreds = fresh;
101
+ cachedAt = now;
102
+ cachedPath = resolvedPath;
103
+ } else {
104
+ cachedCreds = null;
105
+ }
106
+ return cachedCreds;
107
+ }
108
+
109
+ // src/model.ts
110
+ import { APIError, RateLimitError } from "@anthropic-ai/sdk";
111
+ import { createHash, randomBytes } from "node:crypto";
112
+
113
+ // src/tool-names.ts
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";
8
117
  var BUILTIN_OPENCODE_TO_CLAUDE = {
9
118
  task: "Agent",
10
119
  question: "AskUserQuestion",
@@ -36,15 +145,15 @@ var mcpServerNames = null;
36
145
  function detectMcpServers() {
37
146
  const servers = new Set;
38
147
  const paths = [
39
- join(process.cwd(), ".opencode", "opencode.json"),
40
- join(homedir(), ".config", "opencode", "opencode.json"),
41
- join(homedir(), ".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")
42
151
  ];
43
152
  for (const p of paths) {
44
153
  try {
45
- if (!existsSync(p))
154
+ if (!existsSync2(p))
46
155
  continue;
47
- let raw = readFileSync(p, "utf-8");
156
+ let raw = readFileSync2(p, "utf-8");
48
157
  raw = raw.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
49
158
  const config = JSON.parse(raw);
50
159
  if (config.mcp && typeof config.mcp === "object") {
@@ -272,47 +381,6 @@ function formatToolResultContent(output) {
272
381
  }
273
382
  }
274
383
 
275
- // src/tools.ts
276
- function cleanSchema(schema) {
277
- const cleaned = {};
278
- for (const [key, value] of Object.entries(schema)) {
279
- if (key === "custom")
280
- continue;
281
- if (value && typeof value === "object" && !Array.isArray(value)) {
282
- cleaned[key] = cleanSchema(value);
283
- } else {
284
- cleaned[key] = value;
285
- }
286
- }
287
- if (cleaned.properties && !cleaned.type) {
288
- cleaned.type = "object";
289
- }
290
- return cleaned;
291
- }
292
- function convertTools(tools) {
293
- if (!tools || tools.length === 0)
294
- return;
295
- return tools.filter((t) => t.type === "function").map((tool) => ({
296
- name: toClaudeToolName(tool.name),
297
- description: tool.description ?? "",
298
- input_schema: cleanSchema(tool.inputSchema)
299
- }));
300
- }
301
- function convertToolChoice(toolChoice) {
302
- if (!toolChoice)
303
- return;
304
- switch (toolChoice.type) {
305
- case "auto":
306
- return { type: "auto" };
307
- case "required":
308
- return { type: "any" };
309
- case "none":
310
- return;
311
- case "tool":
312
- return { type: "tool", name: toClaudeToolName(toolChoice.toolName) };
313
- }
314
- }
315
-
316
384
  // src/stream.ts
317
385
  var idCounter = 0;
318
386
  function generateId() {
@@ -492,9 +560,48 @@ function processEvent(event, blockStates, modelId) {
492
560
  return parts;
493
561
  }
494
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
+
495
604
  // src/model.ts
496
- import { randomBytes, createHash } from "node:crypto";
497
- import { APIError, RateLimitError } from "@anthropic-ai/sdk";
498
605
  function handleApiError(error) {
499
606
  if (error instanceof RateLimitError || error instanceof APIError && error.status === 429) {
500
607
  const h = error.headers;
@@ -544,6 +651,9 @@ function buildMetadata() {
544
651
  user_id: JSON.stringify({ device_id: DEVICE_ID })
545
652
  };
546
653
  }
654
+ function supportsContextManagement(apiModelId) {
655
+ return !apiModelId.includes("claude-3-");
656
+ }
547
657
 
548
658
  class AnthropicSDKModel {
549
659
  client;
@@ -553,12 +663,16 @@ class AnthropicSDKModel {
553
663
  provider;
554
664
  modelId;
555
665
  supportedUrls = {};
666
+ apiModelId;
667
+ is1MContext;
556
668
  constructor(modelId, client, providerName, isOAuth = false) {
557
669
  this.client = client;
558
670
  this.providerName = providerName;
559
671
  this.isOAuth = isOAuth;
560
672
  this.modelId = modelId;
561
673
  this.provider = providerName;
674
+ this.is1MContext = modelId.endsWith("-1m");
675
+ this.apiModelId = this.is1MContext ? modelId.replace(/-1m$/, "") : modelId;
562
676
  }
563
677
  buildParams(options) {
564
678
  const { system, messages } = convertPrompt(options.prompt);
@@ -575,7 +689,7 @@ class AnthropicSDKModel {
575
689
  const tools = options.toolChoice?.type === "none" ? undefined : convertTools(options.tools);
576
690
  const toolChoice = options.toolChoice?.type === "none" ? undefined : convertToolChoice(options.toolChoice);
577
691
  const params = {
578
- model: this.modelId,
692
+ model: this.apiModelId,
579
693
  max_tokens: options.maxOutputTokens ?? 64000,
580
694
  messages
581
695
  };
@@ -593,7 +707,7 @@ class AnthropicSDKModel {
593
707
  params.system = [BILLING_SYSTEM_BLOCK, IDENTITY_SYSTEM_BLOCK];
594
708
  }
595
709
  params.metadata = buildMetadata();
596
- const supportsEffort = !this.modelId.includes("haiku") && !this.modelId.includes("claude-3-");
710
+ const supportsEffort = !this.apiModelId.includes("haiku") && !this.apiModelId.includes("claude-3-");
597
711
  if (supportsEffort) {
598
712
  if (options.temperature == null) {
599
713
  params.temperature = 1;
@@ -681,8 +795,27 @@ class AnthropicSDKModel {
681
795
  if (anthropicOptions.metadata)
682
796
  params.metadata = anthropicOptions.metadata;
683
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
+ }
684
811
  return { params, warnings };
685
812
  }
813
+ buildRequestOptions(signal) {
814
+ const opts = {};
815
+ if (signal)
816
+ opts.signal = signal;
817
+ return opts;
818
+ }
686
819
  async doGenerate(options) {
687
820
  const { params, warnings } = this.buildParams(options);
688
821
  if (!options.maxOutputTokens && params.max_tokens > 4096) {
@@ -693,7 +826,7 @@ class AnthropicSDKModel {
693
826
  response = await this.client.messages.create({
694
827
  ...params,
695
828
  stream: false
696
- }, { signal: options.abortSignal });
829
+ }, this.buildRequestOptions(options.abortSignal));
697
830
  } catch (error) {
698
831
  handleApiError(error);
699
832
  }
@@ -762,7 +895,7 @@ class AnthropicSDKModel {
762
895
  anthropicStream = await this.client.messages.create({
763
896
  ...params,
764
897
  stream: true
765
- }, { signal: options.abortSignal });
898
+ }, this.buildRequestOptions(options.abortSignal));
766
899
  } catch (error) {
767
900
  if (error instanceof APIError && error.status === 400 && error.message?.includes("must end with a user message")) {
768
901
  return {
@@ -818,100 +951,19 @@ class AnthropicSDKModel {
818
951
  }
819
952
  }
820
953
 
821
- // src/credentials.ts
822
- import { readFileSync as readFileSync2, existsSync as existsSync2 } from "node:fs";
823
- import { execSync } from "node:child_process";
824
- import { join as join2 } from "node:path";
825
- import { homedir as homedir2 } from "node:os";
826
- var CREDENTIAL_CACHE_TTL_MS = 30000;
827
- var EXPIRY_BUFFER_MS = 60000;
828
- var cachedCreds = null;
829
- var cachedAt = 0;
830
- var cachedPath;
831
- function getCredentialsPath() {
832
- return join2(homedir2(), ".claude", ".credentials.json");
833
- }
834
- function readClaudeCredentials(path) {
835
- const credPath = path ?? getCredentialsPath();
836
- if (!existsSync2(credPath))
837
- return null;
838
- try {
839
- const raw = readFileSync2(credPath, "utf-8");
840
- const parsed = JSON.parse(raw);
841
- if (!parsed.claudeAiOauth?.accessToken)
842
- return null;
843
- return parsed.claudeAiOauth;
844
- } catch {
845
- return null;
846
- }
847
- }
848
- function isExpired(creds) {
849
- return Date.now() > creds.expiresAt - EXPIRY_BUFFER_MS;
850
- }
851
- function refreshViaCli() {
852
- const maxAttempts = 2;
853
- for (let i = 0;i < maxAttempts; i++) {
854
- try {
855
- execSync("claude -p . --model haiku", {
856
- timeout: 60000,
857
- encoding: "utf-8",
858
- env: { ...process.env, TERM: "dumb" },
859
- stdio: "ignore"
860
- });
861
- return true;
862
- } catch {}
863
- }
864
- return false;
865
- }
866
- function refreshIfNeeded(path) {
867
- const creds = readClaudeCredentials(path);
868
- if (!creds)
869
- return null;
870
- if (!isExpired(creds))
871
- return creds;
872
- console.warn("[anthropic-sdk-provider] OAuth token near expiry, refreshing via Claude CLI...");
873
- const refreshed = refreshViaCli();
874
- if (!refreshed) {
875
- console.warn("[anthropic-sdk-provider] CLI refresh failed. Token may be expired.");
876
- return creds;
877
- }
878
- const fresh = readClaudeCredentials(path);
879
- if (fresh && !isExpired(fresh)) {
880
- console.warn("[anthropic-sdk-provider] Token refreshed successfully.");
881
- return fresh;
882
- }
883
- return fresh ?? creds;
884
- }
885
- function getCachedCredentials(path) {
886
- const now = Date.now();
887
- const resolvedPath = path ?? cachedPath;
888
- if (cachedCreds && now - cachedAt < CREDENTIAL_CACHE_TTL_MS && !isExpired(cachedCreds)) {
889
- return cachedCreds;
890
- }
891
- const fresh = refreshIfNeeded(resolvedPath);
892
- if (fresh) {
893
- cachedCreds = fresh;
894
- cachedAt = now;
895
- cachedPath = resolvedPath;
896
- } else {
897
- cachedCreds = null;
898
- }
899
- return cachedCreds;
900
- }
901
-
902
954
  // src/usage.ts
903
955
  import {
904
- readFileSync as readFileSync3,
905
- writeFileSync,
956
+ closeSync,
957
+ constants as fsConstants,
906
958
  mkdirSync,
907
- unlinkSync,
908
959
  openSync,
909
- closeSync,
960
+ readFileSync as readFileSync3,
910
961
  renameSync,
911
- constants as fsConstants
962
+ unlinkSync,
963
+ writeFileSync
912
964
  } from "node:fs";
913
- import { join as join3 } from "node:path";
914
965
  import { homedir as homedir3 } from "node:os";
966
+ import { join as join3 } from "node:path";
915
967
  var cachedUsage = {};
916
968
  var XDG_STATE = process.env.XDG_STATE_HOME || join3(homedir3(), ".local", "state");
917
969
  var USAGE_CACHE_DIR = join3(XDG_STATE, "opencode");
@@ -992,30 +1044,6 @@ function persistCachedUsage() {
992
1044
  }
993
1045
  var API_TTL_MS = 5 * 60000;
994
1046
 
995
- // src/cch.ts
996
- import xxhashInit from "xxhash-wasm";
997
- var CCH_SEED = 0x6e52736ac806831en;
998
- var CCH_PLACEHOLDER = "cch=00000";
999
- var CCH_MASK = 0xfffffn;
1000
- var hasherPromise = null;
1001
- function getHasher() {
1002
- if (!hasherPromise) {
1003
- hasherPromise = xxhashInit();
1004
- }
1005
- return hasherPromise;
1006
- }
1007
- async function computeCch(body) {
1008
- const hasher = await getHasher();
1009
- const hash = hasher.h64Raw(new TextEncoder().encode(body), CCH_SEED);
1010
- return (hash & CCH_MASK).toString(16).padStart(5, "0");
1011
- }
1012
- function replaceCchPlaceholder(body, cch) {
1013
- return body.replace(CCH_PLACEHOLDER, `cch=${cch}`);
1014
- }
1015
- function hasCchPlaceholder(body) {
1016
- return body.includes(CCH_PLACEHOLDER);
1017
- }
1018
-
1019
1047
  // src/index.ts
1020
1048
  var CLAUDE_CODE_VERSION = "2.1.81";
1021
1049
  var OAUTH_BETAS = [
@@ -1026,63 +1054,90 @@ var OAUTH_BETAS = [
1026
1054
  "prompt-caching-scope-2026-01-05",
1027
1055
  "effort-2025-11-24"
1028
1056
  ];
1029
- var CONTEXT_1M_BETA = "context-1m-2025-08-07";
1030
1057
  var API_KEY_BETAS = ["interleaved-thinking-2025-05-14", "fine-grained-tool-streaming-2025-05-14"];
1031
1058
  var PACKAGE_NAME = "@xtruder/opencode-claude-max-plugin";
1032
1059
  var PROVIDER_ID = "anthropic-sdk";
1033
- var PLUGIN_MODELS = {
1034
- "claude-haiku-4-5": {
1035
- name: "Claude Haiku 4.5",
1036
- reasoning: false,
1037
- tool_call: true,
1038
- attachment: true,
1039
- temperature: true,
1040
- limit: { context: 200000, output: 8192 },
1041
- cost: { input: 0.8, output: 4, cache_read: 0.08, cache_write: 1 },
1042
- modalities: {
1043
- input: ["text", "image"],
1044
- output: ["text"]
1045
- }
1046
- },
1047
- "claude-sonnet-4-6": {
1048
- name: "Claude Sonnet 4.6",
1049
- reasoning: true,
1050
- tool_call: true,
1051
- attachment: true,
1052
- temperature: true,
1053
- limit: { context: 200000, output: 16000 },
1054
- cost: { input: 3, output: 15, cache_read: 0.3, cache_write: 3.75 },
1055
- modalities: {
1056
- input: ["text", "image", "pdf"],
1057
- output: ["text"]
1058
- },
1059
- 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 = {
1060
1069
  variants: {
1061
1070
  low: { effort: "low" },
1062
1071
  medium: { effort: "medium" },
1063
- high: { effort: "high" }
1072
+ high: { effort: "high" },
1073
+ max: { effort: "max" }
1064
1074
  }
1065
- },
1066
- "claude-opus-4-6": {
1067
- name: "Claude Opus 4.6",
1068
- reasoning: true,
1069
- tool_call: true,
1070
- attachment: true,
1071
- temperature: true,
1072
- limit: { context: 200000, output: 32000 },
1073
- cost: { input: 15, output: 75, cache_read: 1.5, cache_write: 18.75 },
1074
- modalities: {
1075
- input: ["text", "image", "pdf"],
1076
- 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
+ }
1077
1089
  },
1078
- options: { effort: "medium" },
1079
- variants: {
1080
- low: { effort: "low" },
1081
- medium: { effort: "medium" },
1082
- 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
1083
1138
  }
1084
- }
1085
- };
1139
+ };
1140
+ }
1086
1141
  function resolveAuth(options) {
1087
1142
  if (options.apiKey) {
1088
1143
  return { apiKey: options.apiKey, isOAuth: false };
@@ -1111,7 +1166,6 @@ function createAnthropicSDK(options = {}) {
1111
1166
  defaultHeaders["anthropic-dangerous-direct-browser-access"] = "true";
1112
1167
  defaultHeaders["x-stainless-package-version"] = "0.74.0";
1113
1168
  }
1114
- const CONTEXT_1M_BODY_THRESHOLD = 600000;
1115
1169
  const baseFetch = customFetch ?? globalThis.fetch;
1116
1170
  const wrappedFetch = async (url, init) => {
1117
1171
  if (auth.isOAuth && init) {
@@ -1122,14 +1176,6 @@ function createAnthropicSDK(options = {}) {
1122
1176
  init = { ...init, headers: reqHeaders };
1123
1177
  }
1124
1178
  }
1125
- if (init?.body && typeof init.body === "string" && init.body.length > CONTEXT_1M_BODY_THRESHOLD) {
1126
- const betaHeaders = new Headers(init.headers);
1127
- const existingBetas = betaHeaders.get("anthropic-beta") ?? "";
1128
- if (!existingBetas.includes(CONTEXT_1M_BETA)) {
1129
- betaHeaders.set("anthropic-beta", existingBetas + "," + CONTEXT_1M_BETA);
1130
- init = { ...init, headers: betaHeaders };
1131
- }
1132
- }
1133
1179
  if (auth.isOAuth && init?.body && typeof init.body === "string" && hasCchPlaceholder(init.body)) {
1134
1180
  try {
1135
1181
  const cch = await computeCch(init.body);
@@ -1178,6 +1224,7 @@ function createAnthropicSDK(options = {}) {
1178
1224
  };
1179
1225
  }
1180
1226
  var anthropicSDKPlugin = async () => {
1227
+ const isOAuth = resolveAuth({}).isOAuth;
1181
1228
  return {
1182
1229
  config: async (cfg) => {
1183
1230
  if (!cfg.provider) {
@@ -1185,7 +1232,7 @@ var anthropicSDKPlugin = async () => {
1185
1232
  }
1186
1233
  cfg.provider[PROVIDER_ID] = {
1187
1234
  npm: PACKAGE_NAME,
1188
- models: PLUGIN_MODELS,
1235
+ models: buildPluginModels(isOAuth),
1189
1236
  ...cfg.provider[PROVIDER_ID]
1190
1237
  };
1191
1238
  }
@@ -1 +1 @@
1
- {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAA+B,MAAM,kBAAkB,CAAA;AAC9F,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAA;AAG9C,KAAK,kBAAkB,GAAG,SAAS,CAAC,kBAAkB,CAAA;AAmCtD,wBAAgB,aAAa,CAC3B,eAAe,EAAE,aAAa,CAAC,kBAAkB,CAAC,EAClD,OAAO,EAAE,MAAM,GACd,cAAc,CAAC,yBAAyB,CAAC,CAwD3C"}
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA+B,yBAAyB,EAAE,MAAM,kBAAkB,CAAA;AAC9F,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAA;AAG9C,KAAK,kBAAkB,GAAG,SAAS,CAAC,kBAAkB,CAAA;AAmCtD,wBAAgB,aAAa,CAC3B,eAAe,EAAE,aAAa,CAAC,kBAAkB,CAAC,EAClD,OAAO,EAAE,MAAM,GACd,cAAc,CAAC,yBAAyB,CAAC,CAwD3C"}
package/build/tui.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ /** @jsxImportSource @opentui/solid */
2
+ import type { TuiPluginModule } from "@opencode-ai/plugin/tui";
3
+ declare const plugin: TuiPluginModule & {
4
+ id: string;
5
+ };
6
+ export default plugin;
7
+ //# sourceMappingURL=tui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../src/tui.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,KAAK,EAGV,eAAe,EAEhB,MAAM,yBAAyB,CAAA;AA+XhC,QAAA,MAAM,MAAM,EAAE,eAAe,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAG3C,CAAA;AAED,eAAe,MAAM,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xtruder/opencode-claude-max-plugin",
3
- "version": "0.2.0",
3
+ "version": "0.2.3",
4
4
  "description": "OpenCode plugin for Claude Max/Pro subscription via @anthropic-ai/sdk - uses Claude Code OAuth credentials",
5
5
  "keywords": [
6
6
  "ai-sdk",
@@ -56,6 +56,7 @@
56
56
  "@ai-sdk/provider": "3.0.8",
57
57
  "@ai-sdk/provider-utils": "3.0.2",
58
58
  "@opencode-ai/plugin": "^1.3.0",
59
+ "@opentui/solid": "^0.1.96",
59
60
  "ai": "5.0.124",
60
61
  "bun-types": "^1.3.11",
61
62
  "oxfmt": "^0.41.0",
@@ -1,7 +1,7 @@
1
- import { readFileSync, existsSync } from "node:fs"
2
1
  import { execSync } from "node:child_process"
3
- import { join } from "node:path"
2
+ import { existsSync, readFileSync } from "node:fs"
4
3
  import { homedir } from "node:os"
4
+ import { join } from "node:path"
5
5
 
6
6
  export interface ClaudeOAuthCredentials {
7
7
  accessToken: string