@cortexkit/anthropic-auth-core 1.20.0 → 1.22.0
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 +1 -1
- package/dist/accounts.d.ts +66 -16
- package/dist/accounts.js +693 -223
- package/dist/auth.js +3 -10
- package/dist/cch.d.ts +13 -9
- package/dist/cch.js +57 -19
- package/dist/claude-code.d.ts +4 -3
- package/dist/claude-code.js +130 -25
- package/dist/claustrum.d.ts +109 -0
- package/dist/claustrum.js +529 -0
- package/dist/commands/account.d.ts +5 -1
- package/dist/commands/account.js +16 -2
- package/dist/constants.d.ts +4 -5
- package/dist/constants.js +4 -5
- package/dist/dump.d.ts +1 -0
- package/dist/dump.js +8 -2
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/json.d.ts +1 -0
- package/dist/json.js +10 -0
- package/dist/mid-conversation-output-config.d.ts +13 -0
- package/dist/mid-conversation-output-config.js +89 -0
- package/dist/models.d.ts +27 -1
- package/dist/models.js +43 -0
- package/dist/network-errors.d.ts +1 -0
- package/dist/network-errors.js +27 -0
- package/dist/oauth-profile.d.ts +2 -1
- package/dist/oauth-profile.js +10 -4
- package/dist/quota-header-feed.d.ts +52 -0
- package/dist/quota-header-feed.js +279 -0
- package/dist/quota-headers.js +63 -8
- package/dist/quota-manager.d.ts +41 -28
- package/dist/quota-manager.js +405 -148
- package/dist/sticky-routing.d.ts +14 -2
- package/dist/sticky-routing.js +30 -13
- package/dist/thinking-binding.d.ts +7 -0
- package/dist/thinking-binding.js +54 -0
- package/package.json +3 -1
package/dist/sticky-routing.d.ts
CHANGED
|
@@ -3,9 +3,21 @@ export declare const STICKY_ROUTING_MAIN_ACCOUNT_ID = "main";
|
|
|
3
3
|
export declare const STICKY_ROUTING_SHORT_RESET_GRACE_MS: number;
|
|
4
4
|
export declare const STICKY_ROUTING_ASSIGNMENT_TTL_MS: number;
|
|
5
5
|
export type StickyRouteFamily = 'fable' | 'opus' | 'general';
|
|
6
|
-
export type
|
|
6
|
+
export type IdentityState = {
|
|
7
|
+
kind: 'known';
|
|
7
8
|
accountId: string;
|
|
9
|
+
} | {
|
|
10
|
+
kind: 'unknown';
|
|
11
|
+
};
|
|
12
|
+
export type QuotaState = {
|
|
13
|
+
kind: 'known';
|
|
8
14
|
quota: OAuthQuotaSnapshot;
|
|
15
|
+
} | {
|
|
16
|
+
kind: 'unknown';
|
|
17
|
+
};
|
|
18
|
+
export type StickyRouteCandidate = {
|
|
19
|
+
accountId: string;
|
|
20
|
+
quota: OAuthQuotaSnapshot | QuotaState;
|
|
9
21
|
order: number;
|
|
10
22
|
};
|
|
11
23
|
export type StickyRouteAssignment = {
|
|
@@ -56,7 +68,7 @@ export declare function stickyRouteCandidateWeight(input: {
|
|
|
56
68
|
}): number;
|
|
57
69
|
export declare function stickyRouteKnownFableExhausted(candidate: StickyRouteCandidate, storage: AccountStorage | null, now?: number): boolean;
|
|
58
70
|
export declare function decideStickyQuotaFailure(input: {
|
|
59
|
-
quota: OAuthQuotaSnapshot | undefined;
|
|
71
|
+
quota: OAuthQuotaSnapshot | QuotaState | undefined;
|
|
60
72
|
modelId?: string;
|
|
61
73
|
now?: number;
|
|
62
74
|
}): StickyQuotaFailureDecision;
|
package/dist/sticky-routing.js
CHANGED
|
@@ -136,6 +136,13 @@ export function stickyQuotaSnapshotIsFresh(quota, storage, now = Date.now(), mod
|
|
|
136
136
|
function snapshotCheckedAt(quota) {
|
|
137
137
|
return Math.max(quota.checkedAt ?? 0, quota.five_hour?.checkedAt ?? 0, quota.seven_day?.checkedAt ?? 0, ...(quota.scoped ?? []).map((window) => window.checkedAt ?? 0));
|
|
138
138
|
}
|
|
139
|
+
function knownQuota(quota) {
|
|
140
|
+
if (!quota)
|
|
141
|
+
return undefined;
|
|
142
|
+
if ('kind' in quota)
|
|
143
|
+
return quota.kind === 'known' ? quota.quota : undefined;
|
|
144
|
+
return quota;
|
|
145
|
+
}
|
|
139
146
|
function remainingThreshold(storage, accountId, key) {
|
|
140
147
|
const quotaMinimum = getQuotaMinimumRemainingThresholds(storage);
|
|
141
148
|
const quotaThreshold = key === 'five_hour'
|
|
@@ -170,18 +177,21 @@ export function stickyRouteFamilyForModel(model) {
|
|
|
170
177
|
export function stickyRouteCandidateWeight(input) {
|
|
171
178
|
const now = input.now ?? Date.now();
|
|
172
179
|
const { candidate, storage } = input;
|
|
173
|
-
|
|
180
|
+
const quota = knownQuota(candidate.quota);
|
|
181
|
+
if (!quota)
|
|
182
|
+
return 0;
|
|
183
|
+
if (!stickyQuotaSnapshotIsFresh(quota, storage, now, input.modelId)) {
|
|
174
184
|
return 0;
|
|
175
185
|
}
|
|
176
186
|
const weights = [];
|
|
177
187
|
for (const key of ['five_hour', 'seven_day']) {
|
|
178
|
-
const window =
|
|
188
|
+
const window = quota[key];
|
|
179
189
|
if (!window || !Number.isFinite(window.remainingPercent))
|
|
180
190
|
return 0;
|
|
181
191
|
weights.push(sustainableWindowWeight(window.remainingPercent, remainingThreshold(storage, candidate.accountId, key), window.resetsAt, now));
|
|
182
192
|
}
|
|
183
193
|
if (input.family === 'fable') {
|
|
184
|
-
const window = getScopedQuotaWindowForModel(
|
|
194
|
+
const window = getScopedQuotaWindowForModel(quota, input.modelId);
|
|
185
195
|
if (window && Number.isFinite(window.remainingPercent)) {
|
|
186
196
|
weights.push(sustainableWindowWeight(window.remainingPercent, remainingThreshold(storage, candidate.accountId, 'scoped'), window.resetsAt, now));
|
|
187
197
|
}
|
|
@@ -189,29 +199,31 @@ export function stickyRouteCandidateWeight(input) {
|
|
|
189
199
|
return Math.min(...weights);
|
|
190
200
|
}
|
|
191
201
|
export function stickyRouteKnownFableExhausted(candidate, storage, now = Date.now()) {
|
|
192
|
-
const
|
|
202
|
+
const quota = knownQuota(candidate.quota);
|
|
203
|
+
const window = getScopedQuotaWindowForModel(quota, 'claude-fable-5');
|
|
193
204
|
return Boolean(window &&
|
|
194
|
-
stickyQuotaSnapshotIsFresh(
|
|
205
|
+
stickyQuotaSnapshotIsFresh(quota, storage, now, 'claude-fable-5') &&
|
|
195
206
|
Number.isFinite(window.remainingPercent) &&
|
|
196
207
|
window.remainingPercent <= 0);
|
|
197
208
|
}
|
|
198
209
|
export function decideStickyQuotaFailure(input) {
|
|
199
210
|
const now = input.now ?? Date.now();
|
|
200
|
-
|
|
211
|
+
const quota = knownQuota(input.quota);
|
|
212
|
+
if (!quota)
|
|
201
213
|
return { action: 'retain', reason: 'unknown' };
|
|
202
|
-
const scoped = getScopedQuotaWindowForModel(
|
|
214
|
+
const scoped = getScopedQuotaWindowForModel(quota, input.modelId);
|
|
203
215
|
if (scoped &&
|
|
204
216
|
Number.isFinite(scoped.remainingPercent) &&
|
|
205
217
|
scoped.remainingPercent <= 0) {
|
|
206
218
|
return { action: 'migrate', reason: 'model-scoped' };
|
|
207
219
|
}
|
|
208
|
-
const sevenDay =
|
|
220
|
+
const sevenDay = quota.seven_day;
|
|
209
221
|
if (sevenDay &&
|
|
210
222
|
Number.isFinite(sevenDay.remainingPercent) &&
|
|
211
223
|
sevenDay.remainingPercent <= 0) {
|
|
212
224
|
return { action: 'migrate', reason: 'seven-day' };
|
|
213
225
|
}
|
|
214
|
-
const fiveHour =
|
|
226
|
+
const fiveHour = quota.five_hour;
|
|
215
227
|
if (fiveHour &&
|
|
216
228
|
Number.isFinite(fiveHour.remainingPercent) &&
|
|
217
229
|
fiveHour.remainingPercent <= 0) {
|
|
@@ -386,14 +398,18 @@ export class StickySessionRouter {
|
|
|
386
398
|
});
|
|
387
399
|
return weight > 0 ? [{ candidate, weight }] : [];
|
|
388
400
|
});
|
|
389
|
-
if (weighted.length === 0
|
|
390
|
-
|
|
401
|
+
if (weighted.length === 0 &&
|
|
402
|
+
candidates.every((candidate) => !knownQuota(candidate.quota))) {
|
|
403
|
+
return [...candidates].sort((left, right) => left.order - right.order ||
|
|
404
|
+
left.accountId.localeCompare(right.accountId))[0];
|
|
405
|
+
}
|
|
391
406
|
const pendingBytes = new Map();
|
|
392
407
|
for (const assignment of Object.values(input.state.assignments)) {
|
|
393
408
|
const candidate = weighted.find((entry) => entry.candidate.accountId === assignment.accountId)?.candidate;
|
|
394
409
|
if (!candidate)
|
|
395
410
|
continue;
|
|
396
|
-
|
|
411
|
+
const quota = knownQuota(candidate.quota);
|
|
412
|
+
if (quota && assignment.quotaCheckedAt !== snapshotCheckedAt(quota))
|
|
397
413
|
continue;
|
|
398
414
|
pendingBytes.set(assignment.accountId, (pendingBytes.get(assignment.accountId) ?? 0) +
|
|
399
415
|
assignment.initialInputBytes);
|
|
@@ -466,13 +482,14 @@ export class StickySessionRouter {
|
|
|
466
482
|
return null;
|
|
467
483
|
}
|
|
468
484
|
const now = this.now();
|
|
485
|
+
const selectedQuota = knownQuota(selected.quota);
|
|
469
486
|
const assignment = {
|
|
470
487
|
accountId: selected.accountId,
|
|
471
488
|
family: input.family,
|
|
472
489
|
assignedAt: now,
|
|
473
490
|
lastSeenAt: now,
|
|
474
491
|
initialInputBytes: Math.max(1, input.inputBytes),
|
|
475
|
-
quotaCheckedAt: snapshotCheckedAt(
|
|
492
|
+
quotaCheckedAt: selectedQuota ? snapshotCheckedAt(selectedQuota) : 0,
|
|
476
493
|
};
|
|
477
494
|
state.assignments[key] = assignment;
|
|
478
495
|
await this.writeState(state);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AccountStorage } from './accounts.ts';
|
|
2
|
+
export declare const THINKING_BINDING_CONTROLS_BETA = "thinking-binding-controls-2026-08-01";
|
|
3
|
+
export type ThinkingPrefixMismatchBehavior = 'account-default' | 'error' | 'drop_block';
|
|
4
|
+
export declare function getThinkingPrefixMismatchBehavior(storage: Pick<AccountStorage, 'thinkingBinding'> | null | undefined): ThinkingPrefixMismatchBehavior;
|
|
5
|
+
export declare function hasReplayableThinkingBlocks(body: Record<string, unknown>): boolean;
|
|
6
|
+
export declare function applyThinkingBindingControls(body: Record<string, unknown>, behavior?: ThinkingPrefixMismatchBehavior): boolean;
|
|
7
|
+
export declare function hasThinkingBindingControls(body: Record<string, unknown>): boolean;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { isClaudeFable51Model } from './models.js';
|
|
2
|
+
export const THINKING_BINDING_CONTROLS_BETA = 'thinking-binding-controls-2026-08-01';
|
|
3
|
+
function isRecord(value) {
|
|
4
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
5
|
+
}
|
|
6
|
+
function isReplayableThinkingBlock(block) {
|
|
7
|
+
if (!isRecord(block))
|
|
8
|
+
return false;
|
|
9
|
+
if (block.type === 'thinking') {
|
|
10
|
+
return typeof block.signature === 'string' && block.signature.length > 0;
|
|
11
|
+
}
|
|
12
|
+
if (block.type === 'redacted_thinking') {
|
|
13
|
+
return typeof block.data === 'string' && block.data.length > 0;
|
|
14
|
+
}
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
export function getThinkingPrefixMismatchBehavior(storage) {
|
|
18
|
+
const behavior = storage?.thinkingBinding?.prefixMismatchBehavior;
|
|
19
|
+
return behavior === 'error' || behavior === 'drop_block'
|
|
20
|
+
? behavior
|
|
21
|
+
: 'account-default';
|
|
22
|
+
}
|
|
23
|
+
export function hasReplayableThinkingBlocks(body) {
|
|
24
|
+
if (!Array.isArray(body.messages))
|
|
25
|
+
return false;
|
|
26
|
+
return body.messages.some((message) => {
|
|
27
|
+
if (!isRecord(message) || message.role !== 'assistant')
|
|
28
|
+
return false;
|
|
29
|
+
return (Array.isArray(message.content) &&
|
|
30
|
+
message.content.some(isReplayableThinkingBlock));
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
export function applyThinkingBindingControls(body, behavior = 'account-default') {
|
|
34
|
+
if (behavior === 'account-default')
|
|
35
|
+
return false;
|
|
36
|
+
if (!isClaudeFable51Model(body.model))
|
|
37
|
+
return false;
|
|
38
|
+
if (!hasReplayableThinkingBlocks(body))
|
|
39
|
+
return false;
|
|
40
|
+
if (!isRecord(body.thinking) || body.thinking.type === 'disabled')
|
|
41
|
+
return false;
|
|
42
|
+
body.thinking.block_binding = {
|
|
43
|
+
prefix_mismatch_behavior: behavior,
|
|
44
|
+
};
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
export function hasThinkingBindingControls(body) {
|
|
48
|
+
if (!isRecord(body.thinking))
|
|
49
|
+
return false;
|
|
50
|
+
if (!isRecord(body.thinking.block_binding))
|
|
51
|
+
return false;
|
|
52
|
+
const behavior = body.thinking.block_binding.prefix_mismatch_behavior;
|
|
53
|
+
return behavior === 'error' || behavior === 'drop_block';
|
|
54
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cortexkit/anthropic-auth-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.22.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -22,11 +22,13 @@
|
|
|
22
22
|
],
|
|
23
23
|
"scripts": {
|
|
24
24
|
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
25
|
+
"test": "bun run build && bun test src/tests",
|
|
25
26
|
"typecheck": "tsc",
|
|
26
27
|
"types": "tsc",
|
|
27
28
|
"prepublishOnly": "bun run build"
|
|
28
29
|
},
|
|
29
30
|
"dependencies": {
|
|
31
|
+
"@cortexkit/subc-client": "^0.8.1",
|
|
30
32
|
"xxhash-wasm": "^1.1.0"
|
|
31
33
|
}
|
|
32
34
|
}
|