cartethyia 2.7.4 → 2.7.6

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 (595) hide show
  1. package/.env.example +5 -0
  2. package/README.md +18 -6
  3. package/dist/dashboard/assets/BannedPage-B1N603cM.js +1 -0
  4. package/dist/dashboard/assets/BannedPage-B1N603cM.js.gz +0 -0
  5. package/dist/dashboard/assets/CliToolDetailPage-9q4_4NoK.js +3 -0
  6. package/dist/dashboard/assets/CliToolDetailPage-9q4_4NoK.js.gz +0 -0
  7. package/dist/dashboard/assets/CliToolsPage-DwshGtK-.js +1 -0
  8. package/dist/dashboard/assets/CliToolsPage-DwshGtK-.js.gz +0 -0
  9. package/dist/dashboard/assets/CombosPage-D762MIkp.js +1 -0
  10. package/dist/dashboard/assets/CombosPage-D762MIkp.js.gz +0 -0
  11. package/dist/dashboard/assets/ConsoleLogPage-KRYjHZsX.js +1 -0
  12. package/dist/dashboard/assets/ConsoleLogPage-KRYjHZsX.js.gz +0 -0
  13. package/dist/dashboard/assets/CustomizationPage-DXsxk5uM.js +1 -0
  14. package/dist/dashboard/assets/CustomizationPage-DXsxk5uM.js.gz +0 -0
  15. package/dist/dashboard/assets/HealthEventsModal-BEjAjD4F.js +1 -0
  16. package/dist/dashboard/assets/HealthEventsModal-BEjAjD4F.js.gz +0 -0
  17. package/dist/dashboard/assets/InjectSystemPromptPanel-d5v3K_Yc.js +899 -0
  18. package/dist/dashboard/assets/InjectSystemPromptPanel-d5v3K_Yc.js.gz +0 -0
  19. package/dist/dashboard/assets/LoginPage-Ccv4tjNS.js +1 -0
  20. package/dist/dashboard/assets/LoginPage-Ccv4tjNS.js.gz +0 -0
  21. package/dist/dashboard/assets/{ModelPicker-BMS2t8BA.js → ModelPicker-C6WlpU5E.js} +1 -1
  22. package/dist/dashboard/assets/ModelPicker-C6WlpU5E.js.gz +0 -0
  23. package/dist/dashboard/assets/OverviewPage-DN9fYNWA.js +1 -0
  24. package/dist/dashboard/assets/OverviewPage-DN9fYNWA.js.gz +0 -0
  25. package/dist/dashboard/assets/ProviderDetailPage-BY0ieUgz.js +5 -0
  26. package/dist/dashboard/assets/ProviderDetailPage-BY0ieUgz.js.gz +0 -0
  27. package/dist/dashboard/assets/ProviderIcon-jjqXJDA3.js +1 -0
  28. package/dist/dashboard/assets/ProviderIcon-jjqXJDA3.js.gz +0 -0
  29. package/dist/dashboard/assets/ProvidersPage-DNsbfea2.js +1 -0
  30. package/dist/dashboard/assets/ProvidersPage-DNsbfea2.js.gz +0 -0
  31. package/dist/dashboard/assets/{ProxyPage-lsrx7NYg.js → ProxyPage-DxjvUzSD.js} +1 -1
  32. package/dist/dashboard/assets/ProxyPage-DxjvUzSD.js.gz +0 -0
  33. package/dist/dashboard/assets/QuotaPage-OaHScjpX.js +1 -0
  34. package/dist/dashboard/assets/QuotaPage-OaHScjpX.js.gz +0 -0
  35. package/dist/dashboard/assets/SettingsPage-BW4AKj2H.js +1 -0
  36. package/dist/dashboard/assets/SettingsPage-BW4AKj2H.js.gz +0 -0
  37. package/dist/dashboard/assets/SetupPage-44BZrxFC.js +1 -0
  38. package/dist/dashboard/assets/SetupPage-44BZrxFC.js.gz +0 -0
  39. package/dist/dashboard/assets/{StudioPage-Cq5tW7hW.js → StudioPage-DRPavCdU.js} +4 -4
  40. package/dist/dashboard/assets/StudioPage-DRPavCdU.js.gz +0 -0
  41. package/dist/dashboard/assets/ToolIcon-CfeLA-Z_.js +1 -0
  42. package/dist/dashboard/assets/ToolIcon-CfeLA-Z_.js.gz +0 -0
  43. package/dist/dashboard/assets/UsagePage-B7M7LvMM.js +56 -0
  44. package/dist/dashboard/assets/UsagePage-B7M7LvMM.js.gz +0 -0
  45. package/dist/dashboard/assets/api-keys-KvX83mRe.js +1 -0
  46. package/dist/dashboard/assets/api-keys-KvX83mRe.js.gz +0 -0
  47. package/dist/dashboard/assets/app-DRnQLhsc.js +9 -0
  48. package/dist/dashboard/assets/app-DRnQLhsc.js.gz +0 -0
  49. package/dist/dashboard/assets/app-mweRcsKp.css +2 -0
  50. package/dist/dashboard/assets/app-mweRcsKp.css.gz +0 -0
  51. package/dist/dashboard/assets/assert-CidQVoNo.js +1 -0
  52. package/dist/dashboard/assets/assert-CidQVoNo.js.gz +0 -0
  53. package/dist/dashboard/assets/{badge-D9CS6dZk.js → badge-BaX2GTrn.js} +1 -1
  54. package/dist/dashboard/assets/badge-BaX2GTrn.js.gz +0 -0
  55. package/dist/dashboard/assets/{banner-DympBNq4.js → banner-DFH4Bkte.js} +1 -1
  56. package/dist/dashboard/assets/banner-DFH4Bkte.js.gz +0 -0
  57. package/dist/dashboard/assets/brand/login_register.jpg +0 -0
  58. package/dist/dashboard/assets/brand/login_register_initial.jpg +0 -0
  59. package/dist/dashboard/assets/brand/og_bansos.jpg +0 -0
  60. package/dist/dashboard/assets/brand/og_image.jpg +0 -0
  61. package/dist/dashboard/assets/{card-ibRWU_uT.js → card-CxDw0lK6.js} +1 -1
  62. package/dist/dashboard/assets/card-CxDw0lK6.js.gz +0 -0
  63. package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js +1 -0
  64. package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js.gz +0 -0
  65. package/dist/dashboard/assets/circle-question-mark-Cz4un8sH.js +1 -0
  66. package/dist/dashboard/assets/circle-question-mark-Cz4un8sH.js.gz +0 -0
  67. package/dist/dashboard/assets/cli-tools-Bwv5-zGZ.js +1 -0
  68. package/dist/dashboard/assets/cli-tools-Bwv5-zGZ.js.gz +0 -0
  69. package/dist/dashboard/assets/{clipboard-button-DJm-9pz7.js → clipboard-button-DfS1ntiq.js} +1 -1
  70. package/dist/dashboard/assets/clipboard-button-DfS1ntiq.js.gz +0 -0
  71. package/dist/dashboard/assets/dialog-BK-NRr5u.js +1 -0
  72. package/dist/dashboard/assets/dialog-BK-NRr5u.js.gz +0 -0
  73. package/dist/dashboard/assets/{drawer-CqGYeOrd.js → drawer-QqPul6sC.js} +1 -1
  74. package/dist/dashboard/assets/drawer-QqPul6sC.js.gz +0 -0
  75. package/dist/dashboard/assets/entry-BMlYJVFj.js +1 -0
  76. package/dist/dashboard/assets/entry-BMlYJVFj.js.gz +0 -0
  77. package/dist/dashboard/assets/entry-D6WvojeD.js +4 -0
  78. package/dist/dashboard/assets/entry-D6WvojeD.js.gz +0 -0
  79. package/dist/dashboard/assets/entry-Dmx7gBiN.js +1 -0
  80. package/dist/dashboard/assets/entry-Dmx7gBiN.js.gz +0 -0
  81. package/dist/dashboard/assets/{formatters-D-MTJxMr.js → formatters-u7JPB5BX.js} +1 -1
  82. package/dist/dashboard/assets/formatters-u7JPB5BX.js.gz +0 -0
  83. package/dist/dashboard/assets/house-h9AZlJuT.js +1 -0
  84. package/dist/dashboard/assets/house-h9AZlJuT.js.gz +0 -0
  85. package/dist/dashboard/assets/{index-DBNPOfhV.js → index-Ko4dLRnV.js} +2 -2
  86. package/dist/dashboard/assets/index-Ko4dLRnV.js.gz +0 -0
  87. package/dist/dashboard/assets/{inline-BT0zntEr.js → inline-CHJQwxLa.js} +1 -1
  88. package/dist/dashboard/assets/inline-CHJQwxLa.js.gz +0 -0
  89. package/dist/dashboard/assets/{input-Da2ZViWg.js → input-BlmlizVV.js} +1 -1
  90. package/dist/dashboard/assets/input-BlmlizVV.js.gz +0 -0
  91. package/dist/dashboard/assets/{layout-BXNeLw6M.js → layout-Bz93I-yE.js} +1 -1
  92. package/dist/dashboard/assets/layout-Bz93I-yE.js.gz +0 -0
  93. package/dist/dashboard/assets/{list-row-BycOrrIV.js → list-row-Ml16KCfu.js} +1 -1
  94. package/dist/dashboard/assets/list-row-Ml16KCfu.js.gz +0 -0
  95. package/dist/dashboard/assets/live-7_QpnYGu.js +1 -0
  96. package/dist/dashboard/assets/live-7_QpnYGu.js.gz +0 -0
  97. package/dist/dashboard/assets/{mutation-Rr0TIvcj.js → mutation-GU7XdEjz.js} +1 -1
  98. package/dist/dashboard/assets/mutation-GU7XdEjz.js.gz +0 -0
  99. package/dist/dashboard/assets/network-CuMDaTzT.js +1 -0
  100. package/dist/dashboard/assets/network-CuMDaTzT.js.gz +0 -0
  101. package/dist/dashboard/assets/numbers-CoqpaDMx.js +2 -0
  102. package/dist/dashboard/assets/numbers-CoqpaDMx.js.gz +0 -0
  103. package/dist/dashboard/assets/pagination-B5aOoweZ.js +1 -0
  104. package/dist/dashboard/assets/pagination-B5aOoweZ.js.gz +0 -0
  105. package/dist/dashboard/assets/providers/zai.webp +0 -0
  106. package/dist/dashboard/assets/providers/zcode.webp +0 -0
  107. package/dist/dashboard/assets/{query-keys-BloKtaXJ.js → query-keys-YSoQOUh6.js} +1 -1
  108. package/dist/dashboard/assets/{query-keys-BloKtaXJ.js.gz → query-keys-YSoQOUh6.js.gz} +0 -0
  109. package/dist/dashboard/assets/quota-DJ1QlAOq.js +1 -0
  110. package/dist/dashboard/assets/quota-DJ1QlAOq.js.gz +0 -0
  111. package/dist/dashboard/assets/routing-fnCsxgNO.js +1 -0
  112. package/dist/dashboard/assets/routing-fnCsxgNO.js.gz +0 -0
  113. package/dist/dashboard/assets/{select-BIYIBkMU.js → select-BHqpd-bg.js} +2 -2
  114. package/dist/dashboard/assets/select-BHqpd-bg.js.gz +0 -0
  115. package/dist/dashboard/assets/settings-BxslsErn.js +1 -0
  116. package/dist/dashboard/assets/settings-BxslsErn.js.gz +0 -0
  117. package/dist/dashboard/assets/shield-BMQNxORh.js +1 -0
  118. package/dist/dashboard/assets/shield-BMQNxORh.js.gz +0 -0
  119. package/dist/dashboard/assets/{stack-DfgnFDWY.js → stack-j7cXjgYX.js} +1 -1
  120. package/dist/dashboard/assets/stack-j7cXjgYX.js.gz +0 -0
  121. package/dist/dashboard/assets/{state-CkfdYWel.js → state-DHmEnLa2.js} +1 -1
  122. package/dist/dashboard/assets/state-DHmEnLa2.js.gz +0 -0
  123. package/dist/dashboard/assets/{switch-SYm237HG.js → switch-DmZcyTIC.js} +1 -1
  124. package/dist/dashboard/assets/switch-DmZcyTIC.js.gz +0 -0
  125. package/dist/dashboard/assets/{useMutation-BQqCRNIi.js → useMutation-CbCP4w1o.js} +1 -1
  126. package/dist/dashboard/assets/useMutation-CbCP4w1o.js.gz +0 -0
  127. package/dist/dashboard/console-backgrounds.jpg +0 -0
  128. package/dist/dashboard/console-backgrounds_initial.jpg +0 -0
  129. package/dist/dashboard/index.html +2 -2
  130. package/dist/dashboard/index.html.gz +0 -0
  131. package/dist/dashboard/precompressed-assets.json +60 -59
  132. package/migrations/full-postgres/0036_system_prompt_presets_refs.sql +10 -0
  133. package/migrations/full-postgres/0037_share_concurrency_scope.sql +3 -0
  134. package/migrations/full-postgres/0038_add_accounts_quota_snapshot.sql +7 -0
  135. package/migrations/full-postgres/0039_add_telemetry_provider_model_indexes.sql +13 -0
  136. package/migrations/full-postgres/0040_add_models_dialect.sql +3 -0
  137. package/migrations/full-postgres/0041_add_daily_checkin_ledger_account_fk.sql +7 -0
  138. package/migrations/full-postgres/0042_add_telemetry_degenerate_stop.sql +14 -0
  139. package/migrations/lite-sqlite3/0036_system_prompt_presets_refs.sql +14 -0
  140. package/migrations/lite-sqlite3/0037_share_concurrency_scope.sql +3 -0
  141. package/migrations/lite-sqlite3/0038_add_accounts_quota_snapshot.sql +4 -0
  142. package/migrations/lite-sqlite3/0039_add_telemetry_provider_model_indexes.sql +6 -0
  143. package/migrations/lite-sqlite3/0040_add_models_dialect.sql +3 -0
  144. package/migrations/lite-sqlite3/0041_add_daily_checkin_ledger_account_fk.sql +26 -0
  145. package/migrations/lite-sqlite3/0042_add_telemetry_degenerate_stop.sql +12 -0
  146. package/package.json +4 -6
  147. package/scripts/cli/update.ts +15 -41
  148. package/src/boot/app.ts +58 -2
  149. package/src/boot/dependencies.ts +794 -732
  150. package/src/boot/lifecycle.ts +11 -12
  151. package/src/config/cooldowns.ts +34 -55
  152. package/src/config/network.ts +1 -1
  153. package/src/config/package-paths.ts +1 -1
  154. package/src/config/providers.ts +19 -14
  155. package/src/config/resources.ts +0 -5
  156. package/src/config/runtime.ts +2 -5
  157. package/src/config/spec.ts +33 -6
  158. package/src/config/usage.ts +27 -0
  159. package/src/console/api-keys/ban-constants.ts +38 -0
  160. package/src/console/api-keys/contracts.ts +71 -62
  161. package/src/console/api-keys/routes.ts +56 -24
  162. package/src/console/auth/access.ts +4 -4
  163. package/src/console/auth/account-reset.ts +1 -1
  164. package/src/console/auth/audit-recorder.ts +1 -1
  165. package/src/console/auth/lockout.ts +7 -3
  166. package/src/console/auth/row-coercion.ts +57 -12
  167. package/src/console/auth/session-resolver.ts +1 -1
  168. package/src/console/auth/session-service.ts +8 -2
  169. package/src/console/auth/session.ts +37 -31
  170. package/src/console/auth/setup-service.ts +4 -3
  171. package/src/console/auth/user-store.ts +1 -1
  172. package/src/console/backup/9router-map.ts +0 -3
  173. package/src/console/backup/contracts.ts +9 -9
  174. package/src/console/backup/export-endpoint.ts +5 -6
  175. package/src/console/backup/nine-router.ts +1 -7
  176. package/src/console/backup/routes.ts +29 -33
  177. package/src/console/backup/service.ts +468 -468
  178. package/src/console/backup/store.ts +47 -29
  179. package/src/console/backup/validate.ts +11 -1
  180. package/src/console/cli-tools/contracts.ts +43 -299
  181. package/src/console/cli-tools/fs-ops.ts +29 -0
  182. package/src/console/cli-tools/injectors/claude.ts +3 -3
  183. package/src/console/cli-tools/injectors/codex.ts +181 -181
  184. package/src/console/cli-tools/injectors/driver.ts +150 -247
  185. package/src/console/cli-tools/injectors/kilo.ts +146 -21
  186. package/src/console/cli-tools/injectors/opencode.ts +176 -153
  187. package/src/console/cli-tools/routes.ts +7 -1
  188. package/src/console/cli-tools/service.ts +8 -7
  189. package/src/console/cli-tools/store.ts +2 -2
  190. package/src/console/console-router.ts +32 -0
  191. package/src/console/dashboard-assets.ts +9 -9
  192. package/src/console/domain-registration.ts +16 -2
  193. package/src/console/inferhub/client.ts +0 -7
  194. package/src/console/inferhub/key-store.ts +1 -1
  195. package/src/console/inferhub/normalize.ts +2 -2
  196. package/src/console/inferhub/routes.ts +1 -1
  197. package/src/console/inferhub/types.ts +1 -1
  198. package/src/console/observability/contracts.ts +7 -1
  199. package/src/console/observability/live.ts +31 -18
  200. package/src/console/observability/logs.ts +1 -1
  201. package/src/console/observability/sse.ts +62 -8
  202. package/src/console/observability/store.ts +23 -4
  203. package/src/console/providers/catalog/catalog-projections.ts +1 -1
  204. package/src/console/providers/catalog/contracts.ts +39 -0
  205. package/src/console/providers/catalog/model-operations.ts +1 -1
  206. package/src/console/providers/catalog/provider-operations.ts +95 -17
  207. package/src/console/providers/catalog/public-model-store.ts +0 -0
  208. package/src/console/providers/catalog/routes.ts +27 -3
  209. package/src/console/providers/catalog/store.ts +147 -8
  210. package/src/console/providers/detail/routes.ts +1 -1
  211. package/src/console/providers/oauth/callback-listener.ts +100 -18
  212. package/src/console/providers/oauth/routes.ts +92 -13
  213. package/src/console/quota/account-quota-global.ts +41 -3
  214. package/src/console/quota/account-quota-shared.ts +10 -3
  215. package/src/console/quota/account-quota-tenant.ts +259 -66
  216. package/src/console/quota/daily-growth-job.ts +308 -0
  217. package/src/console/quota/native-identity.ts +2 -2
  218. package/src/console/quota/quota-view.ts +1 -1
  219. package/src/console/remote-support/routes.ts +1 -1
  220. package/src/console/remote-support/service.ts +2 -2
  221. package/src/console/routing/model/contracts.ts +1 -1
  222. package/src/console/routing/pools/contracts.ts +2 -2
  223. package/src/console/routing/pools/import-parse.ts +3 -3
  224. package/src/console/routing/pools/relay-deploy.ts +3 -3
  225. package/src/console/settings/contracts.ts +29 -2
  226. package/src/console/settings/store.ts +20 -0
  227. package/src/console/share/share-router.ts +100 -32
  228. package/src/console/share/share-stats.ts +11 -13
  229. package/src/console/share/share-usage.ts +1 -1
  230. package/src/console/shared/errors.ts +2 -2
  231. package/src/console/shared/object.ts +18 -0
  232. package/src/console/shared/read-through-cache.ts +4 -4
  233. package/src/console/shared/transaction.ts +14 -0
  234. package/src/console/system-prompt/contracts.ts +89 -12
  235. package/src/console/system-prompt/routes.ts +98 -45
  236. package/src/console/updates/apply-update.ts +244 -0
  237. package/src/console/updates/routes.ts +252 -97
  238. package/src/main.ts +11 -5
  239. package/src/network/http2-bidi.ts +1 -1
  240. package/src/network/ip-utils.ts +298 -0
  241. package/src/network/outbound-fetch.ts +1 -1
  242. package/src/network/pool/agent.ts +7 -6
  243. package/src/network/pool/byte-accounting.ts +1 -1
  244. package/src/network/pool/resolver.ts +16 -12
  245. package/src/network/pool/selector.ts +150 -136
  246. package/src/network/pool-health-machine.ts +1 -1
  247. package/src/network/rate-limit-verdict.ts +1 -1
  248. package/src/network/retry.ts +1 -1
  249. package/src/network/ssrf.ts +20 -71
  250. package/src/observability/event-log.ts +9 -2
  251. package/src/observability/event-query.ts +61 -291
  252. package/src/observability/log-sanitize.ts +1 -1
  253. package/src/observability/metrics.ts +4 -4
  254. package/src/observability/payload-capture.ts +6 -5
  255. package/src/observability/payload-store.ts +1 -1
  256. package/src/observability/runtime-metrics.ts +1 -1
  257. package/src/observability/telemetry-buffer.ts +19 -3
  258. package/src/observability/telemetry-reconciliation.ts +3 -3
  259. package/src/observability/token-speed.ts +1 -1
  260. package/src/persistence/connection-url.ts +1 -1
  261. package/src/persistence/db-handle.ts +1 -1
  262. package/src/persistence/db-pg.ts +2 -2
  263. package/src/persistence/db-sqlite.ts +3 -3
  264. package/src/persistence/dialect.ts +5 -1
  265. package/src/persistence/readiness.ts +1 -1
  266. package/src/persistence/redis.ts +1 -1
  267. package/src/persistence/schema.ts +121 -40
  268. package/src/persistence/shared-cache.ts +2 -2
  269. package/src/persistence/sort-order.ts +1 -1
  270. package/src/persistence/stores/api-key-store.ts +29 -2
  271. package/src/persistence/stores/share-store.ts +20 -8
  272. package/src/persistence/system-prompt-store.ts +63 -18
  273. package/src/persistence/tenant-preferences.ts +1 -1
  274. package/src/persistence/ttl-cache.ts +3 -3
  275. package/src/persistence/usage-flush.ts +7 -2
  276. package/src/protocol/canonical-model.ts +1 -1
  277. package/src/protocol/codecs.ts +6 -10
  278. package/src/protocol/dsml.ts +8 -125
  279. package/src/protocol/image-clamp.ts +2 -2
  280. package/src/protocol/reasoning-text.ts +1 -1
  281. package/src/protocol/reasoning.ts +7 -52
  282. package/src/protocol/registry.ts +50 -15
  283. package/src/protocol/request/chat.ts +46 -19
  284. package/src/protocol/request/codex.ts +1 -1
  285. package/src/protocol/request/messages.ts +46 -14
  286. package/src/protocol/request/responses.ts +19 -10
  287. package/src/protocol/response/chat.ts +25 -10
  288. package/src/protocol/response/codex.ts +1 -1
  289. package/src/protocol/response/messages.ts +1 -1
  290. package/src/protocol/response/omp-tool-call-markup.ts +1 -1
  291. package/src/protocol/response/responses.ts +1 -1
  292. package/src/protocol/sse-decoder.ts +50 -1
  293. package/src/protocol/stop-reason.ts +2 -2
  294. package/src/protocol/think-split.ts +347 -0
  295. package/src/protocol/translation/attachment-integrity.ts +3 -3
  296. package/src/protocol/translation/cache-controls.ts +8 -20
  297. package/src/protocol/translation/capabilities.ts +6 -6
  298. package/src/protocol/translation/dialect/deepseek.ts +10 -0
  299. package/src/protocol/translation/dialect/inband.ts +39 -0
  300. package/src/protocol/translation/dialect/model-thinking.ts +89 -0
  301. package/src/protocol/translation/dialect/qwen.ts +114 -0
  302. package/src/protocol/translation/dialect/resolver.ts +83 -0
  303. package/src/protocol/translation/dialect/rules.ts +93 -0
  304. package/src/protocol/translation/dialect/thinking-ladder.ts +245 -0
  305. package/src/protocol/translation/dialect/types.ts +58 -0
  306. package/src/protocol/translation/quirks.ts +18 -4
  307. package/src/protocol/translation/thinking.ts +12 -252
  308. package/src/protocol/translation/tool-id.ts +3 -3
  309. package/src/protocol/translation/tool-repair.ts +1 -1
  310. package/src/protocol/upstream/post-json.ts +6 -1
  311. package/src/providers/adapters/compatible-adapter.ts +71 -4
  312. package/src/providers/authentication/jwt-validator.ts +0 -5
  313. package/src/providers/authentication/oauth-client.ts +254 -253
  314. package/src/providers/authentication/oauth-flow-store.ts +42 -7
  315. package/src/providers/bundled-discovery-providers.ts +6 -30
  316. package/src/providers/configured-openai-providers.ts +82 -97
  317. package/src/providers/default-registry.ts +35 -37
  318. package/src/providers/discovery/catalog/catalog-format.ts +13 -2
  319. package/src/providers/discovery/discovery-types.ts +0 -1
  320. package/src/providers/discovery/openai-model-discovery.ts +2 -2
  321. package/src/providers/discovery/probe-phases.ts +48 -13
  322. package/src/providers/discovery/probing-service.ts +6 -8
  323. package/src/providers/integrations/agentrouter/agentrouter.ts +12 -2
  324. package/src/providers/integrations/antigravity/antigravity-oauth.ts +0 -1
  325. package/src/providers/integrations/antigravity/antigravity-protocol.ts +88 -28
  326. package/src/providers/integrations/antigravity/antigravity-quota.ts +18 -6
  327. package/src/providers/integrations/antigravity/antigravity.ts +22 -13
  328. package/src/providers/integrations/buddy/buddy-catalog-shared.ts +1 -1
  329. package/src/providers/integrations/buddy/buddy-chat-shared.ts +20 -4
  330. package/src/providers/integrations/buddy/buddy-cli-headers.ts +19 -52
  331. package/src/providers/integrations/buddy/buddy-identity.ts +86 -0
  332. package/src/providers/integrations/buddy/buddy-oauth-shared.ts +1 -1
  333. package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +1 -2
  334. package/src/providers/integrations/buddy/codebuddy/provider.ts +4 -15
  335. package/src/providers/integrations/buddy/codebuddy/shared.ts +30 -9
  336. package/src/providers/integrations/buddy/workbuddy/provider.ts +5 -9
  337. package/src/providers/integrations/buddy/workbuddy/shared.ts +21 -3
  338. package/src/providers/integrations/claude/claude-cch.ts +148 -148
  339. package/src/providers/integrations/claude/fallback-credit.ts +3 -7
  340. package/src/providers/integrations/cline/cline.ts +1 -1
  341. package/src/providers/integrations/codex/codex-device-code.ts +101 -101
  342. package/src/providers/integrations/codex/codex-oauth.ts +0 -1
  343. package/src/providers/integrations/commandcode/commandcode.ts +75 -115
  344. package/src/providers/integrations/commandcode/quota.ts +131 -51
  345. package/src/providers/integrations/cursor/cursor-http2.ts +0 -3
  346. package/src/providers/integrations/cursor/cursor-quota.ts +2 -6
  347. package/src/providers/integrations/cursor/cursor-request.ts +0 -87
  348. package/src/providers/integrations/cursor/cursor-shared.ts +0 -4
  349. package/src/providers/integrations/cursor/cursor.ts +35 -3
  350. package/src/providers/integrations/cursor/protocol/framing.ts +0 -56
  351. package/src/providers/integrations/cursor/protocol/messages.ts +0 -96
  352. package/src/providers/integrations/factory/factory.ts +9 -9
  353. package/src/providers/integrations/github/github-discovery.ts +70 -12
  354. package/src/providers/integrations/github/github-oauth.ts +184 -14
  355. package/src/providers/integrations/github/github.ts +134 -26
  356. package/src/providers/integrations/grok/grok-oauth.ts +261 -261
  357. package/src/providers/integrations/grok/grok-quota-frame.ts +1 -1
  358. package/src/providers/integrations/grok/grok-quota.ts +16 -7
  359. package/src/providers/integrations/grok/grok-ratelimit-store.ts +0 -5
  360. package/src/providers/integrations/grok/grok-ratelimit.ts +3 -0
  361. package/src/providers/integrations/grok/grok.ts +86 -36
  362. package/src/providers/integrations/kilo/kilo-oauth.ts +1 -1
  363. package/src/providers/integrations/kiro/kiro-cache.ts +31 -0
  364. package/src/providers/integrations/kiro/kiro-catalog.ts +31 -5
  365. package/src/providers/integrations/kiro/kiro-discovery.ts +47 -43
  366. package/src/providers/integrations/kiro/kiro-machine-id.ts +6 -3
  367. package/src/providers/integrations/kiro/kiro-oauth.ts +523 -255
  368. package/src/providers/integrations/kiro/kiro-quota.ts +35 -47
  369. package/src/providers/integrations/kiro/kiro-request.ts +8 -11
  370. package/src/providers/integrations/kiro/kiro-stream.ts +13 -0
  371. package/src/providers/integrations/kiro/kiro.ts +80 -68
  372. package/src/providers/integrations/muse/muse-oauth.ts +0 -1
  373. package/src/providers/integrations/muse/muse-quota.ts +0 -4
  374. package/src/providers/integrations/opencode/fingerprint.ts +7 -5
  375. package/src/providers/integrations/opencode/provider.ts +17 -24
  376. package/src/providers/integrations/qoder/qoder-catalog.ts +94 -11
  377. package/src/providers/integrations/qoder/qoder-oauth.ts +165 -25
  378. package/src/providers/integrations/qoder/qoder-quota.ts +48 -6
  379. package/src/providers/integrations/qoder/qoder-realm.ts +10 -31
  380. package/src/providers/integrations/qoder/qoder-sse.ts +159 -0
  381. package/src/providers/integrations/qoder/qoder-umid.ts +21 -25
  382. package/src/providers/integrations/qoder/qoder-virtual.ts +12 -0
  383. package/src/providers/integrations/qoder/qoder.ts +422 -71
  384. package/src/providers/integrations/shared/connect.ts +0 -54
  385. package/src/providers/integrations/shared/hash.ts +15 -0
  386. package/src/providers/integrations/shared/session-cache.ts +136 -0
  387. package/src/providers/integrations/trae/trae-cache.ts +7 -87
  388. package/src/providers/integrations/trae/trae-catalog.ts +1 -6
  389. package/src/providers/integrations/trae/trae-protocol.ts +17 -8
  390. package/src/providers/integrations/trae/trae-realm.ts +0 -7
  391. package/src/providers/integrations/trae/trae.ts +51 -8
  392. package/src/providers/integrations/xai/xai-oauth.ts +5 -5
  393. package/src/providers/integrations/zcode-start-plan/gifts.ts +265 -0
  394. package/src/providers/integrations/zcode-start-plan/oauth.ts +154 -0
  395. package/src/providers/integrations/zcode-start-plan/provider.ts +131 -0
  396. package/src/providers/integrations/zcode-start-plan/quota.ts +152 -0
  397. package/src/providers/integrations/zcode-start-plan/zcode_prompt.json +10 -0
  398. package/src/providers/operations/account-error-classification.ts +198 -133
  399. package/src/providers/operations/account-health-service.ts +31 -39
  400. package/src/providers/operations/account-reset-service.ts +58 -1
  401. package/src/providers/operations/byok-wire-profile.ts +19 -15
  402. package/src/providers/operations/cli-platform.ts +31 -5
  403. package/src/providers/operations/client-version-resolver.ts +4 -6
  404. package/src/providers/operations/client-versions.ts +10 -7
  405. package/src/providers/operations/provider-catalog-seeder.ts +2 -0
  406. package/src/providers/operations/provider-catalog-service.ts +18 -2
  407. package/src/providers/operations/provider-credential-service.ts +19 -2
  408. package/src/providers/provider-contracts.ts +18 -7
  409. package/src/providers/provider-metadata.ts +17 -2
  410. package/src/providers/provider-model-definition.ts +22 -1
  411. package/src/providers/provider-probe.ts +4 -2
  412. package/src/providers/provider-usage.ts +50 -19
  413. package/src/providers/quota/cache.ts +29 -0
  414. package/src/providers/quota/quota-contracts.ts +4 -0
  415. package/src/providers/quota/refresh.ts +27 -4
  416. package/src/providers/quota/snapshot.ts +94 -0
  417. package/src/providers/search/search-provider.ts +1 -3
  418. package/src/providers/search/search-providers.ts +2 -1
  419. package/src/security/abuse.ts +4 -4
  420. package/src/security/admission/service.ts +13 -6
  421. package/src/security/admission/ttl.ts +61 -61
  422. package/src/security/api-key-auth.ts +17 -3
  423. package/src/security/client-router-fingerprint.ts +4 -4
  424. package/src/security/credential-codec.ts +3 -3
  425. package/src/security/csrf.ts +2 -2
  426. package/src/security/ip-boundary.ts +16 -189
  427. package/src/security/model-access-rule.ts +1 -1
  428. package/src/security/outbound-headers.ts +18 -0
  429. package/src/shared/invoke-guard.ts +47 -0
  430. package/src/transport/contracts.ts +13 -4
  431. package/src/transport/dispatch/attempt-finalize.ts +70 -22
  432. package/src/transport/dispatch/attempt-loop.ts +22 -0
  433. package/src/transport/dispatch/capture-policy.ts +34 -37
  434. package/src/transport/dispatch/empty-stream.ts +23 -20
  435. package/src/transport/dispatch/generation.ts +25 -45
  436. package/src/transport/dispatch/native-shared.ts +127 -0
  437. package/src/transport/dispatch/proxy-request.ts +3 -1
  438. package/src/transport/dispatch/responses-compact.ts +25 -46
  439. package/src/transport/dispatch/streaming/encoder.ts +18 -72
  440. package/src/transport/dispatch/streaming/finalize.ts +2 -2
  441. package/src/transport/dispatch/streaming/stream.ts +7 -3
  442. package/src/transport/dispatch/streaming/thinking-loop.ts +1 -1
  443. package/src/transport/dispatch/systemone.ts +20 -48
  444. package/src/transport/dispatch/token-count.ts +41 -38
  445. package/src/transport/dispatch/websearch.ts +19 -45
  446. package/src/transport/drain-endpoint.ts +1 -1
  447. package/src/transport/failure-policy.ts +21 -1
  448. package/src/transport/guards/auth-guard.ts +0 -6
  449. package/src/transport/guards/body-policy.ts +3 -3
  450. package/src/transport/guards/error-lifecycle.ts +4 -0
  451. package/src/transport/guards/headroom-guard.ts +1 -1
  452. package/src/transport/guards/pipeline.ts +1 -1
  453. package/src/transport/guards/request-context.ts +12 -17
  454. package/src/transport/request/preparer.ts +286 -7
  455. package/src/transport/request/rtk/compress-request.ts +3 -3
  456. package/src/transport/request/rtk/rtk-constants.ts +2 -2
  457. package/src/transport/request/rtk/rtk-filters.ts +8 -8
  458. package/src/transport/request/state.ts +7 -13
  459. package/src/transport/request/system-prompt-injection.ts +74 -11
  460. package/src/transport/request/tenant-preferences.ts +22 -0
  461. package/src/transport/routing/candidate-index.ts +2 -2
  462. package/src/transport/routing/round-robin.ts +1 -1
  463. package/src/transport/routing/route-catalog.ts +17 -18
  464. package/src/transport/routing/route-model.ts +126 -33
  465. package/src/transport/routing/router.ts +159 -37
  466. package/src/transport/shutdown-notice.ts +2 -2
  467. package/src/transport/surface/adapters.ts +3 -3
  468. package/src/transport/surface/chat/encode.ts +7 -7
  469. package/src/transport/surface/chat/parse.ts +7 -7
  470. package/src/transport/surface/completion.ts +2 -2
  471. package/src/transport/surface/content-parts.ts +1 -1
  472. package/src/transport/surface/dialects.ts +2 -2
  473. package/src/transport/surface/messages/parse.ts +3 -3
  474. package/src/transport/surface/reasoning-summary.ts +9 -14
  475. package/src/transport/surface/responses/adapter.ts +1 -1
  476. package/src/transport/surface/responses/errors.ts +0 -9
  477. package/src/transport/vision-handoff-cache.ts +58 -0
  478. package/src/transport/vision-handoff.ts +431 -0
  479. package/src/workers/account-identity-sweep.ts +2 -2
  480. package/src/workers/buddy-growth-tasks.ts +392 -346
  481. package/src/workers/daily-checkin.ts +102 -49
  482. package/src/workers/maintenance-lease.ts +2 -35
  483. package/src/workers/oauth-refresh-sweep.ts +8 -1
  484. package/src/workers/quota-refresh-sweep.ts +120 -82
  485. package/src/workers/scheduler.ts +67 -4
  486. package/src/workers/sweep-runner.ts +24 -5
  487. package/src/workers/zcode-gift-claim.ts +108 -0
  488. package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js +0 -1
  489. package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js.gz +0 -0
  490. package/dist/dashboard/assets/BannedPage-ChG5svFb.js +0 -1
  491. package/dist/dashboard/assets/BannedPage-ChG5svFb.js.gz +0 -0
  492. package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js +0 -1
  493. package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js.gz +0 -0
  494. package/dist/dashboard/assets/CliToolsPage-Bf2VelDe.js +0 -1
  495. package/dist/dashboard/assets/CliToolsPage-Bf2VelDe.js.gz +0 -0
  496. package/dist/dashboard/assets/CombosPage-DCgm5g6g.js +0 -1
  497. package/dist/dashboard/assets/CombosPage-DCgm5g6g.js.gz +0 -0
  498. package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js +0 -1
  499. package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js.gz +0 -0
  500. package/dist/dashboard/assets/CustomizationPage-ggeMSjte.js +0 -1
  501. package/dist/dashboard/assets/CustomizationPage-ggeMSjte.js.gz +0 -0
  502. package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js +0 -1
  503. package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js.gz +0 -0
  504. package/dist/dashboard/assets/LoginPage-U6AKaJcF.js +0 -1
  505. package/dist/dashboard/assets/LoginPage-U6AKaJcF.js.gz +0 -0
  506. package/dist/dashboard/assets/ModelPicker-BMS2t8BA.js.gz +0 -0
  507. package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js +0 -1
  508. package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js.gz +0 -0
  509. package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js +0 -5
  510. package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js.gz +0 -0
  511. package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js +0 -1
  512. package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js.gz +0 -0
  513. package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js +0 -1
  514. package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js.gz +0 -0
  515. package/dist/dashboard/assets/ProxyPage-lsrx7NYg.js.gz +0 -0
  516. package/dist/dashboard/assets/QuotaPage-L0skzML8.js +0 -1
  517. package/dist/dashboard/assets/QuotaPage-L0skzML8.js.gz +0 -0
  518. package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js +0 -1
  519. package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js.gz +0 -0
  520. package/dist/dashboard/assets/SetupPage-f0DE1h0-.js +0 -1
  521. package/dist/dashboard/assets/SetupPage-f0DE1h0-.js.gz +0 -0
  522. package/dist/dashboard/assets/SortableList-ClzpwyET.js +0 -1
  523. package/dist/dashboard/assets/SortableList-ClzpwyET.js.gz +0 -0
  524. package/dist/dashboard/assets/StudioPage-Cq5tW7hW.js.gz +0 -0
  525. package/dist/dashboard/assets/ToolIcon-K1ckcDKg.js +0 -1
  526. package/dist/dashboard/assets/ToolIcon-K1ckcDKg.js.gz +0 -0
  527. package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js +0 -56
  528. package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js.gz +0 -0
  529. package/dist/dashboard/assets/api-keys-C38iXoO4.js +0 -1
  530. package/dist/dashboard/assets/api-keys-C38iXoO4.js.gz +0 -0
  531. package/dist/dashboard/assets/app-BayTTy01.js +0 -9
  532. package/dist/dashboard/assets/app-BayTTy01.js.gz +0 -0
  533. package/dist/dashboard/assets/app-a159k0ub.css +0 -2
  534. package/dist/dashboard/assets/app-a159k0ub.css.gz +0 -0
  535. package/dist/dashboard/assets/assert-DbRA8EG2.js +0 -15
  536. package/dist/dashboard/assets/assert-DbRA8EG2.js.gz +0 -0
  537. package/dist/dashboard/assets/badge-D9CS6dZk.js.gz +0 -0
  538. package/dist/dashboard/assets/banner-DympBNq4.js.gz +0 -0
  539. package/dist/dashboard/assets/card-ibRWU_uT.js.gz +0 -0
  540. package/dist/dashboard/assets/cli-tools-63qBGaRw.js +0 -1
  541. package/dist/dashboard/assets/cli-tools-63qBGaRw.js.gz +0 -0
  542. package/dist/dashboard/assets/clipboard-button-DJm-9pz7.js.gz +0 -0
  543. package/dist/dashboard/assets/dialog-8fiE6tec.js +0 -1
  544. package/dist/dashboard/assets/dialog-8fiE6tec.js.gz +0 -0
  545. package/dist/dashboard/assets/drawer-CqGYeOrd.js.gz +0 -0
  546. package/dist/dashboard/assets/entry-BSAsYsmV.js +0 -1
  547. package/dist/dashboard/assets/entry-BSAsYsmV.js.gz +0 -0
  548. package/dist/dashboard/assets/entry-CiIQULZD.js +0 -4
  549. package/dist/dashboard/assets/entry-CiIQULZD.js.gz +0 -0
  550. package/dist/dashboard/assets/entry-Daz0lJ-W.js +0 -1
  551. package/dist/dashboard/assets/entry-Daz0lJ-W.js.gz +0 -0
  552. package/dist/dashboard/assets/formatters-D-MTJxMr.js.gz +0 -0
  553. package/dist/dashboard/assets/github-badge-CPK47xQx.js +0 -1
  554. package/dist/dashboard/assets/github-badge-CPK47xQx.js.gz +0 -0
  555. package/dist/dashboard/assets/index-DBNPOfhV.js.gz +0 -0
  556. package/dist/dashboard/assets/inline-BT0zntEr.js.gz +0 -0
  557. package/dist/dashboard/assets/input-Da2ZViWg.js.gz +0 -0
  558. package/dist/dashboard/assets/layout-BXNeLw6M.js.gz +0 -0
  559. package/dist/dashboard/assets/list-row-BycOrrIV.js.gz +0 -0
  560. package/dist/dashboard/assets/live-DCQNZpF7.js +0 -1
  561. package/dist/dashboard/assets/live-DCQNZpF7.js.gz +0 -0
  562. package/dist/dashboard/assets/mutation-Rr0TIvcj.js.gz +0 -0
  563. package/dist/dashboard/assets/network-9Yj2ZyLo.js +0 -1
  564. package/dist/dashboard/assets/network-9Yj2ZyLo.js.gz +0 -0
  565. package/dist/dashboard/assets/numbers-CEagj6ZZ.js +0 -2
  566. package/dist/dashboard/assets/numbers-CEagj6ZZ.js.gz +0 -0
  567. package/dist/dashboard/assets/providers/zai-coding-plan.svg +0 -6
  568. package/dist/dashboard/assets/providers/zai-coding-plan.svg.gz +0 -0
  569. package/dist/dashboard/assets/quota-Caw7wqci.js +0 -1
  570. package/dist/dashboard/assets/quota-Caw7wqci.js.gz +0 -0
  571. package/dist/dashboard/assets/routing-CO9zCUus.js +0 -1
  572. package/dist/dashboard/assets/routing-CO9zCUus.js.gz +0 -0
  573. package/dist/dashboard/assets/select-BIYIBkMU.js.gz +0 -0
  574. package/dist/dashboard/assets/settings-jS3-PNSA.js +0 -1
  575. package/dist/dashboard/assets/settings-jS3-PNSA.js.gz +0 -0
  576. package/dist/dashboard/assets/stack-DfgnFDWY.js.gz +0 -0
  577. package/dist/dashboard/assets/state-CkfdYWel.js.gz +0 -0
  578. package/dist/dashboard/assets/stream-retry-5QnVuSSo.js +0 -1
  579. package/dist/dashboard/assets/stream-retry-5QnVuSSo.js.gz +0 -0
  580. package/dist/dashboard/assets/switch-SYm237HG.js.gz +0 -0
  581. package/dist/dashboard/assets/useMutation-BQqCRNIi.js.gz +0 -0
  582. package/src/console/cli-tools/injectors/cline.ts +0 -110
  583. package/src/console/cli-tools/injectors/copilot.ts +0 -108
  584. package/src/console/cli-tools/injectors/cowork.ts +0 -64
  585. package/src/console/cli-tools/injectors/deepseek-tui.ts +0 -85
  586. package/src/console/cli-tools/injectors/droid.ts +0 -96
  587. package/src/console/cli-tools/injectors/grok-build.ts +0 -70
  588. package/src/console/cli-tools/injectors/hermes.ts +0 -101
  589. package/src/console/cli-tools/injectors/jcode.ts +0 -115
  590. package/src/console/cli-tools/injectors/openclaw.ts +0 -161
  591. package/src/network/response-headers.ts +0 -39
  592. package/src/protocol/response/dsml.ts +0 -38
  593. package/src/providers/integrations/xiaomi-mimo/think-stream.ts +0 -229
  594. /package/dist/dashboard/assets/brand/{og_bansos.webp → og_bansos_initial.webp} +0 -0
  595. /package/dist/dashboard/assets/brand/{og_image.webp → og_image_initial.webp} +0 -0
