@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,31 +1,31 @@
1
1
  export enum CircuitState {
2
- CLOSED = "CLOSED",
3
- OPEN = "OPEN",
4
- HALF_OPEN = "HALF_OPEN",
2
+ CLOSED = "CLOSED",
3
+ OPEN = "OPEN",
4
+ HALF_OPEN = "HALF_OPEN",
5
5
  }
6
6
 
7
7
  export const BreakerState = CircuitState;
8
8
 
9
9
  export interface CircuitBreakerOptions {
10
- clientId?: string;
11
- failureThreshold?: number;
12
- resetTimeoutMs?: number;
10
+ clientId?: string;
11
+ failureThreshold?: number;
12
+ resetTimeoutMs?: number;
13
13
  }
14
14
 
15
15
  export interface CircuitBreakerConfig {
16
- clientId?: string;
17
- failureThreshold: number;
18
- resetTimeoutMs: number;
16
+ clientId?: string;
17
+ failureThreshold: number;
18
+ resetTimeoutMs: number;
19
19
  }
20
20
 
21
21
  export interface CircuitBreakerSuccess<T> {
22
- success: true;
23
- data: T;
22
+ success: true;
23
+ data: T;
24
24
  }
25
25
 
26
26
  export interface CircuitBreakerFailure {
27
- success: false;
28
- error: string;
27
+ success: false;
28
+ error: string;
29
29
  }
30
30
 
31
31
  export type CircuitBreakerResult<T> = CircuitBreakerSuccess<T> | CircuitBreakerFailure;
@@ -36,200 +36,200 @@ const DEFAULT_RESET_TIMEOUT_MS = 30_000;
36
36
  const pendingClientBreakers = new Map<string, CircuitBreaker>();
37
37
 
38
38
  function normalizeConfig(options: CircuitBreakerOptions = {}): CircuitBreakerConfig {
39
- return {
40
- clientId: options.clientId,
41
- failureThreshold: Math.max(1, Math.trunc(options.failureThreshold ?? DEFAULT_FAILURE_THRESHOLD)),
42
- resetTimeoutMs: Math.max(0, Math.trunc(options.resetTimeoutMs ?? DEFAULT_RESET_TIMEOUT_MS)),
43
- };
39
+ return {
40
+ clientId: options.clientId,
41
+ failureThreshold: Math.max(1, Math.trunc(options.failureThreshold ?? DEFAULT_FAILURE_THRESHOLD)),
42
+ resetTimeoutMs: Math.max(0, Math.trunc(options.resetTimeoutMs ?? DEFAULT_RESET_TIMEOUT_MS)),
43
+ };
44
44
  }
45
45
 
46
46
  function getErrorMessage(error: unknown): string {
47
- if (error instanceof Error && error.message) {
48
- return error.message;
49
- }
47
+ if (error instanceof Error && error.message) {
48
+ return error.message;
49
+ }
50
50
 
51
- if (typeof error === "string" && error) {
52
- return error;
53
- }
51
+ if (typeof error === "string" && error) {
52
+ return error;
53
+ }
54
54
 
55
- return "Unknown error";
55
+ return "Unknown error";
56
56
  }
57
57
 
58
58
  function isPromiseLike<T>(value: T | Promise<T>): value is Promise<T> {
59
- return typeof value === "object" && value !== null && "then" in value;
59
+ return typeof value === "object" && value !== null && "then" in value;
60
60
  }
61
61
 
62
62
  function releasePendingClientBreaker(clientId: string, breaker: CircuitBreaker): void {
63
- queueMicrotask(() => {
64
- if (pendingClientBreakers.get(clientId) === breaker) {
65
- pendingClientBreakers.delete(clientId);
66
- }
67
- });
63
+ queueMicrotask(() => {
64
+ if (pendingClientBreakers.get(clientId) === breaker) {
65
+ pendingClientBreakers.delete(clientId);
66
+ }
67
+ });
68
68
  }
69
69
 
