@linxiraos/pi-catalog 1.1.7 → 1.1.8
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 +8 -8
- package/README.md +9 -8
- package/dist/types/build.d.ts +13 -8
- package/dist/types/cline-pass-model-id.d.ts +4 -0
- package/dist/types/compat/anthropic.d.ts +10 -4
- package/dist/types/compat/auth-ids.d.ts +4 -0
- package/dist/types/compat/auth.d.ts +7 -0
- package/dist/types/compat/axes.d.ts +50 -0
- package/dist/types/compat/behavior.d.ts +69 -0
- package/dist/types/compat/cascade.d.ts +37 -0
- package/dist/types/{variant-collapse.d.ts → compat/collapse.d.ts} +60 -35
- package/dist/types/compat/openai.d.ts +7 -26
- package/dist/types/compat/resolve.d.ts +15 -0
- package/dist/types/compat/revision.d.ts +41 -0
- package/dist/types/compat/taxonomy.d.ts +93 -0
- package/dist/types/compat/types.d.ts +565 -0
- package/dist/types/discovery/antigravity.d.ts +1 -1
- package/dist/types/discovery/cursor-proto.d.ts +6 -6
- package/dist/types/discovery/cursor.d.ts +5 -3
- package/dist/types/discovery/devin-proto.d.ts +363 -0
- package/dist/types/discovery/gemini-cli.d.ts +1 -1
- package/dist/types/identity/id.d.ts +1 -0
- package/dist/types/identity/index.d.ts +3 -3
- package/dist/types/identity/reference.d.ts +0 -10
- package/dist/types/index.d.ts +1 -1
- package/dist/types/model-thinking.d.ts +6 -24
- package/dist/types/provider-models/cline-pass.d.ts +22 -0
- package/dist/types/provider-models/descriptors.d.ts +20 -1
- package/dist/types/provider-models/models-dev-policies.d.ts +2 -1
- package/dist/types/provider-models/openai-compat.d.ts +59 -46
- package/dist/types/provider-models/special.d.ts +23 -2
- package/dist/types/types.d.ts +177 -13
- package/dist/types/wire/cline-pass.d.ts +21 -0
- package/dist/types/wire/devin-proto.d.ts +14 -0
- package/dist/types/wire/devin.d.ts +36 -0
- package/dist/types/wire/github-copilot.d.ts +31 -12
- package/package.json +6 -4
- package/src/build.ts +165 -48
- package/src/cline-pass-model-id.ts +11 -0
- package/src/compat/anthropic.ts +15 -136
- package/src/compat/auth-ids.ts +157 -0
- package/src/compat/auth.ts +60 -0
- package/src/compat/axes.ts +290 -0
- package/src/compat/behavior.ts +207 -0
- package/src/compat/cascade.ts +230 -0
- package/src/{variant-collapse.ts → compat/collapse.ts} +381 -773
- package/src/compat/openai.ts +17 -848
- package/src/compat/resolve.ts +1229 -0
- package/src/compat/revision.ts +154 -0
- package/src/compat/rules/README.md +315 -0
- package/src/compat/rules/auth/_order.kdl +13 -0
- package/src/compat/rules/auth/abliteration.kdl +9 -0
- package/src/compat/rules/auth/aiand.kdl +9 -0
- package/src/compat/rules/auth/aimlapi.kdl +3 -0
- package/src/compat/rules/auth/alibaba-coding-plan.kdl +5 -0
- package/src/compat/rules/auth/alibaba-token-plan.kdl +11 -0
- package/src/compat/rules/auth/amazon-bedrock.kdl +5 -0
- package/src/compat/rules/auth/anthropic.kdl +53 -0
- package/src/compat/rules/auth/azure.kdl +3 -0
- package/src/compat/rules/auth/baseten.kdl +9 -0
- package/src/compat/rules/auth/bedrock-mantle.kdl +5 -0
- package/src/compat/rules/auth/cerebras.kdl +9 -0
- package/src/compat/rules/auth/cline-pass.kdl +12 -0
- package/src/compat/rules/auth/cloudflare-ai-gateway.kdl +4 -0
- package/src/compat/rules/auth/coreweave.kdl +9 -0
- package/src/compat/rules/auth/cursor.kdl +5 -0
- package/src/compat/rules/auth/deepinfra.kdl +11 -0
- package/src/compat/rules/auth/deepseek.kdl +10 -0
- package/src/compat/rules/auth/devin.kdl +28 -0
- package/src/compat/rules/auth/exa.kdl +9 -0
- package/src/compat/rules/auth/firepass.kdl +14 -0
- package/src/compat/rules/auth/fireworks.kdl +16 -0
- package/src/compat/rules/auth/github-copilot.kdl +7 -0
- package/src/compat/rules/auth/gitlab-duo-agent.kdl +23 -0
- package/src/compat/rules/auth/gitlab-duo.kdl +24 -0
- package/src/compat/rules/auth/gmi-cloud.kdl +9 -0
- package/src/compat/rules/auth/google-antigravity.kdl +28 -0
- package/src/compat/rules/auth/google-gemini-cli.kdl +26 -0
- package/src/compat/rules/auth/google-vertex.kdl +5 -0
- package/src/compat/rules/auth/google.kdl +3 -0
- package/src/compat/rules/auth/groq.kdl +3 -0
- package/src/compat/rules/auth/huggingface.kdl +9 -0
- package/src/compat/rules/auth/kagi.kdl +9 -0
- package/src/compat/rules/auth/kilo.kdl +4 -0
- package/src/compat/rules/auth/kimi-code.kdl +18 -0
- package/src/compat/rules/auth/litellm.kdl +8 -0
- package/src/compat/rules/auth/llama.cpp.kdl +10 -0
- package/src/compat/rules/auth/lm-studio.kdl +7 -0
- package/src/compat/rules/auth/meta.kdl +9 -0
- package/src/compat/rules/auth/minimax-code-cn.kdl +9 -0
- package/src/compat/rules/auth/minimax-code.kdl +9 -0
- package/src/compat/rules/auth/minimax.kdl +3 -0
- package/src/compat/rules/auth/mistral.kdl +3 -0
- package/src/compat/rules/auth/moonshot.kdl +9 -0
- package/src/compat/rules/auth/nanogpt.kdl +9 -0
- package/src/compat/rules/auth/novita.kdl +12 -0
- package/src/compat/rules/auth/nvidia.kdl +11 -0
- package/src/compat/rules/auth/ollama-cloud.kdl +8 -0
- package/src/compat/rules/auth/ollama.kdl +9 -0
- package/src/compat/rules/auth/openai-codex-device.kdl +20 -0
- package/src/compat/rules/auth/openai-codex.kdl +33 -0
- package/src/compat/rules/auth/openai.kdl +3 -0
- package/src/compat/rules/auth/opencode-go.kdl +10 -0
- package/src/compat/rules/auth/opencode-zen.kdl +9 -0
- package/src/compat/rules/auth/openrouter.kdl +32 -0
- package/src/compat/rules/auth/parallel.kdl +9 -0
- package/src/compat/rules/auth/perplexity.kdl +7 -0
- package/src/compat/rules/auth/qianfan.kdl +9 -0
- package/src/compat/rules/auth/qwen-portal.kdl +9 -0
- package/src/compat/rules/auth/sakana.kdl +9 -0
- package/src/compat/rules/auth/siliconflow-cn.kdl +9 -0
- package/src/compat/rules/auth/siliconflow.kdl +9 -0
- package/src/compat/rules/auth/synthetic.kdl +9 -0
- package/src/compat/rules/auth/tavily.kdl +9 -0
- package/src/compat/rules/auth/together.kdl +14 -0
- package/src/compat/rules/auth/umans.kdl +9 -0
- package/src/compat/rules/auth/venice.kdl +9 -0
- package/src/compat/rules/auth/vercel-ai-gateway.kdl +8 -0
- package/src/compat/rules/auth/vllm.kdl +9 -0
- package/src/compat/rules/auth/wafer-serverless.kdl +11 -0
- package/src/compat/rules/auth/xai-oauth.kdl +27 -0
- package/src/compat/rules/auth/xai.kdl +9 -0
- package/src/compat/rules/auth/xiaomi-token-plan-ams.kdl +9 -0
- package/src/compat/rules/auth/xiaomi-token-plan-cn.kdl +9 -0
- package/src/compat/rules/auth/xiaomi-token-plan-sgp.kdl +9 -0
- package/src/compat/rules/auth/xiaomi.kdl +6 -0
- package/src/compat/rules/auth/yolo-auto.kdl +11 -0
- package/src/compat/rules/auth/zai-coding-plan.kdl +29 -0
- package/src/compat/rules/auth/zai.kdl +9 -0
- package/src/compat/rules/auth/zenmux.kdl +9 -0
- package/src/compat/rules/auth/zhipu-coding-plan.kdl +9 -0
- package/src/compat/rules/classes/amazon.kdl +21 -0
- package/src/compat/rules/classes/anthropic.kdl +285 -0
- package/src/compat/rules/classes/baidu.kdl +9 -0
- package/src/compat/rules/classes/bytedance.kdl +9 -0
- package/src/compat/rules/classes/cohere.kdl +7 -0
- package/src/compat/rules/classes/deepseek.kdl +80 -0
- package/src/compat/rules/classes/gemini.kdl +107 -0
- package/src/compat/rules/classes/gemma.kdl +14 -0
- package/src/compat/rules/classes/glm.kdl +115 -0
- package/src/compat/rules/classes/gpt-oss.kdl +16 -0
- package/src/compat/rules/classes/kimi.kdl +113 -0
- package/src/compat/rules/classes/meta.kdl +15 -0
- package/src/compat/rules/classes/mimo.kdl +32 -0
- package/src/compat/rules/classes/minimax.kdl +79 -0
- package/src/compat/rules/classes/mistral.kdl +19 -0
- package/src/compat/rules/classes/openai.kdl +42 -0
- package/src/compat/rules/classes/qwen.kdl +72 -0
- package/src/compat/rules/classes/stepfun.kdl +10 -0
- package/src/compat/rules/classes/xai.kdl +45 -0
- package/src/compat/rules/providers/abliteration.kdl +8 -0
- package/src/compat/rules/providers/aiand.kdl +19 -0
- package/src/compat/rules/providers/aimlapi.kdl +24 -0
- package/src/compat/rules/providers/alibaba-coding-plan.kdl +20 -0
- package/src/compat/rules/providers/alibaba-token-plan.kdl +35 -0
- package/src/compat/rules/providers/amazon-bedrock.kdl +36 -0
- package/src/compat/rules/providers/anthropic.kdl +24 -0
- package/src/compat/rules/providers/azure.kdl +19 -0
- package/src/compat/rules/providers/baseten.kdl +19 -0
- package/src/compat/rules/providers/bedrock-mantle.kdl +15 -0
- package/src/compat/rules/providers/cerebras.kdl +19 -0
- package/src/compat/rules/providers/cline-pass.kdl +8 -0
- package/src/compat/rules/providers/cloudflare-ai-gateway.kdl +26 -0
- package/src/compat/rules/providers/coreweave.kdl +16 -0
- package/src/compat/rules/providers/cursor.kdl +52 -0
- package/src/compat/rules/providers/deepseek.kdl +21 -0
- package/src/compat/rules/providers/firepass.kdl +15 -0
- package/src/compat/rules/providers/fireworks.kdl +43 -0
- package/src/compat/rules/providers/github-copilot.kdl +62 -0
- package/src/compat/rules/providers/gitlab-duo.kdl +24 -0
- package/src/compat/rules/providers/gmi-cloud.kdl +8 -0
- package/src/compat/rules/providers/google-antigravity.kdl +59 -0
- package/src/compat/rules/providers/google-gemini-cli.kdl +12 -0
- package/src/compat/rules/providers/google-vertex.kdl +25 -0
- package/src/compat/rules/providers/google.kdl +17 -0
- package/src/compat/rules/providers/groq.kdl +8 -0
- package/src/compat/rules/providers/huggingface.kdl +24 -0
- package/src/compat/rules/providers/kilo.kdl +51 -0
- package/src/compat/rules/providers/kimi-code.kdl +37 -0
- package/src/compat/rules/providers/llama.cpp.kdl +6 -0
- package/src/compat/rules/providers/lm-studio.kdl +6 -0
- package/src/compat/rules/providers/meta.kdl +10 -0
- package/src/compat/rules/providers/minimax-code-cn.kdl +13 -0
- package/src/compat/rules/providers/minimax-code.kdl +13 -0
- package/src/compat/rules/providers/minimax.kdl +6 -0
- package/src/compat/rules/providers/mistral.kdl +8 -0
- package/src/compat/rules/providers/moonshot.kdl +36 -0
- package/src/compat/rules/providers/nanogpt.kdl +100 -0
- package/src/compat/rules/providers/novita.kdl +34 -0
- package/src/compat/rules/providers/nvidia.kdl +27 -0
- package/src/compat/rules/providers/ollama-cloud.kdl +20 -0
- package/src/compat/rules/providers/ollama.kdl +12 -0
- package/src/compat/rules/providers/openai-codex.kdl +121 -0
- package/src/compat/rules/providers/openai.kdl +82 -0
- package/src/compat/rules/providers/opencode-go.kdl +97 -0
- package/src/compat/rules/providers/opencode-zen.kdl +103 -0
- package/src/compat/rules/providers/openrouter.kdl +66 -0
- package/src/compat/rules/providers/qianfan.kdl +8 -0
- package/src/compat/rules/providers/sakana.kdl +10 -0
- package/src/compat/rules/providers/synthetic.kdl +16 -0
- package/src/compat/rules/providers/together.kdl +22 -0
- package/src/compat/rules/providers/umans.kdl +28 -0
- package/src/compat/rules/providers/venice.kdl +46 -0
- package/src/compat/rules/providers/vercel-ai-gateway.kdl +73 -0
- package/src/compat/rules/providers/vllm.kdl +8 -0
- package/src/compat/rules/providers/wafer-serverless.kdl +35 -0
- package/src/compat/rules/providers/xai-oauth.kdl +48 -0
- package/src/compat/rules/providers/xai.kdl +50 -0
- package/src/compat/rules/providers/xiaomi-token-plan-ams.kdl +9 -0
- package/src/compat/rules/providers/xiaomi-token-plan-cn.kdl +9 -0
- package/src/compat/rules/providers/xiaomi-token-plan-sgp.kdl +9 -0
- package/src/compat/rules/providers/xiaomi.kdl +22 -0
- package/src/compat/rules/providers/yolo-auto.kdl +16 -0
- package/src/compat/rules/providers/zai.kdl +36 -0
- package/src/compat/rules/providers/zenmux.kdl +108 -0
- package/src/compat/rules/providers/zhipu-coding-plan.kdl +49 -0
- package/src/compat/rules/runtime/behavior.kdl +254 -0
- package/src/compat/rules/taxonomy/_collapse.kdl +747 -0
- package/src/compat/rules/taxonomy/_discovery.kdl +60 -0
- package/src/compat/rules/taxonomy/ai21.kdl +6 -0
- package/src/compat/rules/taxonomy/amazon.kdl +8 -0
- package/src/compat/rules/taxonomy/anthropic.kdl +17 -0
- package/src/compat/rules/taxonomy/baidu.kdl +5 -0
- package/src/compat/rules/taxonomy/bytedance.kdl +5 -0
- package/src/compat/rules/taxonomy/cohere.kdl +6 -0
- package/src/compat/rules/taxonomy/deepseek.kdl +18 -0
- package/src/compat/rules/taxonomy/gemini.kdl +9 -0
- package/src/compat/rules/taxonomy/gemma.kdl +3 -0
- package/src/compat/rules/taxonomy/glm.kdl +17 -0
- package/src/compat/rules/taxonomy/gpt-oss.kdl +11 -0
- package/src/compat/rules/taxonomy/kimi.kdl +20 -0
- package/src/compat/rules/taxonomy/meta.kdl +10 -0
- package/src/compat/rules/taxonomy/mimo.kdl +7 -0
- package/src/compat/rules/taxonomy/minimax.kdl +9 -0
- package/src/compat/rules/taxonomy/mistral.kdl +7 -0
- package/src/compat/rules/taxonomy/openai.kdl +43 -0
- package/src/compat/rules/taxonomy/qwen.kdl +33 -0
- package/src/compat/rules/taxonomy/stepfun.kdl +5 -0
- package/src/compat/rules/taxonomy/unknown.kdl +3 -0
- package/src/compat/rules/taxonomy/xai.kdl +12 -0
- package/src/compat/rules.d.json.ts +5 -0
- package/src/compat/rules.json +16933 -0
- package/src/compat/taxonomy.ts +452 -0
- package/src/compat/types.ts +586 -0
- package/src/discovery/antigravity.ts +5 -6
- package/src/discovery/codex.ts +12 -7
- package/src/discovery/cursor-proto.ts +7 -7
- package/src/discovery/cursor.ts +47 -58
- package/src/discovery/devin-proto.ts +613 -0
- package/src/discovery/devin.ts +358 -52
- package/src/discovery/gemini-cli.ts +14 -11
- package/src/discovery/gemini.ts +2 -0
- package/src/identity/dialect.ts +2 -2
- package/src/identity/id.ts +12 -0
- package/src/identity/index.ts +3 -3
- package/src/identity/reference.ts +30 -4
- package/src/index.ts +1 -1
- package/src/model-manager.ts +4 -4
- package/src/model-thinking.ts +6 -810
- package/src/model-tokenizer.ts +37 -44
- package/src/models.json +86187 -23440
- package/src/models.ts +6 -1
- package/src/provider-models/bundled-references.ts +3 -1
- package/src/provider-models/cline-pass.ts +226 -0
- package/src/provider-models/descriptors.ts +18 -0
- package/src/provider-models/google.ts +14 -5
- package/src/provider-models/models-dev-policies.ts +4 -29
- package/src/provider-models/ollama.ts +15 -2
- package/src/provider-models/openai-compat.ts +794 -520
- package/src/provider-models/special.ts +186 -2
- package/src/types.ts +197 -11
- package/src/wire/cline-pass.ts +35 -0
- package/src/wire/devin-proto.ts +30 -0
- package/src/wire/devin.ts +72 -0
- package/src/wire/github-copilot.ts +49 -7
- package/dist/types/compat/bedrock.d.ts +0 -3
- package/dist/types/compat/devin.d.ts +0 -9
- package/dist/types/identity/classify.d.ts +0 -69
- package/dist/types/identity/family.d.ts +0 -243
- package/dist/types/identity/markers.d.ts +0 -4
- package/dist/types/openai-pricing.d.ts +0 -17
- package/src/compat/bedrock.ts +0 -153
- package/src/compat/devin.ts +0 -12
- package/src/identity/classify.ts +0 -242
- package/src/identity/family.ts +0 -496
- package/src/identity/markers.ts +0 -49
- package/src/openai-pricing.ts +0 -29
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Devin (Codeium Cascade) wire constants shared by catalog discovery, the pi-ai
|
|
3
|
+
* provider, and account usage. This module deliberately stays free of the
|
|
4
|
+
* generated protobuf runtime so the synchronous model seed can import it
|
|
5
|
+
* without pulling devin-gen into the boot path.
|
|
6
|
+
*/
|
|
7
|
+
/** Base host for Codeium/Windsurf's Cascade API (Connect protocol over HTTP/1.1). */
|
|
8
|
+
export declare const DEVIN_DEFAULT_BASE_URL = "https://server.codeium.com";
|
|
9
|
+
/** Session token as the wire format carries it: the scheme prefix is required. */
|
|
10
|
+
export declare function normalizeDevinSessionToken(apiKey: string | undefined): string;
|
|
11
|
+
/**
|
|
12
|
+
* Fields for `Metadata` on released-CLI calls (`GetUserJwt`, `AssignModel`,
|
|
13
|
+
* `GetChatMessage`, `GetUserStatus`). `userJwt` stays empty for the calls the
|
|
14
|
+
* CLI makes with the session token alone (auth, model assignment, usage).
|
|
15
|
+
*/
|
|
16
|
+
export declare function devinCliMetadata(apiKey: string | undefined, userJwt?: string): {
|
|
17
|
+
ideName: "devin-cli";
|
|
18
|
+
ideType: "chisel";
|
|
19
|
+
ideVersion: "3000.6.2";
|
|
20
|
+
extensionName: "chisel";
|
|
21
|
+
extensionVersion: "3000.6.2";
|
|
22
|
+
locale: "en";
|
|
23
|
+
os: "darwin" | "linux" | "windows";
|
|
24
|
+
apiKey: string;
|
|
25
|
+
userJwt: string;
|
|
26
|
+
};
|
|
27
|
+
/** Fields for `Metadata` on the dev-channel `GetCliModelConfigs` call. */
|
|
28
|
+
export declare function devinDiscoveryMetadata(apiKey: string | undefined): {
|
|
29
|
+
ideName: "chisel";
|
|
30
|
+
ideVersion: "0.0.0-dev";
|
|
31
|
+
extensionName: "chisel";
|
|
32
|
+
extensionVersion: "0.0.0-dev";
|
|
33
|
+
locale: "en";
|
|
34
|
+
os: "darwin" | "linux" | "windows";
|
|
35
|
+
apiKey: string;
|
|
36
|
+
};
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import type { FetchImpl } from "../types.js";
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*/
|
|
7
|
-
export declare const
|
|
8
|
-
|
|
9
|
-
readonly "
|
|
2
|
+
/** Headers sent by Copilot CLI to GitHub API and OAuth endpoints. */
|
|
3
|
+
export declare const COPILOT_GITHUB_HEADERS: {
|
|
4
|
+
readonly "User-Agent": "copilot/1.0.82";
|
|
5
|
+
};
|
|
6
|
+
/** Copilot CLI identity sent to the Copilot API. */
|
|
7
|
+
export declare const COPILOT_CAPI_IDENTITY_HEADERS: {
|
|
8
|
+
readonly "User-Agent": "copilot/1.0.82";
|
|
9
|
+
readonly "Editor-Version": "copilot/1.0.82";
|
|
10
|
+
readonly "Copilot-Integration-Id": "copilot-developer-cli";
|
|
11
|
+
readonly "Copilot-Harness-Id": "copilot-sdk";
|
|
12
|
+
readonly "Openai-Intent": "conversation-agent";
|
|
10
13
|
};
|
|
11
14
|
/**
|
|
12
15
|
* Copilot API version sent on `api.githubcopilot.com` requests (`/models`,
|
|
@@ -17,12 +20,28 @@ export declare const OPENCODE_HEADERS: {
|
|
|
17
20
|
* of 1M for Claude Opus). Never send this to `api.github.com` REST endpoints —
|
|
18
21
|
* they validate `X-GitHub-Api-Version` against the REST version vocabulary.
|
|
19
22
|
*/
|
|
20
|
-
export declare const COPILOT_API_VERSION: "2026-
|
|
21
|
-
/** Headers
|
|
23
|
+
export declare const COPILOT_API_VERSION: "2026-08-01";
|
|
24
|
+
/** Headers shared by Copilot API model requests and model definitions. */
|
|
22
25
|
export declare const COPILOT_API_HEADERS: {
|
|
23
|
-
readonly "User-Agent": "
|
|
24
|
-
readonly "
|
|
26
|
+
readonly "User-Agent": "copilot/1.0.82";
|
|
27
|
+
readonly "Editor-Version": "copilot/1.0.82";
|
|
28
|
+
readonly "Copilot-Integration-Id": "copilot-developer-cli";
|
|
29
|
+
readonly "Copilot-Harness-Id": "copilot-sdk";
|
|
30
|
+
readonly "Openai-Intent": "conversation-agent";
|
|
31
|
+
readonly "X-GitHub-Api-Version": "2026-08-01";
|
|
32
|
+
};
|
|
33
|
+
/** Copilot CLI headers for user-initiated model discovery. */
|
|
34
|
+
export declare const COPILOT_DISCOVERY_HEADERS: {
|
|
35
|
+
readonly "User-Agent": "copilot/1.0.82";
|
|
36
|
+
readonly "Editor-Version": "copilot/1.0.82";
|
|
37
|
+
readonly "Copilot-Integration-Id": "copilot-developer-cli";
|
|
38
|
+
readonly "Copilot-Harness-Id": "copilot-sdk";
|
|
39
|
+
readonly "Openai-Intent": "conversation-agent";
|
|
40
|
+
readonly "X-GitHub-Api-Version": "2026-08-01";
|
|
41
|
+
readonly "X-Initiator": "user";
|
|
25
42
|
};
|
|
43
|
+
/** Preserve model-specific headers while enforcing the current Copilot API identity. */
|
|
44
|
+
export declare function mergeCopilotApiHeaders(headers?: Readonly<Record<string, string>>): Record<string, string>;
|
|
26
45
|
export type ParsedGitHubCopilotApiKey = {
|
|
27
46
|
accessToken: string;
|
|
28
47
|
enterpriseUrl?: string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@linxiraos/pi-catalog",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.8",
|
|
5
5
|
"description": "Model catalog for omp: bundled model database, provider discovery descriptors, model identity, classification, and equivalence",
|
|
6
6
|
"homepage": "https://linxira-os.github.io/zeta/",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -31,14 +31,16 @@
|
|
|
31
31
|
"fix": "biome check --write --unsafe .",
|
|
32
32
|
"fmt": "biome format --write .",
|
|
33
33
|
"gen:models": "bun scripts/generate-models.ts",
|
|
34
|
+
"gen:compat": "bun scripts/compile-compat.ts",
|
|
34
35
|
"gen:proto": "bun scripts/generate-protocols.ts"
|
|
35
36
|
},
|
|
36
37
|
"dependencies": {
|
|
37
|
-
"@linxiraos/pi-omptype": "1.1.
|
|
38
|
-
"@linxiraos/pi-utils": "1.1.
|
|
38
|
+
"@linxiraos/pi-omptype": "1.1.8",
|
|
39
|
+
"@linxiraos/pi-utils": "1.1.8"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
41
|
-
"@
|
|
42
|
+
"@bgotink/kdl": "0.4.0",
|
|
43
|
+
"@linxiraos/pi-ai": "1.1.8",
|
|
42
44
|
"@types/bun": "^1.3.14"
|
|
43
45
|
},
|
|
44
46
|
"engines": {
|
package/src/build.ts
CHANGED
|
@@ -1,26 +1,149 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The single Model constructor. Resolution
|
|
3
|
-
*
|
|
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);
|
|
2
|
+
* The single Model constructor. Resolution runs through the compat engine
|
|
3
|
+
* (`compat/resolve`): identity classification, cascade-rule axes, host
|
|
4
|
+
* detection, and spec overrides materialize exactly once per spec.
|
|
8
5
|
*
|
|
9
6
|
* Request handlers read fields — they never detect, parse ids, or allocate
|
|
10
7
|
* compat per request.
|
|
11
8
|
*/
|
|
12
9
|
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { buildDevinCompat } from "./compat/devin";
|
|
16
|
-
import { buildOpenAICompat, buildOpenAIResponsesCompat, buildOpenRouterCompat } from "./compat/openai";
|
|
17
|
-
import { bareModelId, parseOpenAIModel, semverGte } from "./identity/classify";
|
|
18
|
-
import { isClaudeModelId } from "./identity/family";
|
|
19
|
-
import { resolveModelThinking } from "./model-thinking";
|
|
10
|
+
import { resolveModelPolicy } from "./compat/resolve";
|
|
11
|
+
import type { ModelIdentity } from "./compat/types";
|
|
20
12
|
import { resolveModelTokenizer } from "./model-tokenizer";
|
|
21
|
-
import type { Api,
|
|
13
|
+
import type { Api, Model, ModelSpec } from "./types";
|
|
22
14
|
import { cleanModelName } from "./utils";
|
|
23
15
|
|
|
16
|
+
function numberField(source: object, key: string): number | undefined {
|
|
17
|
+
const value: unknown = Reflect.get(source, key);
|
|
18
|
+
return typeof value === "number" ? value : undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Narrow an unknown compiled-axis payload to an object payload. */
|
|
22
|
+
function objectPayload(value: unknown): object | undefined {
|
|
23
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Narrow a compiled `input-modalities` axis value to the model input union. */
|
|
27
|
+
function isInputModalities(value: unknown): value is ("text" | "image")[] {
|
|
28
|
+
return Array.isArray(value) && value.every(entry => entry === "text" || entry === "image");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Applies resolved catalog-data axes onto the model: reviewed metadata
|
|
33
|
+
* corrections (`cost-patch`, `limits-patch`, `long-context-cost`,
|
|
34
|
+
* `context-window-floor`) overwrite upstream values; selection metadata
|
|
35
|
+
* (`priority`, `apply-patch-tool-type`, `service-tier-cost`,
|
|
36
|
+
* `requires-cursor-tool-schema-projection`) is rule-owned;
|
|
37
|
+
* `context-promotion-target` fills only when the spec left it unset.
|
|
38
|
+
*/
|
|
39
|
+
function applyCatalogAssignments<TApi extends Api>(model: Model<TApi>, catalog: Record<string, unknown>): void {
|
|
40
|
+
const serviceTierCost = objectPayload(catalog.serviceTierCost);
|
|
41
|
+
if (serviceTierCost !== undefined) {
|
|
42
|
+
const flex = numberField(serviceTierCost, "flex");
|
|
43
|
+
const priorityTier = numberField(serviceTierCost, "priority");
|
|
44
|
+
model.serviceTierCost = {
|
|
45
|
+
...(flex !== undefined && { flex }),
|
|
46
|
+
...(priorityTier !== undefined && { priority: priorityTier }),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const priority = catalog.priority;
|
|
50
|
+
if (typeof priority === "number") model.priority = priority;
|
|
51
|
+
const applyPatchToolType = catalog.applyPatchToolType;
|
|
52
|
+
if (applyPatchToolType === "freeform" || applyPatchToolType === "function") {
|
|
53
|
+
model.applyPatchToolType = applyPatchToolType;
|
|
54
|
+
}
|
|
55
|
+
const requiresCursorToolSchemaProjection = catalog.requiresCursorToolSchemaProjection;
|
|
56
|
+
if (requiresCursorToolSchemaProjection === true) {
|
|
57
|
+
model.requiresCursorToolSchemaProjection = true;
|
|
58
|
+
} else {
|
|
59
|
+
delete model.requiresCursorToolSchemaProjection;
|
|
60
|
+
}
|
|
61
|
+
const contextPromotionTarget = catalog.contextPromotionTarget;
|
|
62
|
+
if (typeof contextPromotionTarget === "string" && model.contextPromotionTarget === undefined) {
|
|
63
|
+
model.contextPromotionTarget = contextPromotionTarget;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Applies reviewed catalog-data value corrections (`cost-patch`,
|
|
69
|
+
* `limits-patch`, `long-context-cost`, `context-window-floor`,
|
|
70
|
+
* `input-modalities`) onto an upstream-sourced spec. Applied by
|
|
71
|
+
* `buildModel` to every upstream-sourced spec; user-authored overrides are
|
|
72
|
+
* recomposed after building by the override applicators, so explicit user
|
|
73
|
+
* limits and pricing still win.
|
|
74
|
+
*/
|
|
75
|
+
export function applyCatalogCorrections(
|
|
76
|
+
model: Pick<ModelSpec<Api>, "cost" | "contextWindow" | "maxTokens" | "input">,
|
|
77
|
+
catalog: Record<string, unknown>,
|
|
78
|
+
): void {
|
|
79
|
+
const longContext = objectPayload(catalog.longContext);
|
|
80
|
+
if (longContext !== undefined) {
|
|
81
|
+
const inputThreshold = numberField(longContext, "inputThreshold");
|
|
82
|
+
const inclusive = Reflect.get(longContext, "inputThresholdInclusive") === true;
|
|
83
|
+
const multiplier = numberField(longContext, "multiplier");
|
|
84
|
+
const input = numberField(longContext, "input");
|
|
85
|
+
const output = numberField(longContext, "output");
|
|
86
|
+
const cacheRead = numberField(longContext, "cacheRead");
|
|
87
|
+
const cacheWrite = numberField(longContext, "cacheWrite");
|
|
88
|
+
const base = model.cost;
|
|
89
|
+
const hasTokenPrice = base.input !== 0 || base.output !== 0 || base.cacheRead !== 0 || base.cacheWrite !== 0;
|
|
90
|
+
if (inputThreshold !== undefined && multiplier !== undefined && hasTokenPrice) {
|
|
91
|
+
// Multiplier form: tier rates derive from the row's live list price.
|
|
92
|
+
model.cost = {
|
|
93
|
+
...base,
|
|
94
|
+
longContext: {
|
|
95
|
+
inputThreshold,
|
|
96
|
+
...(inclusive && { inputThresholdInclusive: true }),
|
|
97
|
+
input: base.input * multiplier,
|
|
98
|
+
output: base.output * multiplier,
|
|
99
|
+
cacheRead: base.cacheRead * multiplier,
|
|
100
|
+
cacheWrite: base.cacheWrite * multiplier,
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
} else if (
|
|
104
|
+
inputThreshold !== undefined &&
|
|
105
|
+
input !== undefined &&
|
|
106
|
+
output !== undefined &&
|
|
107
|
+
cacheRead !== undefined &&
|
|
108
|
+
cacheWrite !== undefined
|
|
109
|
+
) {
|
|
110
|
+
model.cost = { ...model.cost, longContext: { inputThreshold, input, output, cacheRead, cacheWrite } };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const patch = objectPayload(catalog.costPatch);
|
|
114
|
+
if (patch !== undefined) {
|
|
115
|
+
model.cost = { ...model.cost };
|
|
116
|
+
const input = numberField(patch, "input");
|
|
117
|
+
if (input !== undefined) model.cost.input = input;
|
|
118
|
+
const output = numberField(patch, "output");
|
|
119
|
+
if (output !== undefined) model.cost.output = output;
|
|
120
|
+
const cacheRead = numberField(patch, "cacheRead");
|
|
121
|
+
if (cacheRead !== undefined) model.cost.cacheRead = cacheRead;
|
|
122
|
+
const cacheWrite = numberField(patch, "cacheWrite");
|
|
123
|
+
if (cacheWrite !== undefined) model.cost.cacheWrite = cacheWrite;
|
|
124
|
+
}
|
|
125
|
+
const limitsPatch = objectPayload(catalog.limitsPatch);
|
|
126
|
+
if (limitsPatch !== undefined) {
|
|
127
|
+
const contextWindow = numberField(limitsPatch, "contextWindow");
|
|
128
|
+
if (contextWindow !== undefined) model.contextWindow = contextWindow;
|
|
129
|
+
const maxTokens = numberField(limitsPatch, "maxTokens");
|
|
130
|
+
if (maxTokens !== undefined) model.maxTokens = maxTokens;
|
|
131
|
+
}
|
|
132
|
+
const contextWindowFloor = catalog.contextWindowFloor;
|
|
133
|
+
if (typeof contextWindowFloor === "number") {
|
|
134
|
+
model.contextWindow = Math.max(model.contextWindow ?? 0, contextWindowFloor);
|
|
135
|
+
}
|
|
136
|
+
const inputModalities = catalog.inputModalities;
|
|
137
|
+
if (isInputModalities(inputModalities)) {
|
|
138
|
+
model.input = inputModalities;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Direct first-party OpenAI Responses endpoints (api.openai.com, Azure OpenAI
|
|
144
|
+
* deployments). Gates GA computer-use detection; identity supplies the model
|
|
145
|
+
* generation.
|
|
146
|
+
*/
|
|
24
147
|
function isDirectOpenAIResponsesEndpoint(spec: ModelSpec<Api>): boolean {
|
|
25
148
|
if (spec.api === "openai-responses") {
|
|
26
149
|
if (spec.provider !== "openai") return false;
|
|
@@ -48,16 +171,27 @@ function isDirectOpenAIResponsesEndpoint(spec: ModelSpec<Api>): boolean {
|
|
|
48
171
|
}
|
|
49
172
|
|
|
50
173
|
function explicitComputerUseConfig(spec: ModelSpec<Api>): boolean | undefined {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
174
|
+
if (!("supportsComputerUseConfig" in spec)) return spec.supportsComputerUse;
|
|
175
|
+
const value: unknown = Reflect.get(spec, "supportsComputerUseConfig");
|
|
176
|
+
return typeof value === "boolean" ? value : undefined;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function revisionAtLeast(identity: ModelIdentity, major: number, minor: number): boolean {
|
|
180
|
+
if (identity.revision === undefined) return false;
|
|
181
|
+
const [revMajor = 0, revMinor = 0] = identity.revision.split(".").map(Number);
|
|
182
|
+
return revMajor > major || (revMajor === major && revMinor >= minor);
|
|
54
183
|
}
|
|
55
184
|
|
|
56
|
-
function supportsOpenAIGAComputerUse(
|
|
185
|
+
function supportsOpenAIGAComputerUse(
|
|
186
|
+
spec: ModelSpec<Api>,
|
|
187
|
+
identity: ModelIdentity,
|
|
188
|
+
explicitSupport: boolean | undefined,
|
|
189
|
+
): boolean {
|
|
57
190
|
if (explicitSupport !== undefined) return explicitSupport;
|
|
58
191
|
if (!isDirectOpenAIResponsesEndpoint(spec)) return false;
|
|
59
|
-
const
|
|
60
|
-
|
|
192
|
+
const wireIdentity =
|
|
193
|
+
spec.requestModelId === undefined ? identity : resolveModelPolicy({ ...spec, id: spec.requestModelId }).identity;
|
|
194
|
+
return wireIdentity.class === "openai" && revisionAtLeast(wireIdentity, 5, 4);
|
|
61
195
|
}
|
|
62
196
|
|
|
63
197
|
/**
|
|
@@ -66,38 +200,21 @@ function supportsOpenAIGAComputerUse(spec: ModelSpec<Api>, explicitSupport: bool
|
|
|
66
200
|
* this only runs for discovered/custom/override specs.
|
|
67
201
|
*/
|
|
68
202
|
export function buildModel<TApi extends Api>(spec: ModelSpec<TApi>): Model<TApi> {
|
|
69
|
-
const
|
|
203
|
+
const policy = resolveModelPolicy(spec);
|
|
70
204
|
const supportsComputerUseConfig = explicitComputerUseConfig(spec);
|
|
71
|
-
|
|
205
|
+
const model: Model<TApi> = {
|
|
72
206
|
...spec,
|
|
73
207
|
name: cleanModelName(spec.name),
|
|
74
|
-
|
|
208
|
+
identity: policy.identity,
|
|
209
|
+
requiresGlyphTokenization: policy.identity.class === "anthropic",
|
|
75
210
|
tokenizer: spec.tokenizer ?? resolveModelTokenizer(spec.requestModelId ?? spec.id),
|
|
76
|
-
thinking:
|
|
77
|
-
supportsComputerUse: supportsOpenAIGAComputerUse(spec, supportsComputerUseConfig),
|
|
211
|
+
thinking: policy.thinking,
|
|
212
|
+
supportsComputerUse: supportsOpenAIGAComputerUse(spec, policy.identity, supportsComputerUseConfig),
|
|
78
213
|
supportsComputerUseConfig,
|
|
79
|
-
compat,
|
|
214
|
+
compat: policy.compat,
|
|
80
215
|
compatConfig: spec.compat,
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
switch (spec.api) {
|
|
86
|
-
case "openrouter":
|
|
87
|
-
return buildOpenRouterCompat(spec as ModelSpec<"openrouter">);
|
|
88
|
-
case "openai-completions":
|
|
89
|
-
return buildOpenAICompat(spec as ModelSpec<"openai-completions">);
|
|
90
|
-
case "openai-responses":
|
|
91
|
-
case "azure-openai-responses":
|
|
92
|
-
case "openai-codex-responses":
|
|
93
|
-
return buildOpenAIResponsesCompat(spec as ModelSpec<"openai-responses">);
|
|
94
|
-
case "anthropic-messages":
|
|
95
|
-
return buildAnthropicCompat(spec as ModelSpec<"anthropic-messages">);
|
|
96
|
-
case "bedrock-converse-stream":
|
|
97
|
-
return buildBedrockCompat(spec as ModelSpec<"bedrock-converse-stream">);
|
|
98
|
-
case "devin-agent":
|
|
99
|
-
return buildDevinCompat(spec as ModelSpec<"devin-agent">);
|
|
100
|
-
default:
|
|
101
|
-
return undefined;
|
|
102
|
-
}
|
|
216
|
+
};
|
|
217
|
+
applyCatalogAssignments(model, policy.catalog);
|
|
218
|
+
applyCatalogCorrections(model, policy.catalog);
|
|
219
|
+
return model;
|
|
103
220
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const CLINEPASS_WIRE_PREFIX = "cline-pass/";
|
|
2
|
+
|
|
3
|
+
/** Convert a public ClinePass catalog id to the gateway's wire id. */
|
|
4
|
+
export function toClinePassWireModelId(modelId: string): string {
|
|
5
|
+
return modelId.startsWith(CLINEPASS_WIRE_PREFIX) ? modelId : `${CLINEPASS_WIRE_PREFIX}${modelId}`;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/** Convert a gateway ClinePass wire id to the public catalog id. */
|
|
9
|
+
export function toClinePassPublicModelId(modelId: string): string {
|
|
10
|
+
return modelId.startsWith(CLINEPASS_WIRE_PREFIX) ? modelId.slice(CLINEPASS_WIRE_PREFIX.length) : modelId;
|
|
11
|
+
}
|
package/src/compat/anthropic.ts
CHANGED
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Anthropic-
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Anthropic endpoint-shape predicates: which URLs are the official first-party
|
|
3
|
+
* API, and which non-official hosts enforce Anthropic's thinking-signature
|
|
4
|
+
* protocol on replay. Compat resolution (`./resolve`) and runtime routing in
|
|
5
|
+
* pi-ai both consume these; URL matching is the one detection surface that
|
|
6
|
+
* stays in code.
|
|
6
7
|
*/
|
|
7
|
-
import { hostMatchesUrl
|
|
8
|
-
import {
|
|
9
|
-
hasOpus47ApiRestrictions,
|
|
10
|
-
isAnthropicFableOrMythosModel,
|
|
11
|
-
isKimiK3ModelId,
|
|
12
|
-
supportsMidConversationSystemMessages,
|
|
13
|
-
} from "../identity/family";
|
|
14
|
-
import type { ModelSpec, ResolvedAnthropicCompat } from "../types";
|
|
15
|
-
import { applyCompatOverrides } from "./apply";
|
|
8
|
+
import { hostMatchesUrl } from "../hosts";
|
|
16
9
|
|
|
17
10
|
const OFFICIAL_ANTHROPIC_URL = "https://api.anthropic.com";
|
|
18
11
|
|
|
@@ -29,75 +22,25 @@ export function isOfficialAnthropicApiUrl(baseUrl?: string): boolean {
|
|
|
29
22
|
return lower === OFFICIAL_ANTHROPIC_URL || lower.startsWith(`${OFFICIAL_ANTHROPIC_URL}/`);
|
|
30
23
|
}
|
|
31
24
|
|
|
32
|
-
/**
|
|
33
|
-
* Kimi models whose native endpoints (api.kimi.com, api.moonshot.ai) keep
|
|
34
|
-
* thinking enabled server-side no matter what the request carries: they
|
|
35
|
-
* reject disabled thinking (#3852) AND reject forced tool_choice
|
|
36
|
-
* (`tool_choice 'specified' is incompatible with thinking enabled`), so compat
|
|
37
|
-
* must keep thinking on and downgrade forced choices to `auto`. Covers the
|
|
38
|
-
* K2.7 Code family — public id, its Highspeed variant, and the kimi-code
|
|
39
|
-
* `kimi-for-coding[-highspeed]` aliases — plus K3 (`kimi-k3`, bare `k3` on
|
|
40
|
-
* kimi-code). Broader than the `compat/openai.ts` mirror: the OpenAI surface
|
|
41
|
-
* has its own per-dialect policies (K3 forced-choice guard, explicit disable
|
|
42
|
-
* shapes), while this surface has no working way to force a tool.
|
|
43
|
-
* Native-only host gating is the caller's responsibility.
|
|
44
|
-
*/
|
|
45
|
-
const KIMI_K27_CODE_MODEL_PATTERN = /(?:^|\/)kimi[-._]?k2(?:[._-]?|p)7[-._]?code(?:[-._]?highspeed)?$/i;
|
|
46
|
-
|
|
47
|
-
function matchesKimiMandatoryThinkingModel(spec: ModelSpec<"anthropic-messages">): boolean {
|
|
48
|
-
if (KIMI_K27_CODE_MODEL_PATTERN.test(spec.id)) return true;
|
|
49
|
-
if (spec.id === "kimi-for-coding" || spec.id === "kimi-for-coding-highspeed") return true;
|
|
50
|
-
return isKimiK3ModelId(spec.id) || spec.id === "k3";
|
|
51
|
-
}
|
|
52
|
-
|
|
53
25
|
const CLOUDFLARE_ANTHROPIC_GATEWAY_URL_MARKER = /gateway\.ai\.cloudflare\.com\/.+\/anthropic(?:\/|$)/i;
|
|
54
26
|
const VERTEX_ANTHROPIC_URL_MARKER = /aiplatform\.googleapis\.com\/.+\/publishers\/anthropic\//i;
|
|
55
27
|
const BEDROCK_ANTHROPIC_URL_MARKER = /(?:^|\/\/|\.)bedrock-runtime\.[a-z0-9-]+\.amazonaws\.com/i;
|
|
56
28
|
const AZURE_ANTHROPIC_URL_MARKER = /(?:^|\/\/|\.)[a-z0-9-]+\.(?:inference|services)\.ai\.azure\.com/i;
|
|
57
29
|
|
|
58
|
-
/**
|
|
59
|
-
* Cloudflare AI Gateway's `/anthropic` route forwards to signature-enforcing
|
|
60
|
-
* Anthropic (same failure class as GitHub Copilot #2851 / ZenMux #4192).
|
|
61
|
-
* Detection is by baseUrl marker rather than provider id: users routinely
|
|
62
|
-
* declare `provider: "custom"` (or other free-form ids) in `models.yml` for
|
|
63
|
-
* their own Cloudflare gateway account.
|
|
64
|
-
*/
|
|
65
|
-
function isCloudflareAnthropicGateway(baseUrl?: string): boolean {
|
|
66
|
-
return baseUrl !== undefined && CLOUDFLARE_ANTHROPIC_GATEWAY_URL_MARKER.test(baseUrl);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Google Vertex's `publishers/anthropic/models/…:streamRawPredict` route
|
|
71
|
-
* proxies Claude through Google's identity layer and returns full thinking
|
|
72
|
-
* signatures, so it is a SIGNING endpoint.
|
|
73
|
-
*/
|
|
74
|
-
function isVertexAnthropicRoute(baseUrl?: string): boolean {
|
|
75
|
-
return baseUrl !== undefined && VERTEX_ANTHROPIC_URL_MARKER.test(baseUrl);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* AWS Bedrock's Anthropic route (`bedrock-runtime.<region>.amazonaws.com`)
|
|
80
|
-
* forwards Claude requests through Anthropic's signature protocol. Users can
|
|
81
|
-
* front Bedrock with a custom `anthropic-messages` provider entry in
|
|
82
|
-
* `models.yml`; the URL marker makes those signing by default without
|
|
83
|
-
* requiring a provider-id list.
|
|
84
|
-
*/
|
|
85
|
-
function isBedrockAnthropicRoute(baseUrl?: string): boolean {
|
|
86
|
-
return baseUrl !== undefined && BEDROCK_ANTHROPIC_URL_MARKER.test(baseUrl);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
30
|
/**
|
|
90
31
|
* Azure AI Inference / Foundry Anthropic route
|
|
91
32
|
* (`<resource>.inference.ai.azure.com`, `<resource>.services.ai.azure.com`).
|
|
92
33
|
* Fronts Claude behind Azure identity and enforces Anthropic signatures on
|
|
93
|
-
* replay.
|
|
34
|
+
* replay; it also rejects the top-level `strict` tool field.
|
|
94
35
|
*/
|
|
95
|
-
function isAzureAnthropicRoute(baseUrl?: string): boolean {
|
|
36
|
+
export function isAzureAnthropicRoute(baseUrl?: string): boolean {
|
|
96
37
|
return baseUrl !== undefined && AZURE_ANTHROPIC_URL_MARKER.test(baseUrl);
|
|
97
38
|
}
|
|
98
39
|
|
|
99
40
|
/**
|
|
100
|
-
* Known non-official URLs that enforce Anthropic thinking signatures on replay
|
|
41
|
+
* Known non-official URLs that enforce Anthropic thinking signatures on replay
|
|
42
|
+
* (GitHub Copilot, ZenMux, Cloudflare AI Gateway `/anthropic`, Google Vertex
|
|
43
|
+
* `publishers/anthropic`, AWS Bedrock, Azure Foundry).
|
|
101
44
|
*
|
|
102
45
|
* Runtime routing calls this with the effective URL because a model's resolved
|
|
103
46
|
* compat can be stale after Foundry or a provider base-URL override reroutes it.
|
|
@@ -106,74 +49,10 @@ export function isAnthropicSigningProxyUrl(baseUrl?: string): boolean {
|
|
|
106
49
|
return (
|
|
107
50
|
hostMatchesUrl(baseUrl, "githubCopilot") ||
|
|
108
51
|
hostMatchesUrl(baseUrl, "zenmux") ||
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
52
|
+
(baseUrl !== undefined &&
|
|
53
|
+
(CLOUDFLARE_ANTHROPIC_GATEWAY_URL_MARKER.test(baseUrl) ||
|
|
54
|
+
VERTEX_ANTHROPIC_URL_MARKER.test(baseUrl) ||
|
|
55
|
+
BEDROCK_ANTHROPIC_URL_MARKER.test(baseUrl))) ||
|
|
112
56
|
isAzureAnthropicRoute(baseUrl)
|
|
113
57
|
);
|
|
114
58
|
}
|
|
115
|
-
|
|
116
|
-
/** Build the resolved anthropic-messages compat record for a model spec. */
|
|
117
|
-
export function buildAnthropicCompat(spec: ModelSpec<"anthropic-messages">): ResolvedAnthropicCompat {
|
|
118
|
-
const baseUrl = spec.baseUrl;
|
|
119
|
-
const official = isOfficialAnthropicApiUrl(baseUrl);
|
|
120
|
-
// Z.AI's Anthropic-compatible proxy lives at `api.z.ai/api/anthropic`.
|
|
121
|
-
const isZai = modelMatchesHost(spec, "zai");
|
|
122
|
-
// GitHub Copilot's `anthropic-messages` proxy (api.githubcopilot.com/v1/messages)
|
|
123
|
-
// rejects the per-tool `eager_input_streaming` field with
|
|
124
|
-
// `tools.0.custom.eager_input_streaming: Extra inputs are not permitted` and
|
|
125
|
-
// doesn't whitelist the `fine-grained-tool-streaming-2025-05-14` beta either
|
|
126
|
-
// (issue #2558), so eager tool-input streaming is unavailable on this host.
|
|
127
|
-
const isCopilot = modelMatchesHost(spec, "githubCopilot");
|
|
128
|
-
// ZenMux's `anthropic-messages` route (zenmux.ai/api/anthropic) forwards to
|
|
129
|
-
// signature-enforcing Anthropic — same failure class as GitHub Copilot #2851
|
|
130
|
-
// (issue #4192).
|
|
131
|
-
const isZenmux = modelMatchesHost(spec, "zenmux");
|
|
132
|
-
const requiresThinkingEnabled = modelMatchesHost(spec, "moonshotNative") && matchesKimiMandatoryThinkingModel(spec);
|
|
133
|
-
const isAzure = isAzureAnthropicRoute(baseUrl);
|
|
134
|
-
const signingEndpoint = official || isCopilot || isZenmux || isAnthropicSigningProxyUrl(baseUrl);
|
|
135
|
-
const compat: ResolvedAnthropicCompat = {
|
|
136
|
-
officialEndpoint: official,
|
|
137
|
-
signingEndpoint,
|
|
138
|
-
disableStrictTools: isAzure,
|
|
139
|
-
disableAdaptiveThinking: false,
|
|
140
|
-
allowAnthropicHeaderOverrides: false,
|
|
141
|
-
supportsEagerToolInputStreaming: official,
|
|
142
|
-
// Long cache retention is only sent to the official API by default;
|
|
143
|
-
// proxies opt in explicitly via `compat.supportsLongCacheRetention: true`.
|
|
144
|
-
supportsLongCacheRetention: official,
|
|
145
|
-
// First-party Claude API only. Bedrock/Vertex/Foundry and other
|
|
146
|
-
// Anthropic-compatible gateways reject mid-conversation system roles, so
|
|
147
|
-
// detection requires the canonical api.anthropic.com host plus a
|
|
148
|
-
// supported model id.
|
|
149
|
-
supportsMidConversationSystem: official && supportsMidConversationSystemMessages(spec.id),
|
|
150
|
-
supportsForcedToolChoice: !requiresThinkingEnabled && !isAnthropicFableOrMythosModel(spec.id),
|
|
151
|
-
// Opus 4.7+ and Fable/Mythos reject temperature/top_p/top_k with a 400.
|
|
152
|
-
supportsSamplingParams: !hasOpus47ApiRestrictions(spec.id),
|
|
153
|
-
// Z.AI workaround (issue #814): its proxy deserializes tool_result blocks
|
|
154
|
-
// into a class that reads `.id`.
|
|
155
|
-
requiresToolResultId: isZai,
|
|
156
|
-
requiresThinkingEnabled,
|
|
157
|
-
// Official Anthropic and Anthropic-compatible signing proxies enforce
|
|
158
|
-
// signature-based thinking-chain integrity, so unsigned thinking blocks
|
|
159
|
-
// must stay text there. Every other `anthropic-messages` reasoning
|
|
160
|
-
// endpoint replays unsigned thinking natively so the reasoning chain
|
|
161
|
-
// survives continuation and doesn't destabilize the next tool-call
|
|
162
|
-
// arguments (#2005, #2257, #2265, #3288, #3433, #3434). Opaque custom
|
|
163
|
-
// signing proxies remain the reporter's responsibility to mark with
|
|
164
|
-
// `compat.replayUnsignedThinking: false`; the transport surfaces a
|
|
165
|
-
// pointed remediation the first time the signing 400 fires (#4297).
|
|
166
|
-
//
|
|
167
|
-
// Known signing Anthropic-messages hosts (Copilot, ZenMux, Cloudflare
|
|
168
|
-
// AI Gateway `/anthropic`, Google Vertex `publishers/anthropic`, AWS
|
|
169
|
-
// Bedrock `bedrock-runtime.<region>.amazonaws.com`, and Azure
|
|
170
|
-
// AI Inference / Foundry `<res>.(inference|services).ai.azure.com`)
|
|
171
|
-
// are excluded automatically because they can be recognised by provider
|
|
172
|
-
// id or baseUrl marker.
|
|
173
|
-
replayUnsignedThinking: !signingEndpoint && (Boolean(spec.reasoning) || modelMatchesHost(spec, "deepseekFamily")),
|
|
174
|
-
escapeBuiltinToolNames: modelMatchesHost(spec, "umans"),
|
|
175
|
-
streamIdleTimeoutMs: spec.compat?.streamIdleTimeoutMs,
|
|
176
|
-
};
|
|
177
|
-
applyCompatOverrides(compat, spec.compat);
|
|
178
|
-
return compat;
|
|
179
|
-
}
|