cartethyia 2.7.8 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (519) hide show
  1. package/.env.example +3 -3
  2. package/README.md +29 -59
  3. package/dist/dashboard/assets/BannedPage-Cc0vKpMG.js +1 -0
  4. package/dist/dashboard/assets/BannedPage-Cc0vKpMG.js.gz +0 -0
  5. package/dist/dashboard/assets/{CliToolDetailPage-BRWKPQPf.js → CliToolDetailPage-Bqj2aa1T.js} +1 -1
  6. package/dist/dashboard/assets/CliToolDetailPage-Bqj2aa1T.js.gz +0 -0
  7. package/dist/dashboard/assets/{CliToolsPage-BP-Y5iHN.js → CliToolsPage-CXsaOAO2.js} +1 -1
  8. package/dist/dashboard/assets/CliToolsPage-CXsaOAO2.js.gz +0 -0
  9. package/dist/dashboard/assets/CombosPage-BeLpJ4ma.js +1 -0
  10. package/dist/dashboard/assets/CombosPage-BeLpJ4ma.js.gz +0 -0
  11. package/dist/dashboard/assets/ConsoleLogPage-DnV0uZ3m.js +1 -0
  12. package/dist/dashboard/assets/ConsoleLogPage-DnV0uZ3m.js.gz +0 -0
  13. package/dist/dashboard/assets/CustomizationPage-CBxAjo63.js +1 -0
  14. package/dist/dashboard/assets/CustomizationPage-CBxAjo63.js.gz +0 -0
  15. package/dist/dashboard/assets/HealthEventsModal-B5yEE0k6.js +1 -0
  16. package/dist/dashboard/assets/HealthEventsModal-B5yEE0k6.js.gz +0 -0
  17. package/dist/dashboard/assets/{InjectSystemPromptPanel-Cv-2Ol_K.js → InjectSystemPromptPanel-BWFLECmz.js} +2 -2
  18. package/dist/dashboard/assets/InjectSystemPromptPanel-BWFLECmz.js.gz +0 -0
  19. package/dist/dashboard/assets/{LoginPage-bKfz_b1K.js → LoginPage-CgoPc5B9.js} +1 -1
  20. package/dist/dashboard/assets/LoginPage-CgoPc5B9.js.gz +0 -0
  21. package/dist/dashboard/assets/{ModelPicker-B-WQxx_H.js → ModelPicker-D9bFQern.js} +1 -1
  22. package/dist/dashboard/assets/ModelPicker-D9bFQern.js.gz +0 -0
  23. package/dist/dashboard/assets/OverviewPage-B_p4tL8k.js +1 -0
  24. package/dist/dashboard/assets/OverviewPage-B_p4tL8k.js.gz +0 -0
  25. package/dist/dashboard/assets/ProviderDetailPage-rs5E2rxv.js +8 -0
  26. package/dist/dashboard/assets/ProviderDetailPage-rs5E2rxv.js.gz +0 -0
  27. package/dist/dashboard/assets/ProviderIcon-D_0PiZtg.js +1 -0
  28. package/dist/dashboard/assets/ProviderIcon-D_0PiZtg.js.gz +0 -0
  29. package/dist/dashboard/assets/ProvidersPage-CLI2bJTK.js +1 -0
  30. package/dist/dashboard/assets/ProvidersPage-CLI2bJTK.js.gz +0 -0
  31. package/dist/dashboard/assets/{ProxyPage-emlTuxz6.js → ProxyPage-BwNC_-Cx.js} +1 -1
  32. package/dist/dashboard/assets/ProxyPage-BwNC_-Cx.js.gz +0 -0
  33. package/dist/dashboard/assets/QuotaPage-DA-a1iSN.js +1 -0
  34. package/dist/dashboard/assets/QuotaPage-DA-a1iSN.js.gz +0 -0
  35. package/dist/dashboard/assets/SettingsPage-CctTga2C.js +1 -0
  36. package/dist/dashboard/assets/SettingsPage-CctTga2C.js.gz +0 -0
  37. package/dist/dashboard/assets/{SetupPage-CUZrKs9r.js → SetupPage-febLU4r1.js} +1 -1
  38. package/dist/dashboard/assets/SetupPage-febLU4r1.js.gz +0 -0
  39. package/dist/dashboard/assets/{StudioPage-jWmUdDpy.js → StudioPage-M6fvR5Wz.js} +1 -1
  40. package/dist/dashboard/assets/StudioPage-M6fvR5Wz.js.gz +0 -0
  41. package/dist/dashboard/assets/UsagePage-nyeuRqz9.js +56 -0
  42. package/dist/dashboard/assets/UsagePage-nyeuRqz9.js.gz +0 -0
  43. package/dist/dashboard/assets/api-keys-BFOlvrJC.js +1 -0
  44. package/dist/dashboard/assets/api-keys-BFOlvrJC.js.gz +0 -0
  45. package/dist/dashboard/assets/app-Dx2QgsNj.css +2 -0
  46. package/dist/dashboard/assets/app-Dx2QgsNj.css.gz +0 -0
  47. package/dist/dashboard/assets/{assert-CidQVoNo.js → assert-CqTLw5e7.js} +1 -1
  48. package/dist/dashboard/assets/assert-CqTLw5e7.js.gz +0 -0
  49. package/dist/dashboard/assets/{badge-DyI_mJfi.js → badge-C83EqLB0.js} +1 -1
  50. package/dist/dashboard/assets/badge-C83EqLB0.js.gz +0 -0
  51. package/dist/dashboard/assets/ban-durations-B58FyRxC.js +1 -0
  52. package/dist/dashboard/assets/ban-durations-B58FyRxC.js.gz +0 -0
  53. package/dist/dashboard/assets/{banner-B-yXtCqb.js → banner-D1xn7pIe.js} +1 -1
  54. package/dist/dashboard/assets/banner-D1xn7pIe.js.gz +0 -0
  55. package/dist/dashboard/assets/brand/bansos_page.webp +0 -0
  56. package/dist/dashboard/assets/brand/denia_bansos.webp +0 -0
  57. package/dist/dashboard/assets/brand/favicon.webp +0 -0
  58. package/dist/dashboard/assets/brand/login_register.webp +0 -0
  59. package/dist/dashboard/assets/brand/login_register_initial.webp +0 -0
  60. package/dist/dashboard/assets/brand/og_bansos.webp +0 -0
  61. package/dist/dashboard/assets/brand/og_image.webp +0 -0
  62. package/dist/dashboard/assets/brand/sidebar_ico.webp +0 -0
  63. package/dist/dashboard/assets/{card-_HwAEqFF.js → card-DU3Lq5Lm.js} +1 -1
  64. package/dist/dashboard/assets/card-DU3Lq5Lm.js.gz +0 -0
  65. package/dist/dashboard/assets/cli-tools-Dw1U_drK.js +1 -0
  66. package/dist/dashboard/assets/cli-tools-Dw1U_drK.js.gz +0 -0
  67. package/dist/dashboard/assets/{clipboard-button-ByjCk0o9.js → clipboard-button-CEL5Sg_J.js} +1 -1
  68. package/dist/dashboard/assets/clipboard-button-CEL5Sg_J.js.gz +0 -0
  69. package/dist/dashboard/assets/{dialog-BZhOlfz-.js → dialog-BjFR5UHy.js} +1 -1
  70. package/dist/dashboard/assets/dialog-BjFR5UHy.js.gz +0 -0
  71. package/dist/dashboard/assets/{drawer-BADqIRYP.js → drawer-HvBW0AjI.js} +1 -1
  72. package/dist/dashboard/assets/drawer-HvBW0AjI.js.gz +0 -0
  73. package/dist/dashboard/assets/entry-BSu3gFlt.js +4 -0
  74. package/dist/dashboard/assets/entry-BSu3gFlt.js.gz +0 -0
  75. package/dist/dashboard/assets/{entry-COaC-irN.js → entry-CECVELyy.js} +1 -1
  76. package/dist/dashboard/assets/entry-CECVELyy.js.gz +0 -0
  77. package/dist/dashboard/assets/entry-DYYofQ7W.js +1 -0
  78. package/dist/dashboard/assets/entry-DYYofQ7W.js.gz +0 -0
  79. package/dist/dashboard/assets/{formatters-DcHJyRiu.js → formatters-DLW4i8zK.js} +1 -1
  80. package/dist/dashboard/assets/formatters-DLW4i8zK.js.gz +0 -0
  81. package/dist/dashboard/assets/{index-CgKmFngv.js → index-1-fCqe64.js} +2 -2
  82. package/dist/dashboard/assets/index-1-fCqe64.js.gz +0 -0
  83. package/dist/dashboard/assets/{inline-B2BirKry.js → inline-DGvU2oLK.js} +1 -1
  84. package/dist/dashboard/assets/inline-DGvU2oLK.js.gz +0 -0
  85. package/dist/dashboard/assets/{input-D-qV9dKY.js → input-iNnO1X2K.js} +1 -1
  86. package/dist/dashboard/assets/input-iNnO1X2K.js.gz +0 -0
  87. package/dist/dashboard/assets/{layout-B7tVWhtV.js → layout-0q8UGypb.js} +1 -1
  88. package/dist/dashboard/assets/layout-0q8UGypb.js.gz +0 -0
  89. package/dist/dashboard/assets/{list-row-CtkGE3bF.js → list-row-C0w2bQjJ.js} +1 -1
  90. package/dist/dashboard/assets/list-row-C0w2bQjJ.js.gz +0 -0
  91. package/dist/dashboard/assets/{live-DGizF06-.js → live-M5aJ_xCa.js} +1 -1
  92. package/dist/dashboard/assets/live-M5aJ_xCa.js.gz +0 -0
  93. package/dist/dashboard/assets/{mutation-GU7XdEjz.js → mutation-BQ0ccH_A.js} +1 -1
  94. package/dist/dashboard/assets/mutation-BQ0ccH_A.js.gz +0 -0
  95. package/dist/dashboard/assets/{network-C9UE-bOr.js → network-BKeQGT3K.js} +1 -1
  96. package/dist/dashboard/assets/network-BKeQGT3K.js.gz +0 -0
  97. package/dist/dashboard/assets/{numbers-BnAd22a_.js → numbers-CivAk3da.js} +1 -1
  98. package/dist/dashboard/assets/numbers-CivAk3da.js.gz +0 -0
  99. package/dist/dashboard/assets/{pagination-BAywyMzS.js → pagination-CpzvI5ep.js} +1 -1
  100. package/dist/dashboard/assets/pagination-CpzvI5ep.js.gz +0 -0
  101. package/dist/dashboard/assets/providers/devin.svg +9 -0
  102. package/dist/dashboard/assets/providers/devin.svg.gz +0 -0
  103. package/dist/dashboard/assets/providers/windsurf.svg +10 -0
  104. package/dist/dashboard/assets/providers/windsurf.svg.gz +0 -0
  105. package/dist/dashboard/assets/providers/zro.svg +3 -0
  106. package/dist/dashboard/assets/providers/zro.svg.gz +0 -0
  107. package/dist/dashboard/assets/{query-keys-YSoQOUh6.js → query-keys-IKLh0YFd.js} +1 -1
  108. package/dist/dashboard/assets/query-keys-IKLh0YFd.js.gz +0 -0
  109. package/dist/dashboard/assets/quota-DiPD6UKH.js +1 -0
  110. package/dist/dashboard/assets/quota-DiPD6UKH.js.gz +0 -0
  111. package/dist/dashboard/assets/routing-BFQX2VBc.js +1 -0
  112. package/dist/dashboard/assets/routing-BFQX2VBc.js.gz +0 -0
  113. package/dist/dashboard/assets/{select-BCOcv8WK.js → select-CXbck0jG.js} +2 -2
  114. package/dist/dashboard/assets/select-CXbck0jG.js.gz +0 -0
  115. package/dist/dashboard/assets/settings-C_XvMHh9.js +1 -0
  116. package/dist/dashboard/assets/settings-C_XvMHh9.js.gz +0 -0
  117. package/dist/dashboard/assets/{stack-ByKt3Q1g.js → stack-DggRiCxE.js} +1 -1
  118. package/dist/dashboard/assets/stack-DggRiCxE.js.gz +0 -0
  119. package/dist/dashboard/assets/{state-DXbGTx7N.js → state-ClFzfbYp.js} +1 -1
  120. package/dist/dashboard/assets/state-ClFzfbYp.js.gz +0 -0
  121. package/dist/dashboard/assets/story/25817331.webp +0 -0
  122. package/dist/dashboard/assets/story/Shorekeeper.webp +0 -0
  123. package/dist/dashboard/assets/story/cartethyia-god.webp +0 -0
  124. package/dist/dashboard/assets/story/fleurdelys_plus.webp +0 -0
  125. package/dist/dashboard/assets/story/jinhsi-blossom.webp +0 -0
  126. package/dist/dashboard/assets/story/phrolova-a.webp +0 -0
  127. package/dist/dashboard/assets/story/requestdeniawokkjpg.webp +0 -0
  128. package/dist/dashboard/assets/story/wuthering-waves-hiyuki-aemeath-hiyuki-rover.webp +0 -0
  129. package/dist/dashboard/assets/{switch-ZeTsW623.js → switch-CTIFxKqS.js} +1 -1
  130. package/dist/dashboard/assets/switch-CTIFxKqS.js.gz +0 -0
  131. package/dist/dashboard/assets/{useMutation-CbCP4w1o.js → useMutation-BClG3yWj.js} +1 -1
  132. package/dist/dashboard/assets/useMutation-BClG3yWj.js.gz +0 -0
  133. package/dist/dashboard/console-backgrounds.webp +0 -0
  134. package/dist/dashboard/console-backgrounds_initial.webp +0 -0
  135. package/dist/dashboard/donation/qris-risun-marke.webp +0 -0
  136. package/dist/dashboard/index.html +3 -3
  137. package/dist/dashboard/index.html.gz +0 -0
  138. package/dist/dashboard/precompressed-assets.json +59 -56
  139. package/migrations/full-postgres/0044_add_models_warning_metadata.sql +10 -0
  140. package/migrations/full-postgres/0045_migrate_workbuddy_to_codebuddy.sql +156 -0
  141. package/migrations/full-postgres/0046_add_accounts_quota_plan_fetched_at.sql +7 -0
  142. package/migrations/lite-sqlite3/0044_add_models_warning_metadata.sql +11 -0
  143. package/migrations/lite-sqlite3/0045_migrate_workbuddy_to_codebuddy.sql +156 -0
  144. package/migrations/lite-sqlite3/0046_add_accounts_quota_plan_fetched_at.sql +4 -0
  145. package/package.json +1 -1
  146. package/src/boot/app.ts +10 -13
  147. package/src/boot/dependencies.ts +12 -4
  148. package/src/boot/flush.ts +20 -0
  149. package/src/boot/lifecycle.ts +7 -5
  150. package/src/config/cooldowns.ts +1 -1
  151. package/src/config/routing.ts +26 -0
  152. package/src/config/spec-metadata.ts +72 -0
  153. package/src/config/spec.ts +20 -6
  154. package/src/console/api-keys/contracts.ts +12 -1
  155. package/src/console/api-keys/routes.ts +50 -31
  156. package/src/console/auth/account-reset.ts +7 -9
  157. package/src/console/backup/contracts.ts +4 -0
  158. package/src/console/backup/export-endpoint.ts +7 -5
  159. package/src/console/cli-tools/service.ts +6 -12
  160. package/src/console/console-router-guards.ts +23 -16
  161. package/src/console/console-router.ts +7 -0
  162. package/src/console/dashboard-assets.ts +5 -5
  163. package/src/console/domain-registration.ts +27 -2
  164. package/src/console/inferhub/normalize.ts +24 -28
  165. package/src/console/inferhub/types.ts +3 -0
  166. package/src/console/ip-bans/routes.ts +93 -0
  167. package/src/console/observability/store.ts +0 -53
  168. package/src/console/providers/catalog/catalog-projections.ts +5 -2
  169. package/src/console/providers/catalog/contracts.ts +123 -0
  170. package/src/console/providers/catalog/discover-constants.ts +6 -0
  171. package/src/console/providers/catalog/model-operations.ts +122 -10
  172. package/src/console/providers/catalog/provider-operations.ts +116 -8
  173. package/src/console/providers/catalog/public-model-store.ts +0 -0
  174. package/src/console/providers/catalog/routes.ts +65 -4
  175. package/src/console/providers/catalog/store-helpers.ts +30 -1
  176. package/src/console/providers/catalog/store.ts +249 -4
  177. package/src/console/quota/account-quota-global.ts +97 -19
  178. package/src/console/quota/account-quota-shared.ts +49 -0
  179. package/src/console/quota/account-quota-tenant.ts +6 -18
  180. package/src/console/quota/native-identity.ts +2 -0
  181. package/src/console/quota/quota-view.ts +19 -3
  182. package/src/console/routing/pools/operations.ts +31 -46
  183. package/src/console/settings/contracts.ts +18 -0
  184. package/src/console/settings/store.ts +32 -0
  185. package/src/console/shared/errors.ts +33 -6
  186. package/src/console/system-prompt/contracts.ts +0 -1
  187. package/src/main.ts +3 -3
  188. package/src/network/pool/byte-accounting.ts +3 -2
  189. package/src/network/pool/selector.ts +182 -39
  190. package/src/network/pool-cooldown-store.ts +89 -14
  191. package/src/network/pool-health.ts +49 -61
  192. package/src/network/rate-limit-verdict.ts +1 -1
  193. package/src/network/ssrf.ts +6 -6
  194. package/src/observability/event-log.ts +7 -361
  195. package/src/observability/event-query.ts +18 -4
  196. package/src/observability/performance-metrics.ts +9 -0
  197. package/src/observability/runtime-metrics.ts +14 -9
  198. package/src/observability/telemetry-buffer.ts +15 -25
  199. package/src/observability/telemetry-reconciliation.ts +9 -37
  200. package/src/observability/telemetry-row.ts +125 -0
  201. package/src/persistence/db-mode.ts +4 -1
  202. package/src/persistence/dialect.ts +30 -0
  203. package/src/persistence/migrate.ts +6 -3
  204. package/src/persistence/schema.ts +28 -2
  205. package/src/persistence/ttl-cache.ts +20 -2
  206. package/src/protocol/codecs.ts +1 -1
  207. package/src/protocol/dsml.ts +35 -87
  208. package/src/protocol/gateway-error.ts +1 -0
  209. package/src/protocol/markup-stream-parser.ts +195 -0
  210. package/src/protocol/reasoning-text.ts +19 -0
  211. package/src/protocol/reasoning.ts +1 -1
  212. package/src/protocol/request/chat.ts +14 -14
  213. package/src/protocol/request/gemini.ts +8 -2
  214. package/src/protocol/request/messages.ts +4 -5
  215. package/src/protocol/response/chat.ts +12 -20
  216. package/src/protocol/response/gemini.ts +6 -1
  217. package/src/protocol/response/omp-tool-call-markup.ts +43 -86
  218. package/src/protocol/response/responses.ts +18 -2
  219. package/src/protocol/sse-decoder.ts +25 -8
  220. package/src/protocol/stop-reason.ts +23 -1
  221. package/src/protocol/stream-error-frames.ts +13 -3
  222. package/src/protocol/think-split.ts +112 -0
  223. package/src/protocol/translation/dialect/qwen.ts +26 -58
  224. package/src/protocol/translation/quirks.ts +1 -1
  225. package/src/protocol/translation/tool-repair.ts +2 -2
  226. package/src/protocol/upstream/send-claude-messages.ts +15 -4
  227. package/src/protocol/upstream-parsing.ts +1 -1
  228. package/src/providers/adapters/compatible-adapter.ts +78 -17
  229. package/src/providers/authentication/oauth-client.ts +1 -1
  230. package/src/providers/authentication/oauth-device-flow.ts +98 -8
  231. package/src/providers/authentication/oauth-refresh-service.ts +153 -59
  232. package/src/providers/configured-provider.ts +148 -0
  233. package/src/providers/default-registry.ts +117 -27
  234. package/src/providers/discovery/discovery-types.ts +12 -0
  235. package/src/providers/discovery/probe-phases.ts +74 -33
  236. package/src/providers/discovery/probing-service.ts +293 -165
  237. package/src/providers/integrations/alibabacp/alibabacp-models.ts +1 -2
  238. package/src/providers/integrations/{dashscope-models.ts → alibabacp/dashscope-models.ts} +2 -2
  239. package/src/providers/integrations/antigravity/antigravity-protocol.ts +121 -2
  240. package/src/providers/integrations/antigravity/antigravity.ts +13 -2
  241. package/src/providers/integrations/buddy/buddy-catalog-shared.ts +72 -34
  242. package/src/providers/integrations/buddy/buddy-chat-shared.ts +191 -35
  243. package/src/providers/integrations/buddy/buddy-checkin.ts +17 -39
  244. package/src/providers/integrations/buddy/buddy-conversation-headers.ts +2 -2
  245. package/src/providers/integrations/buddy/buddy-discovery-shared.ts +5 -5
  246. package/src/providers/integrations/buddy/buddy-identity.ts +89 -6
  247. package/src/providers/integrations/buddy/buddy-media.ts +4 -5
  248. package/src/providers/integrations/buddy/buddy-oauth-shared.ts +2 -2
  249. package/src/providers/integrations/buddy/buddy-quota-shared.ts +1 -1
  250. package/src/providers/integrations/buddy/buddy-usage-shared.ts +1 -3
  251. package/src/providers/integrations/buddy/capabilities.ts +6 -43
  252. package/src/providers/integrations/buddy/codebuddy/cn-catalog.ts +2 -1
  253. package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +23 -1
  254. package/src/providers/integrations/buddy/codebuddy/provider.ts +6 -2
  255. package/src/providers/integrations/buddy/codebuddy/shared.ts +38 -27
  256. package/src/providers/integrations/claude/claude-quota.ts +14 -17
  257. package/src/providers/integrations/cline/cline.ts +2 -2
  258. package/src/providers/integrations/commandcode/quota.ts +22 -28
  259. package/src/providers/integrations/cursor/cursor-auth.ts +0 -8
  260. package/src/providers/integrations/cursor/cursor-catalog.ts +2 -0
  261. package/src/providers/integrations/cursor/cursor-exec.ts +745 -0
  262. package/src/providers/integrations/cursor/cursor-http2.ts +2 -0
  263. package/src/providers/integrations/cursor/cursor-request.ts +35 -20
  264. package/src/providers/integrations/cursor/cursor-shared.ts +26 -5
  265. package/src/providers/integrations/cursor/cursor.ts +139 -70
  266. package/src/providers/integrations/cursor/protocol/messages.ts +22 -29
  267. package/src/providers/integrations/cursor/protocol/protobuf-schema.ts +37 -0
  268. package/src/providers/integrations/cursor/protocol/tool-canonical.ts +26 -100
  269. package/src/providers/integrations/devin/devin-auth.ts +353 -0
  270. package/src/providers/integrations/devin/devin-catalog.ts +207 -0
  271. package/src/providers/integrations/devin/devin-http.ts +91 -0
  272. package/src/providers/integrations/devin/devin-quota.ts +214 -0
  273. package/src/providers/integrations/devin/devin-shared.ts +111 -0
  274. package/src/providers/integrations/devin/devin.ts +539 -0
  275. package/src/providers/integrations/devin/protocol/devin-proto.ts +558 -0
  276. package/src/providers/integrations/devin/protocol/framing.ts +124 -0
  277. package/src/providers/integrations/factory/factory-oauth.ts +17 -44
  278. package/src/providers/integrations/factory/factory.ts +2 -2
  279. package/src/providers/integrations/freebuff/assets/official-system-manager.txt +88 -0
  280. package/src/providers/integrations/freebuff/assets/official-system-worker.txt +57 -0
  281. package/src/providers/integrations/freebuff/assets/official-tools.json +1070 -0
  282. package/src/providers/integrations/freebuff/freebuff-catalog.ts +120 -0
  283. package/src/providers/integrations/freebuff/freebuff-constants.ts +1233 -0
  284. package/src/providers/integrations/freebuff/freebuff-discovery.ts +108 -0
  285. package/src/providers/integrations/freebuff/freebuff-oauth.ts +240 -0
  286. package/src/providers/integrations/freebuff/freebuff-quota.ts +260 -0
  287. package/src/providers/integrations/freebuff/freebuff-virtual.ts +89 -0
  288. package/src/providers/integrations/freebuff/freebuff.ts +682 -0
  289. package/src/providers/integrations/freepi/freepi-catalog.ts +60 -0
  290. package/src/providers/integrations/freepi/freepi-discovery.ts +82 -0
  291. package/src/providers/integrations/freepi/freepi-headers.ts +21 -0
  292. package/src/providers/integrations/freepi/freepi-oauth.ts +142 -0
  293. package/src/providers/integrations/freepi/freepi-protocol.ts +242 -0
  294. package/src/providers/integrations/freepi/freepi-quota.ts +126 -0
  295. package/src/providers/integrations/freepi/freepi-realm.ts +35 -0
  296. package/src/providers/integrations/freepi/freepi.ts +292 -0
  297. package/src/providers/integrations/gemini.ts +2 -2
  298. package/src/providers/integrations/grok/grok-oauth.ts +48 -45
  299. package/src/providers/integrations/grok/grok-ratelimit-store.ts +10 -17
  300. package/src/providers/integrations/grok/grok-turn-index.ts +11 -16
  301. package/src/providers/integrations/hermes/hermes-oauth.ts +94 -0
  302. package/src/providers/integrations/{hermes.ts → hermes/hermes.ts} +13 -21
  303. package/src/providers/integrations/hermes/index.ts +2 -0
  304. package/src/providers/integrations/kiro/kiro-catalog.ts +17 -1
  305. package/src/providers/integrations/kiro/kiro-discovery.ts +10 -12
  306. package/src/providers/integrations/kiro/kiro-quota.ts +8 -4
  307. package/src/providers/integrations/kiro/kiro.ts +15 -19
  308. package/src/providers/integrations/ollamacloud/index.ts +2 -0
  309. package/src/providers/integrations/{ollamacloud-models.ts → ollamacloud/models.ts} +2 -2
  310. package/src/providers/integrations/{ollamacloud-quota.ts → ollamacloud/quota.ts} +3 -3
  311. package/src/providers/integrations/opencode/fingerprint.ts +1 -1
  312. package/src/providers/integrations/opencode/opencode-go-quota.ts +2 -8
  313. package/src/providers/integrations/perch/perch-catalog.ts +105 -0
  314. package/src/providers/integrations/perch/perch-credential.ts +25 -0
  315. package/src/providers/integrations/perch/perch-oauth.ts +170 -0
  316. package/src/providers/integrations/perch/perch-protocol.ts +208 -0
  317. package/src/providers/integrations/perch/perch-quota.ts +123 -0
  318. package/src/providers/integrations/perch/perch-realm.ts +82 -0
  319. package/src/providers/integrations/perch/perch-system-prompt.ts +13 -0
  320. package/src/providers/integrations/perch/perch.ts +305 -0
  321. package/src/providers/integrations/perch/saffron-system-prompt.txt +8 -0
  322. package/src/providers/integrations/qoder/chat-proto.ts +328 -328
  323. package/src/providers/integrations/qoder/claim-qoder-credits.ts +19 -60
  324. package/src/providers/integrations/qoder/qoder-adapter.ts +90 -40
  325. package/src/providers/integrations/qoder/qoder-auth.ts +101 -29
  326. package/src/providers/integrations/qoder/qoder-cache.ts +32 -0
  327. package/src/providers/integrations/qoder/qoder-catalog.ts +26 -6
  328. package/src/providers/integrations/qoder/qoder-chat.ts +7 -21
  329. package/src/providers/integrations/qoder/qoder-checkin.ts +6 -6
  330. package/src/providers/integrations/qoder/qoder-grpc.ts +210 -7
  331. package/src/providers/integrations/qoder/qoder-ide.ts +5 -108
  332. package/src/providers/integrations/qoder/qoder-identity-cache.ts +184 -0
  333. package/src/providers/integrations/qoder/qoder-native-identity-store.ts +83 -18
  334. package/src/providers/integrations/qoder/qoder-realm.ts +9 -6
  335. package/src/providers/integrations/qoder/qoder-umid.ts +109 -342
  336. package/src/providers/integrations/qoder/qoder-virtual.ts +33 -1
  337. package/src/providers/integrations/qoder/qoder.ts +3 -7
  338. package/src/providers/integrations/trae/trae-catalog.ts +9 -14
  339. package/src/providers/integrations/trae/trae-headers.ts +36 -11
  340. package/src/providers/integrations/trae/trae-oauth.ts +14 -17
  341. package/src/providers/integrations/trae/trae-protocol.ts +12 -11
  342. package/src/providers/integrations/trae/trae-quota.ts +96 -36
  343. package/src/providers/integrations/trae/trae-realm.ts +74 -15
  344. package/src/providers/integrations/trae/trae.ts +99 -26
  345. package/src/providers/integrations/zcode-start-plan/provider.ts +226 -23
  346. package/src/providers/integrations/zcode-start-plan/quota.ts +19 -2
  347. package/src/providers/integrations/zro/zro.ts +204 -0
  348. package/src/providers/operations/account-error-classification.ts +235 -278
  349. package/src/providers/operations/account-health-service.ts +273 -26
  350. package/src/providers/operations/account-refresh-status.ts +269 -0
  351. package/src/providers/operations/account-tier.ts +66 -0
  352. package/src/providers/operations/client-version-resolver.ts +1 -1
  353. package/src/providers/operations/client-versions.ts +42 -150
  354. package/src/providers/operations/cooldown-rules.ts +56 -0
  355. package/src/providers/operations/{model-catalog-cache.ts → provider-caches.ts} +68 -16
  356. package/src/providers/operations/provider-catalog-seeder.ts +4 -0
  357. package/src/providers/operations/provider-catalog-service.ts +1 -1
  358. package/src/providers/operations/provider-credential-service.ts +102 -32
  359. package/src/providers/operations/provider-rules/github.ts +48 -0
  360. package/src/providers/operations/provider-rules/grok.ts +33 -0
  361. package/src/providers/operations/provider-rules/inception.ts +49 -0
  362. package/src/providers/operations/provider-rules/index.ts +32 -0
  363. package/src/providers/operations/provider-rules/perch.ts +37 -0
  364. package/src/providers/operations/provider-rules/qoder.ts +70 -0
  365. package/src/providers/operations/provider-rules/trae.ts +81 -0
  366. package/src/providers/provider-contracts.ts +33 -2
  367. package/src/providers/{provider-credential-resolver.ts → provider-credentials.ts} +40 -3
  368. package/src/providers/provider-metadata.ts +99 -14
  369. package/src/providers/provider-model-definition.ts +36 -0
  370. package/src/providers/provider-probe.ts +15 -1
  371. package/src/providers/provider-registry.ts +42 -33
  372. package/src/providers/quota/quota-limit-windows.ts +16 -5
  373. package/src/providers/quota/quota-support.ts +1 -1
  374. package/src/providers/quota/quota-window-parser.ts +90 -18
  375. package/src/providers/quota/refresh.ts +96 -18
  376. package/src/security/abuse.ts +71 -0
  377. package/src/security/api-key-auth-cache.ts +1 -1
  378. package/src/security/api-key-auth.ts +6 -2
  379. package/src/transport/dispatch/attempt-finalize.ts +14 -13
  380. package/src/transport/dispatch/attempt-loop.ts +71 -17
  381. package/src/transport/dispatch/generation.ts +2 -8
  382. package/src/transport/dispatch/native-shared.ts +25 -0
  383. package/src/transport/dispatch/proxy-request.ts +9 -46
  384. package/src/transport/dispatch/responses-compact.ts +2 -8
  385. package/src/transport/dispatch/streaming/finalize.ts +9 -6
  386. package/src/transport/dispatch/streaming/stream.ts +9 -36
  387. package/src/transport/dispatch/systemone.ts +2 -8
  388. package/src/transport/dispatch/token-count.ts +2 -6
  389. package/src/transport/dispatch/upstream.ts +67 -1
  390. package/src/transport/drain-endpoint.ts +31 -4
  391. package/src/transport/failure-policy.ts +129 -37
  392. package/src/transport/guards/body-policy.ts +7 -1
  393. package/src/transport/guards/error-lifecycle.ts +13 -1
  394. package/src/transport/guards/request-context.ts +22 -14
  395. package/src/transport/request/preparer.ts +81 -71
  396. package/src/transport/routing/bounded-lru.ts +14 -0
  397. package/src/transport/routing/drain-reserve.ts +129 -0
  398. package/src/transport/routing/plan-gate.ts +7 -1
  399. package/src/transport/routing/round-robin.ts +60 -0
  400. package/src/transport/routing/route-catalog.ts +123 -111
  401. package/src/transport/routing/route-model.ts +51 -9
  402. package/src/transport/routing/router.ts +418 -33
  403. package/src/transport/surface/adapters.ts +11 -2
  404. package/src/transport/surface/chat/adapter.ts +2 -2
  405. package/src/transport/surface/chat/encode.ts +47 -4
  406. package/src/transport/surface/chat/parse.ts +2 -12
  407. package/src/transport/surface/completion.ts +44 -33
  408. package/src/transport/surface/content-parts.ts +21 -0
  409. package/src/transport/surface/messages/adapter.ts +9 -2
  410. package/src/transport/surface/messages/encode.ts +11 -3
  411. package/src/transport/surface/messages/parse.ts +2 -1
  412. package/src/transport/surface/messages/stream.ts +33 -17
  413. package/src/transport/surface/responses/encode.ts +34 -6
  414. package/src/transport/surface/responses/parse.ts +3 -11
  415. package/src/workers/daily-checkin.ts +1 -1
  416. package/src/workers/quota-refresh-sweep.ts +1 -1
  417. package/src/workers/scheduler.ts +22 -4
  418. package/dist/dashboard/assets/BannedPage-DeIbIiBU.js +0 -1
  419. package/dist/dashboard/assets/BannedPage-DeIbIiBU.js.gz +0 -0
  420. package/dist/dashboard/assets/CliToolDetailPage-BRWKPQPf.js.gz +0 -0
  421. package/dist/dashboard/assets/CliToolsPage-BP-Y5iHN.js.gz +0 -0
  422. package/dist/dashboard/assets/CombosPage-B7JHozVa.js +0 -1
  423. package/dist/dashboard/assets/CombosPage-B7JHozVa.js.gz +0 -0
  424. package/dist/dashboard/assets/ConsoleLogPage-GX7iGGcu.js +0 -1
  425. package/dist/dashboard/assets/ConsoleLogPage-GX7iGGcu.js.gz +0 -0
  426. package/dist/dashboard/assets/CustomizationPage-HVonbGEa.js +0 -1
  427. package/dist/dashboard/assets/CustomizationPage-HVonbGEa.js.gz +0 -0
  428. package/dist/dashboard/assets/HealthEventsModal-xaut4OJ9.js +0 -1
  429. package/dist/dashboard/assets/HealthEventsModal-xaut4OJ9.js.gz +0 -0
  430. package/dist/dashboard/assets/InjectSystemPromptPanel-Cv-2Ol_K.js.gz +0 -0
  431. package/dist/dashboard/assets/LoginPage-bKfz_b1K.js.gz +0 -0
  432. package/dist/dashboard/assets/ModelPicker-B-WQxx_H.js.gz +0 -0
  433. package/dist/dashboard/assets/OverviewPage-Z9pJZFo8.js +0 -1
  434. package/dist/dashboard/assets/OverviewPage-Z9pJZFo8.js.gz +0 -0
  435. package/dist/dashboard/assets/ProviderDetailPage-CMeDBxR1.js +0 -7
  436. package/dist/dashboard/assets/ProviderDetailPage-CMeDBxR1.js.gz +0 -0
  437. package/dist/dashboard/assets/ProviderIcon-jjqXJDA3.js +0 -1
  438. package/dist/dashboard/assets/ProviderIcon-jjqXJDA3.js.gz +0 -0
  439. package/dist/dashboard/assets/ProvidersPage-BXPdOpG4.js +0 -1
  440. package/dist/dashboard/assets/ProvidersPage-BXPdOpG4.js.gz +0 -0
  441. package/dist/dashboard/assets/ProxyPage-emlTuxz6.js.gz +0 -0
  442. package/dist/dashboard/assets/QuotaPage-CMJKNYWb.js +0 -1
  443. package/dist/dashboard/assets/QuotaPage-CMJKNYWb.js.gz +0 -0
  444. package/dist/dashboard/assets/SettingsPage-BSy7EwGo.js +0 -1
  445. package/dist/dashboard/assets/SettingsPage-BSy7EwGo.js.gz +0 -0
  446. package/dist/dashboard/assets/SetupPage-CUZrKs9r.js.gz +0 -0
  447. package/dist/dashboard/assets/StudioPage-jWmUdDpy.js.gz +0 -0
  448. package/dist/dashboard/assets/UsagePage-5F9tGVGG.js +0 -56
  449. package/dist/dashboard/assets/UsagePage-5F9tGVGG.js.gz +0 -0
  450. package/dist/dashboard/assets/api-keys-KvX83mRe.js +0 -1
  451. package/dist/dashboard/assets/api-keys-KvX83mRe.js.gz +0 -0
  452. package/dist/dashboard/assets/app-BEsU8hKs.css +0 -2
  453. package/dist/dashboard/assets/app-BEsU8hKs.css.gz +0 -0
  454. package/dist/dashboard/assets/assert-CidQVoNo.js.gz +0 -0
  455. package/dist/dashboard/assets/badge-DyI_mJfi.js.gz +0 -0
  456. package/dist/dashboard/assets/banner-B-yXtCqb.js.gz +0 -0
  457. package/dist/dashboard/assets/brand/bansos_page.png +0 -0
  458. package/dist/dashboard/assets/brand/denia_bansos.jpg +0 -0
  459. package/dist/dashboard/assets/brand/favicon.jpg +0 -0
  460. package/dist/dashboard/assets/brand/login_register.jpg +0 -0
  461. package/dist/dashboard/assets/brand/login_register_initial.jpg +0 -0
  462. package/dist/dashboard/assets/brand/og_bansos.jpg +0 -0
  463. package/dist/dashboard/assets/brand/og_image.jpg +0 -0
  464. package/dist/dashboard/assets/brand/sidebar_ico.jpg +0 -0
  465. package/dist/dashboard/assets/card-_HwAEqFF.js.gz +0 -0
  466. package/dist/dashboard/assets/cli-tools-Bwv5-zGZ.js +0 -1
  467. package/dist/dashboard/assets/cli-tools-Bwv5-zGZ.js.gz +0 -0
  468. package/dist/dashboard/assets/clipboard-button-ByjCk0o9.js.gz +0 -0
  469. package/dist/dashboard/assets/dialog-BZhOlfz-.js.gz +0 -0
  470. package/dist/dashboard/assets/drawer-BADqIRYP.js.gz +0 -0
  471. package/dist/dashboard/assets/entry-COaC-irN.js.gz +0 -0
  472. package/dist/dashboard/assets/entry-Ca7LSCet.js +0 -4
  473. package/dist/dashboard/assets/entry-Ca7LSCet.js.gz +0 -0
  474. package/dist/dashboard/assets/entry-PDd27uCd.js +0 -1
  475. package/dist/dashboard/assets/entry-PDd27uCd.js.gz +0 -0
  476. package/dist/dashboard/assets/formatters-DcHJyRiu.js.gz +0 -0
  477. package/dist/dashboard/assets/index-CgKmFngv.js.gz +0 -0
  478. package/dist/dashboard/assets/inline-B2BirKry.js.gz +0 -0
  479. package/dist/dashboard/assets/input-D-qV9dKY.js.gz +0 -0
  480. package/dist/dashboard/assets/layout-B7tVWhtV.js.gz +0 -0
  481. package/dist/dashboard/assets/list-row-CtkGE3bF.js.gz +0 -0
  482. package/dist/dashboard/assets/live-DGizF06-.js.gz +0 -0
  483. package/dist/dashboard/assets/minimize-2-BTmMTK4o.js +0 -1
  484. package/dist/dashboard/assets/minimize-2-BTmMTK4o.js.gz +0 -0
  485. package/dist/dashboard/assets/mutation-GU7XdEjz.js.gz +0 -0
  486. package/dist/dashboard/assets/network-C9UE-bOr.js.gz +0 -0
  487. package/dist/dashboard/assets/numbers-BnAd22a_.js.gz +0 -0
  488. package/dist/dashboard/assets/pagination-BAywyMzS.js.gz +0 -0
  489. package/dist/dashboard/assets/query-keys-YSoQOUh6.js.gz +0 -0
  490. package/dist/dashboard/assets/quota-DJ1QlAOq.js +0 -1
  491. package/dist/dashboard/assets/quota-DJ1QlAOq.js.gz +0 -0
  492. package/dist/dashboard/assets/routing-fnCsxgNO.js +0 -1
  493. package/dist/dashboard/assets/routing-fnCsxgNO.js.gz +0 -0
  494. package/dist/dashboard/assets/select-BCOcv8WK.js.gz +0 -0
  495. package/dist/dashboard/assets/settings-BxslsErn.js +0 -1
  496. package/dist/dashboard/assets/settings-BxslsErn.js.gz +0 -0
  497. package/dist/dashboard/assets/stack-ByKt3Q1g.js.gz +0 -0
  498. package/dist/dashboard/assets/state-DXbGTx7N.js.gz +0 -0
  499. package/dist/dashboard/assets/switch-ZeTsW623.js.gz +0 -0
  500. package/dist/dashboard/assets/useMutation-CbCP4w1o.js.gz +0 -0
  501. package/dist/dashboard/console-backgrounds.jpg +0 -0
  502. package/dist/dashboard/console-backgrounds_initial.jpg +0 -0
  503. package/dist/dashboard/donation/qris-risun-marke.png +0 -0
  504. package/src/providers/bundled-discovery-providers.ts +0 -98
  505. package/src/providers/configured-openai-providers.ts +0 -120
  506. package/src/providers/integrations/buddy/turing-device-token.ts +0 -262
  507. package/src/providers/integrations/buddy/workbuddy/cn-oauth.ts +0 -30
  508. package/src/providers/integrations/buddy/workbuddy/cn-provider.ts +0 -58
  509. package/src/providers/integrations/buddy/workbuddy/oauth.ts +0 -31
  510. package/src/providers/integrations/buddy/workbuddy/provider.ts +0 -209
  511. package/src/providers/integrations/buddy/workbuddy/quota.ts +0 -161
  512. package/src/providers/integrations/buddy/workbuddy/shared.ts +0 -285
  513. package/src/providers/operations/model-discovery-cache.ts +0 -34
  514. package/src/providers/operations/probe-fetch.ts +0 -15
  515. package/src/providers/operations/provider-version-cache.ts +0 -30
  516. package/src/providers/provider-capabilities.ts +0 -33
  517. package/src/providers/provider-credential-envelope.ts +0 -43
  518. /package/dist/dashboard/assets/{app-CTxoqyYB.js → app-DIXLjojg.js} +0 -0
  519. /package/dist/dashboard/assets/{app-CTxoqyYB.js.gz → app-DIXLjojg.js.gz} +0 -0
