@cortexkit/anthropic-auth-core 1.21.0 → 1.23.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 +100 -3
- package/dist/accounts.js +1099 -169
- package/dist/auth.js +6 -10
- package/dist/cachekeep.d.ts +18 -1
- package/dist/cachekeep.js +108 -82
- package/dist/cch.d.ts +23 -9
- package/dist/cch.js +104 -21
- package/dist/claude-code.d.ts +8 -3
- package/dist/claude-code.js +24 -7
- package/dist/claustrum-enrollment-registry.d.ts +17 -0
- package/dist/claustrum-enrollment-registry.js +194 -0
- package/dist/claustrum-enrollment.d.ts +70 -0
- package/dist/claustrum-enrollment.js +485 -0
- package/dist/claustrum-scoped-roster.d.ts +23 -0
- package/dist/claustrum-scoped-roster.js +194 -0
- package/dist/claustrum-scoped-runtime.d.ts +28 -0
- package/dist/claustrum-scoped-runtime.js +230 -0
- package/dist/claustrum-scoped.d.ts +39 -0
- package/dist/claustrum-scoped.js +193 -0
- package/dist/claustrum.d.ts +252 -0
- package/dist/claustrum.js +1471 -0
- package/dist/commands/account.d.ts +43 -11
- package/dist/commands/account.js +147 -4
- package/dist/constants.d.ts +5 -5
- package/dist/constants.js +5 -5
- package/dist/custom-headers.d.ts +3 -0
- package/dist/custom-headers.js +102 -0
- package/dist/dump.js +2 -1
- package/dist/fast.js +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.js +11 -0
- package/dist/json.d.ts +1 -0
- package/dist/json.js +10 -0
- package/dist/logger.js +3 -1
- package/dist/mid-conversation-output-config.d.ts +13 -0
- package/dist/mid-conversation-output-config.js +89 -0
- package/dist/model-remap.d.ts +27 -0
- package/dist/model-remap.js +72 -0
- package/dist/models.d.ts +46 -1
- package/dist/models.js +87 -8
- 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 +6 -0
- package/dist/prime.d.ts +11 -3
- package/dist/prime.js +25 -7
- package/dist/quota-header-feed.d.ts +32 -7
- package/dist/quota-header-feed.js +93 -10
- package/dist/quota-headers.js +59 -6
- package/dist/quota-manager.d.ts +20 -2
- package/dist/quota-manager.js +101 -24
- package/dist/relay.d.ts +8 -0
- package/dist/relay.js +72 -12
- package/dist/sticky-routing.d.ts +2 -0
- package/dist/sticky-routing.js +19 -1
- package/dist/thinking-binding.d.ts +7 -0
- package/dist/thinking-binding.js +54 -0
- package/package.json +4 -1
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { isClaudeFable51Model } from './models.js';
|
|
2
|
+
export const MID_CONVERSATION_OUTPUT_CONFIG_BETA = 'mid-conversation-output-config-2026-07-01';
|
|
3
|
+
function isRecord(value) {
|
|
4
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
5
|
+
}
|
|
6
|
+
export function normalizeAdaptiveEffort(value) {
|
|
7
|
+
if (value === 'minimal')
|
|
8
|
+
return 'low';
|
|
9
|
+
if (value === 'low' ||
|
|
10
|
+
value === 'medium' ||
|
|
11
|
+
value === 'high' ||
|
|
12
|
+
value === 'xhigh' ||
|
|
13
|
+
value === 'max') {
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
export function usesMidConversationOutputConfig(body) {
|
|
19
|
+
return isClaudeFable51Model(body.model);
|
|
20
|
+
}
|
|
21
|
+
function compactTransitions(transitions) {
|
|
22
|
+
const compacted = [];
|
|
23
|
+
for (const transition of transitions) {
|
|
24
|
+
if (!Number.isSafeInteger(transition.afterAssistantMessages) ||
|
|
25
|
+
transition.afterAssistantMessages < 0 ||
|
|
26
|
+
!normalizeAdaptiveEffort(transition.effort)) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
const normalized = {
|
|
30
|
+
afterAssistantMessages: transition.afterAssistantMessages,
|
|
31
|
+
effort: transition.effort,
|
|
32
|
+
};
|
|
33
|
+
const previous = compacted.at(-1);
|
|
34
|
+
if (previous &&
|
|
35
|
+
previous.afterAssistantMessages === normalized.afterAssistantMessages) {
|
|
36
|
+
previous.effort = normalized.effort;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (previous?.effort === normalized.effort)
|
|
40
|
+
continue;
|
|
41
|
+
compacted.push(normalized);
|
|
42
|
+
}
|
|
43
|
+
return compacted;
|
|
44
|
+
}
|
|
45
|
+
export function applyMidConversationOutputConfig(body, transitions) {
|
|
46
|
+
if (!usesMidConversationOutputConfig(body) || !Array.isArray(body.messages)) {
|
|
47
|
+
return { applied: false, inserted: 0 };
|
|
48
|
+
}
|
|
49
|
+
const compacted = compactTransitions(transitions);
|
|
50
|
+
const currentOutputConfig = isRecord(body.output_config)
|
|
51
|
+
? body.output_config
|
|
52
|
+
: {};
|
|
53
|
+
const baseline = compacted[0]?.effort ??
|
|
54
|
+
normalizeAdaptiveEffort(currentOutputConfig.effort) ??
|
|
55
|
+
'high';
|
|
56
|
+
body.output_config = { ...currentOutputConfig, effort: baseline };
|
|
57
|
+
if (compacted.length < 2)
|
|
58
|
+
return { applied: true, inserted: 0 };
|
|
59
|
+
const messages = body.messages;
|
|
60
|
+
const transitionsByBoundary = new Map();
|
|
61
|
+
for (const transition of compacted.slice(1)) {
|
|
62
|
+
transitionsByBoundary.set(transition.afterAssistantMessages, transition.effort);
|
|
63
|
+
}
|
|
64
|
+
let assistantMessages = 0;
|
|
65
|
+
let activeEffort = baseline;
|
|
66
|
+
let inserted = 0;
|
|
67
|
+
const rewritten = [];
|
|
68
|
+
for (const message of messages) {
|
|
69
|
+
if (isRecord(message) &&
|
|
70
|
+
message.role === 'user' &&
|
|
71
|
+
transitionsByBoundary.has(assistantMessages)) {
|
|
72
|
+
const effort = transitionsByBoundary.get(assistantMessages);
|
|
73
|
+
if (effort && effort !== activeEffort) {
|
|
74
|
+
rewritten.push({
|
|
75
|
+
role: 'system',
|
|
76
|
+
content: [],
|
|
77
|
+
output_config: { effort },
|
|
78
|
+
});
|
|
79
|
+
activeEffort = effort;
|
|
80
|
+
inserted++;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
rewritten.push(message);
|
|
84
|
+
if (isRecord(message) && message.role === 'assistant')
|
|
85
|
+
assistantMessages++;
|
|
86
|
+
}
|
|
87
|
+
body.messages = rewritten;
|
|
88
|
+
return { applied: true, inserted };
|
|
89
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remap canonical Claude model IDs to proxy-compatible names
|
|
3
|
+
* using ANTHROPIC_DEFAULT_*_MODEL env vars.
|
|
4
|
+
*
|
|
5
|
+
* LiteLLM/proxy backends often use shorter model aliases
|
|
6
|
+
* (e.g. `claude-sonnet-4-6` instead of `claude-sonnet-4-20250514`).
|
|
7
|
+
* These proxy-route variables follow the Claude Code convention, except
|
|
8
|
+
* ANTHROPIC_DEFAULT_FABLE_MODEL, which is plugin-specific:
|
|
9
|
+
*
|
|
10
|
+
* ANTHROPIC_MODEL — default for any claude-* model
|
|
11
|
+
* ANTHROPIC_DEFAULT_SONNET_MODEL — models matching claude-sonnet-*
|
|
12
|
+
* ANTHROPIC_DEFAULT_OPUS_MODEL — models matching claude-opus-*
|
|
13
|
+
* ANTHROPIC_DEFAULT_HAIKU_MODEL — models matching claude-haiku-*
|
|
14
|
+
* ANTHROPIC_DEFAULT_FABLE_MODEL — models matching claude-fable / claude-mythos
|
|
15
|
+
*
|
|
16
|
+
* Tier-specific vars take precedence over the generic ANTHROPIC_MODEL.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Resolve a canonical model ID to its proxy-compatible alias.
|
|
20
|
+
* Returns the original model when no env override is configured.
|
|
21
|
+
*/
|
|
22
|
+
export declare function remapModelId(model: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Remap the `model` field in a parsed request body in place.
|
|
25
|
+
* Returns true if the model was changed.
|
|
26
|
+
*/
|
|
27
|
+
export declare function remapRequestBodyModel(parsed: Record<string, unknown>): boolean;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remap canonical Claude model IDs to proxy-compatible names
|
|
3
|
+
* using ANTHROPIC_DEFAULT_*_MODEL env vars.
|
|
4
|
+
*
|
|
5
|
+
* LiteLLM/proxy backends often use shorter model aliases
|
|
6
|
+
* (e.g. `claude-sonnet-4-6` instead of `claude-sonnet-4-20250514`).
|
|
7
|
+
* These proxy-route variables follow the Claude Code convention, except
|
|
8
|
+
* ANTHROPIC_DEFAULT_FABLE_MODEL, which is plugin-specific:
|
|
9
|
+
*
|
|
10
|
+
* ANTHROPIC_MODEL — default for any claude-* model
|
|
11
|
+
* ANTHROPIC_DEFAULT_SONNET_MODEL — models matching claude-sonnet-*
|
|
12
|
+
* ANTHROPIC_DEFAULT_OPUS_MODEL — models matching claude-opus-*
|
|
13
|
+
* ANTHROPIC_DEFAULT_HAIKU_MODEL — models matching claude-haiku-*
|
|
14
|
+
* ANTHROPIC_DEFAULT_FABLE_MODEL — models matching claude-fable / claude-mythos
|
|
15
|
+
*
|
|
16
|
+
* Tier-specific vars take precedence over the generic ANTHROPIC_MODEL.
|
|
17
|
+
*/
|
|
18
|
+
function getEnv(name) {
|
|
19
|
+
const value = process.env[name]?.trim();
|
|
20
|
+
return value || undefined;
|
|
21
|
+
}
|
|
22
|
+
function getModelTier(model) {
|
|
23
|
+
if (/^claude-sonnet(?:-|$)/.test(model))
|
|
24
|
+
return 'sonnet';
|
|
25
|
+
if (/^claude-opus(?:-|$)/.test(model))
|
|
26
|
+
return 'opus';
|
|
27
|
+
if (/^claude-haiku(?:-|$)/.test(model))
|
|
28
|
+
return 'haiku';
|
|
29
|
+
if (/^claude-(?:fable|mythos)(?:-|$)/.test(model))
|
|
30
|
+
return 'fable';
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const TIER_ENV_MAP = {
|
|
34
|
+
sonnet: 'ANTHROPIC_DEFAULT_SONNET_MODEL',
|
|
35
|
+
opus: 'ANTHROPIC_DEFAULT_OPUS_MODEL',
|
|
36
|
+
haiku: 'ANTHROPIC_DEFAULT_HAIKU_MODEL',
|
|
37
|
+
fable: 'ANTHROPIC_DEFAULT_FABLE_MODEL',
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Resolve a canonical model ID to its proxy-compatible alias.
|
|
41
|
+
* Returns the original model when no env override is configured.
|
|
42
|
+
*/
|
|
43
|
+
export function remapModelId(model) {
|
|
44
|
+
if (typeof model !== 'string' || !model)
|
|
45
|
+
return model;
|
|
46
|
+
const tier = getModelTier(model);
|
|
47
|
+
if (tier) {
|
|
48
|
+
const tierModel = getEnv(TIER_ENV_MAP[tier]);
|
|
49
|
+
if (tierModel)
|
|
50
|
+
return tierModel;
|
|
51
|
+
}
|
|
52
|
+
// Generic fallback for any claude-* model
|
|
53
|
+
if (model.startsWith('claude-')) {
|
|
54
|
+
const defaultModel = getEnv('ANTHROPIC_MODEL');
|
|
55
|
+
if (defaultModel)
|
|
56
|
+
return defaultModel;
|
|
57
|
+
}
|
|
58
|
+
return model;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Remap the `model` field in a parsed request body in place.
|
|
62
|
+
* Returns true if the model was changed.
|
|
63
|
+
*/
|
|
64
|
+
export function remapRequestBodyModel(parsed) {
|
|
65
|
+
if (typeof parsed.model !== 'string')
|
|
66
|
+
return false;
|
|
67
|
+
const remapped = remapModelId(parsed.model);
|
|
68
|
+
if (remapped === parsed.model)
|
|
69
|
+
return false;
|
|
70
|
+
parsed.model = remapped;
|
|
71
|
+
return true;
|
|
72
|
+
}
|
package/dist/models.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export declare const CLAUDE_FABLE_5_MODEL_ID = "claude-fable-5";
|
|
2
2
|
export declare const CLAUDE_MYTHOS_5_MODEL_ID = "claude-mythos-5";
|
|
3
|
+
export declare const CLAUDE_FABLE_5_1_MODEL_ID = "claude-fable-5-1";
|
|
4
|
+
export declare const CLAUDE_MYTHOS_5_1_MODEL_ID = "claude-mythos-5-1";
|
|
3
5
|
/**
|
|
4
6
|
* Haiku 4.5 model identifier used by `/claude-prime` to start each OAuth
|
|
5
7
|
* account's five-hour quota window with a minimal request. Usage is measured
|
|
@@ -7,6 +9,8 @@ export declare const CLAUDE_MYTHOS_5_MODEL_ID = "claude-mythos-5";
|
|
|
7
9
|
* above so per-million-token cost estimation does not conflate families.
|
|
8
10
|
*/
|
|
9
11
|
export declare const CLAUDE_HAIKU_4_5_MODEL_ID = "claude-haiku-4-5";
|
|
12
|
+
/** Remove OpenCode's context-window qualifier before model-family checks. */
|
|
13
|
+
export declare function normalizeAnthropicModelId(model: string): string;
|
|
10
14
|
/**
|
|
11
15
|
* Per-million-token USD pricing for Haiku 4.5. Used to project the cumulative
|
|
12
16
|
* cost of prime requests from persisted usage counters — never persisted on
|
|
@@ -16,7 +20,8 @@ export declare const CLAUDE_HAIKU_4_5_PRICING: {
|
|
|
16
20
|
readonly input: 1;
|
|
17
21
|
readonly output: 5;
|
|
18
22
|
};
|
|
19
|
-
export declare const
|
|
23
|
+
export declare const CLAUDE_FABLE_MYTHOS_5_1_MODEL_IDS: readonly ["claude-fable-5-1", "claude-mythos-5-1"];
|
|
24
|
+
export declare const CLAUDE_FABLE_MYTHOS_5_MODEL_IDS: readonly ["claude-fable-5", "claude-mythos-5", "claude-fable-5-1", "claude-mythos-5-1"];
|
|
20
25
|
export type ClaudeFableMythos5ModelId = (typeof CLAUDE_FABLE_MYTHOS_5_MODEL_IDS)[number];
|
|
21
26
|
export declare const CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING: {
|
|
22
27
|
readonly type: 'adaptive';
|
|
@@ -29,15 +34,38 @@ export declare const CLAUDE_FABLE_MYTHOS_5_PRICING: {
|
|
|
29
34
|
readonly cacheWrite5m: 12.5;
|
|
30
35
|
readonly cacheWrite1h: 20;
|
|
31
36
|
};
|
|
37
|
+
export declare const CLAUDE_FABLE_MYTHOS_5_1_PRICING: {
|
|
38
|
+
readonly input: 10;
|
|
39
|
+
readonly output: 50;
|
|
40
|
+
readonly cacheRead: 0.25;
|
|
41
|
+
readonly cacheWrite5m: 12.5;
|
|
42
|
+
readonly cacheWrite1h: 20;
|
|
43
|
+
};
|
|
32
44
|
export declare const CLAUDE_FABLE_MYTHOS_5_CONTEXT_WINDOW = 1000000;
|
|
33
45
|
export declare const CLAUDE_FABLE_MYTHOS_5_MAX_OUTPUT_TOKENS = 128000;
|
|
34
46
|
export declare const CLAUDE_FABLE_MYTHOS_5_RELEASE_DATE = "2026-06-09";
|
|
47
|
+
export declare const CLAUDE_FABLE_MYTHOS_5_1_RELEASE_DATE = "2026-09-01";
|
|
35
48
|
export declare const CLAUDE_FABLE_MYTHOS_5_MODEL_SPECS: Record<ClaudeFableMythos5ModelId, {
|
|
36
49
|
id: ClaudeFableMythos5ModelId;
|
|
37
50
|
name: string;
|
|
38
51
|
limited?: boolean;
|
|
39
52
|
}>;
|
|
53
|
+
export declare const CLAUDE_FABLE_MYTHOS_5_1_MODEL_SPECS: {
|
|
54
|
+
"claude-fable-5-1": {
|
|
55
|
+
id: ClaudeFableMythos5ModelId;
|
|
56
|
+
name: string;
|
|
57
|
+
limited?: boolean;
|
|
58
|
+
};
|
|
59
|
+
"claude-mythos-5-1": {
|
|
60
|
+
id: ClaudeFableMythos5ModelId;
|
|
61
|
+
name: string;
|
|
62
|
+
limited?: boolean;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
40
65
|
export declare function isClaudeFableOrMythos5Model(model: unknown): boolean;
|
|
66
|
+
export declare function isClaudeFableOrMythos51Model(model: unknown): boolean;
|
|
67
|
+
export declare function isClaudeFable51Model(model: unknown): boolean;
|
|
68
|
+
export declare function getClaudeFableMythos5ReleaseDate(model: unknown): "2026-06-09" | "2026-09-01";
|
|
41
69
|
export declare const CLAUDE_SONNET_5_MODEL_ID = "claude-sonnet-5";
|
|
42
70
|
/**
|
|
43
71
|
* Sonnet 5 enables adaptive thinking by default but ships `display: "omitted"`,
|
|
@@ -64,4 +92,21 @@ export declare const CLAUDE_OPUS_5_ADAPTIVE_THINKING: {
|
|
|
64
92
|
readonly display: 'summarized';
|
|
65
93
|
};
|
|
66
94
|
export declare function isClaudeOpus5Model(model: unknown): boolean;
|
|
95
|
+
export declare const CLAUDE_OPUS_5_5_MODEL_ID = "claude-opus-5-5";
|
|
96
|
+
export declare const CLAUDE_OPUS_5_5_RELEASE_DATE = "2026-09-18";
|
|
97
|
+
export declare const CLAUDE_OPUS_5_5_CONTEXT_WINDOW = 1000000;
|
|
98
|
+
export declare const CLAUDE_OPUS_5_5_MAX_OUTPUT_TOKENS = 128000;
|
|
99
|
+
export declare const CLAUDE_OPUS_5_5_PRICING: {
|
|
100
|
+
readonly input: 4;
|
|
101
|
+
readonly output: 20;
|
|
102
|
+
readonly cacheRead: 0.2;
|
|
103
|
+
readonly cacheWrite5m: 5;
|
|
104
|
+
readonly cacheWrite1h: 8;
|
|
105
|
+
};
|
|
106
|
+
export declare const CLAUDE_OPUS_5_5_ADAPTIVE_THINKING: {
|
|
107
|
+
readonly type: 'adaptive';
|
|
108
|
+
readonly display: 'summarized';
|
|
109
|
+
};
|
|
110
|
+
export declare function isClaudeOpus55Model(model: unknown): boolean;
|
|
111
|
+
export declare function isClaudeOpus5FamilyModel(model: unknown): boolean;
|
|
67
112
|
export declare function isOpenAIReasoningSignature(value: unknown): boolean;
|
package/dist/models.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export const CLAUDE_FABLE_5_MODEL_ID = 'claude-fable-5';
|
|
2
2
|
export const CLAUDE_MYTHOS_5_MODEL_ID = 'claude-mythos-5';
|
|
3
|
+
export const CLAUDE_FABLE_5_1_MODEL_ID = 'claude-fable-5-1';
|
|
4
|
+
export const CLAUDE_MYTHOS_5_1_MODEL_ID = 'claude-mythos-5-1';
|
|
3
5
|
/**
|
|
4
6
|
* Haiku 4.5 model identifier used by `/claude-prime` to start each OAuth
|
|
5
7
|
* account's five-hour quota window with a minimal request. Usage is measured
|
|
@@ -7,6 +9,10 @@ export const CLAUDE_MYTHOS_5_MODEL_ID = 'claude-mythos-5';
|
|
|
7
9
|
* above so per-million-token cost estimation does not conflate families.
|
|
8
10
|
*/
|
|
9
11
|
export const CLAUDE_HAIKU_4_5_MODEL_ID = 'claude-haiku-4-5';
|
|
12
|
+
/** Remove OpenCode's context-window qualifier before model-family checks. */
|
|
13
|
+
export function normalizeAnthropicModelId(model) {
|
|
14
|
+
return model.endsWith('[1m]') ? model.slice(0, -4) : model;
|
|
15
|
+
}
|
|
10
16
|
/**
|
|
11
17
|
* Per-million-token USD pricing for Haiku 4.5. Used to project the cumulative
|
|
12
18
|
* cost of prime requests from persisted usage counters — never persisted on
|
|
@@ -16,9 +22,14 @@ export const CLAUDE_HAIKU_4_5_PRICING = {
|
|
|
16
22
|
input: 1,
|
|
17
23
|
output: 5,
|
|
18
24
|
};
|
|
25
|
+
export const CLAUDE_FABLE_MYTHOS_5_1_MODEL_IDS = [
|
|
26
|
+
CLAUDE_FABLE_5_1_MODEL_ID,
|
|
27
|
+
CLAUDE_MYTHOS_5_1_MODEL_ID,
|
|
28
|
+
];
|
|
19
29
|
export const CLAUDE_FABLE_MYTHOS_5_MODEL_IDS = [
|
|
20
30
|
CLAUDE_FABLE_5_MODEL_ID,
|
|
21
31
|
CLAUDE_MYTHOS_5_MODEL_ID,
|
|
32
|
+
...CLAUDE_FABLE_MYTHOS_5_1_MODEL_IDS,
|
|
22
33
|
];
|
|
23
34
|
export const CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING = {
|
|
24
35
|
type: 'adaptive',
|
|
@@ -31,9 +42,17 @@ export const CLAUDE_FABLE_MYTHOS_5_PRICING = {
|
|
|
31
42
|
cacheWrite5m: 12.5,
|
|
32
43
|
cacheWrite1h: 20,
|
|
33
44
|
};
|
|
45
|
+
export const CLAUDE_FABLE_MYTHOS_5_1_PRICING = {
|
|
46
|
+
input: 10,
|
|
47
|
+
output: 50,
|
|
48
|
+
cacheRead: 0.25,
|
|
49
|
+
cacheWrite5m: 12.5,
|
|
50
|
+
cacheWrite1h: 20,
|
|
51
|
+
};
|
|
34
52
|
export const CLAUDE_FABLE_MYTHOS_5_CONTEXT_WINDOW = 1_000_000;
|
|
35
53
|
export const CLAUDE_FABLE_MYTHOS_5_MAX_OUTPUT_TOKENS = 128_000;
|
|
36
54
|
export const CLAUDE_FABLE_MYTHOS_5_RELEASE_DATE = '2026-06-09';
|
|
55
|
+
export const CLAUDE_FABLE_MYTHOS_5_1_RELEASE_DATE = '2026-09-01';
|
|
37
56
|
export const CLAUDE_FABLE_MYTHOS_5_MODEL_SPECS = {
|
|
38
57
|
[CLAUDE_FABLE_5_MODEL_ID]: {
|
|
39
58
|
id: CLAUDE_FABLE_5_MODEL_ID,
|
|
@@ -44,10 +63,43 @@ export const CLAUDE_FABLE_MYTHOS_5_MODEL_SPECS = {
|
|
|
44
63
|
name: 'Claude Mythos 5',
|
|
45
64
|
limited: true,
|
|
46
65
|
},
|
|
66
|
+
[CLAUDE_FABLE_5_1_MODEL_ID]: {
|
|
67
|
+
id: CLAUDE_FABLE_5_1_MODEL_ID,
|
|
68
|
+
name: 'Claude Fable 5.1',
|
|
69
|
+
},
|
|
70
|
+
[CLAUDE_MYTHOS_5_1_MODEL_ID]: {
|
|
71
|
+
id: CLAUDE_MYTHOS_5_1_MODEL_ID,
|
|
72
|
+
name: 'Claude Mythos 5.1',
|
|
73
|
+
limited: true,
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
export const CLAUDE_FABLE_MYTHOS_5_1_MODEL_SPECS = {
|
|
77
|
+
[CLAUDE_FABLE_5_1_MODEL_ID]: CLAUDE_FABLE_MYTHOS_5_MODEL_SPECS[CLAUDE_FABLE_5_1_MODEL_ID],
|
|
78
|
+
[CLAUDE_MYTHOS_5_1_MODEL_ID]: CLAUDE_FABLE_MYTHOS_5_MODEL_SPECS[CLAUDE_MYTHOS_5_1_MODEL_ID],
|
|
47
79
|
};
|
|
48
80
|
export function isClaudeFableOrMythos5Model(model) {
|
|
49
|
-
|
|
50
|
-
|
|
81
|
+
if (typeof model !== 'string')
|
|
82
|
+
return false;
|
|
83
|
+
const normalized = normalizeAnthropicModelId(model);
|
|
84
|
+
return CLAUDE_FABLE_MYTHOS_5_MODEL_IDS.some((id) => normalized === id || normalized.startsWith(`${id}-`));
|
|
85
|
+
}
|
|
86
|
+
export function isClaudeFableOrMythos51Model(model) {
|
|
87
|
+
if (typeof model !== 'string')
|
|
88
|
+
return false;
|
|
89
|
+
const normalized = normalizeAnthropicModelId(model);
|
|
90
|
+
return CLAUDE_FABLE_MYTHOS_5_1_MODEL_IDS.some((id) => normalized === id || normalized.startsWith(`${id}-`));
|
|
91
|
+
}
|
|
92
|
+
export function isClaudeFable51Model(model) {
|
|
93
|
+
if (typeof model !== 'string')
|
|
94
|
+
return false;
|
|
95
|
+
const normalized = normalizeAnthropicModelId(model);
|
|
96
|
+
return (normalized === CLAUDE_FABLE_5_1_MODEL_ID ||
|
|
97
|
+
normalized.startsWith(`${CLAUDE_FABLE_5_1_MODEL_ID}-`));
|
|
98
|
+
}
|
|
99
|
+
export function getClaudeFableMythos5ReleaseDate(model) {
|
|
100
|
+
return isClaudeFableOrMythos51Model(model)
|
|
101
|
+
? CLAUDE_FABLE_MYTHOS_5_1_RELEASE_DATE
|
|
102
|
+
: CLAUDE_FABLE_MYTHOS_5_RELEASE_DATE;
|
|
51
103
|
}
|
|
52
104
|
export const CLAUDE_SONNET_5_MODEL_ID = 'claude-sonnet-5';
|
|
53
105
|
/**
|
|
@@ -58,9 +110,11 @@ export const CLAUDE_SONNET_5_MODEL_ID = 'claude-sonnet-5';
|
|
|
58
110
|
*/
|
|
59
111
|
export const CLAUDE_SONNET_5_ADAPTIVE_THINKING = CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING;
|
|
60
112
|
export function isClaudeSonnet5Model(model) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
113
|
+
if (typeof model !== 'string')
|
|
114
|
+
return false;
|
|
115
|
+
const normalized = normalizeAnthropicModelId(model);
|
|
116
|
+
return (normalized === CLAUDE_SONNET_5_MODEL_ID ||
|
|
117
|
+
normalized.startsWith(`${CLAUDE_SONNET_5_MODEL_ID}-`));
|
|
64
118
|
}
|
|
65
119
|
export const CLAUDE_OPUS_5_MODEL_ID = 'claude-opus-5';
|
|
66
120
|
/**
|
|
@@ -73,9 +127,34 @@ export const CLAUDE_OPUS_5_MODEL_ID = 'claude-opus-5';
|
|
|
73
127
|
*/
|
|
74
128
|
export const CLAUDE_OPUS_5_ADAPTIVE_THINKING = CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING;
|
|
75
129
|
export function isClaudeOpus5Model(model) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
130
|
+
if (typeof model !== 'string')
|
|
131
|
+
return false;
|
|
132
|
+
const normalized = normalizeAnthropicModelId(model);
|
|
133
|
+
return (!isClaudeOpus55Model(normalized) &&
|
|
134
|
+
(normalized === CLAUDE_OPUS_5_MODEL_ID ||
|
|
135
|
+
normalized.startsWith(`${CLAUDE_OPUS_5_MODEL_ID}-`)));
|
|
136
|
+
}
|
|
137
|
+
export const CLAUDE_OPUS_5_5_MODEL_ID = 'claude-opus-5-5';
|
|
138
|
+
export const CLAUDE_OPUS_5_5_RELEASE_DATE = '2026-09-18';
|
|
139
|
+
export const CLAUDE_OPUS_5_5_CONTEXT_WINDOW = 1_000_000;
|
|
140
|
+
export const CLAUDE_OPUS_5_5_MAX_OUTPUT_TOKENS = 128_000;
|
|
141
|
+
export const CLAUDE_OPUS_5_5_PRICING = {
|
|
142
|
+
input: 4,
|
|
143
|
+
output: 20,
|
|
144
|
+
cacheRead: 0.2,
|
|
145
|
+
cacheWrite5m: 5,
|
|
146
|
+
cacheWrite1h: 8,
|
|
147
|
+
};
|
|
148
|
+
export const CLAUDE_OPUS_5_5_ADAPTIVE_THINKING = CLAUDE_FABLE_MYTHOS_5_SUMMARIZED_THINKING;
|
|
149
|
+
export function isClaudeOpus55Model(model) {
|
|
150
|
+
if (typeof model !== 'string')
|
|
151
|
+
return false;
|
|
152
|
+
const normalized = normalizeAnthropicModelId(model);
|
|
153
|
+
return (normalized === CLAUDE_OPUS_5_5_MODEL_ID ||
|
|
154
|
+
normalized.startsWith(`${CLAUDE_OPUS_5_5_MODEL_ID}-`));
|
|
155
|
+
}
|
|
156
|
+
export function isClaudeOpus5FamilyModel(model) {
|
|
157
|
+
return isClaudeOpus5Model(model) || isClaudeOpus55Model(model);
|
|
79
158
|
}
|
|
80
159
|
export function isOpenAIReasoningSignature(value) {
|
|
81
160
|
if (typeof value !== 'string')
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isTransientNetworkError(error: unknown): boolean;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const TRANSIENT_NETWORK_ERROR_CODES = new Set([
|
|
2
|
+
'EAI_AGAIN',
|
|
3
|
+
'ECONNREFUSED',
|
|
4
|
+
'ECONNRESET',
|
|
5
|
+
'EHOSTUNREACH',
|
|
6
|
+
'ENETUNREACH',
|
|
7
|
+
'ENOTFOUND',
|
|
8
|
+
'ETIMEDOUT',
|
|
9
|
+
'UND_ERR_CONNECT_TIMEOUT',
|
|
10
|
+
]);
|
|
11
|
+
function errorField(error, field) {
|
|
12
|
+
if (!error || typeof error !== 'object')
|
|
13
|
+
return undefined;
|
|
14
|
+
const value = error[field];
|
|
15
|
+
return typeof value === 'string' ? value : undefined;
|
|
16
|
+
}
|
|
17
|
+
export function isTransientNetworkError(error) {
|
|
18
|
+
const code = errorField(error, 'code');
|
|
19
|
+
if (code && TRANSIENT_NETWORK_ERROR_CODES.has(code))
|
|
20
|
+
return true;
|
|
21
|
+
const message = error instanceof Error
|
|
22
|
+
? error.message
|
|
23
|
+
: (errorField(error, 'message') ?? String(error));
|
|
24
|
+
if (message.includes('fetch failed'))
|
|
25
|
+
return true;
|
|
26
|
+
return [...TRANSIENT_NETWORK_ERROR_CODES].some((candidate) => message.includes(candidate));
|
|
27
|
+
}
|
package/dist/oauth-profile.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { OAuthAccountProfile } from './accounts.ts';
|
|
1
|
+
import type { OAuthAccountProfile, ProviderAccountUuid } from './accounts.ts';
|
|
2
2
|
export declare const PROFILE_TTL_MS: number;
|
|
3
3
|
export declare function fetchOAuthAccountProfile(input: {
|
|
4
4
|
accessToken: string;
|
|
5
5
|
accountIdentity?: string;
|
|
6
|
+
providerAccountUuid?: ProviderAccountUuid;
|
|
6
7
|
fetchImpl?: typeof fetch;
|
|
7
8
|
now?: () => number;
|
|
8
9
|
signal?: AbortSignal;
|
package/dist/oauth-profile.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { assertNotCustodyTombstone } from './claustrum.js';
|
|
1
2
|
const PROFILE_URL = 'https://api.anthropic.com/api/oauth/profile';
|
|
2
3
|
export const PROFILE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
3
4
|
export async function fetchOAuthAccountProfile(input) {
|
|
5
|
+
// The bearer value is guarded where it becomes a header, like every other builder.
|
|
6
|
+
assertNotCustodyTombstone(input.accessToken, 'anthropic');
|
|
4
7
|
const response = await (input.fetchImpl ?? fetch)(PROFILE_URL, {
|
|
5
8
|
method: 'GET',
|
|
6
9
|
signal: input.signal,
|
|
@@ -29,6 +32,9 @@ export async function fetchOAuthAccountProfile(input) {
|
|
|
29
32
|
...(input.accountIdentity !== undefined && {
|
|
30
33
|
accountIdentity: input.accountIdentity,
|
|
31
34
|
}),
|
|
35
|
+
...(input.providerAccountUuid !== undefined && {
|
|
36
|
+
providerAccountUuid: input.providerAccountUuid,
|
|
37
|
+
}),
|
|
32
38
|
};
|
|
33
39
|
}
|
|
34
40
|
export function oauthProfileMatchesIdentity(profile, accountIdentity) {
|
package/dist/prime.d.ts
CHANGED
|
@@ -30,7 +30,7 @@ export type PrimeAccountStatus = {
|
|
|
30
30
|
label: string;
|
|
31
31
|
nextDueAt?: number;
|
|
32
32
|
lastPrimedAt?: number | null;
|
|
33
|
-
lastResult?: 'ok' | 'error';
|
|
33
|
+
lastResult?: 'ok' | 'error' | 'skipped';
|
|
34
34
|
usage?: import('./accounts.ts').PrimeUsageCounters;
|
|
35
35
|
estimatedCostUsd?: number;
|
|
36
36
|
};
|
|
@@ -47,7 +47,7 @@ export type PrimeSendResult = {
|
|
|
47
47
|
status?: number;
|
|
48
48
|
ms?: number;
|
|
49
49
|
error: string;
|
|
50
|
-
reason?: 'token-refresh' | 'send';
|
|
50
|
+
reason?: 'token-refresh' | 'vault-cold' | 'send';
|
|
51
51
|
};
|
|
52
52
|
/**
|
|
53
53
|
* Pure command parser — accepts `''` / `on` / `off` and treats anything else
|
|
@@ -72,7 +72,7 @@ export declare function buildPrimeAccountStatuses(storage: AccountStorage | null
|
|
|
72
72
|
now?: number;
|
|
73
73
|
transient?: ReadonlyMap<string, {
|
|
74
74
|
lastPrimedAt?: number;
|
|
75
|
-
lastResult?: 'ok' | 'error';
|
|
75
|
+
lastResult?: 'ok' | 'error' | 'skipped';
|
|
76
76
|
}>;
|
|
77
77
|
}): PrimeAccountStatus[];
|
|
78
78
|
/**
|
|
@@ -182,9 +182,17 @@ export type PrimeManagerOptions = {
|
|
|
182
182
|
now?: () => number;
|
|
183
183
|
markerDir?: string;
|
|
184
184
|
storagePath: string;
|
|
185
|
+
setIntervalImpl?: typeof globalThis.setInterval;
|
|
186
|
+
clearIntervalImpl?: typeof globalThis.clearInterval;
|
|
187
|
+
setTimeoutImpl?: typeof globalThis.setTimeout;
|
|
188
|
+
clearTimeoutImpl?: typeof globalThis.clearTimeout;
|
|
185
189
|
};
|
|
186
190
|
export declare class PrimeManager {
|
|
187
191
|
private timer;
|
|
192
|
+
private readonly setIntervalImpl;
|
|
193
|
+
private readonly clearIntervalImpl;
|
|
194
|
+
private readonly setTimeoutImpl;
|
|
195
|
+
private readonly clearTimeoutImpl;
|
|
188
196
|
private postFireRefreshTimers;
|
|
189
197
|
private lastForcedCheck;
|
|
190
198
|
private stopped;
|
package/dist/prime.js
CHANGED
|
@@ -155,6 +155,8 @@ function formatPrimed(lastPrimedAt, lastResult) {
|
|
|
155
155
|
});
|
|
156
156
|
if (lastResult === 'error')
|
|
157
157
|
return `primed ${time} err`;
|
|
158
|
+
if (lastResult === 'skipped')
|
|
159
|
+
return `primed ${time} skipped`;
|
|
158
160
|
return `primed ${time} \u2713`;
|
|
159
161
|
}
|
|
160
162
|
function formatUsd(value) {
|
|
@@ -346,6 +348,10 @@ function storedResetMs(window) {
|
|
|
346
348
|
}
|
|
347
349
|
export class PrimeManager {
|
|
348
350
|
timer = null;
|
|
351
|
+
setIntervalImpl;
|
|
352
|
+
clearIntervalImpl;
|
|
353
|
+
setTimeoutImpl;
|
|
354
|
+
clearTimeoutImpl;
|
|
349
355
|
postFireRefreshTimers = new Set();
|
|
350
356
|
lastForcedCheck = new Map();
|
|
351
357
|
// Set true by `stop()` so a tick already in flight can short-circuit
|
|
@@ -373,6 +379,11 @@ export class PrimeManager {
|
|
|
373
379
|
windowActive = new Map();
|
|
374
380
|
constructor(options) {
|
|
375
381
|
this.options = options;
|
|
382
|
+
this.setIntervalImpl = options.setIntervalImpl ?? globalThis.setInterval;
|
|
383
|
+
this.clearIntervalImpl =
|
|
384
|
+
options.clearIntervalImpl ?? globalThis.clearInterval;
|
|
385
|
+
this.setTimeoutImpl = options.setTimeoutImpl ?? globalThis.setTimeout;
|
|
386
|
+
this.clearTimeoutImpl = options.clearTimeoutImpl ?? globalThis.clearTimeout;
|
|
376
387
|
}
|
|
377
388
|
updateOptions(options) {
|
|
378
389
|
this.options = options;
|
|
@@ -382,7 +393,7 @@ export class PrimeManager {
|
|
|
382
393
|
return;
|
|
383
394
|
this.stopped = false;
|
|
384
395
|
logger.trace('prime', 'manager started');
|
|
385
|
-
this.timer =
|
|
396
|
+
this.timer = this.setIntervalImpl(() => {
|
|
386
397
|
void this.tick().catch((error) => {
|
|
387
398
|
logger.warn('prime', 'tick failed', {
|
|
388
399
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -399,11 +410,12 @@ export class PrimeManager {
|
|
|
399
410
|
const hadPostFireRefresh = this.postFireRefreshTimers.size > 0;
|
|
400
411
|
this.stopped = true;
|
|
401
412
|
if (this.timer) {
|
|
402
|
-
|
|
413
|
+
this.clearIntervalImpl(this.timer);
|
|
403
414
|
this.timer = null;
|
|
404
415
|
}
|
|
405
|
-
for (const timer of this.postFireRefreshTimers)
|
|
406
|
-
|
|
416
|
+
for (const timer of this.postFireRefreshTimers) {
|
|
417
|
+
this.clearTimeoutImpl(timer);
|
|
418
|
+
}
|
|
407
419
|
this.postFireRefreshTimers.clear();
|
|
408
420
|
this.lastForcedCheck.clear();
|
|
409
421
|
if (!hadTimer && !hadPostFireRefresh)
|
|
@@ -687,7 +699,7 @@ export class PrimeManager {
|
|
|
687
699
|
if (this.stopped)
|
|
688
700
|
return;
|
|
689
701
|
if (!result.ok) {
|
|
690
|
-
//
|
|
702
|
+
// `vault-cold` is a cache-warm skip; it is not a provider failure.
|
|
691
703
|
// - `prime token refresh failed` — token-refresh failure
|
|
692
704
|
// before the request fires (reason: 'token-refresh').
|
|
693
705
|
// - `prime fire failed` — HTTP error / fetch throw /
|
|
@@ -698,6 +710,12 @@ export class PrimeManager {
|
|
|
698
710
|
error: result.error,
|
|
699
711
|
});
|
|
700
712
|
}
|
|
713
|
+
else if (result.reason === 'vault-cold') {
|
|
714
|
+
logger.debug('prime', 'prime vault credential cold', {
|
|
715
|
+
account: evaluation.label,
|
|
716
|
+
reason: result.reason,
|
|
717
|
+
});
|
|
718
|
+
}
|
|
701
719
|
else {
|
|
702
720
|
logger.warn('prime', 'prime fire failed', {
|
|
703
721
|
account: evaluation.label,
|
|
@@ -707,7 +725,7 @@ export class PrimeManager {
|
|
|
707
725
|
}
|
|
708
726
|
this.transient.set(evaluation.id, {
|
|
709
727
|
lastPrimedAt: now,
|
|
710
|
-
lastResult: 'error',
|
|
728
|
+
lastResult: result.reason === 'vault-cold' ? 'skipped' : 'error',
|
|
711
729
|
});
|
|
712
730
|
return;
|
|
713
731
|
}
|
|
@@ -757,7 +775,7 @@ export class PrimeManager {
|
|
|
757
775
|
// Unified fire-response headers can arm the window instantly on newer
|
|
758
776
|
// trees. This branch predates header harvesting, so a delayed poll captures
|
|
759
777
|
// the reset after the usage API's observed propagation lag.
|
|
760
|
-
const timer =
|
|
778
|
+
const timer = this.setTimeoutImpl(() => {
|
|
761
779
|
this.postFireRefreshTimers.delete(timer);
|
|
762
780
|
if (this.stopped)
|
|
763
781
|
return;
|