@xiaoso/dsh-tool-plus 0.1.6 → 0.1.7-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD_PARTY_NOTICES.md +9 -3
- package/lib/{abort-Cwwm4Err.mjs → abort-Caqff3M6.mjs} +2 -2
- package/lib/alibaba-coding-plan-DTupMiAi.mjs +73 -0
- package/lib/alibaba-token-plan-CHGyWOfX.mjs +46 -0
- package/lib/alibaba-token-plan-Dj3OZhEE.mjs +82 -0
- package/lib/{amazon-bedrock-TVMpUTRG.mjs → amazon-bedrock-DbFSYXfJ.mjs} +117 -38
- package/lib/{anthropic-BL6LFDQS.mjs → anthropic-CTJ3IQVa.mjs} +675 -166
- package/lib/anthropic-CXfWlp-x.mjs +105 -0
- package/lib/{aws-credentials-B20dliS7.mjs → anthropic-wire-CKuhDwZ1.mjs} +74 -14
- package/lib/{api-key-login-CIDnXeYd.mjs → api-key-validation-CGCJFbFr.mjs} +27 -68
- package/lib/{azure-openai-responses-BkhsLmN3.mjs → azure-openai-responses-ChFbWaGj.mjs} +27 -16
- package/lib/{browser-render-CmgvSNte.mjs → browser-render-9o0Rknop.mjs} +4 -4
- package/lib/bun-shim.mjs +71 -2
- package/lib/{bundled-references-ChZSPDFw.mjs → bundled-references-DY3EJxZV.mjs} +6 -5
- package/lib/cline-pass-Bwg3esu9.mjs +44 -0
- package/lib/cloudflare-ai-gateway-BupNXyKK.mjs +35 -0
- package/lib/cloudflare-ai-gateway-EWo0VkP5.mjs +44 -0
- package/lib/collapse-DOR8sOGf.mjs +2304 -0
- package/lib/coreweave-C82HrLpb.mjs +31 -0
- package/lib/coreweave-Ct8cF-da.mjs +14 -0
- package/lib/{cursor-B6HcmplF.mjs → cursor-B95LzVWV.mjs} +11 -3
- package/lib/{cursor-CRpLpaZ3.mjs → cursor-DJV_dcgB.mjs} +887 -1784
- package/lib/{cursor-B8m6SqAH.mjs → cursor-LKGjucn2.mjs} +48 -38
- package/lib/cursor-proto-B8Wj8bv9.mjs +10513 -0
- package/lib/{deterministic-id-D-yIV_eI.mjs → deterministic-id-CUEIMSqR.mjs} +1 -1
- package/lib/devin-BMTdx_hx.mjs +316 -0
- package/lib/{devin-DUAfvBsW.mjs → devin-DSp0Rw_E.mjs} +172 -86
- package/lib/devin-ExGIghmx.mjs +69 -0
- package/lib/devin-proto-Br8fdyNl.mjs +2888 -0
- package/lib/{dom-CawWi8fa.mjs → dom-DG3sPESc.mjs} +8 -8
- package/lib/effort-BdtQMN-_.mjs +23 -0
- package/lib/{error-C-f_Wnw4.mjs → error-CORgGg5a.mjs} +275 -154
- package/lib/{event-stream-Dh2guZxS.mjs → event-stream-ulcDenZD.mjs} +20 -4
- package/lib/{gemini-headers-DKUShltF.mjs → gemini-headers-Co9cVvex.mjs} +2 -2
- package/lib/{github-copilot-suDymKrx.mjs → github-copilot-Dstq1D3s.mjs} +69 -29
- package/lib/github-copilot-headers-DOh1gt_w.mjs +312 -0
- package/lib/gitlab-duo-DSCMrU0m.mjs +11 -0
- package/lib/google-CtsKkOQK.mjs +38 -0
- package/lib/google-antigravity-z-5KsEci.mjs +252 -0
- package/lib/{google-auth-DYJLM792.mjs → google-auth-ieLBaneO.mjs} +4 -4
- package/lib/{google-gemini-cli-8BT513Ul.mjs → google-gemini-cli-C6NE5mWz.mjs} +28 -54
- package/lib/{google-gemini-cli-D6cSmfvB.mjs → google-gemini-cli-CAIPSl7e.mjs} +23 -29
- package/lib/google-oauth-shared-DhMllAkt.mjs +53 -0
- package/lib/{google-shared-CVbHK5vZ.mjs → google-shared-B0aNCYEH.mjs} +140 -44
- package/lib/{google-validation-Cgbn3tWJ.mjs → google-validation-BEkNs-Bx.mjs} +1 -1
- package/lib/{google-vertex-Bui-ypAe.mjs → google-vertex-Bbd1tYNc.mjs} +8 -8
- package/lib/hosts-00rjRzUD.mjs +203 -0
- package/lib/id-AL5obQzR.mjs +71 -0
- package/lib/{idle-iterator-CYAxUkSD.mjs → idle-iterator-DlUkEfzW.mjs} +3 -3
- package/lib/index.mjs +598 -5275
- package/lib/kilo-ChJL54wq.mjs +81 -0
- package/lib/kimi-C2c_Zq8A.mjs +67 -0
- package/lib/{launch-BmgEUycu.mjs → launch-DKDH71En.mjs} +1 -1
- package/lib/markit-CmRfm4E2.mjs +9885 -0
- package/lib/models-DnXMYGcJ.mjs +381604 -0
- package/lib/muse-code-Di1VZmB1.mjs +143 -0
- package/lib/{ollama-Df9ce-Cp.mjs → ollama-B8ic3sEp.mjs} +15 -30
- package/lib/{openai-codex-CAVI3Me-.mjs → openai-codex-DuJNC99x.mjs} +29 -99
- package/lib/{openai-codex-responses-BcnOotRB.mjs → openai-codex-responses-BL29nh9K.mjs} +204 -116
- package/lib/{openai-completions-Bq4WT47M.mjs → openai-completions-BK2f2dBv.mjs} +152 -82
- package/lib/openai-configuration-update-xMYUjaK_.mjs +150 -0
- package/lib/{openai-reasoning-fallback-DXsfiSXO.mjs → openai-reasoning-fallback-BdB3RCbj.mjs} +106 -12
- package/lib/{openai-responses-Mq_-PjvE.mjs → openai-responses-CGQPlIIy.mjs} +76 -82
- package/lib/{perplexity-XgLF73E7.mjs → perplexity-TBjz3VMB.mjs} +52 -9
- package/lib/{pkce-BlQikGPu.mjs → pkce-BYjmugmw.mjs} +1 -1
- package/lib/protobuf-aab1UGVn.mjs +717 -0
- package/lib/{provider-response-C6vcbQyO.mjs → provider-response-SqKSkkUc.mjs} +1 -1
- package/lib/{proxy-D9lm7ONA.mjs → proxy-5nWqRL1f.mjs} +45 -5
- package/lib/{readability-Cpm-ocau.mjs → readability-uGhqb4GC.mjs} +2 -2
- package/lib/reference-CtvM4zLU.mjs +114 -0
- package/lib/{request-debug-HJMoJncL.mjs → request-debug-NQN0BjHH.mjs} +1 -1
- package/lib/{sanitize-text-CfcXzw5X.mjs → sanitize-text-BCf5KmCf.mjs} +1 -1
- package/lib/{scrapers-Cg5w77td.mjs → scrapers-BpqEnqNM.mjs} +12 -12
- package/lib/{src-BcD0_rQR.mjs → src-BwW51vA5.mjs} +979 -388
- package/lib/{sse-debug-CYdjOC96.mjs → sse-debug-B-tkLCPW.mjs} +1 -1
- package/lib/{stream-Bjq8wjfr.mjs → stream-B_7qN-bA.mjs} +3802 -2623
- package/lib/stream-markup-healing-DKT1lnkW.mjs +267 -0
- package/lib/{strict-tool-validation-imVLUcbI.mjs → strict-tool-validation-CBTz1dAA.mjs} +2 -2
- package/lib/taxonomy-DSIM99rS.mjs +15392 -0
- package/lib/{stream-markup-healing-DZ6bVDxH.mjs → thinking-CiLa2LFB.mjs} +31 -186
- package/lib/{turndown-DN7ByzEI.mjs → turndown-DrX1M4WG.mjs} +4 -4
- package/lib/{type-guards-B9VVjRDK.mjs → type-guards-CttAANEx.mjs} +1 -1
- package/lib/types/client/BashPlusCard.d.ts +53 -0
- package/lib/types/client/ToolPlusSection.d.ts +36 -0
- package/lib/types/client/forms.d.ts +42 -0
- package/lib/types/client/index.d.ts +29 -0
- package/lib/types/client/locales.d.ts +19 -0
- package/lib/types/client/rm-safe-status-text.d.ts +15 -0
- package/lib/types/client/rows.d.ts +107 -0
- package/lib/types/client/web-connection-rpc.d.ts +22 -0
- package/lib/types/config/fields.d.ts +85 -0
- package/lib/types/config/omp-settings.d.ts +21 -0
- package/lib/types/config/settings.d.ts +212 -0
- package/lib/types/config/truncate.d.ts +27 -0
- package/lib/types/host/browser-probe-rpc.d.ts +29 -0
- package/lib/types/index.d.ts +6 -0
- package/lib/types/tools/ast-edit/adapter/index.d.ts +26 -0
- package/lib/types/tools/ast-edit/adapter/sdk.d.ts +49 -0
- package/lib/types/tools/ast-grep/adapter/index.d.ts +31 -0
- package/lib/types/tools/ast-grep/adapter/sdk.d.ts +44 -0
- package/lib/types/tools/bash/adapter/spill.d.ts +34 -0
- package/lib/types/tools/bash/background.d.ts +40 -0
- package/lib/types/tools/bash/bash-executor.d.ts +102 -0
- package/lib/types/tools/bash/bash-interceptor.d.ts +33 -0
- package/lib/types/tools/bash/cd-workdir.d.ts +35 -0
- package/lib/types/tools/bash/logger.d.ts +18 -0
- package/lib/types/tools/bash/non-interactive-env.d.ts +5 -0
- package/lib/types/tools/bash/render.d.ts +46 -0
- package/lib/types/tools/bash/rm-safe-status.d.ts +62 -0
- package/lib/types/tools/bash/rm-safe.d.ts +18 -0
- package/lib/types/tools/bash/sanitize-text.d.ts +34 -0
- package/lib/types/tools/bash/shell-snapshot.d.ts +31 -0
- package/lib/types/tools/bash/shell-tokenize.d.ts +60 -0
- package/lib/types/tools/bash/streaming-output.d.ts +32 -0
- package/lib/types/tools/bash/trash-cli-main.d.ts +1 -0
- package/lib/types/tools/bash/trash-cli.d.ts +77 -0
- package/lib/types/tools/bash/types.d.ts +107 -0
- package/lib/types/tools/bash/which.d.ts +20 -0
- package/lib/types/tools/bash/windows-shell.d.ts +31 -0
- package/lib/types/tools/bash/yield.d.ts +71 -0
- package/lib/types/tools/edit/adapter/index.d.ts +57 -0
- package/lib/types/tools/edit/adapter/tools/auto-generated-guard.d.ts +10 -0
- package/lib/types/tools/edit/adapter/tools/output-meta.d.ts +34 -0
- package/lib/types/tools/edit/adapter/tools/plan-mode-guard.d.ts +21 -0
- package/lib/types/tools/glob/adapter/index.d.ts +52 -0
- package/lib/types/tools/grep/adapter/index.d.ts +53 -0
- package/lib/types/tools/grep/adapter/match-path.d.ts +1 -0
- package/lib/types/tools/hashline/native/diff-preview.d.ts +37 -0
- package/lib/types/tools/hashline/native/index.d.ts +109 -0
- package/lib/types/tools/hashline/native/normalize.d.ts +29 -0
- package/lib/types/tools/hashline/native/policy.d.ts +98 -0
- package/lib/types/tools/hashline/native/writer.d.ts +42 -0
- package/lib/types/tools/omp/browser/launch.d.ts +28 -0
- package/lib/types/tools/omp/browser/readable.d.ts +17 -0
- package/lib/types/tools/omp/config/settings-schema.d.ts +12 -0
- package/lib/types/tools/omp/config/settings.d.ts +59 -0
- package/lib/types/tools/omp/edit/apply-patch/parser.d.ts +34 -0
- package/lib/types/tools/omp/edit/details.d.ts +54 -0
- package/lib/types/tools/omp/edit/diff.d.ts +60 -0
- package/lib/types/tools/omp/edit/dispatch.d.ts +43 -0
- package/lib/types/tools/omp/edit/file-snapshot-store.d.ts +81 -0
- package/lib/types/tools/omp/edit/hashline/execute.d.ts +40 -0
- package/lib/types/tools/omp/edit/hashline/params.d.ts +6 -0
- package/lib/types/tools/omp/edit/modes/apply-patch.d.ts +25 -0
- package/lib/types/tools/omp/edit/modes/patch.d.ts +109 -0
- package/lib/types/tools/omp/edit/modes/replace.d.ts +151 -0
- package/lib/types/tools/omp/edit/normalize.d.ts +31 -0
- package/lib/types/tools/omp/edit/notebook.d.ts +50 -0
- package/lib/types/tools/omp/edit/read-file.d.ts +2 -0
- package/lib/types/tools/omp/edit/snapshot-details.d.ts +33 -0
- package/lib/types/tools/omp/extensibility/skills.d.ts +22 -0
- package/lib/types/tools/omp/internal-urls/index.d.ts +100 -0
- package/lib/types/tools/omp/internal-urls/local-protocol.d.ts +12 -0
- package/lib/types/tools/omp/internal-urls/parse.d.ts +31 -0
- package/lib/types/tools/omp/internal-urls/types.d.ts +189 -0
- package/lib/types/tools/omp/internal-urls/xd-protocol.d.ts +19 -0
- package/lib/types/tools/omp/markit/converters/docx.d.ts +6 -0
- package/lib/types/tools/omp/markit/converters/epub.d.ts +15 -0
- package/lib/types/tools/omp/markit/converters/pdf/index.d.ts +7 -0
- package/lib/types/tools/omp/markit/converters/pptx.d.ts +57 -0
- package/lib/types/tools/omp/markit/converters/xlsx.d.ts +25 -0
- package/lib/types/tools/omp/markit/index.d.ts +2 -0
- package/lib/types/tools/omp/markit/registry.d.ts +16 -0
- package/lib/types/tools/omp/markit/types.d.ts +30 -0
- package/lib/types/tools/omp/sdk.d.ts +103 -0
- package/lib/types/tools/omp/session/agent-storage.d.ts +154 -0
- package/lib/types/tools/omp/session/streaming-output.d.ts +244 -0
- package/lib/types/tools/omp/task/spawn-policy.d.ts +22 -0
- package/lib/types/tools/omp/tools/approval.d.ts +62 -0
- package/lib/types/tools/omp/tools/ast-edit.d.ts +73 -0
- package/lib/types/tools/omp/tools/ast-grep.d.ts +61 -0
- package/lib/types/tools/omp/tools/auto-generated-guard.d.ts +20 -0
- package/lib/types/tools/omp/tools/conflict-detect.d.ts +237 -0
- package/lib/types/tools/omp/tools/fetch.d.ts +103 -0
- package/lib/types/tools/omp/tools/file-recorder.d.ts +13 -0
- package/lib/types/tools/omp/tools/fs-cache-invalidation.d.ts +15 -0
- package/lib/types/tools/omp/tools/glob.d.ts +86 -0
- package/lib/types/tools/omp/tools/grep.d.ts +102 -0
- package/lib/types/tools/omp/tools/grouped-file-output.d.ts +70 -0
- package/lib/types/tools/omp/tools/index.d.ts +23 -0
- package/lib/types/tools/omp/tools/list-limit.d.ts +12 -0
- package/lib/types/tools/omp/tools/match-line-format.d.ts +11 -0
- package/lib/types/tools/omp/tools/output-meta.d.ts +160 -0
- package/lib/types/tools/omp/tools/path-utils.d.ts +326 -0
- package/lib/types/tools/omp/tools/plan-mode-guard.d.ts +33 -0
- package/lib/types/tools/omp/tools/read-archive.d.ts +16 -0
- package/lib/types/tools/omp/tools/read-format.d.ts +104 -0
- package/lib/types/tools/omp/tools/read-path-resolution.d.ts +19 -0
- package/lib/types/tools/omp/tools/read-selector.d.ts +27 -0
- package/lib/types/tools/omp/tools/read-sqlite.d.ts +16 -0
- package/lib/types/tools/omp/tools/read-summary.d.ts +15 -0
- package/lib/types/tools/omp/tools/read.d.ts +70 -0
- package/lib/types/tools/omp/tools/render-utils.d.ts +28 -0
- package/lib/types/tools/omp/tools/report-tool-issue.d.ts +149 -0
- package/lib/types/tools/omp/tools/resolve.d.ts +127 -0
- package/lib/types/tools/omp/tools/sqlite-reader.d.ts +114 -0
- package/lib/types/tools/omp/tools/tool-errors.d.ts +33 -0
- package/lib/types/tools/omp/tools/tool-result.d.ts +33 -0
- package/lib/types/tools/omp/tools/tool-timeouts.d.ts +57 -0
- package/lib/types/tools/omp/tools/write.d.ts +53 -0
- package/lib/types/tools/omp/tools/writethrough.d.ts +24 -0
- package/lib/types/tools/omp/utils/block-context.d.ts +35 -0
- package/lib/types/tools/omp/utils/cpuprofile.d.ts +51 -0
- package/lib/types/tools/omp/utils/edit-mode.d.ts +13 -0
- package/lib/types/tools/omp/utils/file-display-mode.d.ts +27 -0
- package/lib/types/tools/omp/utils/image-loading.d.ts +51 -0
- package/lib/types/tools/omp/utils/image-resize.d.ts +42 -0
- package/lib/types/tools/omp/utils/lang-from-path.d.ts +9 -0
- package/lib/types/tools/omp/utils/markit-cache.d.ts +23 -0
- package/lib/types/tools/omp/utils/markit.d.ts +30 -0
- package/lib/types/tools/omp/utils/profile-tree.d.ts +47 -0
- package/lib/types/tools/omp/utils/sample-profile.d.ts +67 -0
- package/lib/types/tools/omp/utils/sixel.d.ts +21 -0
- package/lib/types/tools/omp/utils/tools-manager.d.ts +11 -0
- package/lib/types/tools/omp/utils/turndown.d.ts +15 -0
- package/lib/types/tools/omp/utils/zip.d.ts +129 -0
- package/lib/types/tools/omp/web/browser-render.d.ts +50 -0
- package/lib/types/tools/omp/web/parallel.d.ts +68 -0
- package/lib/types/tools/omp/web/scrapers/artifacthub.d.ts +6 -0
- package/lib/types/tools/omp/web/scrapers/arxiv.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/aur.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/biorxiv.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/bluesky.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/brew.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/cheatsh.d.ts +8 -0
- package/lib/types/tools/omp/web/scrapers/chocolatey.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/choosealicense.d.ts +2 -0
- package/lib/types/tools/omp/web/scrapers/cisa-kev.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/clojars.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/coingecko.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/crates-io.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/crossref.d.ts +2 -0
- package/lib/types/tools/omp/web/scrapers/devto.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/discogs.d.ts +8 -0
- package/lib/types/tools/omp/web/scrapers/discourse.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/dockerhub.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/docs-rs.d.ts +9 -0
- package/lib/types/tools/omp/web/scrapers/fdroid.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/firefox-addons.d.ts +2 -0
- package/lib/types/tools/omp/web/scrapers/flathub.d.ts +2 -0
- package/lib/types/tools/omp/web/scrapers/github-gist.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/github.d.ts +34 -0
- package/lib/types/tools/omp/web/scrapers/gitlab.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/go-pkg.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/hackage.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/hackernews.d.ts +2 -0
- package/lib/types/tools/omp/web/scrapers/hex.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/huggingface.d.ts +2 -0
- package/lib/types/tools/omp/web/scrapers/iacr.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/index.d.ts +84 -0
- package/lib/types/tools/omp/web/scrapers/jetbrains-marketplace.d.ts +2 -0
- package/lib/types/tools/omp/web/scrapers/lemmy.d.ts +2 -0
- package/lib/types/tools/omp/web/scrapers/lobsters.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/mastodon.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/maven.d.ts +6 -0
- package/lib/types/tools/omp/web/scrapers/mdn.d.ts +2 -0
- package/lib/types/tools/omp/web/scrapers/metacpan.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/musicbrainz.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/npm.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/nuget.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/nvd.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/ollama.d.ts +2 -0
- package/lib/types/tools/omp/web/scrapers/open-vsx.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/opencorporates.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/openlibrary.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/orcid.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/osv.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/packagist.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/pub-dev.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/pubmed.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/pypi.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/rawg.d.ts +2 -0
- package/lib/types/tools/omp/web/scrapers/readthedocs.d.ts +2 -0
- package/lib/types/tools/omp/web/scrapers/reddit.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/repology.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/rfc.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/rubygems.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/searchcode.d.ts +2 -0
- package/lib/types/tools/omp/web/scrapers/sec-edgar.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/semantic-scholar.d.ts +2 -0
- package/lib/types/tools/omp/web/scrapers/snapcraft.d.ts +2 -0
- package/lib/types/tools/omp/web/scrapers/sourcegraph.d.ts +2 -0
- package/lib/types/tools/omp/web/scrapers/spdx.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/spotify.d.ts +8 -0
- package/lib/types/tools/omp/web/scrapers/stackoverflow.d.ts +6 -0
- package/lib/types/tools/omp/web/scrapers/terraform.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/tldr.d.ts +7 -0
- package/lib/types/tools/omp/web/scrapers/twitter.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/types.d.ts +90 -0
- package/lib/types/tools/omp/web/scrapers/utils.d.ts +26 -0
- package/lib/types/tools/omp/web/scrapers/vimeo.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/vscode-marketplace.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/w3c.d.ts +2 -0
- package/lib/types/tools/omp/web/scrapers/wikidata.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/wikipedia.d.ts +5 -0
- package/lib/types/tools/omp/web/scrapers/youtube.d.ts +5 -0
- package/lib/types/tools/omp/web/search/providers/utils.d.ts +49 -0
- package/lib/types/tools/omp/web/search/types.d.ts +501 -0
- package/lib/types/tools/omp/web/search/utils.d.ts +4 -0
- package/lib/types/tools/omp/workspace-tree.d.ts +42 -0
- package/lib/types/tools/read/adapter/index.d.ts +49 -0
- package/lib/types/tools/read/adapter/internal-urls/artifact-protocol.d.ts +15 -0
- package/lib/types/tools/read/adapter/internal-urls/registry-helpers.d.ts +44 -0
- package/lib/types/tools/read/adapter/registry/agent-registry.d.ts +29 -0
- package/lib/types/tools/shared/auto-generated-guard.dsh.d.ts +16 -0
- package/lib/types/tools/shared/browser-detect.d.ts +54 -0
- package/lib/types/tools/shared/browser-rpc-channel.d.ts +40 -0
- package/lib/types/tools/shared/bun-ffi-shim.d.ts +13 -0
- package/lib/types/tools/shared/bun-named-shim.d.ts +42 -0
- package/lib/types/tools/shared/bun-shim.d.ts +138 -0
- package/lib/types/tools/shared/bun-sqlite-shim.d.ts +49 -0
- package/lib/types/tools/shared/fs-promises-shim.d.ts +15 -0
- package/lib/types/tools/shared/image-bridge.d.ts +98 -0
- package/lib/types/tools/shared/omp-prompt.d.ts +47 -0
- package/lib/types/tools/shared/sandbox-policy.d.ts +38 -0
- package/lib/types/tools/shared/session-state.d.ts +51 -0
- package/lib/types/tools/shared/tool-errors.d.ts +33 -0
- package/lib/types/tools/shared/win-path-fixes.d.ts +16 -0
- package/lib/types/tools/write/adapter/index.d.ts +31 -0
- package/lib/{types-DX_bvuus.mjs → types-PVueGi9S.mjs} +2 -2
- package/lib/{utils-C-dSORPa.mjs → utils-B7A3Eu4L.mjs} +2364 -2676
- package/lib/{utils-Cp2Mxf_U.mjs → utils-CUPhpw9A.mjs} +413 -134
- package/lib/{utils-CQHPEQ3W.mjs → utils-DeWqNWV8.mjs} +2 -2
- package/lib/{vision-guard-mBmtAHx0.mjs → vision-guard-_XwsL1DF.mjs} +14 -29
- package/lib/xai-oauth-CXhnz0gO.mjs +210 -0
- package/lib/{xiaomi-7mE345KX.mjs → xiaomi-psoUItal.mjs} +8 -37
- package/lib/{zai-CeNpMV3W.mjs → zai-ApJ8HBgT.mjs} +8 -71
- package/lib/{zip-BK7UHCwX.mjs → zip-Kd602XNe.mjs} +1 -1
- package/package.json +12 -12
- package/presets/package.json +1 -1
- package/presets/tool-plus-ptc/agent.cordis.yml +1 -1
- package/presets/tool-plus-standard/agent.cordis.yml +1 -1
- package/scripts/patch-pi-natives.mjs +108 -108
- package/lib/agent_pb-Rizyt9Zg.mjs +0 -805
- package/lib/anthropic-CDmj476p.mjs +0 -262
- package/lib/api_server_pb-CDZgLMta.mjs +0 -252
- package/lib/callback-server-CFJK-jvK.mjs +0 -398
- package/lib/codex-P1dGpX7G.mjs +0 -54
- package/lib/device-code-CuXTWYwY.mjs +0 -51
- package/lib/devin-BcQwht1W.mjs +0 -114
- package/lib/devin-BvMfGevz.mjs +0 -95
- package/lib/github-copilot-B3kQl0g0.mjs +0 -104
- package/lib/gitlab-duo-BriUTP8k.mjs +0 -155
- package/lib/gitlab-duo-workflow-wK5Ljzmc.mjs +0 -91
- package/lib/google-CE5tFDod.mjs +0 -30
- package/lib/google-antigravity-C1jgNljz.mjs +0 -198
- package/lib/google-oauth-shared-BLVTvokk.mjs +0 -147
- package/lib/grammar-D-NqNUxQ.mjs +0 -49
- package/lib/identity-HNO1Oe9B.mjs +0 -219
- package/lib/kimi-DgcUpPtK.mjs +0 -236
- package/lib/markit-DtGoRE6M.mjs +0 -1417
- package/lib/minimax-code-Y3h5li9N.mjs +0 -53
- package/lib/models-DRA2c_8U.mjs +0 -104660
- package/lib/opencode-BsVw9rCD.mjs +0 -38
- package/lib/to-binary-B1BEBIPC.mjs +0 -6002
- package/lib/wafer-BlhWLweO.mjs +0 -17
- package/lib/xai-oauth-5pORHUrg.mjs +0 -446
|
@@ -0,0 +1,2304 @@
|
|
|
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-DeWqNWV8.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 };
|