@xiaoso/dsh-tool-plus 0.1.16 → 0.1.17-beta.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.
Files changed (109) hide show
  1. package/lib/{abort-DZ54CaKU.mjs → abort-BTblp0Rt.mjs} +2 -2
  2. package/lib/{alibaba-coding-plan-DODpkcqi.mjs → alibaba-coding-plan-t3R4YKCB.mjs} +3 -3
  3. package/lib/{alibaba-token-plan-C6lpKCda.mjs → alibaba-token-plan-CO4djG1y.mjs} +4 -4
  4. package/lib/{alibaba-token-plan-CHGyWOfX.mjs → alibaba-token-plan-CUjYJX0-.mjs} +1 -1
  5. package/lib/{anthropic-Dv_GGX6g.mjs → anthropic-nf7w6so1.mjs} +48 -21
  6. package/lib/{api-key-validation-MnMf_ihX.mjs → api-key-validation-C_tZ7Y9a.mjs} +2 -2
  7. package/lib/behavior-BwvTUtag.mjs +111 -0
  8. package/lib/{browser-render-BZXt548F.mjs → browser-render-BQaEVK_n.mjs} +4 -4
  9. package/lib/{reference-CtvM4zLU.mjs → bundled-references-CrQ4dQcT.mjs} +57 -4
  10. package/lib/cascade-BWjRTD1q.mjs +30265 -0
  11. package/lib/{cline-pass-BT9CBEOj.mjs → cline-pass-Bjm-O8GG.mjs} +2 -2
  12. package/lib/cloudflare-CKXRJ0l9.mjs +37 -0
  13. package/lib/{cloudflare-ai-gateway-DReN6ohJ.mjs → cloudflare-ai-gateway-BpnBSjwV.mjs} +8 -4
  14. package/lib/cloudflare-workers-ai-odj9XswL.mjs +32 -0
  15. package/lib/collapse-_nkb2dn7.mjs +1945 -0
  16. package/lib/{coreweave-C82HrLpb.mjs → coreweave-CGDZOD8-.mjs} +1 -1
  17. package/lib/{coreweave-C68UgRQO.mjs → coreweave-DwffcgW5.mjs} +4 -4
  18. package/lib/cursor-BgOuV7Qf.mjs +794 -0
  19. package/lib/{cursor-_gHHq-Dq.mjs → cursor-CF1iHHbv.mjs} +68 -19
  20. package/lib/{cursor-proto-Cr_WEMuv.mjs → cursor-proto-BuNTjX3L.mjs} +823 -23
  21. package/lib/{devin-QpfTSl9H.mjs → devin-7OEeEb80.mjs} +112 -31
  22. package/lib/{devin-proto-DYhp4Ty6.mjs → devin-proto-C-QreeAv.mjs} +71 -5
  23. package/lib/{dom-DG3sPESc.mjs → dom-BmbZv4v9.mjs} +598 -182
  24. package/lib/{error-O63pC8zg.mjs → error-8LVo7tug.mjs} +725 -104
  25. package/lib/factory-droid-ChhmsGWb.mjs +71 -0
  26. package/lib/{fs-promises-shim-B2YFWkcd.mjs → fs-promises-shim-CANAxFWh.mjs} +10 -1
  27. package/lib/{github-copilot-BMEcw8N1.mjs → github-copilot-QwevdT30.mjs} +4 -4
  28. package/lib/{github-copilot-headers-DnjGEbko.mjs → github-copilot-headers-CAUZ0rUD.mjs} +138 -26
  29. package/lib/{gitlab-duo-DnHqJjFY.mjs → gitlab-duo-DigV7k_o.mjs} +2 -2
  30. package/lib/{google-antigravity-B1mSckrK.mjs → google-antigravity-D-oe0r8A.mjs} +6 -7
  31. package/lib/{google-gemini-cli-DJwThCCn.mjs → google-gemini-cli-CQBHgGJT.mjs} +5 -6
  32. package/lib/{google-oauth-shared-BctLpVUN.mjs → google-oauth-shared-CvgVIUwJ.mjs} +2 -2
  33. package/lib/google-validation-CdvRj4ec.mjs +126 -0
  34. package/lib/id-EJwVLDHE.mjs +2548 -0
  35. package/lib/index.mjs +248 -258
  36. package/lib/{kilo-BEgEwMJQ.mjs → kilo-5r6OffCa.mjs} +2 -2
  37. package/lib/{kimi-T9NldEIJ.mjs → kimi-DOOtbXmm.mjs} +9 -10
  38. package/lib/{launch-BIWNyrBB.mjs → launch-DkAjib7h.mjs} +1 -1
  39. package/lib/{markit-Dvp2JPdT.mjs → markit-CCcyeAds.mjs} +359 -140
  40. package/lib/{models-DnXMYGcJ.mjs → models-DCpDT_im.mjs} +199203 -112275
  41. package/lib/{muse-code-CNvqqAp6.mjs → muse-code-CYf8zj_B.mjs} +5 -5
  42. package/lib/{openai-codex-D5-CyTxa.mjs → openai-codex-Cj-TvSFh.mjs} +13 -10
  43. package/lib/{perplexity-A2PEoGaC.mjs → perplexity-Dh_Qgsmx.mjs} +68 -25
  44. package/lib/{pkce-BYjmugmw.mjs → pkce-DO-jBJLV.mjs} +1 -1
  45. package/lib/pricing-DusBEhwm.mjs +593 -0
  46. package/lib/{readability-uGhqb4GC.mjs → readability-XHK0o3bv.mjs} +287 -27
  47. package/lib/{scrapers-C1ujjV8k.mjs → scrapers-B6PADOVm.mjs} +13 -13
  48. package/lib/slugify-ynYWBIA5.mjs +11 -0
  49. package/lib/snowflake-B_jap6lz.mjs +666 -0
  50. package/lib/snowflake-Cu1ZyOp6.mjs +151 -0
  51. package/lib/{src-AELUUb5U.mjs → src-BhinCSpi.mjs} +1172 -458
  52. package/lib/{stream-AVOoe5Hj.mjs → stream-D2ivg3GH.mjs} +3740 -5311
  53. package/lib/{turndown-D6fof1OX.mjs → turndown-Vya8SavL.mjs} +82 -30
  54. package/lib/types/tools/hashline/native/index.d.ts +2 -2
  55. package/lib/types/tools/hashline/native/policy.d.ts +19 -21
  56. package/lib/types/tools/omp/session/agent-storage.d.ts +3 -3
  57. package/lib/types/tools/shared/bun-named-shim.d.ts +5 -0
  58. package/lib/{types-BLrLohwK.mjs → types-tH1v9uRm.mjs} +2 -2
  59. package/lib/{utils-cZX3f_Ls.mjs → utils-C_Ncya1r.mjs} +1737 -509
  60. package/lib/utils-D2tK38xq.mjs +34006 -0
  61. package/lib/{utils-I4I8azHN.mjs → utils-DrDwmNtu.mjs} +8 -3
  62. package/lib/{xai-oauth-CbeldUSV.mjs → xai-oauth-DLLzX6my.mjs} +4 -4
  63. package/lib/{xiaomi-Dl3VSs04.mjs → xiaomi-CqK-KivK.mjs} +2 -2
  64. package/lib/{zai-FyjGSypr.mjs → zai-DoJ2xPIH.mjs} +2 -2
  65. package/lib/{zip-DRrycScC.mjs → zip-DG1mUV6X.mjs} +1 -1
  66. package/package.json +8 -8
  67. package/lib/amazon-bedrock-Dx0rr9dY.mjs +0 -996
  68. package/lib/anthropic-ClCw0PV_.mjs +0 -3624
  69. package/lib/anthropic-wire-lbGAFzYb.mjs +0 -927
  70. package/lib/azure-openai-responses-WE_bgFWp.mjs +0 -285
  71. package/lib/bundled-references-DY3EJxZV.mjs +0 -56
  72. package/lib/cloudflare-ai-gateway-CrMa97Ap.mjs +0 -44
  73. package/lib/collapse-CkMNRNr7.mjs +0 -2304
  74. package/lib/cursor-C6jaIJDg.mjs +0 -283
  75. package/lib/cursor-D-XZYDf_.mjs +0 -4544
  76. package/lib/deterministic-id-CUEIMSqR.mjs +0 -17
  77. package/lib/devin-ExGIghmx.mjs +0 -69
  78. package/lib/devin-u0ljw5P6.mjs +0 -628
  79. package/lib/effort-BdtQMN-_.mjs +0 -23
  80. package/lib/event-stream-BKEtb45Y.mjs +0 -167
  81. package/lib/gemini-headers-Co9cVvex.mjs +0 -54
  82. package/lib/google-auth-qAN-6DMW.mjs +0 -232
  83. package/lib/google-gemini-cli-B2Aw1S5w.mjs +0 -844
  84. package/lib/google-lTxuq28n.mjs +0 -38
  85. package/lib/google-shared-Y01j9xOr.mjs +0 -856
  86. package/lib/google-validation-BEkNs-Bx.mjs +0 -18
  87. package/lib/google-vertex-DcM-FRC5.mjs +0 -99
  88. package/lib/hosts-00rjRzUD.mjs +0 -203
  89. package/lib/id-AL5obQzR.mjs +0 -71
  90. package/lib/idle-iterator-D0ZXEcUq.mjs +0 -366
  91. package/lib/ollama-6R0oXZks.mjs +0 -574
  92. package/lib/openai-codex-responses-C8bnBWOe.mjs +0 -3232
  93. package/lib/openai-completions-DNr3mUsn.mjs +0 -1430
  94. package/lib/openai-configuration-update-xMYUjaK_.mjs +0 -150
  95. package/lib/openai-reasoning-fallback-Ju-5pSR8.mjs +0 -380
  96. package/lib/openai-responses-CjpafAEr.mjs +0 -861
  97. package/lib/protobuf-BMgDYu_U.mjs +0 -717
  98. package/lib/provider-response-SqKSkkUc.mjs +0 -22
  99. package/lib/proxy-DxvCQOCA.mjs +0 -230
  100. package/lib/request-debug-BwPOqN_j.mjs +0 -183
  101. package/lib/sanitize-text-BCf5KmCf.mjs +0 -33
  102. package/lib/sse-debug-B-tkLCPW.mjs +0 -11
  103. package/lib/stream-markup-healing-CN3RsqG9.mjs +0 -267
  104. package/lib/strict-tool-validation-CBTz1dAA.mjs +0 -105
  105. package/lib/taxonomy-DSIM99rS.mjs +0 -15392
  106. package/lib/thinking-ngMwf_1Y.mjs +0 -336
  107. package/lib/type-guards-CttAANEx.mjs +0 -11
  108. package/lib/utils-CE3DSebh.mjs +0 -11763
  109. package/lib/vision-guard-BCpXWUj3.mjs +0 -77