@@ -4,13 +4,20 @@
4
4
  // drag every integration into memory at process start.
5
5
  import {
6
6
  GENERIC_API_KEY_SPECS,
7
- } from "./configured-openai-providers";
8
- import { createDiscoveryBackedProviderCapabilities, discoveryBackedCapabilities } from "./bundled-discovery-providers";
9
- import { createApiKeyAdapter } from "./configured-provider";
10
- import type { ApiKeyProviderSpec } from "./configured-provider";
11
- import { oauthCapability, quotaCapability, type ProviderModuleCapabilities } from "./provider-capabilities";
7
+ createDiscoveryBackedProviderCapabilities,
8
+ discoveryBackedCapabilities,
9
+ createApiKeyAdapter,
10
+ type ApiKeyProviderSpec,
11
+ } from "./configured-provider";
12
12
  import { BUDDY_PROVIDER_CAPABILITIES } from "./integrations/buddy/capabilities";
13
- import { ProviderRegistry, toRegistration, type ProviderModule } from "./provider-registry";
13
+ import {
14
+ ProviderRegistry,
15
+ toRegistration,
16
+ oauthCapability,
17
+ quotaCapability,
18
+ type ProviderModule,
19
+ type ProviderModuleCapabilities,
20
+ } from "./provider-registry";
14
21
  import { BUNDLED_PROVIDER_METADATA, PROVIDER_COMPATIBILITY_PROFILES, providerBaseUrl, providerRequiresAccount, providerUpstreamHost, providerDefaultWireFamily, type BundledProviderId } from "./provider-metadata";
