@oh-my-pi/pi-catalog 18.8.5 → 18.8.7
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 +21 -0
- package/dist/types/compat/auth-ids.d.ts +2 -2
- package/dist/types/compat/prompt-cache-lookback.d.ts +7 -0
- package/dist/types/compat/provider-ids.d.ts +1 -1
- package/dist/types/model-manager.d.ts +16 -0
- package/dist/types/provider-models/openai-compat.d.ts +13 -0
- package/dist/types/types.d.ts +8 -1
- package/package.json +4 -4
- package/src/compat/auth-ids.ts +2 -0
- package/src/compat/axes.ts +8 -2
- package/src/compat/prompt-cache-lookback.ts +23 -0
- package/src/compat/provider-ids.ts +1 -0
- package/src/compat/resolve.ts +2 -0
- package/src/compat/rules/README.md +2 -0
- package/src/compat/rules/auth/_order.kdl +1 -1
- package/src/compat/rules/auth/coralbricks.kdl +13 -0
- package/src/compat/rules/classes/anthropic.kdl +10 -0
- package/src/compat/rules/providers/coralbricks.kdl +62 -0
- package/src/compat/rules.json +1 -1
- package/src/model-manager.ts +107 -41
- package/src/models.json +1 -1
- package/src/provider-models/descriptors.ts +2 -0
- package/src/provider-models/openai-compat.ts +165 -0
- package/src/types.ts +8 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [18.8.7] - 2026-10-09
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added built-in CoralBricks support with `/login`, live model discovery, per-model reasoning levels and off controls, and bundled offline fallbacks. ([#14146](https://github.com/can1357/oh-my-pi/pull/14146) by [@ryan-brosas](https://github.com/ryan-brosas))
|
|
10
|
+
- Added `gen:models --provider <id>` to update one provider without changing other providers' catalog snapshots. ([#14146](https://github.com/can1357/oh-my-pi/pull/14146) by [@ryan-brosas](https://github.com/ryan-brosas))
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Fixed Claude Haiku 5.5 thinking Off to request explicitly disabled thinking on every host serving its adaptive thinking ([#14996](https://github.com/can1357/oh-my-pi/pull/14996) by [@bse-ai](https://github.com/bse-ai)).
|
|
15
|
+
|
|
16
|
+
## [18.8.6] - 2026-10-08
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- Added prompt-cache lookback support for Claude models across all hosts, including the public `prompt-cache-lookback` catalog axis and `resolvePromptCacheLookback` API.
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- Fixed model discovery when providers publish models before they are recognized by the catalog; unsupported models are now skipped with a warning so other available models remain discoverable.
|
|
25
|
+
|
|
5
26
|
## [18.8.5] - 2026-10-08
|
|
6
27
|
|
|
7
28
|
### Breaking Changes
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/** Every provider with an `auth/<id>.kdl` policy. */
|
|
2
|
-
export type AuthProviderId = "abliteration" | "aiand" | "aimlapi" | "alibaba-coding-plan" | "alibaba-token-plan" | "amazon-bedrock" | "anthropic" | "apple" | "azure" | "baseten" | "bedrock-mantle" | "cerebras" | "charm-hyper" | "cline-pass" | "cloudflare-ai-gateway" | "commandcode" | "coreweave" | "cursor" | "deepinfra" | "deepseek" | "devin" | "exa" | "factory-droid" | "firepass" | "fireworks" | "github-copilot" | "gitlab-duo" | "gitlab-duo-agent" | "gmi-cloud" | "google" | "google-antigravity" | "google-gemini-cli" | "google-vertex" | "groq" | "helmcode" | "huggingface" | "kagi" | "kilo" | "kimi-code" | "litellm" | "llama.cpp" | "lm-studio" | "local" | "meta" | "minimax" | "minimax-code" | "minimax-code-cn" | "mistral" | "moonshot" | "muse-code" | "nanogpt" | "novita" | "nvidia" | "ollama" | "ollama-cloud" | "openai" | "openai-codex" | "openai-codex-device" | "opencode-go" | "opencode-zen" | "openrouter" | "parallel" | "perplexity" | "qianfan" | "qwen-portal" | "sakana" | "siliconflow" | "siliconflow-cn" | "singularityapi-dev" | "singularityapi-tech" | "snowflake" | "stencil" | "stepfun" | "synthetic" | "tavily" | "together" | "typesafe" | "umans" | "venice" | "vercel-ai-gateway" | "vllm" | "wafer-serverless" | "web" | "xai" | "xai-oauth" | "xiaomi" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-sgp" | "yolo-auto" | "zai" | "zai-coding-plan" | "zenmux" | "zhipu-coding-plan";
|
|
2
|
+
export type AuthProviderId = "abliteration" | "aiand" | "aimlapi" | "alibaba-coding-plan" | "alibaba-token-plan" | "amazon-bedrock" | "anthropic" | "apple" | "azure" | "baseten" | "bedrock-mantle" | "cerebras" | "charm-hyper" | "cline-pass" | "cloudflare-ai-gateway" | "commandcode" | "coralbricks" | "coreweave" | "cursor" | "deepinfra" | "deepseek" | "devin" | "exa" | "factory-droid" | "firepass" | "fireworks" | "github-copilot" | "gitlab-duo" | "gitlab-duo-agent" | "gmi-cloud" | "google" | "google-antigravity" | "google-gemini-cli" | "google-vertex" | "groq" | "helmcode" | "huggingface" | "kagi" | "kilo" | "kimi-code" | "litellm" | "llama.cpp" | "lm-studio" | "local" | "meta" | "minimax" | "minimax-code" | "minimax-code-cn" | "mistral" | "moonshot" | "muse-code" | "nanogpt" | "novita" | "nvidia" | "ollama" | "ollama-cloud" | "openai" | "openai-codex" | "openai-codex-device" | "opencode-go" | "opencode-zen" | "openrouter" | "parallel" | "perplexity" | "qianfan" | "qwen-portal" | "sakana" | "siliconflow" | "siliconflow-cn" | "singularityapi-dev" | "singularityapi-tech" | "snowflake" | "stencil" | "stepfun" | "synthetic" | "tavily" | "together" | "typesafe" | "umans" | "venice" | "vercel-ai-gateway" | "vllm" | "wafer-serverless" | "web" | "xai" | "xai-oauth" | "xiaomi" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-sgp" | "yolo-auto" | "zai" | "zai-coding-plan" | "zenmux" | "zhipu-coding-plan";
|
|
3
3
|
/** Providers whose policy declares a `login` flow (the `/login` roster). */
|
|
4
|
-
export type LoginProviderId = "abliteration" | "aiand" | "alibaba-coding-plan" | "alibaba-token-plan" | "anthropic" | "baseten" | "cerebras" | "charm-hyper" | "cline-pass" | "cloudflare-ai-gateway" | "commandcode" | "coreweave" | "cursor" | "deepinfra" | "deepseek" | "devin" | "exa" | "factory-droid" | "firepass" | "fireworks" | "github-copilot" | "gitlab-duo" | "gitlab-duo-agent" | "gmi-cloud" | "google-antigravity" | "google-gemini-cli" | "helmcode" | "huggingface" | "kagi" | "kilo" | "kimi-code" | "litellm" | "llama.cpp" | "lm-studio" | "meta" | "minimax-code" | "minimax-code-cn" | "moonshot" | "muse-code" | "nanogpt" | "novita" | "nvidia" | "ollama" | "ollama-cloud" | "openai-codex" | "openai-codex-device" | "opencode-go" | "opencode-zen" | "openrouter" | "parallel" | "perplexity" | "qianfan" | "qwen-portal" | "sakana" | "siliconflow" | "siliconflow-cn" | "singularityapi-dev" | "singularityapi-tech" | "snowflake" | "stencil" | "stepfun" | "synthetic" | "tavily" | "together" | "typesafe" | "umans" | "venice" | "vercel-ai-gateway" | "vllm" | "wafer-serverless" | "xai" | "xai-oauth" | "xiaomi" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-sgp" | "yolo-auto" | "zai" | "zai-coding-plan" | "zenmux" | "zhipu-coding-plan";
|
|
4
|
+
export type LoginProviderId = "abliteration" | "aiand" | "alibaba-coding-plan" | "alibaba-token-plan" | "anthropic" | "baseten" | "cerebras" | "charm-hyper" | "cline-pass" | "cloudflare-ai-gateway" | "commandcode" | "coralbricks" | "coreweave" | "cursor" | "deepinfra" | "deepseek" | "devin" | "exa" | "factory-droid" | "firepass" | "fireworks" | "github-copilot" | "gitlab-duo" | "gitlab-duo-agent" | "gmi-cloud" | "google-antigravity" | "google-gemini-cli" | "helmcode" | "huggingface" | "kagi" | "kilo" | "kimi-code" | "litellm" | "llama.cpp" | "lm-studio" | "meta" | "minimax-code" | "minimax-code-cn" | "moonshot" | "muse-code" | "nanogpt" | "novita" | "nvidia" | "ollama" | "ollama-cloud" | "openai-codex" | "openai-codex-device" | "opencode-go" | "opencode-zen" | "openrouter" | "parallel" | "perplexity" | "qianfan" | "qwen-portal" | "sakana" | "siliconflow" | "siliconflow-cn" | "singularityapi-dev" | "singularityapi-tech" | "snowflake" | "stencil" | "stepfun" | "synthetic" | "tavily" | "together" | "typesafe" | "umans" | "venice" | "vercel-ai-gateway" | "vllm" | "wafer-serverless" | "xai" | "xai-oauth" | "xiaomi" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-sgp" | "yolo-auto" | "zai" | "zai-coding-plan" | "zenmux" | "zhipu-coding-plan";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Model } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Block positions the provider's prompt cache checks back from a breakpoint for
|
|
4
|
+
* an earlier request's entry (`prompt-cache-lookback` axis), or `undefined` when
|
|
5
|
+
* the model has no known lookback bound.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolvePromptCacheLookback(model: Model): number | undefined;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Every chat-model provider with a catalog entry (`default-model` in its provider rules). */
|
|
2
|
-
export type KnownProvider = "abliteration" | "aiand" | "aimlapi" | "alibaba-coding-plan" | "alibaba-token-plan" | "amazon-bedrock" | "anthropic" | "apple" | "azure" | "baseten" | "bedrock-mantle" | "cerebras" | "charm-hyper" | "cline-pass" | "cloudflare-ai-gateway" | "commandcode" | "coreweave" | "cursor" | "deepinfra" | "deepseek" | "devin" | "factory-droid" | "firepass" | "fireworks" | "github-copilot" | "gitlab-duo" | "gitlab-duo-agent" | "gmi-cloud" | "google" | "google-antigravity" | "google-gemini-cli" | "google-vertex" | "groq" | "helmcode" | "huggingface" | "kilo" | "kimi-code" | "litellm" | "lm-studio" | "local" | "meta" | "minimax" | "minimax-code" | "minimax-code-cn" | "mistral" | "moonshot" | "muse-code" | "nanogpt" | "novita" | "nvidia" | "ollama" | "ollama-cloud" | "openai" | "openai-codex" | "opencode-go" | "opencode-zen" | "openrouter" | "qianfan" | "qwen-portal" | "sakana" | "siliconflow" | "siliconflow-cn" | "singularityapi-dev" | "singularityapi-tech" | "snowflake" | "stepfun" | "synthetic" | "together" | "typesafe" | "umans" | "venice" | "vercel-ai-gateway" | "vllm" | "wafer-serverless" | "web" | "xai" | "xai-oauth" | "xiaomi" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-sgp" | "yolo-auto" | "zai" | "zenmux" | "zhipu-coding-plan";
|
|
2
|
+
export type KnownProvider = "abliteration" | "aiand" | "aimlapi" | "alibaba-coding-plan" | "alibaba-token-plan" | "amazon-bedrock" | "anthropic" | "apple" | "azure" | "baseten" | "bedrock-mantle" | "cerebras" | "charm-hyper" | "cline-pass" | "cloudflare-ai-gateway" | "commandcode" | "coralbricks" | "coreweave" | "cursor" | "deepinfra" | "deepseek" | "devin" | "factory-droid" | "firepass" | "fireworks" | "github-copilot" | "gitlab-duo" | "gitlab-duo-agent" | "gmi-cloud" | "google" | "google-antigravity" | "google-gemini-cli" | "google-vertex" | "groq" | "helmcode" | "huggingface" | "kilo" | "kimi-code" | "litellm" | "lm-studio" | "local" | "meta" | "minimax" | "minimax-code" | "minimax-code-cn" | "mistral" | "moonshot" | "muse-code" | "nanogpt" | "novita" | "nvidia" | "ollama" | "ollama-cloud" | "openai" | "openai-codex" | "opencode-go" | "opencode-zen" | "openrouter" | "qianfan" | "qwen-portal" | "sakana" | "siliconflow" | "siliconflow-cn" | "singularityapi-dev" | "singularityapi-tech" | "snowflake" | "stepfun" | "synthetic" | "together" | "typesafe" | "umans" | "venice" | "vercel-ai-gateway" | "vllm" | "wafer-serverless" | "web" | "xai" | "xai-oauth" | "xiaomi" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-sgp" | "yolo-auto" | "zai" | "zenmux" | "zhipu-coding-plan";
|
|
@@ -35,6 +35,22 @@ export interface ModelManagerOptions<TApi extends Api = Api, TModelsDevPayload =
|
|
|
35
35
|
cacheTtlMs?: number;
|
|
36
36
|
/** When true, a successful dynamic fetch is the complete provider catalog and prunes static-only models. */
|
|
37
37
|
dynamicModelsAuthoritative?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* When true, a provider's dynamic rows are the deployment's whole truth
|
|
40
|
+
* for input modality: a live text-only row strips the bundled reference's
|
|
41
|
+
* image support instead of OR-merging it back. Declared by providers whose
|
|
42
|
+
* capability flags are authoritative and whose endpoints reject
|
|
43
|
+
* unsupported content (`github-copilot`, `deepinfra`, `coralbricks`).
|
|
44
|
+
*/
|
|
45
|
+
dynamicInputAuthoritative?: boolean;
|
|
46
|
+
/** When true, live reasoning capability replaces the fallback, including an explicit false. */
|
|
47
|
+
dynamicReasoningAuthoritative?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* When true, a live per-million price replaces the fallback even when it is
|
|
50
|
+
* an explicit `0` (a free model or a dropped cache-write charge). Without it,
|
|
51
|
+
* a zero discovery price is treated as unknown and the bundled rate is kept.
|
|
52
|
+
*/
|
|
53
|
+
dynamicCostAuthoritative?: boolean;
|
|
38
54
|
/**
|
|
39
55
|
* When true, a fresh cache never satisfies an online-eligible refresh: the
|
|
40
56
|
* dynamic fetch always runs (an explicit `"offline"` strategy is still
|
|
@@ -154,6 +154,19 @@ export interface DeepinfraModelManagerConfig {
|
|
|
154
154
|
* model availability at runtime is still gated on credentials by the registry.
|
|
155
155
|
*/
|
|
156
156
|
export declare function deepinfraModelManagerOptions(config?: DeepinfraModelManagerConfig): ModelManagerOptions<"openai-completions">;
|
|
157
|
+
export declare const CORALBRICKS_BASE_URL = "https://inference.coralbricks.ai/v1";
|
|
158
|
+
/** CoralBricks OpenAI-compatible discovery configuration. */
|
|
159
|
+
export interface CoralbricksModelManagerConfig {
|
|
160
|
+
apiKey?: string;
|
|
161
|
+
baseUrl?: string;
|
|
162
|
+
fetch?: FetchImpl;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Builds CoralBricks' model-discovery manager. `/v1/models` is key-protected
|
|
166
|
+
* (401 without a bearer key), so a keyless config serves only the bundled
|
|
167
|
+
* reviewed seed rows; with a key, live rows are authoritative over the bundle.
|
|
168
|
+
*/
|
|
169
|
+
export declare function coralbricksModelManagerOptions(config?: CoralbricksModelManagerConfig): ModelManagerOptions<"openai-completions">;
|
|
157
170
|
export interface XaiModelManagerConfig {
|
|
158
171
|
apiKey?: string;
|
|
159
172
|
baseUrl?: string;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -192,6 +192,8 @@ export interface OpenAICompat {
|
|
|
192
192
|
supportsMultipleSystemMessages?: boolean;
|
|
193
193
|
/** Whether the provider supports `reasoning_effort`. Default: auto-detected from URL. */
|
|
194
194
|
supportsReasoningEffort?: boolean;
|
|
195
|
+
/** Do not infer a thinking dial when discovery supplies no explicit thinking configuration. */
|
|
196
|
+
trustExplicitThinkingOnly?: boolean;
|
|
195
197
|
/** Optional mapping from pi-ai reasoning levels to provider/model-specific `reasoning_effort` values. */
|
|
196
198
|
reasoningEffortMap?: Partial<Record<Effort, string>>;
|
|
197
199
|
/** Whether the provider supports `stream_options: { include_usage: true }` for token usage in streaming responses. Default: true. */
|
|
@@ -646,6 +648,8 @@ export interface AnthropicCompat {
|
|
|
646
648
|
* deliberately not used to infer these request-shape capabilities.
|
|
647
649
|
*/
|
|
648
650
|
export interface BedrockCompat {
|
|
651
|
+
/** Explicit disabled-thinking wire form; unset preserves the provider's existing behavior. */
|
|
652
|
+
disabledThinking?: AnthropicCompat["disabledThinking"];
|
|
649
653
|
/** Whether this endpoint accepts no checkpoints, automatic caching, or explicit cachePoint blocks. */
|
|
650
654
|
promptCacheMode?: "none" | "automatic" | "explicit";
|
|
651
655
|
/** Whether this wire may revise already-streamed text (`stream-revision` axis). Unassigned: append-only. */
|
|
@@ -684,6 +688,8 @@ export interface BedrockCompat {
|
|
|
684
688
|
}
|
|
685
689
|
/** Fully-resolved Bedrock Converse prompt-cache capabilities, materialized once by `buildModel`. */
|
|
686
690
|
export interface ResolvedBedrockCompat {
|
|
691
|
+
/** See {@link BedrockCompat.disabledThinking}. */
|
|
692
|
+
disabledThinking?: BedrockCompat["disabledThinking"];
|
|
687
693
|
promptCacheMode: NonNullable<BedrockCompat["promptCacheMode"]>;
|
|
688
694
|
/** See {@link BedrockCompat.streamRevision}. */
|
|
689
695
|
streamRevision?: BedrockCompat["streamRevision"];
|
|
@@ -738,6 +744,7 @@ export interface ResolvedOpenAISharedCompat {
|
|
|
738
744
|
supportsDeveloperRole: boolean;
|
|
739
745
|
supportsStrictMode: boolean;
|
|
740
746
|
supportsReasoningEffort: boolean;
|
|
747
|
+
trustExplicitThinkingOnly?: boolean;
|
|
741
748
|
reasoningEffortMap: Partial<Record<Effort, string>>;
|
|
742
749
|
supportsReasoningParams: boolean;
|
|
743
750
|
supportsSamplingParams: boolean;
|
|
@@ -814,7 +821,7 @@ export interface ResolvedOpenAISharedCompat {
|
|
|
814
821
|
* `buildModel`; request handlers read fields and never detect, resolve, or
|
|
815
822
|
* allocate.
|
|
816
823
|
*/
|
|
817
|
-
export type ResolvedOpenAICompat = ResolvedOpenAISharedCompat & Required<Omit<OpenAICompat, "supportsDeveloperRole" | "supportsReasoningEffort" | "reasoningEffortMap" | "supportsReasoningParams" | "supportsReasoningSummary" | "statefulResponses" | "supportsSamplingParams" | "supportsPenaltyAndStopParams" | "thinkingFormat" | "kimiApiFormat" | "reasoningDisableMode" | "omitReasoningEffort" | "includeEncryptedReasoning" | "filterReasoningHistory" | "disableReasoningOnForcedToolChoice" | "disableReasoningOnToolChoice" | "disableReasoningWithTools" | "supportsToolChoice" | "supportsForcedToolChoice" | "supportsNamedToolChoice" | "reasoningContentField" | "mistralReasoningContentParts" | "requiresReasoningContentForToolCalls" | "requiresReasoningContentForAllAssistantTurns" | "allowsSyntheticReasoningContentForToolCalls" | "syntheticReasoningContentFallback" | "replayReasoningContent" | "qwenPreserveThinking" | "qwenTemplateReasoningEffort" | "requiresThinkingAsText" | "requiresMistralToolIds" | "requiresToolResultName" | "requiresAssistantAfterToolResult" | "requiresAssistantContentForToolCalls" | "stripDeepseekSpecialTokens" | "streamMarkupHealingPattern" | "reasoningDeltasMayBeCumulative" | "emptyLengthFinishIsContextError" | "usesOpenAIToolCallIdLimit" | "promptCacheSessionHeader" | "supportsPromptCacheBreakpoints" | "promptCacheBreakpointTtl" | "openRouterRouting" | "isOpenRouterHost" | "supportsStrictMode" | "supportsLongPromptCacheRetention" | "alwaysSendMaxTokens" | "clampOutputToModelMax" | "wireModelIdMode" | "vercelGatewayRouting" | "extraBody" | "toolStrictMode" | "toolSchemaFlavor" | "streamFirstEventTimeoutMs" | "streamIdleTimeoutMs" | "streamRevision" | "cacheControlFormat" | "thinkingKeep" | "strictResponsesPairing" | "supportsImageDetailOriginal" | "supportsConfigurationUpdate" | "supportsSteering" | "stripImageInput" | "thinkingLoopGuard" | "whenThinking">> & {
|
|
824
|
+
export type ResolvedOpenAICompat = ResolvedOpenAISharedCompat & Required<Omit<OpenAICompat, "supportsDeveloperRole" | "supportsReasoningEffort" | "trustExplicitThinkingOnly" | "reasoningEffortMap" | "supportsReasoningParams" | "supportsReasoningSummary" | "statefulResponses" | "supportsSamplingParams" | "supportsPenaltyAndStopParams" | "thinkingFormat" | "kimiApiFormat" | "reasoningDisableMode" | "omitReasoningEffort" | "includeEncryptedReasoning" | "filterReasoningHistory" | "disableReasoningOnForcedToolChoice" | "disableReasoningOnToolChoice" | "disableReasoningWithTools" | "supportsToolChoice" | "supportsForcedToolChoice" | "supportsNamedToolChoice" | "reasoningContentField" | "mistralReasoningContentParts" | "requiresReasoningContentForToolCalls" | "requiresReasoningContentForAllAssistantTurns" | "allowsSyntheticReasoningContentForToolCalls" | "syntheticReasoningContentFallback" | "replayReasoningContent" | "qwenPreserveThinking" | "qwenTemplateReasoningEffort" | "requiresThinkingAsText" | "requiresMistralToolIds" | "requiresToolResultName" | "requiresAssistantAfterToolResult" | "requiresAssistantContentForToolCalls" | "stripDeepseekSpecialTokens" | "streamMarkupHealingPattern" | "reasoningDeltasMayBeCumulative" | "emptyLengthFinishIsContextError" | "usesOpenAIToolCallIdLimit" | "promptCacheSessionHeader" | "supportsPromptCacheBreakpoints" | "promptCacheBreakpointTtl" | "openRouterRouting" | "isOpenRouterHost" | "supportsStrictMode" | "supportsLongPromptCacheRetention" | "alwaysSendMaxTokens" | "clampOutputToModelMax" | "wireModelIdMode" | "vercelGatewayRouting" | "extraBody" | "toolStrictMode" | "toolSchemaFlavor" | "streamFirstEventTimeoutMs" | "streamIdleTimeoutMs" | "streamRevision" | "cacheControlFormat" | "thinkingKeep" | "strictResponsesPairing" | "supportsImageDetailOriginal" | "supportsConfigurationUpdate" | "supportsSteering" | "stripImageInput" | "thinkingLoopGuard" | "whenThinking">> & {
|
|
818
825
|
vercelGatewayRouting?: OpenAICompat["vercelGatewayRouting"];
|
|
819
826
|
extraBody?: OpenAICompat["extraBody"];
|
|
820
827
|
cacheControlFormat?: OpenAICompat["cacheControlFormat"];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oh-my-pi/pi-catalog",
|
|
3
|
-
"version": "18.8.
|
|
3
|
+
"version": "18.8.7",
|
|
4
4
|
"description": "Model catalog for omp: bundled model database, provider discovery descriptors, model identity, classification, and equivalence",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -93,12 +93,12 @@
|
|
|
93
93
|
"gen:proto": "bun scripts/generate-protocols.ts"
|
|
94
94
|
},
|
|
95
95
|
"dependencies": {
|
|
96
|
-
"@oh-my-pi/omptype": "18.8.
|
|
97
|
-
"@oh-my-pi/pi-utils": "18.8.
|
|
96
|
+
"@oh-my-pi/omptype": "18.8.7",
|
|
97
|
+
"@oh-my-pi/pi-utils": "18.8.7"
|
|
98
98
|
},
|
|
99
99
|
"devDependencies": {
|
|
100
100
|
"@bgotink/kdl": "0.4.0",
|
|
101
|
-
"@oh-my-pi/pi-ai": "18.8.
|
|
101
|
+
"@oh-my-pi/pi-ai": "18.8.7",
|
|
102
102
|
"@types/bun": "^1.3.14"
|
|
103
103
|
},
|
|
104
104
|
"engines": {
|
package/src/compat/auth-ids.ts
CHANGED
|
@@ -18,6 +18,7 @@ export type AuthProviderId =
|
|
|
18
18
|
| "cline-pass"
|
|
19
19
|
| "cloudflare-ai-gateway"
|
|
20
20
|
| "commandcode"
|
|
21
|
+
| "coralbricks"
|
|
21
22
|
| "coreweave"
|
|
22
23
|
| "cursor"
|
|
23
24
|
| "deepinfra"
|
|
@@ -110,6 +111,7 @@ export type LoginProviderId =
|
|
|
110
111
|
| "cline-pass"
|
|
111
112
|
| "cloudflare-ai-gateway"
|
|
112
113
|
| "commandcode"
|
|
114
|
+
| "coralbricks"
|
|
113
115
|
| "coreweave"
|
|
114
116
|
| "cursor"
|
|
115
117
|
| "deepinfra"
|
package/src/compat/axes.ts
CHANGED
|
@@ -229,7 +229,7 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
|
|
|
229
229
|
"allow-anthropic-header-overrides": wire("allowAnthropicHeaderOverrides", ["anthropic"]),
|
|
230
230
|
"disable-adaptive-thinking": wire("disableAdaptiveThinking", ["anthropic"]),
|
|
231
231
|
"disable-strict-tools": wire("disableStrictTools", ["anthropic"]),
|
|
232
|
-
"disabled-thinking": wire("disabledThinking", ["anthropic"], "scalar", ["omit", "disabled", "adaptive"]),
|
|
232
|
+
"disabled-thinking": wire("disabledThinking", ["anthropic", "bedrock"], "scalar", ["omit", "disabled", "adaptive"]),
|
|
233
233
|
"effort-beta": wire("effortBeta", ["anthropic"]),
|
|
234
234
|
"escape-builtin-tool-names": wire("escapeBuiltinToolNames", ["anthropic"]),
|
|
235
235
|
"fast-mode": wire("fastMode", ["anthropic"]),
|
|
@@ -261,7 +261,7 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
|
|
|
261
261
|
// ── wire: devin-agent ──
|
|
262
262
|
"model-router": wire("modelRouter", ["devin"]),
|
|
263
263
|
"supports-parallel-tool-calls": wire("supportsParallelToolCalls", ["devin"]),
|
|
264
|
-
"trust-explicit-thinking-only": wire("trustExplicitThinkingOnly", ["devin"]),
|
|
264
|
+
"trust-explicit-thinking-only": wire("trustExplicitThinkingOnly", [...OAI, "devin"]),
|
|
265
265
|
|
|
266
266
|
// ── wire: google APIs ──
|
|
267
267
|
"antigravity-claude-tool-mode": wire("antigravityClaudeToolMode", ["google"]),
|
|
@@ -399,6 +399,12 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
|
|
|
399
399
|
"limits-patch": { key: "limitsPatch", set: "catalog", shape: "object" },
|
|
400
400
|
"long-context-cost": { key: "longContext", set: "catalog", shape: "object" },
|
|
401
401
|
"prompt-cache": { key: "promptCache", set: "catalog", shape: "object" },
|
|
402
|
+
/**
|
|
403
|
+
* Prompt-cache lookback in block positions: how far back from a cache
|
|
404
|
+
* breakpoint the provider looks for an earlier request's cache entry.
|
|
405
|
+
* Unassigned: no known lookback bound.
|
|
406
|
+
*/
|
|
407
|
+
"prompt-cache-lookback": { key: "promptCacheLookback", set: "catalog", shape: "scalar" },
|
|
402
408
|
"long-usage-limit-fallback": { key: "longUsageLimitFallback", set: "catalog", shape: "scalar" },
|
|
403
409
|
"max-context-window": { key: "maxContextWindow", set: "catalog", shape: "scalar" },
|
|
404
410
|
"pricing-status": {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { toModelSpec } from "../provider-models/bundled-references";
|
|
2
|
+
import type { Model } from "../types";
|
|
3
|
+
import { resolveCatalogAxes } from "./resolve";
|
|
4
|
+
|
|
5
|
+
const lookbackCache = new Map<string, number | null>();
|
|
6
|
+
const LOOKBACK_CACHE_MAX = 8192;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Block positions the provider's prompt cache checks back from a breakpoint for
|
|
10
|
+
* an earlier request's entry (`prompt-cache-lookback` axis), or `undefined` when
|
|
11
|
+
* the model has no known lookback bound.
|
|
12
|
+
*/
|
|
13
|
+
export function resolvePromptCacheLookback(model: Model): number | undefined {
|
|
14
|
+
const key = `${model.provider} ${model.id} ${model.api}`;
|
|
15
|
+
let lookback = lookbackCache.get(key);
|
|
16
|
+
if (lookback === undefined) {
|
|
17
|
+
const value = resolveCatalogAxes(toModelSpec(model)).promptCacheLookback;
|
|
18
|
+
lookback = typeof value === "number" && Number.isInteger(value) && value > 0 ? value : null;
|
|
19
|
+
if (lookbackCache.size >= LOOKBACK_CACHE_MAX) lookbackCache.clear();
|
|
20
|
+
lookbackCache.set(key, lookback);
|
|
21
|
+
}
|
|
22
|
+
return lookback ?? undefined;
|
|
23
|
+
}
|
package/src/compat/resolve.ts
CHANGED
|
@@ -503,6 +503,7 @@ function detectOpenAICompat(
|
|
|
503
503
|
supportsDeveloperRole: isOpenAIHost || isAzureHost,
|
|
504
504
|
supportsMultipleSystemMessages: supportsMultipleSystemMessagesDefault,
|
|
505
505
|
supportsReasoningEffort: !isGrok && !d.isXiaomiMimo && (!(d.isZai || d.isZhipu) || supportsZaiReasoningEffort),
|
|
506
|
+
trustExplicitThinkingOnly: undefined,
|
|
506
507
|
// API-conditional: this completions-only Copilot exclusion cannot be a
|
|
507
508
|
// provider rule without changing Copilot Responses rows.
|
|
508
509
|
supportsReasoningParams: provider !== "github-copilot",
|
|
@@ -732,6 +733,7 @@ function resolveOpenAIResponsesPolicy(
|
|
|
732
733
|
hostMatchesUrl(baseUrl, "openrouter") ||
|
|
733
734
|
hostMatchesUrl(baseUrl, "deepseekFamily"),
|
|
734
735
|
supportsReasoningEffort: !isXaiHost,
|
|
736
|
+
trustExplicitThinkingOnly: undefined,
|
|
735
737
|
supportsLongPromptCacheRetention: isOpenAIUrl,
|
|
736
738
|
supportsPromptCacheBreakpoints,
|
|
737
739
|
promptCacheBreakpointTtl: supportsPromptCacheBreakpoints ? "30m" : undefined,
|
|
@@ -219,6 +219,8 @@ One object axis carries a computed form: `long-context-cost` accepts either the
|
|
|
219
219
|
|
|
220
220
|
`inline-image-byte-budget` caps retained base64 image characters for a deployment's request body. It leaves room for tool schemas and text beneath the provider's body-size limit; the coding agent reads it through `resolveInlineImageByteBudget` before sending live history. The budget applies only while `compat.officialEndpoint` holds: a custom `baseUrl` imposes its own body limit.
|
|
221
221
|
|
|
222
|
+
`prompt-cache-lookback` is how many block positions back from a cache breakpoint the model's prompt cache looks for an earlier request's entry (Claude: 20, counting the breakpoint; a run of consecutive `tool_use` or `tool_result` blocks is one position). The coding agent reads it through `resolvePromptCacheLookback` and keeps warm-cache tool-result pruning inside the window; unassigned means no known bound.
|
|
223
|
+
|
|
222
224
|
The routed-subscription registry axes (`upstream-rotation`, `region-upstreams-global|us|eu`, `region-limits-eu`, `credit-rates`, `list-price-from`, `routing-family`, `policy-aliases`, `entitlement`, `default-reasoning-off`) describe a gateway whose proxy fans one model out to several upstreams. They are read through `src/compat/factory-droid.ts` by Factory Droid discovery and its request provider, not materialized by `buildModel`. A provider-wide `region-upstreams-*` rule is the upstream serving table and a model rule replaces it for that region. `list-price-from "<provider>" ["<id>"]` shows a bundled row's list price beside the subscription's own billing; unlike seed values it is resolved at runtime and degrades to the seed's zero cost when the row is gone. See [`providers/factory-droid.kdl`](providers/factory-droid.kdl), whose wire and billing pool per model are `api-routes` and `quota-tiers` rules in `runtime/behavior.kdl`.
|
|
223
225
|
|
|
224
226
|
### Time-based pricing
|
|
@@ -10,4 +10,4 @@ login-order "openai-codex" "anthropic" "zai" "zai-coding-plan" "kimi-code" "open
|
|
|
10
10
|
"qianfan" "venice" "siliconflow" "siliconflow-cn" "synthetic" "nanogpt" "wafer-serverless" "coreweave" \
|
|
11
11
|
"vercel-ai-gateway" "cloudflare-ai-gateway" "snowflake" "litellm" "kilo" "zenmux" "opencode-zen" "opencode-go" \
|
|
12
12
|
"yolo-auto" "tavily" "kagi" "exa" "parallel" "typesafe" "ollama" "ollama-cloud" "lm-studio" "llama.cpp" "vllm" \
|
|
13
|
-
"gmi-cloud" "stencil" "singularityapi-dev" "singularityapi-tech"
|
|
13
|
+
"gmi-cloud" "stencil" "singularityapi-dev" "singularityapi-tech" "coralbricks"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// `/v1/models` is key-protected — it answers `401 missing_api_key` without a
|
|
2
|
+
// bearer key and `401 invalid_api_key` to a rejected one (verified
|
|
3
|
+
// 2026-10-02) — so login validates the pasted key there. The probe bills
|
|
4
|
+
// nothing, unlike a chat-completions ping against a prepaid balance.
|
|
5
|
+
auth "coralbricks" {
|
|
6
|
+
name "CoralBricks"
|
|
7
|
+
login "api-key" {
|
|
8
|
+
auth-url "https://www.coralbricks.ai/api-keys"
|
|
9
|
+
instructions "Create or copy your API key from the CoralBricks dashboard (keys look like cb_...)"
|
|
10
|
+
prompt "Paste your CoralBricks API key" placeholder="cb_..."
|
|
11
|
+
validate "models-endpoint" label="CoralBricks" url="https://inference.coralbricks.ai/v1/models"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -9,7 +9,13 @@
|
|
|
9
9
|
// are never undercounted; only Opus/Sonnet/Haiku revisions known to predate
|
|
10
10
|
// 4.7 take the standard tier. Separator-collapsed revisions parse as two
|
|
11
11
|
// digits (`claude-opus-45` is Opus 4.5 → 45), so 10–46 is standard too.
|
|
12
|
+
// Claude's prompt cache finds an earlier request's entry only within 20 block
|
|
13
|
+
// positions back from a breakpoint, counting the breakpoint; a run of
|
|
14
|
+
// consecutive tool_use or tool_result blocks is one position. Warm-cache
|
|
15
|
+
// tool-result pruning keeps its rewrites inside this window.
|
|
16
|
+
// https://platform.claude.com/docs/en/build-with-claude/prompt-caching
|
|
12
17
|
class "anthropic" {
|
|
18
|
+
prompt-cache-lookback 20
|
|
13
19
|
image-tokenization {
|
|
14
20
|
regime "anthropic-patch"
|
|
15
21
|
max-edge 2576
|
|
@@ -302,8 +308,12 @@ class "anthropic" {
|
|
|
302
308
|
family "haiku" {
|
|
303
309
|
thinking-mode "budget"
|
|
304
310
|
// Haiku 5.5 is the first adaptive Haiku: `budget_tokens` is a 400.
|
|
311
|
+
// An omitted `thinking` is adaptive, but unlike Sonnet/Opus 5.5 it
|
|
312
|
+
// accepts `disabled` at effort `high` or below, so Off is explicit.
|
|
313
|
+
// https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5#use-effort-to-control-thinking
|
|
305
314
|
revision ">=5.5 <6" {
|
|
306
315
|
thinking-mode "anthropic-adaptive"
|
|
316
|
+
disabled-thinking "disabled"
|
|
307
317
|
}
|
|
308
318
|
}
|
|
309
319
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// CoralBricks inference gateway deployment contract
|
|
2
|
+
// (https://www.coralbricks.ai/docs.md; catalog snapshot 2026-10-08).
|
|
3
|
+
//
|
|
4
|
+
// Coral serves open-weight models behind an OpenAI-compatible wire at
|
|
5
|
+
// https://inference.coralbricks.ai/v1 with a single bearer API key. The
|
|
6
|
+
// key-protected `GET /v1/models` publishes each row's context window,
|
|
7
|
+
// per-million pricing, and capability flags, and Coral documents those
|
|
8
|
+
// flags as authoritative (unsupported content answers
|
|
9
|
+
// `400 unsupported_content_type` rather than being dropped), so live
|
|
10
|
+
// discovery is the deployment truth and same-id rows on other hosts must
|
|
11
|
+
// not backfill capabilities or limits into this provider's rows.
|
|
12
|
+
provider "coralbricks" {
|
|
13
|
+
default-model "glm-5.3-fast"
|
|
14
|
+
// Official docs authenticate via `CORAL_API_KEY`
|
|
15
|
+
// (https://www.coralbricks.ai/docs.md#authentication); `CORALBRICKS_API_KEY`
|
|
16
|
+
// is the alias the Coral pi provider extension shipped with, kept as a
|
|
17
|
+
// compatibility fallback in precedence order.
|
|
18
|
+
env "CORAL_API_KEY" "CORALBRICKS_API_KEY"
|
|
19
|
+
dynamic-models-authoritative #true
|
|
20
|
+
skip-cross-provider-reference-fills #true
|
|
21
|
+
discovery label="CoralBricks"
|
|
22
|
+
|
|
23
|
+
// Reviewed snapshot of the public catalog
|
|
24
|
+
// (https://www.coralbricks.ai/api/public/models). Coral retired GLM 5.3
|
|
25
|
+
// Flash on 2026-10-07 and renamed the remaining slugs (`glm-5.3-fast`,
|
|
26
|
+
// `deepseek-v4.1-flash-fast`). The public rows list input/output rates
|
|
27
|
+
// only; cache-write rates come from Coral's published pricing and cached
|
|
28
|
+
// reads are $0 on every model. `/v1/models` needs a key, so generation
|
|
29
|
+
// without credentials bundles these rows; successful runtime discovery
|
|
30
|
+
// replaces them.
|
|
31
|
+
seed api="openai-completions" base-url="https://inference.coralbricks.ai/v1" bundle="always" {
|
|
32
|
+
model "glm-5.3-fast" name="GLM 5.3" {
|
|
33
|
+
reasoning #true
|
|
34
|
+
input "text"
|
|
35
|
+
cost input=1.12 output=4.4 cache-read=0 cache-write=1.68
|
|
36
|
+
limits context=1048576 max-tokens=131072
|
|
37
|
+
}
|
|
38
|
+
model "deepseek-v4.1-flash-fast" name="DeepSeek V4.1 Flash" {
|
|
39
|
+
reasoning #true
|
|
40
|
+
input "text" "image"
|
|
41
|
+
cost input=0.3 output=1.2 cache-read=0 cache-write=0.09
|
|
42
|
+
limits context=1048576 max-tokens=131072
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// DeepSeek V4.1 Flash is the one CoralBricks SKU that advertises a genuine
|
|
47
|
+
// off value (`none` in its reasoning-effort vocabulary, per the reasoning
|
|
48
|
+
// table at https://www.coralbricks.ai/docs.md#reasoning), so a
|
|
49
|
+
// thinking-off request disables reasoning instead of clamping to the
|
|
50
|
+
// lowest effort like the GLM SKUs.
|
|
51
|
+
models "deepseek-v4.1-flash-fast" {
|
|
52
|
+
reasoning-disable-mode "none-effort"
|
|
53
|
+
}
|
|
54
|
+
// Gateway request dialect, matching Coral's plain Chat Completions
|
|
55
|
+
// surface ("unchanged from what your existing SDK expects"): output caps
|
|
56
|
+
// ride `max_tokens`, system prompts ride the `system` role, and no
|
|
57
|
+
// `store` field is sent. Coral accepts unknown fields, so acceptance is
|
|
58
|
+
// not evidence the semantics are honored (same call as charm-hyper).
|
|
59
|
+
supports-developer-role #false
|
|
60
|
+
supports-store #false
|
|
61
|
+
max-tokens-field "max_tokens"
|
|
62
|
+
}
|