cartethyia 2.7.0 → 2.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (320) hide show
  1. package/.env.example +107 -106
  2. package/README.md +25 -2
  3. package/dist/dashboard/assets/{BannedPage-P76QLGJA.js → BannedPage-D-J75hBM.js} +1 -1
  4. package/dist/dashboard/assets/BannedPage-D-J75hBM.js.gz +0 -0
  5. package/dist/dashboard/assets/{CliToolDetailPage-DdBggJS9.js → CliToolDetailPage-CVe6RaBH.js} +1 -1
  6. package/dist/dashboard/assets/CliToolDetailPage-CVe6RaBH.js.gz +0 -0
  7. package/dist/dashboard/assets/{CliToolsPage-aN1iXhhP.js → CliToolsPage-Dd8ZSamp.js} +1 -1
  8. package/dist/dashboard/assets/CliToolsPage-Dd8ZSamp.js.gz +0 -0
  9. package/dist/dashboard/assets/{CombosPage-DE-F1nxZ.js → CombosPage-QoJ6foxo.js} +1 -1
  10. package/dist/dashboard/assets/CombosPage-QoJ6foxo.js.gz +0 -0
  11. package/dist/dashboard/assets/ConsoleLogPage-DpNRay4C.js +1 -0
  12. package/dist/dashboard/assets/ConsoleLogPage-DpNRay4C.js.gz +0 -0
  13. package/dist/dashboard/assets/{CustomizationPage-3CUxMy2X.js → CustomizationPage-CKUFTcW4.js} +1 -1
  14. package/dist/dashboard/assets/CustomizationPage-CKUFTcW4.js.gz +0 -0
  15. package/dist/dashboard/assets/HealthEventsModal-CzSLiDzr.js +1 -0
  16. package/dist/dashboard/assets/HealthEventsModal-CzSLiDzr.js.gz +0 -0
  17. package/dist/dashboard/assets/LoginPage-DubdQcvX.js +1 -0
  18. package/dist/dashboard/assets/LoginPage-DubdQcvX.js.gz +0 -0
  19. package/dist/dashboard/assets/{ModelPicker-DKVslqG3.js → ModelPicker-BH8Tehdi.js} +1 -1
  20. package/dist/dashboard/assets/ModelPicker-BH8Tehdi.js.gz +0 -0
  21. package/dist/dashboard/assets/OverviewPage-DuWzAQFL.js +1 -0
  22. package/dist/dashboard/assets/OverviewPage-DuWzAQFL.js.gz +0 -0
  23. package/dist/dashboard/assets/ProviderDetailPage-BKEKe2Fm.js +4 -0
  24. package/dist/dashboard/assets/ProviderDetailPage-BKEKe2Fm.js.gz +0 -0
  25. package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js +1 -0
  26. package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js.gz +0 -0
  27. package/dist/dashboard/assets/ProvidersPage-Bwotu8UJ.js +1 -0
  28. package/dist/dashboard/assets/ProvidersPage-Bwotu8UJ.js.gz +0 -0
  29. package/dist/dashboard/assets/ProxyPage-D7hpWbg9.js +9 -0
  30. package/dist/dashboard/assets/ProxyPage-D7hpWbg9.js.gz +0 -0
  31. package/dist/dashboard/assets/{QuotaPage-BjldQwIU.js → QuotaPage-ATpaxrbl.js} +1 -1
  32. package/dist/dashboard/assets/QuotaPage-ATpaxrbl.js.gz +0 -0
  33. package/dist/dashboard/assets/{SettingsPage-DUIoLRxk.js → SettingsPage-CETophpx.js} +1 -1
  34. package/dist/dashboard/assets/SettingsPage-CETophpx.js.gz +0 -0
  35. package/dist/dashboard/assets/SetupPage-BdgECjqq.js +1 -0
  36. package/dist/dashboard/assets/SetupPage-BdgECjqq.js.gz +0 -0
  37. package/dist/dashboard/assets/{SortableList-fI7JkdIB.js → SortableList-CAK-EN9z.js} +1 -1
  38. package/dist/dashboard/assets/SortableList-CAK-EN9z.js.gz +0 -0
  39. package/dist/dashboard/assets/{StudioPage-CHVZqskZ.js → StudioPage-B7W2_RhT.js} +3 -3
  40. package/dist/dashboard/assets/StudioPage-B7W2_RhT.js.gz +0 -0
  41. package/dist/dashboard/assets/UsagePage-6T4EFDjW.js +56 -0
  42. package/dist/dashboard/assets/UsagePage-6T4EFDjW.js.gz +0 -0
  43. package/dist/dashboard/assets/{api-keys-DFY_fZU4.js → api-keys-CUi6UXsR.js} +1 -1
  44. package/dist/dashboard/assets/api-keys-CUi6UXsR.js.gz +0 -0
  45. package/dist/dashboard/assets/app-KvsUJUMF.css +2 -0
  46. package/dist/dashboard/assets/app-KvsUJUMF.css.gz +0 -0
  47. package/dist/dashboard/assets/{assert-CwdnZARt.js → assert-67xXH5rf.js} +1 -1
  48. package/dist/dashboard/assets/assert-67xXH5rf.js.gz +0 -0
  49. package/dist/dashboard/assets/{badge-Dr-uf0Au.js → badge-DC2L43Mj.js} +1 -1
  50. package/dist/dashboard/assets/badge-DC2L43Mj.js.gz +0 -0
  51. package/dist/dashboard/assets/{banner-BddmMdoS.js → banner-BBVcb0J3.js} +1 -1
  52. package/dist/dashboard/assets/banner-BBVcb0J3.js.gz +0 -0
  53. package/dist/dashboard/assets/{card-CK0PXWlX.js → card-Cca1XC6G.js} +1 -1
  54. package/dist/dashboard/assets/card-Cca1XC6G.js.gz +0 -0
  55. package/dist/dashboard/assets/{cli-tools-CcB6mGh2.js → cli-tools-KvsWa1Jl.js} +1 -1
  56. package/dist/dashboard/assets/cli-tools-KvsWa1Jl.js.gz +0 -0
  57. package/dist/dashboard/assets/{clipboard-button-DGb2P9Yx.js → clipboard-button-DUzEbynq.js} +1 -1
  58. package/dist/dashboard/assets/clipboard-button-DUzEbynq.js.gz +0 -0
  59. package/dist/dashboard/assets/{dialog-LkfuL50u.js → dialog-DFvWhwTa.js} +1 -1
  60. package/dist/dashboard/assets/dialog-DFvWhwTa.js.gz +0 -0
  61. package/dist/dashboard/assets/{drawer-ZbEZ_84c.js → drawer-CFM2sMX1.js} +1 -1
  62. package/dist/dashboard/assets/drawer-CFM2sMX1.js.gz +0 -0
  63. package/dist/dashboard/assets/{entry-CWBY5A0f.js → entry-BLBLxX0h.js} +3 -3
  64. package/dist/dashboard/assets/entry-BLBLxX0h.js.gz +0 -0
  65. package/dist/dashboard/assets/{entry-BJfsVMvA.js → entry-Bqy8RFvM.js} +1 -1
  66. package/dist/dashboard/assets/entry-Bqy8RFvM.js.gz +0 -0
  67. package/dist/dashboard/assets/{entry-CvC1-Zqx.js → entry-_xHo5x6r.js} +1 -1
  68. package/dist/dashboard/assets/entry-_xHo5x6r.js.gz +0 -0
  69. package/dist/dashboard/assets/formatters-mpBPqAQ8.js +1 -0
  70. package/dist/dashboard/assets/formatters-mpBPqAQ8.js.gz +0 -0
  71. package/dist/dashboard/assets/{github-badge-BxpznFLt.js → github-badge-C9e8Ts7e.js} +1 -1
  72. package/dist/dashboard/assets/github-badge-C9e8Ts7e.js.gz +0 -0
  73. package/dist/dashboard/assets/{index-CDzP3ovJ.js → index-D6QzEC_n.js} +2 -2
  74. package/dist/dashboard/assets/index-D6QzEC_n.js.gz +0 -0
  75. package/dist/dashboard/assets/{inline-Ae13MQ5w.js → inline-BFUcvllj.js} +1 -1
  76. package/dist/dashboard/assets/inline-BFUcvllj.js.gz +0 -0
  77. package/dist/dashboard/assets/{input-D23fo7cp.js → input-C_ILAvBb.js} +1 -1
  78. package/dist/dashboard/assets/input-C_ILAvBb.js.gz +0 -0
  79. package/dist/dashboard/assets/{layout-CSsxjj5P.js → layout-CBIyT6Rt.js} +1 -1
  80. package/dist/dashboard/assets/layout-CBIyT6Rt.js.gz +0 -0
  81. package/dist/dashboard/assets/{list-row-dmbwZMDY.js → list-row-ebJ_-Nsb.js} +1 -1
  82. package/dist/dashboard/assets/list-row-ebJ_-Nsb.js.gz +0 -0
  83. package/dist/dashboard/assets/{live-BG1oUsZZ.js → live-D0mm--ME.js} +1 -1
  84. package/dist/dashboard/assets/live-D0mm--ME.js.gz +0 -0
  85. package/dist/dashboard/assets/{mutation-DSF-e4ho.js → mutation-sMD965oO.js} +1 -1
  86. package/dist/dashboard/assets/mutation-sMD965oO.js.gz +0 -0
  87. package/dist/dashboard/assets/{numbers-Bm_aECY7.js → numbers-BO9dKaFr.js} +1 -1
  88. package/dist/dashboard/assets/numbers-BO9dKaFr.js.gz +0 -0
  89. package/dist/dashboard/assets/providers/inception.svg +5 -0
  90. package/dist/dashboard/assets/providers/inception.svg.gz +0 -0
  91. package/dist/dashboard/assets/{query-keys-CF56nYIV.js → query-keys-CfL_Zdoh.js} +1 -1
  92. package/dist/dashboard/assets/query-keys-CfL_Zdoh.js.gz +0 -0
  93. package/dist/dashboard/assets/{routing-CeA71n7G.js → routing-BnIpi1IJ.js} +1 -1
  94. package/dist/dashboard/assets/routing-BnIpi1IJ.js.gz +0 -0
  95. package/dist/dashboard/assets/{select-KIT0rC6G.js → select-Cj5Nw43g.js} +1 -1
  96. package/dist/dashboard/assets/select-Cj5Nw43g.js.gz +0 -0
  97. package/dist/dashboard/assets/{settings-B_2gkePf.js → settings-BAFhDgX8.js} +1 -1
  98. package/dist/dashboard/assets/settings-BAFhDgX8.js.gz +0 -0
  99. package/dist/dashboard/assets/{stack-D7WOSzcX.js → stack-EMrOMt4I.js} +1 -1
  100. package/dist/dashboard/assets/stack-EMrOMt4I.js.gz +0 -0
  101. package/dist/dashboard/assets/{state-BBxtKZOQ.js → state-CWoo7ty5.js} +1 -1
  102. package/dist/dashboard/assets/state-CWoo7ty5.js.gz +0 -0
  103. package/dist/dashboard/assets/{switch-DNS_D5Ea.js → switch-CCjT6IkF.js} +1 -1
  104. package/dist/dashboard/assets/switch-CCjT6IkF.js.gz +0 -0
  105. package/dist/dashboard/assets/{useMutation-BgoxdoMk.js → useMutation-DjkLHUcE.js} +1 -1
  106. package/dist/dashboard/assets/useMutation-DjkLHUcE.js.gz +0 -0
  107. package/dist/dashboard/index.html +1 -1
  108. package/dist/dashboard/index.html.gz +0 -0
  109. package/dist/dashboard/precompressed-assets.json +54 -53
  110. package/migrations/full-postgres/0024_add_pool_provider_cooldowns.sql +12 -0
  111. package/migrations/full-postgres/0025_add_pool_random_strategy.sql +3 -0
  112. package/migrations/lite-sqlite3/0024_add_pool_provider_cooldowns.sql +12 -0
  113. package/migrations/lite-sqlite3/0025_add_pool_random_strategy.sql +20 -0
  114. package/package.json +96 -96
  115. package/scripts/cli/console-menu.ts +5 -2
  116. package/scripts/cli/tray.ts +21 -6
  117. package/src/boot/app.ts +684 -714
  118. package/src/boot/dependencies.ts +65 -62
  119. package/src/config/cooldowns.ts +16 -0
  120. package/src/config/providers.ts +13 -1
  121. package/src/config/resources.ts +70 -70
  122. package/src/config/security.ts +37 -37
  123. package/src/config/spec.ts +371 -358
  124. package/src/console/console-router.ts +233 -225
  125. package/src/console/domain-registration.ts +398 -381
  126. package/src/console/providers/catalog/catalog-projections.ts +2 -6
  127. package/src/console/providers/catalog/contracts.ts +19 -0
  128. package/src/console/providers/catalog/provider-operations.ts +38 -0
  129. package/src/console/providers/catalog/routes.ts +14 -0
  130. package/src/console/providers/catalog/store-helpers.ts +326 -0
  131. package/src/console/providers/catalog/store.ts +1292 -1563
  132. package/src/console/quota/account-quota-global.ts +2 -2
  133. package/src/console/quota/account-quota-shared.ts +1 -1
  134. package/src/console/quota/account-quota-tenant.ts +35 -12
  135. package/src/console/quota/quota-view.ts +2 -2
  136. package/src/console/routing/pools/contracts.ts +41 -1
  137. package/src/console/routing/pools/operations.ts +183 -4
  138. package/src/console/routing/pools/relay-deploy.ts +17 -4
  139. package/src/console/routing/pools/routes.ts +30 -0
  140. package/src/console/routing/pools/store.ts +98 -8
  141. package/src/main.ts +183 -167
  142. package/src/network/outbound-fetch.ts +226 -365
  143. package/src/network/pool/agent.ts +8 -0
  144. package/src/network/pool/pool-state.ts +7 -0
  145. package/src/network/pool/selector.ts +110 -2
  146. package/src/network/pool-cooldown-store.ts +252 -0
  147. package/src/network/pool-health-machine.ts +5 -3
  148. package/src/network/pool-health.ts +36 -9
  149. package/src/observability/event-query.ts +57 -0
  150. package/src/observability/metrics.ts +467 -467
  151. package/src/observability/runtime-metrics.ts +269 -269
  152. package/src/persistence/health-event-flush.ts +2 -0
  153. package/src/persistence/schema.ts +19 -0
  154. package/src/persistence/usage-flush.ts +8 -3
  155. package/src/protocol/canonical-model.ts +1 -1
  156. package/src/protocol/dsml.ts +377 -0
  157. package/src/protocol/gateway-error.ts +232 -232
  158. package/src/{providers/provider-reasoning.ts → protocol/reasoning.ts} +10 -9
  159. package/src/protocol/request/chat.ts +7 -7
  160. package/src/protocol/request/codex.ts +2 -2
  161. package/src/protocol/request/gemini.ts +1 -1
  162. package/src/protocol/request/messages.ts +6 -6
  163. package/src/protocol/request/responses.ts +7 -7
  164. package/src/protocol/response/dsml.ts +12 -133
  165. package/src/{transport → protocol}/translation/attachment-integrity.ts +2 -2
  166. package/src/{transport → protocol}/translation/cache-controls.ts +1 -1
  167. package/src/{transport → protocol}/translation/capabilities.ts +2 -2
  168. package/src/{transport → protocol}/translation/normalize.ts +1 -1
  169. package/src/{transport → protocol}/translation/quirks.ts +1 -1
  170. package/src/{transport → protocol}/translation/search.ts +1 -1
  171. package/src/{transport → protocol}/translation/thinking.ts +23 -1
  172. package/src/{transport → protocol}/translation/tool-id.ts +1 -1
  173. package/src/{transport → protocol}/translation/tool-repair.ts +2 -2
  174. package/src/protocol/upstream-parsing.ts +176 -0
  175. package/src/providers/adapters/compatible-adapter.ts +11 -2
  176. package/src/providers/authentication/oauth-refresh-service.ts +9 -5
  177. package/src/providers/default-registry.ts +21 -5
  178. package/src/providers/discovery/probe-phases.ts +16 -3
  179. package/src/providers/discovery/probing-service.ts +4 -1
  180. package/src/providers/integrations/anthropic.ts +1 -1
  181. package/src/providers/integrations/buddy/buddy-catalog-shared.ts +1 -4
  182. package/src/providers/integrations/buddy/buddy-chat-shared.ts +141 -8
  183. package/src/providers/integrations/buddy/buddy-checkin.ts +5 -1
  184. package/src/providers/integrations/buddy/buddy-growth-shared.ts +0 -82
  185. package/src/providers/integrations/buddy/buddy-identity.ts +25 -0
  186. package/src/providers/integrations/buddy/buddy-server-tools.ts +240 -0
  187. package/src/providers/integrations/buddy/codebuddy/cn-catalog.ts +36 -0
  188. package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +6 -31
  189. package/src/providers/integrations/buddy/codebuddy/provider.ts +2 -0
  190. package/src/providers/integrations/buddy/codebuddy/shared.ts +19 -4
  191. package/src/providers/integrations/buddy/turing-device-token.ts +262 -0
  192. package/src/providers/integrations/buddy/workbuddy/provider.ts +2 -0
  193. package/src/providers/integrations/buddy/workbuddy/shared.ts +56 -3
  194. package/src/providers/integrations/claude/claude.ts +1 -1
  195. package/src/providers/integrations/cloudflareai/cloudflareai.ts +1 -1
  196. package/src/providers/integrations/codex/codex-errors.ts +1 -1
  197. package/src/providers/integrations/codex/codex.ts +1 -1
  198. package/src/providers/integrations/factory/factory.ts +1 -1
  199. package/src/providers/integrations/github/github.ts +1 -1
  200. package/src/providers/integrations/grok/grok.ts +1 -1
  201. package/src/providers/integrations/inception/provider.ts +91 -0
  202. package/src/providers/integrations/inferhub.ts +1 -1
  203. package/src/providers/integrations/kiro/kiro-request.ts +1 -1
  204. package/src/providers/integrations/mistral.ts +193 -19
  205. package/src/providers/integrations/opencode/fingerprint.ts +19 -2
  206. package/src/providers/integrations/opencode/prompt.ts +111 -0
  207. package/src/providers/integrations/opencode/provider.ts +101 -23
  208. package/src/providers/integrations/opencode/tool-definitions.ts +4 -4
  209. package/src/providers/integrations/qoder/qoder-checkin.ts +303 -0
  210. package/src/providers/integrations/qoder/qoder.ts +1641 -1458
  211. package/src/providers/integrations/shared/install-id.ts +2 -1
  212. package/src/providers/integrations/trae/trae-cache.ts +110 -0
  213. package/src/providers/integrations/trae/trae-oauth.ts +29 -4
  214. package/src/providers/integrations/trae/trae-protocol.ts +2 -1
  215. package/src/providers/integrations/trae/trae.ts +106 -23
  216. package/src/providers/operations/account-error-classification.ts +1660 -0
  217. package/src/providers/operations/account-health-service.ts +621 -2097
  218. package/src/providers/operations/account-reset-service.ts +2 -0
  219. package/src/providers/provider-contracts.ts +0 -2
  220. package/src/providers/provider-metadata.ts +25 -4
  221. package/src/providers/provider-probe.ts +2 -2
  222. package/src/{console → providers}/quota/cache.ts +1 -1
  223. package/src/{console → providers}/quota/refresh.ts +5 -5
  224. package/src/transport/dispatch/attempt-finalize.ts +114 -12
  225. package/src/transport/dispatch/attempt-loop.ts +3 -0
  226. package/src/transport/dispatch/empty-stream.ts +224 -217
  227. package/src/transport/dispatch/generation.ts +37 -55
  228. package/src/transport/dispatch/handler-deps.ts +32 -0
  229. package/src/transport/dispatch/leases.ts +9 -4
  230. package/src/transport/dispatch/proxy-request.ts +6 -30
  231. package/src/transport/dispatch/responses-compact.ts +22 -43
  232. package/src/transport/dispatch/streaming/finalize.ts +3 -0
  233. package/src/transport/dispatch/streaming/stream.ts +0 -8
  234. package/src/transport/dispatch/systemone.ts +22 -42
  235. package/src/transport/dispatch/token-count.ts +23 -39
  236. package/src/transport/dispatch/upstream.ts +1 -3
  237. package/src/transport/dispatch/websearch.ts +22 -41
  238. package/src/transport/failure-policy.ts +59 -178
  239. package/src/transport/guards/abuse-guard.ts +10 -0
  240. package/src/transport/guards/auth-guard.ts +109 -109
  241. package/src/transport/guards/error-lifecycle.ts +1 -1
  242. package/src/transport/guards/pipeline.ts +220 -220
  243. package/src/transport/guards/request-context.ts +245 -238
  244. package/src/transport/request/degradation.ts +20 -1
  245. package/src/transport/request/inflight.ts +4 -114
  246. package/src/transport/request/preparer.ts +6 -6
  247. package/src/transport/request/state.ts +66 -38
  248. package/src/transport/request/tenant-preferences.ts +1 -1
  249. package/src/transport/routing/route-catalog.ts +41 -31
  250. package/src/transport/routing/router.ts +2 -2
  251. package/src/transport/surface/messages/parse.ts +1 -1
  252. package/src/workers/buddy-growth-tasks.ts +346 -425
  253. package/src/workers/daily-checkin.ts +17 -6
  254. package/src/workers/quota-refresh-sweep.ts +2 -2
  255. package/src/workers/scheduler.ts +17 -1
  256. package/dist/dashboard/assets/BannedPage-P76QLGJA.js.gz +0 -0
  257. package/dist/dashboard/assets/CliToolDetailPage-DdBggJS9.js.gz +0 -0
  258. package/dist/dashboard/assets/CliToolsPage-aN1iXhhP.js.gz +0 -0
  259. package/dist/dashboard/assets/CombosPage-DE-F1nxZ.js.gz +0 -0
  260. package/dist/dashboard/assets/ConsoleLogPage-5SpmfLyw.js +0 -1
  261. package/dist/dashboard/assets/ConsoleLogPage-5SpmfLyw.js.gz +0 -0
  262. package/dist/dashboard/assets/CustomizationPage-3CUxMy2X.js.gz +0 -0
  263. package/dist/dashboard/assets/HealthEventsModal-BkmJQKC0.js +0 -1
  264. package/dist/dashboard/assets/HealthEventsModal-BkmJQKC0.js.gz +0 -0
  265. package/dist/dashboard/assets/LoginPage-B_0FUKWc.js +0 -1
  266. package/dist/dashboard/assets/LoginPage-B_0FUKWc.js.gz +0 -0
  267. package/dist/dashboard/assets/ModelPicker-DKVslqG3.js.gz +0 -0
  268. package/dist/dashboard/assets/OverviewPage-D-H4MEiT.js +0 -1
  269. package/dist/dashboard/assets/OverviewPage-D-H4MEiT.js.gz +0 -0
  270. package/dist/dashboard/assets/ProviderDetailPage-CEJw6Guo.js +0 -3
  271. package/dist/dashboard/assets/ProviderDetailPage-CEJw6Guo.js.gz +0 -0
  272. package/dist/dashboard/assets/ProviderIcon-CmfzxpVM.js +0 -1
  273. package/dist/dashboard/assets/ProviderIcon-CmfzxpVM.js.gz +0 -0
  274. package/dist/dashboard/assets/ProvidersPage-CEplAR-i.js +0 -1
  275. package/dist/dashboard/assets/ProvidersPage-CEplAR-i.js.gz +0 -0
  276. package/dist/dashboard/assets/ProxyPage-CAN7hy0f.js +0 -7
  277. package/dist/dashboard/assets/ProxyPage-CAN7hy0f.js.gz +0 -0
  278. package/dist/dashboard/assets/QuotaPage-BjldQwIU.js.gz +0 -0
  279. package/dist/dashboard/assets/SettingsPage-DUIoLRxk.js.gz +0 -0
  280. package/dist/dashboard/assets/SetupPage-_bCaTM0v.js +0 -1
  281. package/dist/dashboard/assets/SetupPage-_bCaTM0v.js.gz +0 -0
  282. package/dist/dashboard/assets/SortableList-fI7JkdIB.js.gz +0 -0
  283. package/dist/dashboard/assets/StudioPage-CHVZqskZ.js.gz +0 -0
  284. package/dist/dashboard/assets/UsagePage-DiFBymHj.js +0 -56
  285. package/dist/dashboard/assets/UsagePage-DiFBymHj.js.gz +0 -0
  286. package/dist/dashboard/assets/api-keys-DFY_fZU4.js.gz +0 -0
  287. package/dist/dashboard/assets/app-BOJ1_xUB.css +0 -2
  288. package/dist/dashboard/assets/app-BOJ1_xUB.css.gz +0 -0
  289. package/dist/dashboard/assets/assert-CwdnZARt.js.gz +0 -0
  290. package/dist/dashboard/assets/badge-Dr-uf0Au.js.gz +0 -0
  291. package/dist/dashboard/assets/banner-BddmMdoS.js.gz +0 -0
  292. package/dist/dashboard/assets/card-CK0PXWlX.js.gz +0 -0
  293. package/dist/dashboard/assets/cli-tools-CcB6mGh2.js.gz +0 -0
  294. package/dist/dashboard/assets/clipboard-button-DGb2P9Yx.js.gz +0 -0
  295. package/dist/dashboard/assets/cog-CdWhsajs.js +0 -1
  296. package/dist/dashboard/assets/cog-CdWhsajs.js.gz +0 -0
  297. package/dist/dashboard/assets/dialog-LkfuL50u.js.gz +0 -0
  298. package/dist/dashboard/assets/drawer-ZbEZ_84c.js.gz +0 -0
  299. package/dist/dashboard/assets/entry-BJfsVMvA.js.gz +0 -0
  300. package/dist/dashboard/assets/entry-CWBY5A0f.js.gz +0 -0
  301. package/dist/dashboard/assets/entry-CvC1-Zqx.js.gz +0 -0
  302. package/dist/dashboard/assets/github-badge-BxpznFLt.js.gz +0 -0
  303. package/dist/dashboard/assets/index-CDzP3ovJ.js.gz +0 -0
  304. package/dist/dashboard/assets/inline-Ae13MQ5w.js.gz +0 -0
  305. package/dist/dashboard/assets/input-D23fo7cp.js.gz +0 -0
  306. package/dist/dashboard/assets/layout-CSsxjj5P.js.gz +0 -0
  307. package/dist/dashboard/assets/list-row-dmbwZMDY.js.gz +0 -0
  308. package/dist/dashboard/assets/live-BG1oUsZZ.js.gz +0 -0
  309. package/dist/dashboard/assets/mutation-DSF-e4ho.js.gz +0 -0
  310. package/dist/dashboard/assets/numbers-Bm_aECY7.js.gz +0 -0
  311. package/dist/dashboard/assets/query-keys-CF56nYIV.js.gz +0 -0
  312. package/dist/dashboard/assets/routing-CeA71n7G.js.gz +0 -0
  313. package/dist/dashboard/assets/select-KIT0rC6G.js.gz +0 -0
  314. package/dist/dashboard/assets/settings-B_2gkePf.js.gz +0 -0
  315. package/dist/dashboard/assets/stack-D7WOSzcX.js.gz +0 -0
  316. package/dist/dashboard/assets/state-BBxtKZOQ.js.gz +0 -0
  317. package/dist/dashboard/assets/switch-DNS_D5Ea.js.gz +0 -0
  318. package/dist/dashboard/assets/useMutation-BgoxdoMk.js.gz +0 -0
  319. /package/dist/dashboard/assets/{app-CaXZ9SCn.js → app-BaWd0puM.js} +0 -0
  320. /package/dist/dashboard/assets/{app-CaXZ9SCn.js.gz → app-BaWd0puM.js.gz} +0 -0