@@ -34,6 +34,30 @@ export interface AccountHealthEventRecord {
34
34
  readonly createdAt: string;
35
35
  }
36
36
 
37
+ /**
38
+ * Runs a write against the db handle, wrapping it in a transaction when the
39
+ * handle supports one. Kept as a capability probe, not a correctness guard:
40
+ * health writes are reachable with a partially-implemented database handle
41
+ * (the dispatch tests pass a narrow double), and a transaction is an
42
+ * optimization here, not a requirement — the same writes are correct without
43
+ * one. Returns `fallback` when the write throws; health must never fail
44
+ * requests.
45
+ */
46
+ async function withTransaction<T>(
47
+ db: CartethyiaDatabase,
48
+ mutate: (tx: CartethyiaDatabase) => Promise<T>,
49
+ fallback: T,
50
+ ): Promise<T> {
51
+ try {
52
+ if (typeof db.transaction === "function") {
53
+ return await db.transaction((tx) => mutate(tx as CartethyiaDatabase));
54
+ }
55
+ return await mutate(db);
56
+ } catch {
57
+ return fallback;
58
+ }
59
+ }
60
+
37
61
  /** Persists one classified failure to the account row and appends a health event. */
38
62
  export async function recordAccountFailure(
39
63
  db: CartethyiaDatabase,
@@ -260,18 +284,7 @@ export async function recordAccountFailure(
260
284
  return { ...classification, routesVisible: true };
261
285
  };
262
286
 
263
- try {
264
- // Kept as a capability probe, not a correctness guard: this function is
265
- // reachable with a partially-implemented database handle (the dispatch
266
- // tests pass a narrow double), and a transaction is an optimization here,
267
- // not a requirement — the same writes are correct without one.
268
- if (typeof db.transaction === "function") {
269
- return await db.transaction((tx) => persist(tx as CartethyiaDatabase));
270
- }
271
- return await persist(db);
272
- } catch {
273
- return null;
274
- }
287
+ return withTransaction(db, persist, null);
275
288
  }
