@oh-my-pi/pi-catalog 17.0.8 → 17.1.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/CHANGELOG.md +12 -0
- package/dist/types/build.d.ts +11 -0
- package/dist/types/compat/bedrock.d.ts +3 -0
- package/dist/types/hosts.d.ts +2 -2
- package/dist/types/provider-models/descriptors.d.ts +17 -0
- package/dist/types/provider-models/openai-compat.d.ts +15 -0
- package/dist/types/types.d.ts +56 -3
- package/dist/types/wire/alibaba-token-plan.d.ts +6 -0
- package/package.json +3 -3
- package/src/build.ts +4 -0
- package/src/compat/bedrock.ts +114 -0
- package/src/compat/openai.ts +22 -0
- package/src/discovery/codex.ts +12 -16
- package/src/hosts.ts +4 -1
- package/src/identity/priority.ts +1 -0
- package/src/models.json +277 -23
- package/src/provider-models/descriptors.ts +17 -0
- package/src/provider-models/openai-compat.ts +203 -0
- package/src/types.ts +67 -6
- package/src/wire/alibaba-token-plan.ts +27 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [17.1.0] - 2026-07-24
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added Bedrock Converse prompt-cache compatibility limits, including 5-minute checkpoint support for Nova models (Lite, Micro, Pro, Premier, Nova 2 Lite) and 1-hour Claude retention.
|
|
10
|
+
- Added native Meta Model API provider and Muse Spark 1.1 support, featuring Responses API reasoning replay, image input, and reasoning-effort controls.
|
|
11
|
+
- Added Vercel AI Gateway integration features, including opt-in automatic prompt-cache compatibility, provider routing preferences, and Responses cache-anchor and cache-lifetime controls.
|
|
12
|
+
- Added prompt-cache breakpoint capability metadata for OpenAI GPT-5.6, with opt-in support for older models and compatible endpoints.
|
|
13
|
+
- Added native alibaba-token-plan provider with QwenCloud Token Plan Individual discovery and a curated chat-model fallback catalog.
|
|
14
|
+
|
|
15
|
+
## [17.0.9] - 2026-07-23
|
|
16
|
+
|
|
5
17
|
### Changed
|
|
6
18
|
|
|
7
19
|
- Renamed `codex-auto-review` model to `GPT-5.3 Codex Spark` with updated pricing and capabilities
|
package/dist/types/build.d.ts
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single Model constructor. Resolution order is a dependency chain, each
|
|
3
|
+
* step materialized exactly once per spec:
|
|
4
|
+
*
|
|
5
|
+
* 1. compat — URL/provider/id detection resolved into a complete record;
|
|
6
|
+
* 2. thinking — derived from identity + resolved compat (or trusted verbatim
|
|
7
|
+
* when the spec carries explicit metadata);
|
|
8
|
+
*
|
|
9
|
+
* Request handlers read fields — they never detect, parse ids, or allocate
|
|
10
|
+
* compat per request.
|
|
11
|
+
*/
|
|
1
12
|
import type { Api, CompatOf, Model, ModelSpec } from "./types.js";
|
|
2
13
|
export declare function buildModel<TApi extends Api>(spec: ModelSpec<TApi>): Model<TApi>;
|
|
3
14
|
export declare function buildCompat(spec: ModelSpec<Api>): CompatOf<Api>;
|
package/dist/types/hosts.d.ts
CHANGED
|
@@ -62,8 +62,8 @@ export declare const KNOWN_HOSTS: {
|
|
|
62
62
|
readonly urlMarkers: readonly ["api.kilo.ai"];
|
|
63
63
|
};
|
|
64
64
|
readonly alibabaDashscope: {
|
|
65
|
-
readonly providers: readonly ["alibaba-coding-plan"];
|
|
66
|
-
readonly urlMarkers: readonly ["dashscope"];
|
|
65
|
+
readonly providers: readonly ["alibaba-coding-plan", "alibaba-token-plan"];
|
|
66
|
+
readonly urlMarkers: readonly ["dashscope", "token-plan."];
|
|
67
67
|
};
|
|
68
68
|
readonly umans: {
|
|
69
69
|
readonly providers: readonly ["umans"];
|
|
@@ -23,6 +23,15 @@ export declare const CATALOG_PROVIDERS: readonly [{
|
|
|
23
23
|
readonly catalogDiscovery: {
|
|
24
24
|
readonly label: "Alibaba Coding Plan";
|
|
25
25
|
};
|
|
26
|
+
}, {
|
|
27
|
+
readonly id: "alibaba-token-plan";
|
|
28
|
+
readonly defaultModel: "qwen3.7-plus";
|
|
29
|
+
readonly envVars: readonly ["ALIBABA_TOKEN_PLAN_API_KEY", "BAILIAN_TOKEN_PLAN_API_KEY"];
|
|
30
|
+
readonly createModelManagerOptions: (config: ModelManagerConfig) => import("../index.js").ModelManagerOptions<"openai-completions", unknown>;
|
|
31
|
+
readonly dynamicModelsAuthoritative: true;
|
|
32
|
+
readonly catalogDiscovery: {
|
|
33
|
+
readonly label: "QwenCloud Token Plan";
|
|
34
|
+
};
|
|
26
35
|
}, {
|
|
27
36
|
readonly id: "baseten";
|
|
28
37
|
readonly defaultModel: "moonshotai/Kimi-K2.7-Code";
|
|
@@ -200,6 +209,14 @@ export declare const CATALOG_PROVIDERS: readonly [{
|
|
|
200
209
|
readonly defaultModel: "devstral-medium-latest";
|
|
201
210
|
readonly envVars: readonly ["MISTRAL_API_KEY"];
|
|
202
211
|
readonly createModelManagerOptions: (config: ModelManagerConfig) => import("../index.js").ModelManagerOptions<"openai-completions", unknown>;
|
|
212
|
+
}, {
|
|
213
|
+
readonly id: "meta";
|
|
214
|
+
readonly defaultModel: "muse-spark-1.1";
|
|
215
|
+
readonly envVars: readonly ["MODEL_API_KEY", "META_API_KEY"];
|
|
216
|
+
readonly createModelManagerOptions: (config: ModelManagerConfig) => import("../index.js").ModelManagerOptions<"openai-responses", unknown>;
|
|
217
|
+
readonly catalogDiscovery: {
|
|
218
|
+
readonly label: "Meta Model API";
|
|
219
|
+
};
|
|
203
220
|
}, {
|
|
204
221
|
readonly id: "moonshot";
|
|
205
222
|
readonly defaultModel: "kimi-k2.7-code";
|
|
@@ -299,6 +299,14 @@ export interface AlibabaCodingPlanModelManagerConfig {
|
|
|
299
299
|
fetch?: FetchImpl;
|
|
300
300
|
}
|
|
301
301
|
export declare function alibabaCodingPlanModelManagerOptions(config?: AlibabaCodingPlanModelManagerConfig): ModelManagerOptions<"openai-completions">;
|
|
302
|
+
export declare const ALIBABA_TOKEN_PLAN_BASE_URL = "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1";
|
|
303
|
+
export declare const ALIBABA_TOKEN_PLAN_STATIC_MODELS: readonly ModelSpec<"openai-completions">[];
|
|
304
|
+
export interface AlibabaTokenPlanModelManagerConfig {
|
|
305
|
+
apiKey?: string;
|
|
306
|
+
baseUrl?: string;
|
|
307
|
+
fetch?: FetchImpl;
|
|
308
|
+
}
|
|
309
|
+
export declare function alibabaTokenPlanModelManagerOptions(config?: AlibabaTokenPlanModelManagerConfig): ModelManagerOptions<"openai-completions">;
|
|
302
310
|
export interface VercelAiGatewayModelManagerConfig {
|
|
303
311
|
apiKey?: string;
|
|
304
312
|
baseUrl?: string;
|
|
@@ -359,6 +367,13 @@ export interface CoreWeaveModelManagerConfig {
|
|
|
359
367
|
fetch?: FetchImpl;
|
|
360
368
|
}
|
|
361
369
|
export declare function coreWeaveModelManagerOptions(config?: CoreWeaveModelManagerConfig): ModelManagerOptions<"openai-completions">;
|
|
370
|
+
export declare const META_MUSE_STATIC_MODELS: readonly ModelSpec<"openai-responses">[];
|
|
371
|
+
export interface MetaModelManagerConfig {
|
|
372
|
+
apiKey?: string;
|
|
373
|
+
baseUrl?: string;
|
|
374
|
+
fetch?: FetchImpl;
|
|
375
|
+
}
|
|
376
|
+
export declare function metaModelManagerOptions(config?: MetaModelManagerConfig): ModelManagerOptions<"openai-responses">;
|
|
362
377
|
export interface MoonshotModelManagerConfig {
|
|
363
378
|
apiKey?: string;
|
|
364
379
|
baseUrl?: string;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -268,6 +268,14 @@ export interface OpenAICompat {
|
|
|
268
268
|
promptCacheSessionHeader?: "x-grok-conv-id";
|
|
269
269
|
/** Whether chat-completions payloads should include provider-specific prompt-cache markers. */
|
|
270
270
|
cacheControlFormat?: "anthropic" | undefined;
|
|
271
|
+
/**
|
|
272
|
+
* Whether this endpoint/model accepts OpenAI's explicit
|
|
273
|
+
* `prompt_cache_breakpoint` content markers and `prompt_cache_options`.
|
|
274
|
+
* Defaults to the exact first-party model generation allowlist.
|
|
275
|
+
*/
|
|
276
|
+
supportsPromptCacheBreakpoints?: boolean;
|
|
277
|
+
/** The only currently supported minimum lifetime for explicit OpenAI cache breakpoints. */
|
|
278
|
+
promptCacheBreakpointTtl?: "30m";
|
|
271
279
|
/** Whether the provider supports the `strict` field in tool definitions. Default: auto-detected per provider/baseUrl (conservative for unknown providers). */
|
|
272
280
|
supportsStrictMode?: boolean;
|
|
273
281
|
/**
|
|
@@ -419,6 +427,34 @@ export interface AnthropicCompat {
|
|
|
419
427
|
*/
|
|
420
428
|
escapeBuiltinToolNames?: boolean;
|
|
421
429
|
}
|
|
430
|
+
/**
|
|
431
|
+
* Compatibility settings for Bedrock Converse prompt caching. Cache pricing is
|
|
432
|
+
* deliberately not used to infer these request-shape capabilities.
|
|
433
|
+
*/
|
|
434
|
+
export interface BedrockCompat {
|
|
435
|
+
/** Whether this endpoint accepts no checkpoints, automatic caching, or explicit cachePoint blocks. */
|
|
436
|
+
promptCacheMode?: "none" | "automatic" | "explicit";
|
|
437
|
+
/** Whether explicit cachePoint blocks accept `ttl: "1h"`; omitted TTL means Bedrock's 5-minute default. */
|
|
438
|
+
supportsLongPromptCacheRetention?: boolean;
|
|
439
|
+
/**
|
|
440
|
+
* Bedrock-enforced minimum prompt-prefix tokens for an effective checkpoint.
|
|
441
|
+
* Capability metadata only: emitters must not estimate local token counts.
|
|
442
|
+
* Zero means no explicit checkpoints.
|
|
443
|
+
*/
|
|
444
|
+
promptCacheMinimumTokens?: number;
|
|
445
|
+
/**
|
|
446
|
+
* Bedrock-enforced maximum explicit cache checkpoints per request.
|
|
447
|
+
* Capability metadata only; zero means no explicit checkpoints.
|
|
448
|
+
*/
|
|
449
|
+
promptCacheMaximumCheckpoints?: number;
|
|
450
|
+
}
|
|
451
|
+
/** Fully-resolved Bedrock Converse prompt-cache capabilities, materialized once by `buildModel`. */
|
|
452
|
+
export interface ResolvedBedrockCompat {
|
|
453
|
+
promptCacheMode: NonNullable<BedrockCompat["promptCacheMode"]>;
|
|
454
|
+
supportsLongPromptCacheRetention: boolean;
|
|
455
|
+
promptCacheMinimumTokens: number;
|
|
456
|
+
promptCacheMaximumCheckpoints: number;
|
|
457
|
+
}
|
|
422
458
|
/**
|
|
423
459
|
* OpenRouter provider routing preferences.
|
|
424
460
|
* Controls which upstream providers OpenRouter routes requests to.
|
|
@@ -440,6 +476,12 @@ export interface VercelGatewayRouting {
|
|
|
440
476
|
only?: string[];
|
|
441
477
|
/** List of provider slugs to try in order (e.g., ["anthropic", "openai"]). */
|
|
442
478
|
order?: string[];
|
|
479
|
+
/** Enables Vercel AI Gateway's provider-aware automatic prompt caching. */
|
|
480
|
+
caching?: "auto";
|
|
481
|
+
/** Stable Responses input-item prefix to anchor for automatic caching. */
|
|
482
|
+
cacheAnchorItems?: number;
|
|
483
|
+
/** Requested automatic-cache lifetime for the Responses API. */
|
|
484
|
+
cacheTtl?: "5m" | "1h";
|
|
443
485
|
}
|
|
444
486
|
type ResolvedToolStrictMode = NonNullable<OpenAICompat["toolStrictMode"]> | "mixed";
|
|
445
487
|
/**
|
|
@@ -482,6 +524,14 @@ export interface ResolvedOpenAISharedCompat {
|
|
|
482
524
|
emptyLengthFinishIsContextError: boolean;
|
|
483
525
|
usesOpenAIToolCallIdLimit: boolean;
|
|
484
526
|
promptCacheSessionHeader?: OpenAICompat["promptCacheSessionHeader"];
|
|
527
|
+
/**
|
|
528
|
+
* Whether this model accepts explicit OpenAI prompt-cache breakpoints.
|
|
529
|
+
* Built catalog models always materialize this false-by-default value;
|
|
530
|
+
* optionality preserves hand-authored resolved compat fixtures.
|
|
531
|
+
*/
|
|
532
|
+
supportsPromptCacheBreakpoints?: boolean;
|
|
533
|
+
/** Minimum cache lifetime supported by explicit OpenAI prompt-cache breakpoints. */
|
|
534
|
+
promptCacheBreakpointTtl?: "30m";
|
|
485
535
|
/** The model sits behind OpenRouter (routing prefs and max-token omission apply). */
|
|
486
536
|
isOpenRouterHost: boolean;
|
|
487
537
|
/** Whether this endpoint needs a max-token field even when caller did not set one. */
|
|
@@ -500,7 +550,7 @@ export interface ResolvedOpenAISharedCompat {
|
|
|
500
550
|
* `buildModel`; request handlers read fields and never detect, resolve, or
|
|
501
551
|
* allocate.
|
|
502
552
|
*/
|
|
503
|
-
export type ResolvedOpenAICompat = ResolvedOpenAISharedCompat & Required<Omit<OpenAICompat, "supportsDeveloperRole" | "supportsReasoningEffort" | "reasoningEffortMap" | "supportsReasoningParams" | "supportsSamplingParams" | "thinkingFormat" | "kimiApiFormat" | "reasoningDisableMode" | "omitReasoningEffort" | "includeEncryptedReasoning" | "filterReasoningHistory" | "disableReasoningOnForcedToolChoice" | "disableReasoningOnToolChoice" | "supportsToolChoice" | "supportsForcedToolChoice" | "supportsNamedToolChoice" | "reasoningContentField" | "requiresReasoningContentForToolCalls" | "requiresReasoningContentForAllAssistantTurns" | "allowsSyntheticReasoningContentForToolCalls" | "replayReasoningContent" | "qwenPreserveThinking" | "requiresThinkingAsText" | "requiresMistralToolIds" | "requiresToolResultName" | "requiresAssistantAfterToolResult" | "requiresAssistantContentForToolCalls" | "stripDeepseekSpecialTokens" | "streamMarkupHealingPattern" | "reasoningDeltasMayBeCumulative" | "emptyLengthFinishIsContextError" | "usesOpenAIToolCallIdLimit" | "promptCacheSessionHeader" | "openRouterRouting" | "isOpenRouterHost" | "supportsStrictMode" | "supportsLongPromptCacheRetention" | "alwaysSendMaxTokens" | "wireModelIdMode" | "vercelGatewayRouting" | "extraBody" | "toolStrictMode" | "toolSchemaFlavor" | "streamIdleTimeoutMs" | "cacheControlFormat" | "thinkingKeep" | "strictResponsesPairing" | "supportsImageDetailOriginal" | "enableGeminiThinkingLoopGuard" | "whenThinking">> & {
|
|
553
|
+
export type ResolvedOpenAICompat = ResolvedOpenAISharedCompat & Required<Omit<OpenAICompat, "supportsDeveloperRole" | "supportsReasoningEffort" | "reasoningEffortMap" | "supportsReasoningParams" | "supportsSamplingParams" | "thinkingFormat" | "kimiApiFormat" | "reasoningDisableMode" | "omitReasoningEffort" | "includeEncryptedReasoning" | "filterReasoningHistory" | "disableReasoningOnForcedToolChoice" | "disableReasoningOnToolChoice" | "supportsToolChoice" | "supportsForcedToolChoice" | "supportsNamedToolChoice" | "reasoningContentField" | "requiresReasoningContentForToolCalls" | "requiresReasoningContentForAllAssistantTurns" | "allowsSyntheticReasoningContentForToolCalls" | "replayReasoningContent" | "qwenPreserveThinking" | "requiresThinkingAsText" | "requiresMistralToolIds" | "requiresToolResultName" | "requiresAssistantAfterToolResult" | "requiresAssistantContentForToolCalls" | "stripDeepseekSpecialTokens" | "streamMarkupHealingPattern" | "reasoningDeltasMayBeCumulative" | "emptyLengthFinishIsContextError" | "usesOpenAIToolCallIdLimit" | "promptCacheSessionHeader" | "supportsPromptCacheBreakpoints" | "promptCacheBreakpointTtl" | "openRouterRouting" | "isOpenRouterHost" | "supportsStrictMode" | "supportsLongPromptCacheRetention" | "alwaysSendMaxTokens" | "wireModelIdMode" | "vercelGatewayRouting" | "extraBody" | "toolStrictMode" | "toolSchemaFlavor" | "streamIdleTimeoutMs" | "cacheControlFormat" | "thinkingKeep" | "strictResponsesPairing" | "supportsImageDetailOriginal" | "enableGeminiThinkingLoopGuard" | "whenThinking">> & {
|
|
504
554
|
vercelGatewayRouting?: OpenAICompat["vercelGatewayRouting"];
|
|
505
555
|
extraBody?: OpenAICompat["extraBody"];
|
|
506
556
|
cacheControlFormat?: OpenAICompat["cacheControlFormat"];
|
|
@@ -520,6 +570,9 @@ export interface ResolvedOpenAIResponsesCompat extends ResolvedOpenAISharedCompa
|
|
|
520
570
|
supportsImageDetailOriginal: boolean;
|
|
521
571
|
supportsObfuscationOptOut: boolean;
|
|
522
572
|
streamIdleTimeoutMs?: number;
|
|
573
|
+
vercelGatewayRouting?: OpenAICompat["vercelGatewayRouting"];
|
|
574
|
+
/** The model sits behind Vercel AI Gateway's Responses endpoint. */
|
|
575
|
+
isVercelGatewayHost: boolean;
|
|
523
576
|
}
|
|
524
577
|
/**
|
|
525
578
|
* OpenRouter is a pseudo API: runtime dispatch can use either Responses
|
|
@@ -567,9 +620,9 @@ export interface DevinCompat {
|
|
|
567
620
|
/** Fully-resolved devin-agent compat view. */
|
|
568
621
|
export type ResolvedDevinCompat = Required<DevinCompat>;
|
|
569
622
|
/** Sparse, user-authored compat overrides for a given API (models.json / config vocabulary). */
|
|
570
|
-
export type CompatConfigOf<TApi extends Api> = TApi extends "openai-completions" | "openrouter" | "openai-responses" | "azure-openai-responses" | "openai-codex-responses" ? OpenAICompat : TApi extends "anthropic-messages" ? AnthropicCompat : TApi extends "devin-agent" ? DevinCompat : undefined;
|
|
623
|
+
export type CompatConfigOf<TApi extends Api> = TApi extends "openai-completions" | "openrouter" | "openai-responses" | "azure-openai-responses" | "openai-codex-responses" ? OpenAICompat : TApi extends "anthropic-messages" ? AnthropicCompat : TApi extends "bedrock-converse-stream" ? BedrockCompat : TApi extends "devin-agent" ? DevinCompat : undefined;
|
|
571
624
|
/** Resolved compat for a given API: complete record, materialized once by `buildModel`. */
|
|
572
|
-
export type CompatOf<TApi extends Api> = TApi extends "openrouter" ? ResolvedOpenRouterCompat : TApi extends "openai-completions" ? ResolvedOpenAICompat : TApi extends "openai-responses" | "azure-openai-responses" | "openai-codex-responses" ? ResolvedOpenAIResponsesCompat : TApi extends "anthropic-messages" ? ResolvedAnthropicCompat : TApi extends "devin-agent" ? ResolvedDevinCompat : undefined;
|
|
625
|
+
export type CompatOf<TApi extends Api> = TApi extends "openrouter" ? ResolvedOpenRouterCompat : TApi extends "openai-completions" ? ResolvedOpenAICompat : TApi extends "openai-responses" | "azure-openai-responses" | "openai-codex-responses" ? ResolvedOpenAIResponsesCompat : TApi extends "anthropic-messages" ? ResolvedAnthropicCompat : TApi extends "bedrock-converse-stream" ? ResolvedBedrockCompat : TApi extends "devin-agent" ? ResolvedDevinCompat : undefined;
|
|
573
626
|
/** Provider-native compaction endpoint configuration for one model. */
|
|
574
627
|
export interface RemoteCompactionConfig<TApi extends Api = Api> {
|
|
575
628
|
/** Enables provider-native compaction for providers not enabled by built-in policy. */
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export interface AlibabaTokenPlanCredential {
|
|
2
|
+
token: string;
|
|
3
|
+
cookie?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function parseAlibabaTokenPlanCredential(value: string): AlibabaTokenPlanCredential | null;
|
|
6
|
+
export declare function serializeAlibabaTokenPlanCredential(token: string, cookie: string): string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-catalog",
|
|
4
|
-
"version": "17.0
|
|
4
|
+
"version": "17.1.0",
|
|
5
5
|
"description": "Model catalog for omp: bundled model database, provider discovery descriptors, model identity, classification, and equivalence",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@bufbuild/protobuf": "^2.12.1",
|
|
37
|
-
"@oh-my-pi/pi-utils": "17.0
|
|
37
|
+
"@oh-my-pi/pi-utils": "17.1.0",
|
|
38
38
|
"arktype": "2.2.3",
|
|
39
39
|
"zod": "^4"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@oh-my-pi/pi-ai": "17.0
|
|
42
|
+
"@oh-my-pi/pi-ai": "17.1.0",
|
|
43
43
|
"@types/bun": "^1.3.14"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|
package/src/build.ts
CHANGED
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
* Request handlers read fields — they never detect, parse ids, or allocate
|
|
10
10
|
* compat per request.
|
|
11
11
|
*/
|
|
12
|
+
|
|
12
13
|
import { buildAnthropicCompat } from "./compat/anthropic";
|
|
14
|
+
import { buildBedrockCompat } from "./compat/bedrock";
|
|
13
15
|
import { buildDevinCompat } from "./compat/devin";
|
|
14
16
|
import { buildOpenAICompat, buildOpenAIResponsesCompat, buildOpenRouterCompat } from "./compat/openai";
|
|
15
17
|
import { resolveModelThinking } from "./model-thinking";
|
|
@@ -39,6 +41,8 @@ export function buildCompat(spec: ModelSpec<Api>): CompatOf<Api> {
|
|
|
39
41
|
return buildOpenAIResponsesCompat(spec as ModelSpec<"openai-responses">);
|
|
40
42
|
case "anthropic-messages":
|
|
41
43
|
return buildAnthropicCompat(spec as ModelSpec<"anthropic-messages">);
|
|
44
|
+
case "bedrock-converse-stream":
|
|
45
|
+
return buildBedrockCompat(spec as ModelSpec<"bedrock-converse-stream">);
|
|
42
46
|
case "devin-agent":
|
|
43
47
|
return buildDevinCompat(spec as ModelSpec<"devin-agent">);
|
|
44
48
|
default:
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { ModelSpec, ResolvedBedrockCompat } from "../types";
|
|
2
|
+
import { applyCompatOverrides } from "./apply";
|
|
3
|
+
|
|
4
|
+
const NO_EXPLICIT_CHECKPOINTS: ResolvedBedrockCompat = {
|
|
5
|
+
promptCacheMode: "none",
|
|
6
|
+
supportsLongPromptCacheRetention: false,
|
|
7
|
+
promptCacheMinimumTokens: 0,
|
|
8
|
+
promptCacheMaximumCheckpoints: 0,
|
|
9
|
+
};
|
|
10
|
+
const EXPLICIT_CHECKPOINTS_1024_5M: ResolvedBedrockCompat = {
|
|
11
|
+
promptCacheMode: "explicit",
|
|
12
|
+
supportsLongPromptCacheRetention: false,
|
|
13
|
+
promptCacheMinimumTokens: 1024,
|
|
14
|
+
promptCacheMaximumCheckpoints: 4,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const EXPLICIT_CHECKPOINTS_1024_1H: ResolvedBedrockCompat = {
|
|
18
|
+
promptCacheMode: "explicit",
|
|
19
|
+
supportsLongPromptCacheRetention: true,
|
|
20
|
+
promptCacheMinimumTokens: 1024,
|
|
21
|
+
promptCacheMaximumCheckpoints: 4,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const EXPLICIT_CHECKPOINTS_2048_5M: ResolvedBedrockCompat = {
|
|
25
|
+
promptCacheMode: "explicit",
|
|
26
|
+
supportsLongPromptCacheRetention: false,
|
|
27
|
+
promptCacheMinimumTokens: 2048,
|
|
28
|
+
promptCacheMaximumCheckpoints: 4,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const EXPLICIT_CHECKPOINTS_4096_5M: ResolvedBedrockCompat = {
|
|
32
|
+
promptCacheMode: "explicit",
|
|
33
|
+
supportsLongPromptCacheRetention: false,
|
|
34
|
+
promptCacheMinimumTokens: 4096,
|
|
35
|
+
promptCacheMaximumCheckpoints: 4,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const EXPLICIT_CHECKPOINTS_4096_1H: ResolvedBedrockCompat = {
|
|
39
|
+
promptCacheMode: "explicit",
|
|
40
|
+
supportsLongPromptCacheRetention: true,
|
|
41
|
+
promptCacheMinimumTokens: 4096,
|
|
42
|
+
promptCacheMaximumCheckpoints: 4,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Explicit Nova cache points complement Bedrock's automatic prefix caching:
|
|
47
|
+
* AWS recommends them for consistent cache hits and input-cost savings. Keep
|
|
48
|
+
* these exact documented model and inference-profile IDs conservative rather
|
|
49
|
+
* than treating arbitrary Nova-like application profiles as checkpoint-capable.
|
|
50
|
+
*/
|
|
51
|
+
function detectedBedrockCompat(modelId: string): ResolvedBedrockCompat {
|
|
52
|
+
const id = modelId.toLowerCase();
|
|
53
|
+
|
|
54
|
+
if (
|
|
55
|
+
id === "amazon.nova-lite-v1:0" ||
|
|
56
|
+
id === "us.amazon.nova-lite-v1:0" ||
|
|
57
|
+
id === "amazon.nova-micro-v1:0" ||
|
|
58
|
+
id === "us.amazon.nova-micro-v1:0" ||
|
|
59
|
+
id === "amazon.nova-pro-v1:0" ||
|
|
60
|
+
id === "us.amazon.nova-pro-v1:0" ||
|
|
61
|
+
id === "amazon.nova-premier-v1:0" ||
|
|
62
|
+
id === "us.amazon.nova-premier-v1:0" ||
|
|
63
|
+
id === "amazon.nova-2-lite-v1:0" ||
|
|
64
|
+
id === "us.amazon.nova-2-lite-v1:0" ||
|
|
65
|
+
id === "eu.amazon.nova-2-lite-v1:0" ||
|
|
66
|
+
id === "jp.amazon.nova-2-lite-v1:0" ||
|
|
67
|
+
id === "global.amazon.nova-2-lite-v1:0"
|
|
68
|
+
) {
|
|
69
|
+
return EXPLICIT_CHECKPOINTS_1024_5M;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html
|
|
73
|
+
// This list is deliberately sourced from AWS model cards, not cache pricing:
|
|
74
|
+
// https://docs.aws.amazon.com/bedrock/latest/userguide/model-cards.html
|
|
75
|
+
if (
|
|
76
|
+
id.includes("anthropic.claude-opus-4-5") ||
|
|
77
|
+
id.includes("anthropic.claude-sonnet-4-5") ||
|
|
78
|
+
id.includes("anthropic.claude-haiku-4-5") ||
|
|
79
|
+
id.includes("anthropic.claude-opus-4-7") ||
|
|
80
|
+
id.includes("anthropic.claude-opus-4-8") ||
|
|
81
|
+
id.includes("anthropic.claude-sonnet-5")
|
|
82
|
+
) {
|
|
83
|
+
return EXPLICIT_CHECKPOINTS_4096_1H;
|
|
84
|
+
}
|
|
85
|
+
if (id.includes("anthropic.claude-opus-4-6")) {
|
|
86
|
+
return EXPLICIT_CHECKPOINTS_4096_5M;
|
|
87
|
+
}
|
|
88
|
+
if (id.includes("anthropic.claude-3-5-haiku")) {
|
|
89
|
+
return EXPLICIT_CHECKPOINTS_2048_5M;
|
|
90
|
+
}
|
|
91
|
+
if (id.includes("anthropic.claude-fable-5")) {
|
|
92
|
+
return EXPLICIT_CHECKPOINTS_1024_1H;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (
|
|
96
|
+
id.includes("anthropic.claude-opus-4-1") ||
|
|
97
|
+
id.includes("anthropic.claude-opus-4-20250514") ||
|
|
98
|
+
id.includes("anthropic.claude-sonnet-4-20250514") ||
|
|
99
|
+
id.includes("anthropic.claude-sonnet-4-6") ||
|
|
100
|
+
id.includes("anthropic.claude-3-7-sonnet") ||
|
|
101
|
+
id.includes("anthropic.claude-3-5-sonnet-20241022-v2")
|
|
102
|
+
) {
|
|
103
|
+
return EXPLICIT_CHECKPOINTS_1024_5M;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return NO_EXPLICIT_CHECKPOINTS;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Resolve Bedrock Converse prompt-cache capabilities once per model. */
|
|
110
|
+
export function buildBedrockCompat(spec: ModelSpec<"bedrock-converse-stream">): ResolvedBedrockCompat {
|
|
111
|
+
const compat = { ...detectedBedrockCompat(spec.id) };
|
|
112
|
+
applyCompatOverrides(compat, spec.compat);
|
|
113
|
+
return compat;
|
|
114
|
+
}
|
package/src/compat/openai.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { isFireworksFastModelId } from "../fireworks-model-id";
|
|
11
11
|
import { hostMatchesUrl, modelMatchesHost } from "../hosts";
|
|
12
|
+
import { bareModelId, parseOpenAIModel, semverGte } from "../identity/classify";
|
|
12
13
|
import {
|
|
13
14
|
isAnthropicNamespacedModelId,
|
|
14
15
|
isClaudeModelId,
|
|
@@ -133,6 +134,17 @@ function isOfficialOpenAIEndpoint(provider: string, baseUrl: string): boolean {
|
|
|
133
134
|
}
|
|
134
135
|
}
|
|
135
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Explicit prompt-cache breakpoints are a GPT-5.6+ first-party contract. Keep
|
|
139
|
+
* this intentionally narrow: compatible gateways and older OpenAI models
|
|
140
|
+
* reject the new request fields unless their catalog compat opts in.
|
|
141
|
+
*/
|
|
142
|
+
function supportsOfficialOpenAIPromptCacheBreakpoints(provider: string, modelId: string, baseUrl: string): boolean {
|
|
143
|
+
if (!isOfficialOpenAIEndpoint(provider, baseUrl)) return false;
|
|
144
|
+
const model = parseOpenAIModel(bareModelId(modelId));
|
|
145
|
+
return model !== null && semverGte(model.version, "5.6");
|
|
146
|
+
}
|
|
147
|
+
|
|
136
148
|
/**
|
|
137
149
|
* OpenCode's gateways (https://opencode.ai/zen|go) gate `reasoning_content`
|
|
138
150
|
* on the request's thinking state for every model they front (Kimi K2.x,
|
|
@@ -341,6 +353,7 @@ export function buildOpenAICompat(spec: ModelSpec<"openai-completions">): Resolv
|
|
|
341
353
|
hostMatchesUrl(baseUrl, "fireworks") ||
|
|
342
354
|
isDirectDeepseekApi;
|
|
343
355
|
|
|
356
|
+
const supportsPromptCacheBreakpoints = supportsOfficialOpenAIPromptCacheBreakpoints(provider, spec.id, baseUrl);
|
|
344
357
|
// Hosts whose chat-completions endpoints are known to accept multiple
|
|
345
358
|
// leading `system`/`developer` messages (preferred for KV-cache reuse).
|
|
346
359
|
// Anything outside this allowlist defaults to coalescing because
|
|
@@ -546,6 +559,8 @@ export function buildOpenAICompat(spec: ModelSpec<"openai-completions">): Resolv
|
|
|
546
559
|
(thinkingFormat === "qwen" || thinkingFormat === "qwen-chat-template") && isLocalOpenAICompatBackend,
|
|
547
560
|
requiresAssistantContentForToolCalls: isKimiModel || isDirectDeepseekReasoning,
|
|
548
561
|
cacheControlFormat: isOpenRouter && spec.id.startsWith("anthropic/") ? "anthropic" : undefined,
|
|
562
|
+
supportsPromptCacheBreakpoints,
|
|
563
|
+
promptCacheBreakpointTtl: supportsPromptCacheBreakpoints ? "30m" : undefined,
|
|
549
564
|
openRouterRouting: undefined,
|
|
550
565
|
vercelGatewayRouting: undefined,
|
|
551
566
|
isOpenRouterHost: isOpenRouter,
|
|
@@ -623,7 +638,9 @@ export function buildOpenAIResponsesCompat(spec: OpenAIResponsesSpecLike): Resol
|
|
|
623
638
|
const isAzure = modelMatchesHost({ provider: spec.provider, baseUrl }, "azureOpenAI");
|
|
624
639
|
const isOpenRouter = modelMatchesHost({ provider: spec.provider, baseUrl }, "openrouter");
|
|
625
640
|
const isOpenAIUrl = hostMatchesUrl(baseUrl, "openai");
|
|
641
|
+
const isVercelGateway = modelMatchesHost({ provider: spec.provider, baseUrl }, "vercelAIGateway");
|
|
626
642
|
const id = spec.id ?? "";
|
|
643
|
+
const supportsPromptCacheBreakpoints = supportsOfficialOpenAIPromptCacheBreakpoints(spec.provider, id, baseUrl);
|
|
627
644
|
const thinkingFormat: ResolvedOpenAISharedCompat["thinkingFormat"] = isOpenRouter ? "openrouter" : "openai";
|
|
628
645
|
const isKimiModel = id ? isKimiModelId(id) : false;
|
|
629
646
|
const isAnthropicModel = id ? isClaudeModelId(id) || isAnthropicNamespacedModelId(id) : false;
|
|
@@ -642,6 +659,8 @@ export function buildOpenAIResponsesCompat(spec: OpenAIResponsesSpecLike): Resol
|
|
|
642
659
|
supportsStrictMode: isAzure || detectStrictModeSupport(spec.provider, baseUrl),
|
|
643
660
|
supportsReasoningEffort: spec.provider !== "xai-oauth" || isGrokReasoningEffortCapable(id),
|
|
644
661
|
supportsLongPromptCacheRetention: isOpenAIUrl,
|
|
662
|
+
supportsPromptCacheBreakpoints,
|
|
663
|
+
promptCacheBreakpointTtl: supportsPromptCacheBreakpoints ? "30m" : undefined,
|
|
645
664
|
// Azure OpenAI and GitHub Copilot Responses paths require tool results
|
|
646
665
|
// to strictly match prior tool calls when building Responses inputs.
|
|
647
666
|
strictResponsesPairing: isAzure || spec.provider === "github-copilot",
|
|
@@ -686,7 +705,9 @@ export function buildOpenAIResponsesCompat(spec: OpenAIResponsesSpecLike): Resol
|
|
|
686
705
|
requiresAssistantAfterToolResult: false,
|
|
687
706
|
requiresAssistantContentForToolCalls: isKimiModel,
|
|
688
707
|
openRouterRouting: undefined,
|
|
708
|
+
vercelGatewayRouting: undefined,
|
|
689
709
|
isOpenRouterHost: isOpenRouter,
|
|
710
|
+
isVercelGatewayHost: isVercelGateway,
|
|
690
711
|
wireModelIdMode: isOpenRouter ? "openrouter" : "raw",
|
|
691
712
|
// Mirrors buildOpenAICompat: Kimi behind a Responses-capable proxy still
|
|
692
713
|
// lands on Moonshot's MFJS validator.
|
|
@@ -724,6 +745,7 @@ function pickResponsesOnly(compat: ResolvedOpenAIResponsesCompat): ResponsesOnly
|
|
|
724
745
|
strictResponsesPairing: compat.strictResponsesPairing,
|
|
725
746
|
supportsImageDetailOriginal: compat.supportsImageDetailOriginal,
|
|
726
747
|
supportsObfuscationOptOut: compat.supportsObfuscationOptOut,
|
|
748
|
+
isVercelGatewayHost: compat.isVercelGatewayHost,
|
|
727
749
|
} satisfies ResponsesOnlyCompat;
|
|
728
750
|
}
|
|
729
751
|
|
package/src/discovery/codex.ts
CHANGED
|
@@ -8,11 +8,11 @@ const DEFAULT_MODEL_LIST_PATHS = ["/codex/models", "/models"] as const;
|
|
|
8
8
|
const DEFAULT_CONTEXT_WINDOW = 272_000;
|
|
9
9
|
const DEFAULT_MAX_TOKENS = 128_000;
|
|
10
10
|
/**
|
|
11
|
-
* GPT-5.6 luna/sol/terra hard context capacity.
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
11
|
+
* GPT-5.6 luna/sol/terra hard context capacity. Codex discovery omits
|
|
12
|
+
* `context_window` for these SKUs, so the generic {@link DEFAULT_CONTEXT_WINDOW}
|
|
13
|
+
* (272000) would understate the real window — OpenAI's Codex model registry
|
|
14
|
+
* declares context_window = max_context_window = 372000 (#5705). Used as the
|
|
15
|
+
* fallback only when upstream reports no value.
|
|
16
16
|
*/
|
|
17
17
|
const GPT_5_6_CONTEXT_WINDOW = 372_000;
|
|
18
18
|
const CODEX_REMOTE_COMPACTION = {
|
|
@@ -223,18 +223,14 @@ function normalizeCodexModelEntry(entry: unknown, baseUrl: string): NormalizedCo
|
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
const name = toNonEmptyString(payload.display_name) ?? slug;
|
|
226
|
-
// GPT-5.6 luna/sol/terra
|
|
227
|
-
//
|
|
228
|
-
// actively returned as 272000 (#6259). Treat GPT_5_6_CONTEXT_WINDOW as a
|
|
229
|
-
// floor for these SKUs so neither the omission nor the active under-report
|
|
230
|
-
// regresses the real capacity; other models honor the reported value with
|
|
231
|
-
// the generic 272000 fallback.
|
|
226
|
+
// Codex discovery omits `context_window` for GPT-5.6 luna/sol/terra; the
|
|
227
|
+
// generic 272000 fallback understates their real 372000 window (#5705).
|
|
232
228
|
const parsed = parseKnownModel(slug);
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
229
|
+
const fallbackContextWindow =
|
|
230
|
+
parsed.family === "openai" && semverEqual(parsed.version, "5.6")
|
|
231
|
+
? GPT_5_6_CONTEXT_WINDOW
|
|
232
|
+
: DEFAULT_CONTEXT_WINDOW;
|
|
233
|
+
const contextWindow = toPositiveInt(payload.context_window) ?? fallbackContextWindow;
|
|
238
234
|
const maxTokens = Math.min(DEFAULT_MAX_TOKENS, contextWindow);
|
|
239
235
|
const reasoning = supportsReasoning(payload.default_reasoning_level, payload.supported_reasoning_levels);
|
|
240
236
|
const input = normalizeInputModalities(payload.input_modalities);
|
package/src/hosts.ts
CHANGED
|
@@ -41,7 +41,10 @@ export const KNOWN_HOSTS = {
|
|
|
41
41
|
zai: { providers: ["zai"], urlMarkers: ["api.z.ai"] },
|
|
42
42
|
zhipu: { providers: ["zhipu-coding-plan"], urlMarkers: ["open.bigmodel.cn"] },
|
|
43
43
|
kilo: { providers: ["kilo"], urlMarkers: ["api.kilo.ai"] },
|
|
44
|
-
alibabaDashscope: {
|
|
44
|
+
alibabaDashscope: {
|
|
45
|
+
providers: ["alibaba-coding-plan", "alibaba-token-plan"],
|
|
46
|
+
urlMarkers: ["dashscope", "token-plan."],
|
|
47
|
+
},
|
|
45
48
|
umans: { providers: ["umans"], urlMarkers: ["api.code.umans.ai"] },
|
|
46
49
|
xiaomi: { providers: ["xiaomi"], providerPrefixes: ["xiaomi-token-plan-"], urlMarkers: ["xiaomimimo.com"] },
|
|
47
50
|
xai: { providers: ["xai"], urlMarkers: ["api.x.ai"] },
|