@oh-my-pi/pi-ai 15.10.8 → 15.10.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/CHANGELOG.md +17 -1
- package/dist/types/model-thinking.d.ts +4 -2
- package/dist/types/provider-models/openai-compat.d.ts +11 -0
- package/dist/types/providers/amazon-bedrock.d.ts +6 -5
- package/dist/types/providers/anthropic.d.ts +6 -5
- package/dist/types/providers/openai-completions.d.ts +1 -1
- package/dist/types/rate-limit-utils.d.ts +3 -2
- package/dist/types/types.d.ts +12 -3
- package/dist/types/usage/google-antigravity.d.ts +26 -1
- package/package.json +2 -2
- package/src/auth-storage.ts +2 -1
- package/src/model-thinking.ts +41 -11
- package/src/models.json +597 -445
- package/src/provider-models/openai-compat.ts +39 -0
- package/src/providers/amazon-bedrock.ts +17 -14
- package/src/providers/anthropic.ts +40 -17
- package/src/providers/openai-completions.ts +31 -9
- package/src/rate-limit-utils.ts +13 -3
- package/src/types.ts +12 -3
- package/src/usage/google-antigravity.ts +37 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [15.10.9] - 2026-06-09
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added `antigravityRankingStrategy` and registered it as the default `CredentialRankingStrategy` for `google-antigravity`, so multi-account selection consumes the per-counter Antigravity usage reports (sorted ascending by `remainingFraction` in `fetchAntigravityUsage`) before falling back to round-robin — preventing the exhausted-counter credential from being chosen first when an unblocked sibling has headroom ([#2187](https://github.com/can1357/oh-my-pi/issues/2187)).
|
|
10
|
+
- Added Claude Fable 5 to the first-party Anthropic catalog, seeded directly via `ANTHROPIC_CURATED_FALLBACK_MODELS` rather than waiting on models.dev (1M context / 128k output, adaptive thinking, $10/$50 per MTok). The model parser recognizes the `fable` kind so effort tiers (low→max), adaptive thinking, and Opus-4.7-style sampling restrictions apply; token limits and pricing are pinned in `applyAnthropicCatalogPolicy`.
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Fixed `google-antigravity` not rotating to another stored OAuth account when Cloud Code Assist returns `429 You have exhausted your capacity on this model. Your quota will reset after …`. `parseRateLimitReason` matched the literal `capacity` before the `quota will reset` suffix and downgraded the failure to `MODEL_CAPACITY_EXHAUSTED` (45–75 s backoff), and `isUsageLimitError` returned false for the same message — so `markUsageLimitReached` was never invoked and the agent kept hammering the exhausted credential while the retry layer bailed on the multi-hour `retry-after`. Both paths now treat the Antigravity phrasing as `QUOTA_EXHAUSTED` / usage-limit, blocking the current credential until reset and letting the session pick an unblocked sibling ([#2187](https://github.com/can1357/oh-my-pi/issues/2187)).
|
|
15
|
+
- Fixed OpenRouter Anthropic chat-completions requests placing `cache_control` on empty assistant tool-call content. The cache marker now skips empty text and attaches to the most recent non-empty text part, avoiding HTTP 400 payloads with `{type:"text", text:"", cache_control:...}`.
|
|
16
|
+
- Fixed Fable-only Anthropic request shaping to cover Claude Mythos 5, and added Mythos 5 to the first-party Anthropic catalog seed. Adaptive display, sampling suppression, mid-conversation system messages, forced-tool-choice downgrade, and Bedrock adaptive metadata now handle both model families.
|
|
17
|
+
- Fixed adaptive-only Claude models (Opus 4.6+, Sonnet 4.6+, Fable/Mythos 5) returning HTTP 400 `"thinking.type.disabled" is not supported for this model` whenever thinking was turned off (utility calls and forced-tool turns route through the disable path). These models accept only `thinking.type: "adaptive"`; the request builder now omits the thinking field and pins the lowest adaptive effort instead of emitting `type: "disabled"`.
|
|
18
|
+
- Widened the OpenAI-completions first-event watchdog floor from 120s to 300s for DeepSeek V4 reasoning models hosted on the official DeepSeek API. The reasoner emits no SSE bytes until its private chain-of-thought finishes, which routinely takes longer than the generic 100s first-event budget under load — every chat then aborted with `OpenAI completions stream timed out while waiting for the first event` and silently retried. Mirrors the existing GLM coding-plan widening ([#2177](https://github.com/can1357/oh-my-pi/issues/2177)).
|
|
19
|
+
|
|
5
20
|
## [15.10.8] - 2026-06-09
|
|
21
|
+
|
|
6
22
|
### Added
|
|
7
23
|
|
|
8
24
|
- Added optional `fetch` transport override (`fetch?: FetchImpl`) to Google, Ollama, and OpenAI-compatible model-manager options so dynamic model discovery and metadata lookups can use a caller-supplied HTTP client instead of only global `fetch`
|
|
@@ -3102,4 +3118,4 @@ _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
|
|
|
3102
3118
|
|
|
3103
3119
|
## [0.9.4] - 2025-11-26
|
|
3104
3120
|
|
|
3105
|
-
Initial release with multi-provider LLM support.
|
|
3121
|
+
Initial release with multi-provider LLM support.
|
|
@@ -71,7 +71,7 @@ export declare function mapEffortToGoogleThinkingLevel<TApi extends Api>(model:
|
|
|
71
71
|
/** Maps a normalized thinking effort to Anthropic adaptive effort values. */
|
|
72
72
|
export declare function mapEffortToAnthropicAdaptiveEffort<TApi extends Api>(model: ApiModel<TApi>, effort: Effort): "low" | "medium" | "high" | "xhigh" | "max";
|
|
73
73
|
/**
|
|
74
|
-
* Returns true for Anthropic models with Opus 4.7 API restrictions:
|
|
74
|
+
* Returns true for Anthropic models with Opus 4.7+/Fable/Mythos API restrictions:
|
|
75
75
|
* - Sampling parameters (temperature/top_p/top_k) return 400 error
|
|
76
76
|
* - Thinking content is omitted by default (needs display: "summarized")
|
|
77
77
|
*/
|
|
@@ -79,7 +79,9 @@ export declare function hasOpus47ApiRestrictions(modelId: string): boolean;
|
|
|
79
79
|
/**
|
|
80
80
|
* Mid-conversation `role: "system"` messages (system instructions appended at
|
|
81
81
|
* non-first positions in the `messages` array) are supported starting with
|
|
82
|
-
* Claude Opus 4.8
|
|
82
|
+
* Claude Opus 4.8 and the Claude Fable/Mythos 5 generation. Earlier Claude
|
|
83
|
+
* models reject the role.
|
|
83
84
|
* @see https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages
|
|
84
85
|
*/
|
|
85
86
|
export declare function supportsMidConversationSystemMessages(modelId: string): boolean;
|
|
87
|
+
export declare function isAnthropicFableOrMythosModel(modelId: string): boolean;
|
|
@@ -24,6 +24,17 @@ export interface ModelsDevModel {
|
|
|
24
24
|
npm?: string;
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Curated Anthropic models that are live or limited-availability on the
|
|
29
|
+
* first-party `/v1/models` endpoint but that models.dev has not catalogued yet.
|
|
30
|
+
* Seeded into model generation so the bundled catalog is never gated on
|
|
31
|
+
* models.dev's update cadence; deduped behind upstream catalog / models.dev
|
|
32
|
+
* entries once those appear. Token limits and pricing are pinned
|
|
33
|
+
* authoritatively in
|
|
34
|
+
* `applyAnthropicCatalogPolicy`, and `thinking` is derived by
|
|
35
|
+
* `refreshModelThinking` during generation.
|
|
36
|
+
*/
|
|
37
|
+
export declare const ANTHROPIC_CURATED_FALLBACK_MODELS: readonly Model<"anthropic-messages">[];
|
|
27
38
|
type SimpleProviderConfig = {
|
|
28
39
|
apiKey?: string;
|
|
29
40
|
baseUrl?: string;
|
|
@@ -27,11 +27,12 @@ export interface BedrockOptions extends StreamOptions {
|
|
|
27
27
|
* - `"omitted"`: thinking content is suppressed; the encrypted signature still
|
|
28
28
|
* travels back for multi-turn continuity.
|
|
29
29
|
*
|
|
30
|
-
* Starting with Claude Opus 4.7
|
|
31
|
-
* leaves callers waiting on a silent stream during
|
|
32
|
-
* #1373). We default to `"summarized"` so adaptive-
|
|
33
|
-
* the field keep producing visible thinking deltas.
|
|
34
|
-
* models (Opus 4.6, Sonnet 4.6+) reject the field, so
|
|
30
|
+
* Starting with Claude Opus 4.7 and Claude Fable/Mythos 5 the Anthropic API
|
|
31
|
+
* default is `"omitted"`, which leaves callers waiting on a silent stream during
|
|
32
|
+
* long reasoning runs (issue #1373). We default to `"summarized"` so adaptive-
|
|
33
|
+
* thinking models that accept the field keep producing visible thinking deltas.
|
|
34
|
+
* Older adaptive-thinking models (Opus 4.6, Sonnet 4.6+) reject the field, so
|
|
35
|
+
* we omit it for them.
|
|
35
36
|
*/
|
|
36
37
|
thinkingDisplay?: BedrockThinkingDisplay;
|
|
37
38
|
}
|
|
@@ -56,17 +56,18 @@ export type AnthropicThinkingDisplay = "summarized" | "omitted";
|
|
|
56
56
|
export interface AnthropicOptions extends StreamOptions {
|
|
57
57
|
/**
|
|
58
58
|
* Enable extended thinking.
|
|
59
|
-
* For Opus 4.6
|
|
60
|
-
*
|
|
59
|
+
* For adaptive-capable models (Opus 4.6+, Sonnet 4.6+, Fable/Mythos 5):
|
|
60
|
+
* uses adaptive thinking (Claude decides when/how much to think). For older
|
|
61
|
+
* models: uses budget-based thinking with thinkingBudgetTokens.
|
|
61
62
|
*/
|
|
62
63
|
thinkingEnabled?: boolean;
|
|
63
64
|
/**
|
|
64
65
|
* Token budget for extended thinking (older models only).
|
|
65
|
-
* Ignored for
|
|
66
|
+
* Ignored for adaptive-capable models.
|
|
66
67
|
*/
|
|
67
68
|
thinkingBudgetTokens?: number;
|
|
68
69
|
/**
|
|
69
|
-
* Effort level for adaptive thinking
|
|
70
|
+
* Effort level for adaptive thinking.
|
|
70
71
|
* Controls how much thinking Claude allocates:
|
|
71
72
|
* - "max": Always thinks with no constraints
|
|
72
73
|
* - "high": Always thinks, deep reasoning (default)
|
|
@@ -182,7 +183,7 @@ export declare function normalizeExtraBetas(betas?: string[] | string): string[]
|
|
|
182
183
|
export declare function buildAnthropicClientOptions(args: AnthropicClientOptionsArgs): AnthropicClientOptionsResult;
|
|
183
184
|
/**
|
|
184
185
|
* A single Anthropic conversation turn, including the mid-conversation
|
|
185
|
-
* `system` role (Opus 4.8+).
|
|
186
|
+
* `system` role (Opus 4.8+ and Fable/Mythos 5).
|
|
186
187
|
*/
|
|
187
188
|
export type AnthropicMessageParam = MessageParam;
|
|
188
189
|
export declare function convertAnthropicMessages(messages: Message[], model: Model<"anthropic-messages">, isOAuthToken: boolean, baseUrl?: string | undefined): AnthropicMessageParam[];
|
|
@@ -41,7 +41,7 @@ export interface OpenAICompletionsOptions extends StreamOptions {
|
|
|
41
41
|
* Exported for unit testing.
|
|
42
42
|
*/
|
|
43
43
|
export declare function applyOpenRouterRoutingVariant(modelId: string, variant: string | undefined): string;
|
|
44
|
-
/** Returns the widened OpenAI stream watchdog floor for slow
|
|
44
|
+
/** Returns the widened OpenAI stream watchdog floor for slow reasoning models hosted on OpenAI-compatible endpoints. */
|
|
45
45
|
export declare function getOpenAICompletionsStreamIdleTimeoutFallbackMs(model: Model<"openai-completions">): number | undefined;
|
|
46
46
|
export declare const streamOpenAICompletions: StreamFunction<"openai-completions">;
|
|
47
47
|
export declare function parseChunkUsage(rawUsage: object, model: Model<"openai-completions">, premiumRequests: number | undefined): AssistantMessage["usage"];
|
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
export type RateLimitReason = "QUOTA_EXHAUSTED" | "RATE_LIMIT_EXCEEDED" | "MODEL_CAPACITY_EXHAUSTED" | "SERVER_ERROR" | "UNKNOWN";
|
|
6
6
|
/**
|
|
7
7
|
* Classify a rate-limit error message into a reason category.
|
|
8
|
-
* Priority order:
|
|
8
|
+
* Priority order: QUOTA (Antigravity "quota will reset") > MODEL_CAPACITY > QUOTA (account) >
|
|
9
|
+
* RATE_LIMIT > QUOTA (generic) > SERVER_ERROR > UNKNOWN.
|
|
9
10
|
*
|
|
10
11
|
* "resource exhausted" maps to MODEL_CAPACITY (transient, short wait)
|
|
11
|
-
* "quota exceeded" maps to QUOTA_EXHAUSTED (long wait, switch account)
|
|
12
|
+
* "quota exceeded" / "quota will reset" maps to QUOTA_EXHAUSTED (long wait, switch account)
|
|
12
13
|
*/
|
|
13
14
|
export declare function parseRateLimitReason(errorMessage: string): RateLimitReason;
|
|
14
15
|
/**
|
package/dist/types/types.d.ts
CHANGED
|
@@ -741,11 +741,20 @@ export interface AnthropicCompat {
|
|
|
741
741
|
supportsLongCacheRetention?: boolean;
|
|
742
742
|
/**
|
|
743
743
|
* Whether mid-conversation `role: "system"` messages are accepted in the
|
|
744
|
-
* `messages` array (Claude Opus 4.8+
|
|
745
|
-
* Claude Platform on AWS). When unset,
|
|
746
|
-
* base URL. Not available on Bedrock,
|
|
744
|
+
* `messages` array (Claude Opus 4.8+ and Claude Fable/Mythos 5 on the
|
|
745
|
+
* first-party Claude API and Claude Platform on AWS). When unset,
|
|
746
|
+
* auto-detected from the model id and base URL. Not available on Bedrock,
|
|
747
|
+
* Vertex AI, or Microsoft Foundry.
|
|
747
748
|
*/
|
|
748
749
|
supportsMidConversationSystem?: boolean;
|
|
750
|
+
/**
|
|
751
|
+
* Whether the model accepts a forced `tool_choice` (`{ type: "any" }` or
|
|
752
|
+
* `{ type: "tool", name }`). Claude Fable/Mythos 5 reject forced tool use
|
|
753
|
+
* outright ("tool_choice forces tool use is not compatible with this model");
|
|
754
|
+
* the request builder downgrades forced choices to `auto` when this is false.
|
|
755
|
+
* When unset, auto-detected from the model id. Default: true.
|
|
756
|
+
*/
|
|
757
|
+
supportsForcedToolChoice?: boolean;
|
|
749
758
|
}
|
|
750
759
|
/**
|
|
751
760
|
* OpenRouter provider routing preferences.
|
|
@@ -1,2 +1,27 @@
|
|
|
1
|
-
import type { UsageProvider } from "../usage";
|
|
1
|
+
import type { CredentialRankingStrategy, UsageProvider } from "../usage";
|
|
2
2
|
export declare const antigravityUsageProvider: UsageProvider;
|
|
3
|
+
/**
|
|
4
|
+
* Credential ranking strategy for `google-antigravity`. Drives proactive
|
|
5
|
+
* multi-account selection in {@link AuthStorage} by reading the per-counter
|
|
6
|
+
* Antigravity usage reports.
|
|
7
|
+
*
|
|
8
|
+
* Antigravity reports one {@link UsageLimit} per backend counter (Google /
|
|
9
|
+
* Anthropic / OpenAI) per tier per window, and {@link fetchAntigravityUsage}
|
|
10
|
+
* sorts them ascending by `remainingFraction` — so `limits[0]` is always the
|
|
11
|
+
* most-pressured counter for the credential, and `limits[1]` (when present)
|
|
12
|
+
* is the next-most-pressured counter.
|
|
13
|
+
*
|
|
14
|
+
* `AuthStorage` compares the `secondary*` ranking metrics before `primary*`
|
|
15
|
+
* because other providers model a long-window budget as secondary. Antigravity
|
|
16
|
+
* does not expose a short/long split; every counter is a sibling bottleneck.
|
|
17
|
+
* Therefore the most-pressured counter goes in `secondary`, with the runner-up
|
|
18
|
+
* in `primary`, so proactive account selection always ranks the bottleneck
|
|
19
|
+
* before any healthier sibling counter.
|
|
20
|
+
*
|
|
21
|
+
* The Antigravity API exposes `resetTime` but not window duration, so the
|
|
22
|
+
* drain-rate calculation depends on `windowDefaults`. Antigravity quotas are
|
|
23
|
+
* effectively daily; 24h is the right fallback for both axes — any 5h tier
|
|
24
|
+
* still ranks correctly because both credentials are normalised against the
|
|
25
|
+
* same fallback.
|
|
26
|
+
*/
|
|
27
|
+
export declare const antigravityRankingStrategy: CredentialRankingStrategy;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-ai",
|
|
4
|
-
"version": "15.10.
|
|
4
|
+
"version": "15.10.9",
|
|
5
5
|
"description": "Unified LLM API with automatic model discovery and provider configuration",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@bufbuild/protobuf": "^2.12.0",
|
|
42
|
-
"@oh-my-pi/pi-utils": "15.10.
|
|
42
|
+
"@oh-my-pi/pi-utils": "15.10.9",
|
|
43
43
|
"openai": "^6.39.0",
|
|
44
44
|
"partial-json": "^0.1.7",
|
|
45
45
|
"zod": "4.4.3"
|
package/src/auth-storage.ts
CHANGED
|
@@ -31,7 +31,7 @@ import type {
|
|
|
31
31
|
import { claudeRankingStrategy, claudeUsageProvider } from "./usage/claude";
|
|
32
32
|
import { googleGeminiCliUsageProvider } from "./usage/gemini";
|
|
33
33
|
import { githubCopilotUsageProvider } from "./usage/github-copilot";
|
|
34
|
-
import { antigravityUsageProvider } from "./usage/google-antigravity";
|
|
34
|
+
import { antigravityRankingStrategy, antigravityUsageProvider } from "./usage/google-antigravity";
|
|
35
35
|
import { kimiUsageProvider } from "./usage/kimi";
|
|
36
36
|
import { codexRankingStrategy, openaiCodexUsageProvider } from "./usage/openai-codex";
|
|
37
37
|
import { zaiUsageProvider } from "./usage/zai";
|
|
@@ -650,6 +650,7 @@ function resolveDefaultUsageProvider(provider: Provider): UsageProvider | undefi
|
|
|
650
650
|
const DEFAULT_RANKING_STRATEGIES = new Map<Provider, CredentialRankingStrategy>([
|
|
651
651
|
["openai-codex", codexRankingStrategy],
|
|
652
652
|
["anthropic", claudeRankingStrategy],
|
|
653
|
+
["google-antigravity", antigravityRankingStrategy],
|
|
653
654
|
]);
|
|
654
655
|
|
|
655
656
|
function resolveDefaultRankingStrategy(provider: Provider): CredentialRankingStrategy | undefined {
|
package/src/model-thinking.ts
CHANGED
|
@@ -23,7 +23,7 @@ type SemVer = {
|
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
type GeminiKind = "pro" | "flash";
|
|
26
|
-
type AnthropicKind = "opus" | "sonnet";
|
|
26
|
+
type AnthropicKind = "opus" | "sonnet" | "fable" | "mythos";
|
|
27
27
|
type OpenAIVariant = "base" | "codex" | "codex-max" | "codex-mini" | "codex-spark" | "mini" | "max" | "nano";
|
|
28
28
|
|
|
29
29
|
const CODEX_GPT_5_4_PRIORITY_BY_VARIANT: Partial<Record<OpenAIVariant, number>> = {
|
|
@@ -308,7 +308,8 @@ export function mapEffortToAnthropicAdaptiveEffort<TApi extends Api>(
|
|
|
308
308
|
): "low" | "medium" | "high" | "xhigh" | "max" {
|
|
309
309
|
const supported = requireSupportedEffort(model, effort);
|
|
310
310
|
if (anthropicModelHasRealXHighEffort(model)) {
|
|
311
|
-
// Opus 4.7+ on the Messages API
|
|
311
|
+
// Opus 4.7+ and Fable/Mythos 5 on the Messages API expose the full
|
|
312
|
+
// five-tier adaptive scale
|
|
312
313
|
// (low/medium/high/xhigh/max). Shift our user-facing efforts up one notch so
|
|
313
314
|
// the top tier reaches the genuine "max" and "high" lands on Anthropic's
|
|
314
315
|
// recommended "xhigh" coding/agentic default.
|
|
@@ -341,33 +342,44 @@ export function mapEffortToAnthropicAdaptiveEffort<TApi extends Api>(
|
|
|
341
342
|
}
|
|
342
343
|
|
|
343
344
|
/**
|
|
344
|
-
* Returns true for Anthropic models with Opus 4.7 API restrictions:
|
|
345
|
+
* Returns true for Anthropic models with Opus 4.7+/Fable/Mythos API restrictions:
|
|
345
346
|
* - Sampling parameters (temperature/top_p/top_k) return 400 error
|
|
346
347
|
* - Thinking content is omitted by default (needs display: "summarized")
|
|
347
348
|
*/
|
|
348
349
|
export function hasOpus47ApiRestrictions(modelId: string): boolean {
|
|
349
350
|
const parsed = parseAnthropicModel(getCanonicalModelId(modelId));
|
|
350
351
|
if (!parsed) return false;
|
|
351
|
-
return semverGte(parsed.version, "4.7")
|
|
352
|
+
return (parsed.kind === "opus" && semverGte(parsed.version, "4.7")) || isFableOrMythos(parsed.kind);
|
|
352
353
|
}
|
|
353
354
|
|
|
354
355
|
/**
|
|
355
356
|
* Mid-conversation `role: "system"` messages (system instructions appended at
|
|
356
357
|
* non-first positions in the `messages` array) are supported starting with
|
|
357
|
-
* Claude Opus 4.8
|
|
358
|
+
* Claude Opus 4.8 and the Claude Fable/Mythos 5 generation. Earlier Claude
|
|
359
|
+
* models reject the role.
|
|
358
360
|
* @see https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages
|
|
359
361
|
*/
|
|
360
362
|
export function supportsMidConversationSystemMessages(modelId: string): boolean {
|
|
361
363
|
const parsed = parseAnthropicModel(getCanonicalModelId(modelId));
|
|
362
364
|
if (!parsed) return false;
|
|
363
|
-
return parsed.kind === "opus" && semverGte(parsed.version, "4.8");
|
|
365
|
+
return (parsed.kind === "opus" && semverGte(parsed.version, "4.8")) || isFableOrMythos(parsed.kind);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export function isAnthropicFableOrMythosModel(modelId: string): boolean {
|
|
369
|
+
const parsed = parseAnthropicModel(getCanonicalModelId(modelId));
|
|
370
|
+
return parsed !== null && isFableOrMythos(parsed.kind);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function isFableOrMythos(kind: AnthropicKind): boolean {
|
|
374
|
+
return kind === "fable" || kind === "mythos";
|
|
364
375
|
}
|
|
365
376
|
|
|
366
377
|
function anthropicModelHasRealXHighEffort<TApi extends Api>(model: ApiModel<TApi>): boolean {
|
|
367
378
|
if (model.api !== "anthropic-messages") return false;
|
|
368
379
|
const parsedModel = parseKnownModel(model.id);
|
|
369
|
-
if (parsedModel.family !== "anthropic"
|
|
370
|
-
|
|
380
|
+
if (parsedModel.family !== "anthropic") return false;
|
|
381
|
+
if (isFableOrMythos(parsedModel.kind)) return true;
|
|
382
|
+
return parsedModel.kind === "opus" && semverGte(parsedModel.version, "4.7");
|
|
371
383
|
}
|
|
372
384
|
|
|
373
385
|
function applyGeneratedModelPolicy(model: ApiModel<Api>): void {
|
|
@@ -431,6 +443,19 @@ function applyAnthropicCatalogPolicy(model: ApiModel<Api>, parsedModel: Anthropi
|
|
|
431
443
|
model.contextWindow = 1000000;
|
|
432
444
|
model.maxTokens = 128000;
|
|
433
445
|
}
|
|
446
|
+
|
|
447
|
+
// Claude Fable/Mythos 5: Anthropic's /v1/models omits token limits and
|
|
448
|
+
// pricing, and models.dev lags new releases. Pin authoritative values from
|
|
449
|
+
// the model card (1M context / 128k output) and pricing docs ($10 in / $50
|
|
450
|
+
// out per MTok).
|
|
451
|
+
if (model.provider === "anthropic" && isFableOrMythos(parsedModel.kind)) {
|
|
452
|
+
model.contextWindow = 1_000_000;
|
|
453
|
+
model.maxTokens = 128_000;
|
|
454
|
+
model.cost.input = 10;
|
|
455
|
+
model.cost.output = 50;
|
|
456
|
+
model.cost.cacheRead = 1;
|
|
457
|
+
model.cost.cacheWrite = 12.5;
|
|
458
|
+
}
|
|
434
459
|
}
|
|
435
460
|
|
|
436
461
|
function inferGeneratedApplyPatchToolType(
|
|
@@ -562,7 +587,9 @@ function inferAnthropicSupportedEfforts<TApi extends Api>(
|
|
|
562
587
|
(model.api === "anthropic-messages" || model.api === "bedrock-converse-stream") &&
|
|
563
588
|
semverGte(parsedModel.version, "4.6")
|
|
564
589
|
) {
|
|
565
|
-
return parsedModel.kind === "opus"
|
|
590
|
+
return parsedModel.kind === "opus" || isFableOrMythos(parsedModel.kind)
|
|
591
|
+
? DEFAULT_REASONING_EFFORTS_WITH_XHIGH
|
|
592
|
+
: DEFAULT_REASONING_EFFORTS;
|
|
566
593
|
}
|
|
567
594
|
return inferFallbackEfforts(model);
|
|
568
595
|
}
|
|
@@ -618,7 +645,10 @@ function inferThinkingControlMode<TApi extends Api>(
|
|
|
618
645
|
|
|
619
646
|
case "bedrock-converse-stream":
|
|
620
647
|
if (parsedModel.family === "anthropic") {
|
|
621
|
-
if (
|
|
648
|
+
if (
|
|
649
|
+
semverGte(parsedModel.version, "4.6") &&
|
|
650
|
+
(parsedModel.kind === "opus" || isFableOrMythos(parsedModel.kind))
|
|
651
|
+
) {
|
|
622
652
|
return "anthropic-adaptive";
|
|
623
653
|
}
|
|
624
654
|
if (semverGte(parsedModel.version, "4.5")) {
|
|
@@ -658,7 +688,7 @@ function parseGeminiModel(modelId: string): GeminiModel | null {
|
|
|
658
688
|
}
|
|
659
689
|
|
|
660
690
|
function parseAnthropicModel(modelId: string): AnthropicModel | null {
|
|
661
|
-
const match = /claude-(opus|sonnet)-(\d{1,2}(?:[.-]\d{1,2}){0,2})\b/.exec(modelId);
|
|
691
|
+
const match = /claude-(opus|sonnet|fable|mythos)-(\d{1,2}(?:[.-]\d{1,2}){0,2})\b/.exec(modelId);
|
|
662
692
|
if (!match) {
|
|
663
693
|
return null;
|
|
664
694
|
}
|