276
289
 
277
290
  /** Clears failure state after a successful dispatch; true when the account changed. */
@@ -333,14 +346,7 @@ export async function recordAccountSuccess(
333
346
  }
334
347
  return hadFailures;
335
348
  };
336
- try {
337
- if (typeof db.transaction === "function") {
338
- return await db.transaction((tx) => mutate(tx as CartethyiaDatabase));
339
- }
340
- return await mutate(db);
341
- } catch {
342
- return false;
343
- }
349
+ return withTransaction(db, mutate, false);
344
350
  }
345
351
 
346
352
  /** Operator-initiated recovery: forces the account back to active and logs the transition. */
@@ -393,14 +399,7 @@ export async function recoverAccount(
393
399
  }
394
400
  return true;
395
401
  };
396
- try {
397
- if (typeof db.transaction === "function") {
398
- return await db.transaction((tx) => recover(tx as CartethyiaDatabase));
399
- }
400
- return await recover(db);
401
- } catch {
402
- return false;
403
- }
402
+ return withTransaction(db, recover, false);
404
403
  }
405
404
 
406
405
  /** Recovers accounts whose cooldown elapsed and prunes expired per-model keys. */
@@ -481,14 +480,7 @@ export async function sweepExpiredCooldowns(db: CartethyiaDatabase): Promise<num
481
480
  .where(pruning.changed);
