@oh-my-pi/pi-catalog 18.8.9 → 18.9.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 +9 -0
- package/dist/types/compat/reasoning-carry.d.ts +21 -0
- package/dist/types/provider-models/openai-compat.d.ts +5 -0
- package/dist/types/types.d.ts +51 -11
- package/dist/types/wire/factory-droid.d.ts +1 -1
- package/package.json +4 -4
- package/src/compat/axes.ts +22 -1
- package/src/compat/reasoning-carry.ts +64 -0
- package/src/compat/resolve.ts +5 -0
- package/src/compat/rules/classes/deepseek.kdl +6 -0
- package/src/compat/rules/classes/glm.kdl +16 -7
- package/src/compat/rules/classes/kimi.kdl +8 -0
- package/src/compat/rules/classes/minimax.kdl +10 -0
- package/src/compat/rules/classes/openai.kdl +5 -3
- package/src/compat/rules/providers/abliteration.kdl +7 -0
- package/src/compat/rules/providers/cursor.kdl +4 -0
- package/src/compat/rules/providers/factory-droid.kdl +77 -13
- package/src/compat/rules/providers/litellm.kdl +4 -1
- package/src/compat/rules/providers/mistral.kdl +5 -1
- package/src/compat/rules/providers/openai-codex.kdl +12 -10
- package/src/compat/rules/providers/openai.kdl +4 -2
- package/src/compat/rules/providers/opencode-zen.kdl +20 -0
- package/src/compat/rules/providers/openrouter.kdl +6 -0
- package/src/compat/rules/providers/zhipu-coding-plan.kdl +10 -0
- package/src/compat/rules/runtime/behavior.kdl +5 -4
- package/src/compat/rules.json +1 -1
- package/src/models.json +1 -1
- package/src/provider-models/openai-compat.ts +11 -5
- package/src/types.ts +53 -9
- package/src/wire/factory-droid.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [18.9.0] - 2026-10-11
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Fixed GLM-5.3-FlashX on Zhipu Coding Plan so bundled context, image, and reasoning-level capabilities are reported correctly.
|
|
10
|
+
- Fixed OpenRouter Decisions endpoint derivation when the chat base URL has a trailing slash.
|
|
11
|
+
- Fixed GPT-6.1 Sol Ultrafast usage pricing to apply OpenAI's published premium rates for the OpenAI API and Codex included usage.
|
|
12
|
+
- Fixed GPT-6 Sol, GPT-6.1 Sol, and GPT-6 Luna so changing reasoning effort preserves prompt caching.
|
|
13
|
+
|
|
5
14
|
## [18.8.8] - 2026-10-10
|
|
6
15
|
|
|
7
16
|
### Added
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ModelIdentity } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* The identity a deployment's reasoning is carried under, or `undefined` when
|
|
4
|
+
* the deployment's model family is not declared portable there. Class-only
|
|
5
|
+
* identities never qualify: they name a lineage, not a set of weights.
|
|
6
|
+
*/
|
|
7
|
+
export declare function portableReasoningIdentity(provider: string, api: string, modelId: string): ModelIdentity | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Whether reasoning recorded on `source` may replay natively on `target`:
|
|
10
|
+
* both deployments declare the family portable and classify to the same
|
|
11
|
+
* class, family, and revision.
|
|
12
|
+
*/
|
|
13
|
+
export declare function carriesReasoning(source: {
|
|
14
|
+
provider: string;
|
|
15
|
+
api: string;
|
|
16
|
+
model: string;
|
|
17
|
+
}, target: {
|
|
18
|
+
provider: string;
|
|
19
|
+
api: string;
|
|
20
|
+
id: string;
|
|
21
|
+
}): boolean;
|
|
@@ -352,6 +352,11 @@ export interface OpenRouterModelManagerConfig {
|
|
|
352
352
|
baseUrl?: string;
|
|
353
353
|
fetch?: FetchImpl;
|
|
354
354
|
}
|
|
355
|
+
/**
|
|
356
|
+
* OpenRouter's Decisions API lives at `/api/alpha`, a sibling of the `/api/v1`
|
|
357
|
+
* chat root; derive it so a custom gateway base URL keeps both aligned.
|
|
358
|
+
*/
|
|
359
|
+
export declare function openrouterDecisionsBaseUrl(chatBaseUrl: string): string;
|
|
355
360
|
export declare function openrouterModelManagerOptions(config?: OpenRouterModelManagerConfig): ModelManagerOptions<Api>;
|
|
356
361
|
export interface ZenMuxModelManagerConfig {
|
|
357
362
|
apiKey?: string;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -340,6 +340,8 @@ export interface OpenAICompat {
|
|
|
340
340
|
extraBody?: Record<string, unknown>;
|
|
341
341
|
/** Request-session header that should mirror the normalized prompt-cache key. Default: unset. */
|
|
342
342
|
promptCacheSessionHeader?: "x-grok-conv-id";
|
|
343
|
+
/** Request header carrying the conversation session id, independent of prompt caching. Default: unset. */
|
|
344
|
+
sessionHeader?: "x-litellm-session-id";
|
|
343
345
|
/** Whether chat-completions payloads should include provider-specific prompt-cache markers. */
|
|
344
346
|
cacheControlFormat?: "anthropic" | undefined;
|
|
345
347
|
/**
|
|
@@ -423,8 +425,8 @@ export interface OpenAICompat {
|
|
|
423
425
|
/**
|
|
424
426
|
* Whether the Responses endpoint accepts `configuration_update` input items
|
|
425
427
|
* that change `reasoning.effort` mid-conversation while the request-level
|
|
426
|
-
* effort stays pinned for prompt caching (GPT-6
|
|
427
|
-
* rule-detected (`true` for
|
|
428
|
+
* effort stays pinned for prompt caching (GPT-6 family). Default:
|
|
429
|
+
* rule-detected (`true` for GPT-6 models on any host, `false` otherwise).
|
|
428
430
|
* Set `false` for custom `openai-responses` / `openai-codex-responses`
|
|
429
431
|
* endpoints that reject the item type with HTTP 400; effort changes are then
|
|
430
432
|
* sent as the top-level `reasoning.effort`.
|
|
@@ -621,12 +623,31 @@ export interface AnthropicCompat {
|
|
|
621
623
|
injectClaudeCodeInstruction?: boolean;
|
|
622
624
|
/** Strip image inputs before encoding (text-only serving of a multimodal id). */
|
|
623
625
|
stripImageInput?: boolean;
|
|
626
|
+
/**
|
|
627
|
+
* Largest width or height a single image block may carry. The canonical
|
|
628
|
+
* Anthropic API rejects anything larger with `At least one of the image
|
|
629
|
+
* dimensions exceed max allowed size: 8000 pixels`, and the rejection
|
|
630
|
+
* poisons every retry and model fallback because the block stays in
|
|
631
|
+
* context, so the request builder downscales to this value first. Hosts
|
|
632
|
+
* with a different image contract override it. Default: 8000.
|
|
633
|
+
*/
|
|
634
|
+
maxImageDimension?: number;
|
|
635
|
+
/**
|
|
636
|
+
* Largest base64 payload a single image block may carry, in bytes. The
|
|
637
|
+
* canonical Anthropic API measures the encoded string, not the decoded
|
|
638
|
+
* bytes (`image exceeds 10 MB maximum: 14012300 bytes > 10485760 bytes`),
|
|
639
|
+
* and an image inside {@link maxImageDimension} can still cross it, so
|
|
640
|
+
* payload size is clamped on its own. Hosts with a different image
|
|
641
|
+
* contract override it. Default: 10485760.
|
|
642
|
+
*/
|
|
643
|
+
maxImagePayloadBytes?: number;
|
|
624
644
|
/** Thinking-loop watchdog guard family applied to streamed reasoning. */
|
|
625
645
|
thinkingLoopGuard?: "gemini" | "deepseek" | "xai";
|
|
626
646
|
/**
|
|
627
647
|
* Drop the enabled `thinking` config and replayed thinking blocks when the
|
|
628
648
|
* conversation is not thinking-led (a proxy contract for non-interleaved
|
|
629
|
-
* budget models)
|
|
649
|
+
* budget models), and replay history without thinking blocks on every turn
|
|
650
|
+
* that sends `thinking: { type: "disabled" }`. Default: false.
|
|
630
651
|
*/
|
|
631
652
|
stripThinkingHistory?: boolean;
|
|
632
653
|
/**
|
|
@@ -636,10 +657,15 @@ export interface AnthropicCompat {
|
|
|
636
657
|
effortBeta?: boolean;
|
|
637
658
|
/**
|
|
638
659
|
* Wire form of a disabled-thinking turn: omit the field, send
|
|
639
|
-
* `{ type: "disabled" }`,
|
|
640
|
-
* direct-provider behavior.
|
|
660
|
+
* `{ type: "disabled" }`, keep adaptive thinking, or send
|
|
661
|
+
* `{ type: "between_tools" }`. Unset keeps the direct-provider behavior.
|
|
662
|
+
*/
|
|
663
|
+
disabledThinking?: "omit" | "disabled" | "adaptive" | "between-tools";
|
|
664
|
+
/**
|
|
665
|
+
* `output_config.effort` pinned on a `between_tools` turn. Unset leaves
|
|
666
|
+
* the turn's effort untouched.
|
|
641
667
|
*/
|
|
642
|
-
|
|
668
|
+
betweenToolsEffort?: "low" | "medium" | "high";
|
|
643
669
|
/** The model is a fast-mode SKU: send `speed: "fast"` with the fast-mode beta. Default: false. */
|
|
644
670
|
fastMode?: boolean;
|
|
645
671
|
}
|
|
@@ -787,6 +813,7 @@ export interface ResolvedOpenAISharedCompat {
|
|
|
787
813
|
emptyLengthFinishIsContextError: boolean;
|
|
788
814
|
usesOpenAIToolCallIdLimit: boolean;
|
|
789
815
|
promptCacheSessionHeader?: OpenAICompat["promptCacheSessionHeader"];
|
|
816
|
+
sessionHeader?: OpenAICompat["sessionHeader"];
|
|
790
817
|
/**
|
|
791
818
|
* Whether this model accepts explicit OpenAI prompt-cache breakpoints.
|
|
792
819
|
* Built catalog models always materialize this false-by-default value;
|
|
@@ -821,7 +848,7 @@ export interface ResolvedOpenAISharedCompat {
|
|
|
821
848
|
* `buildModel`; request handlers read fields and never detect, resolve, or
|
|
822
849
|
* allocate.
|
|
823
850
|
*/
|
|
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">> & {
|
|
851
|
+
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" | "sessionHeader" | "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">> & {
|
|
825
852
|
vercelGatewayRouting?: OpenAICompat["vercelGatewayRouting"];
|
|
826
853
|
extraBody?: OpenAICompat["extraBody"];
|
|
827
854
|
cacheControlFormat?: OpenAICompat["cacheControlFormat"];
|
|
@@ -851,8 +878,8 @@ export interface ResolvedOpenAIResponsesCompat extends ResolvedOpenAISharedCompa
|
|
|
851
878
|
/**
|
|
852
879
|
* Whether a `configuration_update` input item may change `reasoning.effort`
|
|
853
880
|
* mid-conversation while the request-level effort stays byte-stable for
|
|
854
|
-
* prompt caching. Rule-owned: GPT-6
|
|
855
|
-
* the item type
|
|
881
|
+
* prompt caching. Rule-owned: the GPT-6 family; earlier models do not
|
|
882
|
+
* support the item type.
|
|
856
883
|
*/
|
|
857
884
|
supportsConfigurationUpdate: boolean;
|
|
858
885
|
/**
|
|
@@ -908,15 +935,28 @@ export interface ResolvedOpenAIResponsesCompat extends ResolvedOpenAISharedCompa
|
|
|
908
935
|
*/
|
|
909
936
|
export type ResolvedOpenRouterCompat = ResolvedOpenAICompat & ResolvedOpenAIResponsesCompat;
|
|
910
937
|
/** Fully-resolved anthropic-messages compat view (same contract as `ResolvedOpenAICompat`). */
|
|
911
|
-
export type ResolvedAnthropicCompat = Required<Omit<AnthropicCompat, "streamIdleTimeoutMs" | "thinkingLoopGuard" | "bedrockMessagesApi" | "effortBeta" | "disabledThinking" | "stripThinkingHistory" | "fastMode">> & {
|
|
938
|
+
export type ResolvedAnthropicCompat = Required<Omit<AnthropicCompat, "streamIdleTimeoutMs" | "thinkingLoopGuard" | "bedrockMessagesApi" | "effortBeta" | "disabledThinking" | "betweenToolsEffort" | "stripThinkingHistory" | "fastMode" | "maxImageDimension" | "maxImagePayloadBytes">> & {
|
|
912
939
|
/** Effort-beta override; undefined keeps the transport's legacy heuristic. */
|
|
913
940
|
effortBeta?: AnthropicCompat["effortBeta"];
|
|
914
941
|
/** Disabled-thinking wire form; undefined keeps the direct-provider behavior. */
|
|
915
942
|
disabledThinking?: AnthropicCompat["disabledThinking"];
|
|
916
|
-
/**
|
|
943
|
+
/** Effort pinned on `between_tools` turns; undefined leaves effort untouched. */
|
|
944
|
+
betweenToolsEffort?: AnthropicCompat["betweenToolsEffort"];
|
|
945
|
+
/** Strip thinking history on non-thinking-led and disabled-thinking turns; undefined behaves as false. */
|
|
917
946
|
stripThinkingHistory?: AnthropicCompat["stripThinkingHistory"];
|
|
918
947
|
/** Fast-mode SKU; undefined behaves as false. */
|
|
919
948
|
fastMode?: AnthropicCompat["fastMode"];
|
|
949
|
+
/**
|
|
950
|
+
* Largest width or height a single image block may carry. Undefined defers
|
|
951
|
+
* to the canonical Anthropic API limit applied by the request builder.
|
|
952
|
+
*/
|
|
953
|
+
maxImageDimension?: number;
|
|
954
|
+
/**
|
|
955
|
+
* Largest base64 image payload a single block may carry, in bytes.
|
|
956
|
+
* Undefined defers to the canonical Anthropic API limit applied by the
|
|
957
|
+
* request builder.
|
|
958
|
+
*/
|
|
959
|
+
maxImagePayloadBytes?: number;
|
|
920
960
|
/** Thinking-loop watchdog guard family applied to streamed reasoning. */
|
|
921
961
|
thinkingLoopGuard?: AnthropicCompat["thinkingLoopGuard"];
|
|
922
962
|
/**
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* native request corpus with `packages/ai/scripts/capture-factory-droid-native.ts`
|
|
4
4
|
* against the matching CLI binary and make `factory-droid-native-parity.test.ts` pass.
|
|
5
5
|
*/
|
|
6
|
-
export declare const FACTORY_DROID_CLIENT_VERSION = "0.
|
|
6
|
+
export declare const FACTORY_DROID_CLIENT_VERSION = "0.237.0";
|
|
7
7
|
/** Wire protocols the Factory proxy multiplexes; `api-routes provider="factory-droid"` picks one per model. */
|
|
8
8
|
export declare const FACTORY_DROID_WIRES: readonly ["openai-completions", "openai-responses", "anthropic-messages", "google-generate"];
|
|
9
9
|
/** Wire protocol used by the Factory proxy for each model. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oh-my-pi/pi-catalog",
|
|
3
|
-
"version": "18.
|
|
3
|
+
"version": "18.9.0",
|
|
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.
|
|
97
|
-
"@oh-my-pi/pi-utils": "18.
|
|
96
|
+
"@oh-my-pi/omptype": "18.9.0",
|
|
97
|
+
"@oh-my-pi/pi-utils": "18.9.0"
|
|
98
98
|
},
|
|
99
99
|
"devDependencies": {
|
|
100
100
|
"@bgotink/kdl": "0.4.0",
|
|
101
|
-
"@oh-my-pi/pi-ai": "18.
|
|
101
|
+
"@oh-my-pi/pi-ai": "18.9.0",
|
|
102
102
|
"@types/bun": "^1.3.14"
|
|
103
103
|
},
|
|
104
104
|
"engines": {
|
package/src/compat/axes.ts
CHANGED
|
@@ -140,6 +140,7 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
|
|
|
140
140
|
"qwen-preserve-thinking": wire("qwenPreserveThinking", ["openai"]),
|
|
141
141
|
"reject-root-object-union": wire("rejectRootObjectUnion", OAI),
|
|
142
142
|
"retry-without-strict-on-grammar-error": wire("retryWithoutStrictOnGrammarError", OAI),
|
|
143
|
+
"session-header": wire("sessionHeader", OAI, "scalar", ["x-litellm-session-id"]),
|
|
143
144
|
"reasoning-content-field": wire("reasoningContentField", OAI, "scalar", [
|
|
144
145
|
"reasoning_content",
|
|
145
146
|
"reasoning",
|
|
@@ -230,12 +231,20 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
|
|
|
230
231
|
"allow-anthropic-header-overrides": wire("allowAnthropicHeaderOverrides", ["anthropic"]),
|
|
231
232
|
"disable-adaptive-thinking": wire("disableAdaptiveThinking", ["anthropic"]),
|
|
232
233
|
"disable-strict-tools": wire("disableStrictTools", ["anthropic"]),
|
|
233
|
-
"
|
|
234
|
+
"between-tools-effort": wire("betweenToolsEffort", ["anthropic"], "scalar", ["low", "medium", "high"]),
|
|
235
|
+
"disabled-thinking": wire("disabledThinking", ["anthropic", "bedrock"], "scalar", [
|
|
236
|
+
"omit",
|
|
237
|
+
"disabled",
|
|
238
|
+
"adaptive",
|
|
239
|
+
"between-tools",
|
|
240
|
+
]),
|
|
234
241
|
"effort-beta": wire("effortBeta", ["anthropic"]),
|
|
235
242
|
"escape-builtin-tool-names": wire("escapeBuiltinToolNames", ["anthropic"]),
|
|
236
243
|
"fast-mode": wire("fastMode", ["anthropic"]),
|
|
237
244
|
"first-party-provider": wire("firstPartyProvider", ["anthropic"]),
|
|
238
245
|
"inject-claude-code-instruction": wire("injectClaudeCodeInstruction", ["anthropic"]),
|
|
246
|
+
"max-image-dimension": wire("maxImageDimension", ["anthropic"]),
|
|
247
|
+
"max-image-payload-bytes": wire("maxImagePayloadBytes", ["anthropic"]),
|
|
239
248
|
"official-endpoint": wire("officialEndpoint", ["anthropic", "openai-responses"]),
|
|
240
249
|
"replay-unsigned-thinking": wire("replayUnsignedThinking", ["anthropic"]),
|
|
241
250
|
"requires-thinking-enabled": wire("requiresThinkingEnabled", ["anthropic"]),
|
|
@@ -408,6 +417,18 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
|
|
|
408
417
|
"prompt-cache-lookback": { key: "promptCacheLookback", set: "catalog", shape: "scalar" },
|
|
409
418
|
"long-usage-limit-fallback": { key: "longUsageLimitFallback", set: "catalog", shape: "scalar" },
|
|
410
419
|
"max-context-window": { key: "maxContextWindow", set: "catalog", shape: "scalar" },
|
|
420
|
+
/**
|
|
421
|
+
* Every host of the model returns its full plaintext trace wherever the
|
|
422
|
+
* wire does not mark reasoning as a summary (`ThinkingContent.summary ===
|
|
423
|
+
* false` vouches for nothing more), and its identity (class + family +
|
|
424
|
+
* revision) pins one set of weights, so a turn's reasoning may replay
|
|
425
|
+
* natively on another host serving the same model. Marked summaries never
|
|
426
|
+
* carry; do not declare it where a host serves summaries unmarked.
|
|
427
|
+
* Declared per family in `classes/*.kdl`; a host whose reasoning must not be
|
|
428
|
+
* carried in or out sets `#false` in its `providers/*.kdl`. Read through
|
|
429
|
+
* `compat/reasoning-carry.ts`.
|
|
430
|
+
*/
|
|
431
|
+
"portable-reasoning": { key: "portableReasoning", set: "catalog", shape: "scalar", values: [true, false] },
|
|
411
432
|
"pricing-status": {
|
|
412
433
|
key: "pricingStatus",
|
|
413
434
|
set: "catalog",
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reasoning carry: whether reasoning a model produced on one host may replay
|
|
3
|
+
* natively on another host serving the same model.
|
|
4
|
+
*
|
|
5
|
+
* The model-side half is declared with the `portable-reasoning` catalog axis
|
|
6
|
+
* per family in `rules/classes/*.kdl`: the family's stored reasoning is its own
|
|
7
|
+
* full plaintext trace, and its identity pins one set of weights. A host whose
|
|
8
|
+
* reasoning must neither be carried in nor out overrides it to `#false` in its
|
|
9
|
+
* `rules/providers/*.kdl`. Whether the target host has a native slot for
|
|
10
|
+
* earlier reasoning is derived by the request encoders in `@oh-my-pi/pi-ai`,
|
|
11
|
+
* not declared here.
|
|
12
|
+
*
|
|
13
|
+
* Resolved through the cascade on demand (like delegation bias) because
|
|
14
|
+
* bundled rows are frozen by the generator; results are memoized per
|
|
15
|
+
* deployment.
|
|
16
|
+
*/
|
|
17
|
+
import { resolveCascade } from "./cascade";
|
|
18
|
+
import { classifyModel } from "./taxonomy";
|
|
19
|
+
import type { ModelIdentity } from "./types";
|
|
20
|
+
|
|
21
|
+
/** `null` records a deployment that does not carry reasoning. */
|
|
22
|
+
const portableIdentityMemo = new Map<string, ModelIdentity | null>();
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The identity a deployment's reasoning is carried under, or `undefined` when
|
|
26
|
+
* the deployment's model family is not declared portable there. Class-only
|
|
27
|
+
* identities never qualify: they name a lineage, not a set of weights.
|
|
28
|
+
*/
|
|
29
|
+
export function portableReasoningIdentity(provider: string, api: string, modelId: string): ModelIdentity | undefined {
|
|
30
|
+
const key = `${provider}\0${api}\0${modelId}`;
|
|
31
|
+
const memo = portableIdentityMemo.get(key);
|
|
32
|
+
if (memo !== undefined) return memo ?? undefined;
|
|
33
|
+
const identity = classifyModel(provider, modelId, { lenient: true });
|
|
34
|
+
let portable: ModelIdentity | null = null;
|
|
35
|
+
if (identity.family !== undefined || identity.revision !== undefined) {
|
|
36
|
+
const declared = resolveCascade({
|
|
37
|
+
provider,
|
|
38
|
+
api,
|
|
39
|
+
class: identity.class,
|
|
40
|
+
model: modelId,
|
|
41
|
+
reasoning: true,
|
|
42
|
+
...(identity.family !== undefined && { family: identity.family }),
|
|
43
|
+
...(identity.revision !== undefined && { revision: identity.revision }),
|
|
44
|
+
}).catalog.portableReasoning;
|
|
45
|
+
if (declared === true) portable = identity;
|
|
46
|
+
}
|
|
47
|
+
portableIdentityMemo.set(key, portable);
|
|
48
|
+
return portable ?? undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Whether reasoning recorded on `source` may replay natively on `target`:
|
|
53
|
+
* both deployments declare the family portable and classify to the same
|
|
54
|
+
* class, family, and revision.
|
|
55
|
+
*/
|
|
56
|
+
export function carriesReasoning(
|
|
57
|
+
source: { provider: string; api: string; model: string },
|
|
58
|
+
target: { provider: string; api: string; id: string },
|
|
59
|
+
): boolean {
|
|
60
|
+
const to = portableReasoningIdentity(target.provider, target.api, target.id);
|
|
61
|
+
if (!to) return false;
|
|
62
|
+
const from = portableReasoningIdentity(source.provider, source.api, source.model);
|
|
63
|
+
return from !== undefined && from.class === to.class && from.family === to.family && from.revision === to.revision;
|
|
64
|
+
}
|
package/src/compat/resolve.ts
CHANGED
|
@@ -915,6 +915,11 @@ function resolveAnthropicPolicy(
|
|
|
915
915
|
escapeBuiltinToolNames: false,
|
|
916
916
|
injectClaudeCodeInstruction: true,
|
|
917
917
|
stripImageInput: false,
|
|
918
|
+
// Unset means "canonical Anthropic image contract"; the request builder
|
|
919
|
+
// owns those numbers. The keys must exist for a KDL rule or a
|
|
920
|
+
// user-authored `compat` block to override them.
|
|
921
|
+
maxImageDimension: undefined,
|
|
922
|
+
maxImagePayloadBytes: undefined,
|
|
918
923
|
thinkingLoopGuard: undefined,
|
|
919
924
|
// Present as keys so models.yml `compat` can set them; unset unless a rule assigns them.
|
|
920
925
|
stripThinkingHistory: undefined,
|
|
@@ -98,4 +98,10 @@ class "deepseek" {
|
|
|
98
98
|
// providers alike. On hosts that parse it the healer sees no markup.
|
|
99
99
|
stream-markup-healing-pattern "dsml"
|
|
100
100
|
thinking-loop-guard "deepseek"
|
|
101
|
+
// V4 reasoning reaches omp as its plaintext trace on every host, and the
|
|
102
|
+
// revision pins the weights (flash 4.0 / 4.1, pro 4.0). Earlier lineages
|
|
103
|
+
// classify too coarsely to carry: `r1` also matches the R1 distills.
|
|
104
|
+
revision ">=4" {
|
|
105
|
+
portable-reasoning #true
|
|
106
|
+
}
|
|
101
107
|
}
|
|
@@ -65,7 +65,7 @@ class "glm" {
|
|
|
65
65
|
// GLM Coding Plan: the selectable 1M-context served ids; pin them so
|
|
66
66
|
// endpoint discovery or older bundled fallbacks cannot regress to 200k.
|
|
67
67
|
on "zai" "zhipu-coding-plan" {
|
|
68
|
-
models "glm-5.2" "glm-5.3" "glm-5.3-flash" {
|
|
68
|
+
models "glm-5.2" "glm-5.3" "glm-5.3-flash" "glm-5.3-flashx" {
|
|
69
69
|
limits-patch {
|
|
70
70
|
context-window 1000000
|
|
71
71
|
max-tokens 131072
|
|
@@ -84,10 +84,9 @@ class "glm" {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
|
-
//
|
|
88
|
-
// reports as text-only.
|
|
87
|
+
// GLM-5.3 Flash and FlashX accept native image input on their coding routes.
|
|
89
88
|
on "zai" "zhipu-coding-plan" {
|
|
90
|
-
models "glm-5.3-flash" {
|
|
89
|
+
models "glm-5.3-flash" "glm-5.3-flashx" {
|
|
91
90
|
input-modalities "text" "image"
|
|
92
91
|
}
|
|
93
92
|
}
|
|
@@ -99,17 +98,27 @@ class "glm" {
|
|
|
99
98
|
thinking-efforts "minimal" "low" "medium" "high"
|
|
100
99
|
}
|
|
101
100
|
}
|
|
102
|
-
// GLM-5.3+ coding SKUs (base/air/turbo/flash
|
|
101
|
+
// GLM-5.3+ coding SKUs (base/air/turbo/flash/flashx) expose a uniform
|
|
103
102
|
// wire-exact low/high/max reasoning-effort ladder on every host, thinking
|
|
104
103
|
// can no longer be disabled, and the default effort is max.
|
|
105
104
|
// residue: taxonomy ranks cannot separate these ids from the vision (`…v`)
|
|
106
|
-
// and
|
|
105
|
+
// and preview shapes that keep host dialects; the explicit priority resolves
|
|
107
106
|
// the intentional overlap with census host-dialect residues such as
|
|
108
107
|
// baseten's `zai-org/GLM-5*`.
|
|
109
|
-
models "*glm-5.3" "*glm-5.3-air" "*glm-5.3-turbo" "*glm-5.3-flash" "*glm-5.3:*" \
|
|
108
|
+
models "*glm-5.3" "*glm-5.3-air" "*glm-5.3-turbo" "*glm-5.3-flash" "*glm-5.3-flashx" "*glm-5.3:*" \
|
|
110
109
|
"*glm-5.3-flash-uncensored" "*glm-5.3-free" "*glm-5.3-highspeed" "*glm-5.3-fast" "*glm-5.3-flash-lab" priority=10 {
|
|
111
110
|
thinking-default-level "max"
|
|
112
111
|
thinking-efforts "low" "high" "max"
|
|
113
112
|
thinking-requires-effort #true
|
|
114
113
|
}
|
|
114
|
+
// GLM 5+ reasoning reaches omp as its plaintext trace on every host, and
|
|
115
|
+
// family plus revision pin the weights (glm-5.2, glm-5.3-flash, ...). GLM 4
|
|
116
|
+
// classifies too coarsely to carry: 4.0 also matches glm-4.5v and glm-4.6v.
|
|
117
|
+
revision ">=5" {
|
|
118
|
+
portable-reasoning #true
|
|
119
|
+
// residue: fine-tuned weights that classify as the base GLM revision.
|
|
120
|
+
models "*-uncensored" "*-cybersecurity" {
|
|
121
|
+
portable-reasoning #false
|
|
122
|
+
}
|
|
123
|
+
}
|
|
115
124
|
}
|
|
@@ -123,4 +123,12 @@ class "kimi" {
|
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
|
+
// K3 reasoning reaches omp as its plaintext trace on every host, and K3 was
|
|
127
|
+
// trained to read all of its earlier reasoning back (preserved thinking).
|
|
128
|
+
// A recall probe showed the reasoning slot of moonshot, factory-droid,
|
|
129
|
+
// openrouter and devin reaches the model, so K3 reasoning moves between
|
|
130
|
+
// those hosts natively instead of as visible `<think>` text.
|
|
131
|
+
family "k3" {
|
|
132
|
+
portable-reasoning #true
|
|
133
|
+
}
|
|
126
134
|
}
|
|
@@ -98,4 +98,14 @@ class "minimax" {
|
|
|
98
98
|
on "minimax-code" "minimax-code-cn" "wafer-serverless" {
|
|
99
99
|
reasoning-content-field "reasoning_content"
|
|
100
100
|
}
|
|
101
|
+
// M3 reasoning reaches omp as its plaintext trace on every host, and
|
|
102
|
+
// MiniMax asks agents to pass all earlier reasoning back.
|
|
103
|
+
family "m3" {
|
|
104
|
+
portable-reasoning #true
|
|
105
|
+
// residue: M3.1 Flash Preview classifies as family m3 (no revision is
|
|
106
|
+
// extracted), but it is a different model.
|
|
107
|
+
models "*m3.1*" {
|
|
108
|
+
portable-reasoning #false
|
|
109
|
+
}
|
|
110
|
+
}
|
|
101
111
|
}
|
|
@@ -49,10 +49,12 @@ class "openai" {
|
|
|
49
49
|
delegation-bias "restrained"
|
|
50
50
|
supports-steering #true
|
|
51
51
|
}
|
|
52
|
-
// GPT-6
|
|
52
|
+
// The GPT-6 family changes reasoning effort mid-conversation through a
|
|
53
53
|
// `configuration_update` input item so the request-level effort (and the
|
|
54
|
-
// cached prompt prefix) stays put
|
|
55
|
-
|
|
54
|
+
// cached prompt prefix) stays put. OpenAI's reasoning guide ("Change
|
|
55
|
+
// reasoning mid-conversation") documents it for the family, and Codex's
|
|
56
|
+
// `/models` reports `supports_reasoning_effort_updates` on every GPT-6 SKU.
|
|
57
|
+
revision ">=6 <7" {
|
|
56
58
|
supports-configuration-update #true
|
|
57
59
|
}
|
|
58
60
|
// Codex SKUs: the advertised 400K figure includes the output budget; the
|
|
@@ -37,4 +37,11 @@ provider "abliteration" {
|
|
|
37
37
|
|
|
38
38
|
include-encrypted-reasoning #false
|
|
39
39
|
stream-idle-timeout-ms 0
|
|
40
|
+
// Abliterated weights classify as the GLM revision they derive from, but
|
|
41
|
+
// they are modified weights: their reasoning is not carried to or from GLM.
|
|
42
|
+
class "glm" {
|
|
43
|
+
revision ">=5" {
|
|
44
|
+
portable-reasoning #false
|
|
45
|
+
}
|
|
46
|
+
}
|
|
40
47
|
}
|
|
@@ -36,6 +36,10 @@ provider "cursor" {
|
|
|
36
36
|
input-modalities "text" "image"
|
|
37
37
|
context-window-floor 1000000
|
|
38
38
|
}
|
|
39
|
+
// Cursor's agent protocol relays thinking opaquely, so it is not
|
|
40
|
+
// verified as K3's full trace: Cursor K3 turns are not carried to
|
|
41
|
+
// other K3 hosts (Cursor itself refuses foreign history).
|
|
42
|
+
portable-reasoning #false
|
|
39
43
|
}
|
|
40
44
|
family "k2.7-code" {
|
|
41
45
|
// Cursor advertised Kimi K2.7 Code Context window 262k.
|