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
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Devin model catalog: live discovery via `GetCliModelConfigs` plus a static
3
+ * seed for boot. Ported from oh-my-pi (`discovery/devin.ts`, MIT) with the
4
+ * Cartethyia `defineModel` shape.
5
+ */
6
+
7
+ import { defineModel, type ModelDefinition } from "../../provider-model-definition";
8
+ import { callDevinUnary } from "./devin-http";
9
+ import {
10
+ DEVIN_CHAT_MESSAGE_PATH,
11
+ DEVIN_GET_CLI_MODEL_CONFIGS_PATH,
12
+ DEFAULT_CONTEXT_WINDOW,
13
+ DEFAULT_MAX_TOKENS,
14
+ DEVIN_DEFAULT_BASE_URL,
15
+ DEVIN_INTERNAL_MODEL_DISPLAYS,
16
+ devinDiscoveryMetadata,
17
+ } from "./devin-shared";
18
+ import { DevinMessageTypes } from "./protocol/devin-proto";
19
+
20
+ const DISCOVERY_TIMEOUT_MS = 15_000;
21
+
22
+ /** Static seed shown before discovery succeeds (boot-safe, synchronous). */
23
+ export const DEVIN_MODELS: readonly ModelDefinition[] = [
24
+ defineModel({
25
+ id: "swe-1-6-fast",
26
+ providerId: "devin",
27
+ wireFamily: "chat",
28
+ endpoint: DEVIN_CHAT_MESSAGE_PATH,
29
+ ctx: DEFAULT_CONTEXT_WINDOW,
30
+ out: 128_000,
31
+ // No vision: paired live control showed both available models either
32
+ // ignore or reject inline images. Declaring it would route images into a
33
+ // guaranteed failure.
34
+ reasoning: true,
35
+ toolCall: true,
36
+ }),
37
+ // `swe-1-6` removed: not present in the live `GetCliModelConfigs` roster on
38
+ // this account (1003 of 1010 configs are disabled) and a chat dispatch to
39
+ // it failed with `failed_precondition`.
40
+ // Operator-declared lanes. The upstream catalog has not been fetched live
41
+ // yet, so these rows are pinned from the measured spec rather than generated.
42
+ defineModel({
43
+ id: "swe-1-6-slow",
44
+ providerId: "devin",
45
+ wireFamily: "chat",
46
+ endpoint: DEVIN_CHAT_MESSAGE_PATH,
47
+ ctx: 200_000,
48
+ out: 128_000,
49
+ reasoning: true,
50
+ toolCall: true,
51
+ }),
52
+ defineModel({
53
+ id: "swe-2-flash-medium",
54
+ providerId: "devin",
55
+ wireFamily: "chat",
56
+ endpoint: DEVIN_CHAT_MESSAGE_PATH,
57
+ // Live `GetCliModelConfigs` (2026-11-07): ctx=262144, maxOutput=131072,
58
+ // features = thinking + tools. This uid is the account default.
59
+ ctx: 262_144,
60
+ out: 131_072,
61
+ reasoning: true,
62
+ toolCall: true,
63
+ }),
64
+ ];
65
+
66
+ interface RawModelConfig {
67
+ modelUid?: string;
68
+ label?: string;
69
+ disabled?: boolean;
70
+ supportsImages?: boolean;
71
+ maxTokens?: number;
72
+ description?: string;
73
+ isNew?: boolean;
74
+ isBeta?: boolean;
75
+ isRecommended?: boolean;
76
+ isDefaultModelInFamily?: boolean;
77
+ modelInfo?: {
78
+ maxTokens?: number;
79
+ maxOutputTokens?: number;
80
+ displayOption?: number;
81
+ harnessUids?: string[];
82
+ isModelRouter?: boolean;
83
+ modelFeatures?: { supportsImages?: boolean; supportsToolCalls?: boolean; supportsThinking?: boolean };
84
+ };
85
+ modelDimensions?: { label?: string; value?: number; denominator?: string; kind?: number }[];
86
+ }
87
+
88
+ const REASONING_LABEL_PATTERN = /think|thinking|minimal|high|medium|low|xhigh|max|reasoning/i;
89
+ const NO_REASONING_LABEL_PATTERN = /\bno thinking\b/i;
90
+
91
+ function supportsThinking(config: RawModelConfig): boolean {
92
+ const features = config.modelInfo?.modelFeatures;
93
+ if (features) return features.supportsThinking === true;
94
+ const label = config.label ?? "";
95
+ if (NO_REASONING_LABEL_PATTERN.test(label)) return false;
96
+ return REASONING_LABEL_PATTERN.test(label);
97
+ }
98
+
99
+ function modelCost(config: RawModelConfig): { input: number; output: number; cache_read: number } {
100
+ let input = 0;
101
+ let output = 0;
102
+ let cache_read = 0;
103
+ const dims = config.modelDimensions ?? [];
104
+ for (const dim of dims) {
105
+ if (dim.kind !== 1 && dim.kind !== 2) continue; // COST / COST_FUZZY
106
+ if ((dim.label ?? "").toLowerCase() === "sidekick") break;
107
+ let value = dim.value ?? 0;
108
+ const denom = dim.denominator ?? "";
109
+ const m = denom.match(/(\d+(?:\.\d+)?)\s*([kmb])?/i);
110
+ let divisor = 1_000_000;
111
+ if (m) {
112
+ const num = Number(m[1]);
113
+ const suffix = m[2]?.toLowerCase();
114
+ if (suffix === "k") divisor = num * 1_000;
115
+ else if (suffix === "m") divisor = num * 1_000_000;
116
+ else if (suffix === "b") divisor = num * 1_000_000_000;
117
+ else divisor = num;
118
+ }
119
+ value = (value * 1_000_000) / divisor;
120
+ const label = (dim.label ?? "").toLowerCase();
121
+ if (label.includes("input")) input = Math.round(value * 1e6) / 1e6;
122
+ else if (label.includes("output")) output = Math.round(value * 1e6) / 1e6;
123
+ else if (label.includes("cached")) cache_read = Math.round(value * 1e6) / 1e6;
124
+ }
125
+ return { input, output, cache_read };
126
+ }
127
+
128
+ export interface DevinDiscoveryInput {
129
+ readonly credential: string;
130
+ readonly fetcher?: typeof fetch;
131
+ }
132
+
133
+ /** Live discovery: GetCliModelConfigs -> ModelDefinition rows. */
134
+ export async function discoverDevinModels(
135
+ input: DevinDiscoveryInput,
136
+ ): Promise<readonly ModelDefinition[] | null> {
137
+ const { credential, fetcher } = input;
138
+ const request = {
139
+ metadata: devinDiscoveryMetadata(credential),
140
+ };
141
+ const response = await callDevinUnary<{ clientModelConfigs?: RawModelConfig[]; defaultOverrideModelConfig?: { modelUid?: string } }>(
142
+ DEVIN_GET_CLI_MODEL_CONFIGS_PATH,
143
+ DevinMessageTypes.GetCliModelConfigsRequest,
144
+ DevinMessageTypes.GetCliModelConfigsResponse,
145
+ request,
146
+ {
147
+ baseUrl: DEVIN_DEFAULT_BASE_URL,
148
+ ...(fetcher === undefined ? {} : { fetchImpl: fetcher }),
149
+ signal: AbortSignal.timeout(DISCOVERY_TIMEOUT_MS),
150
+ },
151
+ );
152
+ const configs = response.clientModelConfigs ?? [];
153
+ const defaultUid = response.defaultOverrideModelConfig?.modelUid?.trim();
154
+
155
+ const rows: ModelDefinition[] = [];
156
+ const seen = new Set<string>();
157
+ for (const config of configs) {
158
+ if (config.disabled) continue;
159
+ const uid = config.modelUid?.trim();
160
+ if (!uid || seen.has(uid)) continue;
161
+ const displayOption = config.modelInfo?.displayOption ?? 0;
162
+ if (DEVIN_INTERNAL_MODEL_DISPLAYS.has(displayOption)) continue;
163
+ seen.add(uid);
164
+
165
+ const features = config.modelInfo?.modelFeatures;
166
+ // Operator-pinned lanes, confirmed against live `GetCliModelConfigs`:
167
+ // `swe-2-flash-medium` = 262144/131072 (account default),
168
+ // `swe-1-6-slow` = 200000/128000.
169
+ const pinnedContext = uid === "swe-2-flash-medium" ? 262_144 : uid === "swe-1-6-slow" ? 200_000 : undefined;
170
+ const pinnedOutput = uid === "swe-2-flash-medium" ? 131_072 : undefined;
171
+ const contextLimit =
172
+ pinnedContext ?? ((config.maxTokens ?? 0) > 0 ? config.maxTokens! : (config.modelInfo?.maxTokens ?? 0) > 0 ? config.modelInfo!.maxTokens! : DEFAULT_CONTEXT_WINDOW);
173
+ const outputLimit = pinnedOutput ?? ((config.modelInfo?.maxOutputTokens ?? 0) > 0 ? config.modelInfo!.maxOutputTokens! : DEFAULT_MAX_TOKENS);
174
+ // `supportsImages` from the server is NOT an entitlement: live paired
175
+ // control showed `swe-1-6-slow` (supportsImages=true) answering the same
176
+ // "cannot see" with and without an ImageData payload. Never advertise
177
+ // vision for this provider; the adapter drops image parts entirely.
178
+ const cost = modelCost(config);
179
+
180
+ rows.push(
181
+ defineModel({
182
+ id: uid,
183
+ providerId: "devin",
184
+ wireFamily: "chat",
185
+ endpoint: DEVIN_CHAT_MESSAGE_PATH,
186
+ ctx: contextLimit,
187
+ out: outputLimit,
188
+ reasoning: supportsThinking(config),
189
+ toolCall: features ? features.supportsToolCalls !== false : true,
190
+ free: cost.input === 0 && cost.output === 0,
191
+ ...(config.isNew ? { warnings: [{ kind: "is_new", message: "New model", severity: "info" as const }] } : {}),
192
+ ...(config.isRecommended ? { warnings: [{ kind: "recommended", message: "Recommended by Devin", severity: "info" as const }] } : {}),
193
+ }),
194
+ );
195
+ }
196
+
197
+ // Account default wins: promote its row to default (first in list).
198
+ if (defaultUid && seen.has(defaultUid)) {
199
+ const idx = rows.findIndex((r) => r.modelId === defaultUid);
200
+ if (idx > 0) {
201
+ const [row] = rows.splice(idx, 1);
202
+ rows.unshift(row!);
203
+ }
204
+ }
205
+
206
+ return rows;
207
+ }
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Devin unary Connect-RPC client (`application/proto`).
3
+ *
4
+ * Responses may arrive as raw protobuf or gzipped protobuf (Connect servers
5
+ * compress when the client advertises `connect-accept-encoding: gzip`), so
6
+ * decode always has a gunzip fallback. Ported from oh-my-pi
7
+ * (`packages/catalog/src/wire/devin-proto.ts` + `discovery/devin.ts`, MIT).
8
+ */
9
+
10
+ import { gunzipSync } from "node:zlib";
11
+ import type { Type } from "protobufjs";
12
+ import { GatewayError } from "../../../protocol/gateway-error";
13
+ import { DEVIN_CONNECT_UA } from "./devin-shared";
14
+
15
+ export interface DevinUnaryOptions {
16
+ readonly baseUrl?: string;
17
+ readonly fetchImpl?: typeof fetch;
18
+ readonly signal?: AbortSignal;
19
+ readonly timeoutMs?: number;
20
+ /** Include `connect-go` User-Agent (chat path) rather than plain unary. */
21
+ readonly connectGoUA?: boolean;
22
+ }
23
+
24
+ /** Calls one unary RPC and decodes the response message. */
25
+ export async function callDevinUnary<T extends object>(
26
+ path: string,
27
+ requestType: Type,
28
+ responseType: Type,
29
+ request: object,
30
+ options: DevinUnaryOptions = {},
31
+ ): Promise<T> {
32
+ const baseUrl = (options.baseUrl ?? "https://server.codeium.com").replace(/\/+$/, "");
33
+ const fetcher = options.fetchImpl ?? fetch;
34
+ const body = Buffer.from(requestType.encode(request).finish());
35
+
36
+ const headers: Record<string, string> = {
37
+ "content-type": "application/proto",
38
+ "connect-protocol-version": "1",
39
+ accept: "*/*",
40
+ };
41
+ if (options.connectGoUA) headers["user-agent"] = DEVIN_CONNECT_UA;
42
+
43
+ const signal =
44
+ options.signal === undefined
45
+ ? options.timeoutMs !== undefined
46
+ ? AbortSignal.timeout(options.timeoutMs)
47
+ : undefined
48
+ : options.timeoutMs !== undefined
49
+ ? AbortSignal.any([options.signal, AbortSignal.timeout(options.timeoutMs)])
50
+ : options.signal;
51
+
52
+ const response = await fetcher(`${baseUrl}${path}`, {
53
+ method: "POST",
54
+ headers,
55
+ body,
56
+ ...(signal === undefined ? {} : { signal }),
57
+ });
58
+
59
+ const buf = Buffer.from(await response.arrayBuffer());
60
+ if (!response.ok) {
61
+ const text = buf.subarray(0, 2048).toString("utf8");
62
+ throw new GatewayError(
63
+ "upstream_unprocessable",
64
+ response.status,
65
+ `Devin upstream error ${response.status}: ${text} (request {requestId})`,
66
+ { providerId: "devin", upstreamCode: String(response.status) },
67
+ "upstream",
68
+ );
69
+ }
70
+
71
+ return decodeDevinUnary<T>(responseType, buf);
72
+ }
73
+
74
+ /** Decodes a unary response, trying raw protobuf then gunzip. */
75
+ export function decodeDevinUnary<T extends object>(type: Type, buf: Buffer): T {
76
+ try {
77
+ return type.decode(buf) as T;
78
+ } catch {
79
+ try {
80
+ return type.decode(gunzipSync(buf)) as T;
81
+ } catch {
82
+ throw new GatewayError(
83
+ "internal_error",
84
+ 500,
85
+ "Devin upstream returned an undecodable response (request {requestId})",
86
+ { providerId: "devin" },
87
+ "upstream",
88
+ );
89
+ }
90
+ }
91
+ }
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Devin usage/quota collector via `GetUserStatus` (SeatManagementService).
3
+ *
4
+ * Ported from oh-my-pi (`usage/devin.ts`, MIT) onto Cartethyia's
5
+ * `QuotaFetcher` contract. Never throws — a failed read returns a null
6
+ * error result so the usage pipeline stays best-effort.
7
+ */
8
+
9
+ import type { ProviderQuotaResult, ProviderQuotaWindow, FetchLike } from "../../quota/quota-contracts";
10
+ import { callDevinUnary } from "./devin-http";
11
+ import { identityFromDevinUserStatus } from "./devin-auth";
12
+ import {
13
+ DEVIN_DEFAULT_BASE_URL,
14
+ DEVIN_GET_USER_STATUS_PATH,
15
+ devinCliMetadata,
16
+ } from "./devin-shared";
17
+ import { DevinEnums, DevinMessageTypes, fromEnum } from "./protocol/devin-proto";
18
+
19
+ const MICROS_PER_USD = 1_000_000;
20
+
21
+ interface RawUserStatusResponse {
22
+ userStatus?: {
23
+ teamId?: string;
24
+ email?: string;
25
+ teamsTier?: number;
26
+ userId?: string;
27
+ planStatus?: RawPlanStatus;
28
+ };
29
+ planInfo?: RawPlanInfo;
30
+ }
31
+
32
+ interface RawPlanInfo {
33
+ teamsTier?: number;
34
+ planName?: string;
35
+ monthlyPromptCredits?: string | number;
36
+ monthlyFlowCredits?: string | number;
37
+ monthlyFlexCreditPurchaseAmount?: string | number;
38
+ devinInfo?: { orgId?: string; accountDisplayName?: string };
39
+ billingStrategy?: number;
40
+ hideDailyQuota?: boolean;
41
+ hideWeeklyQuota?: boolean;
42
+ }
43
+
44
+ interface RawPlanStatus {
45
+ planInfo?: RawPlanInfo;
46
+ planStart?: string | number;
47
+ planEnd?: string | number;
48
+ availablePromptCredits?: string | number;
49
+ availableFlowCredits?: string | number;
50
+ availableFlexCredits?: string | number;
51
+ usedPromptCredits?: string | number;
52
+ usedFlowCredits?: string | number;
53
+ usedFlexCredits?: string | number;
54
+ overageBalanceMicros?: string | number;
55
+ dailyQuotaRemainingPercent?: number;
56
+ weeklyQuotaRemainingPercent?: number;
57
+ dailyQuotaResetAtUnix?: string | number;
58
+ weeklyQuotaResetAtUnix?: string | number;
59
+ }
60
+
61
+ /** protobufjs returns a Long-like object for int64 fields; never coerce it via String(). */
62
+ function toNum(v: unknown): number {
63
+ if (v === undefined || v === null) return 0;
64
+ if (typeof v === "number") return Number.isFinite(v) ? v : 0;
65
+ if (typeof v === "string") {
66
+ const n = Number(v);
67
+ return Number.isFinite(n) ? n : 0;
68
+ }
69
+ if (typeof v === "object" && "low" in v && "high" in v) {
70
+ const low = Number((v as { low: unknown }).low);
71
+ const high = Number((v as { high: unknown }).high);
72
+ if (!Number.isFinite(low) || !Number.isFinite(high)) return 0;
73
+ // Signed low/high pair → JS number (values here are small credits/timestamps).
74
+ return high * 0x1_0000_0000 + (low >>> 0);
75
+ }
76
+ return 0;
77
+ }
78
+
79
+ function tierLabel(tier: number | undefined): string {
80
+ const name = fromEnum(DevinEnums.TeamsTier, tier);
81
+ return name === "UNSPECIFIED" ? "" : name.replace(/_/g, " ").replace(/\b\w/g, (c: string) => c.toUpperCase());
82
+ }
83
+
84
+ function creditWindow(
85
+ id: string,
86
+ label: string,
87
+ limit: number,
88
+ used: number,
89
+ available: number,
90
+ ): ProviderQuotaWindow | undefined {
91
+ if (limit === 0 && used === 0 && available === 0) return undefined;
92
+ return {
93
+ kind: id,
94
+ label,
95
+ accounting: "pooled",
96
+ usedPercent: limit > 0 ? Math.min(100, (used / limit) * 100) : null,
97
+ remainingPercent: limit > 0 ? Math.min(100, Math.max(0, (available / limit) * 100)) : null,
98
+ resetsAt: null,
99
+ used,
100
+ limit,
101
+ remaining: available,
102
+ recurring: true,
103
+ };
104
+ }
105
+
106
+ function quotaWindow(
107
+ id: string,
108
+ label: string,
109
+ remainingPercent: number | undefined,
110
+ resetAtUnix: unknown,
111
+ ): ProviderQuotaWindow | undefined {
112
+ if (remainingPercent === undefined) return undefined;
113
+ const used = Math.max(0, 100 - remainingPercent);
114
+ const resetSeconds = toNum(resetAtUnix);
115
+ const resetsAt = resetSeconds > 0 ? new Date(resetSeconds * 1000).toISOString() : null;
116
+ return {
117
+ kind: id,
118
+ label,
119
+ accounting: "independent",
120
+ usedPercent: used,
121
+ remainingPercent,
122
+ resetsAt,
123
+ recurring: true,
124
+ };
125
+ }
126
+
127
+ export async function fetchDevinQuota(
128
+ credential: string,
129
+ fetcher: FetchLike,
130
+ ): Promise<ProviderQuotaResult> {
131
+ const result: ProviderQuotaResult = { source: "devin", plan: null, windows: [], error: null };
132
+ try {
133
+ const response = await callDevinUnary<RawUserStatusResponse>(
134
+ DEVIN_GET_USER_STATUS_PATH,
135
+ DevinMessageTypes.GetUserStatusRequest,
136
+ DevinMessageTypes.GetUserStatusResponse,
137
+ { metadata: devinCliMetadata(credential) },
138
+ { baseUrl: DEVIN_DEFAULT_BASE_URL, fetchImpl: fetcher as unknown as typeof fetch, signal: AbortSignal.timeout(15_000) },
139
+ );
140
+
141
+ const plan = response.planInfo ?? response.userStatus?.planStatus?.planInfo ?? undefined;
142
+ const planStatus = response.userStatus?.planStatus;
143
+ if (!plan || !planStatus) return { ...result, error: "Devin returned no plan data" };
144
+
145
+ const planName = plan.planName?.trim() || tierLabel(plan.teamsTier ?? response.userStatus?.teamsTier);
146
+ // Prefer the upstream email/display name over the opaque team tag; fall
147
+ // back to the team id only when the upstream reports nothing friendlier.
148
+ const accountLabel =
149
+ identityFromDevinUserStatus(response) ??
150
+ (plan.devinInfo?.orgId?.trim() || response.userStatus?.teamId?.trim() || undefined);
151
+
152
+ const billingStrategy = toNum(plan.billingStrategy);
153
+ const quotaBilled = billingStrategy === DevinEnums.BillingStrategy.QUOTA;
154
+
155
+ const windows: ProviderQuotaWindow[] = [];
156
+ if (!quotaBilled) {
157
+ // Legacy credit buckets. QUOTA-billed plans (DEVIN_FREE) still report
158
+ // them for backwards compatibility but they do not gate anything —
159
+ // showing "0 / 2,500 Credits" next to the real quota is misleading.
160
+ const prompt = creditWindow("prompt", "Prompt Credits", toNum(plan.monthlyPromptCredits), toNum(planStatus.usedPromptCredits), toNum(planStatus.availablePromptCredits));
161
+ const flow = creditWindow("flow", "Flow Credits", toNum(plan.monthlyFlowCredits), toNum(planStatus.usedFlowCredits), toNum(planStatus.availableFlowCredits));
162
+ const flex = creditWindow("flex", "Flex Credits", toNum(plan.monthlyFlexCreditPurchaseAmount), toNum(planStatus.usedFlexCredits), toNum(planStatus.availableFlexCredits));
163
+ if (prompt) windows.push(prompt);
164
+ if (flow) windows.push(flow);
165
+ if (flex) windows.push(flex);
166
+ }
167
+
168
+ // Quota windows: only on QUOTA-billed plans, and never when hidden.
169
+ // Credit-billed accounts leave the percent at proto default (100) with a
170
+ // zero reset, which would render a fake "100% quota" row.
171
+ const quotaApplicable = (hidden: boolean | undefined, resetAt: unknown): boolean =>
172
+ quotaBilled && !hidden && !(toNum(resetAt) === 0);
173
+
174
+ if (quotaApplicable(plan.hideDailyQuota, planStatus.dailyQuotaResetAtUnix)) {
175
+ const w = quotaWindow("1d", "Daily Quota", planStatus.dailyQuotaRemainingPercent, planStatus.dailyQuotaResetAtUnix);
176
+ if (w) windows.push(w);
177
+ }
178
+ if (quotaApplicable(plan.hideWeeklyQuota, planStatus.weeklyQuotaResetAtUnix)) {
179
+ const w = quotaWindow("7d", "Weekly Quota", planStatus.weeklyQuotaRemainingPercent, planStatus.weeklyQuotaResetAtUnix);
180
+ if (w) windows.push(w);
181
+ }
182
+
183
+ // Monthly plan window belongs to credit-billed plans only.
184
+ if (!quotaBilled) {
185
+ const start = toNum(planStatus.planStart);
186
+ const end = toNum(planStatus.planEnd);
187
+ if (end > start) {
188
+ windows.push({
189
+ kind: "monthly",
190
+ label: "Plan Period",
191
+ accounting: "independent",
192
+ usedPercent: null,
193
+ remainingPercent: null,
194
+ resetsAt: new Date(end * 1000).toISOString(),
195
+ recurring: true,
196
+ });
197
+ }
198
+ }
199
+
200
+ const overageMicros = toNum(planStatus.overageBalanceMicros);
201
+ const overageUsd = overageMicros / MICROS_PER_USD;
202
+
203
+ return {
204
+ source: "devin",
205
+ plan: planName || null,
206
+ windows,
207
+ error: null,
208
+ ...(accountLabel ? { accountLabel } : {}),
209
+ ...(overageUsd !== 0 ? { plan: `${planName} (overage $${overageUsd.toFixed(2)})` } : {}),
210
+ };
211
+ } catch {
212
+ return { ...result, error: "Devin quota fetch failed" };
213
+ }
214
+ }
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Devin (Codeium Cascade) shared wire constants and metadata identity.
3
+ *
4
+ * Two identity tuples exist upstream, sourced from oh-my-pi
5
+ * (`packages/catalog/src/wire/devin.ts`, MIT) and cross-checked against the
6
+ * other donors: the released CLI identity (`devin-cli`/`chisel`/
7
+ * `3000.11.205`) for chat/auth/usage, and the dev-channel discovery identity
8
+ * (`chisel`/`0.0.0-dev`) for `GetCliModelConfigs` — the latter is what
9
+ * unlocks the full native catalog.
10
+ */
11
+
12
+ /** `Metadata.os` vocabulary; `process.platform` is fixed for the process lifetime. */
13
+ export const DEVIN_OS =
14
+ process.platform === "darwin" ? "darwin" : process.platform === "win32" ? "windows" : "linux";
15
+
16
+ export const DEVIN_DEFAULT_BASE_URL = "https://server.codeium.com";
17
+
18
+ export const DEVIN_SESSION_TOKEN_PREFIX = "devin-session-token$";
19
+
20
+ /** Paths. */
21
+ export const DEVIN_CHAT_MESSAGE_PATH = "/exa.api_server_pb.ApiServerService/GetChatMessage";
22
+ export const DEVIN_ASSIGN_MODEL_PATH = "/exa.api_server_pb.ApiServerService/AssignModel";
23
+ export const DEVIN_GET_CLI_MODEL_CONFIGS_PATH = "/exa.api_server_pb.ApiServerService/GetCliModelConfigs";
24
+ export const DEVIN_GET_USER_JWT_PATH = "/exa.auth_pb.AuthService/GetUserJwt";
25
+ export const DEVIN_GET_USER_STATUS_PATH = "/exa.seat_management_pb.SeatManagementService/GetUserStatus";
26
+ export const DEVIN_EXCHANGE_PATH = "/exa.seat_management_pb.SeatManagementService/ExchangePKCEAuthorizationCode";
27
+
28
+ /** User-Agent used for the chat stream (connect-go spoof). */
29
+ export const DEVIN_CONNECT_UA = "connect-go/1.18.1 (go1.26.3)";
30
+
31
+ /** Released CLI identity (chat, auth, usage). */
32
+ export const DEVIN_CLI_METADATA = {
33
+ ideName: "devin-cli",
34
+ ideType: "chisel",
35
+ ideVersion: "3000.11.205",
36
+ extensionName: "chisel",
37
+ extensionVersion: "3000.11.205",
38
+ locale: "en",
39
+ os: DEVIN_OS,
40
+ } as const;
41
+
42
+ /** Dev-channel discovery identity (GetCliModelConfigs). */
43
+ export const DEVIN_DISCOVERY_METADATA = {
44
+ ideName: "chisel",
45
+ ideVersion: "0.0.0-dev",
46
+ extensionName: "chisel",
47
+ extensionVersion: "0.0.0-dev",
48
+ locale: "en",
49
+ os: DEVIN_OS,
50
+ } as const;
51
+
52
+ /**
53
+ * Display slots requested in `Metadata.supportedModelDisplays` (field 30).
54
+ * Requests slots 6 (internal default) / 7 (unclassified) / 8 (normal) beyond
55
+ * the generated enum's 0-4 so the server sends the full native catalog.
56
+ */
57
+ export const DEVIN_SUPPORTED_MODEL_DISPLAYS = [3, 4, 6, 7, 8];
58
+
59
+ /** Display slots filtered out client-side (not surfaced to users). */
60
+ export const DEVIN_INTERNAL_MODEL_DISPLAYS = new Set([4, 6]);
61
+
62
+ /** Models that advertise image support but silently drop images (live-verified). */
63
+ export const DEVIN_IMAGE_BLIND_UIDS = new Set(["swe-1-6-fast", "swe-1-6-slow"]);
64
+
65
+ /** Default limits when the catalog reports none. */
66
+ export const DEFAULT_CONTEXT_WINDOW = 200_000;
67
+ export const DEFAULT_MAX_TOKENS = 64_000;
68
+
69
+ /** Stop patterns the CLI sends by default. */
70
+ export const DEVIN_DEFAULT_STOP_PATTERNS = [
71
+ "\u0004",
72
+ "<|bot|>",
73
+ "<|context_request|>",
74
+ "\u0019",
75
+ "<|end_of_turn|>",
76
+ ];
77
+
78
+ /**
79
+ * Encodes a credential for `Metadata.apiKey` (field 3). A bare JWT (3
80
+ * dot-separated segments) gets the `devin-session-token$` prefix; every other
81
+ * key — including legacy `sk-ws-…` — goes out verbatim.
82
+ */
83
+ export function encodeDevinCredential(apiKey: string | undefined): string {
84
+ const key = apiKey?.trim();
85
+ if (!key) return "";
86
+ if (key.startsWith(DEVIN_SESSION_TOKEN_PREFIX)) return key;
87
+ return key.split(".").length === 3 ? `${DEVIN_SESSION_TOKEN_PREFIX}${key}` : key;
88
+ }
89
+
90
+ /** Builds the Metadata message object for a chat/usage call. */
91
+ export function devinCliMetadata(
92
+ apiKey: string,
93
+ userJwt?: string,
94
+ sessionId?: string,
95
+ ): Record<string, unknown> {
96
+ return {
97
+ ...DEVIN_CLI_METADATA,
98
+ apiKey: encodeDevinCredential(apiKey),
99
+ ...(userJwt ? { userJwt } : {}),
100
+ ...(sessionId ? { sessionId } : {}),
101
+ };
102
+ }
103
+
104
+ /** Builds the Metadata message object for discovery. */
105
+ export function devinDiscoveryMetadata(apiKey: string): Record<string, unknown> {
106
+ return {
107
+ ...DEVIN_DISCOVERY_METADATA,
108
+ apiKey: encodeDevinCredential(apiKey),
109
+ supportedModelDisplays: DEVIN_SUPPORTED_MODEL_DISPLAYS,
110
+ };
111
+ }