@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.
Files changed (287) hide show
  1. package/CHANGELOG.md +8 -8
  2. package/README.md +9 -8
  3. package/dist/types/build.d.ts +13 -8
  4. package/dist/types/cline-pass-model-id.d.ts +4 -0
  5. package/dist/types/compat/anthropic.d.ts +10 -4
  6. package/dist/types/compat/auth-ids.d.ts +4 -0
  7. package/dist/types/compat/auth.d.ts +7 -0
  8. package/dist/types/compat/axes.d.ts +50 -0
  9. package/dist/types/compat/behavior.d.ts +69 -0
  10. package/dist/types/compat/cascade.d.ts +37 -0
  11. package/dist/types/{variant-collapse.d.ts → compat/collapse.d.ts} +60 -35
  12. package/dist/types/compat/openai.d.ts +7 -26
  13. package/dist/types/compat/resolve.d.ts +15 -0
  14. package/dist/types/compat/revision.d.ts +41 -0
  15. package/dist/types/compat/taxonomy.d.ts +93 -0
  16. package/dist/types/compat/types.d.ts +565 -0
  17. package/dist/types/discovery/antigravity.d.ts +1 -1
  18. package/dist/types/discovery/cursor-proto.d.ts +6 -6
  19. package/dist/types/discovery/cursor.d.ts +5 -3
  20. package/dist/types/discovery/devin-proto.d.ts +363 -0
  21. package/dist/types/discovery/gemini-cli.d.ts +1 -1
  22. package/dist/types/identity/id.d.ts +1 -0
  23. package/dist/types/identity/index.d.ts +3 -3
  24. package/dist/types/identity/reference.d.ts +0 -10
  25. package/dist/types/index.d.ts +1 -1
  26. package/dist/types/model-thinking.d.ts +6 -24
  27. package/dist/types/provider-models/cline-pass.d.ts +22 -0
  28. package/dist/types/provider-models/descriptors.d.ts +20 -1
  29. package/dist/types/provider-models/models-dev-policies.d.ts +2 -1
  30. package/dist/types/provider-models/openai-compat.d.ts +59 -46
  31. package/dist/types/provider-models/special.d.ts +23 -2
  32. package/dist/types/types.d.ts +177 -13
  33. package/dist/types/wire/cline-pass.d.ts +21 -0
  34. package/dist/types/wire/devin-proto.d.ts +14 -0
  35. package/dist/types/wire/devin.d.ts +36 -0
  36. package/dist/types/wire/github-copilot.d.ts +31 -12
  37. package/package.json +6 -4
  38. package/src/build.ts +165 -48
  39. package/src/cline-pass-model-id.ts +11 -0
  40. package/src/compat/anthropic.ts +15 -136
  41. package/src/compat/auth-ids.ts +157 -0
  42. package/src/compat/auth.ts +60 -0
  43. package/src/compat/axes.ts +290 -0
  44. package/src/compat/behavior.ts +207 -0
  45. package/src/compat/cascade.ts +230 -0
  46. package/src/{variant-collapse.ts → compat/collapse.ts} +381 -773
  47. package/src/compat/openai.ts +17 -848
  48. package/src/compat/resolve.ts +1229 -0
  49. package/src/compat/revision.ts +154 -0
  50. package/src/compat/rules/README.md +315 -0
  51. package/src/compat/rules/auth/_order.kdl +13 -0
  52. package/src/compat/rules/auth/abliteration.kdl +9 -0
  53. package/src/compat/rules/auth/aiand.kdl +9 -0
  54. package/src/compat/rules/auth/aimlapi.kdl +3 -0
  55. package/src/compat/rules/auth/alibaba-coding-plan.kdl +5 -0
  56. package/src/compat/rules/auth/alibaba-token-plan.kdl +11 -0
  57. package/src/compat/rules/auth/amazon-bedrock.kdl +5 -0
  58. package/src/compat/rules/auth/anthropic.kdl +53 -0
  59. package/src/compat/rules/auth/azure.kdl +3 -0
  60. package/src/compat/rules/auth/baseten.kdl +9 -0
  61. package/src/compat/rules/auth/bedrock-mantle.kdl +5 -0
  62. package/src/compat/rules/auth/cerebras.kdl +9 -0
  63. package/src/compat/rules/auth/cline-pass.kdl +12 -0
  64. package/src/compat/rules/auth/cloudflare-ai-gateway.kdl +4 -0
  65. package/src/compat/rules/auth/coreweave.kdl +9 -0
  66. package/src/compat/rules/auth/cursor.kdl +5 -0
  67. package/src/compat/rules/auth/deepinfra.kdl +11 -0
  68. package/src/compat/rules/auth/deepseek.kdl +10 -0
  69. package/src/compat/rules/auth/devin.kdl +28 -0
  70. package/src/compat/rules/auth/exa.kdl +9 -0
  71. package/src/compat/rules/auth/firepass.kdl +14 -0
  72. package/src/compat/rules/auth/fireworks.kdl +16 -0
  73. package/src/compat/rules/auth/github-copilot.kdl +7 -0
  74. package/src/compat/rules/auth/gitlab-duo-agent.kdl +23 -0
  75. package/src/compat/rules/auth/gitlab-duo.kdl +24 -0
  76. package/src/compat/rules/auth/gmi-cloud.kdl +9 -0
  77. package/src/compat/rules/auth/google-antigravity.kdl +28 -0
  78. package/src/compat/rules/auth/google-gemini-cli.kdl +26 -0
  79. package/src/compat/rules/auth/google-vertex.kdl +5 -0
  80. package/src/compat/rules/auth/google.kdl +3 -0
  81. package/src/compat/rules/auth/groq.kdl +3 -0
  82. package/src/compat/rules/auth/huggingface.kdl +9 -0
  83. package/src/compat/rules/auth/kagi.kdl +9 -0
  84. package/src/compat/rules/auth/kilo.kdl +4 -0
  85. package/src/compat/rules/auth/kimi-code.kdl +18 -0
  86. package/src/compat/rules/auth/litellm.kdl +8 -0
  87. package/src/compat/rules/auth/llama.cpp.kdl +10 -0
  88. package/src/compat/rules/auth/lm-studio.kdl +7 -0
  89. package/src/compat/rules/auth/meta.kdl +9 -0
  90. package/src/compat/rules/auth/minimax-code-cn.kdl +9 -0
  91. package/src/compat/rules/auth/minimax-code.kdl +9 -0
  92. package/src/compat/rules/auth/minimax.kdl +3 -0
  93. package/src/compat/rules/auth/mistral.kdl +3 -0
  94. package/src/compat/rules/auth/moonshot.kdl +9 -0
  95. package/src/compat/rules/auth/nanogpt.kdl +9 -0
  96. package/src/compat/rules/auth/novita.kdl +12 -0
  97. package/src/compat/rules/auth/nvidia.kdl +11 -0
  98. package/src/compat/rules/auth/ollama-cloud.kdl +8 -0
  99. package/src/compat/rules/auth/ollama.kdl +9 -0
  100. package/src/compat/rules/auth/openai-codex-device.kdl +20 -0
  101. package/src/compat/rules/auth/openai-codex.kdl +33 -0
  102. package/src/compat/rules/auth/openai.kdl +3 -0
  103. package/src/compat/rules/auth/opencode-go.kdl +10 -0
  104. package/src/compat/rules/auth/opencode-zen.kdl +9 -0
  105. package/src/compat/rules/auth/openrouter.kdl +32 -0
  106. package/src/compat/rules/auth/parallel.kdl +9 -0
  107. package/src/compat/rules/auth/perplexity.kdl +7 -0
  108. package/src/compat/rules/auth/qianfan.kdl +9 -0
  109. package/src/compat/rules/auth/qwen-portal.kdl +9 -0
  110. package/src/compat/rules/auth/sakana.kdl +9 -0
  111. package/src/compat/rules/auth/siliconflow-cn.kdl +9 -0
  112. package/src/compat/rules/auth/siliconflow.kdl +9 -0
  113. package/src/compat/rules/auth/synthetic.kdl +9 -0
  114. package/src/compat/rules/auth/tavily.kdl +9 -0
  115. package/src/compat/rules/auth/together.kdl +14 -0
  116. package/src/compat/rules/auth/umans.kdl +9 -0
  117. package/src/compat/rules/auth/venice.kdl +9 -0
  118. package/src/compat/rules/auth/vercel-ai-gateway.kdl +8 -0
  119. package/src/compat/rules/auth/vllm.kdl +9 -0
  120. package/src/compat/rules/auth/wafer-serverless.kdl +11 -0
  121. package/src/compat/rules/auth/xai-oauth.kdl +27 -0
  122. package/src/compat/rules/auth/xai.kdl +9 -0
  123. package/src/compat/rules/auth/xiaomi-token-plan-ams.kdl +9 -0
  124. package/src/compat/rules/auth/xiaomi-token-plan-cn.kdl +9 -0
  125. package/src/compat/rules/auth/xiaomi-token-plan-sgp.kdl +9 -0
  126. package/src/compat/rules/auth/xiaomi.kdl +6 -0
  127. package/src/compat/rules/auth/yolo-auto.kdl +11 -0
  128. package/src/compat/rules/auth/zai-coding-plan.kdl +29 -0
  129. package/src/compat/rules/auth/zai.kdl +9 -0
  130. package/src/compat/rules/auth/zenmux.kdl +9 -0
  131. package/src/compat/rules/auth/zhipu-coding-plan.kdl +9 -0
  132. package/src/compat/rules/classes/amazon.kdl +21 -0
  133. package/src/compat/rules/classes/anthropic.kdl +285 -0
  134. package/src/compat/rules/classes/baidu.kdl +9 -0
  135. package/src/compat/rules/classes/bytedance.kdl +9 -0
  136. package/src/compat/rules/classes/cohere.kdl +7 -0
  137. package/src/compat/rules/classes/deepseek.kdl +80 -0
  138. package/src/compat/rules/classes/gemini.kdl +107 -0
  139. package/src/compat/rules/classes/gemma.kdl +14 -0
  140. package/src/compat/rules/classes/glm.kdl +115 -0
  141. package/src/compat/rules/classes/gpt-oss.kdl +16 -0
  142. package/src/compat/rules/classes/kimi.kdl +113 -0
  143. package/src/compat/rules/classes/meta.kdl +15 -0
  144. package/src/compat/rules/classes/mimo.kdl +32 -0
  145. package/src/compat/rules/classes/minimax.kdl +79 -0
  146. package/src/compat/rules/classes/mistral.kdl +19 -0
  147. package/src/compat/rules/classes/openai.kdl +42 -0
  148. package/src/compat/rules/classes/qwen.kdl +72 -0
  149. package/src/compat/rules/classes/stepfun.kdl +10 -0
  150. package/src/compat/rules/classes/xai.kdl +45 -0
  151. package/src/compat/rules/providers/abliteration.kdl +8 -0
  152. package/src/compat/rules/providers/aiand.kdl +19 -0
  153. package/src/compat/rules/providers/aimlapi.kdl +24 -0
  154. package/src/compat/rules/providers/alibaba-coding-plan.kdl +20 -0
  155. package/src/compat/rules/providers/alibaba-token-plan.kdl +35 -0
  156. package/src/compat/rules/providers/amazon-bedrock.kdl +36 -0
  157. package/src/compat/rules/providers/anthropic.kdl +24 -0
  158. package/src/compat/rules/providers/azure.kdl +19 -0
  159. package/src/compat/rules/providers/baseten.kdl +19 -0
  160. package/src/compat/rules/providers/bedrock-mantle.kdl +15 -0
  161. package/src/compat/rules/providers/cerebras.kdl +19 -0
  162. package/src/compat/rules/providers/cline-pass.kdl +8 -0
  163. package/src/compat/rules/providers/cloudflare-ai-gateway.kdl +26 -0
  164. package/src/compat/rules/providers/coreweave.kdl +16 -0
  165. package/src/compat/rules/providers/cursor.kdl +52 -0
  166. package/src/compat/rules/providers/deepseek.kdl +21 -0
  167. package/src/compat/rules/providers/firepass.kdl +15 -0
  168. package/src/compat/rules/providers/fireworks.kdl +43 -0
  169. package/src/compat/rules/providers/github-copilot.kdl +62 -0
  170. package/src/compat/rules/providers/gitlab-duo.kdl +24 -0
  171. package/src/compat/rules/providers/gmi-cloud.kdl +8 -0
  172. package/src/compat/rules/providers/google-antigravity.kdl +59 -0
  173. package/src/compat/rules/providers/google-gemini-cli.kdl +12 -0
  174. package/src/compat/rules/providers/google-vertex.kdl +25 -0
  175. package/src/compat/rules/providers/google.kdl +17 -0
  176. package/src/compat/rules/providers/groq.kdl +8 -0
  177. package/src/compat/rules/providers/huggingface.kdl +24 -0
  178. package/src/compat/rules/providers/kilo.kdl +51 -0
  179. package/src/compat/rules/providers/kimi-code.kdl +37 -0
  180. package/src/compat/rules/providers/llama.cpp.kdl +6 -0
  181. package/src/compat/rules/providers/lm-studio.kdl +6 -0
  182. package/src/compat/rules/providers/meta.kdl +10 -0
  183. package/src/compat/rules/providers/minimax-code-cn.kdl +13 -0
  184. package/src/compat/rules/providers/minimax-code.kdl +13 -0
  185. package/src/compat/rules/providers/minimax.kdl +6 -0
  186. package/src/compat/rules/providers/mistral.kdl +8 -0
  187. package/src/compat/rules/providers/moonshot.kdl +36 -0
  188. package/src/compat/rules/providers/nanogpt.kdl +100 -0
  189. package/src/compat/rules/providers/novita.kdl +34 -0
  190. package/src/compat/rules/providers/nvidia.kdl +27 -0
  191. package/src/compat/rules/providers/ollama-cloud.kdl +20 -0
  192. package/src/compat/rules/providers/ollama.kdl +12 -0
  193. package/src/compat/rules/providers/openai-codex.kdl +121 -0
  194. package/src/compat/rules/providers/openai.kdl +82 -0
  195. package/src/compat/rules/providers/opencode-go.kdl +97 -0
  196. package/src/compat/rules/providers/opencode-zen.kdl +103 -0
  197. package/src/compat/rules/providers/openrouter.kdl +66 -0
  198. package/src/compat/rules/providers/qianfan.kdl +8 -0
  199. package/src/compat/rules/providers/sakana.kdl +10 -0
  200. package/src/compat/rules/providers/synthetic.kdl +16 -0
  201. package/src/compat/rules/providers/together.kdl +22 -0
  202. package/src/compat/rules/providers/umans.kdl +28 -0
  203. package/src/compat/rules/providers/venice.kdl +46 -0
  204. package/src/compat/rules/providers/vercel-ai-gateway.kdl +73 -0
  205. package/src/compat/rules/providers/vllm.kdl +8 -0
  206. package/src/compat/rules/providers/wafer-serverless.kdl +35 -0
  207. package/src/compat/rules/providers/xai-oauth.kdl +48 -0
  208. package/src/compat/rules/providers/xai.kdl +50 -0
  209. package/src/compat/rules/providers/xiaomi-token-plan-ams.kdl +9 -0
  210. package/src/compat/rules/providers/xiaomi-token-plan-cn.kdl +9 -0
  211. package/src/compat/rules/providers/xiaomi-token-plan-sgp.kdl +9 -0
  212. package/src/compat/rules/providers/xiaomi.kdl +22 -0
  213. package/src/compat/rules/providers/yolo-auto.kdl +16 -0
  214. package/src/compat/rules/providers/zai.kdl +36 -0
  215. package/src/compat/rules/providers/zenmux.kdl +108 -0
  216. package/src/compat/rules/providers/zhipu-coding-plan.kdl +49 -0
  217. package/src/compat/rules/runtime/behavior.kdl +254 -0
  218. package/src/compat/rules/taxonomy/_collapse.kdl +747 -0
  219. package/src/compat/rules/taxonomy/_discovery.kdl +60 -0
  220. package/src/compat/rules/taxonomy/ai21.kdl +6 -0
  221. package/src/compat/rules/taxonomy/amazon.kdl +8 -0
  222. package/src/compat/rules/taxonomy/anthropic.kdl +17 -0
  223. package/src/compat/rules/taxonomy/baidu.kdl +5 -0
  224. package/src/compat/rules/taxonomy/bytedance.kdl +5 -0
  225. package/src/compat/rules/taxonomy/cohere.kdl +6 -0
  226. package/src/compat/rules/taxonomy/deepseek.kdl +18 -0
  227. package/src/compat/rules/taxonomy/gemini.kdl +9 -0
  228. package/src/compat/rules/taxonomy/gemma.kdl +3 -0
  229. package/src/compat/rules/taxonomy/glm.kdl +17 -0
  230. package/src/compat/rules/taxonomy/gpt-oss.kdl +11 -0
  231. package/src/compat/rules/taxonomy/kimi.kdl +20 -0
  232. package/src/compat/rules/taxonomy/meta.kdl +10 -0
  233. package/src/compat/rules/taxonomy/mimo.kdl +7 -0
  234. package/src/compat/rules/taxonomy/minimax.kdl +9 -0
  235. package/src/compat/rules/taxonomy/mistral.kdl +7 -0
  236. package/src/compat/rules/taxonomy/openai.kdl +43 -0
  237. package/src/compat/rules/taxonomy/qwen.kdl +33 -0
  238. package/src/compat/rules/taxonomy/stepfun.kdl +5 -0
  239. package/src/compat/rules/taxonomy/unknown.kdl +3 -0
  240. package/src/compat/rules/taxonomy/xai.kdl +12 -0
  241. package/src/compat/rules.d.json.ts +5 -0
  242. package/src/compat/rules.json +16933 -0
  243. package/src/compat/taxonomy.ts +452 -0
  244. package/src/compat/types.ts +586 -0
  245. package/src/discovery/antigravity.ts +5 -6
  246. package/src/discovery/codex.ts +12 -7
  247. package/src/discovery/cursor-proto.ts +7 -7
  248. package/src/discovery/cursor.ts +47 -58
  249. package/src/discovery/devin-proto.ts +613 -0
  250. package/src/discovery/devin.ts +358 -52
  251. package/src/discovery/gemini-cli.ts +14 -11
  252. package/src/discovery/gemini.ts +2 -0
  253. package/src/identity/dialect.ts +2 -2
  254. package/src/identity/id.ts +12 -0
  255. package/src/identity/index.ts +3 -3
  256. package/src/identity/reference.ts +30 -4
  257. package/src/index.ts +1 -1
  258. package/src/model-manager.ts +4 -4
  259. package/src/model-thinking.ts +6 -810
  260. package/src/model-tokenizer.ts +37 -44
  261. package/src/models.json +86187 -23440
  262. package/src/models.ts +6 -1
  263. package/src/provider-models/bundled-references.ts +3 -1
  264. package/src/provider-models/cline-pass.ts +226 -0
  265. package/src/provider-models/descriptors.ts +18 -0
  266. package/src/provider-models/google.ts +14 -5
  267. package/src/provider-models/models-dev-policies.ts +4 -29
  268. package/src/provider-models/ollama.ts +15 -2
  269. package/src/provider-models/openai-compat.ts +794 -520
  270. package/src/provider-models/special.ts +186 -2
  271. package/src/types.ts +197 -11
  272. package/src/wire/cline-pass.ts +35 -0
  273. package/src/wire/devin-proto.ts +30 -0
  274. package/src/wire/devin.ts +72 -0
  275. package/src/wire/github-copilot.ts +49 -7
  276. package/dist/types/compat/bedrock.d.ts +0 -3
  277. package/dist/types/compat/devin.d.ts +0 -9
  278. package/dist/types/identity/classify.d.ts +0 -69
  279. package/dist/types/identity/family.d.ts +0 -243
  280. package/dist/types/identity/markers.d.ts +0 -4
  281. package/dist/types/openai-pricing.d.ts +0 -17
  282. package/src/compat/bedrock.ts +0 -153
  283. package/src/compat/devin.ts +0 -12
  284. package/src/identity/classify.ts +0 -242
  285. package/src/identity/family.ts +0 -496
  286. package/src/identity/markers.ts +0 -49
  287. 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
