@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.
- package/README.md +88 -88
- package/dist/opencode-anthropic-auth-cli.mjs +804 -507
- package/dist/opencode-anthropic-auth-plugin.js +4751 -4109
- package/package.json +67 -59
- package/src/__tests__/billing-edge-cases.test.ts +59 -59
- package/src/__tests__/bun-proxy.parallel.test.ts +388 -382
- package/src/__tests__/cc-comparison.test.ts +87 -87
- package/src/__tests__/cc-credentials.test.ts +254 -250
- package/src/__tests__/cch-drift-checker.test.ts +51 -51
- package/src/__tests__/cch-native-style.test.ts +56 -56
- package/src/__tests__/debug-gating.test.ts +42 -42
- package/src/__tests__/decomposition-smoke.test.ts +68 -68
- package/src/__tests__/fingerprint-regression.test.ts +575 -566
- package/src/__tests__/helpers/conversation-history.smoke.test.ts +271 -271
- package/src/__tests__/helpers/conversation-history.ts +119 -119
- package/src/__tests__/helpers/deferred.smoke.test.ts +103 -103
- package/src/__tests__/helpers/deferred.ts +69 -69
- package/src/__tests__/helpers/in-memory-storage.smoke.test.ts +155 -155
- package/src/__tests__/helpers/in-memory-storage.ts +88 -88
- package/src/__tests__/helpers/mock-bun-proxy.smoke.test.ts +68 -68
- package/src/__tests__/helpers/mock-bun-proxy.ts +189 -189
- package/src/__tests__/helpers/plugin-fetch-harness.smoke.test.ts +273 -273
- package/src/__tests__/helpers/plugin-fetch-harness.ts +288 -288
- package/src/__tests__/helpers/sse.smoke.test.ts +236 -236
- package/src/__tests__/helpers/sse.ts +209 -209
- package/src/__tests__/index.parallel.test.ts +605 -595
- package/src/__tests__/sanitization-regex.test.ts +112 -112
- package/src/__tests__/state-bounds.test.ts +90 -90
- package/src/account-identity.test.ts +197 -192
- package/src/account-identity.ts +69 -67
- package/src/account-state.test.ts +86 -86
- package/src/account-state.ts +25 -25
- package/src/accounts/matching.test.ts +335 -0
- package/src/accounts/matching.ts +167 -0
- package/src/accounts/persistence.test.ts +345 -0
- package/src/accounts/persistence.ts +432 -0
- package/src/accounts/repair.test.ts +276 -0
- package/src/accounts/repair.ts +407 -0
- package/src/accounts.dedup.test.ts +621 -621
- package/src/accounts.test.ts +933 -929
- package/src/accounts.ts +633 -989
- package/src/backoff.test.ts +345 -345
- package/src/backoff.ts +219 -219
- package/src/betas.ts +124 -124
- package/src/bun-fetch.test.ts +345 -342
- package/src/bun-fetch.ts +424 -424
- package/src/bun-proxy.test.ts +25 -25
- package/src/bun-proxy.ts +209 -209
- package/src/cc-credentials.ts +111 -111
- package/src/circuit-breaker.test.ts +184 -184
- package/src/circuit-breaker.ts +169 -169
- package/src/cli/commands/auth.ts +963 -0
- package/src/cli/commands/config.ts +547 -0
- package/src/cli/formatting.test.ts +406 -0
- package/src/cli/formatting.ts +219 -0
- package/src/cli.ts +255 -2022
- package/src/commands/handlers/betas.ts +100 -0
- package/src/commands/handlers/config.ts +99 -0
- package/src/commands/handlers/files.ts +375 -0
- package/src/commands/oauth-flow.ts +181 -166
- package/src/commands/prompts.ts +61 -61
- package/src/commands/router.test.ts +421 -0
- package/src/commands/router.ts +143 -635
- package/src/config.test.ts +482 -482
- package/src/config.ts +412 -404
- package/src/constants.ts +48 -48
- package/src/drift/cch-constants.ts +95 -95
- package/src/env.ts +111 -105
- package/src/headers/billing.ts +33 -33
- package/src/headers/builder.ts +130 -130
- package/src/headers/cch.ts +75 -75
- package/src/headers/stainless.ts +25 -25
- package/src/headers/user-agent.ts +23 -23
- package/src/index.ts +436 -828
- package/src/models.ts +27 -27
- package/src/oauth.test.ts +102 -102
- package/src/oauth.ts +178 -178
- package/src/parent-pid-watcher.test.ts +148 -148
- package/src/parent-pid-watcher.ts +69 -69
- package/src/plugin-helpers.ts +82 -82
- package/src/refresh-helpers.ts +145 -139
- package/src/refresh-lock.test.ts +94 -94
- package/src/refresh-lock.ts +93 -93
- package/src/request/body.history.test.ts +579 -571
- package/src/request/body.ts +255 -255
- package/src/request/metadata.ts +65 -65
- package/src/request/retry.test.ts +156 -156
- package/src/request/retry.ts +67 -67
- package/src/request/url.ts +21 -21
- package/src/request-orchestration-helpers.ts +648 -0
- package/src/response/index.ts +5 -5
- package/src/response/mcp.ts +58 -58
- package/src/response/streaming.test.ts +313 -311
- package/src/response/streaming.ts +412 -410
- package/src/rotation.test.ts +304 -301
- package/src/rotation.ts +205 -205
- package/src/storage.test.ts +547 -547
- package/src/storage.ts +315 -291
- package/src/system-prompt/builder.ts +38 -38
- package/src/system-prompt/index.ts +5 -5
- package/src/system-prompt/normalize.ts +60 -60
- package/src/system-prompt/sanitize.ts +30 -30
- package/src/thinking.ts +21 -20
- package/src/token-refresh.test.ts +265 -265
- package/src/token-refresh.ts +219 -214
- package/src/types.ts +30 -30
- package/dist/bun-proxy.mjs +0 -291
package/src/circuit-breaker.ts
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
export enum CircuitState {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
clientId?: string;
|
|
11
|
+
failureThreshold?: number;
|
|
12
|
+
resetTimeoutMs?: number;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export interface CircuitBreakerConfig {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
clientId?: string;
|
|
17
|
+
failureThreshold: number;
|
|
18
|
+
resetTimeoutMs: number;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export interface CircuitBreakerSuccess<T> {
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
success: true;
|
|
23
|
+
data: T;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export interface CircuitBreakerFailure {
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
if (error instanceof Error && error.message) {
|
|
48
|
+
return error.message;
|
|
49
|
+
}
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
if (typeof error === "string" && error) {
|
|
52
|
+
return error;
|
|
53
|
+
}
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
return "Unknown error";
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
function isPromiseLike<T>(value: T | Promise<T>): value is Promise<T> {
|
|
59
|
-
|
|
59
|
+
return typeof value === "object" && value !== null && "then" in value;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
function releasePendingClientBreaker(clientId: string, breaker: CircuitBreaker): void {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
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
|
-
|
|
79
|
-
|
|
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
|
-
|
|
83
|
-
|
|
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
|
-
|
|
99
|
-
|
|
100
|
-
|
|
82
|
+
getState(): CircuitState {
|
|
83
|
+
return this.state;
|
|
84
|
+
}
|
|
101
85
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
this.transitionToClosed();
|
|
105
|
-
return;
|
|
86
|
+
getFailureCount(): number {
|
|
87
|
+
return this.failureCount;
|
|
106
88
|
}
|
|
107
89
|
|
|
108
|
-
|
|
109
|
-
|
|
90
|
+
getOpenedAt(): number | null {
|
|
91
|
+
return this.openedAt;
|
|
110
92
|
}
|
|
111
|
-
}
|
|
112
93
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
this.transitionToOpen();
|
|
116
|
-
return;
|
|
94
|
+
getConfig(): CircuitBreakerConfig {
|
|
95
|
+
return { ...this.config };
|
|
117
96
|
}
|
|
118
97
|
|
|
119
|
-
|
|
120
|
-
|
|
98
|
+
canExecute(): boolean {
|
|
99
|
+
return this.state !== CircuitState.OPEN;
|
|
121
100
|
}
|
|
122
101
|
|
|
123
|
-
|
|
102
|
+
recordSuccess(): void {
|
|
103
|
+
if (this.state === CircuitState.HALF_OPEN) {
|
|
104
|
+
this.transitionToClosed();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
124
107
|
|
|
125
|
-
|
|
126
|
-
|
|
108
|
+
if (this.state === CircuitState.CLOSED) {
|
|
109
|
+
this.failureCount = 0;
|
|
110
|
+
}
|
|
127
111
|
}
|
|
128
|
-
}
|
|
129
112
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
148
|
-
|
|
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
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
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
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
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
|
}
|