@@ -0,0 +1,303 @@
1
+ /**
2
+ * Qoder daily check-in (streak / 100 Credits per day), ported from the
3
+ * reference bridge (`qoder_accounts.py` in `qoder2api-hub`).
4
+ *
5
+ * Two upstream surfaces, tried in order:
6
+ *
7
+ * 1. Legacy sash: `GET /sash/api/v1/me/daily-check-in/status` then
8
+ * `POST /sash/api/v1/me/daily-check-in/claim`. The status exposes the
9
+ * streak (`currentStreakDays`) and the reward (`rewardCredits`, 100).
10
+ * 2. Activity-platform campaign: when the legacy surface is absent (INTL often
11
+ * answers 404), `GET /sash/api/v1/me/campaigns` lists daily rewards and the
12
+ * CREDITS-kind claimable one is claimed via
13
+ * `POST /sash/api/v1/me/campaigns/{id}/claim`.
14
+ *
15
+ * The result shape is the same `DailyCheckinResult` the buddy family uses, so
16
+ * the shared sweep slot ledger (`daily_checkin_ledger`), the log phrasing, and
17
+ * the console surface treat Qoder like any other daily-grant provider.
18
+ */
19
+ import { QODER_REALMS, qoderRealmForProvider } from "./qoder-realm";
20
+
21
+ /** Structural fetch bound; Bun's own fetch type carries extra host props. */
22
+ type Fetcher = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
23
+ import type { DailyCheckinResult, DailyCheckinState } from "../buddy/buddy-checkin";
24
+
25
+ export const QODER_CHECKIN_PROVIDER_IDS: readonly string[] = ["qoder", "qodercn"];
26
+
27
+ /** True when this provider id runs the Qoder check-in surface. */
28
+ export function isQoderCheckinProvider(providerId: string): boolean {
29
+ return (QODER_CHECKIN_PROVIDER_IDS as readonly string[]).includes(providerId);
30
+ }
31
+
32
+ /** Abort budget for one upstream check-in request. */
33
+ const TIMEOUT_MS = 15_000;
34
+
35
+ const CHECKIN_STATUS_PATH = "/sash/api/v1/me/daily-check-in/status";
36
+ const CHECKIN_CLAIM_PATH = "/sash/api/v1/me/daily-check-in/claim";
37
+ const CAMPAIGNS_PATH = "/sash/api/v1/me/campaigns";
38
+ const CAMPAIGN_CLAIM_PATH = "/sash/api/v1/me/campaigns/%s/claim";
39
+
40
+ function asRecord(value: unknown): Record<string, unknown> | null {
41
+ if (typeof value !== "object" || value === null) return null;
42
+ return value as Record<string, unknown>;
43
+ }
44
+
45
+ function asNumber(value: unknown): number | null {
46
+ if (typeof value === "number" && Number.isFinite(value)) return value;
47
+ if (typeof value === "string" && value.trim() !== "") {
48
+ const parsed = Number(value);
49
+ return Number.isFinite(parsed) ? parsed : null;
50
+ }
51
+ return null;
52
+ }
53
+
54
+ function safeParse(raw: string): unknown {
55
+ try {
56
+ return JSON.parse(raw);
57
+ } catch {
58
+ return null;
59
+ }
60
+ }
61
+
62
+ function baseOutcome(
63
+ providerId: string,
64
+ accountId: string,
65
+ ): { providerId: string; accountId: string; credit: null; streakDays: null; error: null } {
66
+ return { providerId, accountId, credit: null, streakDays: null, error: null };
67
+ }
68
+
69
+ function asState(state: string, today: string, lastClaimedAt: unknown): { active: boolean; todayCheckedIn: boolean } {
70
+ const status = state.toUpperCase();
71
+ const active = status === "CLAIMABLE" || status === "CLAIMED";
72
+ let claimedToday = false;
73
+ if (status === "CLAIMED") {
74
+ const stamp = asNumber(lastClaimedAt);
75
+ if (stamp !== null) {
76
+ const day = new Date(stamp * 1000).toISOString().slice(0, 10);
77
+ claimedToday = day === today;
78
+ }
79
+ }
80
+ return { active, todayCheckedIn: claimedToday };
81
+ }
82
+
83
+ /** GET campaign list; returns `null` when the surface is unreachable/unauthorized. */
84
+ async function fetchCampaigns(
85
+ base: string,
86
+ credential: string,
87
+ fetcher: Fetcher,
88
+ ): Promise<Record<string, unknown>[] | null> {
89
+ try {
90
+ const response = await fetcher(`${base}${CAMPAIGNS_PATH}`, {
91
+ method: "GET",
92
+ headers: {
93
+ Authorization: `Bearer ${credential}`,
94
+ Accept: "application/json",
95
+ },
96
+ signal: AbortSignal.timeout(TIMEOUT_MS),
97
+ });
98
+ if (response.status === 401 || response.status === 403) return null;
99
+ if (!response.ok) return null;
100
+ const payload: unknown = await response.json().catch(() => null);
101
+ const rec = asRecord(payload);
102
+ const list = Array.isArray(rec?.["campaigns"]) ? rec!["campaigns"] : Array.isArray(payload) ? payload : null;
103
+ return Array.isArray(list) ? (list as Record<string, unknown>[]) : null;
104
+ } catch {
105
+ return null;
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Claims one campaign and returns the resulting state. Mirrors the donor's
111
+ * `claim_campaign` idempotence handling: a 409 or `ALREADY_CLAIMED` body is
112
+ * an already-claimed grant, `SAME_PERSON_ALREADY_CLAIMED`/`BLOCKED` is a
113
+ * same-person block (not a failure of this account's day), and anything else
114
+ * is an error.
115
+ */
116
+ async function claimCampaign(
117
+ base: string,
118
+ campaignId: string,
119
+ credential: string,
120
+ fetcher: Fetcher,
121
+ ): Promise<{ state: DailyCheckinState; amount: number }> {
122
+ const url = base + CAMPAIGN_CLAIM_PATH.replace("%s", encodeURIComponent(campaignId));
123
+ let response: Response;
124
+ try {
125
+ response = await fetcher(url, {
126
+ method: "POST",
127
+ headers: {
128
+ Authorization: `Bearer ${credential}`,
129
+ "Content-Type": "application/json",
130
+ Accept: "application/json",
131
+ },
132
+ body: "{}",
133
+ signal: AbortSignal.timeout(TIMEOUT_MS),
134
+ });
135
+ } catch {
136
+ return { state: "error", amount: 0 };
137
+ }
138
+ const raw = await response.text().catch(() => "");
139
+ const payload: unknown = raw ? safeParse(raw) : null;
140
+ const rec = asRecord(payload);
141
+ const status = String(rec?.["status"] ?? "").toUpperCase();
142
+ const failure = String(rec?.["failureCode"] ?? "").toUpperCase();
143
+ const success = rec?.["success"] !== false;
144
+ const benefit = asRecord(rec?.["benefit"]);
145
+ const amount = asNumber(rec?.["amount"] ?? benefit?.["amount"]) ?? 0;
146
+ if (response.status === 409 || failure === "ALREADY_CLAIMED" || status === "CLAIMED" && failure === "REPLAYED") {
147
+ return { state: "already_claimed", amount };
148
+ }
149
+ if (failure === "SAME_PERSON_ALREADY_CLAIMED" || status === "BLOCKED") {
150
+ return { state: "not_eligible", amount: 0 };
151
+ }
152
+ if (response.ok && success && (status === "CLAIMED" || status === "GRANTED" || status === "SUCCESS")) {
153
+ return { state: "claimed", amount };
154
+ }
155
+ return { state: "error", amount: 0 };
156
+ }
157
+
158
+ /** Legacy sash status + claim. Returns `null` when the surface is absent (404/405/410). */
159
+ async function legacySashCheckin(args: {
160
+ readonly base: string;
161
+ readonly credential: string;
162
+ readonly fetcher: Fetcher;
163
+ readonly now?: () => Date;
164
+ }): Promise<{ state: DailyCheckinState; credit: number; streakDays: number } | null> {
165
+ const { base, credential, fetcher } = args;
166
+ const today = (args.now?.() ?? new Date()).toISOString().slice(0, 10);
167
+ let statusResponse: Response;
168
+ try {
169
+ statusResponse = await fetcher(`${base}${CHECKIN_STATUS_PATH}`, {
170
+ method: "GET",
171
+ headers: {
172
+ Authorization: `Bearer ${credential}`,
173
+ Accept: "application/json",
174
+ },
175
+ signal: AbortSignal.timeout(TIMEOUT_MS),
176
+ });
177
+ } catch {
178
+ return { state: "error", credit: 0, streakDays: 0 };
179
+ }
180
+ if (statusResponse.status === 401 || statusResponse.status === 403) {
181
+ return { state: "error", credit: 0, streakDays: 0 };
182
+ }
183
+ if (statusResponse.status === 404 || statusResponse.status === 405 || statusResponse.status === 410) {
184
+ return null; // surface absent — caller falls back to campaign
185
+ }
186
+ if (!statusResponse.ok) {
187
+ return { state: "error", credit: 0, streakDays: 0 };
188
+ }
189
+ const payload: unknown = await statusResponse.json().catch(() => null);
190
+ const rec = asRecord(payload);
191
+ if (!rec) return { state: "error", credit: 0, streakDays: 0 };
192
+ const { active, todayCheckedIn } = asState(String(rec["status"] ?? ""), today, rec["lastClaimedAt"]);
193
+ const streakDays = asNumber(rec["currentStreakDays"]) ?? 0;
194
+ const credit = asNumber(rec["rewardCredits"]) ?? 100;
195
+ if (todayCheckedIn) return { state: "already_claimed", credit: 0, streakDays };
196
+ if (!active) return { state: "not_eligible", credit: 0, streakDays };
197
+ // Claim.
198
+ let claimResponse: Response;
199
+ try {
200
+ claimResponse = await fetcher(`${base}${CHECKIN_CLAIM_PATH}`, {
201
+ method: "POST",
202
+ headers: {
203
+ Authorization: `Bearer ${credential}`,
204
+ "Content-Type": "application/json",
205
+ Accept: "application/json",
206
+ },
207
+ body: "{}",
208
+ signal: AbortSignal.timeout(TIMEOUT_MS),
209
+ });
210
+ } catch {
211
+ return { state: "error", credit: 0, streakDays };
212
+ }
213
+ const raw = await claimResponse.text().catch(() => "");
214
+ const lower = raw.toLowerCase();
215
+ if (claimResponse.status === 409 || lower.includes("already_claimed") || lower.includes("已签到")) {
216
+ return { state: "already_claimed", credit: 0, streakDays };
217
+ }
218
+ const body: unknown = raw ? safeParse(raw) : null;
219
+ const bodyRec = asRecord(body);
220
+ const ok = claimResponse.ok && bodyRec?.["success"] !== false;
221
+ if (!ok) return { state: "error", credit: 0, streakDays };
222
+ return { state: "claimed", credit, streakDays };
223
+ }
224
+
225
+ /**
226
+ * Performs one account's Qoder daily check-in: legacy sash first, campaign
227
+ * fallback when the sash surface is absent. Returns the same
228
+ * `DailyCheckinResult` shape the shared sweep consumes.
229
+ */
230
+ export async function fetchQoderDailyCheckin(args: {
231
+ readonly providerId: string;
232
+ readonly accountId: string;
233
+ readonly credential: string;
234
+ readonly fetcher: Fetcher;
235
+ readonly now?: () => Date;
236
+ }): Promise<DailyCheckinResult> {
237
+ const { providerId, accountId, credential, fetcher } = args;
238
+ const baseResult = baseOutcome(providerId, accountId);
239
+ if (!credential) {
240
+ return { ...baseResult, state: "error", error: "Account has no stored credential." };
241
+ }
242
+ const realm = qoderRealmForProvider(providerId);
243
+ const base = QODER_REALMS[realm].openapi;
244
+
245
+ const sash = await legacySashCheckin({
246
+ base,
247
+ credential,
248
+ fetcher,
249
+ ...(args.now === undefined ? {} : { now: args.now }),
250
+ });
251
+ if (sash !== null) {
252
+ return {
253
+ ...baseResult,
254
+ state: sash.state,
255
+ credit: sash.state === "claimed" ? sash.credit : null,
256
+ streakDays: sash.streakDays,
257
+ ...(sash.state === "error" ? { error: "Upstream daily check-in failed." } : {}),
258
+ };
259
+ }
260
+
261
+ // Legacy surface absent: campaign fallback.
262
+ const campaigns = await fetchCampaigns(base, credential, fetcher);
263
+ if (campaigns === null) {
264
+ return { ...baseResult, state: "error", error: "Check-in surface unavailable (legacy 404 and campaign list failed)." };
265
+ }
266
+ let alreadySeen = false;
267
+ for (const campaign of campaigns) {
268
+ const rec = asRecord(campaign);
269
+ if (!rec) continue;
270
+ const benefit = asRecord(rec["benefit"]);
271
+ const kind = String(benefit?.["kind"] ?? "").toUpperCase();
272
+ if (kind !== "CREDITS" && kind !== "") continue;
273
+ const actionType = String(rec["action_type"] ?? "");
274
+ if (actionType !== "" && actionType !== "CLAIM_BENEFIT") continue;
275
+ const claimStatus = String(rec["claim_status"] ?? "").toUpperCase();
276
+ if (claimStatus === "CLAIMED") {
277
+ alreadySeen = true;
278
+ continue;
279
+ }
280
+ if (claimStatus !== "CLAIMABLE") continue;
281
+ const campaignId = String(rec["campaign_id"] ?? "");
282
+ if (!campaignId) continue;
283
+ const result = await claimCampaign(base, campaignId, credential, fetcher);
284
+ if (result.state === "claimed") {
285
+ const amount = asNumber(benefit?.["amount"]) ?? result.amount;
286
+ return { ...baseResult, state: "claimed", credit: amount, streakDays: null };
287
+ }
288
+ if (result.state === "already_claimed") {
289
+ alreadySeen = true;
290
+ continue;
291
+ }
292
+ if (result.state === "error") {
293
+ return { ...baseResult, state: "error", error: "Campaign claim failed." };
294
+ }
295
+ // not_eligible (same-person block): stop trying further campaigns.
296
+ return { ...baseResult, state: "not_eligible", error: "Same-person claim already used today." };
297
+ }
298
+ return {
299
+ ...baseResult,
300
+ state: alreadySeen ? "already_claimed" : "unavailable",
301
+ error: alreadySeen ? null : "No daily CREDITS campaign claimable.",
302
+ };
303
+ }