- * GitHub Copilot wire metadata: API-key envelope parsing and endpoint
4
- * derivation shared by catalog discovery and the pi-ai OAuth flow. The device
5
- * login / token refresh flow lives in `@linxiraos/pi-ai`'s registry.
6
- */
7
- export declare const COPILOT_USER_AGENT: "opencode/1.3.15";
8
- export declare const OPENCODE_HEADERS: {
9
- readonly "User-Agent": "opencode/1.3.15";
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-06-01";
21
- /** Headers for `api.githubcopilot.com` (capi) requests: discovery, chat, policy. */
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": "opencode/1.3.15";
24
- readonly "X-GitHub-Api-Version": "2026-06-01";
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.7",
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.7",
38
- "@linxiraos/pi-utils": "1.1.7"
38
+ "@linxiraos/pi-omptype": "1.1.8",
39
+ "@linxiraos/pi-utils": "1.1.8"
39
40
  },
40
41
  "devDependencies": {
41
- "@linxiraos/pi-ai": "1.1.7",
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 order is a dependency chain, each
3
- * step materialized exactly once per spec:
4
- *
5
- * 1. compat — URL/provider/id detection resolved into a complete record;
6
- * 2. thinking — derived from identity + resolved compat (or trusted verbatim
7
- * when the spec carries explicit metadata);
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 { buildAnthropicCompat } from "./compat/anthropic";
14
- import { buildBedrockCompat } from "./compat/bedrock";
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, CompatOf, Model, ModelSpec } from "./types";
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
- return "supportsComputerUseConfig" in spec
52
- ? (spec as Model<Api>).supportsComputerUseConfig
53
- : spec.supportsComputerUse;
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(spec: ModelSpec<Api>, explicitSupport: boolean | undefined): boolean {
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 parsed = parseOpenAIModel(bareModelId(spec.requestModelId ?? spec.id));
60
- return parsed !== null && semverGte(parsed.version, "5.4");
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 compat = buildCompat(spec) as CompatOf<TApi>;
203
+ const policy = resolveModelPolicy(spec);
70
204
  const supportsComputerUseConfig = explicitComputerUseConfig(spec);
71
- return {
205
+ const model: Model<TApi> = {
72
206
  ...spec,
73
207
  name: cleanModelName(spec.name),
74
- requiresGlyphTokenization: isClaudeModelId(spec.id),
208
+ identity: policy.identity,
209
+ requiresGlyphTokenization: policy.identity.class === "anthropic",
75
210
  tokenizer: spec.tokenizer ?? resolveModelTokenizer(spec.requestModelId ?? spec.id),
76
- thinking: resolveModelThinking(spec, compat),
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
- } as Model<TApi>;
82
- }
83
-
84
- export function buildCompat(spec: ModelSpec<Api>): CompatOf<Api> {
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
+ }
@@ -1,18 +1,11 @@
1
1
  /**
2
- * Anthropic-messages compat builder — the anthropic-side analogue of
3
- * `./openai`. Runs exactly once per model (from `buildModel`); detect-time
4
- * defaults come from provider ids, strict host checks, and model-id
5
- * classification, with explicit spec overrides assigned on top.
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, modelMatchesHost } from "../hosts";
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
- isCloudflareAnthropicGateway(baseUrl) ||
110
- isVertexAnthropicRoute(baseUrl) ||
111
- isBedrockAnthropicRoute(baseUrl) ||
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
- }