482
481
  return expired.length + affectedRows(pruned);
483
482
  };
484
- try {
485
- if (typeof db.transaction === "function") {
486
- return await db.transaction((tx) => recover(tx as CartethyiaDatabase));
487
- }
488
- return await recover(db);
489
- } catch {
490
- return 0;
491
- }
483
+ return withTransaction(db, recover, 0);
492
484
  }
493
485
 
494
486
  /**
@@ -519,8 +511,8 @@ async function writeHealthEvent(
519
511
  row: {
520
512
  readonly entityKind: "account";
521
513
  readonly accountId: string;
522
- readonly fromStatus: string;
523
- readonly toStatus: string;
514
+ readonly fromStatus: "active" | "cooldown" | "disabled" | null;
515
+ readonly toStatus: "active" | "cooldown" | "disabled";
524
516
  readonly reason: string;
525
517
  readonly errorCategory: string | null;
526
518
  readonly modelId?: string | null;
@@ -533,7 +525,7 @@ async function writeHealthEvent(
533
525
  return;
534
526
  }
535
527
  if (typeof client.insert !== "function") return;
536
- await client.insert(healthEvents).values({ id: randomUUID(), ...row } as never);
528
+ await client.insert(healthEvents).values({ id: randomUUID(), ...row });
537
529
  }
538
530
 
539
531
  export async function reportAttemptOutcome(
@@ -27,6 +27,7 @@ import { CLAUDE_CODE_USER_AGENT } from "../integrations/claude/claude-fingerprin
27
27
  import { authCredential, codexJwtAccountId, text } from "../quota/quota-contracts";
28
28
  import { getCodexVersion } from "./client-versions";
29
29
  import { buildCodexUserAgent } from "./cli-platform";
30
+ import { TtlCache } from "../../persistence/ttl-cache";
30
31
 
31
32
  /** One redeemable (or already-spent) saved reset. */
