@prismshadow/penguin-server 0.2.15 → 0.2.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/README.md +1 -1
  2. package/dist/api/types.d.ts +318 -86
  3. package/dist/api/types.js +9 -3
  4. package/dist/auth-token.d.ts +1 -1
  5. package/dist/auth-token.js +2 -2
  6. package/dist/{chunk-HMTT2PX4.js → chunk-2LZDP26O.js} +8 -5
  7. package/dist/chunk-2LZDP26O.js.map +1 -0
  8. package/dist/{chunk-LPPVGHYD.js → chunk-BL4U7GYY.js} +2 -2
  9. package/dist/chunk-BL4U7GYY.js.map +1 -0
  10. package/dist/{chunk-5Z4UCHDB.js → chunk-D3JNA6ZI.js} +69 -6
  11. package/dist/chunk-D3JNA6ZI.js.map +1 -0
  12. package/dist/{chunk-TOOTEEM4.js → chunk-G7GY7PJU.js} +1 -1
  13. package/dist/chunk-G7GY7PJU.js.map +1 -0
  14. package/dist/chunk-GGIINEEK.js +3401 -0
  15. package/dist/chunk-GGIINEEK.js.map +1 -0
  16. package/dist/chunk-HDBZRVA5.js +29 -0
  17. package/dist/chunk-HDBZRVA5.js.map +1 -0
  18. package/dist/{chunk-NVWAYYRX.js → chunk-HPOHMZCH.js} +686 -531
  19. package/dist/chunk-HPOHMZCH.js.map +1 -0
  20. package/dist/{chunk-QFV3ERQO.js → chunk-OQZDL3TR.js} +2 -2
  21. package/dist/hmr/manifest.js +1 -1
  22. package/dist/index.js +9351 -5551
  23. package/dist/index.js.map +1 -1
  24. package/dist/machine-status.js +2 -2
  25. package/dist/model-catalog.d.ts +610 -0
  26. package/dist/model-catalog.js +108 -0
  27. package/dist/model-catalog.js.map +1 -0
  28. package/dist/plugin/index.d.ts +141 -78
  29. package/dist/reset-admin-password.js +3 -4
  30. package/dist/reset-admin-password.js.map +1 -1
  31. package/dist/version-report.js +2 -2
  32. package/package.json +15 -14
  33. package/web-dist/assets/{abnfDiagram-VCTEODGH-CKWh4hoA.js → abnfDiagram-VCTEODGH-DMzkb4l4.js} +1 -1
  34. package/web-dist/assets/{addon-clipboard-DxLqat7q.js → addon-clipboard-BtD2BVSi.js} +1 -1
  35. package/web-dist/assets/{addon-fit-B8oPGPkW.js → addon-fit-Dr6HWsi_.js} +1 -1
  36. package/web-dist/assets/{addon-web-links-C0W5TcK0.js → addon-web-links-VEE3YLzQ.js} +1 -1
  37. package/web-dist/assets/{arc-Dp9EkaAH.js → arc-CvMPOU_B.js} +1 -1
  38. package/web-dist/assets/{architectureDiagram-5GKGNRK7-BQ3LUcle.js → architectureDiagram-5GKGNRK7-Bk65mIBz.js} +1 -1
  39. package/web-dist/assets/{blockDiagram-I7D4REHJ-CZzyU0Jj.js → blockDiagram-I7D4REHJ-D54-XSNs.js} +1 -1
  40. package/web-dist/assets/{c4Diagram-7LVT6UL2-Qps3jeAu.js → c4Diagram-7LVT6UL2-Dm954LSt.js} +1 -1
  41. package/web-dist/assets/channel-CVHI75kz.js +1 -0
  42. package/web-dist/assets/{chunk-2Q5K7J3B-CQMntzuX.js → chunk-2Q5K7J3B-D_LJ_7Cn.js} +1 -1
  43. package/web-dist/assets/{chunk-5VM5RSS4-2H2ZJAte.js → chunk-5VM5RSS4-B8RI4tl3.js} +1 -1
  44. package/web-dist/assets/{chunk-F27PBJKO-B30xCNBv.js → chunk-F27PBJKO-aVSYH9JV.js} +1 -1
  45. package/web-dist/assets/{chunk-IMKFNOWR-Cyfx4zDs.js → chunk-IMKFNOWR-DnkdWeq2.js} +1 -1
  46. package/web-dist/assets/{chunk-JWPE2WC7-DADUytTh.js → chunk-JWPE2WC7-C2pJzKuW.js} +1 -1
  47. package/web-dist/assets/{chunk-POPQ4Y6H-9bjsAxLS.js → chunk-POPQ4Y6H-Bx7Iikzx.js} +1 -1
  48. package/web-dist/assets/{chunk-SVP7TREG-B9xO1VpN.js → chunk-SVP7TREG-qJC2SMqr.js} +1 -1
  49. package/web-dist/assets/{chunk-TICWLB2K-B6oDkrep.js → chunk-TICWLB2K-Crl_BgKI.js} +1 -1
  50. package/web-dist/assets/{chunk-XXDRQBXY-BbU8DR4B.js → chunk-XXDRQBXY-BFFemuGm.js} +1 -1
  51. package/web-dist/assets/classDiagram-ZZMXUADV-CBdzAPFu.js +1 -0
  52. package/web-dist/assets/classDiagram-v2-VYDZK3BY-CBdzAPFu.js +1 -0
  53. package/web-dist/assets/{cose-bilkent-JH36ORCC-pkbuyec-.js → cose-bilkent-JH36ORCC-Bmh2Kx7h.js} +1 -1
  54. package/web-dist/assets/{cynefin-OW5HDTMX-DU9YQQnc.js → cynefin-OW5HDTMX-BveNWnUV.js} +1 -1
  55. package/web-dist/assets/{cynefinDiagram-5FMLGOSQ-3a3XuhQq.js → cynefinDiagram-5FMLGOSQ-85itazbJ.js} +1 -1
  56. package/web-dist/assets/{dagre-GXQ25YYZ-BfZ9C5CZ.js → dagre-GXQ25YYZ-DIZT-KY_.js} +1 -1
  57. package/web-dist/assets/{diagram-S7CK7UJ4-BoGhVBMn.js → diagram-S7CK7UJ4-Dum-g63f.js} +1 -1
  58. package/web-dist/assets/{diagram-UQ7AKVKN-zE67quty.js → diagram-UQ7AKVKN-DallMKJl.js} +1 -1
  59. package/web-dist/assets/{diagram-VSXAHHWV-NihoXeXm.js → diagram-VSXAHHWV-DWELqxfN.js} +1 -1
  60. package/web-dist/assets/{diagram-VX7I27RA-1627np0S.js → diagram-VX7I27RA-BNs0gB9E.js} +1 -1
  61. package/web-dist/assets/{diagram-Z3DM3KII-Ddg_bUan.js → diagram-Z3DM3KII-C9mF9xAd.js} +1 -1
  62. package/web-dist/assets/{ebnfDiagram-PWID7BFC-CmPUOM4j.js → ebnfDiagram-PWID7BFC-D_Diy9HH.js} +1 -1
  63. package/web-dist/assets/{erDiagram-RLTQ6QDP-DiTnEK72.js → erDiagram-RLTQ6QDP-4QTS5VIh.js} +1 -1
  64. package/web-dist/assets/{flowDiagram-HODETNUW-mGQ38tRM.js → flowDiagram-HODETNUW-CliTRrtV.js} +1 -1
  65. package/web-dist/assets/{ganttDiagram-EL5Y4UJY-DU7MlzpW.js → ganttDiagram-EL5Y4UJY-DCRd-Ss4.js} +1 -1
  66. package/web-dist/assets/{gitGraphDiagram-WWUBYQGX-CRE_3vjl.js → gitGraphDiagram-WWUBYQGX-CTz13GjS.js} +1 -1
  67. package/web-dist/assets/highlighter-BScH1Ud3.js +2 -0
  68. package/web-dist/assets/{highlighter-core-B5CvXcEK.js → highlighter-core-DKz8Z6-I.js} +1 -1
  69. package/web-dist/assets/{highlighter.worker-D6D9fPma.js → highlighter.worker-CKF6ok1g.js} +1 -1
  70. package/web-dist/assets/index-BUvJ5Ctt.js +1299 -0
  71. package/web-dist/assets/index-DRj7nvPY.css +1 -0
  72. package/web-dist/assets/{infoDiagram-27XIBGKW-Cdo6Ar-a.js → infoDiagram-27XIBGKW-DNfTEPAV.js} +1 -1
  73. package/web-dist/assets/{ishikawaDiagram-5VMMS53U-C27pgect.js → ishikawaDiagram-5VMMS53U-B7aCjjG1.js} +1 -1
  74. package/web-dist/assets/{journeyDiagram-3NMN7TZE-CVxtKpLG.js → journeyDiagram-3NMN7TZE-COmDALVr.js} +1 -1
  75. package/web-dist/assets/{kanban-definition-UXKFOSKX-DWA31Da7.js → kanban-definition-UXKFOSKX-BzUfPINh.js} +1 -1
  76. package/web-dist/assets/{layout-DWKCU9PO.js → layout-BwzuPU4M.js} +1 -1
  77. package/web-dist/assets/{linear-BwCthj_k.js → linear-WPZTYjz3.js} +1 -1
  78. package/web-dist/assets/mermaid.core-zKzlwpkw.js +310 -0
  79. package/web-dist/assets/{mindmap-definition-YA3MSWOX-BLEDhbn1.js → mindmap-definition-YA3MSWOX-DCRg7eAx.js} +1 -1
  80. package/web-dist/assets/{pegDiagram-XKGWAZYB-CLEM1SDU.js → pegDiagram-XKGWAZYB-DyphzDLU.js} +1 -1
  81. package/web-dist/assets/{pieDiagram-E7YTZNPT-B__g6eF0.js → pieDiagram-E7YTZNPT-BI5DueGA.js} +1 -1
  82. package/web-dist/assets/powershell-DXrKVo3G.js +1 -0
  83. package/web-dist/assets/powershell-Dpen1YoG.js +1 -0
  84. package/web-dist/assets/{quadrantDiagram-AXDQQJYC-C7VQ2LMY.js → quadrantDiagram-AXDQQJYC-GZxSMY2Z.js} +1 -1
  85. package/web-dist/assets/{railroadDiagram-O6MQD6OU-eWNnzjwS.js → railroadDiagram-O6MQD6OU-DEFCigBf.js} +1 -1
  86. package/web-dist/assets/{requirementDiagram-BXWQKSXE-Bi5qeD4b.js → requirementDiagram-BXWQKSXE-Br0thc4j.js} +1 -1
  87. package/web-dist/assets/{sankeyDiagram-P5KCCOFB-DG1VOpXX.js → sankeyDiagram-P5KCCOFB-DYf0pY67.js} +1 -1
  88. package/web-dist/assets/{sequenceDiagram-WJ2MYXX4-Fhkw73Th.js → sequenceDiagram-WJ2MYXX4-1EFMboX4.js} +1 -1
  89. package/web-dist/assets/{sizeCapture-INFHLROL-D9E_17SF.js → sizeCapture-INFHLROL-BuOFv-5q.js} +1 -1
  90. package/web-dist/assets/{stateDiagram-D77RDMKH-Cs5Y0xhW.js → stateDiagram-D77RDMKH-Bg3H1tjX.js} +1 -1
  91. package/web-dist/assets/stateDiagram-v2-MP3YSRHH-DfaDaPAd.js +1 -0
  92. package/web-dist/assets/{swimlanes-42K2YHIH-t-EocvKZ.js → swimlanes-42K2YHIH-BuOa6Osb.js} +1 -1
  93. package/web-dist/assets/swimlanesDiagram-VR7AAH4N-BopAC7b8.js +8 -0
  94. package/web-dist/assets/{timeline-definition-24CTP7MA-CozGCxuA.js → timeline-definition-24CTP7MA-BDekfdDT.js} +1 -1
  95. package/web-dist/assets/{vennDiagram-4TSXK5OY-ewU8ycSa.js → vennDiagram-4TSXK5OY-DnC09UI4.js} +1 -1
  96. package/web-dist/assets/{wardleyDiagram-VM6X3IG4-DuAhDu-0.js → wardleyDiagram-VM6X3IG4-BXKvxuZQ.js} +1 -1
  97. package/web-dist/assets/{xterm-v5e56GC9.js → xterm-oY4DYg5s.js} +1 -1
  98. package/web-dist/assets/{xychartDiagram-S5SC5T6Z-BxGuZO23.js → xychartDiagram-S5SC5T6Z-DdDC1VLb.js} +1 -1
  99. package/web-dist/index.html +12 -6
  100. package/web-dist/{workflow-ui.css → workbench-ui.css} +72 -67
  101. package/dist/benchmark-package.d.ts +0 -39
  102. package/dist/benchmark-package.js +0 -97
  103. package/dist/benchmark-package.js.map +0 -1
  104. package/dist/chunk-54E64LWB.js +0 -63
  105. package/dist/chunk-54E64LWB.js.map +0 -1
  106. package/dist/chunk-5Z4UCHDB.js.map +0 -1
  107. package/dist/chunk-HMTT2PX4.js.map +0 -1
  108. package/dist/chunk-JKJXQTHH.js +0 -19
  109. package/dist/chunk-JKJXQTHH.js.map +0 -1
  110. package/dist/chunk-LPPVGHYD.js.map +0 -1
  111. package/dist/chunk-NVWAYYRX.js.map +0 -1
  112. package/dist/chunk-Q4ON2L6E.js +0 -52
  113. package/dist/chunk-Q4ON2L6E.js.map +0 -1
  114. package/dist/chunk-TOOTEEM4.js.map +0 -1
  115. package/web-dist/assets/channel--PblgLlC.js +0 -1
  116. package/web-dist/assets/classDiagram-ZZMXUADV-mn8tbuqa.js +0 -1
  117. package/web-dist/assets/classDiagram-v2-VYDZK3BY-mn8tbuqa.js +0 -1
  118. package/web-dist/assets/highlighter-CzfXQ6yd.js +0 -2
  119. package/web-dist/assets/index-BdG4qRyI.js +0 -1275
  120. package/web-dist/assets/index-W-xYFoIm.css +0 -1
  121. package/web-dist/assets/mermaid.core-BcTrmPOv.js +0 -310
  122. package/web-dist/assets/stateDiagram-v2-MP3YSRHH-CEM51fAf.js +0 -1
  123. package/web-dist/assets/swimlanesDiagram-VR7AAH4N-BrR66vrK.js +0 -8
  124. /package/dist/{chunk-QFV3ERQO.js.map → chunk-OQZDL3TR.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/model-catalog/catalog.ts","../src/model-catalog/env-keys.ts","../src/model-catalog/seed.ts"],"sourcesContent":["/**\n * Built-in model catalog data and its lookups (single source of truth): official chat models\n * that MMSP can auto-route, the provider groups, pricing and off-peak rules, and the UI helpers\n * — the server's, which seeds a new Project's config from it (seed.ts), and the Web App's, the\n * CLI's and the component gallery's, which display it through the browser-safe subpath\n * `@prismshadow/penguin-server/model-catalog` (index.ts).\n *\n * Core knows none of this (PRN-021): it holds MMSP's client table and the connection rules\n * (`@prismshadow/penguin-core/model-connection`), and the catalog reaches it only through the\n * Project config this module seeds.\n * Data verified as of 2026-07-10 (Qwen Token Plan entries: 2026-07-20; MiniMax: 2026-08-03;\n * DeepSeek, GLM-5.3 and the whole OpenAI line-up (direct + OpenRouter):\n * 2026-08-18; the direct Anthropic group: 2026-08-20; the DeepSeek V4 Flash Vision Exp rows:\n * 2026-08-21; the TokenDance group: 2026-08-25, its glm-5.3-flash row: 2026-08-26, its\n * qwen3.8-flash row: 2026-08-27 and its running promotions plus the hy4-preview rows\n * (TokenDance + OpenRouter): 2026-08-28; the GLM-5.3 Flash rows (direct + OpenRouter) and\n * the direct qwen3.8-flash: 2026-08-26; the TokenDance Doubao Seed rows (seed-2.1-pro,\n * seed-2.1-turbo, seed-evolving): 2026-09-02; the vLLM group: 2026-09-03; the GPT-6 Astra\n * rows (direct + OpenRouter): 2026-09-09; the whole Gemini 3.x line-up, direct + OpenRouter —\n * the 3.6 / 3.8 Flash launch discounts declared, every other row re-read and unchanged:\n * 2026-09-09; the OpenRouter and TokenDance V4.1 Flash rows, and TokenDance's running\n * promotions plus its Doubao Seed display names: 2026-09-10; the Penguin Go resale lineup,\n * matched to the relay's current generic-client model export: 2026-09-11, its DeepSeek rows to\n * DeepSeek's own lineup: 2026-09-16; the OpenRouter z-ai/glm-5.3-flash row: 2026-09-16; and\n * the 2026-09-16 refresh — the direct DeepSeek group down to the two names its pricing page\n * lists, TokenDance's deepseek-v4-flash-0731 / deepseek-v4-pro-0813 / kimi-k3 promotions, the\n * OpenRouter qwen/qwen3.8-27b row, the Fireworks AI and SiliconFlow additions, and both Qwen\n * groups' line-ups with their peak/off-peak DeepSeek rows: 2026-09-16; the OpenCode Go group:\n * 2026-09-18 — per each provider's docs; the ModelScope group, whose preset ids were read\n * from public model pages and endpoint listings — their windows, vision flags and prices are\n * NOT verified and say so on the rows themselves: 2026-09-18 and 2026-09-20; the\n * 2026-10-10 refresh — Claude Fable 5.1, Opus 5.5, Sonnet 5.5 and Haiku 5.5 and GPT-6.1 Sol\n * (direct + OpenRouter) per MMSP 0.5.2's registry and the vendor pages it carries, the whole\n * TokenDance group re-read from its public portal API, the OpenRouter Step 5 Preview, Grok 4.7\n * and MiMo-V2.6-Flash rows, SiliconFlow's GLM-5.3 Flash and Hy4 preview rows, and Gemini 3.7\n * Flash dropped from every group, Google rerouting the id to 3.8 Flash: 2026-10-10; and the\n * Atlas Cloud group, from its public catalog API and pricing page: 2026-10-11; Gemini 4 Argon\n * (Google, Penguin Go and OpenRouter): 2026-10-14).\n * Docs: packages/docs/content/models.{zh,en}.md (site path /docs/models) documents the\n * provider groups and credential resolution described here.\n *\n * Three-bucket pricing convention (USD per million tokens, matching usageToTokenCounts'\n * token-to-bucket mapping):\n * - cache_read: the vendor's \"cache hit\" price;\n * - cache_write: the vendor's \"cache write\" price (e.g. Anthropic uses 1.25 x input); vendors\n * without a separate cache-write fee use the standard input price;\n * - output: output price (thinking + reply).\n * OpenAI charges extra for >272K input, Gemini 3.1 Pro for >200K input, MiniMax M3 doubles\n * every rate above 512K input, and Claude Haiku 5.5 quintuples every rate above 100K; this\n * catalog records their base tier (the cost center uses a single rate, so long-context usage\n * will be underestimated).\n *\n * Scope: excludes deepseek-chat / deepseek-reasoner legacy aliases (deprecated 2026-07-24),\n * glm-5v-turbo (MMSP's Z.AI client forwards images\n * only for glm-5.3-flash, so a vision model cannot do the one thing it exists for), the\n * OpenRouter z-ai/glm-5.1 and SiliconFlow Pro/zai-org/GLM-5.1 gateway listings\n * (delisted 2026-08-06; the Z.AI direct glm-5.1 remains), the OpenRouter\n * inclusionai/ling-3.0-flash:free listing (delisted from OpenRouter, removed 2026-08-18),\n * non-chat models (embedding / image generation / TTS), and Bedrock. Direct-vendor ids are\n * auto-routed by MMSP and leave client_type unset; eight gateway groups (OpenRouter,\n * Fireworks AI, SiliconFlow, Atlas Cloud, TokenDance, OpenCode Go, Qwen Pay-As-You-Go and Qwen\n * Token Plan) can't be auto-routed, so every gateway row **always pins an explicit\n * client_type** and names its preset base URL. ModelScope's rows pin one protocol too (see below).\n * These are reference values, never runtime fallbacks: a new Project's file receives them\n * once — a group's shared endpoint and protocol in its `[providers.<id>]` table\n * (presetProviderTable), a row's own only where it differs from its group's\n * (catalogModelEntry) — as do \"Add new models\" and \"Restore defaults\"; from then on the file\n * alone says where a request goes (effectiveConnection reads no catalog).\n * Five groups pin at GROUP level as well (ModelProviderInfo.clientType, read\n * through providerClientType), so that a model the user adds there speaks the same protocol\n * as the presets: vLLM, whose added models inherit the local server's address its table is\n * seeded with, and OpenRouter, TokenDance, SiliconFlow and Atlas Cloud, whose inherit the\n * gateway's — see each group's own block comment.\n * That pin is load-bearing, not decoration: MMSP's AutoLLMClient routes an unpinned id by\n * the family its spelling begins with and never looks at base_url (MMSP's routedClientType), so\n * an unpinned gateway id would be placed by its own spelling — `deepseek-ai/DeepSeek-V4` would\n * reach DeepSeek's official client aimed at a gateway, and `openai/gpt-5.6-sol` would throw\n * outright (no known family begins with \"openai/\"). Gateway protocols are pinned:\n * - `openai-responses` for every OpenRouter row: OpenRouter serves the Responses API for\n * every upstream at the same base URL the rows already carry, and the group pins the same\n * protocol so a user-added entry inherits it;\n * - `openai-chat` for the other OpenAI-compatible gateway rows (the generic Chat Completions\n * client — the bare \"openai\" spelling is a deprecated upstream alias, see\n * canonicalClientType);\n * - `openai-chat-vllm-adapter` for the vLLM group, which is Chat Completions on the wire\n * but maps the thinking level onto the served model's own chat template\n * (VLLM_CLIENT_TYPE);\n * - `ant-messages` for the OpenCode Go rows its endpoint table serves on the Anthropic\n * Messages API;\n * - `google-genai` for OpenCode Go's Gemini row. The group pins row by row across four\n * protocols; its other rows use `openai-chat` and `openai-responses` — see its block comment.\n * ModelScope's rows all pin `openai-responses`: ModelScope serves every preset through its\n * OpenAI Responses endpoint, and the explicit pin keeps a Qwen or DeepSeek id from auto-routing\n * to a vendor client with a different request shape.\n *\n * App attribution (the headers that name PenguinHarness to the gateways that read one) is not\n * here: it is keyed on the endpoint host, not on a provider group, and is a module of core's\n * own (`llm/app-attribution.ts`), whose headers GenerativeModel attaches to every request.\n *\n * This file imports no Node built-ins: core's types, core's browser-safe connection subpath and\n * MMSP's credentials module (`@prismshadow/mmsp/credentials`, which imports nothing) only, so it\n * can be bundled directly for the browser.\n */\nimport {\n CLIENT_CREDENTIALS,\n OFFICIAL_CLIENT_TYPES,\n routedClientType,\n} from \"@prismshadow/mmsp/credentials\";\nimport type { ModelPricing } from \"@prismshadow/penguin-core\";\nimport { sameClientType } from \"@prismshadow/penguin-core/model-connection\";\n\n/** Model provider info (used for web grouping/logo and the \"API key blank falls back to env var\" hint). */\n/**\n * A provider that mints API keys through an authorization page instead of a console visit.\n * Present only on providers that publish such a flow; its absence is what makes the harness\n * refuse to start one.\n */\nexport interface ModelProviderOAuth {\n /** Authorization page the user is sent to; the flow's parameters ride on its query string. */\n authorizeUrl: string;\n /** Endpoint that trades an authorization code for a newly minted key. */\n exchangeUrl: string;\n /** Name recorded on the minted key, and the app name the authorization page displays. */\n keyName: string;\n}\n\n/**\n * A group whose credential the App obtains through its own authorization flow rather than by\n * asking the vendor: the client registers a one-time code and device secret with an external\n * bridge, sends the user to the page that bridge hands back, and polls until the bridge\n * delivers the credential. Distinct from `oauth`, where the App itself speaks the vendor's\n * PKCE page — here the App never reaches the vendor at all, because the bridge holds the\n * client secret that conversation would need.\n *\n * The bridge's own address is deliberately NOT here: this file is bundled for the browser and\n * cannot read configuration, so the App resolves the bridge server-side from its environment\n * (PENGUIN_GO_ORIGIN / MODELSCOPE_BRIDGE_URL), keyed by the group's id.\n */\nexport interface ModelProviderBridgeAuth {\n /**\n * Which App-side flow serves this group — one route family and one service per value, so\n * the Web App picks from the group's descriptor rather than from its id.\n */\n flow: \"penguin-go\" | \"modelscope\";\n}\n\n/**\n * An account-balance endpoint the vendor publishes, called with the group's own API key as a\n * Bearer token. The server makes that call (the key never reaches the browser); the endpoint\n * is the vendor's, like the OAuth one above, so it can live in this browser-bundled file.\n */\nexport interface ModelProviderBalance {\n /** GET endpoint answering the balance of the account the key belongs to. */\n url: string;\n /**\n * How to read the answer, one reader per published response shape:\n * - `tokendance`: `{ balance: { credits, credits_used, balance } }`, integers in micro-yuan\n * (1 CNY = 1,000,000);\n * - `deepseek`: `{ is_available, balance_infos: [{ currency, total_balance, … }] }`, one entry\n * per currency the account holds.\n * - `penguin-go`: `{ balance: { units, currency } }`, a CNY ledger integer in 10^-12 yuan.\n */\n format: \"tokendance\" | \"deepseek\" | \"penguin-go\";\n}\n\nexport interface ModelProviderInfo {\n id: string;\n /** Display name (brand name, shared by Chinese and English UI). */\n label: string;\n /**\n * API key env var name: the variable MMSP's client for this group's rows reads when handed no\n * key, which it does only for its own default endpoint (PRN-021, MMSP's rule). A gateway group\n * records OPENAI_* because that is what its generic client reads, and its rows carry the\n * gateway's base URL, so that client never reads it for them.\n */\n envKey: string;\n /** base URL env var name. */\n envBaseUrlKey: string;\n /** Console URL for obtaining an API key (frontend links it beside the API key field of the group key dialog and the model dialog); none for custom. */\n apiKeyUrl?: string;\n /** Vendor's model list / docs page URL (frontend's \"add model\" dialog links this as \"get model id\"); none for custom. */\n modelsUrl?: string;\n /**\n * Gateway's OpenAI-compatible endpoint (openrouter / siliconflow / qwen-token-plan / …): what\n * a new Project writes as the group's `[providers.<id>]` base URL (catalogGroupConnection),\n * so every row of the group — a model added by hand included — follows it without storing\n * the address itself. A reference value: nothing reads it when a request is built. Left\n * blank for direct vendors, custom and vLLM (whose rows name the local server's address).\n */\n gatewayBaseUrl?: string;\n /**\n * Authorization flow that mints a key for the user (see ModelProviderOAuth); absent for\n * every provider whose keys are only obtainable from its console.\n */\n oauth?: ModelProviderOAuth;\n /**\n * The App-side authorization flow that obtains this group's credential (see\n * ModelProviderBridgeAuth); absent for every group whose credential comes from a console or\n * from the vendor's own page. Declaring it is what puts the \"authorize a key\" action on the\n * group in the Web App.\n */\n bridgeAuth?: ModelProviderBridgeAuth;\n /**\n * The vendor's account-balance endpoint (see ModelProviderBalance); absent for every group\n * whose vendor publishes none. Declaring it is what puts the balance in the group's header.\n */\n balance?: ModelProviderBalance;\n /**\n * The group takes models the user adds by hand: `custom` and vLLM, whose rows point at an\n * endpoint the catalog cannot know, and the four gateways whose catalogs list a fraction of\n * what they serve — OpenRouter, TokenDance, SiliconFlow and Atlas Cloud — where an added\n * model follows the group's connection (its endpoint, key and protocol) exactly as the\n * presets do. Every other built-in group carries its catalog presets and the rows it already\n * stores, and nothing else. Read it through isAddableGroup, which also answers for\n * user-defined groups.\n */\n addable?: boolean;\n /**\n * The MMSP protocol EVERY entry in this group speaks, models the user adds included.\n *\n * Set it where the group itself decides the answer for a row the catalog does not list:\n * every group that takes hand-added models and speaks one protocol (vLLM, OpenRouter,\n * TokenDance, SiliconFlow, Atlas Cloud). The other gateways hold catalog rows only, each\n * carrying its own pin, and `custom` / user-defined groups deliberately declare nothing —\n * their whole point is that the protocol is detected from the endpoint or picked by hand,\n * and a pin here would take that choice away.\n *\n * Where it IS set, a new Project writes it as the group's `[providers.<id>]` protocol\n * (catalogGroupConnection), and the rows — models added by hand included — follow that\n * table. A reference value like gatewayBaseUrl: what the app reads at runtime is the file's\n * table. Read it through providerClientType rather than reaching for the field.\n */\n clientType?: string;\n /**\n * The group the product recommends, captioned as such on the models page. It marks the\n * GROUP, not a position: a user who drags the group elsewhere keeps the caption with it,\n * and the default sequence below is what places it first for everyone else.\n */\n recommended?: boolean;\n}\n\n/** A single built-in model's catalog entry (`modelId` is the upstream id; paired with `provider` it forms the catalog's unique key). */\nexport interface ModelCatalogEntry {\n modelId: string;\n displayName: string;\n /** Provider id (one of MODEL_PROVIDERS). */\n provider: string;\n contextWindow?: number;\n pricing?: ModelPricing;\n /**\n * Fraction off the list price the seller is currently running (0.5 = 50% off), applied to\n * every bucket. `pricing` stays the LIST price whatever promotion is live, so a lapsed\n * promotion is one field to delete rather than three numbers to reconstruct;\n * effectivePricing is the rate actually billed. A Project stores the list price too: the\n * fraction is seeded beside it as a promotion (presetPromotions), which the cost center\n * applies when it prices usage, so it charges what the seller charges.\n */\n discount?: number;\n /**\n * A discount that is only live outside a weekly set of peak windows — a vendor billing\n * cheaper off-hours. `pricing` holds the PEAK price, the one billed inside the windows, and\n * the rate applies everywhere else.\n *\n * Like `discount`, this one is never baked into a Project, and here there is no choice: it\n * changes twice a day. `presetModelEntries` writes the peak price and the rate is applied\n * when a price is read.\n * A number on disk that silently meant something different at 09:00 than at 08:00 would be\n * unreadable, and re-syncing presets would rewrite prices by the clock. A seller that also\n * takes something off on top of the schedule, in both tiers, declares it in `discount`: it is\n * seeded like any promotion, and the two multiply, as a Project's promotion and schedule do\n * wherever a price is read.\n */\n offPeakDiscount?: OffPeakDiscount;\n /** Whether image input (vision modality) is supported. */\n supportsVision: boolean;\n /** MMSP client type: required when an id cannot be auto-routed or a shared protocol must be pinned. */\n clientType?: string;\n /**\n * Preset base URL, so only an API key is required. A new Project stores it once: on the\n * group's `[providers.<id>]` table when it is the group's endpoint (catalogGroupConnection),\n * else on the row itself (catalogModelEntry). Never read when a request is built.\n */\n baseUrl?: string;\n /**\n * No longer a preset (superseded or withdrawn), but saved Projects still carry it: a\n * row a Project has is never deleted by \"Add new models\", and several of these were the\n * default model of new Projects. A retired row is not a preset — `presetModelEntries` and\n * `presetPromotions` skip it, so a new Project never gets it or a promotion for it, a sync\n * never adds it, and \"Restore defaults\" deletes it with every other row that is not a preset —\n * but it is still in `catalogModelEntries`, and lookups by `(provider, modelId)` still find\n * it. Projects carrying it keep its display name and vision flag, and their usage on it is\n * priced on its off-peak schedule whenever the row stores the catalog's price: the tier only\n * applies to that price. The schedule is the part that matters: cost is priced when it is\n * read, so deleting a scheduled row would reprice every off-peak record already on those\n * Projects at the peak rate.\n *\n * Compatibility, not catalog data: remove a retired row only after its seller has stopped\n * accepting the id AND the release notes have told users that usage recorded on it will be\n * priced without its schedule from then on. Whoever does the catalog refresh that finds the\n * id rejected makes that call.\n */\n retired?: true;\n /**\n * This row is, or once was, the default model of new Projects (PRESET_DEFAULT_MODEL). Usage\n * recorded on it stays priced after a Project stops storing the row — \"Restore defaults\"\n * deletes every row that is not a preset, retired ones included, and a former default is\n * often most of an older Project's history: retainedCatalogPricing gives the cost path this\n * row's `pricing` for it. Moving the default sets this on the new row and leaves it on the\n * old one, which also keeps the old row in the catalog (retired once it stops being a preset)\n * for as long as anyone may have recorded usage on it.\n */\n wasDefault?: true;\n}\n\n/**\n * MMSP's client for models served by vLLM's OpenAI-compatible Chat Completions API. It is\n * Chat Completions on the wire, but a distinct client: it maps the thinking level onto the\n * `chat_template_kwargs` the SERVED model's chat template reads, which differs per model\n * family, so `openai-chat` would silently lose that mapping.\n */\nconst VLLM_CLIENT_TYPE = \"openai-chat-vllm-adapter\";\n\n/**\n * Where `vllm serve` answers when it runs on this machine with its default port (8000): every\n * vLLM row's preset base URL, so a new Project stores it once, on the group's table\n * (catalogGroupConnection), and the models added to the group by hand follow it too.\n */\nconst VLLM_LOCAL_BASE_URL = \"http://127.0.0.1:8000/v1\";\n\n/** Preset provider endpoints; only OpenAI-compatible gateways expose theirs as gatewayBaseUrl. */\nconst OPENROUTER_BASE_URL = \"https://openrouter.ai/api/v1\";\nconst SILICONFLOW_BASE_URL = \"https://api.siliconflow.cn/v1\";\nconst QWEN_TOKEN_PLAN_BASE_URL =\n \"https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1\";\nconst QWEN_PAYG_BASE_URL = \"https://dashscope.aliyuncs.com/compatible-mode/v1\";\nconst FIREWORKS_BASE_URL = \"https://api.fireworks.ai/inference/v1\";\nconst TOKENDANCE_BASE_URL = \"https://tokendance.space/gateway/v1\";\n/** TokenDance's Anthropic Messages base: the SDK appends /v1/messages itself, so no /v1 here. */\nconst TOKENDANCE_MESSAGES_BASE_URL = \"https://tokendance.space/gateway\";\nconst DEEPSEEK_BASE_URL = \"https://api.deepseek.com\";\nconst MODELSCOPE_BASE_URL = \"https://api-inference.modelscope.cn/v1\";\nconst ATLASCLOUD_BASE_URL = \"https://api.atlascloud.ai/v1\";\nexport const PENGUIN_GO_BASE_URL = \"https://go.penguin.ooo/api/v1\";\n\n/** OpenCode Go's OpenAI-protocol base: the clients append /chat/completions or /responses. */\nconst OPENCODE_GO_BASE_URL = \"https://opencode.ai/zen/go/v1\";\n/** OpenCode Go's Anthropic Messages base: the SDK appends /v1/messages itself, so no /v1 here. */\nconst OPENCODE_GO_MESSAGES_BASE_URL = \"https://opencode.ai/zen/go\";\n/** Go's generateContent base: the Google SDK appends /v1beta/models/<id>:streamGenerateContent. */\nconst OPENCODE_GO_GOOGLE_BASE_URL = \"https://opencode.ai/inference/go/google\";\n\n/** Provider id for the preconfigured Penguin Go relay group. */\nexport const PENGUIN_GO_PROVIDER_ID = \"penguin-go\";\n\n/**\n * The protocol a group is fixed to, or undefined where the group's protocol is the user's to\n * choose. Penguin Go's platform endpoint speaks MMSP alone, so neither its group nor its rows\n * offer a protocol: the Web App shows MMSP without a picker, and the server's model writes and\n * the CLI refuse any other value (fixedClientTypeRefuses).\n */\nexport function fixedClientType(providerId: string): string | undefined {\n return providerId === PENGUIN_GO_PROVIDER_ID ? \"mmsp\" : undefined;\n}\n\n/**\n * Whether writing `next` as the protocol of a group (`target: \"group\"`) or of one of its rows\n * (`\"row\"`) is refused because the group's protocol is fixed (fixedClientType). `next` is the\n * value written, blank or absent for none; `stored` is what that group, or that same row in that\n * same group, stores now.\n *\n * The fixed protocol is always accepted, and so is `stored` written back unchanged: a row a user\n * pointed at their own proxy on another protocol before the protocol was fixed (left alone by\n * migratePenguinGoRoutes) keeps it, and a whole-table save carrying it is not refused. A row\n * with no protocol of its own follows its group, so clearing a row's is accepted; clearing the\n * group's would leave its rows routed by model id, and is refused.\n */\nexport function fixedClientTypeRefuses(\n providerId: string,\n target: \"group\" | \"row\",\n next: string | null | undefined,\n stored: string | undefined,\n): boolean {\n const fixed = fixedClientType(providerId);\n if (fixed === undefined) return false;\n const value = next?.trim() ?? \"\";\n if (value === \"\") return target === \"group\" && (stored?.trim() ?? \"\") !== \"\";\n if (sameClientType(value, fixed)) return false;\n return stored === undefined || !sameClientType(value, stored);\n}\n\n/** Provider id for the ModelScope group. */\nexport const MODELSCOPE_PROVIDER_ID = \"modelscope\";\n\n/**\n * Provider list (web model page groups in this order BY DEFAULT — a user's dragged\n * arrangement is stored per Project and wins over this sequence; see the web's\n * model-group-order.ts). The sequence is a hand-curated display order: TokenDance leads as\n * the recommended group, Penguin Go follows, then OpenCode Go, then DeepSeek as the default\n * model's provider, and custom\n * (custom OpenAI-protocol models) is always last; in between, gateways and first-party\n * vendors are interleaved by expected use rather than sorted by kind. Only this default\n * moves when the curation changes: a Project that has ever reordered its groups has every\n * key stored already, so it keeps the arrangement its user built.\n *\n * The eight gateway groups — OpenRouter, Fireworks AI, SiliconFlow, Atlas Cloud, TokenDance,\n * OpenCode Go, Qwen Pay-As-You-Go and Qwen Token Plan — reach their models through MMSP's generic\n * protocol clients (`openai-responses` for OpenRouter, `openai-chat` for the rest, and all\n * three generic clients within OpenCode Go). Those clients read the vendor variables\n * (**OPENAI_API_KEY / OPENAI_BASE_URL**, and ANTHROPIC_* for OpenCode Go's `ant-messages`\n * rows) when the credential is blank, not the gateway's own variable names, so every gateway\n * group records the OPENAI_* pair as the fact it is. A new Project writes each gateway's base\n * URL on its group, so MMSP refuses a keyless gateway row rather than reading a variable: the\n * variable holds the user's OpenAI (or Anthropic) key, and a gateway is neither. ModelScope\n * also records the OPENAI_* pair; its group credential is an api-inference access token taken\n * from the config alone.\n */\nexport const MODEL_PROVIDERS: ModelProviderInfo[] = [\n {\n id: \"tokendance\",\n label: \"TokenDance\",\n envKey: \"OPENAI_API_KEY\",\n envBaseUrlKey: \"OPENAI_BASE_URL\",\n apiKeyUrl: \"https://tokendance.space/keys\",\n modelsUrl: \"https://tokendance.space/models\",\n gatewayBaseUrl: TOKENDANCE_BASE_URL,\n // Every preset speaks Chat Completions, and the group takes models added by hand\n // (`addable`), which follow the group: a new Project's `[providers.tokendance]` carries\n // this pin, so such a row resolves to it.\n clientType: \"openai-chat\",\n addable: true,\n recommended: true,\n // https://tokendance.space/docs/api-key-oauth\n oauth: {\n authorizeUrl: \"https://tokendance.space/auth\",\n exchangeUrl: \"https://tokendance.space/portal/api/v1/auth/keys\",\n keyName: \"PenguinHarness\",\n },\n // https://tokendance.space/docs/open-api (the account's wallet, in micro-yuan)\n balance: {\n url: \"https://tokendance.space/portal/api/v1/user/balance\",\n format: \"tokendance\",\n },\n },\n {\n id: PENGUIN_GO_PROVIDER_ID,\n label: \"Penguin Go\",\n // The authorization flow writes the relay key once, on the group's `[providers.penguin-go]`\n // table, and that key is the only one the group's rows use: a third-party adapter takes\n // keys from the config alone, and every row names the relay, so none is handed the\n // environment's. The env pair records what the mmsp client reads, as a fact. Every row names the relay and speaks MMSP, so a new\n // Project writes both on the group; the protocol is fixed (fixedClientType).\n envKey: \"MMSP_API_KEY\",\n envBaseUrlKey: \"MMSP_BASE_URL\",\n apiKeyUrl: \"https://go.penguin.ooo/\",\n modelsUrl: \"https://go.penguin.ooo/\",\n bridgeAuth: { flow: \"penguin-go\" },\n balance: {\n url: \"https://go.penguin.ooo/api/me/by-key\",\n format: \"penguin-go\",\n },\n },\n {\n // One key serves the whole group, but its models sit on four protocols (see the group's\n // block comment in MODEL_CATALOG), so no group-level pin: a new Project writes each row's\n // protocol on the row, and the Messages or Google base on the rows that use it. The env pair\n // records what its Chat Completions majority's client reads. Like every gateway's, its rows\n // carry a base URL, so a keyless row is refused: the key goes on the group or the row.\n id: \"opencode-go\",\n label: \"OpenCode Go\",\n envKey: \"OPENAI_API_KEY\",\n envBaseUrlKey: \"OPENAI_BASE_URL\",\n apiKeyUrl: \"https://opencode.ai/v2/docs/console/api/inference/#authentication\",\n modelsUrl: \"https://opencode.ai/v2/docs/console/go/\",\n gatewayBaseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n id: \"deepseek\",\n label: \"DeepSeek\",\n envKey: \"DEEPSEEK_API_KEY\",\n envBaseUrlKey: \"DEEPSEEK_BASE_URL\",\n apiKeyUrl: \"https://platform.deepseek.com/api_keys\",\n modelsUrl: \"https://api-docs.deepseek.com/quick_start/pricing\",\n // https://api-docs.deepseek.com/api/get-user-balance\n balance: { url: `${DEEPSEEK_BASE_URL}/user/balance`, format: \"deepseek\" },\n },\n {\n id: \"openrouter\",\n label: \"OpenRouter\",\n envKey: \"OPENAI_API_KEY\",\n envBaseUrlKey: \"OPENAI_BASE_URL\",\n apiKeyUrl: \"https://openrouter.ai/workspaces/default/keys\",\n modelsUrl: \"https://openrouter.ai/models\",\n gatewayBaseUrl: OPENROUTER_BASE_URL,\n // The whole group speaks the Responses API, which OpenRouter serves at the preset base\n // URL below for every upstream — presets and user-added entries alike.\n clientType: \"openai-responses\",\n // The catalog lists a fraction of what OpenRouter serves, so the group takes more.\n addable: true,\n },\n {\n id: \"fireworks\",\n label: \"Fireworks AI\",\n envKey: \"OPENAI_API_KEY\",\n envBaseUrlKey: \"OPENAI_BASE_URL\",\n apiKeyUrl: \"https://app.fireworks.ai/settings/users/api-keys\",\n modelsUrl: \"https://app.fireworks.ai/models\",\n gatewayBaseUrl: FIREWORKS_BASE_URL,\n },\n {\n id: \"google\",\n label: \"Google Gemini\",\n envKey: \"GEMINI_API_KEY\",\n envBaseUrlKey: \"GEMINI_BASE_URL\",\n apiKeyUrl: \"https://aistudio.google.com/api-keys\",\n modelsUrl: \"https://ai.google.dev/gemini-api/docs/models\",\n },\n {\n id: \"openai\",\n label: \"OpenAI\",\n envKey: \"OPENAI_API_KEY\",\n envBaseUrlKey: \"OPENAI_BASE_URL\",\n apiKeyUrl: \"https://platform.openai.com/api-keys\",\n modelsUrl: \"https://platform.openai.com/docs/models\",\n },\n {\n id: \"anthropic\",\n label: \"Anthropic\",\n envKey: \"ANTHROPIC_API_KEY\",\n envBaseUrlKey: \"ANTHROPIC_BASE_URL\",\n apiKeyUrl: \"https://platform.claude.com/settings/keys\",\n modelsUrl: \"https://docs.claude.com/en/docs/about-claude/models/overview\",\n },\n {\n id: \"siliconflow\",\n label: \"SiliconFlow\",\n envKey: \"OPENAI_API_KEY\",\n envBaseUrlKey: \"OPENAI_BASE_URL\",\n apiKeyUrl: \"https://cloud.siliconflow.cn/me/account/ak\",\n modelsUrl: \"https://cloud.siliconflow.cn/models\",\n gatewayBaseUrl: SILICONFLOW_BASE_URL,\n // As TokenDance: Chat Completions throughout, and models added by hand follow the group.\n clientType: \"openai-chat\",\n addable: true,\n },\n {\n id: \"atlascloud\",\n label: \"Atlas Cloud\",\n envKey: \"OPENAI_API_KEY\",\n envBaseUrlKey: \"OPENAI_BASE_URL\",\n apiKeyUrl: \"https://atlascloud.ai/docs/api-keys\",\n modelsUrl: \"https://atlascloud.ai/models\",\n gatewayBaseUrl: ATLASCLOUD_BASE_URL,\n // As SiliconFlow: Chat Completions throughout, and the catalog lists a fraction of what\n // the gateway serves, so the group takes models added by hand, which follow the group.\n clientType: \"openai-chat\",\n addable: true,\n },\n {\n id: \"zhipu\",\n label: \"Z.AI (GLM)\",\n envKey: \"ZAI_API_KEY\",\n envBaseUrlKey: \"ZAI_BASE_URL\",\n apiKeyUrl: \"https://open.bigmodel.cn/apikey/platform\",\n modelsUrl: \"https://docs.z.ai/guides/overview/pricing\",\n },\n {\n id: \"moonshot\",\n label: \"Moonshot (Kimi)\",\n envKey: \"MOONSHOT_API_KEY\",\n envBaseUrlKey: \"MOONSHOT_BASE_URL\",\n apiKeyUrl: \"https://platform.kimi.com/console/api-keys\",\n modelsUrl: \"https://platform.kimi.com/docs/pricing\",\n },\n {\n id: \"minimax\",\n label: \"MiniMax\",\n envKey: \"MINIMAX_API_KEY\",\n envBaseUrlKey: \"MINIMAX_BASE_URL\",\n // The pay-as-you-go key page; a Token Plan Subscription Key (Billing > Token Plan) works\n // against the same endpoint, so the group is not tied to either billing mode.\n apiKeyUrl: \"https://platform.minimax.io/user-center/basic-information/interface-key\",\n modelsUrl: \"https://platform.minimax.io/docs/guides/models-intro\",\n },\n {\n id: \"qwen-pay-as-you-go\",\n label: \"Qwen Pay-As-You-Go\",\n envKey: \"OPENAI_API_KEY\",\n envBaseUrlKey: \"OPENAI_BASE_URL\",\n apiKeyUrl: \"https://platform.qianwenai.com/docs/api-reference/preparation/api-key\",\n modelsUrl: \"https://www.qianwenai.com/models\",\n gatewayBaseUrl: QWEN_PAYG_BASE_URL,\n },\n {\n id: \"qwen-token-plan\",\n label: \"Qwen Token Plan\",\n envKey: \"OPENAI_API_KEY\",\n envBaseUrlKey: \"OPENAI_BASE_URL\",\n apiKeyUrl: \"https://platform.qianwenai.com/pricing/token-plan\",\n modelsUrl:\n \"https://platform.qianwenai.com/docs/token-plan/personal/token-plan-personal-overview\",\n gatewayBaseUrl: QWEN_TOKEN_PLAN_BASE_URL,\n },\n {\n // ModelScope's own inference service: OpenAI-compatible, reselling other vendors' models\n // under `org/Model-Name` ids. Two things set it apart from the gateways above.\n //\n // Its credential is the account's access token rather than a minted API key, and the\n // group obtains one through the authorization bridge instead of sending the user to copy\n // it out of the console (bridgeAuth below; the console link stays for anyone who already\n // has a token). ModelScope is the vendor here as well as the gateway — the bridge exists\n // because its OAuth requires a client secret the desktop App cannot keep locally, not\n // because inference requests are routed through that bridge.\n //\n // Every preset row names the endpoint and one protocol in the catalog, so a new Project\n // writes both on the group's `[providers.modelscope]` table and the rows follow it.\n id: MODELSCOPE_PROVIDER_ID,\n label: \"ModelScope\",\n envKey: \"OPENAI_API_KEY\",\n envBaseUrlKey: \"OPENAI_BASE_URL\",\n apiKeyUrl: \"https://www.modelscope.cn/my/myaccesstoken\",\n modelsUrl: \"https://www.modelscope.cn/models\",\n gatewayBaseUrl: MODELSCOPE_BASE_URL,\n bridgeAuth: { flow: \"modelscope\" },\n },\n {\n // Self-hosted: the user runs the server, so there is no console to mint a key at\n // (apiKeyUrl) and no endpoint every user shares (gatewayBaseUrl). The group's rows name the\n // address a server started on this machine answers on, which a new Project stores as the\n // group's base URL. modelsUrl points at the recipe index, which is where the served ids in\n // this group are documented.\n id: \"vllm\",\n label: \"vLLM\",\n // vLLM's own pair, which MMSP's vLLM client reads, and never OpenAI's.\n envKey: \"VLLM_API_KEY\",\n envBaseUrlKey: \"VLLM_BASE_URL\",\n modelsUrl: \"https://recipes.vllm.ai/\",\n clientType: VLLM_CLIENT_TYPE,\n // The served ids are the user's own, so this group keeps taking models added by hand.\n addable: true,\n },\n {\n id: \"custom\",\n label: \"Custom\",\n envKey: \"OPENAI_API_KEY\",\n envBaseUrlKey: \"OPENAI_BASE_URL\",\n addable: true,\n },\n];\n\n/** Three-bucket price literal (unit fixed to usd_per_mtok). */\n/**\n * Converts official CNY pricing to USD for storage (prices are always persisted in USD). The\n * conversion rate matches the web display's 7:1 convention, so switching the UI to CNY shows\n * exactly the vendor's official CNY price.\n */\nfunction cny(cacheRead: number, cacheWrite: number, output: number): ModelPricing {\n const r = (v: number): number => Math.round((v / 7) * 1e6) / 1e6;\n return usd(r(cacheRead), r(cacheWrite), r(output));\n}\n\nfunction usd(cacheRead: number, cacheWrite: number, output: number): ModelPricing {\n return { unit: \"usd_per_mtok\", cache_read: cacheRead, cache_write: cacheWrite, output };\n}\n\n/**\n * A weekly peak/off-peak billing schedule, written in a fixed-offset zone.\n *\n * Only fixed offsets are expressible, which is the whole of what the catalog needs: the vendors\n * that bill this way publish their windows in a single national zone that does not observe DST\n * (Beijing is UTC+8 year round). A vendor on a DST zone would need a real tz database, and the\n * honest move then is to add one rather than to approximate.\n */\nexport interface OffPeakDiscount {\n /** Fraction off the peak price outside the windows below (0.5 = half price). */\n rate: number;\n /** Minutes east of UTC the windows are written in (Beijing = 480). */\n utcOffsetMinutes: number;\n /** Days the windows apply to, ISO numbering: 1 = Monday … 7 = Sunday. Days not listed are off-peak all day. */\n peakDays: readonly number[];\n /** Peak windows as [startHour, endHour) in the zone's local hours — end-exclusive, so 12:00 is already off-peak. */\n peakHours: readonly (readonly [number, number])[];\n}\n\n/**\n * Whether `now` falls outside every peak window, i.e. whether the discount is live.\n *\n * Computed in UTC arithmetic rather than through the host's local time: the schedule belongs to\n * the vendor's zone, and a server in Los Angeles must reach the same answer as one in Shanghai.\n */\nexport function offPeakAt(schedule: OffPeakDiscount, now: Date): boolean {\n const local = new Date(now.getTime() + schedule.utcOffsetMinutes * 60_000);\n // getUTCDay is 0 = Sunday; the ISO numbering the schedule uses puts Sunday at 7.\n const isoDay = local.getUTCDay() === 0 ? 7 : local.getUTCDay();\n if (!schedule.peakDays.includes(isoDay)) return true;\n const hour = local.getUTCHours() + local.getUTCMinutes() / 60;\n return !schedule.peakHours.some(([from, to]) => hour >= from && hour < to);\n}\n\n/** DeepSeek's official off-peak tier: half price outside Beijing weekday 09:00–12:00 and 14:00–18:00. */\nexport const DEEPSEEK_OFF_PEAK: OffPeakDiscount = {\n rate: 0.5,\n utcOffsetMinutes: 480,\n peakDays: [1, 2, 3, 4, 5],\n peakHours: [\n [9, 12],\n [14, 18],\n ],\n};\n\n/**\n * Qwen's off-peak tier on the time-banded models it sells (www.qianwenai.com/models/<id>, read\n * 2026-09-16): half price from 22:00 to 08:00 Beijing time, every day of the week, and the peak\n * price at every other hour. Each model page shows the two tiers as separate price tabs, and\n * every bucket's off-peak figure is exactly half its peak one.\n */\nexport const QWEN_OFF_PEAK: OffPeakDiscount = {\n rate: 0.5,\n utcOffsetMinutes: 480,\n peakDays: [1, 2, 3, 4, 5, 6, 7],\n peakHours: [[8, 22]],\n};\n\n/**\n * The catalog's time-based schedules, each with the references that carry it.\n *\n * The cost center needs this to split an aggregation by tier before it prices anything: the\n * rate a request ran at is a fact about when it ran, and only the catalog knows which rows have\n * two rates at all. Grouped by schedule so a second vendor's windows cost one entry, not a\n * second query.\n */\nexport function offPeakScheduledRefs(): Array<{\n schedule: OffPeakDiscount;\n refs: Array<{ provider: string; modelId: string }>;\n}> {\n const bySchedule = new Map<\n OffPeakDiscount,\n { schedule: OffPeakDiscount; refs: Array<{ provider: string; modelId: string }> }\n >();\n for (const entry of MODEL_CATALOG) {\n const schedule = entry.offPeakDiscount;\n if (schedule === undefined) continue;\n const group = bySchedule.get(schedule) ?? { schedule, refs: [] };\n group.refs.push({ provider: entry.provider, modelId: entry.modelId });\n bySchedule.set(schedule, group);\n }\n return [...bySchedule.values()];\n}\n\n/**\n * What the seller actually bills for an entry at `now`: its list `pricing` less any running\n * `discount` and any live off-peak tier, the two multiplied, on every bucket. Rounded to the six\n * decimals cny() already stores at, so a promotional rate reads as a price rather than as a\n * float artifact. An entry with nothing off (or no pricing at all) is returned untouched.\n *\n * Nothing writes this rate into a Project: `presetModelEntries` writes the list price (a\n * scheduled row's peak price), a flat promotion is stored beside it as a fraction, and which\n * tier a request ran in is decided from that request's own timestamp when the usage is\n * aggregated.\n */\nexport function effectivePricing(\n entry: ModelCatalogEntry,\n now: Date = new Date(),\n): ModelPricing | undefined {\n const { pricing } = entry;\n if (pricing === undefined) return pricing;\n // A scheduled discount bills the list price during its peak windows and the reduced rate\n // outside them; a flat one always bills the reduced rate. A row with both takes the flat one\n // off whichever tier is live.\n const tier =\n entry.offPeakDiscount !== undefined && offPeakAt(entry.offPeakDiscount, now)\n ? entry.offPeakDiscount.rate\n : 0;\n const kept = (1 - tier) * (1 - (entry.discount ?? 0));\n if (kept === 1) return pricing;\n const off = (v: number): number => Math.round(v * kept * 1e6) / 1e6;\n return {\n unit: pricing.unit,\n cache_read: off(pricing.cache_read),\n cache_write: off(pricing.cache_write),\n output: off(pricing.output),\n };\n}\n\n/**\n * Built-in model catalog, clustered by provider. Within each provider, entries are in\n * dictionary order by model id, except that newer versions of the same series come first\n * (e.g. gpt-5.6-* before gpt-5.5, claude-opus-4.8 before 4.7, glm-5.2 before glm-5). The\n * order is precomputed by hand right here — no runtime sorting anywhere.\n *\n * The clusters run in their own sequence, which is the row order a new Project's\n * `[[models]]` table is written in. It is not MODEL_PROVIDERS' display order and does not\n * have to track it: nothing renders a catalog row outside its provider group, and the page\n * takes the group sequence from MODEL_PROVIDERS.\n */\nexport const MODEL_CATALOG: ModelCatalogEntry[] = [\n // -- DeepSeek (official CNY pricing: cache hit / cache miss / output). Prices and model\n // names re-read 2026-09-16 from api-docs.deepseek.com/zh-cn/quick_start/pricing, which now\n // lists exactly two names, both with a 1M context window and a 384K output cap:\n // `deepseek-flash` (DeepSeek-V4.1-Flash, image input) on the peak tier CNY 0.04 / 2 / 8, and\n // `deepseek-v4-pro` (DeepSeek-V4-Pro-0813, text only) at 0.30 / 9 / 27. The rows store the\n // PEAK tier and declare DEEPSEEK_OFF_PEAK, which halves every bucket outside Beijing weekday\n // 09:00-12:00 and 14:00-18:00 — so both tiers are billed at the rate actually in force,\n // rather than one of them being approximated by the other.\n // The retired V4 Flash names, `deepseek-v4-flash` and `deepseek-v4-flash-vision-exp`, are\n // still accepted and served by V4.1 Flash at the Flash price and on the same schedule, but\n // the page no longer lists them: they stay below as retired rows, which are not presets. --\n {\n // DeepSeek's pricing page names this model `deepseek-flash` (model version\n // DeepSeek-V4.1-Flash, released as of the 2026-09-10 read): 1M context, image input, and\n // the Flash series peak price and off-peak schedule.\n modelId: \"deepseek-flash\",\n displayName: \"DeepSeek V4.1 Flash\",\n provider: \"deepseek\",\n contextWindow: 1000000,\n pricing: cny(0.04, 2, 8),\n offPeakDiscount: DEEPSEEK_OFF_PEAK,\n supportsVision: true,\n wasDefault: true,\n },\n {\n // Retired 2026-09-16 (see ModelCatalogEntry.retired): the default model of new Projects\n // from 0.2.0 to 0.2.8. DeepSeek still accepts the id and serves it from V4.1 Flash at the\n // Flash price, off-peak schedule included. Text only: MMSP's DeepSeek client refuses\n // image parts for this id.\n modelId: \"deepseek-v4-flash\",\n displayName: \"DeepSeek V4 Flash\",\n provider: \"deepseek\",\n contextWindow: 1000000,\n pricing: cny(0.04, 2, 8),\n offPeakDiscount: DEEPSEEK_OFF_PEAK,\n supportsVision: false,\n retired: true,\n wasDefault: true,\n },\n {\n // Retired 2026-09-16 (see ModelCatalogEntry.retired): the default model of new Projects in\n // 0.2.9, served from V4.1 Flash at the Flash price like deepseek-v4-flash above.\n modelId: \"deepseek-v4-flash-vision-exp\",\n displayName: \"DeepSeek V4 Flash Vision Exp\",\n provider: \"deepseek\",\n contextWindow: 1000000,\n pricing: cny(0.04, 2, 8),\n offPeakDiscount: DEEPSEEK_OFF_PEAK,\n supportsVision: true,\n retired: true,\n wasDefault: true,\n },\n {\n // DeepSeek's pricing page names the model behind this id DeepSeek-V4-Pro-0813 (read\n // 2026-09-16), which is what the display name says — the same 0813 release the gateway\n // groups sell under dated ids. Text only. DeepSeek states that V4 Pro stays available\n // after 2026-09-14 with its billing unchanged, so the row keeps the V4 Pro peak price on\n // the shared off-peak schedule. MMSP's DeepSeek client also matches this bare id against\n // its text-only deny-list /^deepseek-v4-(flash|pro)(-\\d{4})?$/, so image parts never\n // leave the harness for it.\n modelId: \"deepseek-v4-pro\",\n displayName: \"DeepSeek V4 Pro 0813\",\n provider: \"deepseek\",\n contextWindow: 1000000,\n pricing: cny(0.3, 9, 27),\n offPeakDiscount: DEEPSEEK_OFF_PEAK,\n supportsVision: false,\n wasDefault: true,\n },\n // -- OpenRouter (gateway: OpenAI-compatible protocol, preset base URL). Prices re-read in\n // one pass on 2026-08-07 from the models API (/api/v1/models; the API is authoritative\n // where a model's web page disagrees); the DeepSeek rows, the rows added on 2026-08-18\n // (grok-4.6, deepseek-v4-pro-0813, glm-5.3, the openai/* additions) and every\n // pre-existing openai/* and google/* row were re-read on 2026-08-18 from the model\n // pages and the per-model endpoints API. The rows added on 2026-10-10 — the four Claude 5.x\n // rows, openai/gpt-6.1-sol, stepfun/step-5-preview, x-ai/grok-4.7,\n // xiaomi/mimo-v2.6-flash and xiaomi/mimo-v2.6-pro — were read that day from the models API and the per-model\n // endpoints API, whose default endpoint runs no promotion (`discount: 0`) on any of them;\n // their context windows are the listing's `top_provider.context_length`, as on the\n // mimo-v2.5 and step-3.7-flash rows.\n //\n // Protocol: every row pins `openai-responses`. OpenRouter serves the Responses API at\n // {base}/responses for every upstream, at the same https://openrouter.ai/api/v1 base URL\n // the rows already carry, and the group pins the same protocol, which a new Project writes on\n // `[providers.openrouter]`, so an entry added to it by hand follows it. The generic Responses client sends a text-only tool result as a plain\n // string and replays reasoning items only where the upstream returned them.\n //\n // Price buckets: cache_read stores the published input_cache_read\n // (falling back to the input price for the rows without one — the :free rows and the\n // GPT Pro tiers, which publish no cache discount); cache_write stores\n // input_cache_write only when it is a genuine per-token write premium (the Anthropic, GPT\n // and qwen3.8-max rows, 1.25x input) —\n // Gemini's field is an hourly cache-STORAGE rate, not a per-token price, so those rows\n // keep the input price — and otherwise also carries the input price. The :free tier and\n // the openrouter/free Free Models Router store a genuine $0 price (not \"unknown\"), so\n // costs correctly compute to 0. GPT models are uniformly vision-capable (OpenAI\n // product-line policy) even where the gateway page omits the modality.\n //\n // Discounts: what these rows record is what OpenRouter actually BILLS, so a gateway\n // promotion is stored at its discounted rate (unlike the direct-vendor rows, which keep the\n // list price). The Gemini 3.x Flash rows are the exception: the promotion they sit on is\n // Google's own dated launch discount rather than the gateway's, so they keep the list price\n // and declare it in `discount`, exactly as their direct-vendor twins do. The endpoints API\n // exposes the running promotion as `pricing.discount` on the default endpoint; rows sitting\n // on one say so and name the rate to restore, because a lapsed promotion silently doubles\n // the real cost — that is exactly how the gpt-5.6-terra and gpt-5.6-luna rows drifted 2x\n // low before the 2026-08-18 re-read. --\n {\n // $10 input / $12.50 cache write / $0.25 cache read / $50 output, the cache read at 2.5% of\n // input as on Anthropic's own list; 1M window, image input.\n modelId: \"anthropic/claude-fable-5.1\",\n displayName: \"Claude Fable 5.1\",\n provider: \"openrouter\",\n contextWindow: 1000000,\n pricing: usd(0.25, 12.5, 50),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"anthropic/claude-fable-5\",\n displayName: \"Claude Fable 5\",\n provider: \"openrouter\",\n contextWindow: 1000000,\n pricing: usd(1, 12.5, 50),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // $0.10 input / $0.125 cache write / $0.01 cache read / $0.50 output for prompts up to\n // 100,000 tokens; the listing's `overrides` bill every rate 5x from 100,000 prompt tokens,\n // Anthropic's own tiering. The base tier is recorded, as for the other tiered rows.\n modelId: \"anthropic/claude-haiku-5.5\",\n displayName: \"Claude Haiku 5.5\",\n provider: \"openrouter\",\n contextWindow: 1000000,\n pricing: usd(0.01, 0.125, 0.5),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // $4 input / $5 cache write / $0.20 cache read / $20 output.\n modelId: \"anthropic/claude-opus-5.5\",\n displayName: \"Claude Opus 5.5\",\n provider: \"openrouter\",\n contextWindow: 1000000,\n pricing: usd(0.2, 5, 20),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"anthropic/claude-opus-5\",\n displayName: \"Claude Opus 5\",\n provider: \"openrouter\",\n contextWindow: 1000000,\n pricing: usd(0.5, 6.25, 25),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"anthropic/claude-opus-4.8\",\n displayName: \"Claude Opus 4.8\",\n provider: \"openrouter\",\n contextWindow: 1000000,\n pricing: usd(0.5, 6.25, 25),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"anthropic/claude-opus-4.7\",\n displayName: \"Claude Opus 4.7\",\n provider: \"openrouter\",\n contextWindow: 1000000,\n pricing: usd(0.5, 6.25, 25),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // $2 input / $2.50 cache write / $0.10 cache read / $10 output. The cache read is half\n // Sonnet 5's $0.20: Anthropic prices it at 5% of input on this generation (MMSP 0.5.2\n // moved its registry row from $0.20), and OpenRouter bills the same.\n modelId: \"anthropic/claude-sonnet-5.5\",\n displayName: \"Claude Sonnet 5.5\",\n provider: \"openrouter\",\n contextWindow: 1000000,\n pricing: usd(0.1, 2.5, 10),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"anthropic/claude-sonnet-5\",\n displayName: \"Claude Sonnet 5\",\n provider: \"openrouter\",\n contextWindow: 1000000,\n pricing: usd(0.2, 2.5, 10),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // Listed 2026-09-10 from the models API: the base price is the PEAK tier and\n // `pricing.overrides` bill exactly half on weekends and outside weekday UTC 01:00-04:00 /\n // 06:00-10:00 — DeepSeek's own Beijing windows — so the row stores the peak price and\n // declares DEEPSEEK_OFF_PEAK, exactly as the direct row does. Context window and image\n // input from the same listing.\n modelId: \"deepseek/deepseek-v4.1-flash\",\n displayName: \"DeepSeek V4.1 Flash\",\n provider: \"openrouter\",\n contextWindow: 1048576,\n pricing: usd(0.006, 0.3, 1.2),\n offPeakDiscount: DEEPSEEK_OFF_PEAK,\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // The 1017 snapshot, served by DeepSeek's own endpoint (MMSP 0.5.5's registry, models API\n // read 2026-10-19): $0.15 / $0.60 / $0.003 off-peak, double in DeepSeek's weekday windows,\n // so the row stores that peak and declares DEEPSEEK_OFF_PEAK like the row above.\n modelId: \"deepseek/deepseek-v4.1-flash-1017\",\n displayName: \"DeepSeek V4.1 Flash 1017\",\n provider: \"openrouter\",\n contextWindow: 1048576,\n pricing: usd(0.006, 0.3, 1.2),\n offPeakDiscount: DEEPSEEK_OFF_PEAK,\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"deepseek/deepseek-v4-flash-0731\",\n displayName: \"DeepSeek V4 Flash 0731\",\n provider: \"openrouter\",\n contextWindow: 1000000,\n pricing: usd(0.0157192, 0.078596, 0.157192),\n supportsVision: false,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"deepseek/deepseek-v4-flash\",\n displayName: \"DeepSeek V4 Flash\",\n provider: \"openrouter\",\n contextWindow: 1000000,\n pricing: usd(0.0168, 0.0679, 0.168),\n supportsVision: false,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // DeepSeek serves this one alone on OpenRouter, so the stored rates are its own published\n // USD list ($0.22 / $0.66 / $0.007 cache read), and the context window is that endpoint's\n // 1,048,576. The row keeps that flat price as the API lists it: as of the 2026-09-10 read\n // the listing carries no `pricing.overrides`, so unlike the deepseek-v4.1-flash row above\n // there is no peak/off-peak split to record here.\n modelId: \"deepseek/deepseek-v4-flash-vision-exp\",\n displayName: \"DeepSeek V4 Flash Vision Exp\",\n provider: \"openrouter\",\n contextWindow: 1048576,\n pricing: usd(0.007, 0.22, 0.66),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // The 0813 general-availability release of DeepSeek V4 Pro (OpenRouter listing dated\n // 2026-08-12); the default routed endpoint is DeepSeek's own API, so the price matches\n // the official USD list, and the context window is the default endpoint's 1,048,576.\n modelId: \"deepseek/deepseek-v4-pro-0813\",\n displayName: \"DeepSeek V4 Pro 0813\",\n provider: \"openrouter\",\n contextWindow: 1048576,\n pricing: usd(0.022, 0.66, 1.98),\n supportsVision: false,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"deepseek/deepseek-v4-pro\",\n displayName: \"DeepSeek V4 Pro\",\n provider: \"openrouter\",\n contextWindow: 1000000,\n pricing: usd(0.022, 0.66, 1.98),\n supportsVision: false,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // Standard tier from openrouter.ai/google/gemini-4-argon (2026-10-14): Google's\n // $4 input / $20 output / $0.20 cache hit, 50% off through 2026-11-30. Argon supports\n // implicit caching only, so cache_write records input rather than cache storage.\n modelId: \"google/gemini-4-argon\",\n displayName: \"Gemini 4 Argon\",\n provider: \"openrouter\",\n contextWindow: 1048576,\n pricing: usd(0.2, 4, 20),\n discount: 0.5,\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // Same Gemini cache conventions as the gemini-3.6-flash row below. OpenRouter passes\n // Google's launch discount through, so it bills $0.075/$0.75/$3.75 — the list price less\n // 50%, declared in `discount` so the $0.15/$1.50/$7.50 list survives the promotion (same\n // treatment as the 3.6 row below). Gemini 3.7 Flash is no longer listed beside it: Google\n // retires that id and reroutes it to 3.8 Flash.\n modelId: \"google/gemini-3.8-flash\",\n displayName: \"Gemini 3.8 Flash\",\n provider: \"openrouter\",\n contextWindow: 1048576,\n pricing: usd(0.15, 1.5, 7.5),\n discount: 0.5,\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // cache_read is billed as its own bucket in the cost center, and an input-priced\n // cache_read would overstate cache-heavy Gemini spend 10x; cache_write repeats the input\n // price (see the block comment — Gemini publishes storage-per-hour, not per-token write),\n // matching the direct-vendor Gemini rows below. OpenRouter bills $0.075/$0.75/$3.75\n // today (endpoints API, read 2026-09-09): it reports that halved rate as its plain price\n // with `discount: 0`, but it is Google's launch discount passed through and ends with it\n // on 2026-12-31, so this row records the list price and the promotion the way its\n // siblings do.\n modelId: \"google/gemini-3.6-flash\",\n displayName: \"Gemini 3.6 Flash\",\n provider: \"openrouter\",\n contextWindow: 1048576,\n pricing: usd(0.15, 1.5, 7.5),\n discount: 0.5,\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // The 3.5 tier's own list price — $1.50 input / $9.00 output / $0.15 cache hit on Google's\n // page, with no launch discount — and OpenRouter's default endpoint bills exactly that\n // (`discount: 0`, read 2026-09-09). The $9 output is the tier, not a promotion to declare.\n modelId: \"google/gemini-3.5-flash\",\n displayName: \"Gemini 3.5 Flash\",\n provider: \"openrouter\",\n contextWindow: 1048576,\n pricing: usd(0.15, 1.5, 9),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // Same published-cache-price convention as gemini-3.6-flash above (2026-07-22: $0.03/mtok\n // cache hit, $0.30 input, $2.50 output; re-read 2026-09-09, unchanged and `discount: 0`).\n modelId: \"google/gemini-3.5-flash-lite\",\n displayName: \"Gemini 3.5 Flash-Lite\",\n provider: \"openrouter\",\n contextWindow: 1048576,\n pricing: usd(0.03, 0.3, 2.5),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // The paid listing, which replaced the free variant when its free period ended (models API\n // read 2026-10-23): $0.15 input / $0.60 output / $0.015 cache read, 1,048,576 tokens, image\n // input, MiniMax's own list price.\n modelId: \"minimax/minimax-m3.1-flash\",\n displayName: \"MiniMax M3.1 Flash\",\n provider: \"openrouter\",\n contextWindow: 1048576,\n pricing: usd(0.015, 0.15, 0.6),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // No official separate cache price published: cache_read uses the standard input price (no discount assumed).\n modelId: \"minimax/minimax-m3\",\n displayName: \"MiniMax M3\",\n provider: \"openrouter\",\n contextWindow: 1048576,\n pricing: usd(0.06, 0.3, 1.2),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // Read 2026-10-24 from the models API and the per-model endpoints API: $2 input / $10\n // output / $0.20 cache read over 1,048,576 tokens, image input, served by Moonshot AI alone\n // and with no promotion on the default endpoint (`discount: 0`). The listing's\n // `moonshotai/highspeed` endpoint ($4 / $20 / $0.20) is a provider route under this same id,\n // not a model of its own.\n modelId: \"moonshotai/kimi-k3.1-pro\",\n displayName: \"Kimi K3.1 Pro\",\n provider: \"openrouter\",\n contextWindow: 1048576,\n pricing: usd(0.2, 2, 10),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"moonshotai/kimi-k3\",\n displayName: \"Kimi K3\",\n provider: \"openrouter\",\n contextWindow: 1000000,\n pricing: usd(0.3, 3, 15),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"moonshotai/kimi-k2.6\",\n displayName: \"Kimi K2.6\",\n provider: \"openrouter\",\n contextWindow: 262144,\n pricing: usd(0.0992, 0.589, 2.48),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"nvidia/nemotron-3-ultra-550b-a55b:free\",\n displayName: \"Nemotron 3 Ultra (free)\",\n provider: \"openrouter\",\n contextWindow: 1000000,\n pricing: usd(0, 0, 0),\n supportsVision: false,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n // The openai/* rows below mirror the direct OpenAI group one-for-one. Their context\n // windows are OpenRouter's published 1,050,000 / 400,000, matching the direct rows.\n {\n // Read 2026-10-10: the default endpoint is OpenAI's own, at $2 input / $0.10 cached input\n // / $2.50 cache write / $10 output with `discount: 0`, OpenAI's list. The listing's\n // `overrides` from 272,000 prompt tokens (2x prompt and cache, 1.5x completion) are the\n // long-context tier, which is not recorded, as on the direct row.\n modelId: \"openai/gpt-6.1-sol\",\n displayName: \"GPT-6.1 Sol\",\n provider: \"openrouter\",\n contextWindow: 1050000,\n pricing: usd(0.1, 2.5, 10),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // Read 2026-09-09 from the models API and the per-model endpoints API: the default\n // endpoint is OpenAI's own, listed at $10 input / $1 cached input / $12.5 cache write /\n // $50 output with `discount: 0`, so the list price is what OpenRouter bills. The\n // endpoints API also publishes `overrides` above 272,000 prompt tokens (2x prompt and\n // cache, 1.5x completion); as on the direct row, only the base tier is recorded.\n modelId: \"openai/gpt-6-astra\",\n displayName: \"GPT-6 Astra\",\n provider: \"openrouter\",\n contextWindow: 1050000,\n pricing: usd(1, 12.5, 50),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // https://developers.openai.com/api/docs/models/gpt-6-luna (2026-10-14).\n // Base tier: above 272K input, input/cache rates double and output is 1.5x.\n modelId: \"openai/gpt-6-luna\",\n displayName: \"GPT-6 Luna\",\n provider: \"openrouter\",\n contextWindow: 1050000,\n pricing: usd(0.01, 0.125, 0.5),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // The 50% promotion this row used to store has ended: OpenRouter now bills the full\n // $0.20/$1.20 rate (endpoints API `discount: 0`), so the stored rates doubled on the\n // 2026-08-18 re-read.\n modelId: \"openai/gpt-5.6-luna\",\n displayName: \"GPT-5.6 Luna\",\n provider: \"openrouter\",\n contextWindow: 1050000,\n pricing: usd(0.02, 0.25, 1.2),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // Running a `discount: 0.5` promotion as of 2026-08-18, so OpenRouter bills half the\n // $0.50/$6.25/$30 list price — restore the list rates when the promotion ends.\n modelId: \"openai/gpt-5.6-sol\",\n displayName: \"GPT-5.6 Sol\",\n provider: \"openrouter\",\n contextWindow: 1050000,\n pricing: usd(0.25, 3.125, 15),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // Same lapsed promotion as the luna row: now billed at the full $2/$12 rate.\n modelId: \"openai/gpt-5.6-terra\",\n displayName: \"GPT-5.6 Terra\",\n provider: \"openrouter\",\n contextWindow: 1050000,\n pricing: usd(0.2, 2.5, 12),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"openai/gpt-5.5\",\n displayName: \"GPT-5.5\",\n provider: \"openrouter\",\n contextWindow: 1050000,\n pricing: usd(0.5, 5, 30),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // No published cache discount (the Pro tiers bill cached input at the standard rate), so\n // cache_read carries the input price — same convention as the direct gpt-5.5-pro row.\n modelId: \"openai/gpt-5.5-pro\",\n displayName: \"GPT-5.5 Pro\",\n provider: \"openrouter\",\n contextWindow: 1050000,\n pricing: usd(30, 30, 180),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"openai/gpt-5.4\",\n displayName: \"GPT-5.4\",\n provider: \"openrouter\",\n contextWindow: 1050000,\n pricing: usd(0.25, 2.5, 15),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"openai/gpt-5.4-mini\",\n displayName: \"GPT-5.4 mini\",\n provider: \"openrouter\",\n contextWindow: 400000,\n pricing: usd(0.075, 0.75, 4.5),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"openai/gpt-5.4-nano\",\n displayName: \"GPT-5.4 nano\",\n provider: \"openrouter\",\n contextWindow: 400000,\n pricing: usd(0.02, 0.2, 1.25),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // No published cache discount, as with gpt-5.5-pro above.\n modelId: \"openai/gpt-5.4-pro\",\n displayName: \"GPT-5.4 Pro\",\n provider: \"openrouter\",\n contextWindow: 1050000,\n pricing: usd(30, 30, 180),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // OpenRouter's unified Free Models Router: each request is routed to a random free model\n // currently on OpenRouter, filtered by the features the request needs (tool calling,\n // structured outputs, ...). Routed targets vary, so the context window is a deliberately\n // conservative figure rather than any single target's real window: it keeps the 75%\n // compaction clamp meaningful (compaction fires at 96000) and reduces hard context-length\n // 400s on small-window targets. supportsVision stays false deliberately: the harness must\n // not send images to a router whose target may be text-only.\n modelId: \"openrouter/free\",\n displayName: \"Free Models Router\",\n provider: \"openrouter\",\n contextWindow: 128000,\n pricing: usd(0, 0, 0),\n supportsVision: false,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // Read 2026-09-16 from the models API: $0.214 input / $2.55 output with a published $0.15\n // input_cache_read, a 1,000,000-token context window, and text, image and video input.\n modelId: \"qwen/qwen3.8-27b\",\n displayName: \"Qwen 3.8 27B\",\n provider: \"openrouter\",\n contextWindow: 1000000,\n pricing: usd(0.15, 0.214, 2.55),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"qwen/qwen3.8-max\",\n displayName: \"Qwen 3.8 Max\",\n provider: \"openrouter\",\n contextWindow: 1000000,\n pricing: usd(0.25, 2.5, 6),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"qwen/qwen3.6-35b-a3b\",\n displayName: \"Qwen 3.6 35B A3B\",\n provider: \"openrouter\",\n contextWindow: 262144,\n pricing: usd(0.05, 0.14, 1),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // Recursive's Flint, listed 2026-10-21 (models API read 2026-10-23): free, 262,144 tokens,\n // up to 235,929 output tokens, text input only, with reasoning and tool calls.\n modelId: \"recursive/flint-v1.0:free\",\n displayName: \"Flint (free)\",\n provider: \"openrouter\",\n contextWindow: 262144,\n pricing: usd(0, 0, 0),\n supportsVision: false,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // StepFun's own endpoint is the only one: $1 input / $2.70 output with a published $0.05\n // input_cache_read and no write premium, so cache_write carries the input price. 1,000,000\n // window; text, image and video input.\n modelId: \"stepfun/step-5-preview\",\n displayName: \"Step 5 Preview\",\n provider: \"openrouter\",\n contextWindow: 1000000,\n pricing: usd(0.05, 1, 2.7),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // No official separate cache price published: cache_read uses the standard input price.\n modelId: \"stepfun/step-3.7-flash\",\n displayName: \"Step 3.7 Flash\",\n provider: \"openrouter\",\n contextWindow: 256000,\n pricing: usd(0.04, 0.2, 1.15),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // Tencent's Hy4 preview, read 2026-08-28 from its OpenRouter page and the models API:\n // $0.834 input / $2.501 output with a published $0.042 input_cache_read, a 1,048,576\n // context window, and text-only modalities in and out. The same upstream model is sold\n // in the TokenDance group at that gateway's own CNY rate; the two rows are priced by\n // their sellers and are not copies of one another.\n modelId: \"tencent/hy4-preview\",\n displayName: \"Hy4 preview\",\n provider: \"openrouter\",\n contextWindow: 1048576,\n pricing: usd(0.042, 0.834, 2.501),\n supportsVision: false,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"tencent/hy3\",\n displayName: \"Hy3\",\n provider: \"openrouter\",\n contextWindow: 262144,\n pricing: usd(0.033, 0.132, 0.528),\n supportsVision: false,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // Thinking Machines Lab's Inkling (released 2026-07-14): multimodal (image + audio\n // input). Specs from its OpenRouter page; pricing from the models API (2026-08-07),\n // which publishes $1 input (the page shows $0.95) and a $0.17 cached-input price.\n modelId: \"thinkingmachines/inkling\",\n displayName: \"Inkling\",\n provider: \"openrouter\",\n contextWindow: 1000000,\n pricing: usd(0.17, 1, 4.05),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // Grok 4.7 keeps Grok 4.6's $2 input / $6 output / $0.50 cache hit and its 500,000 window,\n // with image input. The listing's `overrides` double every rate from 200,000 prompt tokens;\n // the base tier is recorded.\n modelId: \"x-ai/grok-4.7\",\n displayName: \"Grok 4.7\",\n provider: \"openrouter\",\n contextWindow: 500000,\n pricing: usd(0.5, 2, 6),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // xAI's Grok 4.6 (OpenRouter listing dated 2026-08-12): same $2/$6 input/output rates as\n // Grok 4.5 with a raised $0.50 cache-hit price.\n modelId: \"x-ai/grok-4.6\",\n displayName: \"Grok 4.6\",\n provider: \"openrouter\",\n contextWindow: 500000,\n pricing: usd(0.5, 2, 6),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"x-ai/grok-4.5\",\n displayName: \"Grok 4.5\",\n provider: \"openrouter\",\n contextWindow: 500000,\n pricing: usd(0.3, 2, 6),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // $0.14 input / $0.28 output with a published $0.0028 input_cache_read, the same rates as\n // MiMo-V2.5; text, image, video and audio input.\n modelId: \"xiaomi/mimo-v2.6-flash\",\n displayName: \"MiMo-V2.6-Flash\",\n provider: \"openrouter\",\n contextWindow: 1048576,\n pricing: usd(0.0028, 0.14, 0.28),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // $0.435 input / $0.87 output with a published $0.0036 input_cache_read (models API and\n // the per-model endpoints API, read 2026-10-10: Xiaomi's own endpoint, no discount — the\n // USD face of TokenDance's CNY 0.025 / 3 / 6); text, image, video and audio input.\n modelId: \"xiaomi/mimo-v2.6-pro\",\n displayName: \"MiMo-V2.6-Pro\",\n provider: \"openrouter\",\n contextWindow: 1048576,\n pricing: usd(0.0036, 0.435, 0.87),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"xiaomi/mimo-v2.5\",\n displayName: \"MiMo-V2.5\",\n provider: \"openrouter\",\n contextWindow: 1048576,\n pricing: usd(0.0028, 0.14, 0.28),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // The gateway listing of the direct glm-5.3 row below; OpenRouter's single Z.AI endpoint\n // passes Z.AI's published price straight through (no discount), which is why the two\n // rows agree to the cent. Text-only, per the listing's modalities.\n modelId: \"z-ai/glm-5.3\",\n displayName: \"GLM-5.3\",\n provider: \"openrouter\",\n contextWindow: 1048576,\n pricing: usd(0.26, 1.4, 4.4),\n supportsVision: false,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n // The gateway listing of the direct glm-5.3-flash row below. Stored at the rate OpenRouter's\n // default endpoint bills: DeepInfra (fp4), running `discount: 0.5` on the 0.03 / 0.15 / 0.5\n // list (endpoints API, re-read 2026-09-16) — restore the list rates when that endpoint's\n // promotion ends. Z.AI's own 50% promotion is a different one: it ended at 2026-09-09\n // 16:00 UTC, and the Z.AI endpoint on OpenRouter bills the list price since. The listing\n // takes text, images and video, and the generic Responses client it pins carries image\n // parts through.\n modelId: \"z-ai/glm-5.3-flash\",\n displayName: \"GLM-5.3 Flash\",\n provider: \"openrouter\",\n contextWindow: 1048576,\n pricing: usd(0.015, 0.075, 0.25),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n {\n modelId: \"z-ai/glm-5.2\",\n displayName: \"GLM-5.2\",\n provider: \"openrouter\",\n contextWindow: 1000000,\n pricing: usd(0.1261, 0.679, 2.134),\n supportsVision: false,\n clientType: \"openai-responses\",\n baseUrl: OPENROUTER_BASE_URL,\n },\n // -- Fireworks AI (gateway, standard serverless USD pricing: cached input / uncached\n // input / output from each model's page; API ids use the accounts/fireworks/models/<slug>\n // form, where Fireworks spells a version's dot as `p`: deepseek-v4p1-flash, glm-5p3). The\n // DeepSeek V4.1 Flash, DeepSeek V4 Pro 0813, GLM-5.3, GLM-5.3 Flash and Qwen 3.8 Max rows\n // were added 2026-09-16 from their fireworks.ai/models pages. Fireworks publishes no context\n // length for qwen3p8-max, so that row records the vendor's 1M window, as the other\n // qwen3.8-max rows do. --\n {\n // Fireworks' listing of the model DeepSeek serves directly as `deepseek-flash`: 1,048,576\n // context, image input, and the single serverless price its page lists, so no schedule.\n modelId: \"accounts/fireworks/models/deepseek-v4p1-flash\",\n displayName: \"DeepSeek V4.1 Flash\",\n provider: \"fireworks\",\n contextWindow: 1048576,\n pricing: usd(0.007, 0.22, 0.66),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: FIREWORKS_BASE_URL,\n },\n {\n modelId: \"accounts/fireworks/models/deepseek-v4-flash-0731\",\n displayName: \"DeepSeek V4 Flash 0731\",\n provider: \"fireworks\",\n contextWindow: 1000000,\n pricing: usd(0.028, 0.14, 0.28),\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: FIREWORKS_BASE_URL,\n },\n {\n modelId: \"accounts/fireworks/models/deepseek-v4-flash\",\n displayName: \"DeepSeek V4 Flash\",\n provider: \"fireworks\",\n contextWindow: 1000000,\n pricing: usd(0.03, 0.14, 0.28),\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: FIREWORKS_BASE_URL,\n },\n {\n modelId: \"accounts/fireworks/models/deepseek-v4-pro-0813\",\n displayName: \"DeepSeek V4 Pro 0813\",\n provider: \"fireworks\",\n contextWindow: 1048576,\n pricing: usd(0.044, 1.32, 3.96),\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: FIREWORKS_BASE_URL,\n },\n {\n modelId: \"accounts/fireworks/models/deepseek-v4-pro\",\n displayName: \"DeepSeek V4 Pro\",\n provider: \"fireworks\",\n contextWindow: 1000000,\n pricing: usd(0.15, 1.74, 3.48),\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: FIREWORKS_BASE_URL,\n },\n {\n modelId: \"accounts/fireworks/models/glm-5p3\",\n displayName: \"GLM-5.3\",\n provider: \"fireworks\",\n contextWindow: 1048576,\n pricing: usd(0.26, 1.4, 4.4),\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: FIREWORKS_BASE_URL,\n },\n {\n // Natively multimodal like every other GLM-5.3 Flash row, and this group's generic\n // openai-chat client forwards image_url parts, so image input works on this path.\n modelId: \"accounts/fireworks/models/glm-5p3-flash\",\n displayName: \"GLM-5.3 Flash\",\n provider: \"fireworks\",\n contextWindow: 1048576,\n pricing: usd(0.03, 0.15, 0.5),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: FIREWORKS_BASE_URL,\n },\n {\n modelId: \"accounts/fireworks/models/glm-5p2\",\n displayName: \"GLM-5.2\",\n provider: \"fireworks\",\n contextWindow: 1000000,\n pricing: usd(0.14, 1.4, 4.4),\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: FIREWORKS_BASE_URL,\n },\n {\n // Thinking Machines Lab's Inkling (released 2026-07-14): multimodal (image + audio\n // input); specs and serverless pricing from its Fireworks model page (2026-08-06).\n modelId: \"accounts/fireworks/models/inkling\",\n displayName: \"Inkling\",\n provider: \"fireworks\",\n contextWindow: 1000000,\n pricing: usd(0.17, 1, 4.05),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: FIREWORKS_BASE_URL,\n },\n {\n modelId: \"accounts/fireworks/models/kimi-k3\",\n displayName: \"Kimi K3\",\n provider: \"fireworks\",\n contextWindow: 1000000,\n pricing: usd(0.3, 3, 15),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: FIREWORKS_BASE_URL,\n },\n {\n modelId: \"accounts/fireworks/models/kimi-k2p7-code\",\n displayName: \"Kimi K2.7 Code\",\n provider: \"fireworks\",\n contextWindow: 262144,\n pricing: usd(0.19, 0.95, 4),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: FIREWORKS_BASE_URL,\n },\n {\n modelId: \"accounts/fireworks/models/minimax-m3\",\n displayName: \"MiniMax M3\",\n provider: \"fireworks\",\n contextWindow: 524288,\n pricing: usd(0.06, 0.3, 1.2),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: FIREWORKS_BASE_URL,\n },\n {\n modelId: \"accounts/fireworks/models/qwen3p8-max\",\n displayName: \"Qwen 3.8 Max\",\n provider: \"fireworks\",\n contextWindow: 1000000,\n pricing: usd(0.25, 2, 6),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: FIREWORKS_BASE_URL,\n },\n // -- SiliconFlow (gateway, official CNY pricing: cache hit / input / output) --\n {\n // CNY 1 input / 4 output / 0.02 cache hit over 1,048,576 tokens, image input (MMSP 0.5.5's\n // registry, SiliconFlow's price list).\n modelId: \"deepseek-ai/DeepSeek-V4.1-Flash\",\n displayName: \"DeepSeek V4.1 Flash\",\n provider: \"siliconflow\",\n contextWindow: 1048576,\n pricing: cny(0.02, 1, 4),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: SILICONFLOW_BASE_URL,\n },\n {\n // SiliconFlow repriced it to CNY 1.5 / 4.5 / 0.15 (MMSP 0.5.5's registry).\n modelId: \"deepseek-ai/DeepSeek-V4-Flash\",\n displayName: \"DeepSeek V4 Flash\",\n provider: \"siliconflow\",\n contextWindow: 1048576,\n pricing: cny(0.15, 1.5, 4.5),\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: SILICONFLOW_BASE_URL,\n },\n {\n modelId: \"deepseek-ai/DeepSeek-V4-Pro\",\n displayName: \"DeepSeek V4 Pro\",\n provider: \"siliconflow\",\n contextWindow: 1048576,\n pricing: cny(1, 12, 24),\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: SILICONFLOW_BASE_URL,\n },\n {\n modelId: \"meituan-longcat/LongCat-2.0\",\n displayName: \"LongCat 2.0\",\n provider: \"siliconflow\",\n contextWindow: 1048576,\n pricing: cny(0.1, 5, 20),\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: SILICONFLOW_BASE_URL,\n },\n {\n modelId: \"moonshotai/Kimi-K2.7-Code\",\n displayName: \"Kimi K2.7 Code\",\n provider: \"siliconflow\",\n contextWindow: 262144,\n pricing: cny(1.3, 6.5, 27),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: SILICONFLOW_BASE_URL,\n },\n // The Pro/ and Qwen/ entries below were unpriced until 2026-08-03 (SiliconFlow's price\n // list sits behind an authenticated console); prices below are its official CNY list\n // prices.\n {\n modelId: \"Pro/moonshotai/Kimi-K2.6\",\n displayName: \"Kimi K2.6\",\n provider: \"siliconflow\",\n contextWindow: 262144,\n pricing: cny(1.1, 6.5, 27),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: SILICONFLOW_BASE_URL,\n },\n {\n // No cache-hit price on the list, so cache_read carries the input price.\n modelId: \"Qwen/Qwen3.6-35B-A3B\",\n displayName: \"Qwen 3.6 35B A3B\",\n provider: \"siliconflow\",\n contextWindow: 262144,\n pricing: cny(1.8, 1.8, 10.8),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: SILICONFLOW_BASE_URL,\n },\n {\n // Added 2026-09-16, both ids confirmed in SiliconFlow's /v1/models listing. Hy4 preview is\n // text only at CNY 6 input / 18 output / 0.3 cache hit, the list price as quoted again on\n // 2026-10-10; siliconflow.cn/pricing shows the same input and output figures and no cache\n // price. Its window is the 1,048,576 tokens that page now publishes for it (the row had\n // borrowed the TokenDance row's 1,024,000). GLM-5.3 below is text only at 8 / 28 / 2, with\n // the same 1M window as zai-org/GLM-5.2.\n modelId: \"tencent/Hy4-preview\",\n displayName: \"Hy4 preview\",\n provider: \"siliconflow\",\n contextWindow: 1048576,\n pricing: cny(0.3, 6, 18),\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: SILICONFLOW_BASE_URL,\n },\n {\n modelId: \"zai-org/GLM-5.3\",\n displayName: \"GLM-5.3\",\n provider: \"siliconflow\",\n contextWindow: 1048576,\n pricing: cny(2, 8, 28),\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: SILICONFLOW_BASE_URL,\n },\n {\n // Added 2026-10-10 at the list price quoted that day: CNY 0.23 cache hit / 0.8 input / 2.8\n // output, which is Z.AI's own CNY list for the model and what the TokenDance and Qwen\n // Pay-As-You-Go rows store. siliconflow.cn/pricing currently shows it at CNY 0, beside the\n // platform's free models; a free period is a rate no promotion field can hold, so the row\n // keeps the list price. The window is the 1,048,576 tokens that page publishes. Natively\n // multimodal (`vlm` there), and this group's openai-chat client forwards image_url parts.\n modelId: \"zai-org/GLM-5.3-Flash\",\n displayName: \"GLM-5.3 Flash\",\n provider: \"siliconflow\",\n contextWindow: 1048576,\n pricing: cny(0.23, 0.8, 2.8),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: SILICONFLOW_BASE_URL,\n },\n {\n modelId: \"zai-org/GLM-5.2\",\n displayName: \"GLM-5.2\",\n provider: \"siliconflow\",\n contextWindow: 1048576,\n pricing: cny(2, 8, 28),\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: SILICONFLOW_BASE_URL,\n },\n // -- Atlas Cloud (gateway: OpenAI-compatible protocol, preset base URL). Read 2026-10-11 from\n // the public catalog API (GET https://api.atlascloud.ai/v1/models, no credential required):\n // the ids exactly as listed, context windows, output limits, input modalities, quantization\n // and prices. The API's `pricing` figures are USD per token; the pricing page\n // (https://www.atlascloud.ai/pricing/models) states the same rates in USD per million\n // tokens. The presets are DeepSeek and Qwen models the other gateway groups preset. For\n // DeepSeek they are the releases TokenDance presets instead of the bare V4 ids (the user's\n // call for TokenDance on 2026-10-10, made for this group on 2026-10-11), taken only where\n // Atlas Cloud serves them at fp8: V4.1 Flash and V4 Pro 0813. Its V4 Flash 0731 is served at\n // fp4, like the bare deepseek-v4-flash and deepseek-v4-pro, so none of the three is a preset.\n // Qwen 3.6 35B A3B is the one the SiliconFlow and OpenRouter groups preset. Rows run newest\n // release first within a series (V4.1 before V4). Neither source publishes a cache-write\n // price for these rows, so cache_write carries the input price, as with the TokenDance and\n // Qwen gateways below. Atlas Cloud bills both DeepSeek rows at one fixed rate\n // (`pricing_mode` fixed, no time-based overrides), so neither declares DeepSeek's off-peak\n // schedule. The DeepSeek rows have a 393,216-token output limit; Qwen 3.6 35B A3B, which\n // takes image and video input, has 65,536.\n {\n // Image input, as the listing says (`text`, `image`).\n modelId: \"deepseek-ai/deepseek-v4.1-flash\",\n displayName: \"DeepSeek V4.1 Flash\",\n provider: \"atlascloud\",\n contextWindow: 1048576,\n pricing: usd(0.03, 0.3, 1.2),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: ATLASCLOUD_BASE_URL,\n },\n {\n modelId: \"deepseek-ai/deepseek-v4-pro-0813\",\n displayName: \"DeepSeek V4 Pro 0813\",\n provider: \"atlascloud\",\n contextWindow: 1048576,\n pricing: usd(0.132, 1.32, 3.96),\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: ATLASCLOUD_BASE_URL,\n },\n {\n // The API answers the rate billed today, USD 0.186 input / 1.11375 output, which the\n // pricing page shows as a 25% model discount on a 0.248 / 1.485 list price. The row stores\n // that list price and declares the promotion in `discount`, as every promoted row does.\n // No cache-hit price is published (the API repeats the input price), so cache_read carries\n // the input price too.\n modelId: \"qwen/qwen3.6-35b-a3b\",\n displayName: \"Qwen 3.6 35B A3B\",\n provider: \"atlascloud\",\n contextWindow: 262144,\n pricing: usd(0.248, 0.248, 1.485),\n discount: 0.25,\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: ATLASCLOUD_BASE_URL,\n },\n // -- TokenDance (gateway: OpenAI-compatible protocol, preset base URL). Re-read in full on\n // 2026-10-10 from two public APIs that need no credential: the gateway's catalog (GET\n // https://tokendance.space/gateway/v1/models — ids, context windows and supported protocols)\n // and the portal's model list (GET https://tokendance.space/portal/api/models/all — names,\n // input modalities and prices). Prices are the gateway's own CNY rates. The portal publishes\n // what a model bills as `pricing.items` and, while a promotion runs, its list price beside\n // that as `pricing.reference`. TokenDance charges no separate cache-write fee, so cache_write\n // carries the input price. The per-model pages (tokendance.space/models/<id>) render in the\n // browser from the same data.\n //\n // Discounts: every row here stores the official LIST price — the portal's `reference`, or\n // its `items` where no promotion runs — the convention of the two Qwen groups below, and a\n // promoted row declares its rate in `discount` rather than having its price rewritten: a\n // promotion that lapses is then one field to delete, with the rate to return to still on the\n // row. effectivePricing() applies it; a new Project stores the list price and the fraction as\n // a promotion beside it, which the cost center applies, so it charges what the gateway\n // charges. Eight rows carry a flat promotion as of 2026-10-10: ling-3.0-flash at 65% off, the\n // three Doubao Seed rows (seed-2.1-pro, seed-2.1-turbo, seed-evolving) at 50%, glm-5.2 at 20%,\n // and glm-5.3, glm-5.3-flash and qwen3.8-max at 10%; deepseek-v4.1-flash carries one on top\n // of its schedule (below). The gateway also sells the DeepSeek V4 preview releases under the\n // bare ids deepseek-v4-flash and deepseek-v4-pro (\"… Preview\"); they are deliberately not\n // presets (the user's call, 2026-10-10): the dated rows below are the releases that\n // superseded them.\n //\n // Three DeepSeek rows — deepseek-v4.1-flash, deepseek-v4-flash-0731 and deepseek-v4-pro-0813 —\n // are priced by time instead (`pricing.time_pricing`): a peak price on weekdays 09:00-12:00\n // and 14:00-18:00 Beijing time, DeepSeek's own windows, and half the peak list price at every\n // other hour. They store the peak list price and declare DEEPSEEK_OFF_PEAK, as the direct\n // DeepSeek rows do; so does the retired deepseek-v4-flash-vision-exp row, which is no longer a\n // preset. On top of that schedule the gateway takes 20% off. On deepseek-v4.1-flash it does\n // so in both tiers, and the row declares it in `discount` beside its schedule (re-read\n // 2026-10-13). On the 0731 and 0813 rows it does so in the peak tier alone and bills\n // off-peak at exactly half the list; a declared discount would come off the off-peak tier\n // too, so theirs is not recorded, and the cost center prices their peak hours 25% above what\n // the gateway bills. The rest of the group carries neither, so list price and billed rate\n // coincide.\n //\n // A running promotion usually also shows in a model's `description`, which opens with a\n // bracketed 限时 (\"limited-time\") tag. The tag is neither exhaustive nor authoritative on the\n // rate: kimi-k3's still announces an offer that ended 2026-09-30, and the two Seed 2.1 rows'\n // say 20% while their prices are at 50% off. The rows follow the prices.\n //\n // Display names follow the catalog's spelling of a model family where it has one (GLM-5.3,\n // Qwen 3.8 Max, MiMo-V2.5), and otherwise the portal's name without its \"Vendor: \" prefix\n // (Seed-2.1-Pro, Ling-3.1-flash, Step 5 Preview). Rows are in plain dictionary order by id. --\n {\n // Text only, 1,048,576 window. Priced by time (see the block comment): a CNY 3 input / 9\n // output / 0.1 cache hit list, billed at 2.4 / 7.2 / 0.08 in the peak windows and at half\n // the list, 1.5 / 4.5 / 0.05, at every other hour. It had been quoted on 2026-09-16 as a\n // flat CNY 1.5 / 4.5 / 0.15 list at 10% off.\n modelId: \"deepseek-v4-flash-0731\",\n displayName: \"DeepSeek V4 Flash 0731\",\n provider: \"tokendance\",\n contextWindow: 1048576,\n pricing: cny(0.1, 3, 9),\n offPeakDiscount: DEEPSEEK_OFF_PEAK,\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n // Retired from TokenDance's line-up 2026-09-16 (see ModelCatalogEntry.retired). It was sold\n // on DeepSeek's own peak/off-peak schedule at the peak tier CNY 0.04 / 2 / 8, the price a\n // sync keeps on the Projects still carrying it.\n modelId: \"deepseek-v4-flash-vision-exp\",\n displayName: \"DeepSeek V4 Flash Vision Exp\",\n provider: \"tokendance\",\n contextWindow: 1000000,\n pricing: cny(0.04, 2, 8),\n offPeakDiscount: DEEPSEEK_OFF_PEAK,\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n retired: true,\n },\n {\n // Text only, 1,000,000 window. Priced by time like the 0731 row: a CNY 9 input / 27 output\n // / 0.3 cache hit list, DeepSeek's own peak price for V4 Pro 0813, billed at 7.2 / 21.6 /\n // 0.24 in the peak windows and at half the list, 4.5 / 13.5 / 0.15, at every other hour. It\n // had been quoted on 2026-09-16 as a flat CNY 4.5 / 13.5 / 0.45 list at 10% off.\n modelId: \"deepseek-v4-pro-0813\",\n displayName: \"DeepSeek V4 Pro 0813\",\n provider: \"tokendance\",\n contextWindow: 1000000,\n pricing: cny(0.3, 9, 27),\n offPeakDiscount: DEEPSEEK_OFF_PEAK,\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n // Listed 2026-09-10; the dotted id is the seller's spelling of the model DeepSeek serves\n // directly as `deepseek-flash`. 1M context and native multimodality. Its list follows the\n // vendor's own schedule: the peak tier CNY 0.04 / 2 / 8, the direct row's figures, and half\n // that outside Beijing weekday 09:00-12:00 and 14:00-18:00. The row stores the peak tier\n // and declares DEEPSEEK_OFF_PEAK. The gateway also takes 20% off both tiers, declared in\n // `discount`: it bills 0.032 / 1.6 / 6.4 at peak and 0.016 / 0.8 / 3.2 off-peak (see the\n // block comment). Unlike the direct row this one needs no DeepSeek-specific pin — it is\n // reached through this group's generic openai-chat client, which forwards image_url parts.\n modelId: \"deepseek-v4.1-flash\",\n displayName: \"DeepSeek V4.1 Flash\",\n provider: \"tokendance\",\n contextWindow: 1000000,\n pricing: cny(0.04, 2, 8),\n discount: 0.2,\n offPeakDiscount: DEEPSEEK_OFF_PEAK,\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n // The 1017 snapshot, priced exactly as the row above in the public catalog (re-read\n // 2026-10-23): the same peak tier, schedule and 20% promotion.\n modelId: \"deepseek-v4.1-flash-1017\",\n displayName: \"DeepSeek V4.1 Flash 1017\",\n provider: \"tokendance\",\n contextWindow: 1000000,\n pricing: cny(0.04, 2, 8),\n discount: 0.2,\n offPeakDiscount: DEEPSEEK_OFF_PEAK,\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n // Dots Studio's (rednote / Xiaohongshu) Dots3-Note Preview: an open-weight MoE, 280B total\n // and 16B active, the lightest of the Dots 3 family. TokenDance lists it as \"Dots3-Note\n // Preview(Free)\": the words and the tag are kept as the seller spells them, as the\n // OpenRouter `(free)` rows keep theirs, but the full-width parentheses are the typesetting\n // of the seller's Chinese listing rather than part of the name, and a catalog name shows\n // untranslated in every UI language — so it takes the ASCII \" (\" of every other\n // parenthesised row, which reads right in both. The price is a\n // genuine CNY 0 on every bucket, the same treatment as the OpenRouter `:free` rows, so\n // costs compute to 0 and the free badge shows — over a 512,000-token context window, with\n // openai:chat-completions and anthropic:messages as its supported_protocols (this group's\n // openai-chat pin is a convention here, not the only shape the id serves). The gateway's\n // own listing describes it as covering multimodal understanding, which is what the\n // vision flag records; no image request was sent to it. Read 2026-09-15 from the\n // gateway's /models listing and tokendance.space/models/dots-3-note-preview, and unchanged\n // on 2026-10-10.\n modelId: \"dots-3-note-preview\",\n displayName: \"Dots3-Note Preview (Free)\",\n provider: \"tokendance\",\n contextWindow: 512000,\n pricing: cny(0, 0, 0),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n // Text only, 1,000,000 window. 20% off a CNY 8 input / 28 output / 2 cache hit list, the\n // same list as glm-5.3, so the gateway bills 6.4 / 22.4 / 1.6.\n modelId: \"glm-5.2\",\n displayName: \"GLM-5.2\",\n provider: \"tokendance\",\n contextWindow: 1000000,\n pricing: cny(2, 8, 28),\n discount: 0.2,\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n modelId: \"glm-5.3\",\n displayName: \"GLM-5.3\",\n provider: \"tokendance\",\n contextWindow: 1000000,\n pricing: cny(2, 8, 28),\n discount: 0.1,\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n // Natively multimodal per TokenDance's catalog entry, and this group's generic\n // openai-chat client forwards image_url parts, so image input works on this path. Its\n // supported_protocols are openai:chat-completions and anthropic:messages.\n //\n // The 50% promotion this row used to carry ran through 2026-09-09 24:00 (the catalog\n // API's own description said so) and has been replaced by 10% off; the list price is\n // unchanged, only the `discount` fraction moved.\n modelId: \"glm-5.3-flash\",\n displayName: \"GLM-5.3 Flash\",\n provider: \"tokendance\",\n contextWindow: 1000000,\n pricing: cny(0.23, 0.8, 2.8),\n discount: 0.1,\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n // A faster GLM-5.3 Flash (up to 200 tokens/s, per its listing), natively multimodal like\n // it: text, image and video input, which this group's openai-chat client forwards.\n // 1,000,000 window; CNY 2 input / 7 output / 0.57 cache hit, undiscounted.\n modelId: \"glm-5.3-flashx\",\n displayName: \"GLM-5.3 FlashX\",\n provider: \"tokendance\",\n contextWindow: 1000000,\n pricing: cny(0.57, 2, 7),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n // The same upstream model as the OpenRouter `tencent/hy4-preview` row above, reached\n // through a second seller: each row records what its own seller charges, so the two must\n // not be made to agree (the qwen3.8-flash pair below states the same rule). TokenDance\n // sells it at CNY 6 input / 18 output / 0.3 cache hit, undiscounted, over a 1,024,000\n // context window — both figures its own, neither copied from the OpenRouter listing.\n //\n // Text-only: the catalog entry advertises no image modality, matching the OpenRouter\n // listing's text-in/text-out. Its supported_protocols are openai:chat-completions and\n // openai:responses, so the openai-chat pin is this group's convention rather than the\n // only shape the id serves.\n modelId: \"hy4-preview\",\n displayName: \"Hy4 preview\",\n provider: \"tokendance\",\n contextWindow: 1024000,\n pricing: cny(0.3, 6, 18),\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n // CNY 20 input / 100 output / 2 cache hit, Moonshot's own list, undiscounted as of\n // 2026-10-10. The 40% promotion this row carried (seller's quote 2026-09-16, when the cache\n // hit listed at 1.6) has ended; the description still opens with the tag of an offer that\n // ran to 2026-09-30. Its supported_protocols is openai:chat-completions alone, so the\n // openai-chat pin is the only shape this id serves.\n modelId: \"kimi-k3\",\n displayName: \"Kimi K3\",\n provider: \"tokendance\",\n contextWindow: 1048576,\n pricing: cny(2, 20, 100),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n // Moonshot's Kimi K3.1 Pro (public catalog, read 2026-10-24): text, image and video input\n // over a 1,000,000-token window, at CNY 13 input / 68 output / 1.3 cache hit, undiscounted\n // and the same on both protocols the portal prices it on. Its supported_protocols are\n // openai:chat-completions and anthropic:messages, so the openai-chat pin is the group's\n // convention rather than the only shape the id serves; image parts go through this group's\n // openai-chat client.\n modelId: \"kimi-k3.1-pro\",\n displayName: \"Kimi K3.1 Pro\",\n provider: \"tokendance\",\n contextWindow: 1000000,\n pricing: cny(1.3, 13, 68),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n // inclusionAI's Ling-3.0-flash: text only, with the 256,000-token window the listing gives\n // (the model's native length; its description says it extends to 1M). 65% off a CNY 0.4\n // input / 1.2 output / 0.08 cache hit list, so the gateway bills 0.14 / 0.42 / 0.028.\n modelId: \"ling-3.0-flash\",\n displayName: \"Ling-3.0-flash\",\n provider: \"tokendance\",\n contextWindow: 256000,\n pricing: cny(0.08, 0.4, 1.2),\n discount: 0.65,\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n // Text only, 1,000,000 window, at a CNY 0.4 input / 1.2 output / 0.08 cache hit list (the\n // portal's `reference`, re-read 2026-10-14). Listed 2026-09-30 with a free trial served at\n // 256K, which the portal bills at 0 until 2026-10-14 10:00. A free period is no `discount`,\n // which is a fraction below 1. The row records the list price and the full window the\n // model is sold at after the trial.\n modelId: \"ling-3.1-flash\",\n displayName: \"Ling-3.1-flash\",\n provider: \"tokendance\",\n contextWindow: 1000000,\n pricing: cny(0.08, 0.4, 1.2),\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n // Xiaomi's MiMo-V2.6 line, the three rows alike: text, image, audio and video input (image\n // parts go through this group's openai-chat client), a 1,000,000 window, no promotion, and\n // openai:chat-completions, openai:responses and anthropic:messages as supported_protocols.\n // Flash at CNY 1 input / 2 output / 0.02 cache hit.\n modelId: \"mimo-v2.6-flash\",\n displayName: \"MiMo-V2.6-Flash\",\n provider: \"tokendance\",\n contextWindow: 1000000,\n pricing: cny(0.02, 1, 2),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n // Pro at CNY 3 input / 6 output / 0.025 cache hit.\n modelId: \"mimo-v2.6-pro\",\n displayName: \"MiMo-V2.6-Pro\",\n provider: \"tokendance\",\n contextWindow: 1000000,\n pricing: cny(0.025, 3, 6),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n // The Pro model served up to 20x faster, at ten times its price on every bucket: CNY 30\n // input / 60 output / 0.25 cache hit (OpenRouter lists the same rates in USD for\n // xiaomi/mimo-v2.6-pro-ultraspeed). The seller's id drops \"pro\"; its name keeps it.\n modelId: \"mimo-v2.6-ultraspeed\",\n displayName: \"MiMo-V2.6-Pro-UltraSpeed\",\n provider: \"tokendance\",\n contextWindow: 1000000,\n pricing: cny(0.25, 30, 60),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n // CNY 1 input / 4 output / 0.1 cache hit over a 1,000,000-token window, undiscounted (public\n // catalog, re-read 2026-10-23). Pinned to Anthropic Messages: the gateway's Chat Completions\n // stream for this model ends in a chunk without `delta`, which openai-chat cannot read\n // (MMSP 0.5.5's registry pins the same).\n modelId: \"minimax-m3.1-flash\",\n displayName: \"MiniMax M3.1 Flash\",\n provider: \"tokendance\",\n contextWindow: 1000000,\n pricing: cny(0.1, 1, 4),\n supportsVision: true,\n clientType: \"ant-messages\",\n baseUrl: TOKENDANCE_MESSAGES_BASE_URL,\n },\n {\n // One model reached two ways, priced by whoever is selling it: this row carries the\n // gateway's own CNY 0.8 input / 2.7 output / 0.1 cache hit, and the qwen-pay-as-you-go row\n // carries Qwen's direct list price for the same id. The two figures agree since Qwen's\n // 2026-09-16 re-pricing (its page had read 1 / 3 / 0.1), but only because the two sellers\n // do: each row still follows its own seller.\n //\n // Its supported_protocols are openai:chat-completions, openai:responses and\n // anthropic:messages, so the openai-chat pin here is the group's convention rather than the\n // only shape the id serves. Natively multimodal per the catalog entry, and this group's\n // openai-chat client forwards image_url parts, so image input works on this path.\n //\n // Undiscounted, so its list price and its billed rate coincide — unlike the\n // qwen3.8-max row below, which is on 10% off.\n modelId: \"qwen3.8-flash\",\n displayName: \"Qwen 3.8 Flash\",\n provider: \"tokendance\",\n contextWindow: 1000000,\n pricing: cny(0.1, 0.8, 2.7),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n modelId: \"qwen3.8-max\",\n displayName: \"Qwen 3.8 Max\",\n provider: \"tokendance\",\n contextWindow: 1000000,\n pricing: cny(1.5, 12, 36),\n discount: 0.1,\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n // The three Doubao Seed rows share this note. Priced 2026-09-02 from the seller's quoted\n // 50%-off rates, doubled back to the list price a row stores, and re-read 2026-10-10 from\n // the portal, whose prices still put all three at 50% off a list of CNY 6 / 30 / 1.2\n // (Pro, Evolving) and 3 / 15 / 0.6 (Turbo), input / output / cache hit — although the two\n // 2.1 rows' descriptions announce 20%. Context windows and protocols from the catalog API,\n // whose descriptions call the 2.1 models multimodal Coding/Agent models (this group's\n // openai-chat client forwards image_url parts, so image input works on this path).\n // seed-2.1-pro and seed-2.1-turbo also list openai:responses, so their openai-chat pin is\n // the group's convention rather than the only shape they serve; seed-evolving lists\n // chat-completions alone.\n //\n // Display names are the seller's own, as the catalog API spells them (re-read\n // 2026-10-10): Seed-2.1-Pro, Seed-2.1-Turbo, Seed-Evolving.\n modelId: \"seed-2.1-pro\",\n displayName: \"Seed-2.1-Pro\",\n provider: \"tokendance\",\n contextWindow: 256000,\n pricing: cny(1.2, 6, 30),\n discount: 0.5,\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n modelId: \"seed-2.1-turbo\",\n displayName: \"Seed-2.1-Turbo\",\n provider: \"tokendance\",\n contextWindow: 256000,\n pricing: cny(0.6, 3, 15),\n discount: 0.5,\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n // A rolling id: the catalog API describes it as the newest Seed Coding/Agent model\n // under one stable id — the same model as seed-2.1-pro at the time of reading — and\n // the seller prices it the same.\n modelId: \"seed-evolving\",\n displayName: \"Seed-Evolving\",\n provider: \"tokendance\",\n contextWindow: 256000,\n pricing: cny(1.2, 6, 30),\n discount: 0.5,\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n {\n // StepFun's Step 5 Preview: text, image and video input, a 1,000,000 window, and CNY 7\n // input / 20 output / 0.35 cache hit, undiscounted.\n modelId: \"step-5-preview\",\n displayName: \"Step 5 Preview\",\n provider: \"tokendance\",\n contextWindow: 1000000,\n pricing: cny(0.35, 7, 20),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: TOKENDANCE_BASE_URL,\n },\n // -- Penguin Go. All models use MMSP HTTP; the SDK appends /stream to /api/v1.\n // List prices are preset; authorization and sync supply the platform's promotions.\n // The DeepSeek rows follow\n // DeepSeek's own lineup (re-read 2026-09-16): V4.1 Flash as `deepseek-flash` and V4 Pro 0813\n // as `deepseek-v4-pro`; the two retired V4 Flash ids, served from V4.1 Flash, are not resold.\n // Gemini 3.7 Flash is no longer preset (2026-10-10): Google retires the id and reroutes it to\n // 3.8 Flash.\n {\n // Owner-confirmed relay list prices (2026-10-14), matching Google's introductory\n // rates. Any further Penguin Go promotion comes from authorization or model sync.\n modelId: \"gemini-4-argon\",\n displayName: \"Gemini 4 Argon\",\n provider: PENGUIN_GO_PROVIDER_ID,\n contextWindow: 1048576,\n pricing: usd(0.1, 2, 10),\n supportsVision: true,\n clientType: \"mmsp\",\n baseUrl: PENGUIN_GO_BASE_URL,\n },\n {\n modelId: \"gemini-3.8-flash\",\n displayName: \"Gemini 3.8 Flash\",\n provider: PENGUIN_GO_PROVIDER_ID,\n contextWindow: 1048576,\n pricing: usd(0.075, 0.75, 3.75),\n supportsVision: true,\n clientType: \"mmsp\",\n baseUrl: PENGUIN_GO_BASE_URL,\n },\n {\n modelId: \"gemini-3.6-flash\",\n displayName: \"Gemini 3.6 Flash\",\n provider: PENGUIN_GO_PROVIDER_ID,\n contextWindow: 1048576,\n pricing: usd(0.075, 0.75, 3.75),\n supportsVision: true,\n clientType: \"mmsp\",\n baseUrl: PENGUIN_GO_BASE_URL,\n },\n {\n modelId: \"gemini-3.5-flash\",\n displayName: \"Gemini 3.5 Flash\",\n provider: PENGUIN_GO_PROVIDER_ID,\n contextWindow: 1048576,\n pricing: usd(0.15, 1.5, 9),\n supportsVision: true,\n clientType: \"mmsp\",\n baseUrl: PENGUIN_GO_BASE_URL,\n },\n {\n modelId: \"gemini-3.5-flash-lite\",\n displayName: \"Gemini 3.5 Flash-Lite\",\n provider: PENGUIN_GO_PROVIDER_ID,\n contextWindow: 1048576,\n pricing: usd(0.03, 0.3, 2.5),\n supportsVision: true,\n clientType: \"mmsp\",\n baseUrl: PENGUIN_GO_BASE_URL,\n },\n {\n modelId: \"gemini-3.1-flash-lite\",\n displayName: \"Gemini 3.1 Flash-Lite\",\n provider: PENGUIN_GO_PROVIDER_ID,\n contextWindow: 1048576,\n pricing: usd(0.025, 0.25, 1.5),\n supportsVision: true,\n clientType: \"mmsp\",\n baseUrl: PENGUIN_GO_BASE_URL,\n },\n {\n modelId: \"gemini-3.1-pro-preview\",\n displayName: \"Gemini 3.1 Pro (Preview)\",\n provider: PENGUIN_GO_PROVIDER_ID,\n contextWindow: 1048576,\n pricing: usd(0.2, 2, 12),\n supportsVision: true,\n clientType: \"mmsp\",\n baseUrl: PENGUIN_GO_BASE_URL,\n },\n {\n modelId: \"deepseek-flash\",\n displayName: \"DeepSeek V4.1 Flash\",\n provider: PENGUIN_GO_PROVIDER_ID,\n contextWindow: 1000000,\n pricing: cny(0.04, 2, 8),\n offPeakDiscount: DEEPSEEK_OFF_PEAK,\n supportsVision: true,\n clientType: \"mmsp\",\n baseUrl: PENGUIN_GO_BASE_URL,\n },\n {\n modelId: \"deepseek-v4-pro\",\n displayName: \"DeepSeek V4 Pro 0813\",\n provider: PENGUIN_GO_PROVIDER_ID,\n contextWindow: 1000000,\n pricing: cny(0.3, 9, 27),\n offPeakDiscount: DEEPSEEK_OFF_PEAK,\n supportsVision: false,\n clientType: \"mmsp\",\n baseUrl: PENGUIN_GO_BASE_URL,\n },\n // -- OpenCode Go. Latest generation of each model tier from opencode.ai/v2/docs/console/go/\n // (2026-10-14); context and vision from OpenCode's models.dev registry. The Code, Pro,\n // Flash, Max and Plus tiers are independent: a newer Flash does not replace a Pro.\n // Generic clients pin the documented wire protocol. The /zen/go aliases remain live;\n // keeping them avoids changing existing group endpoints. Requests name their conversation\n // through the x-opencode-session header core's GenerativeModel attaches.\n // Prices measure subscription allowance consumed, not the monthly fee. Cache writes use\n // the input price when no write premium is published. GPT Luna (>272K), Haiku (>100K),\n // Grok (>200K) and Qwen Plus (>256K) store the base tier. DeepSeek stores its peak rates\n // and DEEPSEEK_OFF_PEAK schedule. Allowance multipliers are not price discounts.\n // Superseded rows remain retired for saved Projects and historical off-peak pricing;\n // removal follows ModelCatalogEntry.retired and the backward-compatibility changelog.\n {\n modelId: \"cat-jam-free\",\n displayName: \"Cat Jam Free\",\n provider: \"opencode-go\",\n contextWindow: 262144,\n pricing: usd(0, 0, 0),\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"claude-haiku-5-5\",\n displayName: \"Claude Haiku 5.5\",\n provider: \"opencode-go\",\n contextWindow: 1000000,\n pricing: usd(0.01, 0.125, 0.5),\n supportsVision: true,\n clientType: \"ant-messages\",\n baseUrl: OPENCODE_GO_MESSAGES_BASE_URL,\n },\n {\n modelId: \"deepseek-v4.1-flash\",\n displayName: \"DeepSeek V4.1 Flash\",\n provider: \"opencode-go\",\n contextWindow: 1000000,\n pricing: usd(0.006, 0.3, 1.2),\n offPeakDiscount: DEEPSEEK_OFF_PEAK,\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"deepseek-v4-flash\",\n displayName: \"DeepSeek V4 Flash\",\n provider: \"opencode-go\",\n contextWindow: 1000000,\n pricing: usd(0.006, 0.3, 1.2),\n offPeakDiscount: DEEPSEEK_OFF_PEAK,\n supportsVision: false,\n retired: true,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"deepseek-v4-flash-vision-exp\",\n displayName: \"DeepSeek V4 Flash Vision Exp\",\n provider: \"opencode-go\",\n contextWindow: 1000000,\n pricing: usd(0.006, 0.3, 1.2),\n offPeakDiscount: DEEPSEEK_OFF_PEAK,\n supportsVision: true,\n retired: true,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"deepseek-v4-pro\",\n displayName: \"DeepSeek V4 Pro\",\n provider: \"opencode-go\",\n contextWindow: 1000000,\n pricing: usd(0.044, 1.32, 3.96),\n offPeakDiscount: DEEPSEEK_OFF_PEAK,\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"gemini-4-argon-contributor\",\n displayName: \"Gemini 4 Argon Contributor\",\n provider: \"opencode-go\",\n contextWindow: 1048576,\n pricing: usd(0.2, 4, 20),\n supportsVision: true,\n clientType: \"google-genai\",\n baseUrl: OPENCODE_GO_GOOGLE_BASE_URL,\n },\n {\n modelId: \"glm-5.3\",\n displayName: \"GLM-5.3\",\n provider: \"opencode-go\",\n contextWindow: 1000000,\n pricing: usd(0.26, 1.4, 4.4),\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"glm-5.3-flash\",\n displayName: \"GLM-5.3 Flash\",\n provider: \"opencode-go\",\n contextWindow: 1000000,\n pricing: usd(0.03, 0.15, 0.5),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"glm-5.2\",\n displayName: \"GLM-5.2\",\n provider: \"opencode-go\",\n contextWindow: 1000000,\n pricing: usd(0.26, 1.4, 4.4),\n supportsVision: false,\n retired: true,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"glm-5.1\",\n displayName: \"GLM-5.1\",\n provider: \"opencode-go\",\n contextWindow: 202752,\n pricing: usd(0.26, 1.4, 4.4),\n supportsVision: false,\n retired: true,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"gpt-6-luna\",\n displayName: \"GPT-6 Luna\",\n provider: \"opencode-go\",\n contextWindow: 1050000,\n pricing: usd(0.01, 0.125, 0.5),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"gpt-5.6-luna\",\n displayName: \"GPT-5.6 Luna\",\n provider: \"opencode-go\",\n contextWindow: 1050000,\n pricing: usd(0.02, 0.25, 1.2),\n supportsVision: true,\n retired: true,\n clientType: \"openai-responses\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"grok-4.7\",\n displayName: \"Grok 4.7\",\n provider: \"opencode-go\",\n contextWindow: 500000,\n pricing: usd(0.5, 2, 6),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"grok-4.6\",\n displayName: \"Grok 4.6\",\n provider: \"opencode-go\",\n contextWindow: 500000,\n pricing: usd(0.5, 2, 6),\n supportsVision: true,\n retired: true,\n clientType: \"openai-responses\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"hy4-preview\",\n displayName: \"Hy4 preview\",\n provider: \"opencode-go\",\n contextWindow: 1024000,\n pricing: usd(0.042, 0.834, 2.501),\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n // models.dev lists a 256,000-token context for Hy3 but caps its input at 192,000. Compaction\n // derives from this field, so it records the input cap: at 256,000 a Session would keep\n // sending prompts the upstream refuses until it compacted at ~254K.\n modelId: \"hy3\",\n displayName: \"Hy3\",\n provider: \"opencode-go\",\n contextWindow: 192000,\n pricing: usd(0.035, 0.14, 0.58),\n supportsVision: false,\n retired: true,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"kimi-k3\",\n displayName: \"Kimi K3\",\n provider: \"opencode-go\",\n contextWindow: 1048576,\n pricing: usd(0.3, 3, 15),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"kimi-k2.7-code\",\n displayName: \"Kimi K2.7 Code\",\n provider: \"opencode-go\",\n contextWindow: 262144,\n pricing: usd(0.19, 0.95, 4),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"kimi-k2.6\",\n displayName: \"Kimi K2.6\",\n provider: \"opencode-go\",\n contextWindow: 262144,\n pricing: usd(0.16, 0.95, 4),\n supportsVision: true,\n retired: true,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"longcat-2.5-preview-free\",\n displayName: \"LongCat 2.5 Preview Free\",\n provider: \"opencode-go\",\n contextWindow: 1000000,\n pricing: usd(0, 0, 0),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"longcat-2.0\",\n displayName: \"LongCat 2.0\",\n provider: \"opencode-go\",\n contextWindow: 1000000,\n pricing: usd(0.006, 0.3, 1.2),\n supportsVision: false,\n retired: true,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"mimo-v2.6-flash\",\n displayName: \"MiMo-V2.6-Flash\",\n provider: \"opencode-go\",\n contextWindow: 1048576,\n pricing: usd(0.0028, 0.14, 0.28),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"mimo-v2.6-pro\",\n displayName: \"MiMo-V2.6-Pro\",\n provider: \"opencode-go\",\n contextWindow: 1048576,\n pricing: usd(0.003625, 0.435, 0.87),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"mimo-v2.5\",\n displayName: \"MiMo-V2.5\",\n provider: \"opencode-go\",\n contextWindow: 1000000,\n pricing: usd(0.0028, 0.14, 0.28),\n supportsVision: true,\n retired: true,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"mimo-v2.5-pro\",\n displayName: \"MiMo-V2.5-Pro\",\n provider: \"opencode-go\",\n contextWindow: 1048576,\n pricing: usd(0.003625, 0.435, 0.87),\n supportsVision: false,\n retired: true,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"minimax-m3\",\n displayName: \"MiniMax M3\",\n provider: \"opencode-go\",\n contextWindow: 1000000,\n pricing: usd(0.06, 0.3, 1.2),\n supportsVision: true,\n clientType: \"ant-messages\",\n baseUrl: OPENCODE_GO_MESSAGES_BASE_URL,\n },\n {\n modelId: \"minimax-m2.7\",\n displayName: \"MiniMax M2.7\",\n provider: \"opencode-go\",\n contextWindow: 204800,\n pricing: usd(0.06, 0.375, 1.2),\n supportsVision: false,\n retired: true,\n clientType: \"ant-messages\",\n baseUrl: OPENCODE_GO_MESSAGES_BASE_URL,\n },\n {\n modelId: \"muse-spark-1.3-contributor\",\n displayName: \"Muse Spark 1.3 Contributor\",\n provider: \"opencode-go\",\n contextWindow: 1048576,\n pricing: usd(0.002, 0.1, 0.2),\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"muse-spark-1.2-contributor\",\n displayName: \"Muse Spark 1.2 Contributor\",\n provider: \"opencode-go\",\n contextWindow: 1048576,\n pricing: usd(0.002, 0.1, 0.2),\n supportsVision: true,\n retired: true,\n clientType: \"openai-responses\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"qwen3.8-flash\",\n displayName: \"Qwen 3.8 Flash\",\n provider: \"opencode-go\",\n contextWindow: 1000000,\n pricing: usd(0.016, 0.2, 0.47),\n supportsVision: true,\n clientType: \"ant-messages\",\n baseUrl: OPENCODE_GO_MESSAGES_BASE_URL,\n },\n {\n modelId: \"qwen3.8-max\",\n displayName: \"Qwen 3.8 Max\",\n provider: \"opencode-go\",\n contextWindow: 1000000,\n pricing: usd(0.25, 2.5, 6),\n supportsVision: true,\n clientType: \"ant-messages\",\n baseUrl: OPENCODE_GO_MESSAGES_BASE_URL,\n },\n {\n modelId: \"qwen3.7-max\",\n displayName: \"Qwen 3.7 Max\",\n provider: \"opencode-go\",\n contextWindow: 1000000,\n pricing: usd(0.5, 3.125, 7.5),\n supportsVision: false,\n retired: true,\n clientType: \"ant-messages\",\n baseUrl: OPENCODE_GO_MESSAGES_BASE_URL,\n },\n {\n modelId: \"qwen3.7-plus\",\n displayName: \"Qwen 3.7 Plus\",\n provider: \"opencode-go\",\n contextWindow: 1000000,\n pricing: usd(0.04, 0.5, 1.6),\n supportsVision: true,\n clientType: \"ant-messages\",\n baseUrl: OPENCODE_GO_MESSAGES_BASE_URL,\n },\n {\n modelId: \"qwen3.6-plus\",\n displayName: \"Qwen 3.6 Plus\",\n provider: \"opencode-go\",\n contextWindow: 1000000,\n pricing: usd(0.05, 0.625, 3),\n supportsVision: true,\n retired: true,\n clientType: \"ant-messages\",\n baseUrl: OPENCODE_GO_MESSAGES_BASE_URL,\n },\n {\n // The context spans 1M tokens, but models.dev caps input at 524,288; compaction uses input.\n modelId: \"space-bunny\",\n displayName: \"Space Bunny\",\n provider: \"opencode-go\",\n contextWindow: 524288,\n pricing: usd(0.03, 0.15, 0.6),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n {\n modelId: \"step-5-preview-free\",\n displayName: \"Step 5 Preview Free\",\n provider: \"opencode-go\",\n contextWindow: 1000000,\n pricing: usd(0, 0, 0),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: OPENCODE_GO_BASE_URL,\n },\n // -- Qwen Token Plan (subscription gateway; vision flags per the plan's supported-model\n // table, and for the rows added 2026-09-16 per their model pages' input modalities).\n // Pricing and context windows from each model's page at www.qianwenai.com/models/<id>\n // (official CNY list prices; limited-time promotions such as the 20%/50% off discounts are\n // not stored). Lineup updated 2026-09-16: deepseek-v4.1-flash, deepseek-v4-pro-0813,\n // glm-5.3 and qwen3.8-flash join; deepseek-v4-flash-0731, deepseek-v4-pro and glm-5.2\n // leave the plan.\n //\n // The two DeepSeek rows are priced by time of day: their pages list a peak and an off-peak\n // price, the off-peak one exactly half on every bucket and in force from 22:00 to 08:00\n // Beijing time every day. They store the PEAK price and declare QWEN_OFF_PEAK, the same\n // shape the DeepSeek rows take with DeepSeek's own schedule. --\n {\n // Peak CNY 2 input / 8 output / 0.2 cache hit; off-peak 1 / 4 / 0.1. Text and image input.\n modelId: \"deepseek-v4.1-flash\",\n displayName: \"DeepSeek V4.1 Flash\",\n provider: \"qwen-token-plan\",\n contextWindow: 1000000,\n pricing: cny(0.2, 2, 8),\n offPeakDiscount: QWEN_OFF_PEAK,\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: QWEN_TOKEN_PLAN_BASE_URL,\n },\n {\n // Peak CNY 9 input / 27 output / 0.9 cache hit; off-peak 4.5 / 13.5 / 0.45. Text only.\n modelId: \"deepseek-v4-pro-0813\",\n displayName: \"DeepSeek V4 Pro 0813\",\n provider: \"qwen-token-plan\",\n contextWindow: 1000000,\n pricing: cny(0.9, 9, 27),\n offPeakDiscount: QWEN_OFF_PEAK,\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: QWEN_TOKEN_PLAN_BASE_URL,\n },\n {\n modelId: \"glm-5.3\",\n displayName: \"GLM-5.3\",\n provider: \"qwen-token-plan\",\n contextWindow: 1048576,\n pricing: cny(2, 8, 28),\n supportsVision: false,\n clientType: \"openai-chat\",\n baseUrl: QWEN_TOKEN_PLAN_BASE_URL,\n },\n {\n modelId: \"qwen3.8-flash\",\n displayName: \"Qwen 3.8 Flash\",\n provider: \"qwen-token-plan\",\n contextWindow: 1000000,\n pricing: cny(0.1, 0.8, 2.7),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: QWEN_TOKEN_PLAN_BASE_URL,\n },\n {\n modelId: \"qwen3.8-max\",\n displayName: \"Qwen 3.8 Max\",\n provider: \"qwen-token-plan\",\n contextWindow: 1000000,\n pricing: cny(1.5, 12, 36),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: QWEN_TOKEN_PLAN_BASE_URL,\n },\n {\n modelId: \"qwen3.7-plus\",\n displayName: \"Qwen 3.7 Plus\",\n provider: \"qwen-token-plan\",\n contextWindow: 1000000,\n pricing: cny(0.4, 2, 8),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: QWEN_TOKEN_PLAN_BASE_URL,\n },\n // -- Qwen Pay-As-You-Go (DashScope's OpenAI-compatible pay-per-token marketplace; official\n // CNY list prices and specs from each model's page at www.qianwenai.com/models/<id> —\n // resold third-party models keep their upstream ids exactly as the page lists them: kimi/\n // and ZHIPU/ carry vendor prefixes, DeepSeek is listed bare). Lineup updated 2026-09-16:\n // deepseek-v4.1-flash, kimi/kimi-k2.8-preview and ZHIPU/GLM-5.3-Flash join;\n // deepseek-v4-flash-0731 and ZHIPU/GLM-5.2 leave. The DeepSeek row is priced by time of day\n // on QWEN_OFF_PEAK and stores its peak price, as in the Token Plan group above. --\n {\n // Peak CNY 2 input / 8 output / 0.2 cache hit; off-peak (22:00-08:00 Beijing) 1 / 4 / 0.1.\n // Text and image input, which this group's openai-chat client forwards.\n modelId: \"deepseek-v4.1-flash\",\n displayName: \"DeepSeek V4.1 Flash\",\n provider: \"qwen-pay-as-you-go\",\n contextWindow: 1000000,\n pricing: cny(0.2, 2, 8),\n offPeakDiscount: QWEN_OFF_PEAK,\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: QWEN_PAYG_BASE_URL,\n },\n {\n modelId: \"kimi/kimi-k3\",\n displayName: \"Kimi K3\",\n provider: \"qwen-pay-as-you-go\",\n contextWindow: 1048576,\n pricing: cny(2, 20, 100),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: QWEN_PAYG_BASE_URL,\n },\n {\n // CNY 6.5 input / 27 output / 1.7 cache hit over a 1M window (1,048,576, as on the\n // kimi/kimi-k3 row); text, image and video input.\n modelId: \"kimi/kimi-k2.8-preview\",\n displayName: \"Kimi K2.8 Preview\",\n provider: \"qwen-pay-as-you-go\",\n contextWindow: 1048576,\n pricing: cny(1.7, 6.5, 27),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: QWEN_PAYG_BASE_URL,\n },\n {\n // Official CNY list price from www.qianwenai.com/models/qwen3.8-flash, re-read 2026-09-16:\n // CNY 0.8 input / CNY 0.1 cache hit / CNY 2.7 output per MTok (it had been 1 / 0.1 / 3),\n // over a 1M-token input window with a 131K output cap. Its input modalities include\n // images and video, and this group's openai-chat client converts image parts.\n modelId: \"qwen3.8-flash\",\n displayName: \"Qwen 3.8 Flash\",\n provider: \"qwen-pay-as-you-go\",\n contextWindow: 1000000,\n pricing: cny(0.1, 0.8, 2.7),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: QWEN_PAYG_BASE_URL,\n },\n {\n modelId: \"qwen3.8-max\",\n displayName: \"Qwen 3.8 Max\",\n provider: \"qwen-pay-as-you-go\",\n contextWindow: 1000000,\n pricing: cny(1.5, 12, 36),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: QWEN_PAYG_BASE_URL,\n },\n {\n modelId: \"qwen3.7-plus\",\n displayName: \"Qwen 3.7 Plus\",\n provider: \"qwen-pay-as-you-go\",\n contextWindow: 1000000,\n pricing: cny(0.4, 2, 8),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: QWEN_PAYG_BASE_URL,\n },\n {\n // CNY 0.8 input / 2.8 output / 0.23 cache hit over a 1M window with a 131K output cap;\n // natively multimodal like every other GLM-5.3 Flash row, and this group's openai-chat\n // client forwards image parts.\n modelId: \"ZHIPU/GLM-5.3-Flash\",\n displayName: \"GLM-5.3 Flash\",\n provider: \"qwen-pay-as-you-go\",\n contextWindow: 1000000,\n pricing: cny(0.23, 0.8, 2.8),\n supportsVision: true,\n clientType: \"openai-chat\",\n baseUrl: QWEN_PAYG_BASE_URL,\n },\n // -- ModelScope (api-inference aggregate, preset base URL). Preset ids keep ModelScope's\n // own `org/Model-Name` spelling; DeepSeek was read from the endpoint's public /v1/models\n // listing (2026-09-18), and the Qwen additions from their public model pages (2026-09-20).\n //\n // ModelScope serves all three presets through its OpenAI Responses endpoint, so every row pins\n // MMSP's generic Responses client. Keeping the protocol explicit also prevents ids from\n // auto-routing to vendor-specific clients with a different request shape.\n //\n // The window and vision flags are NOT read from ModelScope's own docs — its model pages are\n // client-rendered and carry no price. They repeat what other rows of the same models record,\n // because ModelScope serves the same upstream ids.\n //\n // `pricing` is deliberately absent. ModelScope bills for api-inference and does not publish a\n // read-able rate, so an absent pricing — which the catalog reads as \"nobody has looked this\n // up\", leaving the row unbadged and the group's usage uncosted — is the honest state. A\n // three-zero pricing would be worse than absent here, not better: `isFreeModel` would badge a\n // billed gateway as \"Free\". Whoever next reads ModelScope's pricing page should fill it in. --\n {\n modelId: \"deepseek-ai/DeepSeek-V4.1-Flash\",\n displayName: \"DeepSeek V4.1 Flash\",\n provider: MODELSCOPE_PROVIDER_ID,\n contextWindow: 1000000,\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: MODELSCOPE_BASE_URL,\n },\n {\n modelId: \"Qwen/Qwen3.8-27B\",\n displayName: \"Qwen 3.8 27B\",\n provider: MODELSCOPE_PROVIDER_ID,\n contextWindow: 262144,\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: MODELSCOPE_BASE_URL,\n },\n {\n modelId: \"Qwen/Qwen3.8-Flash-Next\",\n displayName: \"Qwen 3.8 Flash Next\",\n provider: MODELSCOPE_PROVIDER_ID,\n contextWindow: 262144,\n supportsVision: true,\n clientType: \"openai-responses\",\n baseUrl: MODELSCOPE_BASE_URL,\n },\n // -- MiniMax (official USD pay-as-you-go list prices, standard tier at <=512K input — every\n // rate doubles above 512K, and the priority tier is 1.5x). --\n {\n // Pay-as-you-go list price, one tier (MiniMax pricing guide, read 2026-10-19 by MMSP 0.5.5's\n // registry): $0.15 input / $0.60 output / $0.015 cache hit over a 1,000,000-token window.\n modelId: \"MiniMax-M3.1-Flash\",\n displayName: \"MiniMax M3.1 Flash\",\n provider: \"minimax\",\n contextWindow: 1000000,\n pricing: usd(0.015, 0.15, 0.6),\n supportsVision: true,\n },\n {\n modelId: \"MiniMax-M3\",\n displayName: \"MiniMax M3\",\n provider: \"minimax\",\n contextWindow: 1000000,\n pricing: usd(0.06, 0.3, 1.2),\n supportsVision: true,\n },\n // -- Google Gemini (official USD pricing). Gemini 3.7 Flash left the group on 2026-10-10:\n // Google retires the id and reroutes it to 3.8 Flash, at the same price. --\n {\n // ai.google.dev/gemini-api/docs/pricing#gemini-4-argon (2026-10-14): standard list\n // prices with a 50% introductory discount through 2026-11-30. Only implicit caching\n // is supported; cache_write is the ordinary input price.\n modelId: \"gemini-4-argon\",\n displayName: \"Gemini 4 Argon\",\n provider: \"google\",\n contextWindow: 1048576,\n pricing: usd(0.2, 4, 20),\n discount: 0.5,\n supportsVision: true,\n },\n {\n // Same list price and same launch discount as the gemini-3.6-flash row below: Google\n // halves all three rates through 2026-12-31. Like that row this one declares the\n // promotion in `discount`, so the list price stays on file — here and in a Project, which\n // is seeded with the fraction beside it — while the cost center bills the 0.075/0.75/3.75\n // Google actually charges today. One field to delete when the promotion lapses.\n modelId: \"gemini-3.8-flash\",\n displayName: \"Gemini 3.8 Flash\",\n provider: \"google\",\n contextWindow: 1048576,\n pricing: usd(0.15, 1.5, 7.5),\n discount: 0.5,\n supportsVision: true,\n },\n {\n // Same list price and same launch discount as the 3.8 row: Google halves all three rates\n // through 2026-12-31 (Google's pricing page, read 2026-09-09).\n modelId: \"gemini-3.6-flash\",\n displayName: \"Gemini 3.6 Flash\",\n provider: \"google\",\n contextWindow: 1048576,\n pricing: usd(0.15, 1.5, 7.5),\n discount: 0.5,\n supportsVision: true,\n },\n {\n // Google's 3.5 tier list price ($1.50 / $9.00 / $0.15 cache hit), which carries no launch\n // discount — re-read 2026-09-09. The $9 output is what the tier costs, not a promotion.\n modelId: \"gemini-3.5-flash\",\n displayName: \"Gemini 3.5 Flash\",\n provider: \"google\",\n contextWindow: 1048576,\n pricing: usd(0.15, 1.5, 9),\n supportsVision: true,\n },\n {\n modelId: \"gemini-3.5-flash-lite\",\n displayName: \"Gemini 3.5 Flash-Lite\",\n provider: \"google\",\n contextWindow: 1048576,\n pricing: usd(0.03, 0.3, 2.5),\n supportsVision: true,\n },\n {\n modelId: \"gemini-3.1-flash-lite\",\n displayName: \"Gemini 3.1 Flash-Lite\",\n provider: \"google\",\n contextWindow: 1048576,\n pricing: usd(0.025, 0.25, 1.5),\n supportsVision: true,\n },\n {\n // ≤200K input tier; >200K has official surcharge pricing (see file header comment).\n modelId: \"gemini-3.1-pro-preview\",\n displayName: \"Gemini 3.1 Pro (Preview)\",\n provider: \"google\",\n contextWindow: 1048576,\n pricing: usd(0.2, 2, 12),\n supportsVision: true,\n },\n {\n modelId: \"gemini-3-flash-preview\",\n displayName: \"Gemini 3 Flash (Preview)\",\n provider: \"google\",\n contextWindow: 1048576,\n pricing: usd(0.05, 0.5, 3),\n supportsVision: true,\n },\n // -- Anthropic (official USD pricing; cache write = 1.25 x input, the 5-minute write).\n // Re-read 2026-08-20 from platform.claude.com/docs/en/about-claude/pricing; the 5.5 / 5.1\n // generation added 2026-10-10 from MMSP 0.5.2's registry and the copy of that page it\n // carries (llmsdk_docs/claude5_5/docs/pricing.md). Sonnet 5's $2 input / $10 output is its\n // standard rate rather than an introductory one, so it prices below Sonnet 4.6 — that\n // inversion is Anthropic's list, not a transcription slip. The cache-hit multiplier is no\n // longer one figure: 0.025x input on Fable 5.1, 0.05x on Opus 5.5 and Sonnet 5.5, 0.1x on\n // every other row. Anthropic bills the full 1M window at a single rate on every row but\n // Haiku 5.5, which the file header's tier list names; and the fast-mode premium on Opus 5.5\n // ($8 input / $40 output) and Opus 5 / Opus 4.8 ($10 / $50) is a separate tier these rows do\n // not record. Every row takes image input over a 1,000,000-token window. --\n {\n // $10 input / $12.50 cache write / $0.25 cache hit / $50 output.\n modelId: \"claude-fable-5-1\",\n displayName: \"Claude Fable 5.1\",\n provider: \"anthropic\",\n contextWindow: 1000000,\n pricing: usd(0.25, 12.5, 50),\n supportsVision: true,\n },\n {\n modelId: \"claude-fable-5\",\n displayName: \"Claude Fable 5\",\n provider: \"anthropic\",\n contextWindow: 1000000,\n pricing: usd(1, 12.5, 50),\n supportsVision: true,\n },\n {\n // $0.10 input / $0.125 cache write / $0.01 cache hit / $0.50 output for a prompt of up to\n // 100,000 tokens, counting cache reads and writes; a longer prompt pays 5x on every rate,\n // for the whole request. The base tier is recorded. MMSP 0.5.2 is the first release whose\n // official Anthropic client knows the model: it runs `none` thinking at low effort, refuses\n // a forced tool choice, which Haiku 5.5 answers without thinking, and refuses fast mode,\n // which Haiku 5.5 rejects (fastModeProtocol offers no toggle for it either).\n modelId: \"claude-haiku-5-5\",\n displayName: \"Claude Haiku 5.5\",\n provider: \"anthropic\",\n contextWindow: 1000000,\n pricing: usd(0.01, 0.125, 0.5),\n supportsVision: true,\n },\n {\n // $4 input / $5 cache write / $0.20 cache hit / $20 output.\n modelId: \"claude-opus-5-5\",\n displayName: \"Claude Opus 5.5\",\n provider: \"anthropic\",\n contextWindow: 1000000,\n pricing: usd(0.2, 5, 20),\n supportsVision: true,\n },\n {\n modelId: \"claude-opus-5\",\n displayName: \"Claude Opus 5\",\n provider: \"anthropic\",\n contextWindow: 1000000,\n pricing: usd(0.5, 6.25, 25),\n supportsVision: true,\n },\n {\n modelId: \"claude-opus-4-8\",\n displayName: \"Claude Opus 4.8\",\n provider: \"anthropic\",\n contextWindow: 1000000,\n pricing: usd(0.5, 6.25, 25),\n supportsVision: true,\n },\n {\n modelId: \"claude-opus-4-7\",\n displayName: \"Claude Opus 4.7\",\n provider: \"anthropic\",\n contextWindow: 1000000,\n pricing: usd(0.5, 6.25, 25),\n supportsVision: true,\n },\n {\n // $2 input / $2.50 cache write / $0.10 cache hit / $10 output. MMSP 0.5.0 listed the cache\n // hit at $0.20, Sonnet 5's figure; 0.5.2 lowered it to the 0.05x of input that Anthropic's\n // pricing page states for this model.\n modelId: \"claude-sonnet-5-5\",\n displayName: \"Claude Sonnet 5.5\",\n provider: \"anthropic\",\n contextWindow: 1000000,\n pricing: usd(0.1, 2.5, 10),\n supportsVision: true,\n },\n {\n modelId: \"claude-sonnet-5\",\n displayName: \"Claude Sonnet 5\",\n provider: \"anthropic\",\n contextWindow: 1000000,\n pricing: usd(0.2, 2.5, 10),\n supportsVision: true,\n },\n {\n modelId: \"claude-sonnet-4-6\",\n displayName: \"Claude Sonnet 4.6\",\n provider: \"anthropic\",\n contextWindow: 1000000,\n pricing: usd(0.3, 3.75, 15),\n supportsVision: true,\n },\n // -- OpenAI (official USD pricing) --\n {\n // OpenAI's list price per MMSP 0.5.2's registry and the model page it carries\n // (llmsdk_docs/gpt6/docs/gpt-6.1-sol.md, read 2026-10-10): $2 input / $0.10 cached input\n // (5% of input) / $2.50 cache write / $10 output, over a 1,050,000-token window with text\n // and image input. As on gpt-6-astra below, cache_write carries the published cache-write\n // price; a prompt above 272K tokens pays 2x input and cache and 1.5x output for the whole\n // request, a tier this row does not record.\n modelId: \"gpt-6.1-sol\",\n displayName: \"GPT-6.1 Sol\",\n provider: \"openai\",\n contextWindow: 1050000,\n pricing: usd(0.1, 2.5, 10),\n supportsVision: true,\n },\n {\n // OpenAI's list price (developers.openai.com/api/docs/models/gpt-6-astra, read\n // 2026-09-09) is $10 input / $1 cached input / $12.5 cache write / $50 output. Per the\n // bucket convention at the top of this file, cache_write carries the published\n // cache-write price of 12.5; the $10 rate applies only to input that is not written to\n // cache, a split the three buckets do not express. Every rate doubles above 272K input\n // tokens (output 1.5x) — the base tier is what this row records, as the header says.\n modelId: \"gpt-6-astra\",\n displayName: \"GPT-6 Astra\",\n provider: \"openai\",\n contextWindow: 1050000,\n pricing: usd(1, 12.5, 50),\n supportsVision: true,\n },\n {\n // https://developers.openai.com/api/docs/models/gpt-6-luna (2026-10-14).\n // Base tier: above 272K input, input/cache rates double and output is 1.5x.\n modelId: \"gpt-6-luna\",\n displayName: \"GPT-6 Luna\",\n provider: \"openai\",\n contextWindow: 1050000,\n pricing: usd(0.01, 0.125, 0.5),\n supportsVision: true,\n },\n {\n // The bare gpt-5.6 id routes to gpt-5.6-sol upstream and is priced as that tier, so the\n // row names the Sol codename its siblings and the openai/gpt-5.6-sol row already show —\n // the id stays bare, only the label says which variant this is. This row and the two\n // gpt-5.6 rows below mirror the\n // openai/gpt-5.6-* OpenRouter rows above, which carry the gateway's (currently\n // discounted) rates instead of this list price.\n modelId: \"gpt-5.6\",\n displayName: \"GPT-5.6 Sol\",\n provider: \"openai\",\n contextWindow: 1050000,\n pricing: usd(0.5, 5, 30),\n supportsVision: true,\n },\n {\n modelId: \"gpt-5.6-luna\",\n displayName: \"GPT-5.6 Luna\",\n provider: \"openai\",\n contextWindow: 1050000,\n pricing: usd(0.02, 0.2, 1.2),\n supportsVision: true,\n },\n {\n modelId: \"gpt-5.6-terra\",\n displayName: \"GPT-5.6 Terra\",\n provider: \"openai\",\n contextWindow: 1050000,\n pricing: usd(0.2, 2, 12),\n supportsVision: true,\n },\n {\n modelId: \"gpt-5.5\",\n displayName: \"GPT-5.5\",\n provider: \"openai\",\n contextWindow: 1050000,\n pricing: usd(0.5, 5, 30),\n supportsVision: true,\n },\n {\n // No official cache discount: cache_read uses the standard input price.\n modelId: \"gpt-5.5-pro\",\n displayName: \"GPT-5.5 Pro\",\n provider: \"openai\",\n contextWindow: 1050000,\n pricing: usd(30, 30, 180),\n supportsVision: true,\n },\n {\n modelId: \"gpt-5.4\",\n displayName: \"GPT-5.4\",\n provider: \"openai\",\n contextWindow: 1050000,\n pricing: usd(0.25, 2.5, 15),\n supportsVision: true,\n },\n {\n modelId: \"gpt-5.4-mini\",\n displayName: \"GPT-5.4 mini\",\n provider: \"openai\",\n contextWindow: 400000,\n pricing: usd(0.075, 0.75, 4.5),\n supportsVision: true,\n },\n {\n modelId: \"gpt-5.4-nano\",\n displayName: \"GPT-5.4 nano\",\n provider: \"openai\",\n contextWindow: 400000,\n pricing: usd(0.02, 0.2, 1.25),\n supportsVision: true,\n },\n {\n // No official cache discount: cache_read uses the standard input price.\n modelId: \"gpt-5.4-pro\",\n displayName: \"GPT-5.4 Pro\",\n provider: \"openai\",\n contextWindow: 1050000,\n pricing: usd(30, 30, 180),\n supportsVision: true,\n },\n // -- Z.AI (GLM) --\n {\n // Announced 2026-08-14. Z.AI's price\n // list (docs.z.ai/guides/overview/pricing, read 2026-08-18) publishes the same USD rates\n // as glm-5.2 / glm-5.1.\n modelId: \"glm-5.3\",\n displayName: \"GLM-5.3\",\n provider: \"zhipu\",\n contextWindow: 1000000,\n pricing: usd(0.26, 1.4, 4.4),\n supportsVision: false,\n },\n {\n // Z.AI's price list (docs.z.ai/guides/overview/pricing) publishes $0.15 input / $0.03\n // cached input / $0.50 output; a 50% promotion halved all three through 24:00 on\n // 2026-09-09 (UTC+8). Direct-vendor rows record the vendor's list price, so that is what\n // is stored here — the OpenRouter z-ai/glm-5.3-flash row above carries the rate its\n // default endpoint bills, which runs a promotion of its own.\n //\n // The model is natively multimodal (docs.z.ai/guides/vlm/glm-5.3-flash: images, video\n // and files), and it is the one GLM id whose images MMSP's Z.AI client forwards — as\n // image_url parts, in a prompt and in a tool result alike. Every other GLM id refuses\n // one outright (\"GLM <id> does not support image inputs.\"), which is why the rest of\n // this group is vision-off.\n modelId: \"glm-5.3-flash\",\n displayName: \"GLM-5.3 Flash\",\n provider: \"zhipu\",\n contextWindow: 1000000,\n pricing: usd(0.03, 0.15, 0.5),\n supportsVision: true,\n },\n {\n modelId: \"glm-5.2\",\n displayName: \"GLM-5.2\",\n provider: \"zhipu\",\n contextWindow: 1000000,\n pricing: usd(0.26, 1.4, 4.4),\n supportsVision: false,\n },\n {\n modelId: \"glm-5.1\",\n displayName: \"GLM-5.1\",\n provider: \"zhipu\",\n contextWindow: 200000,\n pricing: usd(0.26, 1.4, 4.4),\n supportsVision: false,\n },\n {\n modelId: \"glm-5\",\n displayName: \"GLM-5\",\n provider: \"zhipu\",\n contextWindow: 200000,\n pricing: usd(0.2, 1, 3.2),\n supportsVision: false,\n },\n // -- Moonshot (Kimi) (official CNY pricing) --\n {\n // Moonshot's list (pricing page, read 2026-10-23 for MMSP 0.5.6's registry): CNY 13 input /\n // 68 output / 1.3 cache hit over a 1,048,576-token window, image input. The default\n // five-minute cache write bills at the input price, which is what cache_write stores; the\n // one-hour write, which only MMSP's `prompt_caching` enhance asks for, bills twice that.\n modelId: \"kimi-k3.1-pro\",\n displayName: \"Kimi K3.1 Pro\",\n provider: \"moonshot\",\n contextWindow: 1048576,\n pricing: cny(1.3, 13, 68),\n supportsVision: true,\n },\n {\n // The same model at two to three times the output speed (Moonshot's model list), at twice\n // the input, output and cache-write prices and the same cache hit: CNY 26 / 136 / 1.3.\n // Moonshot's vision guide names only kimi-k3.1-pro, but its model list files both ids under\n // multimodal models, and MMSP's live probe read a base64 image through this one.\n modelId: \"kimi-k3.1-pro-highspeed\",\n displayName: \"Kimi K3.1 Pro Highspeed\",\n provider: \"moonshot\",\n contextWindow: 1048576,\n pricing: cny(1.3, 26, 136),\n supportsVision: true,\n },\n {\n modelId: \"kimi-k3\",\n displayName: \"Kimi K3\",\n provider: \"moonshot\",\n contextWindow: 1048576,\n pricing: cny(2, 20, 100),\n supportsVision: true,\n },\n {\n modelId: \"kimi-k2.6\",\n displayName: \"Kimi K2.6\",\n provider: \"moonshot\",\n contextWindow: 262144,\n pricing: cny(1.1, 6.5, 27),\n supportsVision: true,\n },\n {\n modelId: \"kimi-k2.5\",\n displayName: \"Kimi K2.5\",\n provider: \"moonshot\",\n contextWindow: 262144,\n pricing: cny(0.7, 4, 21),\n supportsVision: true,\n },\n // -- vLLM (self-hosted: the models MMSP's openai-chat-vllm-adapter client carries a\n // per-model thinking switch for, as published at recipes.vllm.ai — read 2026-09-03).\n //\n // Every row prices at zero, and omits two other things, all because the user runs the server:\n // - **zero pricing**. There is no seller charging per token: what the deployment costs is\n // the operator's own hardware, which no catalog rate could express. Three zero buckets are\n // the same genuine $0 tier the `:free` gateway rows carry, so these models show the free\n // badge and contribute 0 to the cost center rather than the \"unpriced\" mark — which is the\n // truthful reading of a self-hosted endpoint that bills nobody.\n // - **the local server's base URL** (VLLM_LOCAL_BASE_URL), where `vllm serve` answers when\n // it runs on the same machine with its default port. A new Project stores it once, on the\n // group's table; a deployment elsewhere changes the group's base URL.\n // - **no auto-routing**. Each row pins openai-chat-vllm-adapter explicitly, and the pin is\n // load-bearing twice over: `Qwen/*` begins with no family AutoLLMClient knows and would\n // be rejected outright, while `deepseek-ai/DeepSeek-V4-*` begins with \"deepseek-\" and\n // would reach DeepSeek's official Responses client — pointed at a vLLM server.\n //\n // contextWindow is the recipe's NATIVE length, which is the most a deployment can serve\n // without reconfiguration; an operator may serve less (`--max-model-len` below the native\n // limit) or, for the Qwen rows, far more with YaRN rope scaling. The catalog cannot know\n // which, and it derives the compaction thresholds from this number, so the honest default\n // is the checkpoint's own figure — an entry without one would be assumed to be 128000.\n // The DeepSeek rows additionally document `--max-model-len >= 393216` as the floor for\n // their top reasoning levels, which is well inside the window recorded here.\n {\n modelId: \"deepseek-ai/DeepSeek-V4-Flash\",\n displayName: \"DeepSeek V4 Flash\",\n provider: \"vllm\",\n contextWindow: 1000000,\n pricing: usd(0, 0, 0),\n supportsVision: false,\n clientType: VLLM_CLIENT_TYPE,\n baseUrl: VLLM_LOCAL_BASE_URL,\n },\n {\n // The experimental vision revision: DeepSeek's first multimodal V4, a ViT tower on the\n // same language backbone. Its recipe verifies a 32K deployment and notes the 1M the\n // checkpoint advertises was not what was measured; the window below is the checkpoint's,\n // matching every other DeepSeek V4 row in this catalog.\n modelId: \"deepseek-ai/DeepSeek-V4-Flash-Vision-Exp\",\n displayName: \"DeepSeek V4 Flash Vision Exp\",\n provider: \"vllm\",\n contextWindow: 1000000,\n pricing: usd(0, 0, 0),\n supportsVision: true,\n clientType: VLLM_CLIENT_TYPE,\n baseUrl: VLLM_LOCAL_BASE_URL,\n },\n {\n modelId: \"deepseek-ai/DeepSeek-V4-Pro\",\n displayName: \"DeepSeek V4 Pro\",\n provider: \"vllm\",\n contextWindow: 1000000,\n pricing: usd(0, 0, 0),\n supportsVision: false,\n clientType: VLLM_CLIENT_TYPE,\n baseUrl: VLLM_LOCAL_BASE_URL,\n },\n {\n modelId: \"Qwen/Qwen3.5-0.8B\",\n displayName: \"Qwen 3.5 0.8B\",\n provider: \"vllm\",\n contextWindow: 262144,\n pricing: usd(0, 0, 0),\n supportsVision: true,\n clientType: VLLM_CLIENT_TYPE,\n baseUrl: VLLM_LOCAL_BASE_URL,\n },\n {\n modelId: \"Qwen/Qwen3.5-9B\",\n displayName: \"Qwen 3.5 9B\",\n provider: \"vllm\",\n contextWindow: 262144,\n pricing: usd(0, 0, 0),\n supportsVision: true,\n clientType: VLLM_CLIENT_TYPE,\n baseUrl: VLLM_LOCAL_BASE_URL,\n },\n {\n modelId: \"Qwen/Qwen3.6-35B-A3B\",\n displayName: \"Qwen 3.6 35B A3B\",\n provider: \"vllm\",\n contextWindow: 262144,\n pricing: usd(0, 0, 0),\n supportsVision: true,\n clientType: VLLM_CLIENT_TYPE,\n baseUrl: VLLM_LOCAL_BASE_URL,\n },\n {\n modelId: \"Qwen/Qwen3.8-27B\",\n displayName: \"Qwen 3.8 27B\",\n provider: \"vllm\",\n contextWindow: 262144,\n pricing: usd(0, 0, 0),\n supportsVision: true,\n clientType: VLLM_CLIENT_TYPE,\n baseUrl: VLLM_LOCAL_BASE_URL,\n },\n {\n modelId: \"Qwen/Qwen3.8-Flash-Next\",\n displayName: \"Qwen 3.8 Flash Next\",\n provider: \"vllm\",\n contextWindow: 262144,\n pricing: usd(0, 0, 0),\n supportsVision: true,\n clientType: VLLM_CLIENT_TYPE,\n baseUrl: VLLM_LOCAL_BASE_URL,\n },\n // -- Custom (the group that otherwise holds only user-defined models). A preset may live\n // here only as a complete row — its own base URL and a pinned generic protocol — because the\n // group implies neither; it is where a vendor with a single preview model and no console\n // of its own goes rather than opening a group for it. Atria Dawn: the Anthropic\n // Messages API at api.atria-asi.ai (the client appends /v1/messages, so the base URL carries\n // no /v1; the endpoint also serves Chat Completions and Responses, but its Responses side\n // rejects the replayed assistant turn of a multi-turn conversation), a 256K window (262144 —\n // the API caps max_output_tokens at that minus the input), text only (the endpoint rejects\n // image input), and no published price yet, so the row records $0 until the vendor prices\n // it. Read 2026-09-15 from api.atria-asi.ai/docs.\n {\n modelId: \"Atria-Dawn\",\n displayName: \"Atria Dawn\",\n provider: \"custom\",\n contextWindow: 262144,\n pricing: usd(0, 0, 0),\n supportsVision: false,\n clientType: \"ant-messages\",\n baseUrl: \"https://api.atria-asi.ai\",\n },\n];\n\n/** Looks up a catalog entry by (provider, upstream id) pair (**the sole catalog-matching entry point**); returns undefined if not in the catalog. */\nexport function catalogEntryFor(\n provider: string,\n upstreamId: string,\n): ModelCatalogEntry | undefined {\n return MODEL_CATALOG.find((m) => m.provider === provider && m.modelId === upstreamId);\n}\n\n/** Looks up provider info by provider id; returns undefined for an unknown id. */\nexport function providerInfo(providerId: string): ModelProviderInfo | undefined {\n return MODEL_PROVIDERS.find((p) => p.id === providerId);\n}\n\n/**\n * The protocol a group pins on every one of its entries (ModelProviderInfo.clientType), or\n * undefined when the group pins none — an unknown id (a user-defined group) included.\n *\n * Five groups pin: vLLM, whose models are served by the user's own vLLM adapter,\n * OpenRouter, whose models all speak the Responses API OpenRouter serves at its preset base\n * URL, and TokenDance, SiliconFlow and Atlas Cloud, whose models all speak Chat Completions.\n *\n * A reference value, read when a file is written from the catalog (catalogGroupConnection:\n * a new Project, \"Add new models\" for a group new to the file, \"Restore defaults\") and by\n * nothing that builds or judges a request: at runtime a group's protocol is its\n * `[providers.<id>]` table's.\n */\nexport function providerClientType(providerId: string): string | undefined {\n return providerInfo(providerId)?.clientType;\n}\n\n/**\n * A first-party vendor group: one this catalog knows, that is not `custom`, carries no\n * gateway endpoint and pins no protocol of its own — DeepSeek, Google, OpenAI, Anthropic,\n * Z.AI, Moonshot, MiniMax, and the Penguin Go relay.\n *\n * What distinguishes it is that nothing in it decides a protocol: its entries persist no\n * `client_type`, so MMSP places every one of them by the spelling of the upstream model\n * id alone — the vendor family it begins with. An id of no known family cannot be started at\n * all, whatever else is configured on the entry (the Penguin Go rows pin their protocol\n * instead: the relay serves Gemini through generateContent, not the API a `gemini-` id routes\n * to). Every\n * surface that has to answer \"is this one routable?\" reads the group's shape through this one\n * predicate rather than re-deriving it: the models page's cards and its config dialog, the\n * models PUT, and the CLI's `config model add`. Whether a model may be added to the group at\n * all is a separate, wider rule: isAddableGroup.\n *\n * Every other group answers the protocol question by itself and therefore routes any id the\n * endpoint serves: `custom` and user-defined groups detect or pick it, and a gateway's or\n * vLLM's rows speak the protocol their group's `[providers.<id>]` table or the row itself\n * stores (a new Project writes it there).\n */\nexport function isVendorGroup(providerId: string): boolean {\n const info = providerInfo(providerId);\n return (\n info !== undefined &&\n info.id !== \"custom\" &&\n info.gatewayBaseUrl === undefined &&\n info.clientType === undefined\n );\n}\n\n/**\n * Whether this entry would be written into a vendor group with an id MMSP cannot place —\n * the configuration that produces `No client for model \"<id>\": its family is not known` on\n * the first request, and nothing before it.\n *\n * MMSP's `routedClientType` is the authority: AutoLLMClient routes through it, and it returns\n * null on exactly the entries that client rejects. A blank id is not a routing failure — the\n * entry is still being typed, and the required-field validation is what has something to say\n * about it.\n */\nexport function unroutableVendorModel(\n provider: string,\n modelId: string,\n clientType?: string,\n): boolean {\n const id = modelId.trim();\n if (id === \"\" || !isVendorGroup(provider)) return false;\n // A blank pin is none, which routes by the id.\n return routedClientType(id, clientType?.trim() ? clientType : null) === null;\n}\n\n/**\n * The official MMSP client a first-party vendor group's unpinned rows route to: the vendor's\n * own, the official client that reads the variable the group records (`envKey`; MMSP's\n * credentials module). Undefined for every other group, whose protocol its table or its rows\n * decide.\n */\nexport function vendorClientType(providerId: string): string | undefined {\n if (!isVendorGroup(providerId)) return undefined;\n const envKey = providerInfo(providerId)?.envKey;\n return OFFICIAL_CLIENT_TYPES.find((t) => CLIENT_CREDENTIALS[t]?.apiKeyEnv === envKey);\n}\n\n/**\n * Whether models may be added to this group by hand: `custom`, vLLM, OpenRouter, TokenDance,\n * SiliconFlow, Atlas Cloud (ModelProviderInfo.addable) and every user-defined group, i.e. an\n * id this catalog does not know. Every other built-in group — the first-party vendors and the\n * other gateways — carries its catalog presets and the rows it already stores: the models page\n * offers no add-model entry point there, and the models PUT and the CLI's `config model add`\n * refuse a new row that is not a preset (unaddableModel).\n */\nexport function isAddableGroup(providerId: string): boolean {\n const info = providerInfo(providerId);\n return info === undefined || info.addable === true;\n}\n\n/**\n * Whether writing this pair as a NEW row of its group would add a model by hand where the group\n * takes none: a group isAddableGroup refuses, and a `(provider, model_id)` pair that is not one\n * of the catalog's rows for it. A preset passes, so \"Sync presets\" can put a deleted one back;\n * a row the table already stores is not a new one, and the callers never ask about it.\n */\nexport function unaddableModel(provider: string, modelId: string): boolean {\n return !isAddableGroup(provider) && catalogEntryFor(provider, modelId.trim()) === undefined;\n}\n\n/**\n * The price usage on a model is costed at when the Project no longer stores the model's row:\n * the catalog's list `pricing` of a row that is or was the default of new Projects\n * (ModelCatalogEntry.wasDefault), and undefined for every other pair — a row the Project does\n * store is priced from the file, never from here. No promotion applies: a Project's promotion\n * goes with its row. An off-peak schedule still does, since this is the catalog's own peak price.\n */\nexport function retainedCatalogPricing(\n provider: string,\n modelId: string,\n): ModelPricing | undefined {\n const entry = catalogEntryFor(provider, modelId);\n return entry?.wasDefault === true ? entry.pricing : undefined;\n}\n\n/**\n * The model's own homepage/detail page for the frontend's model-card link. Gateway groups\n * have a stable per-model URL pattern (works for user-added ids in those groups too);\n * direct-vendor models link to the vendor's model list/docs page; custom and user-defined\n * groups have no page to vouch for.\n */\nexport function modelHomepageUrl(provider: string, modelId: string): string | undefined {\n if (provider === \"openrouter\") return `https://openrouter.ai/${modelId}`;\n if (provider === \"qwen-token-plan\") {\n return `https://www.qianwenai.com/models/${modelId}`;\n }\n if (provider === \"fireworks\") {\n // API id \"accounts/<owner>/models/<slug>\" -> page \"app.fireworks.ai/models/<owner>/<slug>\";\n // nonconforming (user-added) ids fall back to the models listing.\n const m = /^accounts\\/([^/]+)\\/models\\/(.+)$/.exec(modelId);\n return m\n ? `https://app.fireworks.ai/models/${m[1]}/${m[2]}`\n : providerInfo(provider)?.modelsUrl;\n }\n if (provider === \"tokendance\") return `https://tokendance.space/models/${modelId}`;\n if (provider === \"qwen-pay-as-you-go\") {\n return `https://www.qianwenai.com/models/${encodeURIComponent(modelId)}`;\n }\n if (provider === \"zhipu\") {\n // Z.AI's per-model guide pages use the bare model id as the slug.\n return `https://docs.z.ai/guides/llm/${modelId}`;\n }\n if (provider === \"moonshot\") {\n // Moonshot's pricing pages: kimi-k2.6 -> chat-k26 (dot dropped); other ids fall back.\n const m = /^kimi-k(\\d+)\\.(\\d+)$/.exec(modelId);\n return m\n ? `https://platform.kimi.com/docs/pricing/chat-k${m[1]}${m[2]}`\n : providerInfo(provider)?.modelsUrl;\n }\n if (provider === \"vllm\") {\n // recipes.vllm.ai has a page per model vLLM published a recipe for, which is exactly what\n // this group presets; an id the user serves themselves has no page, so it gets the index.\n return catalogEntryFor(provider, modelId) !== undefined\n ? `https://recipes.vllm.ai/${modelId}`\n : providerInfo(provider)?.modelsUrl;\n }\n if (provider === \"custom\") return undefined;\n return providerInfo(provider)?.modelsUrl;\n}\n","/**\n * The environment variables a model reads, and where its requests go while no base URL is set, as\n * the UI presents them (PRN-021). The rule is MMSP's\n * alone: its credentials module (`environmentCredential`) says what a client handed no key does\n * with the base URL it is handed, and the harness keeps no copy of it. This names the variables\n * for the server's `GET /models` preview, the machine sync's report, the web dialogs' hints, the\n * CLI's list, protocol detection and the balance query, so none of them can disagree with what a\n * Session's client does.\n */\nimport {\n CLIENT_CREDENTIALS,\n environmentCredential,\n routedClientType,\n} from \"@prismshadow/mmsp/credentials\";\nimport { effectiveConnection } from \"@prismshadow/penguin-core/model-connection\";\nimport type {\n ModelCredentialShape,\n ProviderConnectionShape,\n} from \"@prismshadow/penguin-core/model-connection\";\nimport { providerInfo, vendorClientType } from \"./catalog.js\";\n\n/**\n * The variable MMSP's client of this type reads its key from when handed none at this base URL\n * (environmentCredential), or undefined: the client refuses that URL, calls it keyless, or is\n * not one MMSP has. With no base URL it is always the client's own `*_API_KEY`.\n */\nexport function clientEnvKey(clientType: string, baseUrl: string | undefined): string | undefined {\n const credential = environmentCredential(clientType, baseUrl?.trim() || undefined);\n return credential?.kind === \"env\" ? credential.apiKeyEnv : undefined;\n}\n\n/**\n * Whether MMSP's client of this type, handed no key at this base URL and with the variable it\n * would read unset, calls the endpoint without a key. `environmentCredential` says so outright\n * for an open server's client (`mmsp`, `openai-chat-vllm-adapter`) handed any base URL; handed\n * none, such a client reads its `*_API_KEY` and, finding it unset, calls keyless too. vLLM's\n * client then sends vLLM's placeholder key `EMPTY`.\n */\nfunction calledKeyless(clientType: string, baseUrl: string | undefined): boolean {\n const credential = environmentCredential(clientType, baseUrl?.trim() || undefined);\n if (credential?.kind === \"keyless\") return true;\n if (credential?.kind !== \"env\") return false;\n const routed = routedClientType(\"\", clientType);\n return routed !== null && CLIENT_CREDENTIALS[routed]?.openServer === true;\n}\n\n/**\n * A group whose key comes from a sign-in flow (the catalog's `bridgeAuth`: Penguin Go's relay)\n * serves an endpoint that takes no call without that key, whatever its client would do.\n */\nfunction signInKeyed(providerId: string): boolean {\n return providerInfo(providerId)?.bridgeAuth !== undefined;\n}\n\n/** The variables MMSP's routed client reads for a row as configured (see modelEnvironment). */\nexport interface ModelEnvironment {\n /** The key's variable: only for a row with no key in the file. */\n apiKeyEnv?: string;\n /** The endpoint's variable: only for a row with no base URL in the file. */\n baseUrlEnv?: string;\n /**\n * Where that row's requests go while `baseUrlEnv` is unset: the routed client's default\n * endpoint, as MMSP's credentials table records it. Present exactly when `baseUrlEnv` is.\n */\n defaultBaseUrl?: string;\n}\n\n/**\n * What a row takes from the environment, as MMSP decides it (PRN-021). The row's effective\n * connection (core's effectiveConnection) picks the client MMSP routes it to (`routedClientType`)\n * and the base URL that client is handed; `environmentCredential` then says what the client\n * reads. With no key in the file it reads its `*_API_KEY` only for no base URL or its own default\n * endpoint, and with no base URL in the file it goes where its `*_BASE_URL` points, key or not.\n * A row MMSP refuses (no key and another base URL), an open MMSP server and a row nothing routes\n * read nothing. With no base URL in the file the row also names the endpoint its requests go to\n * while that variable is unset (`defaultBaseUrl`). `entry` is the row's OWN values, key\n * included, and `group` its `[providers.<id>]` table.\n */\nexport function modelEnvironment(\n entry: ModelCredentialShape & { apiKey?: string | undefined },\n group: ProviderConnectionShape | undefined,\n): ModelEnvironment {\n const effective = effectiveConnection(entry, group);\n const routed = routedClientType(entry.modelId, effective.clientType ?? null);\n if (routed === null) return {};\n const credential = environmentCredential(routed, effective.baseUrl);\n if (credential?.kind !== \"env\") return {};\n const defaultBaseUrl = CLIENT_CREDENTIALS[routed]?.defaultBaseUrl;\n return {\n ...(effective.apiKey === undefined ? { apiKeyEnv: credential.apiKeyEnv } : {}),\n ...(credential.baseUrlEnv !== null\n ? {\n baseUrlEnv: credential.baseUrlEnv,\n ...(defaultBaseUrl !== undefined ? { defaultBaseUrl } : {}),\n }\n : {}),\n };\n}\n\n/**\n * The variable a row with no key in the file authenticates with, or undefined: modelEnvironment's\n * `apiKeyEnv`. The server's `GET /models` preview, the web dialog's hint and the CLI's list read\n * this, so none of them can disagree with what a Session does.\n */\nexport function modelEnvPreviewKey(\n entry: ModelCredentialShape & { apiKey?: string | undefined },\n group: ProviderConnectionShape | undefined,\n): string | undefined {\n return modelEnvironment(entry, group).apiKeyEnv;\n}\n\n/**\n * MMSP's client for a group as a whole: the group protocol's when it names one, else, for a\n * first-party vendor group, the vendor's (vendorClientType). Undefined for a gateway, custom,\n * vLLM or user-defined group with no protocol, whose rows route by id.\n */\nfunction groupClientType(\n providerId: string,\n group: Pick<ProviderConnectionShape, \"clientType\"> | undefined,\n): string | undefined {\n const pinned = group?.clientType?.trim() ? group.clientType : undefined;\n return pinned ?? vendorClientType(providerId);\n}\n\n/**\n * The variable a group's settings may present as covering a blank group key, or undefined —\n * the group dialog's hint: what MMSP's client for the group (groupClientType) reads when handed\n * no key at the group's base URL (clientEnvKey). A group with no one client names nothing.\n */\nexport function providerEnvFallbackKey(\n providerId: string,\n group: Pick<ProviderConnectionShape, \"baseUrl\" | \"clientType\"> | undefined,\n): string | undefined {\n const clientType = groupClientType(providerId, group);\n return clientType === undefined ? undefined : clientEnvKey(clientType, group?.baseUrl);\n}\n\n/**\n * Whether a group with no key, and its client's variable unset, has its rows called without a\n * key — the group dialog's \"send no key\" hint: MMSP's client for the group (groupClientType) at\n * the group's base URL calls it keyless (calledKeyless). A group with no one client, and one\n * keyed by a sign-in flow, answers no.\n */\nexport function providerCalledKeyless(\n providerId: string,\n group: Pick<ProviderConnectionShape, \"baseUrl\" | \"clientType\"> | undefined,\n): boolean {\n if (signInKeyed(providerId)) return false;\n const clientType = groupClientType(providerId, group);\n return clientType !== undefined && calledKeyless(clientType, group?.baseUrl);\n}\n\n/**\n * Whether a row with no key of its own or its group's, and its client's variable unset, is\n * called without a key — the model dialog's \"send no key\" hint: its routed client at its\n * effective base URL calls it keyless (calledKeyless). A row of a sign-in-keyed group, and one\n * nothing routes, answers no. `entry` is the row's OWN values, and `group` its table.\n */\nexport function modelCalledKeyless(\n entry: ModelCredentialShape & { apiKey?: string | undefined },\n group: ProviderConnectionShape | undefined,\n): boolean {\n if (signInKeyed(entry.provider)) return false;\n const effective = effectiveConnection(entry, group);\n if (effective.apiKey !== undefined) return false;\n const routed = routedClientType(entry.modelId, effective.clientType ?? null);\n return routed !== null && calledKeyless(routed, effective.baseUrl);\n}\n","/**\n * The catalog as a Project config seeds it: each built-in group's `[providers.<id>]` table, the\n * preset rows (storing a protocol or endpoint only where it differs from the table beside it),\n * the default model and the flat promotions — what the server writes when a Project is created,\n * on \"Add new models\" and on \"Restore defaults\". Reference values: nothing reads them when a\n * request is built.\n */\nimport type { ModelEntry, ModelRef, ProviderTable } from \"@prismshadow/penguin-core\";\nimport {\n canonicalClientType,\n sameClientType,\n sameEndpoint,\n} from \"@prismshadow/penguin-core/model-connection\";\nimport { MODEL_CATALOG, MODEL_PROVIDERS, providerClientType, providerInfo } from \"./catalog.js\";\nimport type { ModelCatalogEntry } from \"./catalog.js\";\n\n/**\n * The value every one of `values` holds, by `same`, or undefined when one lacks it, two\n * differ, or there are none.\n */\nfunction sharedValue(\n values: readonly (string | undefined)[],\n same: (a: string, b: string) => boolean,\n): string | undefined {\n const first = values[0];\n if (first === undefined) return undefined;\n return values.every((v) => v !== undefined && same(v, first)) ? first : undefined;\n}\n\n/**\n * The connection the catalog gives a built-in group when a file is written from it — a new\n * Project, \"Add new models\" for a group new to the file, \"Restore defaults\": its gateway\n * endpoint (`gatewayBaseUrl`, else the one base URL every catalog row of the group carries)\n * and its one protocol (the group's pin, providerClientType, else the one pin every catalog\n * row of the group carries; canonical spelling). Retired rows count: the Projects that still\n * carry one store its difference from the same table.\n *\n * Undefined for `custom` (it holds the user's own endpoints), for an id the catalog does not\n * know, and for a group with neither — the first-party vendors, whose rows go to the\n * client's defaults, so their keyless rows are handed no key and MMSP's client reads the\n * vendor's environment variable (PRN-021). A reference value: nothing reads it when a request\n * is built.\n */\nexport function catalogGroupConnection(\n providerId: string,\n): { base_url?: string; client_type?: string } | undefined {\n const info = providerInfo(providerId);\n if (info === undefined || info.id === \"custom\") return undefined;\n const rows = MODEL_CATALOG.filter((m) => m.provider === providerId);\n const baseUrl =\n info.gatewayBaseUrl ??\n sharedValue(\n rows.map((m) => m.baseUrl),\n sameEndpoint,\n );\n const clientType = canonicalClientType(\n providerClientType(providerId) ??\n sharedValue(\n rows.map((m) => m.clientType),\n sameClientType,\n ),\n );\n if (baseUrl === undefined && clientType === undefined) return undefined;\n return {\n ...(baseUrl !== undefined ? { base_url: baseUrl } : {}),\n ...(clientType !== undefined ? { client_type: clientType } : {}),\n };\n}\n\n/**\n * The default model of a new Project: DeepSeek V4.1 Flash, which the vendor serves under the\n * bare name `deepseek-flash` — the current generation of the Flash series, at the same price\n * and schedule as the V4 rows it replaces, and it reads images, so a new Project can take a\n * pasted screenshot without anyone having to notice why it could not. The bare id begins with\n * the `deepseek-` family, so MMSP routes it to DeepSeek's official client without a pin. A\n * Project's default is copied in at creation (the server's seed, and \"Restore defaults\") and\n * owned by it from then on, so this reaches new Projects alone; an existing one keeps whatever\n * it stored, and \"Add new models\" never touches the stored default. Its catalog row carries\n * `wasDefault`, as every former default's does.\n */\nexport const PRESET_DEFAULT_MODEL: Readonly<ModelRef> = {\n provider: \"deepseek\",\n model_id: \"deepseek-flash\",\n};\n\n/**\n * `[providers.<id>]` for every built-in group with a catalogGroupConnection, in the catalog's\n * group order — what a new Project's file stores beside presetModelEntries' rows. A fresh\n * object on every call, so a caller may change it.\n */\nexport function presetProviderTable(): ProviderTable {\n const table: ProviderTable = {};\n for (const p of MODEL_PROVIDERS) {\n const connection = catalogGroupConnection(p.id);\n if (connection !== undefined) table[p.id] = connection;\n }\n return table;\n}\n\n/**\n * Catalog -> preset ModelEntry list (what the server seeds a new Project with and what\n * \"Add new models\" and \"Restore defaults\" write, avoiding duplicate hand-written copies). `provider` and `model_id` are persisted as\n * separate fields (`model_id` is the plain upstream id). The facts a row stores are the\n * context window, the price and `vision = false`, plus the row's protocol and endpoint where\n * they differ from its group's table in `groups` (catalogModelEntry): beside those tables, the\n * file alone says where every request goes, and nothing is left for a resolver to fill from\n * the catalog. `groups` is the `[providers]` table the rows will sit beside — a new Project's\n * (presetProviderTable, the default), or the file's own when \"Add new models\" adds rows to an\n * existing Project, so each added row resolves to its catalog connection whatever the user\n * has set on its group. No secrets are included, so only an API key is needed.\n *\n * Pricing is written as the LIST price the catalog records (a scheduled row's PEAK price),\n * never a discounted number. What is on disk then stays true whatever promotion is live and\n * whatever hour the Project is created or re-synced in: a flat promotion is stored beside the\n * file as a per-Project fraction (presetPromotions), and both it and an off-peak tier are\n * applied when the price is read, by the models page and by the cost center alike.\n */\nexport function presetModelEntries(groups: ProviderTable = presetProviderTable()): ModelEntry[] {\n const catalog = presetProviderTable();\n // A retired row stays in the catalog for the Projects that still carry it, and only for them.\n return MODEL_CATALOG.filter((m) => m.retired !== true).map((m) =>\n catalogModelEntry(m, catalog, groups),\n );\n}\n\n/**\n * Every catalog row as a ModelEntry, retired rows included, in the shape presetModelEntries\n * writes: what a Project carrying a retired row stores for it beside a new Project's group\n * tables (see ModelCatalogEntry.retired). `groups` as in presetModelEntries.\n */\nexport function catalogModelEntries(groups: ProviderTable = presetProviderTable()): ModelEntry[] {\n const catalog = presetProviderTable();\n return MODEL_CATALOG.map((m) => catalogModelEntry(m, catalog, groups));\n}\n\n/**\n * One catalog row as the ModelEntry a Project stores (see presetModelEntries): its facts, and\n * `client_type` / `base_url` exactly where the row's catalog connection — per field, the\n * row's own catalog value, else its group's (`catalog`, presetProviderTable) — differs from\n * the table it will sit beside (`groups`): canonical client types compared, endpoints by\n * sameEndpoint, a blank table field counting as absent. A row whose group's table carries the\n * same value stores none and follows the table; a row whose group has no table (custom's\n * Atria) stores its own.\n */\nfunction catalogModelEntry(\n m: ModelCatalogEntry,\n catalog: ProviderTable,\n groups: ProviderTable,\n): ModelEntry {\n const group = groups[m.provider];\n const clientType = canonicalClientType(m.clientType ?? catalog[m.provider]?.client_type);\n const groupClientType = group?.client_type?.trim() || undefined;\n const ownClientType =\n clientType !== undefined &&\n (groupClientType === undefined || !sameClientType(clientType, groupClientType))\n ? clientType\n : undefined;\n const baseUrl = m.baseUrl ?? catalog[m.provider]?.base_url;\n const groupBaseUrl = group?.base_url?.trim() || undefined;\n const ownBaseUrl =\n baseUrl !== undefined && (groupBaseUrl === undefined || !sameEndpoint(baseUrl, groupBaseUrl))\n ? baseUrl\n : undefined;\n return {\n provider: m.provider,\n model_id: m.modelId,\n ...(m.contextWindow !== undefined ? { context_window: m.contextWindow } : {}),\n ...(ownClientType !== undefined ? { client_type: ownClientType } : {}),\n ...(m.pricing ? { pricing: { ...m.pricing } } : {}),\n // ModelEntry.vision defaults to supported: only models that don't support images\n // explicitly persist false (drives read_file's hand-off of images to the vision model and input\n // image hand-off, see project-config.ts).\n ...(m.supportsVision ? {} : { vision: false }),\n ...(ownBaseUrl !== undefined ? { base_url: ownBaseUrl } : {}),\n };\n}\n\n/**\n * The catalog's flat promotions, as a new Project is seeded with them: every row whose `discount`\n * is a fraction in (0, 1). A retired row is skipped like it is in presetModelEntries: a new\n * Project never carries it, so there is nothing for its promotion to apply to.\n */\nexport function presetPromotions(): Array<{ provider: string; modelId: string; discount: number }> {\n return MODEL_CATALOG.flatMap((m) =>\n m.retired !== true && m.discount !== undefined && m.discount > 0 && m.discount < 1\n ? [{ provider: m.provider, modelId: m.modelId, discount: m.discount }]\n : [],\n );\n}\n"],"mappings":"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","names":["CLIENT_CREDENTIALS","routedClientType","routedClientType","CLIENT_CREDENTIALS","sameClientType","sameClientType","groupClientType"]}