70
70
  export class CircuitBreaker {
71
- private readonly config: CircuitBreakerConfig;
72
-
73
- private state = CircuitState.CLOSED;
74
- private failureCount = 0;
75
- private openedAt: number | null = null;
76
- private resetTimer: ReturnType<typeof setTimeout> | null = null;
71
+ private readonly config: CircuitBreakerConfig;
77
72
 
78
- constructor(options: CircuitBreakerOptions = {}) {
79
- this.config = normalizeConfig(options);
80
- }
73
+ private state = CircuitState.CLOSED;
74
+ private failureCount = 0;
75
+ private openedAt: number | null = null;
76
+ private resetTimer: ReturnType<typeof setTimeout> | null = null;
81
77
 
82
- getState(): CircuitState {
83
- return this.state;
84
- }
85
-
86
- getFailureCount(): number {
87
- return this.failureCount;
88
- }
89
-
90
- getOpenedAt(): number | null {
91
- return this.openedAt;
92
- }
93
-
94
- getConfig(): CircuitBreakerConfig {
95
- return { ...this.config };
96
- }
78
+ constructor(options: CircuitBreakerOptions = {}) {
79
+ this.config = normalizeConfig(options);
80
+ }
97
81
 
98
- canExecute(): boolean {
99
- return this.state !== CircuitState.OPEN;
100
- }
82
+ getState(): CircuitState {
83
+ return this.state;
84
+ }
101
85
 
102
- recordSuccess(): void {
103
- if (this.state === CircuitState.HALF_OPEN) {
104
- this.transitionToClosed();
105
- return;
86
+ getFailureCount(): number {
87
+ return this.failureCount;
106
88
  }
107
89
 
108
- if (this.state === CircuitState.CLOSED) {
109
- this.failureCount = 0;
90
+ getOpenedAt(): number | null {
91
+ return this.openedAt;
110
92
  }
111
- }
112
93
 
113
- recordFailure(): void {
114
- if (this.state === CircuitState.HALF_OPEN) {
115
- this.transitionToOpen();
116
- return;
94
+ getConfig(): CircuitBreakerConfig {
95
+ return { ...this.config };
117
96
  }
118
97
 
119
- if (this.state === CircuitState.OPEN) {
120
- return;
98
+ canExecute(): boolean {
99
+ return this.state !== CircuitState.OPEN;
121
100
  }
122
101
 
123
- this.failureCount += 1;
102
+ recordSuccess(): void {
103
+ if (this.state === CircuitState.HALF_OPEN) {
104
+ this.transitionToClosed();
105
+ return;
106
+ }
124
107
 
125
- if (this.failureCount >= this.config.failureThreshold) {
126
- this.transitionToOpen();
108
+ if (this.state === CircuitState.CLOSED) {
109
+ this.failureCount = 0;
110
+ }
127
111
  }
128
- }
129
112
 
130
- transitionToHalfOpen(): void {
131
- this.clearResetTimer();
132
- this.state = CircuitState.HALF_OPEN;
133
- this.openedAt = null;
134
- this.failureCount = 0;
135
- }
113
+ recordFailure(): void {
114
+ if (this.state === CircuitState.HALF_OPEN) {
115
+ this.transitionToOpen();
116
+ return;
117
+ }
118
+
119
+ if (this.state === CircuitState.OPEN) {
120
+ return;
121
+ }
122
+
123
+ this.failureCount += 1;
124
+
125
+ if (this.failureCount >= this.config.failureThreshold) {
126
+ this.transitionToOpen();
127
+ }
128
+ }
136
129
 
137
- execute<T>(
138
- operation: () => T | Promise<T>,
139
- ): CircuitBreakerResult<Awaited<T>> | Promise<CircuitBreakerResult<Awaited<T>>> {
140
- if (!this.canExecute()) {
141
- return {
142
- success: false,
143
- error: "Circuit breaker is OPEN",
144
- };
130
+ transitionToHalfOpen(): void {
131
+ this.clearResetTimer();
132
+ this.state = CircuitState.HALF_OPEN;
133
+ this.openedAt = null;
134
+ this.failureCount = 0;
145
135
  }
146
136
 
147
- try {
148
- const result = operation();
137
+ execute<T>(
138
+ operation: () => T | Promise<T>,
139
+ ): CircuitBreakerResult<Awaited<T>> | Promise<CircuitBreakerResult<Awaited<T>>> {
140
+ if (!this.canExecute()) {
141
+ return {
142
+ success: false,
143
+ error: "Circuit breaker is OPEN",
144
+ };
145
+ }
146
+
147
+ try {
148
+ const result = operation();
149
+
150
+ if (isPromiseLike(result)) {
151
+ return result
152
+ .then((data) => {
153
+ this.recordSuccess();
154
+ return {
155
+ success: true,
156
+ data: data as Awaited<T>,
157
+ } satisfies CircuitBreakerSuccess<Awaited<T>>;
158
+ })
159
+ .catch((error: unknown) => {
160
+ this.recordFailure();
161
+ return {
162
+ success: false,
163
+ error: getErrorMessage(error),
164
+ } satisfies CircuitBreakerFailure;
165
+ });
166
+ }
149
167
 
150
- if (isPromiseLike(result)) {
151
- return result
152
- .then((data) => {
153
168
  this.recordSuccess();
154
169
  return {
155
- success: true,
156
- data: data as Awaited<T>,
157
- } satisfies CircuitBreakerSuccess<Awaited<T>>;
158
- })
159
- .catch((error: unknown) => {
170
+ success: true,
171
+ data: result as Awaited<T>,
172
+ };
173
+ } catch (error) {
160
174
  this.recordFailure();
161
175
  return {
162
- success: false,
163
- error: getErrorMessage(error),
164
- } satisfies CircuitBreakerFailure;
165
- });
166
- }
167
-
168
- this.recordSuccess();
169
- return {
170
- success: true,
171
- data: result as Awaited<T>,
172
- };
173
- } catch (error) {
174
- this.recordFailure();
175
- return {
176
- success: false,
177
- error: getErrorMessage(error),
178
- };
179
- }
180
- }
181
-
182
- dispose(): void {
183
- this.clearResetTimer();
184
- }
185
-
186
- private transitionToClosed(): void {
187
- this.clearResetTimer();
188
- this.state = CircuitState.CLOSED;
189
- this.failureCount = 0;
190
- this.openedAt = null;
191
- }
192
-
193
- private transitionToOpen(): void {
194
- this.clearResetTimer();
195
- this.state = CircuitState.OPEN;
196
- this.openedAt = Date.now();
197
- this.scheduleHalfOpenTransition();
198
- }
199
-
200
- private scheduleHalfOpenTransition(): void {
201
- this.resetTimer = setTimeout(() => {
202
- this.resetTimer = null;
203
- if (this.state === CircuitState.OPEN) {
204
- this.transitionToHalfOpen();
205
- }
206
- }, this.config.resetTimeoutMs);
207
-
208
- this.resetTimer.unref?.();
209
- }
210
-
211
- private clearResetTimer(): void {
212
- if (!this.resetTimer) {
213
- return;
214
- }
215
-
216
- clearTimeout(this.resetTimer);
217
- this.resetTimer = null;
218
- }
176
+ success: false,
177
+ error: getErrorMessage(error),
178
+ };
179
+ }
180
+ }
181
+
182
+ dispose(): void {
183
+ this.clearResetTimer();
184
+ }
185
+
186
+ private transitionToClosed(): void {
187
+ this.clearResetTimer();
188
+ this.state = CircuitState.CLOSED;
189
+ this.failureCount = 0;
190
+ this.openedAt = null;
191
+ }
192
+
193
+ private transitionToOpen(): void {
194
+ this.clearResetTimer();
195
+ this.state = CircuitState.OPEN;
196
+ this.openedAt = Date.now();
197
+ this.scheduleHalfOpenTransition();
198
+ }
199
+
200
+ private scheduleHalfOpenTransition(): void {
201
+ this.resetTimer = setTimeout(() => {
202
+ this.resetTimer = null;
203
+ if (this.state === CircuitState.OPEN) {
204
+ this.transitionToHalfOpen();
205
+ }
206
+ }, this.config.resetTimeoutMs);
207
+
208
+ this.resetTimer.unref?.();
209
+ }
210
+
211
+ private clearResetTimer(): void {
212
+ if (!this.resetTimer) {
213
+ return;
214
+ }
215
+
216
+ clearTimeout(this.resetTimer);
217
+ this.resetTimer = null;
218
+ }
219
219
  }
220
220
 
221
221
  export function createCircuitBreaker(options: CircuitBreakerOptions = {}): CircuitBreaker {
222
- if (!options.clientId) {
223
- return new CircuitBreaker(options);
224
- }
225
-
226
- const existingBreaker = pendingClientBreakers.get(options.clientId);
227
- if (existingBreaker) {
228
- return existingBreaker;
229
- }
230
-
231
- const breaker = new CircuitBreaker(options);
232
- pendingClientBreakers.set(options.clientId, breaker);
233
- releasePendingClientBreaker(options.clientId, breaker);
234
- return breaker;
222
+ if (!options.clientId) {
223
+ return new CircuitBreaker(options);
224
+ }
225
+
226
+ const existingBreaker = pendingClientBreakers.get(options.clientId);
227
+ if (existingBreaker) {
228
+ return existingBreaker;
229
+ }
230
+
231
+ const breaker = new CircuitBreaker(options);
232
+ pendingClientBreakers.set(options.clientId, breaker);
233
+ releasePendingClientBreaker(options.clientId, breaker);
234
+ return breaker;
235
235
  }