opencode-anthropic-auth 0.0.5 → 0.0.7

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.
@@ -8,6 +8,10 @@ on:
8
8
  required: false
9
9
  default: "patch"
10
10
 
11
+ permissions:
12
+ id-token: write
13
+ contents: read
14
+
11
15
  jobs:
12
16
  publish:
13
17
  runs-on: ubuntu-latest
@@ -16,7 +20,7 @@ jobs:
16
20
 
17
21
  - uses: actions/setup-node@v4
18
22
  with:
19
- node-version: "20"
23
+ node-version: "24"
20
24
  registry-url: "https://registry.npmjs.org"
21
25
 
22
26
  - run: npm install
@@ -24,3 +28,4 @@ jobs:
24
28
  - run: npm publish --access public
25
29
  env:
26
30
  NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
31
+ NPM_CONFIG_PROVENANCE: false
package/index.mjs CHANGED
@@ -127,34 +127,133 @@ 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"];
154
- return fetch(input, {
155
- ...init,
156
- headers,
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");
181
+
182
+ const TOOL_PREFIX = "oc_";
183
+ let body = requestInit.body;
184
+ if (body && typeof body === "string") {
185
+ try {
186
+ const parsed = JSON.parse(body);
187
+ if (parsed.tools && Array.isArray(parsed.tools)) {
188
+ parsed.tools = parsed.tools.map((tool) => ({
189
+ ...tool,
190
+ name: tool.name ? `${TOOL_PREFIX}${tool.name}` : tool.name,
191
+ }));
192
+ body = JSON.stringify(parsed);
193
+ }
194
+ } catch (e) {
195
+ // ignore parse errors
196
+ }
197
+ }
198
+
199
+ let requestInput = input;
200
+ let requestUrl = null;
201
+ try {
202
+ if (typeof input === "string" || input instanceof URL) {
203
+ requestUrl = new URL(input.toString());
204
+ } else if (input instanceof Request) {
205
+ requestUrl = new URL(input.url);
206
+ }
207
+ } catch {
208
+ requestUrl = null;
209
+ }
210
+
211
+ if (
212
+ requestUrl &&
213
+ requestUrl.pathname === "/v1/messages" &&
214
+ !requestUrl.searchParams.has("beta")
215
+ ) {
216
+ requestUrl.searchParams.set("beta", "true");
217
+ requestInput =
218
+ input instanceof Request
219
+ ? new Request(requestUrl.toString(), input)
220
+ : requestUrl;
221
+ }
222
+
223
+ const response = await fetch(requestInput, {
224
+ ...requestInit,
225
+ body,
226
+ headers: requestHeaders,
157
227
  });
228
+
229
+ // Transform streaming response to rename tools back
230
+ if (response.body) {
231
+ const reader = response.body.getReader();
232
+ const decoder = new TextDecoder();
233
+ const encoder = new TextEncoder();
234
+
235
+ const stream = new ReadableStream({
236
+ async pull(controller) {
237
+ const { done, value } = await reader.read();
238
+ if (done) {
239
+ controller.close();
240
+ return;
241
+ }
242
+
243
+ let text = decoder.decode(value, { stream: true });
244
+ text = text.replace(/"name"\s*:\s*"oc_([^"]+)"/g, '"name": "$1"');
245
+ controller.enqueue(encoder.encode(text));
246
+ },
247
+ });
248
+
249
+ return new Response(stream, {
250
+ status: response.status,
251
+ statusText: response.statusText,
252
+ headers: response.headers,
253
+ });
254
+ }
255
+
256
+ return response;
158
257
  },
159
258
  };
160
259
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-anthropic-auth",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "main": "./index.mjs",
5
5
  "devDependencies": {
6
6
  "@opencode-ai/plugin": "^0.4.45"