@@ -1,2304 +0,0 @@
1
- import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
- __installBunShim();
3
- import { n as isRecord } from "./type-guards-CttAANEx.mjs";
4
- import { c as resolveCascade, d as compareRevision, f as parseRevision, i as collapseVocabulary, m as revisionSatisfies, n as classifyModel, o as stripThinkingVariantSuffix, p as parseRevisionConstraint, r as collapseVariantId } from "./taxonomy-DSIM99rS.mjs";
5
- import { t as cleanModelName } from "./utils-I4I8azHN.mjs";
6
- import { n as THINKING_EFFORTS } from "./effort-BdtQMN-_.mjs";
7
- import { t as bareModelId } from "./id-AL5obQzR.mjs";
8
- import { r as modelMatchesHost, t as hostMatchesUrl } from "./hosts-00rjRzUD.mjs";
9
- //#region node_modules/.pnpm/@oh-my-pi+pi-catalog@18.1.17/node_modules/@oh-my-pi/pi-catalog/src/compat/anthropic.ts
10
- /**
11
- * Anthropic endpoint-shape predicates: which URLs are the official first-party
12
- * API, and which non-official hosts enforce Anthropic's thinking-signature
13
- * protocol on replay. Compat resolution (`./resolve`) and runtime routing in
14
- * pi-ai both consume these; URL matching is the one detection surface that
15
- * stays in code.
16
- */
17
- const OFFICIAL_ANTHROPIC_URL = "https://api.anthropic.com";
18
- /**
19
- * Official first-party Anthropic API. A missing baseUrl is official on purpose:
20
- * request dispatch falls back to `https://api.anthropic.com`. This is the one
21
- * auth-sensitive host check — OAuth credentials are attached based on it — so
22
- * it requires the exact origin or a path boundary (`/`) after it; a bare
23
- * prefix check would accept lookalikes like `https://api.anthropic.com.evil.com`.
24
- */
25
- function isOfficialAnthropicApiUrl(baseUrl) {
26
- if (!baseUrl) return true;
27
- const lower = baseUrl.toLowerCase();
28
- return lower === OFFICIAL_ANTHROPIC_URL || lower.startsWith(`${OFFICIAL_ANTHROPIC_URL}/`);
29
- }
30
- const CLOUDFLARE_ANTHROPIC_GATEWAY_URL_MARKER = /gateway\.ai\.cloudflare\.com\/.+\/anthropic(?:\/|$)/i;
31
- const VERTEX_ANTHROPIC_URL_MARKER = /aiplatform\.googleapis\.com\/.+\/publishers\/anthropic\//i;
32
- const BEDROCK_ANTHROPIC_URL_MARKER = /(?:^|\/\/|\.)bedrock-runtime\.[a-z0-9-]+\.amazonaws\.com/i;
33
- const AZURE_ANTHROPIC_URL_MARKER = /(?:^|\/\/|\.)[a-z0-9-]+\.(?:inference|services)\.ai\.azure\.com/i;
34
- /**
35
- * Azure AI Inference / Foundry Anthropic route
36
- * (`<resource>.inference.ai.azure.com`, `<resource>.services.ai.azure.com`).
37
- * Fronts Claude behind Azure identity and enforces Anthropic signatures on
38
- * replay; it also rejects the top-level `strict` tool field.
39
- */
40
- function isAzureAnthropicRoute(baseUrl) {
41
- return baseUrl !== void 0 && AZURE_ANTHROPIC_URL_MARKER.test(baseUrl);
42
- }
43
- /**
44
- * Known non-official URLs that enforce Anthropic thinking signatures on replay
45
- * (GitHub Copilot, ZenMux, Cloudflare AI Gateway `/anthropic`, Google Vertex
46
- * `publishers/anthropic`, AWS Bedrock, Azure Foundry).
47
- *
48
- * Runtime routing calls this with the effective URL because a model's resolved
49
- * compat can be stale after Foundry or a provider base-URL override reroutes it.
50
- */
51
- function isAnthropicSigningProxyUrl(baseUrl) {
52
- return hostMatchesUrl(baseUrl, "githubCopilot") || hostMatchesUrl(baseUrl, "zenmux") || baseUrl !== void 0 && (CLOUDFLARE_ANTHROPIC_GATEWAY_URL_MARKER.test(baseUrl) || VERTEX_ANTHROPIC_URL_MARKER.test(baseUrl) || BEDROCK_ANTHROPIC_URL_MARKER.test(baseUrl)) || isAzureAnthropicRoute(baseUrl);
53
- }
54
- //#endregion
55
- //#region node_modules/.pnpm/@oh-my-pi+pi-catalog@18.1.17/node_modules/@oh-my-pi/pi-catalog/src/compat/apply.ts
56
- /**
57
- * Assign defined override values onto a freshly-built resolved compat record,
58
- * in place. Keys the record doesn't declare are ignored (loosely-typed config
59
- * may carry junk). `buildModel` is the only intended caller — the record being
60
- * mutated is the single per-model allocation; nothing here runs per request.
61
- */
62
- function applyCompatOverrides(compat, overrides) {
63
- if (!overrides) return;
64
- for (const key in overrides) {
65
- const value = overrides[key];
66
- if (value !== void 0 && key in compat) compat[key] = value;
67
- }
68
- }
69
- //#endregion
70
- //#region node_modules/.pnpm/@oh-my-pi+pi-catalog@18.1.17/node_modules/@oh-my-pi/pi-catalog/src/compat/axes.ts
71
- const OAI = ["openai", "openai-responses"];
72
- const EFFORTS = [
73
- "minimal",
74
- "low",
75
- "medium",
76
- "high",
77
- "xhigh",
78
- "max"
79
- ];
80
- [...EFFORTS];
81
- /**
82
- * How hard agent prompts push subagent delegation for a model lineage
83
- * (`delegation-bias` axis). `eager` is the unassigned default: the prompt
84
- * actively pushes fan-out. `restrained` keeps fan-out for genuinely parallel
85
- * slices but forbids reflexive scouts and single-agent babysitting. `gated`
86
- * forbids subagents unless the user or a skill asks.
87
- */
88
- const DELEGATION_BIASES = [
89
- "eager",
90
- "restrained",
91
- "gated"
92
- ];
93
- const THINKING_MODES = [
94
- "effort",
95
- "budget",
96
- "google-level",
97
- "anthropic-adaptive",
98
- "anthropic-budget-effort"
99
- ];
100
- function wire(key, records, shape = "scalar", values) {
101
- return {
102
- key,
103
- set: "wire",
104
- shape,
105
- records,
106
- values
107
- };
108
- }
109
- /**
110
- * KDL directive → axis definition. Keys are the kebab-case directive
111
- * spellings accepted inside `classes/*.kdl` and `providers/*.kdl` rule
112
- * blocks.
113
- */
114
- const AXES = {
115
- "allows-synthetic-reasoning-content-for-tool-calls": wire("allowsSyntheticReasoningContentForToolCalls", OAI),
116
- "always-send-max-tokens": wire("alwaysSendMaxTokens", OAI),
117
- "cache-control-format": wire("cacheControlFormat", OAI, "scalar", ["anthropic"]),
118
- "clamp-output-to-model-max": wire("clampOutputToModelMax", OAI),
119
- "disable-reasoning-on-forced-tool-choice": wire("disableReasoningOnForcedToolChoice", OAI),
120
- "disable-reasoning-on-tool-choice": wire("disableReasoningOnToolChoice", OAI),
121
- "drop-thinking-when-reasoning-effort": wire("dropThinkingWhenReasoningEffort", ["openai"]),
122
- "empty-length-finish-is-context-error": wire("emptyLengthFinishIsContextError", OAI),
123
- "extra-body": {
124
- ...wire("extraBody", ["openai"], "object"),
125
- verbatimKeys: true
126
- },
127
- "filter-reasoning-history": wire("filterReasoningHistory", OAI),
128
- "include-encrypted-reasoning": wire("includeEncryptedReasoning", OAI),
129
- "kimi-api-format": wire("kimiApiFormat", ["openai"], "scalar", ["openai", "anthropic"]),
130
- "max-tokens-field": wire("maxTokensField", ["openai"], "scalar", ["max_completion_tokens", "max_tokens"]),
131
- "native-kimi-k3-reasoning": wire("nativeKimiK3Reasoning", ["openai"]),
132
- "omit-reasoning-effort": wire("omitReasoningEffort", OAI),
133
- "prompt-cache-breakpoint-ttl": wire("promptCacheBreakpointTtl", OAI, "scalar", ["30m"]),
134
- "prompt-cache-session-header": wire("promptCacheSessionHeader", OAI, "scalar", ["x-grok-conv-id"]),
135
- "qwen-preserve-thinking": wire("qwenPreserveThinking", ["openai"]),
136
- "reject-root-object-union": wire("rejectRootObjectUnion", OAI),
137
- "retry-without-strict-on-grammar-error": wire("retryWithoutStrictOnGrammarError", OAI),
138
- "reasoning-content-field": wire("reasoningContentField", OAI, "scalar", [
139
- "reasoning_content",
140
- "reasoning",
141
- "reasoning_text"
142
- ]),
143
- "reasoning-deltas-may-be-cumulative": wire("reasoningDeltasMayBeCumulative", OAI),
144
- "reasoning-disable-mode": wire("reasoningDisableMode", OAI, "scalar", [
145
- "omit",
146
- "lowest-effort",
147
- "none-effort",
148
- "openrouter-enabled-false",
149
- "cline-enabled-false",
150
- "venice-disable-thinking",
151
- "zai-thinking-disabled",
152
- "qwen-enable-thinking-false",
153
- "qwen-template-false",
154
- "chat-template-thinking-false"
155
- ]),
156
- "reasoning-effort-map": wire("reasoningEffortMap", OAI, "object"),
157
- "replay-reasoning-content": wire("replayReasoningContent", ["openai"]),
158
- "requires-assistant-after-tool-result": wire("requiresAssistantAfterToolResult", ["openai"]),
159
- "requires-assistant-content-for-tool-calls": wire("requiresAssistantContentForToolCalls", OAI),
160
- "requires-mistral-tool-ids": wire("requiresMistralToolIds", ["openai"]),
161
- "requires-reasoning-content-for-all-assistant-turns": wire("requiresReasoningContentForAllAssistantTurns", OAI),
162
- "requires-reasoning-content-for-tool-calls": wire("requiresReasoningContentForToolCalls", OAI),
163
- "requires-thinking-as-text": wire("requiresThinkingAsText", ["openai"]),
164
- "requires-tool-result-name": wire("requiresToolResultName", ["openai"]),
165
- "strict-responses-pairing": wire("strictResponsesPairing", ["openai-responses"]),
166
- "requires-reasoning-off-juice-instruction": wire("requiresReasoningOffJuiceInstruction", ["openai-responses"]),
167
- "supports-all-turns-reasoning-context": wire("supportsAllTurnsReasoningContext", ["openai-responses"]),
168
- "supports-configuration-update": wire("supportsConfigurationUpdate", ["openai-responses"]),
169
- "strip-deepseek-special-tokens": wire("stripDeepseekSpecialTokens", OAI),
170
- "stream-markup-healing-pattern": wire("streamMarkupHealingPattern", OAI, "scalar", [
171
- "kimi",
172
- "dsml",
173
- "qwen",
174
- "thinking",
175
- "harmony"
176
- ]),
177
- "supports-developer-role": wire("supportsDeveloperRole", OAI),
178
- "supports-image-detail-original": wire("supportsImageDetailOriginal", ["openai-responses"]),
179
- "supports-long-prompt-cache-retention": wire("supportsLongPromptCacheRetention", [...OAI, "bedrock"]),
180
- "supports-multiple-system-messages": wire("supportsMultipleSystemMessages", ["openai"]),
181
- "supports-named-tool-choice": wire("supportsNamedToolChoice", OAI),
182
- "supports-obfuscation-opt-out": wire("supportsObfuscationOptOut", ["openai-responses"]),
183
- "harmony-leak-mitigation": wire("harmonyLeakMitigation", ["openai-responses"]),
184
- "supports-penalty-and-stop-params": wire("supportsPenaltyAndStopParams", OAI),
185
- "supports-prompt-cache-breakpoints": wire("supportsPromptCacheBreakpoints", OAI),
186
- "supports-prompt-cache-key": wire("supportsPromptCacheKey", ["openai"]),
187
- "supports-reasoning-effort": wire("supportsReasoningEffort", OAI),
188
- "supports-reasoning-params": wire("supportsReasoningParams", OAI),
189
- "supports-reasoning-summary": wire("supportsReasoningSummary", ["openai-responses"]),
190
- "supports-store": wire("supportsStore", ["openai"]),
191
- "supports-strict-mode": wire("supportsStrictMode", OAI),
192
- "supports-tool-choice": wire("supportsToolChoice", OAI),
193
- "supports-usage-in-streaming": wire("supportsUsageInStreaming", ["openai"]),
194
- "template-reasoning-effort": wire("qwenTemplateReasoningEffort", ["openai"]),
195
- "thinking-format": wire("thinkingFormat", OAI, "scalar", [
196
- "openai",
197
- "openrouter",
198
- "zai",
199
- "kimi",
200
- "qwen",
201
- "qwen-chat-template",
202
- "chat-template"
203
- ]),
204
- "thinking-keep": wire("thinkingKeep", ["openai"]),
205
- "tool-schema-flavor": wire("toolSchemaFlavor", OAI, "scalar", [
206
- "moonshot-mfjs",
207
- "grammar",
208
- "none"
209
- ]),
210
- "tool-strict-mode": wire("toolStrictMode", ["openai"], "scalar", [
211
- "all_strict",
212
- "none",
213
- "mixed"
214
- ]),
215
- "uses-openai-tool-call-id-limit": wire("usesOpenAIToolCallIdLimit", OAI),
216
- "when-thinking": wire("whenThinking", ["openai"], "object"),
217
- "wire-model-id-mode": wire("wireModelIdMode", OAI, "scalar", [
218
- "raw",
219
- "cline-pass",
220
- "firepass",
221
- "fireworks",
222
- "openrouter"
223
- ]),
224
- "zai-reasoning-effort-dialect": wire("zaiReasoningEffortDialect", ["openai"]),
225
- "allow-anthropic-header-overrides": wire("allowAnthropicHeaderOverrides", ["anthropic"]),
226
- "disable-adaptive-thinking": wire("disableAdaptiveThinking", ["anthropic"]),
227
- "disable-strict-tools": wire("disableStrictTools", ["anthropic"]),
228
- "escape-builtin-tool-names": wire("escapeBuiltinToolNames", ["anthropic"]),
229
- "inject-claude-code-instruction": wire("injectClaudeCodeInstruction", ["anthropic"]),
230
- "official-endpoint": wire("officialEndpoint", ["anthropic", "openai-responses"]),
231
- "replay-unsigned-thinking": wire("replayUnsignedThinking", ["anthropic"]),
232
- "requires-thinking-enabled": wire("requiresThinkingEnabled", ["anthropic"]),
233
- "requires-tool-result-id": wire("requiresToolResultId", ["anthropic"]),
234
- "signing-endpoint": wire("signingEndpoint", ["anthropic"]),
235
- "supports-context-management": wire("supportsContextManagement", ["anthropic"]),
236
- "supports-output-effort": wire("supportsOutputEffort", ["anthropic"]),
237
- "supports-eager-tool-input-streaming": wire("supportsEagerToolInputStreaming", ["anthropic"]),
238
- "supports-long-cache-retention": wire("supportsLongCacheRetention", ["anthropic"]),
239
- "supports-mid-conversation-system": wire("supportsMidConversationSystem", ["anthropic"]),
240
- "supports-mid-conversation-tool-changes": wire("supportsMidConversationToolChanges", ["anthropic"]),
241
- "supports-per-message-effort": wire("supportsPerMessageEffort", ["anthropic"]),
242
- "supports-thinking-binding-controls": wire("supportsThinkingBindingControls", ["anthropic"]),
243
- "supports-turn-scoped-system": wire("supportsTurnScopedSystem", ["anthropic"]),
244
- "prompt-cache-maximum-checkpoints": wire("promptCacheMaximumCheckpoints", ["bedrock"]),
245
- "prompt-cache-minimum-tokens": wire("promptCacheMinimumTokens", ["bedrock"]),
246
- "prompt-cache-mode": wire("promptCacheMode", ["bedrock"], "scalar", [
247
- "none",
248
- "automatic",
249
- "explicit"
250
- ]),
251
- "model-router": wire("modelRouter", ["devin"]),
252
- "supports-parallel-tool-calls": wire("supportsParallelToolCalls", ["devin"]),
253
- "trust-explicit-thinking-only": wire("trustExplicitThinkingOnly", ["devin"]),
254
- "antigravity-claude-tool-mode": wire("antigravityClaudeToolMode", ["google"]),
255
- "antigravity-usage-label": wire("antigravityUsageLabel", ["google"]),
256
- "cca-legacy-parameters-schema": wire("ccaLegacyParametersSchema", ["google"]),
257
- "claude-thinking-beta-header": wire("claudeThinkingBetaHeader", ["google"]),
258
- "drop-unsigned-thinking": wire("dropUnsignedThinking", ["google"]),
259
- "flash-stream-leak-workaround": wire("flashStreamLeakWorkaround", ["google"]),
260
- "multimodal-function-response": wire("multimodalFunctionResponse", ["google"]),
261
- "requires-skip-thought-signature": wire("requiresSkipThoughtSignature", ["google"]),
262
- "requires-skip-thought-signature-on-first-function-call": wire("requiresSkipThoughtSignatureOnFirstFunctionCall", ["google"]),
263
- "supports-function-part-id": wire("supportsFunctionPartId", ["google"]),
264
- "stream-first-event-timeout-ms": wire("streamFirstEventTimeoutMs", [...OAI, "google"]),
265
- "stream-idle-timeout-ms": wire("streamIdleTimeoutMs", [
266
- ...OAI,
267
- "anthropic",
268
- "bedrock",
269
- "google"
270
- ]),
271
- "strip-image-input": wire("stripImageInput", [
272
- ...OAI,
273
- "anthropic",
274
- "google"
275
- ]),
276
- "supports-forced-tool-choice": wire("supportsForcedToolChoice", [...OAI, "anthropic"]),
277
- "supports-sampling-params": wire("supportsSamplingParams", [...OAI, "anthropic"]),
278
- "thinking-loop-guard": wire("thinkingLoopGuard", [
279
- ...OAI,
280
- "anthropic",
281
- "google"
282
- ], "scalar", [
283
- "gemini",
284
- "deepseek",
285
- "xai"
286
- ]),
287
- "thinking-default-level": {
288
- key: "defaultLevel",
289
- set: "thinking",
290
- shape: "scalar",
291
- values: EFFORTS
292
- },
293
- "thinking-effort-budgets": {
294
- key: "effortBudgets",
295
- set: "thinking",
296
- shape: "object"
297
- },
298
- "thinking-effort-map": {
299
- key: "effortMap",
300
- set: "thinking",
301
- shape: "object"
302
- },
303
- "thinking-efforts": {
304
- key: "efforts",
305
- set: "thinking",
306
- shape: "array",
307
- values: EFFORTS
308
- },
309
- "thinking-mode": {
310
- key: "mode",
311
- set: "thinking",
312
- shape: "scalar",
313
- values: THINKING_MODES
314
- },
315
- "thinking-requires-effort": {
316
- key: "requiresEffort",
317
- set: "thinking",
318
- shape: "scalar"
319
- },
320
- "thinking-prefix-binding": {
321
- key: "prefixBinding",
322
- set: "thinking",
323
- shape: "scalar"
324
- },
325
- "thinking-suppress-when-off": {
326
- key: "suppressWhenOff",
327
- set: "thinking",
328
- shape: "scalar"
329
- },
330
- "thinking-supports-display": {
331
- key: "supportsDisplay",
332
- set: "thinking",
333
- shape: "scalar"
334
- },
335
- "thinking-upgrade-neutral": {
336
- key: "upgradeNeutral",
337
- set: "thinking",
338
- shape: "scalar"
339
- },
340
- "apply-patch-tool-type": {
341
- key: "applyPatchToolType",
342
- set: "catalog",
343
- shape: "scalar",
344
- values: ["freeform", "function"]
345
- },
346
- "clamp-context-override": {
347
- key: "clampContextOverride",
348
- set: "catalog",
349
- shape: "scalar"
350
- },
351
- "context-promotion-target": {
352
- key: "contextPromotionTarget",
353
- set: "catalog",
354
- shape: "scalar"
355
- },
356
- "context-window-floor": {
357
- key: "contextWindowFloor",
358
- set: "catalog",
359
- shape: "scalar"
360
- },
361
- "cost-patch": {
362
- key: "costPatch",
363
- set: "catalog",
364
- shape: "object"
365
- },
366
- "delegation-bias": {
367
- key: "delegationBias",
368
- set: "catalog",
369
- shape: "scalar",
370
- values: DELEGATION_BIASES
371
- },
372
- "edit-prompt-variant": {
373
- key: "editPromptVariant",
374
- set: "catalog",
375
- shape: "scalar",
376
- values: ["full", "compact"]
377
- },
378
- "edit-revision": {
379
- key: "editRevision",
380
- set: "catalog",
381
- shape: "scalar"
382
- },
383
- "input-modalities": {
384
- key: "inputModalities",
385
- set: "catalog",
386
- shape: "array",
387
- values: ["text", "image"]
388
- },
389
- "limits-patch": {
390
- key: "limitsPatch",
391
- set: "catalog",
392
- shape: "object"
393
- },
394
- "long-context-cost": {
395
- key: "longContext",
396
- set: "catalog",
397
- shape: "object"
398
- },
399
- "long-usage-limit-fallback": {
400
- key: "longUsageLimitFallback",
401
- set: "catalog",
402
- shape: "scalar"
403
- },
404
- "max-context-window": {
405
- key: "maxContextWindow",
406
- set: "catalog",
407
- shape: "scalar"
408
- },
409
- "requires-cursor-tool-schema-projection": {
410
- key: "requiresCursorToolSchemaProjection",
411
- set: "catalog",
412
- shape: "scalar"
413
- },
414
- priority: {
415
- key: "priority",
416
- set: "catalog",
417
- shape: "scalar"
418
- },
419
- "service-tier-cost": {
420
- key: "serviceTierCost",
421
- set: "catalog",
422
- shape: "object"
423
- },
424
- "time-based-cost": {
425
- key: "timeBased",
426
- set: "catalog",
427
- shape: "object"
428
- }
429
- };
430
- /** Records applicable to each API family; used by `resolve.ts` when applying wire axes. */
431
- const API_COMPAT_RECORDS = {
432
- "openai-completions": ["openai"],
433
- openrouter: ["openai", "openai-responses"],
434
- "openai-responses": ["openai-responses"],
435
- "azure-openai-responses": ["openai-responses"],
436
- "openai-codex-responses": ["openai-responses"],
437
- "anthropic-messages": ["anthropic"],
438
- "bedrock-converse-stream": ["bedrock"],
439
- "devin-agent": ["devin"],
440
- "google-generative-ai": ["google"],
441
- "google-vertex": ["google"],
442
- "google-gemini-cli": ["google"]
443
- };
444
- //#endregion
445
- //#region node_modules/.pnpm/@oh-my-pi+pi-catalog@18.1.17/node_modules/@oh-my-pi/pi-catalog/src/compat/resolve.ts
446
- /**
447
- * `resolveModelPolicy` — the single model-policy resolver. Layering, later
448
- * layers win:
449
- *
450
- * 1. unconditional per-API compat defaults;
451
- * 2. host-derived flags: URL/provider detection via `hosts.ts`, including
452
- * compound host×identity branches (keyed on {@link ModelIdentity} fields,
453
- * never on model-name matching);
454
- * 3. compat-cascade axes compiled from `rules/` (pure identity- and
455
- * provider-keyed policy lives there, not here);
456
- * 4. spec-authored sparse overrides (`applyCompatOverrides`), then the
457
- * spec-undefined fixups the legacy builders applied.
458
- *
459
- * Thinking metadata resolves after compat: explicit spec thinking wins,
460
- * cascade thinking axes drive the ladder/mode/wire facts, and identity-generic
461
- * fallbacks cover unmatched targets.
462
- */
463
- /** Structured identity plus revision comparison helpers. */
464
- var IdentityFacts = class {
465
- identity;
466
- revision;
467
- constructor(identity) {
468
- this.identity = identity;
469
- this.revision = identity.revision === void 0 ? void 0 : parseRevision(identity.revision);
470
- }
471
- is(cls) {
472
- return this.identity.class === cls;
473
- }
474
- family(...families) {
475
- return this.identity.family !== void 0 && families.includes(this.identity.family);
476
- }
477
- revGte(min) {
478
- if (!this.revision) return false;
479
- const bound = parseRevision(min);
480
- return bound !== void 0 && compareRevision(this.revision, bound) >= 0;
481
- }
482
- revMajor() {
483
- return this.revision?.[0];
484
- }
485
- /** Kimi K2.7-Code / K3 lines whose native hosts mandate enabled thinking. */
486
- get kimiMandatoryThinking() {
487
- return this.is("kimi") && this.family("k2.7-code", "k3");
488
- }
489
- /** Adaptive-thinking Claude generation floor (Opus ≥ min; Sonnet/Fable/Mythos ≥ 5). */
490
- anthropicAdaptiveGenAtLeast(opusMin) {
491
- if (!this.is("anthropic")) return false;
492
- if (this.family("opus")) return this.revGte(opusMin);
493
- if (this.family("sonnet", "fable", "mythos")) return this.revGte("5");
494
- return false;
495
- }
496
- };
497
- function resolveIdentity(spec) {
498
- return classifyModel(spec.provider, spec.id);
499
- }
500
- let keyRecords;
501
- function getKeyRecords() {
502
- if (!keyRecords) {
503
- keyRecords = {};
504
- for (const directive in AXES) {
505
- const axis = AXES[directive];
506
- if (axis.set === "wire" && axis.records) keyRecords[axis.key] = { records: axis.records };
507
- }
508
- }
509
- return keyRecords;
510
- }
511
- /**
512
- * Assigns resolved wire axes onto a freshly-detected compat record. An axis
513
- * lands only when the model's API maps to one of the axis's declared records
514
- * — the axes table is the single applicability authority, so optional keys
515
- * absent from the detected baseline still land.
516
- */
517
- function applyWireAxes(compat, wire, api) {
518
- const records = API_COMPAT_RECORDS[api];
519
- if (!records) return;
520
- const info = getKeyRecords();
521
- for (const key in wire) {
522
- if (!info[key]?.records.some((record) => records.includes(record))) continue;
523
- Reflect.set(compat, key, wire[key]);
524
- }
525
- }
526
- /**
527
- * Preserves legacy per-key merge semantics for map-valued effort remaps: a
528
- * cascade-provided `reasoningEffortMap` is the detected base and sparse spec
529
- * overrides overlay it key by key (spec keys win, unseen keys survive).
530
- */
531
- function overlayEffortMapAxis(compat, axes, specCompat) {
532
- const axisMap = effortRecord(axes.wire.reasoningEffortMap);
533
- if (axisMap && specCompat?.reasoningEffortMap) compat.reasoningEffortMap = {
534
- ...axisMap,
535
- ...specCompat.reasoningEffortMap
536
- };
537
- }
538
- function effortList(value) {
539
- if (!Array.isArray(value) || value.length === 0) return void 0;
540
- const out = [];
541
- for (const entry of value) {
542
- const effort = THINKING_EFFORTS.find((candidate) => candidate === entry);
543
- if (effort === void 0) return void 0;
544
- out.push(effort);
545
- }
546
- return out;
547
- }
548
- function effortValue(value) {
549
- return THINKING_EFFORTS.find((candidate) => candidate === value);
550
- }
551
- function objectPayload$1(value) {
552
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
553
- }
554
- function effortRecord(value) {
555
- if (typeof value !== "object" || value === null) return void 0;
556
- const out = {};
557
- let any = false;
558
- for (const key in value) {
559
- const effort = effortValue(key);
560
- const mapped = Reflect.get(value, key);
561
- if (effort === void 0 || typeof mapped !== "string") continue;
562
- out[effort] = mapped;
563
- any = true;
564
- }
565
- return any ? out : void 0;
566
- }
567
- function effortNumberRecord(value) {
568
- if (typeof value !== "object" || value === null) return void 0;
569
- const out = {};
570
- let any = false;
571
- for (const key in value) {
572
- const effort = effortValue(key);
573
- const mapped = Reflect.get(value, key);
574
- if (effort === void 0 || typeof mapped !== "number") continue;
575
- out[effort] = mapped;
576
- any = true;
577
- }
578
- return any ? out : void 0;
579
- }
580
- function thinkingMode(value) {
581
- switch (value) {
582
- case "effort":
583
- case "budget":
584
- case "google-level":
585
- case "anthropic-adaptive":
586
- case "anthropic-budget-effort": return value;
587
- default: return;
588
- }
589
- }
590
- const GLM_CODING_PLAN_STREAM_IDLE_TIMEOUT_MS = 6e5;
591
- const LOCAL_OPENAI_COMPAT_STREAM_IDLE_TIMEOUT_MS = 3e5;
592
- const LOCAL_OPENAI_COMPAT_PROVIDERS = {
593
- "llama.cpp": true,
594
- "lm-studio": true,
595
- vllm: true,
596
- ollama: true
597
- };
598
- const PROXY_OPENAI_COMPAT_PROVIDERS = { litellm: true };
599
- function hasLocalLoopbackBaseUrl(baseUrl) {
600
- if (!baseUrl) return false;
601
- let hostname;
602
- try {
603
- hostname = new URL(baseUrl).hostname.toLowerCase();
604
- } catch {
605
- return false;
606
- }
607
- if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "0.0.0.0" || hostname === "::1" || hostname === "[::1]") return true;
608
- if (hostname.startsWith("10.")) return true;
609
- if (hostname.startsWith("192.168.")) return true;
610
- if (/^172\.(1[6-9]|2[0-9]|3[01])\./.test(hostname)) return true;
611
- if (hostname.endsWith(".local")) return true;
612
- return false;
613
- }
614
- function resolveReasoningDisableMode(thinkingFormat) {
615
- switch (thinkingFormat) {
616
- case "openrouter": return "openrouter-enabled-false";
617
- case "zai":
618
- case "kimi": return "zai-thinking-disabled";
619
- case "qwen": return "qwen-enable-thinking-false";
620
- case "qwen-chat-template": return "qwen-template-false";
621
- case "chat-template": return "chat-template-thinking-false";
622
- default: return "lowest-effort";
623
- }
624
- }
625
- /** Strict official-OpenAI check: provider id `openai` and an `api.openai.com` host. */
626
- function isOfficialOpenAIEndpoint(provider, baseUrl) {
627
- if (provider !== "openai") return false;
628
- if (!baseUrl) return true;
629
- try {
630
- return new URL(baseUrl).hostname === "api.openai.com";
631
- } catch {
632
- return false;
633
- }
634
- }
635
- function detectOpenAI(spec, facts) {
636
- const provider = spec.provider;
637
- const baseUrl = spec.baseUrl;
638
- const hostModel = {
639
- provider,
640
- baseUrl
641
- };
642
- const isZai = modelMatchesHost(hostModel, "zai");
643
- const isZhipu = modelMatchesHost(hostModel, "zhipu");
644
- const isMoonshotNative = modelMatchesHost(hostModel, "moonshotNative");
645
- const isXiaomiHost = modelMatchesHost(hostModel, "xiaomi");
646
- const isDirectDeepseekApi = modelMatchesHost(hostModel, "deepseekDirect");
647
- const isDeepseekReasoning = (modelMatchesHost(hostModel, "deepseekFamily") || facts.is("deepseek")) && Boolean(spec.reasoning);
648
- const isLocalOpenAICompatBackend = PROXY_OPENAI_COMPAT_PROVIDERS[provider] !== true && (LOCAL_OPENAI_COMPAT_PROVIDERS[provider] === true || hasLocalLoopbackBaseUrl(baseUrl));
649
- return {
650
- facts,
651
- isClinePass: provider === "cline-pass",
652
- isZai,
653
- isZhipu,
654
- isMoonshotNative,
655
- isOpenCodeHost: modelMatchesHost(hostModel, "opencode"),
656
- isOpenCodeProvider: provider === "opencode-go" || provider === "opencode-zen",
657
- isDirectDeepseekApi,
658
- isDeepseekReasoning,
659
- isDirectDeepseekReasoning: isDirectDeepseekApi && isDeepseekReasoning,
660
- isVenice: modelMatchesHost(hostModel, "venice"),
661
- requiresEnabledThinking: isMoonshotNative && facts.is("kimi") && facts.family("k2.7-code"),
662
- isXiaomiMimo: isXiaomiHost && facts.is("mimo"),
663
- isLocalOpenAICompatBackend,
664
- isLocalServingBackend: isLocalOpenAICompatBackend || hasLocalLoopbackBaseUrl(baseUrl),
665
- isOpenRouter: modelMatchesHost(hostModel, "openrouter")
666
- };
667
- }
668
- /**
669
- * Detected chat-completions baseline. Pure identity policy (Kimi max-token
670
- * behavior, DeepSeek reasoning-content contracts, Qwen dialects, sampling
671
- * restrictions, effort maps, markup healers, …) is rule-owned and absent
672
- * here; compound host×identity branches remain, keyed on identity fields.
673
- */
674
- function detectOpenAICompat(spec, d) {
675
- const provider = spec.provider;
676
- const baseUrl = spec.baseUrl;
677
- const hostModel = {
678
- provider,
679
- baseUrl
680
- };
681
- const facts = d.facts;
682
- const isCerebras = modelMatchesHost(hostModel, "cerebras");
683
- const isCerebrasHost = hostMatchesUrl(baseUrl, "cerebras");
684
- const isKilo = modelMatchesHost(hostModel, "kilo");
685
- const isAlibaba = modelMatchesHost(hostModel, "alibabaDashscope");
686
- const isXiaomiHost = modelMatchesHost(hostModel, "xiaomi");
687
- const isGrok = modelMatchesHost(hostModel, "xai");
688
- const isMistral = modelMatchesHost(hostModel, "mistral");
689
- const isGoogleAistudioOpenAI = hostMatchesUrl(baseUrl, "googleAistudio");
690
- const isOpenAIHost = modelMatchesHost(hostModel, "openai");
691
- const isAzureHost = modelMatchesHost(hostModel, "azureOpenAI");
692
- const isVercelGateway = modelMatchesHost(hostModel, "vercelAIGateway");
693
- const isTogether = modelMatchesHost(hostModel, "together");
694
- const isFireworks = hostMatchesUrl(baseUrl, "fireworks");
695
- const isGroqHost = modelMatchesHost(hostModel, "groq");
696
- const isMiniMaxHost = modelMatchesHost(hostModel, "minimax");
697
- const isQwenPortal = modelMatchesHost(hostModel, "qwenPortal");
698
- const isMoonshotKimi = facts.is("kimi") && d.isMoonshotNative;
699
- const isMoonshotKimiK3 = isMoonshotKimi && facts.family("k3");
700
- const usesMoonshotKimiPreservedThinking = isMoonshotKimi && facts.family("k2.6");
701
- const isAnthropicModel = modelMatchesHost(hostModel, "anthropic") || facts.is("anthropic");
702
- const isQwen = facts.is("qwen");
703
- const isDeepseekFamily = modelMatchesHost(hostModel, "deepseekFamily") || facts.is("deepseek");
704
- const supportsZaiReasoningEffort = (d.isZai || d.isZhipu) && facts.is("glm") && facts.revGte("5.2");
705
- const isNonStandard = isCerebras || isGrok || isMistral || isGoogleAistudioOpenAI || hostMatchesUrl(baseUrl, "chutes") || hostMatchesUrl(baseUrl, "deepseekFamily") || isFireworks || isAlibaba || d.isZai || d.isZhipu || isKilo || isQwen || isXiaomiHost || d.isMoonshotNative || d.isOpenCodeHost;
706
- const useMaxTokens = isMistral || d.isMoonshotNative || d.isZai || d.isZhipu || hostMatchesUrl(baseUrl, "chutes") || isFireworks || d.isDirectDeepseekApi;
707
- const supportsPromptCacheBreakpoints = isOfficialOpenAIEndpoint(provider, baseUrl) && facts.is("openai") && facts.revGte("5.6");
708
- const supportsMultipleSystemMessagesDefault = !isMiniMaxHost && !isAlibaba && !isQwenPortal && !isQwen && (isOpenAIHost || isAzureHost || d.isOpenRouter || isCerebras || isTogether || isFireworks || isGroqHost || isDeepseekFamily || isMistral || isGrok || d.isZai || d.isZhipu || provider === "github-copilot" || provider === "zenmux");
709
- const streamIdleTimeoutMs = facts.is("glm") && facts.revGte("5") && !facts.family("vision") && (hostMatchesUrl(baseUrl, "zai") || hostMatchesUrl(baseUrl, "zhipu") || hostMatchesUrl(baseUrl, "opencode")) ? GLM_CODING_PLAN_STREAM_IDLE_TIMEOUT_MS : facts.is("mimo") && hostMatchesUrl(baseUrl, "xiaomi") ? 3e5 : spec.reasoning && facts.is("kimi") && (facts.family("k3") || facts.family("k2.7-code")) && hostMatchesUrl(baseUrl, "moonshotNative") ? 3e5 : spec.reasoning && facts.is("deepseek") && hostMatchesUrl(baseUrl, "deepseekDirect") ? 3e5 : d.isLocalServingBackend ? LOCAL_OPENAI_COMPAT_STREAM_IDLE_TIMEOUT_MS : void 0;
710
- const wireModelIdMode = hostMatchesUrl(baseUrl, "openrouter") ? "openrouter" : "raw";
711
- const thinkingFormat = facts.is("kimi") && !facts.family("k3") && hostMatchesUrl(baseUrl, "moonshotNative") || hostMatchesUrl(baseUrl, "zai") || hostMatchesUrl(baseUrl, "zhipu") || facts.is("mimo") && hostMatchesUrl(baseUrl, "xiaomi") ? "zai" : hostMatchesUrl(baseUrl, "openrouter") ? "openrouter" : isQwen && hostMatchesUrl(baseUrl, "nvidia") ? "qwen-chat-template" : isQwen && (isFireworks || hostMatchesUrl(baseUrl, "venice")) ? "openai" : hostMatchesUrl(baseUrl, "alibabaDashscope") || isQwen ? "qwen" : "openai";
712
- return {
713
- supportsStore: !isNonStandard,
714
- supportsDeveloperRole: isOpenAIHost || isAzureHost,
715
- supportsMultipleSystemMessages: supportsMultipleSystemMessagesDefault,
716
- supportsReasoningEffort: !isGrok && !d.isXiaomiMimo && (!(d.isZai || d.isZhipu) || supportsZaiReasoningEffort),
717
- supportsReasoningParams: provider !== "github-copilot",
718
- supportsSamplingParams: !(facts.is("openai") && (facts.family("o-series") || facts.revGte("5"))),
719
- supportsPenaltyAndStopParams: !(isGrok && Boolean(spec.reasoning)),
720
- reasoningEffortMap: {},
721
- supportsUsageInStreaming: !isCerebrasHost,
722
- alwaysSendMaxTokens: facts.is("kimi"),
723
- disableReasoningOnForcedToolChoice: !d.isClinePass && (facts.is("kimi") && !isMoonshotKimiK3 || isAnthropicModel),
724
- disableReasoningOnToolChoice: !d.isClinePass && isDeepseekFamily && Boolean(spec.reasoning) && !d.isOpenRouter,
725
- supportsToolChoice: d.isClinePass || !d.isDirectDeepseekReasoning,
726
- supportsForcedToolChoice: !d.requiresEnabledThinking && !(d.isOpenCodeHost && d.isDeepseekReasoning) && !(d.isClinePass && isQwen),
727
- supportsNamedToolChoice: true,
728
- maxTokensField: useMaxTokens ? "max_tokens" : "max_completion_tokens",
729
- requiresToolResultName: isMistral,
730
- requiresAssistantAfterToolResult: isMistral,
731
- requiresThinkingAsText: isMistral,
732
- requiresMistralToolIds: isMistral,
733
- thinkingFormat,
734
- kimiApiFormat: void 0,
735
- reasoningDisableMode: d.isClinePass ? "cline-enabled-false" : d.isVenice ? "venice-disable-thinking" : resolveReasoningDisableMode(thinkingFormat),
736
- omitReasoningEffort: false,
737
- includeEncryptedReasoning: true,
738
- filterReasoningHistory: d.isOpenRouter && isAnthropicModel,
739
- thinkingKeep: usesMoonshotKimiPreservedThinking ? "all" : void 0,
740
- reasoningContentField: d.isClinePass ? "reasoning" : "reasoning_content",
741
- requiresReasoningContentForToolCalls: facts.is("kimi") && !d.isOpenCodeProvider || isDeepseekFamily && Boolean(spec.reasoning) || d.isXiaomiMimo || d.isOpenRouter && Boolean(spec.reasoning),
742
- requiresReasoningContentForAllAssistantTurns: (isDeepseekFamily && Boolean(spec.reasoning) || d.isXiaomiMimo) && !d.isOpenRouter,
743
- allowsSyntheticReasoningContentForToolCalls: (!isDeepseekFamily || !spec.reasoning) && !d.isXiaomiMimo,
744
- replayReasoningContent: d.isLocalOpenAICompatBackend,
745
- qwenPreserveThinking: (thinkingFormat === "qwen" || thinkingFormat === "qwen-chat-template") && d.isLocalOpenAICompatBackend,
746
- qwenTemplateReasoningEffort: (thinkingFormat === "qwen" || thinkingFormat === "qwen-chat-template") && d.isLocalOpenAICompatBackend && provider !== "ollama" && isQwen && facts.revGte("3.8"),
747
- requiresAssistantContentForToolCalls: facts.is("kimi") || d.isDirectDeepseekReasoning,
748
- cacheControlFormat: d.isClinePass && (isQwen || isAnthropicModel) || d.isOpenRouter && isAnthropicModel ? "anthropic" : void 0,
749
- supportsPromptCacheBreakpoints,
750
- promptCacheBreakpointTtl: supportsPromptCacheBreakpoints ? "30m" : void 0,
751
- openRouterRouting: void 0,
752
- vercelGatewayRouting: void 0,
753
- isOpenRouterHost: d.isOpenRouter,
754
- wireModelIdMode,
755
- isVercelGatewayHost: isVercelGateway,
756
- supportsStrictMode: hostMatchesUrl(baseUrl, "openai") || hostMatchesUrl(baseUrl, "azureOpenAI") || hostMatchesUrl(baseUrl, "cerebras") || hostMatchesUrl(baseUrl, "together") || hostMatchesUrl(baseUrl, "openrouter") || hostMatchesUrl(baseUrl, "deepseekFamily"),
757
- extraBody: void 0,
758
- toolStrictMode: isCerebrasHost ? "all_strict" : "mixed",
759
- toolSchemaFlavor: d.isMoonshotNative || facts.is("kimi") ? "moonshot-mfjs" : d.isLocalOpenAICompatBackend ? "grammar" : void 0,
760
- streamFirstEventTimeoutMs: d.isLocalServingBackend ? 0 : void 0,
761
- streamIdleTimeoutMs,
762
- stripDeepseekSpecialTokens: facts.is("deepseek") && (provider === "nvidia" || provider === "deepseek"),
763
- streamMarkupHealingPattern: detectStreamMarkupHealing(spec.provider, facts, baseUrl),
764
- reasoningDeltasMayBeCumulative: false,
765
- emptyLengthFinishIsContextError: false,
766
- usesOpenAIToolCallIdLimit: false,
767
- promptCacheSessionHeader: hostMatchesUrl(baseUrl, "xai") ? "x-grok-conv-id" : void 0,
768
- dropThinkingWhenReasoningEffort: false,
769
- nativeKimiK3Reasoning: false,
770
- zaiReasoningEffortDialect: false,
771
- clampOutputToModelMax: false,
772
- stripImageInput: false,
773
- thinkingLoopGuard: void 0,
774
- rejectRootObjectUnion: false,
775
- retryWithoutStrictOnGrammarError: false,
776
- supportsPromptCacheKey: false
777
- };
778
- }
779
- const DSML_HEALING_PROVIDERS = {
780
- ollama: true,
781
- "ollama-cloud": true,
782
- nvidia: true,
783
- deepseek: true,
784
- fireworks: true,
785
- nanogpt: true,
786
- "opencode-go": true,
787
- openrouter: true
788
- };
789
- /**
790
- * Default leaked-markup healer. Kimi/DeepSeek dedicated grammars are keyed on
791
- * identity class; official OpenAI heals nothing; everything else defaults to
792
- * the generic `thinking` healer.
793
- */
794
- function detectStreamMarkupHealing(provider, facts, baseUrl) {
795
- const isKimiK2 = facts.is("kimi") && facts.identity.family?.startsWith("k2") === true;
796
- if (provider === "kimi-code" || provider === "moonshot" || isKimiK2) return "kimi";
797
- if (facts.is("deepseek") && DSML_HEALING_PROVIDERS[provider] === true) return "dsml";
798
- if (isOfficialOpenAIEndpoint(provider, baseUrl)) return void 0;
799
- return "thinking";
800
- }
801
- function fixupOpenAICompat(spec, compat, d, axes) {
802
- const deepseekThinking = compat.extraBody?.thinking;
803
- if (d.isDirectDeepseekReasoning && typeof deepseekThinking === "object" && deepseekThinking !== null && "type" in deepseekThinking && deepseekThinking.type === "enabled") {
804
- const extraBody = { ...compat.extraBody };
805
- delete extraBody.thinking;
806
- compat.extraBody = Object.keys(extraBody).length > 0 ? extraBody : void 0;
807
- }
808
- if (spec.compat?.reasoningDisableMode === void 0 && !("reasoningDisableMode" in axes.wire)) compat.reasoningDisableMode = d.isClinePass ? "cline-enabled-false" : d.requiresEnabledThinking ? "omit" : d.isDirectDeepseekReasoning ? "zai-thinking-disabled" : d.isVenice ? "venice-disable-thinking" : resolveReasoningDisableMode(compat.thinkingFormat);
809
- if (spec.compat?.omitReasoningEffort === void 0 && !("omitReasoningEffort" in axes.wire) && !compat.supportsReasoningEffort) compat.omitReasoningEffort = true;
810
- const axisWhenThinking = spec.reasoning ? objectPayload$1(axes.wire.whenThinking) : void 0;
811
- const whenThinkingPolicy = spec.compat?.whenThinking ?? axisWhenThinking ?? (d.isDirectDeepseekReasoning ? { extraBody: {
812
- ...compat.extraBody,
813
- thinking: { type: "enabled" }
814
- } } : void 0);
815
- if (whenThinkingPolicy) {
816
- const variant = {
817
- ...compat,
818
- whenThinking: void 0
819
- };
820
- applyCompatOverrides(variant, whenThinkingPolicy);
821
- if (Reflect.get(whenThinkingPolicy, "reasoningDisableMode") === void 0) variant.reasoningDisableMode = d.isVenice ? "venice-disable-thinking" : resolveReasoningDisableMode(variant.thinkingFormat);
822
- if (Reflect.get(whenThinkingPolicy, "omitReasoningEffort") === void 0 && !variant.supportsReasoningEffort) variant.omitReasoningEffort = true;
823
- compat.whenThinking = variant;
824
- } else compat.whenThinking = void 0;
825
- }
826
- function resolveOpenAICompletionsPolicy(spec, facts, axes) {
827
- const d = detectOpenAI(spec, facts);
828
- const compat = detectOpenAICompat(spec, d);
829
- applyWireAxes(compat, axes.wire, "openai-completions");
830
- applyCompatOverrides(compat, spec.compat);
831
- overlayEffortMapAxis(compat, axes, spec.compat);
832
- fixupOpenAICompat(spec, compat, d, axes);
833
- return compat;
834
- }
835
- /** Detected Responses-API baseline (ported from `buildOpenAIResponsesCompat`). */
836
- function resolveOpenAIResponsesPolicy(spec, facts, axes, api) {
837
- const baseUrl = spec.baseUrl ?? "";
838
- const provider = spec.provider;
839
- const hostModel = {
840
- provider,
841
- baseUrl
842
- };
843
- const isAzure = modelMatchesHost(hostModel, "azureOpenAI");
844
- const isOpenRouter = modelMatchesHost(hostModel, "openrouter");
845
- const isOpenAIUrl = hostMatchesUrl(baseUrl, "openai");
846
- const isVercelGateway = modelMatchesHost(hostModel, "vercelAIGateway");
847
- const isXaiHost = modelMatchesHost(hostModel, "xai");
848
- const supportsPromptCacheBreakpoints = isOfficialOpenAIEndpoint(provider, baseUrl) && facts.is("openai") && facts.revGte("5.6");
849
- const thinkingFormat = isOpenRouter ? "openrouter" : "openai";
850
- const reasoningCapable = Boolean(spec.reasoning);
851
- const isLocalServingBackend = PROXY_OPENAI_COMPAT_PROVIDERS[provider] !== true && LOCAL_OPENAI_COMPAT_PROVIDERS[provider] === true || hasLocalLoopbackBaseUrl(baseUrl);
852
- const isAnthropicModel = facts.is("anthropic");
853
- const isDeepseekFamily = facts.is("deepseek");
854
- const compat = {
855
- supportsDeveloperRole: isAzure || isOpenAIUrl || hostMatchesUrl(baseUrl, "githubCopilot"),
856
- supportsStrictMode: isAzure || hostMatchesUrl(baseUrl, "openai") || hostMatchesUrl(baseUrl, "azureOpenAI") || hostMatchesUrl(baseUrl, "cerebras") || hostMatchesUrl(baseUrl, "together") || hostMatchesUrl(baseUrl, "openrouter") || hostMatchesUrl(baseUrl, "deepseekFamily"),
857
- supportsReasoningEffort: !isXaiHost,
858
- supportsLongPromptCacheRetention: isOpenAIUrl,
859
- supportsPromptCacheBreakpoints,
860
- promptCacheBreakpointTtl: supportsPromptCacheBreakpoints ? "30m" : void 0,
861
- strictResponsesPairing: isAzure || provider === "github-copilot",
862
- supportsImageDetailOriginal: !isXaiHost && !modelMatchesHost(hostModel, "githubCopilot"),
863
- supportsReasoningSummary: !isXaiHost,
864
- supportsAllTurnsReasoningContext: false,
865
- supportsConfigurationUpdate: false,
866
- requiresReasoningOffJuiceInstruction: false,
867
- stripImageInput: false,
868
- thinkingLoopGuard: void 0,
869
- reasoningEffortMap: {},
870
- supportsReasoningParams: true,
871
- supportsSamplingParams: !(facts.is("openai") && (facts.family("o-series") || facts.revGte("5"))),
872
- supportsPenaltyAndStopParams: !isXaiHost,
873
- thinkingFormat,
874
- reasoningDisableMode: resolveReasoningDisableMode(thinkingFormat),
875
- omitReasoningEffort: false,
876
- includeEncryptedReasoning: true,
877
- filterReasoningHistory: isOpenRouter && isAnthropicModel,
878
- disableReasoningOnForcedToolChoice: facts.is("kimi"),
879
- disableReasoningOnToolChoice: isDeepseekFamily && reasoningCapable && !isOpenRouter,
880
- supportsToolChoice: true,
881
- supportsForcedToolChoice: provider !== "opencode-go" && provider !== "opencode-zen",
882
- supportsNamedToolChoice: true,
883
- reasoningContentField: "reasoning_content",
884
- requiresReasoningContentForToolCalls: (facts.is("kimi") || isDeepseekFamily && reasoningCapable || isOpenRouter && reasoningCapable) && reasoningCapable,
885
- requiresReasoningContentForAllAssistantTurns: isDeepseekFamily && reasoningCapable && !isOpenRouter,
886
- allowsSyntheticReasoningContentForToolCalls: !isDeepseekFamily || !reasoningCapable,
887
- replayReasoningContent: false,
888
- qwenPreserveThinking: false,
889
- qwenTemplateReasoningEffort: false,
890
- requiresThinkingAsText: false,
891
- requiresMistralToolIds: false,
892
- requiresToolResultName: false,
893
- requiresAssistantAfterToolResult: false,
894
- requiresAssistantContentForToolCalls: facts.is("kimi"),
895
- openRouterRouting: void 0,
896
- vercelGatewayRouting: void 0,
897
- isOpenRouterHost: isOpenRouter,
898
- isVercelGatewayHost: isVercelGateway,
899
- wireModelIdMode: isOpenRouter ? "openrouter" : "raw",
900
- toolSchemaFlavor: facts.is("kimi") ? "moonshot-mfjs" : void 0,
901
- alwaysSendMaxTokens: facts.is("kimi"),
902
- clampOutputToModelMax: false,
903
- supportsObfuscationOptOut: isOpenAIUrl || provider === "openai",
904
- officialEndpoint: isOfficialOpenAIEndpoint(provider, baseUrl),
905
- harmonyLeakMitigation: false,
906
- rejectRootObjectUnion: false,
907
- retryWithoutStrictOnGrammarError: false,
908
- cacheControlFormat: isOpenRouter && isAnthropicModel ? "anthropic" : void 0,
909
- stripDeepseekSpecialTokens: facts.is("deepseek") && (provider === "nvidia" || provider === "deepseek"),
910
- streamMarkupHealingPattern: detectStreamMarkupHealing(provider, facts, baseUrl),
911
- reasoningDeltasMayBeCumulative: false,
912
- emptyLengthFinishIsContextError: false,
913
- usesOpenAIToolCallIdLimit: false,
914
- promptCacheSessionHeader: hostMatchesUrl(baseUrl, "xai") ? "x-grok-conv-id" : void 0,
915
- streamFirstEventTimeoutMs: isLocalServingBackend ? 0 : spec.compat?.streamFirstEventTimeoutMs,
916
- streamIdleTimeoutMs: isLocalServingBackend ? LOCAL_OPENAI_COMPAT_STREAM_IDLE_TIMEOUT_MS : spec.compat?.streamIdleTimeoutMs
917
- };
918
- applyWireAxes(compat, axes.wire, api);
919
- applyCompatOverrides(compat, spec.compat);
920
- overlayEffortMapAxis(compat, axes, spec.compat);
921
- if (isXaiHost && "reasoningEffortMap" in axes.wire) {
922
- const canonical = effortRecord(axes.wire.reasoningEffortMap) ?? {};
923
- compat.reasoningEffortMap = {
924
- ...compat.reasoningEffortMap,
925
- ...canonical
926
- };
927
- for (const key of ["xhigh", "max"]) if (!(key in canonical)) delete compat.reasoningEffortMap[key];
928
- }
929
- if (spec.compat?.reasoningDisableMode === void 0 && !("reasoningDisableMode" in axes.wire)) compat.reasoningDisableMode = resolveReasoningDisableMode(compat.thinkingFormat);
930
- if (spec.compat?.omitReasoningEffort === void 0 && !("omitReasoningEffort" in axes.wire) && !compat.supportsReasoningEffort) compat.omitReasoningEffort = true;
931
- if (provider === "xai-oauth" && axes.wire.supportsReasoningEffort === true && spec.compat?.supportsReasoningEffort !== false) {
932
- compat.supportsReasoningEffort = true;
933
- compat.omitReasoningEffort = false;
934
- }
935
- return compat;
936
- }
937
- function pickResponsesOnly(compat) {
938
- return {
939
- supportsLongPromptCacheRetention: compat.supportsLongPromptCacheRetention,
940
- strictResponsesPairing: compat.strictResponsesPairing,
941
- supportsImageDetailOriginal: compat.supportsImageDetailOriginal,
942
- supportsObfuscationOptOut: compat.supportsObfuscationOptOut,
943
- supportsAllTurnsReasoningContext: compat.supportsAllTurnsReasoningContext,
944
- supportsConfigurationUpdate: compat.supportsConfigurationUpdate,
945
- officialEndpoint: compat.officialEndpoint,
946
- harmonyLeakMitigation: compat.harmonyLeakMitigation,
947
- cacheControlFormat: compat.cacheControlFormat,
948
- requiresReasoningOffJuiceInstruction: compat.requiresReasoningOffJuiceInstruction,
949
- supportsReasoningSummary: compat.supportsReasoningSummary,
950
- isVercelGatewayHost: compat.isVercelGatewayHost
951
- };
952
- }
953
- function resolveAnthropicPolicy(spec, facts, axes) {
954
- const baseUrl = spec.baseUrl;
955
- const official = isOfficialAnthropicApiUrl(baseUrl);
956
- const isCopilot = modelMatchesHost(spec, "githubCopilot");
957
- const isZenmux = modelMatchesHost(spec, "zenmux");
958
- const requiresThinkingEnabled = modelMatchesHost(spec, "moonshotNative") && facts.kimiMandatoryThinking;
959
- const isAzure = isAzureAnthropicRoute(baseUrl);
960
- const signingEndpoint = official || isCopilot || isZenmux || isAnthropicSigningProxyUrl(baseUrl);
961
- const compat = {
962
- officialEndpoint: official,
963
- signingEndpoint,
964
- supportsContextManagement: true,
965
- supportsOutputEffort: true,
966
- disableStrictTools: isAzure,
967
- disableAdaptiveThinking: false,
968
- allowAnthropicHeaderOverrides: false,
969
- supportsEagerToolInputStreaming: official,
970
- supportsLongCacheRetention: official,
971
- supportsMidConversationSystem: official && !facts.family("sonnet") && facts.anthropicAdaptiveGenAtLeast("4.8"),
972
- supportsTurnScopedSystem: false,
973
- supportsMidConversationToolChanges: false,
974
- supportsPerMessageEffort: false,
975
- supportsThinkingBindingControls: false,
976
- supportsForcedToolChoice: !requiresThinkingEnabled && !facts.family("fable", "mythos"),
977
- supportsSamplingParams: !facts.anthropicAdaptiveGenAtLeast("4.7"),
978
- requiresToolResultId: false,
979
- requiresThinkingEnabled,
980
- replayUnsignedThinking: !signingEndpoint && (Boolean(spec.reasoning) || modelMatchesHost(spec, "deepseekFamily")),
981
- escapeBuiltinToolNames: false,
982
- injectClaudeCodeInstruction: true,
983
- stripImageInput: false,
984
- thinkingLoopGuard: void 0,
985
- streamIdleTimeoutMs: spec.compat?.streamIdleTimeoutMs
986
- };
987
- applyWireAxes(compat, axes.wire, "anthropic-messages");
988
- applyCompatOverrides(compat, spec.compat);
989
- return compat;
990
- }
991
- const BEDROCK_REASONING_STREAM_IDLE_TIMEOUT_MS = 6e5;
992
- function resolveBedrockPolicy(spec, axes) {
993
- const compat = {
994
- promptCacheMode: "none",
995
- supportsLongPromptCacheRetention: false,
996
- promptCacheMinimumTokens: 0,
997
- promptCacheMaximumCheckpoints: 0
998
- };
999
- compat.streamIdleTimeoutMs = spec.reasoning ? BEDROCK_REASONING_STREAM_IDLE_TIMEOUT_MS : void 0;
1000
- applyWireAxes(compat, axes.wire, "bedrock-converse-stream");
1001
- applyCompatOverrides(compat, spec.compat);
1002
- return compat;
1003
- }
1004
- function resolveDevinPolicy(spec, axes) {
1005
- const compat = {
1006
- trustExplicitThinkingOnly: true,
1007
- modelRouter: false,
1008
- supportsParallelToolCalls: false
1009
- };
1010
- applyWireAxes(compat, axes.wire, "devin-agent");
1011
- applyCompatOverrides(compat, spec.compat);
1012
- return compat;
1013
- }
1014
- function resolveGooglePolicy(spec, axes) {
1015
- const compat = {
1016
- supportsFunctionPartId: false,
1017
- requiresSkipThoughtSignature: false,
1018
- requiresSkipThoughtSignatureOnFirstFunctionCall: false,
1019
- dropUnsignedThinking: false,
1020
- ccaLegacyParametersSchema: false,
1021
- multimodalFunctionResponse: false,
1022
- flashStreamLeakWorkaround: false,
1023
- claudeThinkingBetaHeader: false,
1024
- antigravityClaudeToolMode: false,
1025
- stripImageInput: false
1026
- };
1027
- applyWireAxes(compat, axes.wire, spec.api);
1028
- applyCompatOverrides(compat, spec.compat);
1029
- return compat;
1030
- }
1031
- const DEFAULT_REASONING_EFFORTS = [
1032
- "minimal",
1033
- "low",
1034
- "medium",
1035
- "high"
1036
- ];
1037
- const DEFAULT_REASONING_EFFORTS_WITH_XHIGH = [...DEFAULT_REASONING_EFFORTS, "xhigh"];
1038
- function omitsWireReasoningEffort(api, compat) {
1039
- if (api !== "openai-responses" && api !== "openai-codex-responses" && api !== "azure-openai-responses") return false;
1040
- return compat !== void 0 && "supportsReasoningEffort" in compat && compat.supportsReasoningEffort === false;
1041
- }
1042
- function readCompatEffortMap(compat) {
1043
- if (compat === void 0 || !("reasoningEffortMap" in compat)) return void 0;
1044
- const map = compat.reasoningEffortMap;
1045
- return map && Object.keys(map).length > 0 ? map : void 0;
1046
- }
1047
- /** Host-quirk effort remaps detected outside the rules (URL/API compounds). */
1048
- const FIREWORKS_THINKING_EFFORT_MAP = { ["minimal"]: "none" };
1049
- /** Identity/API-derived default control mode; `thinking-mode` rules override. */
1050
- function defaultThinkingMode(spec, facts) {
1051
- switch (spec.api) {
1052
- case "google-generative-ai":
1053
- case "google-gemini-cli":
1054
- case "google-vertex": return facts.is("gemini") && facts.revMajor() === 3 ? "google-level" : "budget";
1055
- case "anthropic-messages":
1056
- if (facts.is("minimax") && facts.family("m2", "m3")) return "anthropic-adaptive";
1057
- if (facts.is("glm") && facts.revGte("5.2") && (spec.provider === "umans" || spec.provider === "zai")) return "anthropic-budget-effort";
1058
- if (facts.is("anthropic")) {
1059
- if (facts.revGte("4.6") && !facts.family("haiku")) return "anthropic-adaptive";
1060
- if (facts.family("opus") && facts.revGte("4.5")) return "anthropic-budget-effort";
1061
- }
1062
- return "budget";
1063
- case "bedrock-converse-stream":
1064
- if (facts.is("anthropic")) {
1065
- if (facts.anthropicAdaptiveGenAtLeast("4.6")) return "anthropic-adaptive";
1066
- if (facts.family("opus") && facts.revGte("4.5")) return "anthropic-budget-effort";
1067
- }
1068
- if (facts.is("openai")) return "effort";
1069
- return "budget";
1070
- default: return "effort";
1071
- }
1072
- }
1073
- /** API/compat-generic fallback ladder for targets no rule covered. */
1074
- function fallbackEfforts(spec, compat) {
1075
- if (spec.api === "anthropic-messages") return DEFAULT_REASONING_EFFORTS_WITH_XHIGH;
1076
- if (spec.api === "bedrock-converse-stream") return DEFAULT_REASONING_EFFORTS;
1077
- if ((spec.api === "openai-completions" || spec.api === "openrouter") && compat !== void 0 && "thinkingFormat" in compat) {
1078
- if (compat.thinkingFormat === "openai" && compat.supportsReasoningEffort) return DEFAULT_REASONING_EFFORTS_WITH_XHIGH;
1079
- return DEFAULT_REASONING_EFFORTS;
1080
- }
1081
- if (spec.api === "openai-responses" || spec.api === "openai-codex-responses" || spec.api === "azure-openai-responses") return DEFAULT_REASONING_EFFORTS_WITH_XHIGH;
1082
- return DEFAULT_REASONING_EFFORTS;
1083
- }
1084
- function filterEffortMap(map, efforts) {
1085
- let filtered;
1086
- for (const effort of efforts) {
1087
- const mapped = map[effort];
1088
- if (mapped === void 0) continue;
1089
- filtered ??= {};
1090
- filtered[effort] = mapped;
1091
- }
1092
- return filtered;
1093
- }
1094
- function readRuleThinking(axes) {
1095
- const raw = axes.thinking;
1096
- const out = {};
1097
- const mode = thinkingMode(raw.mode);
1098
- if (mode !== void 0) out.mode = mode;
1099
- const efforts = effortList(raw.efforts);
1100
- if (efforts !== void 0) out.efforts = efforts;
1101
- const defaultLevel = effortValue(raw.defaultLevel);
1102
- if (defaultLevel !== void 0) out.defaultLevel = defaultLevel;
1103
- const effortMap = effortRecord(raw.effortMap);
1104
- if (effortMap !== void 0) out.effortMap = effortMap;
1105
- const effortBudgets = effortNumberRecord(raw.effortBudgets);
1106
- if (effortBudgets !== void 0) out.effortBudgets = effortBudgets;
1107
- if (typeof raw.requiresEffort === "boolean") out.requiresEffort = raw.requiresEffort;
1108
- if (typeof raw.suppressWhenOff === "boolean") out.suppressWhenOff = raw.suppressWhenOff;
1109
- if (typeof raw.supportsDisplay === "boolean") out.supportsDisplay = raw.supportsDisplay;
1110
- if (typeof raw.prefixBinding === "boolean") out.prefixBinding = raw.prefixBinding;
1111
- if (typeof raw.upgradeNeutral === "boolean") out.upgradeNeutral = raw.upgradeNeutral;
1112
- return out;
1113
- }
1114
- /** Identity-derived `requiresEffort` default (mandatory-reasoning lineages). */
1115
- function impliesMandatoryReasoning(facts, modelId) {
1116
- if (facts.identity.thinkingVariant) return true;
1117
- if (stripThinkingVariantSuffix(modelId) !== void 0) return true;
1118
- return false;
1119
- }
1120
- function isQwenTemplateReasoningEffortCompat(compat) {
1121
- return compat !== void 0 && "qwenTemplateReasoningEffort" in compat && compat.qwenTemplateReasoningEffort === true;
1122
- }
1123
- function resolveThinkingPolicy(spec, facts, axes, compat) {
1124
- const rule = readRuleThinking(axes);
1125
- const explicitThinking = spec.thinking !== void 0 && Array.isArray(spec.thinking.efforts) && spec.thinking.efforts.length > 0 ? spec.thinking : void 0;
1126
- if (!spec.reasoning && (explicitThinking !== void 0 || rule.upgradeNeutral !== true)) return void 0;
1127
- if (spec.provider === "cline-pass" && compat !== void 0 && "supportsReasoningEffort" in compat && compat.supportsReasoningEffort === false) return;
1128
- if (omitsWireReasoningEffort(spec.api, compat)) return void 0;
1129
- if (explicitThinking !== void 0) return fillExplicitThinking(spec, facts, compat, explicitThinking, rule);
1130
- if (compat !== void 0 && "trustExplicitThinkingOnly" in compat && compat.trustExplicitThinkingOnly === true) return;
1131
- const config = {
1132
- mode: rule.mode ?? defaultThinkingMode(spec, facts),
1133
- efforts: rule.efforts ?? fallbackEfforts(spec, compat)
1134
- };
1135
- if (config.efforts.length === 0) throw new Error(`Model ${spec.provider}/${spec.id} resolved to an empty thinking range`);
1136
- if (rule.defaultLevel !== void 0) config.defaultLevel = rule.defaultLevel;
1137
- const effortMap = mergeEffortMap(spec, rule.effortMap, compat, config.efforts);
1138
- if (effortMap !== void 0) config.effortMap = effortMap;
1139
- if (rule.effortBudgets !== void 0) config.effortBudgets = rule.effortBudgets;
1140
- if (rule.supportsDisplay ?? defaultSupportsDisplay(spec, facts)) config.supportsDisplay = true;
1141
- if (rule.prefixBinding) config.prefixBinding = true;
1142
- if (rule.requiresEffort ?? (impliesMandatoryReasoning(facts, spec.id) || isQwenTemplateReasoningEffortCompat(compat))) config.requiresEffort = true;
1143
- if (rule.suppressWhenOff) config.suppressWhenOff = true;
1144
- return config;
1145
- }
1146
- /**
1147
- * Displayable-thinking default: an api-conditioned lineage fact (Anthropic
1148
- * wire dialects streaming adaptive Claude 4.7+ thinking) that KDL cannot
1149
- * express — cascade selectors have no api dimension. `thinking-supports-display`
1150
- * rules override per deployment.
1151
- */
1152
- function defaultSupportsDisplay(spec, facts) {
1153
- return (spec.api === "anthropic-messages" || spec.api === "bedrock-converse-stream") && facts.anthropicAdaptiveGenAtLeast("4.7");
1154
- }
1155
- function mergeEffortMap(spec, ruleMap, compat, efforts) {
1156
- const detected = (spec.api === "openai-completions" || spec.api === "openrouter") && modelMatchesHost({
1157
- provider: spec.provider,
1158
- baseUrl: spec.baseUrl ?? ""
1159
- }, "fireworks") ? FIREWORKS_THINKING_EFFORT_MAP : void 0;
1160
- const configured = readCompatEffortMap(compat);
1161
- if (detected === void 0 && ruleMap === void 0 && configured === void 0) return void 0;
1162
- return filterEffortMap({
1163
- ...detected,
1164
- ...ruleMap,
1165
- ...configured
1166
- }, efforts);
1167
- }
1168
- /**
1169
- * Backfill missing wire/default fields onto explicit thinking metadata.
1170
- * Explicit spec thinking is layer 4 of the resolution order: its ladder and
1171
- * every explicitly-set field always win; only absent fields are filled from
1172
- * the rules and identity-derived defaults.
1173
- */
1174
- function fillExplicitThinking(spec, facts, compat, thinking, rule) {
1175
- const effortMap = thinking.effortMap === void 0 ? mergeEffortMap(spec, rule.effortMap, compat, thinking.efforts) : void 0;
1176
- const needsDisplay = thinking.supportsDisplay === void 0 && (rule.supportsDisplay ?? defaultSupportsDisplay(spec, facts));
1177
- const needsRequiresEffort = thinking.requiresEffort === void 0 && (rule.requiresEffort ?? (impliesMandatoryReasoning(facts, spec.id) || isQwenTemplateReasoningEffortCompat(compat)));
1178
- const needsDefaultLevel = thinking.defaultLevel === void 0 && rule.defaultLevel !== void 0;
1179
- const needsPrefixBinding = thinking.prefixBinding === void 0 && rule.prefixBinding === true;
1180
- if (effortMap === void 0 && !needsDisplay && !needsRequiresEffort && !needsDefaultLevel && !needsPrefixBinding) return thinking;
1181
- const filled = { ...thinking };
1182
- if (effortMap !== void 0) filled.effortMap = effortMap;
1183
- if (needsDisplay) filled.supportsDisplay = true;
1184
- if (needsDefaultLevel && rule.defaultLevel !== void 0) filled.defaultLevel = rule.defaultLevel;
1185
- if (needsRequiresEffort) filled.requiresEffort = true;
1186
- if (needsPrefixBinding) filled.prefixBinding = true;
1187
- return filled;
1188
- }
1189
- function buildResolveTarget(spec, identity) {
1190
- const target = {
1191
- provider: spec.provider,
1192
- api: spec.api,
1193
- class: identity.class,
1194
- model: spec.id,
1195
- reasoning: Boolean(spec.reasoning)
1196
- };
1197
- if (identity.family !== void 0) target.family = identity.family;
1198
- if (identity.revision !== void 0) target.revision = identity.revision;
1199
- return target;
1200
- }
1201
- function specUsesApi(spec, api) {
1202
- return spec.api === api;
1203
- }
1204
- function resolveModelPolicy(spec) {
1205
- const identity = resolveIdentity(spec);
1206
- const facts = new IdentityFacts(identity);
1207
- const axes = resolveCascade(buildResolveTarget(spec, identity));
1208
- let compat;
1209
- if (specUsesApi(spec, "openrouter")) {
1210
- const chat = resolveOpenAICompletionsPolicy(spec, facts, axes);
1211
- const responses = resolveOpenAIResponsesPolicy(spec, facts, axes, "openrouter");
1212
- compat = {
1213
- ...chat,
1214
- ...pickResponsesOnly(responses)
1215
- };
1216
- } else if (specUsesApi(spec, "openai-completions")) compat = resolveOpenAICompletionsPolicy(spec, facts, axes);
1217
- else if (specUsesApi(spec, "openai-responses") || specUsesApi(spec, "azure-openai-responses") || specUsesApi(spec, "openai-codex-responses")) compat = resolveOpenAIResponsesPolicy(spec, facts, axes, spec.api);
1218
- else if (specUsesApi(spec, "anthropic-messages")) compat = resolveAnthropicPolicy(spec, facts, axes);
1219
- else if (specUsesApi(spec, "bedrock-converse-stream")) compat = resolveBedrockPolicy(spec, axes);
1220
- else if (specUsesApi(spec, "devin-agent")) compat = resolveDevinPolicy(spec, axes);
1221
- else if (specUsesApi(spec, "google-generative-ai") || specUsesApi(spec, "google-vertex") || specUsesApi(spec, "google-gemini-cli")) compat = resolveGooglePolicy(spec, axes);
1222
- else compat = void 0;
1223
- return {
1224
- identity,
1225
- compat,
1226
- thinking: resolveThinkingPolicy(spec, facts, axes, compat),
1227
- catalog: axes.catalog
1228
- };
1229
- }
1230
- //#endregion
1231
- //#region node_modules/.pnpm/@oh-my-pi+pi-catalog@18.1.17/node_modules/@oh-my-pi/pi-catalog/src/model-tokenizer.ts
1232
- const MAX_TOKENIZER_CACHE_ENTRIES = 2048;
1233
- const modelTokenizerCache = /* @__PURE__ */ new Map();
1234
- function revisionAtLeast$1(revision, floor) {
1235
- if (revision === void 0) return false;
1236
- const parsedRevision = parseRevision(revision);
1237
- const parsedFloor = parseRevision(floor);
1238
- return parsedRevision !== void 0 && parsedFloor !== void 0 && compareRevision(parsedRevision, parsedFloor) >= 0;
1239
- }
1240
- function claudeTokenizer(identity) {
1241
- if (identity.class !== "anthropic") return void 0;
1242
- if (identity.family === "opus") {
1243
- if (revisionAtLeast$1(identity.revision, "5")) return "claude-v5";
1244
- if (revisionAtLeast$1(identity.revision, "4.7")) return "claude-v47";
1245
- return "claude-v3";
1246
- }
1247
- if (identity.family === "sonnet" || identity.family === "fable" || identity.family === "mythos") return revisionAtLeast$1(identity.revision, "5") ? "claude-v5-sonnet" : "claude-v3";
1248
- return "claude-v3";
1249
- }
1250
- function qwenTokenizer(identity) {
1251
- return identity.class === "qwen" && revisionAtLeast$1(identity.revision, "3.5") ? "qwen3" : void 0;
1252
- }
1253
- function deepSeekTokenizer(identity) {
1254
- return identity.class === "deepseek" ? "deepseek-v3" : void 0;
1255
- }
1256
- function kimiTokenizer(identity) {
1257
- return identity.class === "kimi" ? "kimi-k2" : void 0;
1258
- }
1259
- function glmTokenizer(identity) {
1260
- return identity.class === "glm" && revisionAtLeast$1(identity.revision, "5") ? "glm5" : void 0;
1261
- }
1262
- /**
1263
- * Resolve the exact locally embedded tokenizer for a canonical model id.
1264
- *
1265
- * This is catalog policy, not a runtime caller heuristic: [`buildModel`](./build.ts)
1266
- * materializes the result as `Model.tokenizer`; consumers read that property.
1267
- */
1268
- function resolveModelTokenizer(modelId) {
1269
- const cached = modelTokenizerCache.get(modelId);
1270
- if (cached !== void 0) return cached ?? void 0;
1271
- const identity = classifyModel("", bareModelId(modelId), { lenient: true });
1272
- const tokenizer = claudeTokenizer(identity) ?? qwenTokenizer(identity) ?? deepSeekTokenizer(identity) ?? kimiTokenizer(identity) ?? glmTokenizer(identity);
1273
- if (modelTokenizerCache.size === MAX_TOKENIZER_CACHE_ENTRIES) modelTokenizerCache.clear();
1274
- modelTokenizerCache.set(modelId, tokenizer ?? null);
1275
- return tokenizer;
1276
- }
1277
- //#endregion
1278
- //#region node_modules/.pnpm/@oh-my-pi+pi-catalog@18.1.17/node_modules/@oh-my-pi/pi-catalog/src/pricing.ts
1279
- function nonnegative(value) {
1280
- return typeof value === "number" && Number.isFinite(value) && value >= 0;
1281
- }
1282
- function isRates(value) {
1283
- return isRecord(value) && nonnegative(value.input) && nonnegative(value.output) && nonnegative(value.cacheRead) && nonnegative(value.cacheWrite);
1284
- }
1285
- function isLongContext(value) {
1286
- return isRecord(value) && isRates(value) && typeof value.inputThreshold === "number" && Number.isFinite(value.inputThreshold) && value.inputThreshold > 0 && (value.inputThresholdInclusive === void 0 || typeof value.inputThresholdInclusive === "boolean");
1287
- }
1288
- function isPeakWindow(value) {
1289
- return isRecord(value) && Array.isArray(value.weekdays) && value.weekdays.length > 0 && value.weekdays.every((day) => Number.isInteger(day) && day >= 0 && day <= 6) && new Set(value.weekdays).size === value.weekdays.length && typeof value.startMinute === "number" && Number.isInteger(value.startMinute) && typeof value.endMinute === "number" && Number.isInteger(value.endMinute) && value.startMinute >= 0 && value.endMinute <= 1440 && value.startMinute < value.endMinute;
1290
- }
1291
- function isEffectiveRate(value) {
1292
- return isRecord(value) && isRates(value) && typeof value.effectiveFrom === "number" && Number.isSafeInteger(value.effectiveFrom) && Math.abs(value.effectiveFrom) <= 864e13 && (value.longContext === void 0 || isLongContext(value.longContext));
1293
- }
1294
- /** Validate serialized schedules before admitting cached model rows. */
1295
- function isTimeBasedCost(value) {
1296
- if (!isRecord(value) || !nonnegative(value.offPeakMultiplier) || !Array.isArray(value.peakWindows) || !value.peakWindows.every(isPeakWindow)) return false;
1297
- if (value.effectiveRates === void 0) return true;
1298
- if (!Array.isArray(value.effectiveRates) || !value.effectiveRates.every(isEffectiveRate)) return false;
1299
- const dates = /* @__PURE__ */ new Set();
1300
- for (const rate of value.effectiveRates) {
1301
- if (dates.has(rate.effectiveFrom)) return false;
1302
- dates.add(rate.effectiveFrom);
1303
- }
1304
- return true;
1305
- }
1306
- function payload(value, keys, field) {
1307
- if (!isRecord(value) || Object.keys(value).some((key) => !keys.includes(key))) throw new Error(`Invalid time-based-cost ${field}`);
1308
- return value;
1309
- }
1310
- function namedEntries(value, field) {
1311
- if (!isRecord(value)) throw new Error(`Invalid time-based-cost ${field}: expected named objects`);
1312
- return Object.values(value);
1313
- }
1314
- /** KDL object children are named records; normalize them once while constructing the model. */
1315
- function materializeTimeBasedCost(value) {
1316
- const source = payload(value, [
1317
- "offPeakMultiplier",
1318
- "peakWindows",
1319
- "effectiveRates"
1320
- ], "schedule");
1321
- const peakWindows = namedEntries(source.peakWindows, "peak-windows").map((entry) => {
1322
- const window = payload(entry, [
1323
- "weekdays",
1324
- "startMinute",
1325
- "endMinute"
1326
- ], "peak-window");
1327
- if (typeof window.weekdays !== "string" || !/^[0-6](,[0-6])*$/.test(window.weekdays)) throw new Error("Invalid time-based-cost weekdays: expected comma-separated UTC weekday numbers");
1328
- return {
1329
- ...window,
1330
- weekdays: window.weekdays.split(",").map(Number)
1331
- };
1332
- });
1333
- const effectiveRates = source.effectiveRates === void 0 ? void 0 : namedEntries(source.effectiveRates, "effective-rates").map((entry) => {
1334
- const rate = payload(entry, [
1335
- "effectiveFrom",
1336
- "input",
1337
- "output",
1338
- "cacheRead",
1339
- "cacheWrite",
1340
- "longContext"
1341
- ], "effective-rate");
1342
- const date = rate.effectiveFrom;
1343
- if (typeof date !== "string" || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z$/.test(date)) throw new Error("Invalid time-based-cost effective-from: expected an ISO UTC timestamp");
1344
- const effectiveFrom = Date.parse(date);
1345
- if (!Number.isFinite(effectiveFrom) || new Date(effectiveFrom).toISOString() !== (date.includes(".") ? date : date.replace("Z", ".000Z"))) throw new Error("Invalid time-based-cost effective-from: invalid UTC date");
1346
- if (rate.longContext !== void 0) payload(rate.longContext, [
1347
- "inputThreshold",
1348
- "inputThresholdInclusive",
1349
- "input",
1350
- "output",
1351
- "cacheRead",
1352
- "cacheWrite"
1353
- ], "long-context");
1354
- return {
1355
- ...rate,
1356
- effectiveFrom
1357
- };
1358
- });
1359
- const schedule = {
1360
- offPeakMultiplier: source.offPeakMultiplier,
1361
- peakWindows,
1362
- ...effectiveRates && { effectiveRates }
1363
- };
1364
- if (!isTimeBasedCost(schedule)) throw new Error("Invalid time-based-cost schedule: invalid windows, rates, or multiplier");
1365
- return schedule;
1366
- }
1367
- //#endregion
1368
- //#region node_modules/.pnpm/@oh-my-pi+pi-catalog@18.1.17/node_modules/@oh-my-pi/pi-catalog/src/build.ts
1369
- /**
1370
- * The single Model constructor. Resolution runs through the compat engine
1371
- * (`compat/resolve`): identity classification, cascade-rule axes, host
1372
- * detection, and spec overrides materialize exactly once per spec.
1373
- *
1374
- * Request handlers read fields — they never detect, parse ids, or allocate
1375
- * compat per request.
1376
- */
1377
- function numberField(source, key) {
1378
- const value = Reflect.get(source, key);
1379
- return typeof value === "number" ? value : void 0;
1380
- }
1381
- /** Narrow an unknown compiled-axis payload to an object payload. */
1382
- function objectPayload(value) {
1383
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
1384
- }
1385
- /** Narrow a compiled `input-modalities` axis value to the model input union. */
1386
- function isInputModalities(value) {
1387
- return Array.isArray(value) && value.every((entry) => entry === "text" || entry === "image");
1388
- }
1389
- /**
1390
- * Applies resolved catalog-data axes onto the model: reviewed metadata
1391
- * corrections (`cost-patch`, `limits-patch`, `long-context-cost`,
1392
- * `context-window-floor`) overwrite upstream values; selection metadata
1393
- * (`priority`, `apply-patch-tool-type`, `service-tier-cost`,
1394
- * `requires-cursor-tool-schema-projection`) is rule-owned;
1395
- * `context-promotion-target` fills only when the spec left it unset.
1396
- */
1397
- function applyCatalogAssignments(model, catalog) {
1398
- const serviceTierCost = objectPayload(catalog.serviceTierCost);
1399
- if (serviceTierCost !== void 0) {
1400
- const flex = numberField(serviceTierCost, "flex");
1401
- const priorityTier = numberField(serviceTierCost, "priority");
1402
- model.serviceTierCost = {
1403
- ...flex !== void 0 && { flex },
1404
- ...priorityTier !== void 0 && { priority: priorityTier }
1405
- };
1406
- }
1407
- const priority = catalog.priority;
1408
- if (typeof priority === "number") model.priority = priority;
1409
- const applyPatchToolType = catalog.applyPatchToolType;
1410
- if (applyPatchToolType === "freeform" || applyPatchToolType === "function") model.applyPatchToolType = applyPatchToolType;
1411
- const editPromptVariant = catalog.editPromptVariant;
1412
- if (editPromptVariant === "full" || editPromptVariant === "compact") model.editPromptVariant = editPromptVariant;
1413
- if (catalog.requiresCursorToolSchemaProjection === true) model.requiresCursorToolSchemaProjection = true;
1414
- else delete model.requiresCursorToolSchemaProjection;
1415
- const contextPromotionTarget = catalog.contextPromotionTarget;
1416
- if (typeof contextPromotionTarget === "string" && model.contextPromotionTarget === void 0) model.contextPromotionTarget = contextPromotionTarget;
1417
- }
1418
- /**
1419
- * Applies reviewed catalog-data value corrections (`cost-patch`,
1420
- * `limits-patch`, `long-context-cost`, `context-window-floor`,
1421
- * `input-modalities`) onto an upstream-sourced spec. Applied by
1422
- * `buildModel` to every upstream-sourced spec; user-authored overrides are
1423
- * recomposed after building by the override applicators, so explicit user
1424
- * limits and pricing still win.
1425
- */
1426
- function applyCatalogCorrections(model, catalog) {
1427
- const longContext = objectPayload(catalog.longContext);
1428
- if (longContext !== void 0) {
1429
- const inputThreshold = numberField(longContext, "inputThreshold");
1430
- const inclusive = Reflect.get(longContext, "inputThresholdInclusive") === true;
1431
- const multiplier = numberField(longContext, "multiplier");
1432
- const input = numberField(longContext, "input");
1433
- const output = numberField(longContext, "output");
1434
- const cacheRead = numberField(longContext, "cacheRead");
1435
- const cacheWrite = numberField(longContext, "cacheWrite");
1436
- const base = model.cost;
1437
- const hasTokenPrice = base.input !== 0 || base.output !== 0 || base.cacheRead !== 0 || base.cacheWrite !== 0;
1438
- if (inputThreshold !== void 0 && multiplier !== void 0 && hasTokenPrice) model.cost = {
1439
- ...base,
1440
- longContext: {
1441
- inputThreshold,
1442
- ...inclusive && { inputThresholdInclusive: true },
1443
- input: base.input * multiplier,
1444
- output: base.output * multiplier,
1445
- cacheRead: base.cacheRead * multiplier,
1446
- cacheWrite: base.cacheWrite * multiplier
1447
- }
1448
- };
1449
- else if (inputThreshold !== void 0 && input !== void 0 && output !== void 0 && cacheRead !== void 0 && cacheWrite !== void 0) model.cost = {
1450
- ...model.cost,
1451
- longContext: {
1452
- inputThreshold,
1453
- input,
1454
- output,
1455
- cacheRead,
1456
- cacheWrite
1457
- }
1458
- };
1459
- }
1460
- const patch = objectPayload(catalog.costPatch);
1461
- if (patch !== void 0) {
1462
- model.cost = { ...model.cost };
1463
- const input = numberField(patch, "input");
1464
- if (input !== void 0) model.cost.input = input;
1465
- const output = numberField(patch, "output");
1466
- if (output !== void 0) model.cost.output = output;
1467
- const cacheRead = numberField(patch, "cacheRead");
1468
- if (cacheRead !== void 0) model.cost.cacheRead = cacheRead;
1469
- const cacheWrite = numberField(patch, "cacheWrite");
1470
- if (cacheWrite !== void 0) model.cost.cacheWrite = cacheWrite;
1471
- }
1472
- if (catalog.timeBased !== void 0) model.cost = {
1473
- ...model.cost,
1474
- timeBased: materializeTimeBasedCost(catalog.timeBased)
1475
- };
1476
- const limitsPatch = objectPayload(catalog.limitsPatch);
1477
- if (limitsPatch !== void 0) {
1478
- const contextWindow = numberField(limitsPatch, "contextWindow");
1479
- if (contextWindow !== void 0) model.contextWindow = contextWindow;
1480
- const maxTokens = numberField(limitsPatch, "maxTokens");
1481
- if (maxTokens !== void 0) model.maxTokens = maxTokens;
1482
- }
1483
- const contextWindowFloor = catalog.contextWindowFloor;
1484
- if (typeof contextWindowFloor === "number") model.contextWindow = Math.max(model.contextWindow ?? 0, contextWindowFloor);
1485
- const inputModalities = catalog.inputModalities;
1486
- if (isInputModalities(inputModalities)) model.input = inputModalities;
1487
- }
1488
- /**
1489
- * Direct first-party OpenAI Responses endpoints (api.openai.com, Azure OpenAI
1490
- * deployments). Gates GA computer-use detection; identity supplies the model
1491
- * generation.
1492
- */
1493
- function isDirectOpenAIResponsesEndpoint(spec) {
1494
- if (spec.api === "openai-responses") {
1495
- if (spec.provider !== "openai") return false;
1496
- if (!spec.baseUrl) return true;
1497
- try {
1498
- const url = new URL(spec.baseUrl);
1499
- return url.protocol === "https:" && url.hostname === "api.openai.com";
1500
- } catch {
1501
- return false;
1502
- }
1503
- }
1504
- if (spec.api !== "azure-openai-responses" || spec.provider !== "azure" && spec.provider !== "azure-openai") return false;
1505
- if (!spec.baseUrl) return true;
1506
- try {
1507
- const url = new URL(spec.baseUrl);
1508
- return url.protocol === "https:" && (url.hostname.endsWith(".openai.azure.com") || url.hostname === "models.inference.ai.azure.com");
1509
- } catch {
1510
- return false;
1511
- }
1512
- }
1513
- function explicitComputerUseConfig(spec) {
1514
- if (!("supportsComputerUseConfig" in spec)) return spec.supportsComputerUse;
1515
- const value = Reflect.get(spec, "supportsComputerUseConfig");
1516
- return typeof value === "boolean" ? value : void 0;
1517
- }
1518
- function revisionAtLeast(identity, major, minor) {
1519
- if (identity.revision === void 0) return false;
1520
- const [revMajor = 0, revMinor = 0] = identity.revision.split(".").map(Number);
1521
- return revMajor > major || revMajor === major && revMinor >= minor;
1522
- }
1523
- function supportsOpenAIGAComputerUse(spec, identity, explicitSupport) {
1524
- if (explicitSupport !== void 0) return explicitSupport;
1525
- if (!isDirectOpenAIResponsesEndpoint(spec)) return false;
1526
- const wireIdentity = spec.requestModelId === void 0 ? identity : resolveModelPolicy({
1527
- ...spec,
1528
- id: spec.requestModelId
1529
- }).identity;
1530
- return wireIdentity.class === "openai" && revisionAtLeast(wireIdentity, 5, 4);
1531
- }
1532
- /**
1533
- * Build one model from an authored spec. Bundled models.json rows are fully
1534
- * materialized by the generator and consumed directly (see `models.ts`), so
1535
- * this only runs for discovered/custom/override specs.
1536
- */
1537
- function buildModel(spec) {
1538
- const policy = resolveModelPolicy(spec);
1539
- const supportsComputerUseConfig = explicitComputerUseConfig(spec);
1540
- const model = {
1541
- ...spec,
1542
- reasoning: spec.reasoning || policy.thinking !== void 0,
1543
- name: cleanModelName(spec.name),
1544
- identity: policy.identity,
1545
- requiresGlyphTokenization: policy.identity.class === "anthropic",
1546
- tokenizer: spec.tokenizer ?? resolveModelTokenizer(spec.requestModelId ?? spec.id),
1547
- thinking: policy.thinking,
1548
- supportsComputerUse: supportsOpenAIGAComputerUse(spec, policy.identity, supportsComputerUseConfig),
1549
- supportsComputerUseConfig,
1550
- compat: policy.compat,
1551
- compatConfig: spec.compat
1552
- };
1553
- applyCatalogAssignments(model, policy.catalog);
1554
- applyCatalogCorrections(model, policy.catalog);
1555
- return model;
1556
- }
1557
- //#endregion
1558
- //#region node_modules/.pnpm/@oh-my-pi+pi-catalog@18.1.17/node_modules/@oh-my-pi/pi-catalog/src/compat/types.ts
1559
- /**
1560
- * Revision placeholder in a templated `variant-family` (`gemini-{rev}-flash`).
1561
- * A family whose id carries it is instantiated once per live revision that
1562
- * discovery advertises, so new generations of a lineage collapse without a
1563
- * new reviewed entry.
1564
- */
1565
- const REVISION_PLACEHOLDER = "{rev}";
1566
- //#endregion
1567
- //#region node_modules/.pnpm/@oh-my-pi+pi-catalog@18.1.17/node_modules/@oh-my-pi/pi-catalog/src/compat/collapse.ts
1568
- const VARIANT_ROUTING_KEYS = ["off", ...THINKING_EFFORTS];
1569
- const DEFAULT_PAIR_EFFORTS = [
1570
- "minimal",
1571
- "low",
1572
- "medium",
1573
- "high"
1574
- ];
1575
- /**
1576
- * Build one effort-tier family from a tier→wire-id map: routing keeps only the
1577
- * listed efforts, `members` dedupes the targets in tier order, and thinking is
1578
- * `mode: "effort"` (mandatory when the family has no `off` route). Shared by the
1579
- * Devin and Cursor tables, whose per-effort siblings follow the same shape.
1580
- */
1581
- function tierFamily(id, name, routes, efforts, defaultMember) {
1582
- const routing = {};
1583
- if (routes.off) routing.off = routes.off;
1584
- for (const effort of efforts) switch (effort) {
1585
- case "minimal":
1586
- if (routes.minimal) routing[effort] = routes.minimal;
1587
- break;
1588
- case "low":
1589
- if (routes.low) routing[effort] = routes.low;
1590
- break;
1591
- case "medium":
1592
- if (routes.medium) routing[effort] = routes.medium;
1593
- break;
1594
- case "high":
1595
- if (routes.high) routing[effort] = routes.high;
1596
- break;
1597
- case "xhigh":
1598
- if (routes.xhigh) routing[effort] = routes.xhigh;
1599
- break;
1600
- case "max": if (routes.max) routing[effort] = routes.max;
1601
- }
1602
- return {
1603
- id,
1604
- name,
1605
- members: [
1606
- routes.off,
1607
- routes.minimal,
1608
- routes.low,
1609
- routes.medium,
1610
- routes.high,
1611
- routes.xhigh,
1612
- routes.max
1613
- ].filter((member, index, items) => typeof member === "string" && items.indexOf(member) === index),
1614
- routing,
1615
- thinking: {
1616
- mode: "effort",
1617
- efforts,
1618
- ...routes.off ? void 0 : { requiresEffort: true }
1619
- },
1620
- ...defaultMember !== void 0 ? { defaultMember } : void 0
1621
- };
1622
- }
1623
- /** One reviewed family from the compiled collapse vocabulary → runtime shape. */
1624
- function compiledFamily(compiled) {
1625
- const family = {
1626
- id: compiled.id,
1627
- name: compiled.name,
1628
- members: compiled.members,
1629
- routing: compiled.routing
1630
- };
1631
- if (compiled.defaultMember !== void 0) family.defaultMember = compiled.defaultMember;
1632
- if (compiled.retiredMembers?.length) family.retiredMembers = compiled.retiredMembers;
1633
- if (!compiled.noThinking && compiled.mode !== void 0) family.thinking = {
1634
- mode: compiled.mode,
1635
- efforts: compiled.efforts ?? [],
1636
- ...compiled.effortBudgets !== void 0 && { effortBudgets: compiled.effortBudgets },
1637
- ...compiled.defaultLevel !== void 0 && { defaultLevel: compiled.defaultLevel },
1638
- ...compiled.requiresEffort === true && { requiresEffort: true }
1639
- };
1640
- if (compiled.suppressWhenOff) family.suppressWhenOff = true;
1641
- if (compiled.preserveAbsentEffortRoutes) family.preserveAbsentEffortRoutes = true;
1642
- if (compiled.extraAliases?.length) family.extraAliases = compiled.extraAliases;
1643
- return family;
1644
- }
1645
- const REVISION_CAPTURE = String.raw`(\d+(?:\.\d+){0,2})`;
1646
- /** One compiled `{rev}` family → runtime template with its id matcher. */
1647
- function compiledTemplate(compiled) {
1648
- const family = compiledFamily(compiled);
1649
- const alternatives = [
1650
- family.id,
1651
- ...family.members,
1652
- ...family.extraAliases ?? []
1653
- ].map((id) => id.split(REVISION_PLACEHOLDER).map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join(REVISION_CAPTURE));
1654
- const template = {
1655
- family,
1656
- pattern: new RegExp(`^(?:${alternatives.join("|")})$`, "i")
1657
- };
1658
- if (compiled.revision !== void 0) {
1659
- const terms = parseRevisionConstraint(compiled.revision);
1660
- if (terms !== void 0) template.revision = terms;
1661
- }
1662
- return template;
1663
- }
1664
- /** Substitute the placeholder throughout one templated family. */
1665
- function instantiateTemplate(template, rev) {
1666
- if (template.revision !== void 0) {
1667
- const parsed = parseRevision(rev);
1668
- if (parsed === void 0 || !revisionSatisfies(parsed, template.revision)) return void 0;
1669
- }
1670
- const fill = (id) => id.replaceAll(REVISION_PLACEHOLDER, rev);
1671
- const source = template.family;
1672
- const routing = {};
1673
- for (const effort of VARIANT_ROUTING_KEYS) {
1674
- const target = source.routing[effort];
1675
- if (target !== void 0) routing[effort] = fill(target);
1676
- }
1677
- const family = {
1678
- ...source,
1679
- id: fill(source.id),
1680
- name: fill(source.name),
1681
- members: source.members.map(fill),
1682
- routing
1683
- };
1684
- if (source.defaultMember !== void 0) family.defaultMember = fill(source.defaultMember);
1685
- if (source.retiredMembers !== void 0) family.retiredMembers = source.retiredMembers.map(fill);
1686
- if (source.extraAliases !== void 0) family.extraAliases = source.extraAliases.map(fill);
1687
- return family;
1688
- }
1689
- /**
1690
- * The family a template yields for `id` (logical id, member, or alias), or
1691
- * undefined when no template matches or the revision is out of range.
1692
- */
1693
- function templateFamilyFor(templates, id) {
1694
- for (const template of templates) {
1695
- const match = template.pattern.exec(id);
1696
- if (match === null) continue;
1697
- let rev;
1698
- for (let group = 1; group < match.length && rev === void 0; group++) rev = match[group];
1699
- if (rev === void 0) continue;
1700
- const family = instantiateTemplate(template, rev);
1701
- if (family !== void 0) return family;
1702
- }
1703
- }
1704
- /**
1705
- * Concrete families for every revision present in `ids`, one per
1706
- * instantiated id, skipping ids a concrete family in `table` already owns.
1707
- */
1708
- function instantiateTemplates(table, ids) {
1709
- const templates = table.templates;
1710
- if (templates === void 0 || templates.length === 0) return [];
1711
- const seen = /* @__PURE__ */ new Set();
1712
- for (const family of table.families) seen.add(family.id);
1713
- const out = [];
1714
- for (const id of ids) {
1715
- const family = templateFamilyFor(templates, id);
1716
- if (family === void 0 || seen.has(family.id)) continue;
1717
- seen.add(family.id);
1718
- out.push(family);
1719
- }
1720
- return out;
1721
- }
1722
- /** Provider id → reviewed collapse table, built once from the compiled vocabulary. */
1723
- function buildCompiledTables() {
1724
- const { variantFamilies, providerAliases } = collapseVocabulary();
1725
- const tables = {};
1726
- for (const compiled of variantFamilies) {
1727
- const table = tables[compiled.provider] ??= { families: [] };
1728
- if (compiled.id.includes("{rev}")) (table.templates ??= []).push(compiledTemplate(compiled));
1729
- else table.families.push(compiledFamily(compiled));
1730
- }
1731
- for (const [provider, aliases] of Object.entries(providerAliases)) {
1732
- tables[provider] ??= { families: [] };
1733
- tables[provider].providerAliases = aliases;
1734
- }
1735
- return tables;
1736
- }
1737
- const CURSOR_TIER_ID_PATTERN = /^(.+?)-(extra-high|none|minimal|low|medium|high|xhigh|max)(-fast)?$/;
1738
- const CURSOR_TIER_BASE_PATTERN = /-(extra-high|none|minimal|low|medium|high|xhigh|max)$/;
1739
- const CURSOR_THINKING_TOKEN_PATTERN = /(^|-)thinking($|-)/;
1740
- const CURSOR_TIER_BY_TOKEN = {
1741
- none: "none",
1742
- minimal: "minimal",
1743
- low: "low",
1744
- medium: "medium",
1745
- high: "high",
1746
- "extra-high": "xhigh",
1747
- xhigh: "xhigh",
1748
- max: "max"
1749
- };
1750
- /** Whether an existing logical row already routes every live member in `members`. */
1751
- function collapsedCursorLogicalMatches(spec, members) {
1752
- const routing = spec.thinking?.effortRouting;
1753
- if (!routing) return false;
1754
- for (const member of members) {
1755
- if (spec.requestModelId === member.spec.id) continue;
1756
- let matched = false;
1757
- for (const effort of VARIANT_ROUTING_KEYS) if (routing[effort] === member.spec.id) {
1758
- matched = true;
1759
- break;
1760
- }
1761
- if (!matched) return false;
1762
- }
1763
- return true;
1764
- }
1765
- /**
1766
- * Derive safe Cursor per-effort families from live wire ids. A family is
1767
- * intentionally left expanded when its base is an independent live SKU, any
1768
- * member already has a thinking ladder, member metadata differs, or a tier
1769
- * token is also part of a product name.
1770
- */
1771
- function deriveCursorEffortFamilies(specs) {
1772
- const byId = /* @__PURE__ */ new Map();
1773
- const groups = /* @__PURE__ */ new Map();
1774
- const candidateBases = /* @__PURE__ */ new Set();
1775
- for (const spec of specs) {
1776
- if (!byId.has(spec.id)) byId.set(spec.id, spec);
1777
- const match = CURSOR_TIER_ID_PATTERN.exec(spec.id);
1778
- if (!match) continue;
1779
- const baseId = match[1];
1780
- const tier = CURSOR_TIER_BY_TOKEN[match[2] ?? ""];
1781
- const fast = match[3] !== void 0;
1782
- if (!baseId || !tier) continue;
1783
- const member = {
1784
- baseId,
1785
- fast,
1786
- spec,
1787
- tier
1788
- };
1789
- const key = `${baseId}\0${fast ? "fast" : "standard"}`;
1790
- const group = groups.get(key);
1791
- if (group) group.push(member);
1792
- else groups.set(key, [member]);
1793
- candidateBases.add(baseId);
1794
- }
1795
- const unsafeBases = /* @__PURE__ */ new Set();
1796
- for (const group of groups.values()) {
1797
- const first = group[0];
1798
- if (!first) continue;
1799
- const { baseId } = first;
1800
- const standardGroup = groups.get(`${baseId}\0standard`) ?? [];
1801
- const standardBase = byId.get(baseId);
1802
- const laneBase = byId.get(`${baseId}${first.fast ? "-fast" : ""}`);
1803
- const independentStandardBase = standardBase !== void 0 && !collapsedCursorLogicalMatches(standardBase, standardGroup);
1804
- const independentLaneBase = laneBase !== void 0 && !collapsedCursorLogicalMatches(laneBase, group);
1805
- if (independentStandardBase || independentLaneBase || new Set(group.map((member) => member.tier)).size !== group.length || CURSOR_TIER_BASE_PATTERN.test(baseId) || CURSOR_THINKING_TOKEN_PATTERN.test(baseId) || candidateBases.has(`${baseId}-thinking`) || byId.has(`${baseId}-thinking`) || byId.has(`${baseId}-thinking-fast`) || byId.has(`${baseId}-fast-thinking`) || group.some((member) => member.spec.thinking !== void 0 || member.spec.requestModelId !== void 0) || group.some((member) => candidateBases.has(`${baseId}-${member.tier}`))) unsafeBases.add(baseId);
1806
- }
1807
- const families = [];
1808
- for (const group of groups.values()) {
1809
- const first = group[0];
1810
- if (!first || group.length < 2 || unsafeBases.has(first.baseId)) continue;
1811
- if (group.some((member) => member.spec.api !== first.spec.api || member.spec.baseUrl !== first.spec.baseUrl || member.spec.contextWindow !== first.spec.contextWindow || member.spec.maxTokens !== first.spec.maxTokens || member.spec.cursorMaxMode !== first.spec.cursorMaxMode || !Bun.deepEquals(member.spec.cost, first.spec.cost) || !Bun.deepEquals(member.spec.compat, first.spec.compat))) continue;
1812
- const routes = {};
1813
- for (const member of group) if (member.tier === "none") routes.off = member.spec.id;
1814
- else routes[member.tier] = member.spec.id;
1815
- const efforts = THINKING_EFFORTS.filter((effort) => routes[effort] !== void 0);
1816
- if (efforts.length === 0) continue;
1817
- const strippedName = first.spec.name.replace(/\s+(extra-high|none|minimal|low|medium|high|xhigh|max)(\s+fast)?$/i, "").trim();
1818
- const baseName = strippedName === first.spec.id ? first.baseId : strippedName || first.baseId;
1819
- const suffix = first.fast ? "-fast" : "";
1820
- families.push(tierFamily(`${first.baseId}${suffix}`, `${baseName}${first.fast ? " Fast" : ""}`, routes, efforts));
1821
- }
1822
- return families;
1823
- }
1824
- /** Provider id → reviewed collapse table. The CCA providers diverge on thinking transport. */
1825
- const REVIEWED_COLLAPSE_TABLES = buildCompiledTables();
1826
- /**
1827
- * Return the reviewed collapse table compiled for `provider`, when declared.
1828
- * Discovery uses this accessor to preserve injectable table seams.
1829
- */
1830
- function reviewedCollapseTable(provider) {
1831
- return REVIEWED_COLLAPSE_TABLES[provider] ?? REVIEWED_COLLAPSE_TABLES[provider.toLowerCase()];
1832
- }
1833
- /**
1834
- * The global automatic rule: derive an `X` + `X-thinking` family for every
1835
- * pair where both ids are live in `specs` (trailing or infix token). Gates:
1836
- * - both members share the same `api`,
1837
- * - known pricing must match — all-zero cost rows count as unknown
1838
- * (aggregators routinely ship them), but twins that BOTH carry real,
1839
- * differing prices are distinct SKUs and never merge,
1840
- * - ids claimed by the provider's reviewed table are skipped (curation wins).
1841
- * The capability surface prefers the thinking member's metadata, then the
1842
- * bare member's, then the canonical deriver (aggregators often ship
1843
- * `reasoning: false` and no thinking config on the twin), then a budget
1844
- * default. `off` routes to the bare id; every supported effort routes to the
1845
- * thinking id.
1846
- */
1847
- function deriveThinkingPairFamilies(specs, table, provider) {
1848
- const byId = /* @__PURE__ */ new Map();
1849
- for (const spec of specs) if (!byId.has(spec.id)) byId.set(spec.id, spec);
1850
- const claimed = table ? getAliasIndex(table) : void 0;
1851
- const families = [];
1852
- for (const spec of specs) {
1853
- const collapsed = provider === void 0 ? void 0 : collapseVariantId(provider, spec.id);
1854
- const baseId = collapsed?.thinkingVariant ? collapsed.logicalId : stripThinkingVariantSuffix(spec.id);
1855
- if (baseId === void 0 || baseId === spec.id) continue;
1856
- const base = byId.get(baseId);
1857
- if (!base) continue;
1858
- if (claimed && (claimed.resolve(spec.id) !== void 0 || claimed.resolve(baseId) !== void 0 || claimed.isFamily(spec.id) || claimed.isFamily(baseId))) continue;
1859
- if (spec.api !== base.api) continue;
1860
- const specPriced = spec.cost.input !== 0 || spec.cost.output !== 0;
1861
- const basePriced = base.cost.input !== 0 || base.cost.output !== 0;
1862
- if (specPriced && basePriced && (spec.cost.input !== base.cost.input || spec.cost.output !== base.cost.output || spec.cost.cacheRead !== base.cost.cacheRead || spec.cost.cacheWrite !== base.cost.cacheWrite)) continue;
1863
- const surface = derivePairThinkingSurface(spec, base);
1864
- const routing = { off: base.id };
1865
- for (const effort of surface.efforts) routing[effort] = spec.id;
1866
- families.push({
1867
- id: base.id,
1868
- name: base.name,
1869
- members: [base.id, spec.id],
1870
- routing,
1871
- thinking: surface
1872
- });
1873
- }
1874
- return families;
1875
- }
1876
- function derivePairThinkingSurface(thinkingSpec, baseSpec) {
1877
- const baked = thinkingSpec.thinking ?? baseSpec.thinking;
1878
- if (baked && baked.efforts.length > 0) {
1879
- const { effortRouting: _routing, suppressWhenOff: _suppress, requiresEffort: _required, ...surface } = baked;
1880
- return surface;
1881
- }
1882
- const { compat: _compat, ...policySpec } = thinkingSpec;
1883
- const derived = resolveModelPolicy({
1884
- ...policySpec,
1885
- reasoning: true,
1886
- thinking: void 0
1887
- }).thinking;
1888
- if (derived && derived.efforts.length > 0) {
1889
- const { effortRouting: _dRouting, suppressWhenOff: _dSuppress, requiresEffort: _dRequired, ...surface } = derived;
1890
- return surface;
1891
- }
1892
- return {
1893
- mode: "budget",
1894
- efforts: DEFAULT_PAIR_EFFORTS
1895
- };
1896
- }
1897
- /**
1898
- * Re-point a stale collapsed spec whose `requestModelId` or routing still
1899
- * targets a retired wire id. Collapsed snapshots (bundled catalog, cache
1900
- * rows, previous-generation fallbacks) pass through collapsing untouched, so
1901
- * a reviewed-table routing fix would otherwise never reach them. Only retired
1902
- * targets are rewritten — presence-filtered routing decisions from live
1903
- * discovery stay authoritative for everything else. Per retired entry the
1904
- * table's route for that effort wins, then the off/first-live-member wire id,
1905
- * then the route is dropped (falls back to `requestModelId ?? id`). Returns
1906
- * `spec` by reference when nothing targets a retired id.
1907
- */
1908
- function reconcileRetiredRouting(spec, family, retired) {
1909
- const currentThinking = spec.thinking;
1910
- const routing = currentThinking?.effortRouting;
1911
- const requestRetired = spec.requestModelId !== void 0 && retired.has(spec.requestModelId);
1912
- let routingRetired = false;
1913
- if (routing !== void 0) for (const key of VARIANT_ROUTING_KEYS) {
1914
- const target = routing[key];
1915
- if (target !== void 0 && retired.has(target)) {
1916
- routingRetired = true;
1917
- break;
1918
- }
1919
- }
1920
- if (!requestRetired && !routingRetired) return spec;
1921
- const offTarget = family.routing.off;
1922
- const fallbackWireId = offTarget !== void 0 && !retired.has(offTarget) ? offTarget : family.members.find((id) => !retired.has(id));
1923
- const next = { ...spec };
1924
- if (routingRetired && routing !== void 0 && currentThinking !== void 0) {
1925
- const nextRouting = {};
1926
- for (const effortKey of VARIANT_ROUTING_KEYS) {
1927
- const target = routing[effortKey];
1928
- if (target === void 0) continue;
1929
- if (!retired.has(target)) {
1930
- nextRouting[effortKey] = target;
1931
- continue;
1932
- }
1933
- const tableTarget = family.routing[effortKey];
1934
- if (tableTarget !== void 0 && !retired.has(tableTarget)) nextRouting[effortKey] = tableTarget;
1935
- else if (fallbackWireId !== void 0) nextRouting[effortKey] = fallbackWireId;
1936
- }
1937
- next.thinking = {
1938
- ...currentThinking,
1939
- effortRouting: nextRouting
1940
- };
1941
- }
1942
- if (requestRetired) {
1943
- if (fallbackWireId !== void 0 && fallbackWireId !== spec.id) next.requestModelId = fallbackWireId;
1944
- else delete next.requestModelId;
1945
- }
1946
- return next;
1947
- }
1948
- /**
1949
- * Refresh a collapsed snapshot's thinking surface in place. Bundled catalog and
1950
- * prev-generation snapshots freeze a family's transport, budgets, and routing;
1951
- * discovery emits the canonical id but the exact-id merge never overwrites a
1952
- * stale `family.id` row (e.g. `gemini-3.1-pro`) nor a recycled `extraAliases`
1953
- * row (e.g. `gemini-3-flash`). This re-applies the reviewed-table family's thinking,
1954
- * routing, and default wire id while keeping the spec id (load-bearing for exact
1955
- * selectors and bundled lookups). Returns `spec` by reference when unchanged.
1956
- */
1957
- function refreshCollapsedThinking(spec, family, retired) {
1958
- const familyThinking = family.thinking;
1959
- if (!spec.reasoning || familyThinking?.effortBudgets === void 0) return spec;
1960
- const routing = {};
1961
- let hasRouting = false;
1962
- for (const effortKey of VARIANT_ROUTING_KEYS) {
1963
- const target = family.routing[effortKey];
1964
- if (target !== void 0 && !retired?.has(target)) {
1965
- routing[effortKey] = target;
1966
- hasRouting = true;
1967
- }
1968
- }
1969
- const thinking = { ...familyThinking };
1970
- if (hasRouting) thinking.effortRouting = routing;
1971
- if (family.suppressWhenOff) thinking.suppressWhenOff = true;
1972
- const offTarget = family.routing.off;
1973
- const requestModelId = offTarget !== void 0 && !retired?.has(offTarget) && offTarget !== spec.id ? offTarget : spec.requestModelId;
1974
- if (Bun.deepEquals(thinking, spec.thinking) && requestModelId === spec.requestModelId) return spec;
1975
- return {
1976
- ...spec,
1977
- thinking,
1978
- ...requestModelId !== void 0 ? { requestModelId } : {}
1979
- };
1980
- }
1981
- /**
1982
- * Re-point a collapsed snapshot's default wire id to the family's declared
1983
- * {@link EffortVariantFamily.defaultMember} when the snapshot still advertises a
1984
- * different default. Bundled catalog and cache rows freeze `requestModelId` from
1985
- * before a family gained a preferred default (Cursor Grok 4.5/4.6 → `-medium`),
1986
- * and neither the existing-collapsed pass-through nor `refreshCollapsedThinking`
1987
- * (scoped to `effortBudgets` families) would otherwise correct them — leaving an
1988
- * effort-less request clamped to the refused `-low` tier (issue #9478). Only
1989
- * re-points when the target is a live route in the snapshot's own
1990
- * `effortRouting`. Returns `spec` by reference when unchanged.
1991
- */
1992
- function reconcileDefaultMember(spec, family, presentMembers) {
1993
- const defaultMember = family.defaultMember;
1994
- if (defaultMember === void 0 || defaultMember === spec.id) return spec;
1995
- const target = presentMembers === void 0 || presentMembers.has(defaultMember) ? defaultMember : family.members.find((id) => presentMembers.has(id));
1996
- if (target === void 0 || spec.requestModelId === target) return spec;
1997
- const routing = spec.thinking?.effortRouting;
1998
- if (routing === void 0) return spec;
1999
- for (const key of VARIANT_ROUTING_KEYS) if (routing[key] === target) return {
2000
- ...spec,
2001
- requestModelId: target
2002
- };
2003
- return spec;
2004
- }
2005
- /**
2006
- * Collapse every family in `table` found in `specs`. Non-member specs pass
2007
- * through verbatim (by reference), order preserved; the collapsed spec
2008
- * replaces the first occurrence of its family.
2009
- */
2010
- function collapseWithTable(specs, table) {
2011
- const byId = /* @__PURE__ */ new Map();
2012
- for (const spec of specs) if (!byId.has(spec.id)) byId.set(spec.id, spec);
2013
- /** family id → spec to emit at the family's first occurrence. */
2014
- const replacement = /* @__PURE__ */ new Map();
2015
- /** spec ids that belong to a touched family (members + logical id). */
2016
- const familyIdBySpecId = /* @__PURE__ */ new Map();
2017
- const instantiated = instantiateTemplates(table, byId.keys());
2018
- const families = instantiated.length === 0 ? table.families : [...table.families, ...instantiated];
2019
- for (const family of families) {
2020
- const retired = family.retiredMembers !== void 0 && family.retiredMembers.length > 0 ? new Set(family.retiredMembers) : void 0;
2021
- const existing = byId.get(family.id);
2022
- const existingCollapsed = existing !== void 0 && (existing.requestModelId !== void 0 || existing.thinking?.effortRouting !== void 0);
2023
- const reconciled = existing !== void 0 && existingCollapsed && retired !== void 0 ? reconcileRetiredRouting(existing, family, retired) : existing;
2024
- const rawPresent = family.members.filter((id) => byId.has(id) && !(id === family.id && existingCollapsed));
2025
- if (rawPresent.length === 0) {
2026
- const refreshed = existing !== void 0 && existingCollapsed ? reconcileDefaultMember(refreshCollapsedThinking(reconciled ?? existing, family, retired), family) : reconciled;
2027
- if (refreshed !== void 0 && refreshed !== existing) {
2028
- familyIdBySpecId.set(family.id, family.id);
2029
- replacement.set(family.id, refreshed);
2030
- }
2031
- continue;
2032
- }
2033
- for (const id of rawPresent) familyIdBySpecId.set(id, family.id);
2034
- if (existing) familyIdBySpecId.set(family.id, family.id);
2035
- if (existingCollapsed && reconciled !== void 0) {
2036
- replacement.set(family.id, reconcileDefaultMember(reconciled, family, new Set(rawPresent)));
2037
- continue;
2038
- }
2039
- const memberSpecs = [];
2040
- for (const id of rawPresent) {
2041
- const member = byId.get(id);
2042
- if (member !== void 0) memberSpecs.push(member);
2043
- }
2044
- const firstMember = memberSpecs[0];
2045
- if (firstMember === void 0) continue;
2046
- const presentSet = new Set(rawPresent);
2047
- const routing = {};
2048
- let hasRouting = false;
2049
- let hasEffortRoute = false;
2050
- let usedAbsentEffortRoute = false;
2051
- for (const effort of VARIANT_ROUTING_KEYS) {
2052
- const target = family.routing[effort];
2053
- const targetPresent = target !== void 0 && presentSet.has(target);
2054
- const preserveAbsentEffort = target !== void 0 && effort !== "off" && family.preserveAbsentEffortRoutes === true;
2055
- if (target !== void 0 && (targetPresent || preserveAbsentEffort) && !retired?.has(target)) {
2056
- routing[effort] = target;
2057
- hasRouting = true;
2058
- if (effort !== "off") hasEffortRoute = true;
2059
- if (!targetPresent && effort !== "off") usedAbsentEffortRoute = true;
2060
- }
2061
- }
2062
- const reasoning = memberSpecs.some((spec) => spec.reasoning) || hasEffortRoute;
2063
- const familyThinking = family.thinking;
2064
- const thinking = familyThinking ? { ...familyThinking } : void 0;
2065
- if (thinking !== void 0) {
2066
- if (hasRouting) thinking.effortRouting = routing;
2067
- if (family.suppressWhenOff) thinking.suppressWhenOff = true;
2068
- }
2069
- const input = [];
2070
- if (memberSpecs.some((spec) => spec.input.includes("text"))) input.push("text");
2071
- if (memberSpecs.some((spec) => spec.input.includes("image"))) input.push("image");
2072
- const collapsed = {
2073
- ...firstMember,
2074
- id: family.id,
2075
- name: family.name,
2076
- reasoning,
2077
- input,
2078
- contextWindow: maxOrNull(memberSpecs.map((spec) => spec.contextWindow)),
2079
- maxTokens: maxOrNull(memberSpecs.map((spec) => spec.maxTokens))
2080
- };
2081
- const defaultWireId = (family.defaultMember !== void 0 && presentSet.has(family.defaultMember) && !retired?.has(family.defaultMember) ? family.defaultMember : void 0) ?? rawPresent.find((id) => !retired?.has(id)) ?? rawPresent[0];
2082
- if (defaultWireId === void 0) continue;
2083
- if (defaultWireId === family.id) {
2084
- if (usedAbsentEffortRoute) collapsed.requestModelId = defaultWireId;
2085
- else delete collapsed.requestModelId;
2086
- } else collapsed.requestModelId = defaultWireId;
2087
- if (reasoning && thinking !== void 0) collapsed.thinking = thinking;
2088
- else delete collapsed.thinking;
2089
- replacement.set(family.id, collapsed);
2090
- }
2091
- for (const family of table.families) {
2092
- if (family.extraAliases === void 0) continue;
2093
- const retired = family.retiredMembers !== void 0 && family.retiredMembers.length > 0 ? new Set(family.retiredMembers) : void 0;
2094
- for (const alias of family.extraAliases) {
2095
- if (alias === family.id || familyIdBySpecId.has(alias)) continue;
2096
- const aliasSpec = byId.get(alias);
2097
- if (aliasSpec === void 0) continue;
2098
- const refreshed = refreshCollapsedThinking(aliasSpec, family, retired);
2099
- if (refreshed !== aliasSpec) {
2100
- familyIdBySpecId.set(alias, alias);
2101
- replacement.set(alias, refreshed);
2102
- }
2103
- }
2104
- }
2105
- if (replacement.size === 0) return [...specs];
2106
- const emitted = /* @__PURE__ */ new Set();
2107
- const out = [];
2108
- for (const spec of specs) {
2109
- const familyId = familyIdBySpecId.get(spec.id);
2110
- if (familyId === void 0) {
2111
- out.push(spec);
2112
- continue;
2113
- }
2114
- if (emitted.has(familyId)) continue;
2115
- emitted.add(familyId);
2116
- const familySpec = replacement.get(familyId);
2117
- if (familySpec !== void 0) out.push(familySpec);
2118
- }
2119
- return out;
2120
- }
2121
- /**
2122
- * Re-key model-to-model configuration after collapse removes a referenced
2123
- * member id. Qualified targets keep their provider; bare targets remain bare.
2124
- */
2125
- function retargetCollapsedModelReferences(specs) {
2126
- const liveIdsByProvider = /* @__PURE__ */ new Map();
2127
- for (const spec of specs) {
2128
- const provider = spec.provider.toLowerCase();
2129
- let liveIds = liveIdsByProvider.get(provider);
2130
- if (!liveIds) {
2131
- liveIds = /* @__PURE__ */ new Set();
2132
- liveIdsByProvider.set(provider, liveIds);
2133
- }
2134
- liveIds.add(spec.id.toLowerCase());
2135
- }
2136
- for (let index = 0; index < specs.length; index++) {
2137
- const spec = specs[index];
2138
- if (!spec) continue;
2139
- const contextPromotionTarget = resolveCollapsedModelReference(spec.contextPromotionTarget, spec.provider, liveIdsByProvider);
2140
- const compactionModel = resolveCollapsedModelReference(spec.compactionModel, spec.provider, liveIdsByProvider);
2141
- if (contextPromotionTarget === spec.contextPromotionTarget && compactionModel === spec.compactionModel) continue;
2142
- specs[index] = {
2143
- ...spec,
2144
- contextPromotionTarget,
2145
- compactionModel
2146
- };
2147
- }
2148
- }
2149
- function resolveCollapsedModelReference(target, currentProvider, liveIdsByProvider) {
2150
- if (target === void 0) return void 0;
2151
- const separator = target.indexOf("/");
2152
- const provider = separator >= 0 ? target.slice(0, separator) : currentProvider;
2153
- const providerId = provider.toLowerCase();
2154
- const normalizedModelId = (separator >= 0 ? target.slice(separator + 1) : target).trim().toLowerCase();
2155
- const liveIds = liveIdsByProvider.get(providerId);
2156
- if (liveIds?.has(normalizedModelId)) return target;
2157
- const alias = resolveRegisteredVariantAlias(provider, normalizedModelId);
2158
- if (alias === void 0 || !liveIds?.has(alias.toLowerCase())) return target;
2159
- return separator >= 0 ? `${provider}/${alias}` : alias;
2160
- }
2161
- /**
2162
- * Collapse a full mixed-provider list: per provider, the compiled reviewed table, Cursor's
2163
- * conservative live effort-sibling rule, and the automatic `X`/`X-thinking`
2164
- * pair rule. Used by the catalog generator; the runtime equivalent lives at
2165
- * the model-manager merge point. Output is regrouped by provider — callers
2166
- * re-sort.
2167
- */
2168
- function collapseVariants(specs, opts) {
2169
- if (opts?.table !== void 0) return collapseWithTable(specs, opts.table);
2170
- const byProvider = /* @__PURE__ */ new Map();
2171
- for (const spec of specs) {
2172
- const slice = byProvider.get(spec.provider);
2173
- if (slice) slice.push(spec);
2174
- else byProvider.set(spec.provider, [spec]);
2175
- }
2176
- const out = [];
2177
- for (const [provider, slice] of byProvider) {
2178
- const table = reviewedCollapseTable(provider);
2179
- let result = table ? collapseWithTable(slice, table) : slice;
2180
- if (provider === "cursor") {
2181
- const cursorDerived = deriveCursorEffortFamilies(result);
2182
- if (cursorDerived.length > 0) result = collapseWithTable(result, { families: cursorDerived });
2183
- }
2184
- const derived = deriveThinkingPairFamilies(result, table, provider);
2185
- if (derived.length > 0) result = collapseWithTable(result, { families: derived });
2186
- registerCollapsedVariantAliases(provider, result);
2187
- out.push(...result);
2188
- }
2189
- retargetCollapsedModelReferences(out);
2190
- return out;
2191
- }
2192
- /**
2193
- * Alias index over a collapse table (or the live families observed at
2194
- * runtime). Templated families are materialized on first lookup of any id
2195
- * they match, so a revision discovery has never advertised still resolves.
2196
- */
2197
- var VariantAliasIndex = class {
2198
- /** lowercased retired id → replacement model id. */
2199
- #forward = /* @__PURE__ */ new Map();
2200
- /**
2201
- * lowercased provider-scoped alias → replacement model id. Kept apart from
2202
- * `#forward` so bare-id and reverse lookups never see it.
2203
- */
2204
- providerScoped = /* @__PURE__ */ new Map();
2205
- /** replacement model id → retired ids that resolve to it. */
2206
- #reverse = /* @__PURE__ */ new Map();
2207
- /** Collapsed logical ids declared by the table or observed at runtime. */
2208
- #familyIds = /* @__PURE__ */ new Set();
2209
- #templates;
2210
- constructor(templates = []) {
2211
- this.#templates = templates;
2212
- }
2213
- /** Register `from` → `to`; false when `from` is already claimed. */
2214
- add(from, to) {
2215
- if (from === to || this.#forward.has(from.toLowerCase())) return false;
2216
- this.#forward.set(from.toLowerCase(), to);
2217
- const sources = this.#reverse.get(to);
2218
- if (sources) sources.push(from);
2219
- else this.#reverse.set(to, [from]);
2220
- return true;
2221
- }
2222
- /** Register a family: its logical id plus every member and extra alias. */
2223
- addFamily(family) {
2224
- this.#familyIds.add(family.id);
2225
- for (const member of family.members) this.add(member, family.id);
2226
- for (const alias of family.extraAliases ?? []) this.add(alias, family.id);
2227
- }
2228
- markFamily(id) {
2229
- this.#familyIds.add(id);
2230
- }
2231
- /** Replacement model id for a retired/member id (case-insensitive). */
2232
- resolve(id) {
2233
- const lower = id.toLowerCase();
2234
- this.#learn(lower);
2235
- return this.#forward.get(lower);
2236
- }
2237
- /** Whether `id` is a collapsed logical id of this index. */
2238
- isFamily(id) {
2239
- this.#learn(id);
2240
- return this.#familyIds.has(id);
2241
- }
2242
- /** Retired ids that resolve to logical `id`. */
2243
- sourcesOf(id) {
2244
- this.#learn(id);
2245
- return this.#reverse.get(id);
2246
- }
2247
- /** Materialize the template family that owns `id`, once. */
2248
- #learn(id) {
2249
- if (this.#templates.length === 0) return;
2250
- const family = templateFamilyFor(this.#templates, id);
2251
- if (family === void 0 || this.#familyIds.has(family.id)) return;
2252
- this.addFamily(family);
2253
- }
2254
- };
2255
- const dynamicAliasIndexes = /* @__PURE__ */ new Map();
2256
- const kAliasIndex = Symbol("compat-collapse.aliasIndex");
2257
- /**
2258
- * Persist aliases embedded in collapsed routing so generated catalog rows and
2259
- * newly discovered families expose the same selector migrations as reviewed tables.
2260
- */
2261
- function registerCollapsedVariantAliases(provider, specs) {
2262
- const providerId = provider.toLowerCase();
2263
- let index = dynamicAliasIndexes.get(providerId);
2264
- for (const spec of specs) {
2265
- const routing = spec.thinking?.effortRouting;
2266
- if (!routing) continue;
2267
- let registered = false;
2268
- for (const effort of VARIANT_ROUTING_KEYS) {
2269
- const source = routing[effort];
2270
- if (!source || source === spec.id) continue;
2271
- index ??= new VariantAliasIndex();
2272
- registered = index.add(source, spec.id) || registered;
2273
- }
2274
- if (spec.requestModelId && spec.requestModelId !== spec.id) {
2275
- index ??= new VariantAliasIndex();
2276
- registered = index.add(spec.requestModelId, spec.id) || registered;
2277
- }
2278
- if (registered) index?.markFamily(spec.id);
2279
- }
2280
- if (index) dynamicAliasIndexes.set(providerId, index);
2281
- }
2282
- function resolveRegisteredVariantAlias(provider, normalizedModelId) {
2283
- const providerId = provider.toLowerCase();
2284
- const table = reviewedCollapseTable(provider) ?? reviewedCollapseTable(providerId);
2285
- return (table ? getAliasIndex(table).resolve(normalizedModelId) : void 0) ?? dynamicAliasIndexes.get(providerId)?.resolve(normalizedModelId);
2286
- }
2287
- function getAliasIndex(table) {
2288
- const cached = Reflect.get(table, kAliasIndex);
2289
- if (cached instanceof VariantAliasIndex) return cached;
2290
- const index = new VariantAliasIndex(table.templates);
2291
- for (const family of table.families) index.addFamily(family);
2292
- for (const alias in table.providerAliases) {
2293
- const target = table.providerAliases[alias];
2294
- if (target !== void 0 && alias !== target) index.providerScoped.set(alias.toLowerCase(), target);
2295
- }
2296
- Reflect.set(table, kAliasIndex, index);
2297
- return index;
2298
- }
2299
- function maxOrNull(values) {
2300
- const known = values.filter((v) => v != null);
2301
- return known.length ? Math.max(...known) : null;
2302
- }
2303
- //#endregion
2304
- export { isOfficialAnthropicApiUrl as a, isAnthropicSigningProxyUrl as i, buildModel as n, resolveModelPolicy as r, collapseVariants as t };