15
22
  import { createAnthropicCompatibleAdapter } from "./integrations/anthropic";
16
23
  import { defineModel } from "./provider-model-definition";
@@ -31,6 +38,29 @@ function configuredProvider(
31
38
  };
32
39
  }
33
40
 
41
+ /**
42
+ * Extracts a bearer token from a JSON credential object when the stored secret
43
+ * is a JSON account export, falling back to the raw secret otherwise. Several
44
+ * discovery paths accept both a bare token and a JSON export, and each used to
45
+ * re-implement this same parse + key-pick; this keeps the reading in one place.
46
+ *
47
+ * Preserves the exact fallback semantics: an unparseable secret, or a JSON
48
+ * object with none of the recognized token keys, yields the raw secret.
49
+ */
50
+ function extractJsonCredentialToken(secret: string): string {
51
+ if (!secret.startsWith("{")) return secret;
52
+ try {
53
+ const parsed = JSON.parse(secret) as Record<string, unknown>;
54
+ const found = ["accessToken", "access_token", "token"].find(
55
+ (key) => typeof parsed[key] === "string" && (parsed[key] as string).length > 0,
56
+ );
57
+ if (found !== undefined) return parsed[found] as string;
58
+ } catch {
59
+ // Use the raw secret as the token.
60
+ }
61
+ return secret;
62
+ }
63
+
34
64
  /**
35
65
  * Qoder's live model list for one realm.
36
66
  *
@@ -60,18 +90,7 @@ function traeDiscovery(
60
90
  if (secret.length === 0 || fetcher === undefined) {
61
91
  return realm === "cn" ? TRAE_CN_MODELS : TRAE_INTL_MODELS;
62
92
  }
63
- let token = secret;
64
- if (secret.startsWith("{")) {
65
- try {
66
- const parsed = JSON.parse(secret) as Record<string, unknown>;
67
- const found = ["accessToken", "access_token", "token"].find(
68
- (key) => typeof parsed[key] === "string" && (parsed[key] as string).length > 0,
69
- );
70
- if (found !== undefined) token = parsed[found] as string;
71
- } catch {
72
- // Use the raw secret as the token.
73
- }
74
- }
93
+ const token = extractJsonCredentialToken(secret);
75
94
  const region = request.authState?.["region"];
76
95
  const rows = await discoverTraeModels({
77
96
  realm,
@@ -84,12 +103,15 @@ function traeDiscovery(
84
103
  if (rows.length === 0) return realm === "cn" ? TRAE_CN_MODELS : TRAE_INTL_MODELS;
85
104
  const fallback = realm === "cn" ? TRAE_CN_MODELS : TRAE_INTL_MODELS;
86
105
  const byId = new Map(fallback.map((model) => [model.modelId, model]));
106
+ // Return everything the upstream picker reports — the live listing is the
107
+ // truth for the account, including configs absent from the static roster.
108
+ // The static roster is only the fallback when discovery fails. A config
109
+ // discovered upstream gets the realm's first row as a template so it is
110
+ // routable with the shape this provider serves, carrying the window
111
+ // upstream reported.
87
112
  return rows.map((row) => {
88
113
  const existing = byId.get(row.id);
89
114
  if (existing === undefined) {
90
- // Discovered upstream but absent from the static roster: clone the
91
- // realm's first row so a new model is routable with the shape this
92
- // provider serves, carrying the window upstream reported.
93
115
  const template = fallback[0];
94
116
  if (template === undefined) return undefined;
95
117
  return { ...template, modelId: row.id, contextLimit: row.ctx ?? null };
@@ -315,6 +337,20 @@ export const PROVIDER_CAPABILITIES = {
315
337
  ...(fetcher === undefined ? {} : { fetcher }),
316
338
  }),
317
339
  },
340
+ devin: {
341
+ // Devin's chat wire is a Connect-RPC protobuf stream; the path is pinned
342
+ // here so a probe verifies dispatch actually calls it.
343
+ endpointPathsByWireFamily: { chat: "/exa.api_server_pb.ApiServerService/GetChatMessage" },
344
+ loadAdapter: async () => (await import("./integrations/devin/devin")).devinAdapter,
345
+ loadModels: async () => (await import("./integrations/devin/devin-catalog")).DEVIN_MODELS,
346
+ loadAuthentication: oauthCapability(() => import("./integrations/devin/devin-auth"), "devinOAuthClient"),
347
+ loadQuotaCollector: quotaCapability(() => import("./integrations/devin/devin-quota"), "fetchDevinQuota"),
348
+ loadModelDiscovery: async () => async ({ credential, fetcher }) =>
349
+ (await import("./integrations/devin/devin-catalog")).discoverDevinModels({
350
+ credential,
351
+ ...(fetcher === undefined ? {} : { fetcher }),
352
+ }),
353
+ },
318
354
  cerebras: {
319
355
  endpointPathsByWireFamily: { chat: "/chat/completions" },
320
356
  loadAdapter: async () => createApiKeyAdapter((await import("./integrations/cerebras")).CEREBRAS_SPEC),
@@ -514,6 +550,40 @@ export const PROVIDER_CAPABILITIES = {
514
550
  loadQuotaCollector: quotaCapability(() => import("./integrations/trae/trae-quota"), "fetchTraeCnQuota"),
515
551
  loadModelDiscovery: traeDiscovery("cn", "traecn"),
516
552
  },
553
+ freepi: {
554
+ loadAdapter: async () => (await import("./integrations/freepi/freepi")).createFreepiAdapter(),
555
+ loadModels: async () => (await import("./integrations/freepi/freepi-catalog")).FREEPI_MODELS,
556
+ // Free-pi login is a GitHub device flow; the issued JWT is the credential.
557
+ loadAuthentication: oauthCapability(() => import("./integrations/freepi/freepi-oauth"), "freepiOAuthClient"),
558
+ loadQuotaCollector: quotaCapability(() => import("./integrations/freepi/freepi-quota"), "fetchFreepiQuota"),
559
+ // Live `/client-version` (Bearer) is the catalog source; the static roster
560
+ // is the offline fallback.
561
+ loadModelDiscovery: async () => async (request: Parameters<ProviderModelDiscovery>[0]) => {
562
+ const { discoverFreepiModels } = await import("./integrations/freepi/freepi-discovery");
563
+ const { FREEPI_MODELS } = await import("./integrations/freepi/freepi-catalog");
564
+ const secret = request.credential.trim();
565
+ const fetcher = request.fetcher as unknown as typeof fetch | undefined;
566
+ if (secret.length === 0 || fetcher === undefined) return FREEPI_MODELS;
567
+ const token = extractJsonCredentialToken(secret);
568
+ const rows = await discoverFreepiModels({ token, fetcher });
569
+ if (rows.length === 0) return FREEPI_MODELS;
570
+ return rows;
571
+ },
572
+ },
573
+ perch: {
574
+ loadAdapter: async () => (await import("./integrations/perch/perch")).createPerchAdapter(),
575
+ loadModels: async () => (await import("./integrations/perch/perch-catalog")).PERCH_MODELS,
576
+ // Perch login is Supabase PKCE (Google/GitHub); the session blob
577
+ // (access/refresh token) is the credential, and the CLI refreshes it.
578
+ loadAuthentication: oauthCapability(() => import("./integrations/perch/perch-oauth"), "perchOAuthClient", { withRefresher: true }),
579
+ loadQuotaCollector: quotaCapability(() => import("./integrations/perch/perch-quota"), "fetchPerchQuota"),
580
+ // The hosted API exposes no public model list — Roost tiers are the only
581
+ // surface the CLI accepts, so discovery returns the static roster.
582
+ loadModelDiscovery: async () => async () => {
583
+ const { PERCH_MODELS } = await import("./integrations/perch/perch-catalog");
584
+ return PERCH_MODELS;
585
+ },
586
+ },
517
587
  inferhub: {
518
588
  loadAdapter: async () => (await import("./integrations/inferhub")).createInferhubAdapter(),
519
589
  // Live `/v1/models` is the primary source: the marketplace republishes its
@@ -527,6 +597,9 @@ export const PROVIDER_CAPABILITIES = {
527
597
  hermes: {
528
598
  loadAdapter: async () => createApiKeyAdapter((await import("./integrations/hermes")).HERMES_SPEC),
529
599
  loadModels: async () => (await import("./integrations/hermes")).HERMES_MODELS,
600
+ // Hermes accepts both API keys and the Nous Portal device-code OAuth flow
601
+ // (subscription route). The OAuth client is refreshable.
602
+ loadAuthentication: oauthCapability(() => import("./integrations/hermes/hermes-oauth"), "hermesOAuthClient", { withRefresher: true }),
530
603
  // `/v1/models` is open and states each row's real limits, so the free
531
604
  // allowance tracks upstream instead of a hand-kept list. The static list
532
605
  // above stays as the offline fallback for a fetch that fails.
@@ -605,9 +678,7 @@ export const PROVIDER_CAPABILITIES = {
605
678
  // dressed ZCode client request (see the integration). The credential is a
606
679
  // ZCode login JWT — pasted, or minted by the sign-in flow below.
607
680
  loadAdapter: async () =>
608
- createApiKeyAdapter(
609
- (await import("./integrations/zcode-start-plan/provider")).ZCODE_START_PLAN_SPEC,
610
- ),
681
+ (await import("./integrations/zcode-start-plan/provider")).createZcodeStartPlanAdapter(),
611
682
  loadModels: async () =>
612
683
  (await import("./integrations/zcode-start-plan/provider")).ZCODE_START_PLAN_MODELS,
613
684
  // The device flow stores the issued ZCode login JWT, not a Coding Plan key.
@@ -718,10 +789,29 @@ export const PROVIDER_CAPABILITIES = {
718
789
  responses: "/responses",
719
790
  },
720
791
  loadAdapter: async () => createApiKeyAdapter(GENERIC_API_KEY_SPECS.ollamacloud),
721
- loadModels: async () => (await import("./integrations/ollamacloud-models")).OLLAMACLOUD_MODELS,
722
- loadQuotaCollector: quotaCapability(() => import("./integrations/ollamacloud-quota"), "fetchOllamaQuota"),
792
+ loadModels: async () => (await import("./integrations/ollamacloud")).OLLAMACLOUD_MODELS,
793
+ loadQuotaCollector: quotaCapability(() => import("./integrations/ollamacloud"), "fetchOllamaQuota"),
723
794
  loadModelDiscovery: openAIModelDiscovery("ollamacloud", { headers: (credential) => ({ authorization: `Bearer ${credential}` }) }),
724
795
  },
796
+ freebuff: {
797
+ // Freebuff chat is OpenAI-compatible on `/api/v1/chat/completions`, but the
798
+ // adapter runs a stateful preflight (session admission + agent-runs START)
799
+ // and a device-signature header set — see the integration.
800
+ endpointPathsByWireFamily: { chat: "/api/v1/chat/completions" },
801
+ loadAdapter: async () => (await import("./integrations/freebuff/freebuff")).createFreebuffAdapter(),
802
+ loadModels: async () => (await import("./integrations/freebuff/freebuff-catalog")).FREEBUFF_MODELS,
803
+ loadAuthentication: oauthCapability(() => import("./integrations/freebuff/freebuff-oauth"), "freebuffOAuthClient"),
804
+ loadQuotaCollector: quotaCapability(() => import("./integrations/freebuff/freebuff-quota"), "fetchFreebuffQuota"),
805
+ loadModelDiscovery: async () =>
806
+ (await import("./integrations/freebuff/freebuff-discovery")).freebuffModelDiscovery(),
807
+ },
808
+ zro: {
809
+ endpointPathsByWireFamily: { messages: "/v1/messages" },
810
+ loadAdapter: async () => (await import("./integrations/zro/zro")).createZroAdapter(),
811
+ loadModels: async () => (await import("./integrations/zro/zro")).ZRO_MODELS,
812
+ loadQuotaCollector: quotaCapability(() => import("./integrations/zro/zro"), "fetchZroQuota"),
813
+ loadModelDiscovery: async () => (await import("./integrations/zro/zro")).zroModelDiscovery()(),
814
+ },
725
815
 
726
816
  ...createDiscoveryBackedProviderCapabilities(openAIModelDiscovery),
727
817
 
@@ -770,7 +860,7 @@ export const PROVIDER_CAPABILITIES = {
770
860
  // the provider usable before anyone syncs.
771
861
  dashscope: {
772
862
  ...discoveryBackedCapabilities("dashscope", GENERIC_API_KEY_SPECS.dashscope, openAIModelDiscovery),
773
- loadModels: async () => (await import("./integrations/dashscope-models")).DASHSCOPE_MODELS,
863
+ loadModels: async () => (await import("./integrations/alibabacp/dashscope-models")).DASHSCOPE_MODELS,
774
864
  },
775
865
 
776
866
  // Anthropic-Messages providers reached with a plain key. The wire path is
@@ -58,6 +58,11 @@ export const PROBE_REASONING_EFFORTS = ["auto", "minimal", "low", "medium", "hig
58
58
  /** One accepted probe reasoning effort. `auto` means "send no reasoning intent". */
