@vacbo/opencode-anthropic-fix 0.1.7 → 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 (107) hide show
  1. package/README.md +88 -88
  2. package/dist/opencode-anthropic-auth-cli.mjs +804 -507
  3. package/dist/opencode-anthropic-auth-plugin.js +4751 -4109
  4. package/package.json +67 -59
  5. package/src/__tests__/billing-edge-cases.test.ts +59 -59
  6. package/src/__tests__/bun-proxy.parallel.test.ts +388 -382
  7. package/src/__tests__/cc-comparison.test.ts +87 -87
  8. package/src/__tests__/cc-credentials.test.ts +254 -250
  9. package/src/__tests__/cch-drift-checker.test.ts +51 -51
  10. package/src/__tests__/cch-native-style.test.ts +56 -56
  11. package/src/__tests__/debug-gating.test.ts +42 -42
  12. package/src/__tests__/decomposition-smoke.test.ts +68 -68
  13. package/src/__tests__/fingerprint-regression.test.ts +575 -566
  14. package/src/__tests__/helpers/conversation-history.smoke.test.ts +271 -271
  15. package/src/__tests__/helpers/conversation-history.ts +119 -119
  16. package/src/__tests__/helpers/deferred.smoke.test.ts +103 -103
  17. package/src/__tests__/helpers/deferred.ts +69 -69
  18. package/src/__tests__/helpers/in-memory-storage.smoke.test.ts +155 -155
  19. package/src/__tests__/helpers/in-memory-storage.ts +88 -88
  20. package/src/__tests__/helpers/mock-bun-proxy.smoke.test.ts +68 -68
  21. package/src/__tests__/helpers/mock-bun-proxy.ts +189 -189
  22. package/src/__tests__/helpers/plugin-fetch-harness.smoke.test.ts +273 -273
  23. package/src/__tests__/helpers/plugin-fetch-harness.ts +288 -288
  24. package/src/__tests__/helpers/sse.smoke.test.ts +236 -236
  25. package/src/__tests__/helpers/sse.ts +209 -209
  26. package/src/__tests__/index.parallel.test.ts +605 -595
  27. package/src/__tests__/sanitization-regex.test.ts +112 -112
  28. package/src/__tests__/state-bounds.test.ts +90 -90
  29. package/src/account-identity.test.ts +197 -192
  30. package/src/account-identity.ts +69 -67
  31. package/src/account-state.test.ts +86 -86
  32. package/src/account-state.ts +25 -25
  33. package/src/accounts/matching.test.ts +335 -0
  34. package/src/accounts/matching.ts +167 -0
  35. package/src/accounts/persistence.test.ts +345 -0
  36. package/src/accounts/persistence.ts +432 -0
  37. package/src/accounts/repair.test.ts +276 -0
  38. package/src/accounts/repair.ts +407 -0
  39. package/src/accounts.dedup.test.ts +621 -621
  40. package/src/accounts.test.ts +933 -929
  41. package/src/accounts.ts +633 -989
  42. package/src/backoff.test.ts +345 -345
  43. package/src/backoff.ts +219 -219
  44. package/src/betas.ts +124 -124
  45. package/src/bun-fetch.test.ts +345 -342
  46. package/src/bun-fetch.ts +424 -424
  47. package/src/bun-proxy.test.ts +25 -25
  48. package/src/bun-proxy.ts +209 -209
  49. package/src/cc-credentials.ts +111 -111
  50. package/src/circuit-breaker.test.ts +184 -184
  51. package/src/circuit-breaker.ts +169 -169
  52. package/src/cli/commands/auth.ts +963 -0
  53. package/src/cli/commands/config.ts +547 -0
  54. package/src/cli/formatting.test.ts +406 -0
  55. package/src/cli/formatting.ts +219 -0
  56. package/src/cli.ts +255 -2022
  57. package/src/commands/handlers/betas.ts +100 -0
  58. package/src/commands/handlers/config.ts +99 -0
  59. package/src/commands/handlers/files.ts +375 -0
  60. package/src/commands/oauth-flow.ts +181 -166
  61. package/src/commands/prompts.ts +61 -61
  62. package/src/commands/router.test.ts +421 -0
  63. package/src/commands/router.ts +143 -635
  64. package/src/config.test.ts +482 -482
  65. package/src/config.ts +412 -404
  66. package/src/constants.ts +48 -48
  67. package/src/drift/cch-constants.ts +95 -95
  68. package/src/env.ts +111 -105
  69. package/src/headers/billing.ts +33 -33
  70. package/src/headers/builder.ts +130 -130
  71. package/src/headers/cch.ts +75 -75
  72. package/src/headers/stainless.ts +25 -25
  73. package/src/headers/user-agent.ts +23 -23
  74. package/src/index.ts +436 -828
  75. package/src/models.ts +27 -27
  76. package/src/oauth.test.ts +102 -102
  77. package/src/oauth.ts +178 -178
  78. package/src/parent-pid-watcher.test.ts +148 -148
  79. package/src/parent-pid-watcher.ts +69 -69
  80. package/src/plugin-helpers.ts +82 -82
  81. package/src/refresh-helpers.ts +145 -139
  82. package/src/refresh-lock.test.ts +94 -94
  83. package/src/refresh-lock.ts +93 -93
  84. package/src/request/body.history.test.ts +579 -571
  85. package/src/request/body.ts +255 -255
  86. package/src/request/metadata.ts +65 -65
  87. package/src/request/retry.test.ts +156 -156
  88. package/src/request/retry.ts +67 -67
  89. package/src/request/url.ts +21 -21
  90. package/src/request-orchestration-helpers.ts +648 -0
  91. package/src/response/index.ts +5 -5
  92. package/src/response/mcp.ts +58 -58
  93. package/src/response/streaming.test.ts +313 -311
  94. package/src/response/streaming.ts +412 -410
  95. package/src/rotation.test.ts +304 -301
  96. package/src/rotation.ts +205 -205
  97. package/src/storage.test.ts +547 -547
  98. package/src/storage.ts +315 -291
  99. package/src/system-prompt/builder.ts +38 -38
  100. package/src/system-prompt/index.ts +5 -5
  101. package/src/system-prompt/normalize.ts +60 -60
  102. package/src/system-prompt/sanitize.ts +30 -30
  103. package/src/thinking.ts +21 -20
  104. package/src/token-refresh.test.ts +265 -265
  105. package/src/token-refresh.ts +219 -214
  106. package/src/types.ts +30 -30
  107. package/dist/bun-proxy.mjs +0 -291
