opencode-anthropic-auth 0.0.6 → 0.0.8

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 (2) hide show
  1. package/index.mjs +89 -23
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -127,52 +127,118 @@ export async function AnthropicAuthPlugin({ client }) {
127
127
  });
128
128
  auth.access = json.access_token;
129
129
  }
130
- // Add oauth-2025-04-20 beta to whatever betas are already present
131
- const incomingBeta = init.headers?.["anthropic-beta"] || "";
130
+ const requestInit = init ?? {};
131
+
132
+ const requestHeaders = new Headers();
133
+ if (input instanceof Request) {
134
+ input.headers.forEach((value, key) => {
135
+ requestHeaders.set(key, value);
136
+ });
137
+ }
138
+ if (requestInit.headers) {
139
+ if (requestInit.headers instanceof Headers) {
140
+ requestInit.headers.forEach((value, key) => {
141
+ requestHeaders.set(key, value);
142
+ });
143
+ } else if (Array.isArray(requestInit.headers)) {
144
+ for (const [key, value] of requestInit.headers) {
145
+ if (typeof value !== "undefined") {
146
+ requestHeaders.set(key, String(value));
147
+ }
148
+ }
149
+ } else {
150
+ for (const [key, value] of Object.entries(requestInit.headers)) {
151
+ if (typeof value !== "undefined") {
152
+ requestHeaders.set(key, String(value));
153
+ }
154
+ }
155
+ }
156
+ }
157
+
158
+ const incomingBeta = requestHeaders.get("anthropic-beta") || "";
132
159
  const incomingBetasList = incomingBeta
133
160
  .split(",")
134
161
  .map((b) => b.trim())
135
162
  .filter(Boolean);
136
163
 
137
- // Add oauth beta and deduplicate
164
+ const includeClaudeCode = incomingBetasList.includes(
165
+ "claude-code-20250219",
166
+ );
167
+
138
168
  const mergedBetas = [
139
- ...new Set([
140
- "oauth-2025-04-20",
141
- "claude-code-20250219",
142
- "interleaved-thinking-2025-05-14",
143
- "fine-grained-tool-streaming-2025-05-14",
144
- ...incomingBetasList,
145
- ]),
169
+ "oauth-2025-04-20",
170
+ "interleaved-thinking-2025-05-14",
171
+ ...(includeClaudeCode ? ["claude-code-20250219"] : []),
146
172
  ].join(",");
147
173
 
148
- const headers = {
149
- ...init.headers,
150
- authorization: `Bearer ${auth.access}`,
151
- "anthropic-beta": mergedBetas,
152
- };
153
- delete headers["x-api-key"];
174
+ requestHeaders.set("authorization", `Bearer ${auth.access}`);
175
+ requestHeaders.set("anthropic-beta", mergedBetas);
176
+ requestHeaders.set(
177
+ "user-agent",
178
+ "claude-cli/2.1.2 (external, cli)",
179
+ );
180
+ requestHeaders.delete("x-api-key");
154
181
 
155
- const TOOL_PREFIX = "oc_";
156
- let body = init.body;
182
+ const TOOL_PREFIX = "mcp_";
183
+ let body = requestInit.body;
157
184
  if (body && typeof body === "string") {
158
185
  try {
159
186
  const parsed = JSON.parse(body);
187
+ // Add prefix to tools definitions
160
188
  if (parsed.tools && Array.isArray(parsed.tools)) {
161
189
  parsed.tools = parsed.tools.map((tool) => ({
162
190
  ...tool,
163
191
  name: tool.name ? `${TOOL_PREFIX}${tool.name}` : tool.name,
164
192
  }));
165
- body = JSON.stringify(parsed);
166
193
  }
194
+ // Add prefix to tool_use blocks in messages
195
+ if (parsed.messages && Array.isArray(parsed.messages)) {
196
+ parsed.messages = parsed.messages.map((msg) => {
197
+ if (msg.content && Array.isArray(msg.content)) {
198
+ msg.content = msg.content.map((block) => {
199
+ if (block.type === "tool_use" && block.name) {
200
+ return { ...block, name: `${TOOL_PREFIX}${block.name}` };
201
+ }
202
+ return block;
203
+ });
204
+ }
205
+ return msg;
206
+ });
207
+ }
208
+ body = JSON.stringify(parsed);
167
209
  } catch (e) {
168
210
  // ignore parse errors
169
211
  }
170
212
  }
171
213
 
172
- const response = await fetch(input, {
173
- ...init,
214
+ let requestInput = input;
215
+ let requestUrl = null;
216
+ try {
217
+ if (typeof input === "string" || input instanceof URL) {
218
+ requestUrl = new URL(input.toString());
219
+ } else if (input instanceof Request) {
220
+ requestUrl = new URL(input.url);
221
+ }
222
+ } catch {
223
+ requestUrl = null;
224
+ }
225
+
226
+ if (
227
+ requestUrl &&
228
+ requestUrl.pathname === "/v1/messages" &&
229
+ !requestUrl.searchParams.has("beta")
230
+ ) {
231
+ requestUrl.searchParams.set("beta", "true");
232
+ requestInput =
233
+ input instanceof Request
234
+ ? new Request(requestUrl.toString(), input)
235
+ : requestUrl;
236
+ }
237
+
238
+ const response = await fetch(requestInput, {
239
+ ...requestInit,
174
240
  body,
175
- headers,
241
+ headers: requestHeaders,
176
242
  });
177
243
 
178
244
  // Transform streaming response to rename tools back
@@ -190,7 +256,7 @@ export async function AnthropicAuthPlugin({ client }) {
190
256
  }
191
257
 
192
258
  let text = decoder.decode(value, { stream: true });
193
- text = text.replace(/"name"\s*:\s*"oc_([^"]+)"/g, '"name": "$1"');
259
+ text = text.replace(/"name"\s*:\s*"mcp_([^"]+)"/g, '"name": "$1"');
194
260
  controller.enqueue(encoder.encode(text));
195
261
  },
196
262
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-anthropic-auth",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "main": "./index.mjs",
5
5
  "devDependencies": {
6
6
  "@opencode-ai/plugin": "^0.4.45"