32
33
  export interface ResetCredit {
@@ -62,6 +63,51 @@ const JUNIPER_PROGRAM = "juniper_tide";
62
63
  const ORG_ID = /^[A-Za-z0-9_-]{1,128}$/;
63
64
  /** Cedar grant ids are short slugs; anything else never reaches the provider. */
64
65
  const CEDAR_GRANT_ID = /^[a-z0-9_-]{1,40}$/;
66
+ /** Abort budget for one upstream reset-path request, mirroring quota refresh. */
67
+ const RESET_FETCH_TIMEOUT_MS = 15_000;
68
+
69
+ /**
70
+ * Short per-account cache for {@link listAccountResetCredits}.
71
+ *
72
+ * The console reads the reset list each time a dialog opens; without a cache
73
+ * every open hits the upstream live. The TTL is short — the list changes when
74
+ * a credit is consumed, and `invalidateResetCreditsCache` clears the entry on
75
+ * a successful redemption — so staleness is bounded to a dialog-refresh
76
+ * window. Failures (`null`) are deliberately not cached: a discovery error
77
+ * stays retryable on the next open.
78
+ */
79
+ const RESET_CREDITS_TTL_MS = 30_000;
80
+ const resetCreditsCache = new TtlCache<ResetCreditList | null>({
81
+ ttlMs: RESET_CREDITS_TTL_MS,
82
+ maxEntries: 512,
83
+ });
84
+
85
+ /**
86
+ * Reads one account's saved reset credits through the short TTL cache.
87
+ * Concurrent misses share one upstream discovery via the cache's load-through
88
+ * deduplication.
89
+ */
90
+ export async function getCachedResetCredits(
91
+ providerId: string,
92
+ accountId: string,
93
+ load: () => Promise<ResetCreditList | null>,
94
+ ): Promise<ResetCreditList | null> {
95
+ return resetCreditsCache.load(`${providerId}:${accountId}`, load, {
96
+ namespace: "reset-credits",
97
+ });
98
+ }
99
+
100
+ /**
101
+ * Drops every cached reset-credit entry for one account. Called after a
102
+ * successful redemption so the dialog does not keep showing a spent credit for
103
+ * the rest of the TTL.
104
+ */
105
+ export function invalidateResetCreditsCache(accountId: string): void {
106
+ const suffix = `:${accountId}`;
107
+ for (const key of resetCreditsCache.keys()) {
108
+ if (key.endsWith(suffix)) resetCreditsCache.delete(key);
109
+ }
110
+ }
65
111
 
66
112
  export function supportsAccountReset(providerId: string): boolean {
67
113
  const norm = providerId.trim().toLowerCase();
@@ -172,7 +218,10 @@ export async function listAccountResetCredits(
172
218
  try {
173
219
  const res = await fetcher(
174
220
  "https://chatgpt.com/backend-api/wham/rate-limit-reset-credits",
175
- { headers: codexHeaders(access, accountId, version, false) },
221
+ {
222
+ headers: codexHeaders(access, accountId, version, false),
223
+ signal: AbortSignal.timeout(RESET_FETCH_TIMEOUT_MS),
224
+ },
176
225
  );
177
226
  if (!res.ok) return null;
178
227
  const payload = (await res.json()) as unknown;
@@ -237,6 +286,7 @@ async function discoverCedar(
237
286
  try {
238
287
  res = await fetcher("https://api.anthropic.com/api/oauth/usage?cedar_ember=1&skip_spend=1", {
239
288
  headers: claudeHeaders(access, false),
289
+ signal: AbortSignal.timeout(RESET_FETCH_TIMEOUT_MS),
240
290
  });
241
291
  } catch {
242
292
  return "failed";
@@ -343,6 +393,7 @@ async function discoverJuniper(
343
393
  try {
344
394
  res = await fetcher("https://api.anthropic.com/api/oauth/usage?at_wall=1&skip_spend=1", {
345
395
  headers: claudeHeaders(access, false),
396
+ signal: AbortSignal.timeout(RESET_FETCH_TIMEOUT_MS),
346
397
  });
347
398
  } catch {
348
399
  return null;
@@ -385,6 +436,7 @@ async function resolveClaudeOrg(access: string, fetcher: typeof fetch): Promise<
385
436
  try {
386
437
  const res = await fetcher("https://api.anthropic.com/api/oauth/profile", {
387
438
  headers: claudeHeaders(access, false),
439
+ signal: AbortSignal.timeout(RESET_FETCH_TIMEOUT_MS),
388
440
  });
389
441
  if (!res.ok) return null;
390
442
  const payload = (await res.json()) as unknown;
@@ -449,6 +501,7 @@ export async function consumeAccountResetCredit(args: {
449
501
  redeem_request_id: randomUUID(),
450
502
  ...(codexAccountId ? { account_id: codexAccountId } : {}),
451
503
  }),
504
+ signal: AbortSignal.timeout(RESET_FETCH_TIMEOUT_MS),
452
505
  },
453
506
  );
454
507
  const body = (await res.json().catch(() => undefined)) as Record<string, unknown> | undefined;
@@ -528,6 +581,7 @@ export async function consumeAccountResetCredit(args: {
528
581
  method: "POST",
529
582
  headers: claudeHeaders(access, true),
530
583
  body: JSON.stringify(body),
584
+ signal: AbortSignal.timeout(RESET_FETCH_TIMEOUT_MS),
531
585
  },
532
586
  );
533
587
  const payload = (await res.json().catch(() => undefined)) as
@@ -651,6 +705,9 @@ async function recordResetActivity(
651
705
  errorCategory: null,
652
706
  createdAt: now,
653
707
  });
708
+ // The redeemed credit is gone; the next dialog open must not serve the
709
+ // pre-redeem list for the rest of the TTL.
710
+ invalidateResetCreditsCache(accountId);
654
711
  await snapshotInvalidator?.invalidate();
655
712
  return;
656
713
  }
@@ -92,12 +92,11 @@ const ENDPOINT_TAIL = /\/(?:v\d+\/)?(?:messages|chat\/completions|responses|comp
92
92
  * The root an operator's pasted URL really meant, plus the endpoint tail that
93
93
  * was removed.
94
94
  *
95
- * The suggestion is the bare **origin**, not the path left behind. For
96
- * `https://api.deepseek.com/anthropic/v1/messages` the tail `/v1/messages` is
97
- * only the last segment; `/anthropic` is part of that same endpoint, and
98
- * suggesting `https://api.deepseek.com/anthropic` would still derive the model
99
- * list at `…/anthropic/models` and 404 — the very failure this corrects. A URL
100
- * that is already a root comes back with an empty `stripped`.
95
+ * Only the **tail** is stripped. Any path before it belongs to the gateway
96
+ * root and survives, so `https://api.longcat.ai/anthropic/v1/messages`
97
+ * resolves to `https://api.longcat.ai/anthropic` (not the bare origin) — the
98
+ * `/anthropic` prefix is where LongCat actually serves the API. A URL that is
99
+ * already a root comes back with an empty `stripped`.
101
100
  */
102
101
  export function splitEndpointBaseUrl(baseUrl: string): { readonly baseUrl: string; readonly stripped: string } {
103
102
  const trimmed = baseUrl.replace(/\/+$/, "");
@@ -110,20 +109,22 @@ export function splitEndpointBaseUrl(baseUrl: string): { readonly baseUrl: strin
110
109
  const basePath = parsed.pathname.replace(/\/+$/, "");
111
110
  const match = ENDPOINT_TAIL.exec(basePath);
112
111
  if (match === null) return { baseUrl: trimmed, stripped: "" };
113
- return { baseUrl: parsed.origin, stripped: basePath };
112
+ const keptPath = basePath.slice(0, match.index);
113
+ return { baseUrl: `${parsed.origin}${keptPath}`, stripped: basePath };
114
114
  }
115
115
 
116
116
  /**
117
117
  * Base URL an operator's model list lives under (`<base>/models`). A bare host
118
118
  * has no version segment, so it gets the `/v1` prefix; a base that already
119
119
  * carries a path (conventionally `/v1`) is used as-is. A pasted endpoint path
120
- * is stripped first, so `…/anthropic/v1/messages` discovers at `<host>/v1/models`
121
- * rather than one level below a per-request path.
120
+ * is stripped first, so `…/anthropic/v1/messages` discovers at
121
+ * `<origin>/anthropic/v1/models` — the gateway prefix before the endpoint tail
122
+ * belongs to the root and is preserved.
122
123
  */
123
124
  export function modelDiscoveryBaseUrl(baseUrl: string): string {
124
- // A pasted endpoint is not a base at all, so its whole path is discarded and
125
- // the list is looked for at `<origin>/v1`. A base that already IS a root —
126
- // bare host, or a version/gateway prefix — keeps that path, because
125
+ // A pasted endpoint has its tail removed; whatever path came before it is a
126
+ // real gateway prefix and stays. A base that already IS a root — bare host,
127
+ // or a version/gateway prefix — keeps that path, because
127
128
  // `https://gateway.example/api/v1` legitimately serves its list there.
128
129
  const trimmed = baseUrl.replace(/\/+$/, "");
129
130
  let parsed: URL;
@@ -133,9 +134,12 @@ export function modelDiscoveryBaseUrl(baseUrl: string): string {
133
134
  return `${trimmed}/v1`;
134
135
  }
135
136
  const basePath = parsed.pathname.replace(/\/+$/, "");
136
- const isPastedEndpoint = ENDPOINT_TAIL.test(basePath);
137
- const listBase = isPastedEndpoint ? parsed.origin : `${parsed.origin}${basePath}`;
138
- if (isPastedEndpoint || basePath === "" || basePath === "/") return `${listBase}/v1`;
137
+ const match = ENDPOINT_TAIL.exec(basePath);
138
+ const listBase =
139
+ match === null
140
+ ? `${parsed.origin}${basePath}`
141
+ : `${parsed.origin}${basePath.slice(0, match.index)}`;
142
+ if (match !== null || basePath === "" || basePath === "/") return `${listBase}/v1`;
139
143
  return listBase;
140
144
  }
141
145
 
@@ -16,6 +16,8 @@
16
16
  * Every value below is what the real client would report, taken from each
17
17
  * client's own source rather than guessed.
18
18
  */
19
+ import { createHash } from "node:crypto";
20
+ import { hostname as osHostname } from "node:os";
19
21
 
20
22
  /**
21
23
  * `os_info` — the crate Codex reads this from — returns the marketing name
@@ -52,9 +54,6 @@ const KIMI_OS_VERSION = "macOS 15.6";
52
54
  */
53
55
  const KIMI_DEVICE_NAME = "MacBook-Pro.local";
54
56
 
55
- /** Qoder's `cosy-machineos`: "<arch>_<os>". */
56
- const QODER_MACHINE_OS = "aarch64_macos";
57
-
58
57
 
59
58
  /**
60
59
  * Cline's `x-platform` / `x-platform-version`.
@@ -128,9 +127,36 @@ export function kimiDeviceName(): string {
128
127
  return KIMI_DEVICE_NAME;
129
128
  }
130
129
 
131
- /** Qoder's `cosy-machineos`. */
130
+ /**
131
+ * Qoder's `cosy-machineos`: "<arch>_<os>".
132
+ *
133
+ * The desktop IDE builds this from its own runtime
134
+ * (`V8e = ${process.arch==="arm64"?"aarch64":process.arch==="x64"?"x86_64":process.arch}_${process.platform}`),
135
+ * so the gateway mirrors that exact mapping instead of a fixed macOS value.
136
+ */
132
137
  export function qoderMachineOs(): string {
133
- return QODER_MACHINE_OS;
138
+ const arch = process.arch === "arm64" ? "aarch64" : process.arch === "x64" ? "x86_64" : process.arch;
139
+ return `${arch}_${process.platform}`;
140
+ }
141
+
142
+ /**
143
+ * Qoder's `cosy-machinehostname`.
144
+ *
145
+ * The desktop IDE sends the real machine hostname, normalized to a header-safe
146
+ * form (`B9i` in the unpacked worker: lowercase, non-ASCII and runs of dashes
147
+ * collapsed, truncated to 96 chars with a short hash suffix). Mirror the exact
148
+ * mapping so the value is indistinguishable from the IDE's.
149
+ */
150
+ export function qoderMachineHostname(): string {
151
+ const raw = (osHostname() ?? "").trim().toLowerCase();
152
+ if (!raw) return "";
153
+ const safe = raw
154
+ .replace(/[^\x21-\x7e]+/gu, "-")
155
+ .replace(/-{2,}/gu, "-")
156
+ .replace(/^-+|-+$/gu, "");
157
+ if (safe.length <= 96) return safe;
158
+ const hash = createHash("sha256").update(safe, "utf8").digest("hex").slice(0, 8);
159
+ return `${safe.slice(0, 96 - 1 - 8)}-${hash}`;
134
160
  }
135
161
 
136
162
  /** Cline's `x-platform`. */
@@ -12,12 +12,11 @@
12
12
  * only call the synchronous `get`/`snapshot` accessors and never fetch.
13
13
  */
14
14
  import { getCachedVersion, resetVersionCacheForTesting } from "./provider-version-cache";
15
+ import type { OutboundFetch } from "../provider-contracts";
16
+ import { composeAbortSignal } from "../authentication/oauth-flow-store";
15
17
 
16
18
  /** Structural fetch contract for providers that inject lightweight transports. */
17
- export type ClientVersionFetcher = (
18
- input: RequestInfo | URL,
19
- init?: RequestInit,
20
- ) => Promise<Response>;
19
+ export type ClientVersionFetcher = OutboundFetch;
21
20
 
22
21
  /** One ordered upstream probe. Earlier entries win. */
23
22
  export interface ClientVersionSource {
@@ -156,10 +155,9 @@ export function createClientVersionResolver(
156
155
  }
157
156
 
158
157
  async function probe(source: ClientVersionSource, fetcher: ClientVersionFetcher, signal?: AbortSignal): Promise<string | null> {
159
- const timeoutSignal = AbortSignal.timeout(FETCH_TIMEOUT_MS);
160
158
  const response = await fetcher(source.url, {
161
159
  headers: { accept: "application/json, text/plain, */*" },
162
- signal: signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal,
160
+ signal: composeAbortSignal(signal, FETCH_TIMEOUT_MS),
163
161
  });
164
162
  if (!response.ok) return null;
165
163
  return (source.extract ?? defaultExtract)(response);
@@ -200,7 +200,7 @@ async function githubReleaseVersion(response: Response): Promise<string | null>
200
200
  * The discovery source below only supplies the *IDE* version that follows the
201
201
  * `KiroIDE` device marker.
202
202
  */
203
- const KIRO_RUNTIME_SDK_VERSION = "1.0.39";
203
+ const KIRO_RUNTIME_SDK_VERSION = "1.0.44";
204
204
 
205
205
  /**
206
206
  * AWS SSO OIDC SDK version stamped into login and token-refresh User-Agents.
@@ -242,7 +242,12 @@ export const VERSION_SOURCES = {
242
242
  },
243
243
  qoder: {
244
244
  key: "qoder",
245
- fallback: "1.1.81",
245
+ // The desktop IDE hardcodes its COSY_VERSION as "1.1.80" (`S9` in the
246
+ // unpacked worker bundle); the model-server surface sees this value, so
247
+ // the gateway presents the same build the IDE ships. Discovery (npm
248
+ // `@qoder-ai/qodercli/latest`) may report a newer CLI, but the CLI and
249
+ // IDE are different products — the chat surface identity is the IDE's.
250
+ fallback: "1.1.80",
246
251
  sources: [
247
252
  {
248
253
  url: "https://registry.npmjs.org/@qoder-ai/qodercli/latest",
@@ -254,7 +259,9 @@ export const VERSION_SOURCES = {
254
259
  key: "opencode",
255
260
  // The v1 package (`opencode-ai`) stopped at 1.18. The v2 line publishes
256
261
  // under `@opencode/cli`, and this feed is what its own installer reads.
257
- fallback: "2.2.2",
262
+ // Fallback = the current latest release; raise it whenever the package
263
+ // moves so a cold process does not present a stale client build.
264
+ fallback: "2.2.5",
258
265
  minVersion: "2.0.0",
259
266
  sources: [{ url: "https://opencode.ai/update/api/latest/cli/npm" }],
260
267
  },
@@ -628,11 +635,8 @@ export function buildGrokAuthUserAgent(version = getGrokVersion()): string {
628
635
  }
629
636
 
630
637
 
631
- export const getClineClientVersion = accessor("clineClient").get;
632
638
  export const getClineSdkVersion = accessor("clineSdk").get;
633
639
  export const getClineCliVersion = accessor("clineCli").get;
634
- export const _resetClineClientVersionCache = accessor("clineClient").reset;
635
- export const _resetClineSdkVersionCache = accessor("clineSdk").reset;
636
640
  export const _resetClineCliVersionCache = accessor("clineCli").reset;
637
641
 
638
642
  export const getCodexVersion = accessor("codex").get;
@@ -696,7 +700,6 @@ export const _resetCodeBuddyCnVersionCache = accessor("codebuddyCn").reset;
696
700
 
697
701
  export const getClaudeCliVersion = accessor("claudeCli").get;
698
702
  export const adoptClaudeCliVersion = accessor("claudeCli").adopt;
699
- export const _resetClaudeCliVersionCache = accessor("claudeCli").reset;
700
703
  export const getClaudeSdkVersion = accessor("claudeSdk").get;
701
704
 
702
705
  export const getKiroVersion = accessor("kiro").get;
@@ -59,6 +59,7 @@ export async function seedBundledModels(
59
59
  // Same three-valued rule for the inverse: the provider's directory
60
60
  // states the tier, so the flag is carried rather than derived.
61
61
  freeTier: definition.freeTier ?? null,
62
+ dialect: definition.dialect ?? null,
62
63
  source: "builtin",
63
64
  sourceUpdatedAt: now,
64
65
  enabled: true,
@@ -88,6 +89,7 @@ export async function seedBundledModels(
88
89
  cost: sql`excluded.cost`,
89
90
  proOnly: sql`excluded.pro_only`,
90
91
  freeTier: sql`excluded.free_tier`,
92
+ dialect: sql`excluded.dialect`,
91
93
  source: sql`'builtin'`,
92
94
  sourceUpdatedAt: sql`excluded.source_updated_at`,
93
95
  },
@@ -20,6 +20,7 @@ import { GATEWAY_USER_AGENT } from "./gateway-user-agent";
20
20
  import { isIP } from "node:net";
21
21
  import { isAddressAllowed } from "../../network/ssrf";
22
22
  import type { SsrfPolicy } from "../../config/network";
23
+ import { BoundedLruMap } from "../../transport/routing/bounded-lru";
23
24
 
24
25
  /**
25
26
  * Revision of the compiled provider catalog, and the last one materialized.
@@ -234,14 +235,20 @@ export async function bundledModelCatalog(
234
235
  * 30 s timer, so an ungated re-seed could be pushed onto the next proxy
235
236
  * request for a catalog that had not changed. The paths that do change the
236
237
  * catalog bump the revision; everything else is a no-op here.
238
+ *
239
+ * `precomputedCatalog` supplies the compiled catalog when the caller already
240
+ * materialized it (the boot path's deferred B-01 resolution), so the seed
241
+ * shares that walk instead of running a second one. Absent, the walk runs
242
+ * here as before.
237
243
  */
238
244
  export async function refreshActiveProviderCatalogs(
239
245
  db: CartethyiaDatabase,
240
246
  registry: ProviderRegistry,
247
+ precomputedCatalog?: BundledProviderCatalog,
241
248
  ): Promise<void> {
242
249
  const revision = currentCatalogRevision();
243
250
  if (revision === lastSeededCatalogRevision) return;
244
- const catalog = await bundledModelCatalog(registry);
251
+ const catalog = precomputedCatalog ?? (await bundledModelCatalog(registry));
245
252
  await seedBundledModels(db, catalog.modelsByProvider);
246
253
  lastSeededCatalogRevision = revision;
247
254
  }
@@ -251,8 +258,17 @@ export async function refreshActiveProviderCatalogs(
251
258
  * Last successfully applied BYOK config per normalized provider ID.
252
259
  * Makes repeated `syncByokProviders` runs cheap: an unchanged row is skipped,
253
260
  * while a changed one is re-registered instead of being rejected.
261
+ *
262
+ * Bounded (G-04 / B-04): provider IDs are operator-created strings, so an
263
+ * unbounded map would pin an entry for every retired or deleted custom
264
+ * provider forever. The LRU bound keeps only the most recently touched
265
+ * registrations resident; a dropped entry simply re-registers on the next
266
+ * pass (the fingerprint is a skip-ahead optimization, not correctness).
254
267
  */
255
- const byokRegistrationFingerprints = new Map<string, string>();
268
+ const BYOK_FINGERPRINT_CACHE_MAX_ENTRIES = 1024;
269
+ const byokRegistrationFingerprints = new BoundedLruMap<string, string>(
270
+ BYOK_FINGERPRINT_CACHE_MAX_ENTRIES,
271
+ );
256
272
 
257
273
  function byokFingerprint(
258
274
  baseUrl: string,
@@ -105,6 +105,23 @@ export function invalidateCredentialCache(accountId?: string): void {
105
105
  }
106
106
  }
107
107
 
108
+ /**
109
+ * Invalidates many accounts' cached credentials in one pass over the cache.
110
+ *
111
+ * The batch-delete route deletes several accounts at once; calling the single
112
+ * variant per id would scan the whole cache once per account. This is one
113
+ * scan with a suffix set, so the cost is one pass regardless of batch size.
114
+ */
115
+ export function invalidateCredentialCaches(accountIds: readonly string[]): void {
116
+ if (accountIds.length === 0) return;
117
+ const suffixes = new Set(accountIds.map((id) => `:${id}`));
118
+ for (const key of credCache.keys()) {
119
+ // Account ids are globally unique and contain no colon, so the trailing
120
+ // `:${accountId}` segment uniquely identifies the owning account.
121
+ if (suffixes.has(key.slice(key.lastIndexOf(":")))) credCache.delete(key);
122
+ }
123
+ }
124
+
108
125
  const resolver = new CredentialResolver();
109
126
 
110
127
  /** Stored account fields needed by credential resolution and token refresh. */
@@ -295,7 +312,7 @@ export async function resolveCredentialForAccount(
295
312
  return value;
296
313
  }
297
314
 
298
- export async function resolveAccountSecretString(
315
+ async function resolveAccountSecretString(
299
316
  db: CartethyiaDatabase,
300
317
  providerId: string,
301
318
  accountId: string,
@@ -306,7 +323,7 @@ export async function resolveAccountSecretString(
306
323
  }
307
324
 
308
325
  /** Decrypts the stored provider tokens after refreshing an expired OAuth access token. */
309
- export async function resolveAccountCredentialsForExport(
326
+ async function resolveAccountCredentialsForExport(
310
327
  db: CartethyiaDatabase,
311
328
  providerId: string,
312
329
  accountId: string,
@@ -92,12 +92,19 @@ export function assertWireFamily(
92
92
  );
93
93
  }
94
94
 
95
- /** Fetch capability that validates DNS answers and redirects before each request. */
96
- export type ValidatedOutboundFetch = (
95
+ /**
96
+ * Minimal fetch surface accepted by provider adapters, collectors, and
97
+ * discovery paths. One canonical shape shared across modules that plug a
98
+ * transport into a provider boundary.
99
+ */
100
+ export type OutboundFetch = (
97
101
  input: RequestInfo | URL,
98
102
  init?: RequestInit,
99
103
  ) => Promise<Response>;
100
104
 
105
+ /** Fetch capability that validates DNS answers and redirects before each request. */
106
+ export type ValidatedOutboundFetch = OutboundFetch;
107
+
101
108
  /** Provider WebSocket session over validated WSS egress. */
102
109
  export interface ProviderWebSocketSession {
103
110
  send(message: string): void;
@@ -261,6 +268,8 @@ export interface ProviderDispatchTarget {
261
268
  readonly endpoint_path: string;
262
269
  readonly output_limit?: number | null;
263
270
  readonly capabilities: Readonly<Record<string, boolean>>;
271
+ /** Explicit wire dialect (from `models.dialect`), when set. Absent = resolver fallback. */
272
+ readonly dialect?: string;
264
273
  }
265
274
 
266
275
  /** Provider adapter boundary: canonical request/events in, no public HTTP routes. */
@@ -272,11 +281,13 @@ export interface ProviderAdapter {
272
281
  context: ProviderDispatchContext,
273
282
  ): AsyncIterable<CanonicalEvent>;
274
283
  /**
275
- * Optional native-protocol capability. A provider whose catalog serves a
276
- * non-`llm` service kind (System One) implements the matching method; the
277
- * native route handler looks it up and dispatches the caller's opaque body
278
- * through it. The body is forwarded untouched — the method only adds the
279
- * provider's auth/identity headers and posts it to `endpoint_path`.
284
+ * Optional native-protocol capability for the public `POST /v1/systemone`
285
+ * route (the dispatch leg of the System One service, alongside the probing
286
+ * leg served by the discovery/probing-service). A provider whose catalog
287
+ * serves a non-`llm` service kind (System One) implements the matching
288
+ * method; the native route handler looks it up and dispatches the caller's
289
+ * opaque body through it. The body is forwarded untouched — the method only
290
+ * adds the provider's auth/identity headers and posts it to `endpoint_path`.
280
291
  *
281
292
  * An adapter without this method is simply not eligible for the route, which
282
293
  * is why it is optional rather than a required no-op.
@@ -115,10 +115,12 @@ const RAW_BUNDLED_PROVIDER_METADATA = [
115
115
  },
116
116
  {
117
117
  // Kiro frames its own conversation ledger over an AWS EventStream wire and
118
- // has no chat-shaped endpoint to route through.
118
+ // has no chat-shaped endpoint to route through. Generation is the Kiro
119
+ // runtime service (`https://runtime.{region}.kiro.dev`), not the legacy
120
+ // `q.{region}.amazonaws.com` AWS surface.
119
121
  id: "kiro",
120
122
  displayName: "Kiro",
121
- baseUrl: "https://q.us-east-1.amazonaws.com",
123
+ baseUrl: "https://runtime.us-east-1.kiro.dev",
122
124
  bespokeWire: true,
123
125
  hasAdapterUserAgent: true,
124
126
  defaultSkipProxy: true,
@@ -276,6 +278,19 @@ const RAW_BUNDLED_PROVIDER_METADATA = [
276
278
  baseUrl: "https://api.z.ai/api/coding/paas/v4",
277
279
  credentialUrl: "https://chat.z.ai",
278
280
  },
281
+ {
282
+ // The ZCode Start Plan is the free plan minted by the referral flow. The
283
+ // endpoint refuses bare Anthropic traffic ("3012 request has been blocked
284
+ // due to unusual activity"); the integration adds the ZCode identity
285
+ // headers and the system/date/cache-control dress in-process.
286
+ id: "zcode-start",
287
+ displayName: "ZCode Start",
288
+ baseUrl: "https://zcode.z.ai/api/v1/zcode-plan/anthropic",
289
+ wireFamilyDefault: "messages",
290
+ hasAdapterUserAgent: true,
291
+ credentialUrl: "https://zcode.z.ai",
292
+ credentialHint: "Use the ZCode login JWT, not a Z.AI access token or Coding Plan API key.",
293
+ },
279
294
  {
280
295
  // Factory Droid's LLM proxy. The base URL is the global residency host; an
281
296
  // EU account resolves to `api.eu.factory.ai` from the region recorded in