@@ -1,291 +0,0 @@
1
- // src/bun-proxy.ts
2
- import { resolve } from "node:path";
3
- import { fileURLToPath } from "node:url";
4
-
5
- // src/parent-pid-watcher.ts
6
- var DEFAULT_POLL_INTERVAL_MS = 5e3;
7
- function assertValidParentPid(parentPid) {
8
- if (!Number.isInteger(parentPid) || parentPid <= 0) {
9
- throw new Error("Parent PID must be a positive integer.");
10
- }
11
- }
12
- function assertValidPollInterval(pollIntervalMs) {
13
- if (!Number.isFinite(pollIntervalMs) || pollIntervalMs <= 0) {
14
- throw new Error("Poll interval must be a positive number.");
15
- }
16
- }
17
- function isParentAlive(parentPid) {
18
- try {
19
- process.kill(parentPid, 0);
20
- return true;
21
- } catch (error) {
22
- const code = error.code;
23
- if (code === "ESRCH") {
24
- return false;
25
- }
26
- if (code === "EPERM") {
27
- return true;
28
- }
29
- return true;
30
- }
31
- }
32
- var ParentPidWatcher = class {
33
- parentPid;
34
- pollIntervalMs;
35
- onParentGone;
36
- interval = null;
37
- shouldMonitorPpidDrift = false;
38
- constructor(options) {
39
- this.parentPid = options.parentPid;
40
- this.pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
41
- this.onParentGone = options.onParentGone;
42
- }
43
- start() {
44
- if (this.interval) {
45
- return;
46
- }
47
- assertValidParentPid(this.parentPid);
48
- assertValidPollInterval(this.pollIntervalMs);
49
- this.shouldMonitorPpidDrift = process.ppid === this.parentPid;
50
- this.interval = setInterval(() => {
51
- if (this.shouldMonitorPpidDrift && process.ppid !== this.parentPid) {
52
- this.handleParentGone();
53
- return;
54
- }
55
- if (!isParentAlive(this.parentPid)) {
56
- this.handleParentGone();
57
- }
58
- }, this.pollIntervalMs);
59
- }
60
- stop() {
61
- if (!this.interval) {
62
- return;
63
- }
64
- clearInterval(this.interval);
65
- this.interval = null;
66
- this.shouldMonitorPpidDrift = false;
67
- }
68
- handleParentGone() {
69
- this.stop();
70
- this.onParentGone();
71
- }
72
- };
73
-
74
- // src/bun-proxy.ts
75
- var DEFAULT_ALLOWED_HOSTS = ["api.anthropic.com", "platform.claude.com"];
76
- var DEFAULT_REQUEST_TIMEOUT_MS = 6e5;
77
- var DEFAULT_PARENT_EXIT_CODE = 1;
78
- var DEFAULT_PARENT_POLL_INTERVAL_MS = 5e3;
79
- var HEALTH_PATH = "/__health";
80
- var DEBUG_ENABLED = process.env.OPENCODE_ANTHROPIC_DEBUG === "1";
81
- function isMainModule(argv = process.argv) {
82
- return Boolean(argv[1]) && resolve(argv[1]) === fileURLToPath(import.meta.url);
83
- }
84
- function parseInteger(value) {
85
- const parsed = Number.parseInt(value ?? "", 10);
86
- return Number.isInteger(parsed) && parsed > 0 ? parsed : null;
87
- }
88
- function parseParentPid(argv) {
89
- const inlineValue = argv.map((argument) => argument.match(/^--parent-pid=(\d+)$/)?.[1] ?? null).find((value) => value !== null);
90
- if (inlineValue) {
91
- return parseInteger(inlineValue);
92
- }
93
- const flagIndex = argv.indexOf("--parent-pid");
94
- return flagIndex >= 0 ? parseInteger(argv[flagIndex + 1]) : null;
95
- }
96
- function createNoopWatcher() {
97
- return {
98
- start() {
99
- },
100
- stop() {
101
- }
102
- };
103
- }
104
- function createDefaultParentWatcherFactory() {
105
- return ({ parentPid, onParentExit, pollIntervalMs, exitCode }) => new ParentPidWatcher({
106
- parentPid,
107
- pollIntervalMs,
108
- onParentGone: () => {
109
- onParentExit(exitCode);
110
- }
111
- });
112
- }
113
- function sanitizeForwardHeaders(source) {
114
- const headers = new Headers(source);
115
- ["x-proxy-url", "host", "connection", "content-length"].forEach((headerName) => {
116
- headers.delete(headerName);
117
- });
118
- return headers;
119
- }
120
- function copyResponseHeaders(source) {
121
- const headers = new Headers(source);
122
- ["transfer-encoding", "content-encoding"].forEach((headerName) => {
123
- headers.delete(headerName);
124
- });
125
- return headers;
126
- }
127
- function resolveTargetUrl(req, allowedHosts) {
128
- const targetUrl = req.headers.get("x-proxy-url");
129
- if (!targetUrl) {
130
- return new Response("Missing x-proxy-url", { status: 400 });
131
- }
132
- try {
133
- const parsedUrl = new URL(targetUrl);
134
- if (allowedHosts.size > 0 && !allowedHosts.has(parsedUrl.hostname)) {
135
- return new Response(`Host not allowed: ${parsedUrl.hostname}`, { status: 403 });
136
- }
137
- return parsedUrl;
138
- } catch {
139
- return new Response("Invalid x-proxy-url", { status: 400 });
140
- }
141
- }
142
- function createAbortContext(requestTimeoutMs) {
143
- const timeoutController = new AbortController();
144
- const timer = setTimeout(() => {
145
- timeoutController.abort(new DOMException("Upstream request timed out", "TimeoutError"));
146
- }, requestTimeoutMs);
147
- timer.unref?.();
148
- return {
149
- timeoutSignal: timeoutController.signal,
150
- cancelTimeout() {
151
- clearTimeout(timer);
152
- }
153
- };
154
- }
155
- function isAbortError(error) {
156
- return error instanceof DOMException ? error.name === "AbortError" || error.name === "TimeoutError" : error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError");
157
- }
158
- function isTimeoutAbort(signal) {
159
- const reason = signal.reason;
160
- return reason instanceof DOMException ? reason.name === "TimeoutError" : reason instanceof Error && reason.name === "TimeoutError";
161
- }
162
- function createAbortResponse(req, timeoutSignal) {
163
- return req.signal.aborted ? new Response("Client disconnected", { status: 499 }) : isTimeoutAbort(timeoutSignal) ? new Response("Upstream request timed out", { status: 504 }) : new Response("Upstream request aborted", { status: 499 });
164
- }
165
- async function createUpstreamInit(req, signal) {
166
- const method = req.method || "GET";
167
- const hasBody = method !== "GET" && method !== "HEAD";
168
- const bodyText = hasBody ? await req.text() : "";
169
- return {
170
- method,
171
- headers: sanitizeForwardHeaders(req.headers),
172
- signal,
173
- ...hasBody && bodyText.length > 0 ? { body: bodyText } : {}
174
- };
175
- }
176
- function logRequest(targetUrl, req) {
177
- if (!DEBUG_ENABLED) {
178
- return;
179
- }
180
- const logHeaders = Object.fromEntries(
181
- [...sanitizeForwardHeaders(req.headers).entries()].map(([key, value]) => [
182
- key,
183
- key === "authorization" ? "Bearer ***" : value
184
- ])
185
- );
186
- console.error("\n[bun-proxy] === FORWARDED REQUEST ===");
187
- console.error(`[bun-proxy] ${req.method} ${targetUrl.toString()}`);
188
- console.error(`[bun-proxy] Headers: ${JSON.stringify(logHeaders, null, 2)}`);
189
- console.error("[bun-proxy] =========================\n");
190
- }
191
- function createProxyRequestHandler(options) {
192
- const allowedHosts = new Set(options.allowHosts ?? DEFAULT_ALLOWED_HOSTS);
193
- const requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
194
- return async function handleProxyRequest(req) {
195
- if (new URL(req.url).pathname === HEALTH_PATH) {
196
- return new Response("ok");
197
- }
198
- const targetUrl = resolveTargetUrl(req, allowedHosts);
199
- if (targetUrl instanceof Response) {
200
- return targetUrl;
201
- }
202
- const abortContext = createAbortContext(requestTimeoutMs);
203
- const upstreamSignal = AbortSignal.any([req.signal, abortContext.timeoutSignal]);
204
- const upstreamInit = await createUpstreamInit(req, upstreamSignal);
205
- logRequest(targetUrl, req);
206
- try {
207
- const upstreamResponse = await options.fetchImpl(targetUrl.toString(), upstreamInit);
208
- return new Response(upstreamResponse.body, {
209
- status: upstreamResponse.status,
210
- statusText: upstreamResponse.statusText,
211
- headers: copyResponseHeaders(upstreamResponse.headers)
212
- });
213
- } catch (error) {
214
- if (upstreamSignal.aborted && isAbortError(error)) {
215
- return createAbortResponse(req, abortContext.timeoutSignal);
216
- }
217
- const message = error instanceof Error ? error.message : String(error);
218
- return new Response(message, { status: 502 });
219
- } finally {
220
- abortContext.cancelTimeout();
221
- }
222
- };
223
- }
224
- function createProxyProcessRuntime(options = {}) {
225
- const argv = options.argv ?? process.argv;
226
- const parentPid = parseParentPid(argv);
227
- if (!parentPid) {
228
- return createNoopWatcher();
229
- }
230
- const exit = options.exit ?? process.exit;
231
- const parentWatcherFactory = options.parentWatcherFactory ?? createDefaultParentWatcherFactory();
232
- return parentWatcherFactory({
233
- parentPid,
234
- pollIntervalMs: DEFAULT_PARENT_POLL_INTERVAL_MS,
235
- exitCode: DEFAULT_PARENT_EXIT_CODE,
236
- onParentExit: (exitCode) => {
237
- exit(exitCode ?? DEFAULT_PARENT_EXIT_CODE);
238
- }
239
- });
240
- }
241
- function assertBunRuntime() {
242
- if (typeof Bun === "undefined") {
243
- throw new Error("bun-proxy.ts must be executed with Bun.");
244
- }
245
- return Bun;
246
- }
247
- async function runProxyProcess() {
248
- const bun = assertBunRuntime();
249
- const watcher = createProxyProcessRuntime();
250
- const server = bun.serve({
251
- port: 0,
252
- fetch: createProxyRequestHandler({
253
- fetchImpl: fetch,
254
- allowHosts: DEFAULT_ALLOWED_HOSTS,
255
- requestTimeoutMs: DEFAULT_REQUEST_TIMEOUT_MS
256
- })
257
- });
258
- const lifecycle = {
259
- closed: false
260
- };
261
- const shutdown = (exitCode = 0) => {
262
- if (lifecycle.closed) {
263
- return;
264
- }
265
- lifecycle.closed = true;
266
- watcher.stop();
267
- server.stop(true);
268
- process.exit(exitCode);
269
- };
270
- process.on("SIGTERM", () => {
271
- shutdown(0);
272
- });
273
- process.on("SIGINT", () => {
274
- shutdown(0);
275
- });
276
- watcher.start();
277
- process.stdout.write(`BUN_PROXY_PORT=${server.port}
278
- `);
279
- }
280
- if (isMainModule()) {
281
- void runProxyProcess().catch((error) => {
282
- const message = error instanceof Error ? error.stack ?? error.message : String(error);
283
- process.stderr.write(`${message}
284
- `);
285
- process.exit(1);
286
- });
287
- }
288
- export {
289
- createProxyProcessRuntime,
290
- createProxyRequestHandler
291
- };