59
59
  export type ProbeReasoningEffort = (typeof PROBE_REASONING_EFFORTS)[number];
60
60
 
61
+ /** Modelprobe modes as a runtime tuple, so the route schema projects one list. */
62
+ export const PROBE_MODES = ["fast", "detail"] as const;
63
+ /** `detail` is the default when `mode` is absent (D39). */
64
+ export type ProbeMode = (typeof PROBE_MODES)[number];
65
+
61
66
  /** Request accepted for a one-shot model connectivity test. `route`
62
67
  * disambiguates when a model id is registered under multiple endpoint
63
68
  * paths; omit it to probe against the model's already-registered wire
@@ -85,6 +90,13 @@ export interface ProbeModelRequest {
85
90
  * result the richest available source of truth.
86
91
  */
87
92
  surface?: "default" | "cosy" | "grpc" | "ide";
93
+ /**
94
+ * `fast` is a cheap liveness check: 32 output tokens, a 10s timeout, no
95
+ * retry, no payload-body capture, compact telemetry, and an 80-char sample.
96
+ * `detail` (the default when absent) is the full diagnostic probe.
97
+ * Health recording is identical in both modes.
98
+ */
99
+ mode?: ProbeMode;
88
100
  }
89
101
  export interface ProbeModelResult {
90
102
  accountId?: string;
@@ -23,7 +23,8 @@ import type {
23
23
  WireFamily,
24
24
  } from "../../protocol/canonical-model";
25
25
  import type { CompatibilityProfile } from "../provider-metadata";
26
- import type { ProbeModelRequest } from "./discovery-types";
26
+ import type { ProbeModelRequest, ProbeMode } from "./discovery-types";
27
+ import type { ModelProbeMode } from "../../console/settings/contracts";
27
28
  import {
28
29
  constrainWireFamily,
29
30
  discoveryPathsFor,
@@ -471,8 +472,9 @@ export async function selectProbeAccount(args: {
471
472
  * back to the generic OpenAI-compatible adapter so probe/dispatch still works.
472
473
  * The low-level compatible adapter is used directly to avoid importing concrete
473
474
  * integrations from discovery (which would violate the provider-architecture
474
- * layering test). `loadOne` returning `undefined` means "no bundled adapter";
475
- * a throw is a registry failure and propagates rather than being reported as
475
+ * layering test). `resolve(..., { force: true })` rebuilds the bundled adapter
476
+ * against the current registration; `undefined` means "no bundled adapter"; a
477
+ * throw is a registry failure and propagates rather than being reported as
476
478
  * "no adapter registered".
477
479
  */
478
480
  export async function resolveProbeAdapter(args: {
@@ -481,7 +483,7 @@ export async function resolveProbeAdapter(args: {
481
483
  readonly providerWireRow: ProbeProviderRow | undefined;
482
484
  }): Promise<ProviderAdapter | undefined> {
483
485
  const { providerRegistry, providerId, providerWireRow } = args;
484
- let adapter = await providerRegistry.loadOne(providerId);
486
+ let adapter = await providerRegistry.resolve(providerId, { force: true });
485
487
  if (!adapter) {
486
488
  try {
487
489
  if (providerWireRow?.baseUrl) {
@@ -509,9 +511,26 @@ export interface ProbeReasoning {
509
511
  summary_mode: "auto" | "concise" | "detailed";
510
512
  }
511
513
 
514
+ /** Default fast-probe timeout, in seconds (D39/D40). */
515
+ export const PROBE_FAST_DEFAULT_TIMEOUT_SECONDS = 10;
516
+ /** Default fast-probe output allowance, in tokens (D40). */
517
+ export const PROBE_FAST_MAX_OUTPUT_TOKENS = 64;
518
+ /** Fast-probe default prompt: a neutral greeting, not an identity question. */
519
+ export const PROBE_FAST_DEFAULT_PROMPT = "ping";
520
+ /** Fast-probe sample bound, in characters (D40). */
521
+ export const PROBE_FAST_SAMPLE_MAX_CHARS = 80;
522
+
512
523
  /** Tenant probe preferences that shape the request and telemetry. */
513
524
  export interface ProbePreferences {
514
525
  readonly probeReasoning: ProbeReasoning | undefined;
526
+ /** Effective probe mode: an explicit request wins over the tenant default. */
527
+ readonly mode: ProbeMode;
528
+ /** Timeout in ms for `fast`; `undefined` keeps `detail`'s 30s budget. */
529
+ readonly timeoutMs: number | undefined;
530
+ /** Token allowance for the canonical request; only `fast` overrides it. */
531
+ readonly maxOutputTokens: number | undefined;
532
+ /** `fast` suppresses payload-body capture and trims telemetry. */
533
+ readonly compactTelemetry: boolean;
515
534
  /**
516
535
  * The tenant's resolved capture policy for the probe, through the same
517
536
  * `resolvePayloadCapture` path every dispatched request uses.
@@ -545,6 +564,8 @@ export async function loadProbePreferences(args: {
545
564
  }): Promise<ProbePreferences> {
546
565
  const { db, tenantId, wireFamily, request } = args;
547
566
  let probeReasoning: ProbeReasoning | undefined;
567
+ let configuredMode: ModelProbeMode = "detail";
568
+ let configuredFastTimeoutSeconds = PROBE_FAST_DEFAULT_TIMEOUT_SECONDS;
548
569
  let payloadCapture: ProbePreferences["payloadCapture"] = {
549
570
  enabled: false,
550
571
  mode: "none",
@@ -568,6 +589,14 @@ export async function loadProbePreferences(args: {
568
589
  const raw = preferences?.responsesReasoningSummary;
569
590
  const mode: "auto" | "concise" | "detailed" =
570
591
  raw === "auto" || raw === "concise" || raw === "detailed" ? raw : "detailed";
592
+ // The tenant's settings default is `detail` when unset (D39); an explicit
593
+ // per-request `mode` still wins below.
594
+ configuredMode = preferences?.modelProbeMode === "fast" ? "fast" : "detail";
595
+ const configuredTimeout = preferences?.modelProbeFastTimeoutSeconds;
596
+ configuredFastTimeoutSeconds =
597
+ typeof configuredTimeout === "number" && Number.isFinite(configuredTimeout)
598
+ ? Math.min(Math.max(configuredTimeout, 1), 120)
599
+ : PROBE_FAST_DEFAULT_TIMEOUT_SECONDS;
571
600
  // Unset matches the settings default: off. Only an explicit choice
572
601
  // captures, and at the tenant's own depth/retention — the same resolution
573
602
  // `resolvePayloadCapture` performs for dispatched requests, read from the
@@ -599,31 +628,22 @@ export async function loadProbePreferences(args: {
599
628
  };
600
629
  }
601
630
  }
602
- return { probeReasoning, payloadCapture };
603
- }
604
-
605
- /**
606
- * The probe's default identity prompt (`What model are you...`) works for
607
- * every Qoder roster row except `cmodel` (virtual id `cantus`): that row's
608
- * gRPC surface answers the identity question with `406 Upstream error [stream]`
609
- * from the upstream proxy (verified live 2026-11-04; dmodel/qmodel/smodel all
610
- * accept it). Returns the neutral replacement prompt when the probe targets
611
- * that row with no explicit prompt, `undefined` otherwise.
612
- *
613
- * The replacement prompt must never *ask* an identity question: the upstream
614
- * guardrail is content-based and swallows the reply (empty sample) for any
615
- * phrasing that interrogates identity — even indirect ones (`what would you
616
- * call yourself`, `which model are you`, `perkenalkan dirimu`). A plain
617
- * greeting that *asserts* the wrong identity (`halo gpt`) makes the model
618
- * correct us on its own, and returns a sample 3/3 runs (verified live
619
- * 2026-11-04). We keep that phrasing — it is 100% consistent and the model
620
- * names itself ("saya Claude... buatan Anthropic") without us ever asking.
621
- */
622
- export function qoderCmodelProbePrompt(providerId: string, modelId: string, prompt: string | undefined): string | undefined {
623
- if (prompt !== undefined) return undefined;
624
- if (providerId !== "qoder" && providerId !== "qodercn") return undefined;
625
- if (modelId !== "cmodel" && modelId !== "cantus") return undefined;
626
- return "halo gpt";
631
+ const effectiveMode: ProbeMode = request.mode ?? configuredMode;
632
+ const fast = effectiveMode === "fast";
633
+ return {
634
+ probeReasoning,
635
+ mode: effectiveMode,
636
+ // `detail` keeps its exact 30s budget; `fast` uses the tenant's setting.
637
+ ...(fast ? { timeoutMs: configuredFastTimeoutSeconds * 1000 } : { timeoutMs: undefined }),
638
+ ...(fast ? { maxOutputTokens: PROBE_FAST_MAX_OUTPUT_TOKENS } : { maxOutputTokens: undefined }),
639
+ compactTelemetry: fast,
640
+ // `fast` never tees provider payload bodies (D40). The reported-model read
641
+ // still needs the exchange wrapper, so capture mode, not the wrapper, is
642
+ // what changes.
643
+ payloadCapture: fast
644
+ ? { enabled: false, mode: "none", depth: "minimum", retentionMs: payloadRetentionMs() }
645
+ : payloadCapture,
646
+ };
627
647
  }
628
648
 
629
649
  /**
@@ -638,10 +658,30 @@ export function buildProbeCanonicalRequest(args: {
638
658
  readonly request: ProbeModelRequest;
639
659
  readonly probeReasoning: ProbeReasoning | undefined;
640
660
  readonly sourceSurface: SourceSurface;
661
+ /** `fast` overrides the token allowance without changing the prompt (D42). */
662
+ readonly maxOutputTokens?: number;
663
+ /**
664
+ * Provider-mandated system prompt (adapter `systemPrompt()`), injected as
665
+ * the probe's system turn so upstreams that fingerprint it accept the
666
+ * probe.
667
+ */
668
+ readonly providerSystemPrompt?: string | undefined;
669
+ /**
670
+ * A provider-specific default probe prompt, used when the operator sent no
671
+ * prompt. Lets a provider whose policy gate flags repeated identical probes
672
+ * (Freebuff: `prompt_policy_refused` / "same message sent over and over")
673
+ * receive a minimal, per-model-varying probe instead of the shared identity
674
+ * question every provider otherwise sends.
675
+ */
676
+ readonly defaultPromptOverride?: string | undefined;
641
677
  }): CanonicalRequest {
642
- const { modelId, request, probeReasoning, sourceSurface } = args;
678
+ const { modelId, request, probeReasoning, sourceSurface, maxOutputTokens, providerSystemPrompt, defaultPromptOverride } = args;
679
+ const fast = maxOutputTokens === PROBE_FAST_MAX_OUTPUT_TOKENS;
643
680
  return {
644
681
  model: modelId,
682
+ ...(providerSystemPrompt && providerSystemPrompt.trim()
683
+ ? { system: [{ kind: "text", text: providerSystemPrompt }] }
684
+ : {}),
645
685
  messages: [
646
686
  {
647
687
  role: "user",
@@ -650,7 +690,8 @@ export function buildProbeCanonicalRequest(args: {
650
690
  kind: "text",
651
691
  text:
652
692
  request.prompt ??
653
- "What model are you, and what is your knowledge cutoff date? Answer in one sentence.",
693
+ defaultPromptOverride ??
694
+ (fast ? PROBE_FAST_DEFAULT_PROMPT : "What model are you, and what is your knowledge cutoff date? Answer in one sentence."),
654
695
  },
655
696
  ],
656
697
  },
@@ -662,8 +703,8 @@ export function buildProbeCanonicalRequest(args: {
662
703
  // class of refusal that answers `400 request illegal`. Matching the
663
704
  // caller's own small budget keeps the probe the same shape as the traffic
664
705
  // it is meant to predict.
665
- max_tokens: request.maxOutputTokens ?? 256,
666
- max_output_tokens: request.maxOutputTokens ?? 256,
706
+ max_tokens: request.maxOutputTokens ?? maxOutputTokens ?? 256,
707
+ max_output_tokens: request.maxOutputTokens ?? maxOutputTokens ?? 256,
667
708
  // No temperature. A real dispatch forwards whatever the client sent, and
668
709
  // the client rarely sends one; pinning 0.2 here made the probe a
669
710
  // different request from the traffic it is supposed to predict. The