cartethyia 2.7.4 → 2.7.5

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 (553) hide show
  1. package/.env.example +2 -0
  2. package/README.md +17 -5
  3. package/dist/dashboard/assets/{BannedPage-ChG5svFb.js → BannedPage-Cj15GsMp.js} +1 -1
  4. package/dist/dashboard/assets/BannedPage-Cj15GsMp.js.gz +0 -0
  5. package/dist/dashboard/assets/ClaimGiftsButton-D83pBJ6J.js +1 -0
  6. package/dist/dashboard/assets/ClaimGiftsButton-D83pBJ6J.js.gz +0 -0
  7. package/dist/dashboard/assets/{CliToolDetailPage-BIcWQun7.js → CliToolDetailPage-DZKmVuJN.js} +1 -1
  8. package/dist/dashboard/assets/CliToolDetailPage-DZKmVuJN.js.gz +0 -0
  9. package/dist/dashboard/assets/{CliToolsPage-Bf2VelDe.js → CliToolsPage-BIccZmeL.js} +1 -1
  10. package/dist/dashboard/assets/CliToolsPage-BIccZmeL.js.gz +0 -0
  11. package/dist/dashboard/assets/CombosPage-DEEKkYD-.js +1 -0
  12. package/dist/dashboard/assets/CombosPage-DEEKkYD-.js.gz +0 -0
  13. package/dist/dashboard/assets/ConsoleLogPage-D5rol2j2.js +1 -0
  14. package/dist/dashboard/assets/ConsoleLogPage-D5rol2j2.js.gz +0 -0
  15. package/dist/dashboard/assets/{CustomizationPage-ggeMSjte.js → CustomizationPage-BKj_r0rp.js} +1 -1
  16. package/dist/dashboard/assets/CustomizationPage-BKj_r0rp.js.gz +0 -0
  17. package/dist/dashboard/assets/InjectSystemPromptPanel-B5nZvmf0.js +656 -0
  18. package/dist/dashboard/assets/InjectSystemPromptPanel-B5nZvmf0.js.gz +0 -0
  19. package/dist/dashboard/assets/{LoginPage-U6AKaJcF.js → LoginPage-DkXb6dx-.js} +1 -1
  20. package/dist/dashboard/assets/LoginPage-DkXb6dx-.js.gz +0 -0
  21. package/dist/dashboard/assets/{ModelPicker-BMS2t8BA.js → ModelPicker-DnQPSIA8.js} +1 -1
  22. package/dist/dashboard/assets/ModelPicker-DnQPSIA8.js.gz +0 -0
  23. package/dist/dashboard/assets/OverviewPage-Ci2wQKUz.js +1 -0
  24. package/dist/dashboard/assets/OverviewPage-Ci2wQKUz.js.gz +0 -0
  25. package/dist/dashboard/assets/ProviderDetailPage-odlgYrOg.js +5 -0
  26. package/dist/dashboard/assets/ProviderDetailPage-odlgYrOg.js.gz +0 -0
  27. package/dist/dashboard/assets/ProviderIcon-EfeloBn4.js +1 -0
  28. package/dist/dashboard/assets/ProviderIcon-EfeloBn4.js.gz +0 -0
  29. package/dist/dashboard/assets/ProvidersPage-CqFBQEB8.js +1 -0
  30. package/dist/dashboard/assets/ProvidersPage-CqFBQEB8.js.gz +0 -0
  31. package/dist/dashboard/assets/{ProxyPage-lsrx7NYg.js → ProxyPage-5SnUSy3j.js} +1 -1
  32. package/dist/dashboard/assets/ProxyPage-5SnUSy3j.js.gz +0 -0
  33. package/dist/dashboard/assets/QuotaPage-CmnMDzhP.js +1 -0
  34. package/dist/dashboard/assets/QuotaPage-CmnMDzhP.js.gz +0 -0
  35. package/dist/dashboard/assets/SettingsPage-BJtRZ4qD.js +1 -0
  36. package/dist/dashboard/assets/SettingsPage-BJtRZ4qD.js.gz +0 -0
  37. package/dist/dashboard/assets/{SetupPage-f0DE1h0-.js → SetupPage-WTa0sktC.js} +1 -1
  38. package/dist/dashboard/assets/SetupPage-WTa0sktC.js.gz +0 -0
  39. package/dist/dashboard/assets/{StudioPage-Cq5tW7hW.js → StudioPage-BfAb5-o_.js} +3 -3
  40. package/dist/dashboard/assets/StudioPage-BfAb5-o_.js.gz +0 -0
  41. package/dist/dashboard/assets/UsagePage-BNzeZ2Vk.js +56 -0
  42. package/dist/dashboard/assets/UsagePage-BNzeZ2Vk.js.gz +0 -0
  43. package/dist/dashboard/assets/api-keys-l29JROPv.js +1 -0
  44. package/dist/dashboard/assets/api-keys-l29JROPv.js.gz +0 -0
  45. package/dist/dashboard/assets/app--PJWq8_C.css +2 -0
  46. package/dist/dashboard/assets/app--PJWq8_C.css.gz +0 -0
  47. package/dist/dashboard/assets/assert-C0K-c4eo.js +1 -0
  48. package/dist/dashboard/assets/assert-C0K-c4eo.js.gz +0 -0
  49. package/dist/dashboard/assets/{badge-D9CS6dZk.js → badge-DfbhQU4k.js} +1 -1
  50. package/dist/dashboard/assets/badge-DfbhQU4k.js.gz +0 -0
  51. package/dist/dashboard/assets/{banner-DympBNq4.js → banner-BllT4LcF.js} +1 -1
  52. package/dist/dashboard/assets/banner-BllT4LcF.js.gz +0 -0
  53. package/dist/dashboard/assets/brand/login_register.jpg +0 -0
  54. package/dist/dashboard/assets/brand/login_register_initial.jpg +0 -0
  55. package/dist/dashboard/assets/brand/og_bansos.jpg +0 -0
  56. package/dist/dashboard/assets/brand/og_image.jpg +0 -0
  57. package/dist/dashboard/assets/{card-ibRWU_uT.js → card-CtkX66Wd.js} +1 -1
  58. package/dist/dashboard/assets/card-CtkX66Wd.js.gz +0 -0
  59. package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js +1 -0
  60. package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js.gz +0 -0
  61. package/dist/dashboard/assets/cli-tools-CQXVMn4P.js +1 -0
  62. package/dist/dashboard/assets/cli-tools-CQXVMn4P.js.gz +0 -0
  63. package/dist/dashboard/assets/{clipboard-button-DJm-9pz7.js → clipboard-button-BQqBQd2n.js} +1 -1
  64. package/dist/dashboard/assets/clipboard-button-BQqBQd2n.js.gz +0 -0
  65. package/dist/dashboard/assets/{dialog-8fiE6tec.js → dialog-BEK7KP0H.js} +1 -1
  66. package/dist/dashboard/assets/dialog-BEK7KP0H.js.gz +0 -0
  67. package/dist/dashboard/assets/{drawer-CqGYeOrd.js → drawer-BrTEZ8zu.js} +1 -1
  68. package/dist/dashboard/assets/drawer-BrTEZ8zu.js.gz +0 -0
  69. package/dist/dashboard/assets/entry-CHWxbS56.js +1 -0
  70. package/dist/dashboard/assets/entry-CHWxbS56.js.gz +0 -0
  71. package/dist/dashboard/assets/{entry-BSAsYsmV.js → entry-EBHJ3DrE.js} +1 -1
  72. package/dist/dashboard/assets/entry-EBHJ3DrE.js.gz +0 -0
  73. package/dist/dashboard/assets/entry-LCS85hiq.js +4 -0
  74. package/dist/dashboard/assets/entry-LCS85hiq.js.gz +0 -0
  75. package/dist/dashboard/assets/{formatters-D-MTJxMr.js → formatters-BAACA727.js} +1 -1
  76. package/dist/dashboard/assets/formatters-BAACA727.js.gz +0 -0
  77. package/dist/dashboard/assets/{github-badge-CPK47xQx.js → github-badge-YSCE4UC2.js} +1 -1
  78. package/dist/dashboard/assets/github-badge-YSCE4UC2.js.gz +0 -0
  79. package/dist/dashboard/assets/{index-DBNPOfhV.js → index-FQlj0HUT.js} +2 -2
  80. package/dist/dashboard/assets/index-FQlj0HUT.js.gz +0 -0
  81. package/dist/dashboard/assets/{inline-BT0zntEr.js → inline-C4gU5iOL.js} +1 -1
  82. package/dist/dashboard/assets/inline-C4gU5iOL.js.gz +0 -0
  83. package/dist/dashboard/assets/{input-Da2ZViWg.js → input-BHHX_Tmm.js} +1 -1
  84. package/dist/dashboard/assets/input-BHHX_Tmm.js.gz +0 -0
  85. package/dist/dashboard/assets/{layout-BXNeLw6M.js → layout-CajrYUnD.js} +1 -1
  86. package/dist/dashboard/assets/layout-CajrYUnD.js.gz +0 -0
  87. package/dist/dashboard/assets/{list-row-BycOrrIV.js → list-row-Bx2I7XUe.js} +1 -1
  88. package/dist/dashboard/assets/list-row-Bx2I7XUe.js.gz +0 -0
  89. package/dist/dashboard/assets/live-DNNqRbj2.js +1 -0
  90. package/dist/dashboard/assets/live-DNNqRbj2.js.gz +0 -0
  91. package/dist/dashboard/assets/network-C5UBACrJ.js +1 -0
  92. package/dist/dashboard/assets/network-C5UBACrJ.js.gz +0 -0
  93. package/dist/dashboard/assets/numbers-CUWAZK4J.js +2 -0
  94. package/dist/dashboard/assets/numbers-CUWAZK4J.js.gz +0 -0
  95. package/dist/dashboard/assets/pagination-Xsi9Qx04.js +1 -0
  96. package/dist/dashboard/assets/pagination-Xsi9Qx04.js.gz +0 -0
  97. package/dist/dashboard/assets/quota-DvQbD_sr.js +1 -0
  98. package/dist/dashboard/assets/quota-DvQbD_sr.js.gz +0 -0
  99. package/dist/dashboard/assets/routing-in0f_IfK.js +1 -0
  100. package/dist/dashboard/assets/routing-in0f_IfK.js.gz +0 -0
  101. package/dist/dashboard/assets/{select-BIYIBkMU.js → select-BLULNqTp.js} +1 -1
  102. package/dist/dashboard/assets/select-BLULNqTp.js.gz +0 -0
  103. package/dist/dashboard/assets/settings-CcGczj6I.js +1 -0
  104. package/dist/dashboard/assets/settings-CcGczj6I.js.gz +0 -0
  105. package/dist/dashboard/assets/shield-BMQNxORh.js +1 -0
  106. package/dist/dashboard/assets/shield-BMQNxORh.js.gz +0 -0
  107. package/dist/dashboard/assets/{stack-DfgnFDWY.js → stack-D2lIR0tg.js} +1 -1
  108. package/dist/dashboard/assets/stack-D2lIR0tg.js.gz +0 -0
  109. package/dist/dashboard/assets/{state-CkfdYWel.js → state-DTARjfiW.js} +1 -1
  110. package/dist/dashboard/assets/state-DTARjfiW.js.gz +0 -0
  111. package/dist/dashboard/assets/{switch-SYm237HG.js → switch-c0oPSnqW.js} +1 -1
  112. package/dist/dashboard/assets/switch-c0oPSnqW.js.gz +0 -0
  113. package/dist/dashboard/assets/{useMutation-BQqCRNIi.js → useMutation-m8WGNPrz.js} +1 -1
  114. package/dist/dashboard/assets/useMutation-m8WGNPrz.js.gz +0 -0
  115. package/dist/dashboard/console-backgrounds.jpg +0 -0
  116. package/dist/dashboard/console-backgrounds_initial.jpg +0 -0
  117. package/dist/dashboard/index.html +2 -2
  118. package/dist/dashboard/index.html.gz +0 -0
  119. package/dist/dashboard/precompressed-assets.json +56 -55
  120. package/migrations/full-postgres/0036_system_prompt_presets_refs.sql +10 -0
  121. package/migrations/full-postgres/0037_share_concurrency_scope.sql +3 -0
  122. package/migrations/full-postgres/0038_add_accounts_quota_snapshot.sql +7 -0
  123. package/migrations/full-postgres/0039_add_telemetry_provider_model_indexes.sql +13 -0
  124. package/migrations/full-postgres/0040_add_models_dialect.sql +3 -0
  125. package/migrations/full-postgres/0041_add_daily_checkin_ledger_account_fk.sql +7 -0
  126. package/migrations/lite-sqlite3/0036_system_prompt_presets_refs.sql +14 -0
  127. package/migrations/lite-sqlite3/0037_share_concurrency_scope.sql +3 -0
  128. package/migrations/lite-sqlite3/0038_add_accounts_quota_snapshot.sql +4 -0
  129. package/migrations/lite-sqlite3/0039_add_telemetry_provider_model_indexes.sql +6 -0
  130. package/migrations/lite-sqlite3/0040_add_models_dialect.sql +3 -0
  131. package/migrations/lite-sqlite3/0041_add_daily_checkin_ledger_account_fk.sql +26 -0
  132. package/package.json +4 -6
  133. package/scripts/cli/update.ts +15 -41
  134. package/src/boot/app.ts +58 -2
  135. package/src/boot/dependencies.ts +786 -732
  136. package/src/boot/lifecycle.ts +11 -12
  137. package/src/config/cooldowns.ts +34 -55
  138. package/src/config/network.ts +1 -1
  139. package/src/config/package-paths.ts +1 -1
  140. package/src/config/providers.ts +13 -14
  141. package/src/config/resources.ts +0 -5
  142. package/src/config/runtime.ts +2 -5
  143. package/src/config/spec.ts +26 -6
  144. package/src/console/api-keys/ban-constants.ts +38 -0
  145. package/src/console/api-keys/contracts.ts +71 -62
  146. package/src/console/api-keys/routes.ts +48 -12
  147. package/src/console/auth/access.ts +4 -4
  148. package/src/console/auth/account-reset.ts +1 -1
  149. package/src/console/auth/audit-recorder.ts +1 -1
  150. package/src/console/auth/lockout.ts +7 -3
  151. package/src/console/auth/row-coercion.ts +57 -12
  152. package/src/console/auth/session-resolver.ts +1 -1
  153. package/src/console/auth/session-service.ts +8 -2
  154. package/src/console/auth/session.ts +37 -31
  155. package/src/console/auth/setup-service.ts +4 -3
  156. package/src/console/auth/user-store.ts +1 -1
  157. package/src/console/backup/9router-map.ts +0 -3
  158. package/src/console/backup/contracts.ts +9 -9
  159. package/src/console/backup/export-endpoint.ts +5 -6
  160. package/src/console/backup/nine-router.ts +1 -7
  161. package/src/console/backup/routes.ts +29 -33
  162. package/src/console/backup/service.ts +468 -468
  163. package/src/console/backup/store.ts +47 -29
  164. package/src/console/backup/validate.ts +11 -1
  165. package/src/console/cli-tools/contracts.ts +7 -7
  166. package/src/console/cli-tools/injectors/cline.ts +110 -110
  167. package/src/console/cli-tools/injectors/codex.ts +181 -181
  168. package/src/console/cli-tools/injectors/copilot.ts +108 -108
  169. package/src/console/cli-tools/injectors/driver.ts +247 -247
  170. package/src/console/cli-tools/injectors/jcode.ts +115 -115
  171. package/src/console/cli-tools/injectors/openclaw.ts +161 -161
  172. package/src/console/cli-tools/injectors/opencode.ts +153 -153
  173. package/src/console/cli-tools/routes.ts +1 -1
  174. package/src/console/cli-tools/service.ts +1 -1
  175. package/src/console/cli-tools/store.ts +2 -2
  176. package/src/console/console-router.ts +32 -0
  177. package/src/console/dashboard-assets.ts +9 -9
  178. package/src/console/domain-registration.ts +16 -2
  179. package/src/console/inferhub/client.ts +0 -7
  180. package/src/console/inferhub/key-store.ts +1 -1
  181. package/src/console/inferhub/normalize.ts +2 -2
  182. package/src/console/inferhub/routes.ts +1 -1
  183. package/src/console/inferhub/types.ts +1 -1
  184. package/src/console/observability/contracts.ts +1 -1
  185. package/src/console/observability/live.ts +31 -18
  186. package/src/console/observability/logs.ts +1 -1
  187. package/src/console/observability/sse.ts +62 -8
  188. package/src/console/observability/store.ts +20 -4
  189. package/src/console/providers/catalog/catalog-projections.ts +1 -1
  190. package/src/console/providers/catalog/contracts.ts +39 -0
  191. package/src/console/providers/catalog/model-operations.ts +1 -1
  192. package/src/console/providers/catalog/provider-operations.ts +95 -17
  193. package/src/console/providers/catalog/public-model-store.ts +0 -0
  194. package/src/console/providers/catalog/routes.ts +27 -3
  195. package/src/console/providers/catalog/store.ts +147 -8
  196. package/src/console/providers/detail/routes.ts +1 -1
  197. package/src/console/providers/oauth/callback-listener.ts +100 -18
  198. package/src/console/providers/oauth/routes.ts +92 -13
  199. package/src/console/quota/account-quota-global.ts +41 -3
  200. package/src/console/quota/account-quota-shared.ts +10 -3
  201. package/src/console/quota/account-quota-tenant.ts +259 -66
  202. package/src/console/quota/daily-growth-job.ts +308 -0
  203. package/src/console/quota/native-identity.ts +2 -2
  204. package/src/console/quota/quota-view.ts +1 -1
  205. package/src/console/remote-support/routes.ts +1 -1
  206. package/src/console/remote-support/service.ts +2 -2
  207. package/src/console/routing/model/contracts.ts +1 -1
  208. package/src/console/routing/pools/contracts.ts +2 -2
  209. package/src/console/routing/pools/import-parse.ts +3 -3
  210. package/src/console/routing/pools/relay-deploy.ts +3 -3
  211. package/src/console/settings/contracts.ts +29 -2
  212. package/src/console/settings/store.ts +20 -0
  213. package/src/console/share/share-router.ts +100 -32
  214. package/src/console/share/share-stats.ts +4 -4
  215. package/src/console/share/share-usage.ts +1 -1
  216. package/src/console/shared/errors.ts +2 -2
  217. package/src/console/shared/object.ts +18 -0
  218. package/src/console/shared/read-through-cache.ts +4 -4
  219. package/src/console/shared/transaction.ts +14 -0
  220. package/src/console/system-prompt/contracts.ts +89 -12
  221. package/src/console/system-prompt/routes.ts +98 -45
  222. package/src/console/updates/apply-update.ts +244 -0
  223. package/src/console/updates/routes.ts +252 -97
  224. package/src/main.ts +11 -5
  225. package/src/network/http2-bidi.ts +1 -1
  226. package/src/network/ip-utils.ts +298 -0
  227. package/src/network/outbound-fetch.ts +1 -1
  228. package/src/network/pool/agent.ts +7 -6
  229. package/src/network/pool/byte-accounting.ts +1 -1
  230. package/src/network/pool/resolver.ts +16 -12
  231. package/src/network/pool/selector.ts +150 -136
  232. package/src/network/pool-health-machine.ts +1 -1
  233. package/src/network/rate-limit-verdict.ts +1 -1
  234. package/src/network/retry.ts +1 -1
  235. package/src/network/ssrf.ts +20 -71
  236. package/src/observability/event-log.ts +2 -2
  237. package/src/observability/event-query.ts +59 -291
  238. package/src/observability/log-sanitize.ts +1 -1
  239. package/src/observability/metrics.ts +4 -4
  240. package/src/observability/payload-capture.ts +6 -5
  241. package/src/observability/payload-store.ts +1 -1
  242. package/src/observability/runtime-metrics.ts +1 -1
  243. package/src/observability/telemetry-buffer.ts +12 -3
  244. package/src/observability/telemetry-reconciliation.ts +3 -3
  245. package/src/observability/token-speed.ts +1 -1
  246. package/src/persistence/connection-url.ts +1 -1
  247. package/src/persistence/db-handle.ts +1 -1
  248. package/src/persistence/db-pg.ts +2 -2
  249. package/src/persistence/db-sqlite.ts +3 -3
  250. package/src/persistence/dialect.ts +5 -1
  251. package/src/persistence/readiness.ts +1 -1
  252. package/src/persistence/redis.ts +1 -1
  253. package/src/persistence/schema.ts +113 -40
  254. package/src/persistence/shared-cache.ts +2 -2
  255. package/src/persistence/sort-order.ts +1 -1
  256. package/src/persistence/stores/api-key-store.ts +10 -1
  257. package/src/persistence/stores/share-store.ts +20 -8
  258. package/src/persistence/system-prompt-store.ts +63 -18
  259. package/src/persistence/tenant-preferences.ts +1 -1
  260. package/src/persistence/ttl-cache.ts +3 -3
  261. package/src/persistence/usage-flush.ts +7 -2
  262. package/src/protocol/canonical-model.ts +1 -1
  263. package/src/protocol/codecs.ts +6 -10
  264. package/src/protocol/dsml.ts +3 -49
  265. package/src/protocol/image-clamp.ts +2 -2
  266. package/src/protocol/reasoning-text.ts +1 -1
  267. package/src/protocol/reasoning.ts +7 -52
  268. package/src/protocol/registry.ts +50 -15
  269. package/src/protocol/request/chat.ts +46 -19
  270. package/src/protocol/request/codex.ts +1 -1
  271. package/src/protocol/request/messages.ts +46 -14
  272. package/src/protocol/request/responses.ts +19 -10
  273. package/src/protocol/response/chat.ts +25 -10
  274. package/src/protocol/response/codex.ts +1 -1
  275. package/src/protocol/response/messages.ts +1 -1
  276. package/src/protocol/response/omp-tool-call-markup.ts +1 -1
  277. package/src/protocol/response/responses.ts +1 -1
  278. package/src/protocol/sse-decoder.ts +50 -1
  279. package/src/protocol/stop-reason.ts +2 -2
  280. package/src/protocol/think-split.ts +347 -0
  281. package/src/protocol/translation/attachment-integrity.ts +3 -3
  282. package/src/protocol/translation/cache-controls.ts +8 -20
  283. package/src/protocol/translation/capabilities.ts +6 -6
  284. package/src/protocol/translation/dialect/deepseek.ts +10 -0
  285. package/src/protocol/translation/dialect/inband.ts +39 -0
  286. package/src/protocol/translation/dialect/model-thinking.ts +89 -0
  287. package/src/protocol/translation/dialect/qwen.ts +114 -0
  288. package/src/protocol/translation/dialect/resolver.ts +83 -0
  289. package/src/protocol/translation/dialect/rules.ts +93 -0
  290. package/src/protocol/translation/dialect/thinking-ladder.ts +245 -0
  291. package/src/protocol/translation/dialect/types.ts +58 -0
  292. package/src/protocol/translation/quirks.ts +18 -4
  293. package/src/protocol/translation/thinking.ts +12 -252
  294. package/src/protocol/translation/tool-id.ts +3 -3
  295. package/src/protocol/translation/tool-repair.ts +1 -1
  296. package/src/protocol/upstream/post-json.ts +6 -1
  297. package/src/providers/adapters/compatible-adapter.ts +42 -3
  298. package/src/providers/authentication/jwt-validator.ts +0 -5
  299. package/src/providers/authentication/oauth-client.ts +254 -253
  300. package/src/providers/authentication/oauth-flow-store.ts +42 -7
  301. package/src/providers/bundled-discovery-providers.ts +6 -30
  302. package/src/providers/configured-openai-providers.ts +82 -97
  303. package/src/providers/default-registry.ts +23 -35
  304. package/src/providers/discovery/catalog/catalog-format.ts +13 -2
  305. package/src/providers/discovery/discovery-types.ts +0 -1
  306. package/src/providers/discovery/openai-model-discovery.ts +2 -2
  307. package/src/providers/discovery/probe-phases.ts +48 -13
  308. package/src/providers/discovery/probing-service.ts +6 -8
  309. package/src/providers/integrations/agentrouter/agentrouter.ts +12 -2
  310. package/src/providers/integrations/antigravity/antigravity-oauth.ts +0 -1
  311. package/src/providers/integrations/antigravity/antigravity-protocol.ts +0 -14
  312. package/src/providers/integrations/antigravity/antigravity.ts +2 -2
  313. package/src/providers/integrations/buddy/buddy-catalog-shared.ts +1 -1
  314. package/src/providers/integrations/buddy/buddy-chat-shared.ts +20 -4
  315. package/src/providers/integrations/buddy/buddy-cli-headers.ts +19 -52
  316. package/src/providers/integrations/buddy/buddy-identity.ts +86 -0
  317. package/src/providers/integrations/buddy/buddy-oauth-shared.ts +1 -1
  318. package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +1 -2
  319. package/src/providers/integrations/buddy/codebuddy/provider.ts +4 -15
  320. package/src/providers/integrations/buddy/codebuddy/shared.ts +30 -9
  321. package/src/providers/integrations/buddy/workbuddy/provider.ts +5 -9
  322. package/src/providers/integrations/buddy/workbuddy/shared.ts +21 -3
  323. package/src/providers/integrations/claude/claude-cch.ts +148 -148
  324. package/src/providers/integrations/claude/fallback-credit.ts +3 -7
  325. package/src/providers/integrations/cline/cline.ts +1 -1
  326. package/src/providers/integrations/codex/codex-device-code.ts +101 -101
  327. package/src/providers/integrations/codex/codex-oauth.ts +0 -1
  328. package/src/providers/integrations/commandcode/commandcode.ts +75 -115
  329. package/src/providers/integrations/commandcode/quota.ts +131 -51
  330. package/src/providers/integrations/cursor/cursor-http2.ts +0 -3
  331. package/src/providers/integrations/cursor/cursor-quota.ts +2 -6
  332. package/src/providers/integrations/cursor/cursor-request.ts +0 -87
  333. package/src/providers/integrations/cursor/cursor-shared.ts +0 -4
  334. package/src/providers/integrations/cursor/cursor.ts +38 -5
  335. package/src/providers/integrations/cursor/protocol/framing.ts +0 -56
  336. package/src/providers/integrations/cursor/protocol/messages.ts +0 -96
  337. package/src/providers/integrations/factory/factory.ts +9 -9
  338. package/src/providers/integrations/github/github-discovery.ts +55 -10
  339. package/src/providers/integrations/github/github-oauth.ts +6 -5
  340. package/src/providers/integrations/github/github.ts +41 -14
  341. package/src/providers/integrations/grok/grok-oauth.ts +261 -261
  342. package/src/providers/integrations/grok/grok-quota-frame.ts +1 -1
  343. package/src/providers/integrations/grok/grok-quota.ts +16 -7
  344. package/src/providers/integrations/grok/grok-ratelimit-store.ts +0 -5
  345. package/src/providers/integrations/grok/grok-ratelimit.ts +3 -0
  346. package/src/providers/integrations/grok/grok.ts +86 -36
  347. package/src/providers/integrations/kilo/kilo-oauth.ts +1 -1
  348. package/src/providers/integrations/kiro/kiro-cache.ts +31 -0
  349. package/src/providers/integrations/kiro/kiro-catalog.ts +31 -5
  350. package/src/providers/integrations/kiro/kiro-discovery.ts +47 -43
  351. package/src/providers/integrations/kiro/kiro-machine-id.ts +6 -3
  352. package/src/providers/integrations/kiro/kiro-oauth.ts +523 -255
  353. package/src/providers/integrations/kiro/kiro-quota.ts +35 -47
  354. package/src/providers/integrations/kiro/kiro-request.ts +8 -11
  355. package/src/providers/integrations/kiro/kiro-stream.ts +13 -0
  356. package/src/providers/integrations/kiro/kiro.ts +81 -68
  357. package/src/providers/integrations/muse/muse-oauth.ts +0 -1
  358. package/src/providers/integrations/muse/muse-quota.ts +0 -4
  359. package/src/providers/integrations/opencode/fingerprint.ts +7 -5
  360. package/src/providers/integrations/opencode/provider.ts +17 -24
  361. package/src/providers/integrations/qoder/qoder-catalog.ts +85 -8
  362. package/src/providers/integrations/qoder/qoder-oauth.ts +165 -25
  363. package/src/providers/integrations/qoder/qoder-quota.ts +48 -6
  364. package/src/providers/integrations/qoder/qoder-realm.ts +10 -31
  365. package/src/providers/integrations/qoder/qoder-sse.ts +159 -0
  366. package/src/providers/integrations/qoder/qoder-umid.ts +21 -25
  367. package/src/providers/integrations/qoder/qoder-virtual.ts +12 -0
  368. package/src/providers/integrations/qoder/qoder.ts +354 -62
  369. package/src/providers/integrations/shared/connect.ts +0 -54
  370. package/src/providers/integrations/shared/hash.ts +15 -0
  371. package/src/providers/integrations/shared/session-cache.ts +136 -0
  372. package/src/providers/integrations/trae/trae-cache.ts +7 -87
  373. package/src/providers/integrations/trae/trae-catalog.ts +1 -6
  374. package/src/providers/integrations/trae/trae-protocol.ts +17 -8
  375. package/src/providers/integrations/trae/trae-realm.ts +0 -7
  376. package/src/providers/integrations/trae/trae.ts +53 -10
  377. package/src/providers/integrations/xai/xai-oauth.ts +5 -5
  378. package/src/providers/integrations/zcode-start-plan/gifts.ts +265 -0
  379. package/src/providers/integrations/zcode-start-plan/oauth.ts +154 -0
  380. package/src/providers/integrations/zcode-start-plan/provider.ts +131 -0
  381. package/src/providers/integrations/zcode-start-plan/quota.ts +152 -0
  382. package/src/providers/integrations/zcode-start-plan/zcode_prompt.json +10 -0
  383. package/src/providers/operations/account-error-classification.ts +131 -116
  384. package/src/providers/operations/account-health-service.ts +31 -39
  385. package/src/providers/operations/account-reset-service.ts +58 -1
  386. package/src/providers/operations/cli-platform.ts +31 -5
  387. package/src/providers/operations/client-version-resolver.ts +4 -6
  388. package/src/providers/operations/client-versions.ts +10 -7
  389. package/src/providers/operations/provider-catalog-seeder.ts +2 -0
  390. package/src/providers/operations/provider-catalog-service.ts +18 -2
  391. package/src/providers/operations/provider-credential-service.ts +19 -2
  392. package/src/providers/provider-contracts.ts +18 -7
  393. package/src/providers/provider-metadata.ts +17 -2
  394. package/src/providers/provider-model-definition.ts +22 -1
  395. package/src/providers/provider-probe.ts +4 -2
  396. package/src/providers/provider-usage.ts +81 -16
  397. package/src/providers/quota/cache.ts +29 -0
  398. package/src/providers/quota/quota-contracts.ts +4 -0
  399. package/src/providers/quota/refresh.ts +27 -4
  400. package/src/providers/quota/snapshot.ts +94 -0
  401. package/src/providers/search/search-provider.ts +1 -3
  402. package/src/providers/search/search-providers.ts +2 -1
  403. package/src/security/abuse.ts +4 -4
  404. package/src/security/admission/service.ts +2 -2
  405. package/src/security/admission/ttl.ts +61 -61
  406. package/src/security/api-key-auth.ts +16 -4
  407. package/src/security/client-router-fingerprint.ts +4 -4
  408. package/src/security/credential-codec.ts +3 -3
  409. package/src/security/csrf.ts +2 -2
  410. package/src/security/ip-boundary.ts +16 -189
  411. package/src/security/model-access-rule.ts +1 -1
  412. package/src/security/outbound-headers.ts +18 -0
  413. package/src/shared/invoke-guard.ts +47 -0
  414. package/src/transport/contracts.ts +13 -4
  415. package/src/transport/dispatch/attempt-finalize.ts +1 -1
  416. package/src/transport/dispatch/capture-policy.ts +34 -37
  417. package/src/transport/dispatch/empty-stream.ts +23 -20
  418. package/src/transport/dispatch/generation.ts +25 -45
  419. package/src/transport/dispatch/native-shared.ts +127 -0
  420. package/src/transport/dispatch/proxy-request.ts +3 -1
  421. package/src/transport/dispatch/responses-compact.ts +25 -46
  422. package/src/transport/dispatch/streaming/encoder.ts +18 -72
  423. package/src/transport/dispatch/streaming/finalize.ts +2 -2
  424. package/src/transport/dispatch/streaming/stream.ts +7 -3
  425. package/src/transport/dispatch/streaming/thinking-loop.ts +1 -1
  426. package/src/transport/dispatch/systemone.ts +20 -48
  427. package/src/transport/dispatch/token-count.ts +41 -38
  428. package/src/transport/dispatch/websearch.ts +19 -45
  429. package/src/transport/drain-endpoint.ts +1 -1
  430. package/src/transport/failure-policy.ts +6 -0
  431. package/src/transport/guards/auth-guard.ts +0 -6
  432. package/src/transport/guards/body-policy.ts +3 -3
  433. package/src/transport/guards/headroom-guard.ts +1 -1
  434. package/src/transport/guards/pipeline.ts +1 -1
  435. package/src/transport/guards/request-context.ts +12 -17
  436. package/src/transport/request/preparer.ts +286 -7
  437. package/src/transport/request/rtk/compress-request.ts +3 -3
  438. package/src/transport/request/rtk/rtk-constants.ts +2 -2
  439. package/src/transport/request/rtk/rtk-filters.ts +8 -8
  440. package/src/transport/request/state.ts +1 -13
  441. package/src/transport/request/system-prompt-injection.ts +74 -11
  442. package/src/transport/request/tenant-preferences.ts +22 -0
  443. package/src/transport/routing/candidate-index.ts +2 -2
  444. package/src/transport/routing/round-robin.ts +1 -1
  445. package/src/transport/routing/route-catalog.ts +17 -18
  446. package/src/transport/routing/route-model.ts +126 -33
  447. package/src/transport/routing/router.ts +152 -37
  448. package/src/transport/shutdown-notice.ts +2 -2
  449. package/src/transport/surface/adapters.ts +3 -3
  450. package/src/transport/surface/chat/encode.ts +7 -7
  451. package/src/transport/surface/chat/parse.ts +7 -7
  452. package/src/transport/surface/completion.ts +2 -2
  453. package/src/transport/surface/content-parts.ts +1 -1
  454. package/src/transport/surface/dialects.ts +2 -2
  455. package/src/transport/surface/messages/parse.ts +3 -3
  456. package/src/transport/surface/responses/adapter.ts +1 -1
  457. package/src/transport/surface/responses/errors.ts +0 -9
  458. package/src/transport/vision-handoff-cache.ts +58 -0
  459. package/src/transport/vision-handoff.ts +376 -0
  460. package/src/workers/account-identity-sweep.ts +2 -2
  461. package/src/workers/buddy-growth-tasks.ts +392 -346
  462. package/src/workers/daily-checkin.ts +102 -49
  463. package/src/workers/maintenance-lease.ts +2 -35
  464. package/src/workers/oauth-refresh-sweep.ts +8 -1
  465. package/src/workers/quota-refresh-sweep.ts +120 -82
  466. package/src/workers/scheduler.ts +67 -4
  467. package/src/workers/sweep-runner.ts +24 -5
  468. package/src/workers/zcode-gift-claim.ts +108 -0
  469. package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js +0 -1
  470. package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js.gz +0 -0
  471. package/dist/dashboard/assets/BannedPage-ChG5svFb.js.gz +0 -0
  472. package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js.gz +0 -0
  473. package/dist/dashboard/assets/CliToolsPage-Bf2VelDe.js.gz +0 -0
  474. package/dist/dashboard/assets/CombosPage-DCgm5g6g.js +0 -1
  475. package/dist/dashboard/assets/CombosPage-DCgm5g6g.js.gz +0 -0
  476. package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js +0 -1
  477. package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js.gz +0 -0
  478. package/dist/dashboard/assets/CustomizationPage-ggeMSjte.js.gz +0 -0
  479. package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js +0 -1
  480. package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js.gz +0 -0
  481. package/dist/dashboard/assets/LoginPage-U6AKaJcF.js.gz +0 -0
  482. package/dist/dashboard/assets/ModelPicker-BMS2t8BA.js.gz +0 -0
  483. package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js +0 -1
  484. package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js.gz +0 -0
  485. package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js +0 -5
  486. package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js.gz +0 -0
  487. package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js +0 -1
  488. package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js.gz +0 -0
  489. package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js +0 -1
  490. package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js.gz +0 -0
  491. package/dist/dashboard/assets/ProxyPage-lsrx7NYg.js.gz +0 -0
  492. package/dist/dashboard/assets/QuotaPage-L0skzML8.js +0 -1
  493. package/dist/dashboard/assets/QuotaPage-L0skzML8.js.gz +0 -0
  494. package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js +0 -1
  495. package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js.gz +0 -0
  496. package/dist/dashboard/assets/SetupPage-f0DE1h0-.js.gz +0 -0
  497. package/dist/dashboard/assets/SortableList-ClzpwyET.js +0 -1
  498. package/dist/dashboard/assets/SortableList-ClzpwyET.js.gz +0 -0
  499. package/dist/dashboard/assets/StudioPage-Cq5tW7hW.js.gz +0 -0
  500. package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js +0 -56
  501. package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js.gz +0 -0
  502. package/dist/dashboard/assets/api-keys-C38iXoO4.js +0 -1
  503. package/dist/dashboard/assets/api-keys-C38iXoO4.js.gz +0 -0
  504. package/dist/dashboard/assets/app-a159k0ub.css +0 -2
  505. package/dist/dashboard/assets/app-a159k0ub.css.gz +0 -0
  506. package/dist/dashboard/assets/assert-DbRA8EG2.js +0 -15
  507. package/dist/dashboard/assets/assert-DbRA8EG2.js.gz +0 -0
  508. package/dist/dashboard/assets/badge-D9CS6dZk.js.gz +0 -0
  509. package/dist/dashboard/assets/banner-DympBNq4.js.gz +0 -0
  510. package/dist/dashboard/assets/card-ibRWU_uT.js.gz +0 -0
  511. package/dist/dashboard/assets/cli-tools-63qBGaRw.js +0 -1
  512. package/dist/dashboard/assets/cli-tools-63qBGaRw.js.gz +0 -0
  513. package/dist/dashboard/assets/clipboard-button-DJm-9pz7.js.gz +0 -0
  514. package/dist/dashboard/assets/dialog-8fiE6tec.js.gz +0 -0
  515. package/dist/dashboard/assets/drawer-CqGYeOrd.js.gz +0 -0
  516. package/dist/dashboard/assets/entry-BSAsYsmV.js.gz +0 -0
  517. package/dist/dashboard/assets/entry-CiIQULZD.js +0 -4
  518. package/dist/dashboard/assets/entry-CiIQULZD.js.gz +0 -0
  519. package/dist/dashboard/assets/entry-Daz0lJ-W.js +0 -1
  520. package/dist/dashboard/assets/entry-Daz0lJ-W.js.gz +0 -0
  521. package/dist/dashboard/assets/formatters-D-MTJxMr.js.gz +0 -0
  522. package/dist/dashboard/assets/github-badge-CPK47xQx.js.gz +0 -0
  523. package/dist/dashboard/assets/index-DBNPOfhV.js.gz +0 -0
  524. package/dist/dashboard/assets/inline-BT0zntEr.js.gz +0 -0
  525. package/dist/dashboard/assets/input-Da2ZViWg.js.gz +0 -0
  526. package/dist/dashboard/assets/layout-BXNeLw6M.js.gz +0 -0
  527. package/dist/dashboard/assets/list-row-BycOrrIV.js.gz +0 -0
  528. package/dist/dashboard/assets/live-DCQNZpF7.js +0 -1
  529. package/dist/dashboard/assets/live-DCQNZpF7.js.gz +0 -0
  530. package/dist/dashboard/assets/network-9Yj2ZyLo.js +0 -1
  531. package/dist/dashboard/assets/network-9Yj2ZyLo.js.gz +0 -0
  532. package/dist/dashboard/assets/numbers-CEagj6ZZ.js +0 -2
  533. package/dist/dashboard/assets/numbers-CEagj6ZZ.js.gz +0 -0
  534. package/dist/dashboard/assets/quota-Caw7wqci.js +0 -1
  535. package/dist/dashboard/assets/quota-Caw7wqci.js.gz +0 -0
  536. package/dist/dashboard/assets/routing-CO9zCUus.js +0 -1
  537. package/dist/dashboard/assets/routing-CO9zCUus.js.gz +0 -0
  538. package/dist/dashboard/assets/select-BIYIBkMU.js.gz +0 -0
  539. package/dist/dashboard/assets/settings-jS3-PNSA.js +0 -1
  540. package/dist/dashboard/assets/settings-jS3-PNSA.js.gz +0 -0
  541. package/dist/dashboard/assets/stack-DfgnFDWY.js.gz +0 -0
  542. package/dist/dashboard/assets/state-CkfdYWel.js.gz +0 -0
  543. package/dist/dashboard/assets/stream-retry-5QnVuSSo.js +0 -1
  544. package/dist/dashboard/assets/stream-retry-5QnVuSSo.js.gz +0 -0
  545. package/dist/dashboard/assets/switch-SYm237HG.js.gz +0 -0
  546. package/dist/dashboard/assets/useMutation-BQqCRNIi.js.gz +0 -0
  547. package/src/network/response-headers.ts +0 -39
  548. package/src/protocol/response/dsml.ts +0 -38
  549. package/src/providers/integrations/xiaomi-mimo/think-stream.ts +0 -229
  550. /package/dist/dashboard/assets/{app-BayTTy01.js → app-Bgd3zANQ.js} +0 -0
  551. /package/dist/dashboard/assets/{app-BayTTy01.js.gz → app-Bgd3zANQ.js.gz} +0 -0
  552. /package/dist/dashboard/assets/brand/{og_bansos.webp → og_bansos_initial.webp} +0 -0
  553. /package/dist/dashboard/assets/brand/{og_image.webp → og_image_initial.webp} +0 -0
@@ -0,0 +1,265 @@
1
+ /**
2
+ * ZCode gift-plan claims (the promo packs).
3
+ *
4
+ * This is **not** a check-in: ZCode has no streak, no daily credit and no
5
+ * status/claim pair like the Buddy family. Its gift plans sit unclaimed on the
6
+ * account until a claim is posted, and where they are offered is the tricky
7
+ * part:
8
+ *
9
+ * - `/api/v1/zcode-plan/billing/preview` lists the plans the account may claim;
10
+ * - the app's marketing feed (`/api/v1/marketing/touch`) lists the **banner**
11
+ * promos — a weekend build that appears in neither `preview` nor `current`
12
+ * while the app shows its banner.
13
+ *
14
+ * Both reads and the claim are app-only endpoints: a Bearer token alone is
15
+ * answered `3001 parameter error` before auth. They need `X-Device-Mid` (the
16
+ * gateway validates it as a UUID and never binds it to the account) and
17
+ * `X-ZCode-App-Version`.
18
+ *
19
+ * The reply is judged by the body, never the HTTP status: `0` claimed, `1003`
20
+ * already claimed, `3007` the app's Aliyun attestation is missing.
21
+ */
22
+ import { createHash } from "node:crypto";
23
+ import { sleep } from "../../../shared/sleep";
24
+ import { asRecord, asTrimmedString } from "../../../shared/coerce";
25
+ import type { ValidatedFetch } from "../../../network/outbound-fetch";
26
+
27
+ const ZCODE = "https://zcode.z.ai";
28
+ const BILLING = `${ZCODE}/api/v1/zcode-plan/billing`;
29
+ const TOUCH = `${ZCODE}/api/v1/marketing/touch`;
30
+ const APP_VERSION = "3.16.3";
31
+ const PLATFORM = "linux-x64";
32
+ const TIMEOUT_MS = 15_000;
33
+ const CLAIMED_ALREADY = 1003;
34
+ const CAPTCHA = 3007;
35
+ /** The upstream answers these under load; the same call succeeds later. */
36
+ const RETRY_STATUSES = new Set([429, 502, 503, 504]);
37
+ const RETRY_TRIES = 3;
38
+
39
+ export type ZcodeGiftState = "claimed" | "already_claimed" | "nothing" | "captcha" | "partial" | "error";
40
+
41
+ export interface ZcodeGiftResult {
42
+ readonly state: ZcodeGiftState;
43
+ readonly claimed: readonly string[];
44
+ readonly detail: string | null;
45
+ }
46
+
47
+ /** Stable per account — a per-request device id is itself a jitter signal. */
48
+ function deviceMid(accountId: string): string {
49
+ const hash = createHash("sha256").update(`zcode-device\0${accountId}`).digest("hex");
50
+ const variant = ((parseInt(hash[16] as string, 16) & 3) | 8).toString(16);
51
+ return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-4${hash.slice(13, 16)}-${variant}${hash.slice(17, 20)}-${hash.slice(20, 32)}`;
52
+ }
53
+
54
+ function headers(credential: string, accountId: string): Record<string, string> {
55
+ return {
56
+ Authorization: `Bearer ${credential}`,
57
+ Accept: "application/json",
58
+ "Content-Type": "application/json",
59
+ "X-Device-Mid": deviceMid(accountId),
60
+ "X-Client-Language": "en-US",
61
+ "X-ZCode-App-Version": APP_VERSION,
62
+ "X-Platform": PLATFORM,
63
+ };
64
+ }
65
+
66
+ /** The claim actions a marketing delivery offers, and the plan's own name. */
67
+ function bannerClaims(delivery: unknown): { plans: Array<{ planId: string; name: string | null }>; malformed: boolean } {
68
+ const ids: string[] = [];
69
+ const names: string[] = [];
70
+ let malformed = false;
71
+ const walk = (node: unknown, depth: number): void => {
72
+ if (depth > 12) return;
73
+ if (Array.isArray(node)) {
74
+ for (const item of node) walk(item, depth + 1);
75
+ return;
76
+ }
77
+ const record = asRecord(node);
78
+ if (!record) return;
79
+ if (asTrimmedString(record["type"]) === "claim_zcode_plan") {
80
+ const planId = asTrimmedString(asRecord(record["args"])?.["plan_id"]);
81
+ if (planId !== undefined) ids.push(planId);
82
+ else malformed = true;
83
+ }
84
+ const plan = asRecord(record["zcode_plan"]);
85
+ const name = asTrimmedString(plan?.["name"]);
86
+ if (name !== undefined) names.push(name);
87
+ for (const value of Object.values(record)) walk(value, depth + 1);
88
+ };
89
+ walk(delivery, 0);
90
+ const name = names[0] ?? null;
91
+ return { plans: ids.map((planId) => ({ planId, name })), malformed };
92
+ }
93
+
94
+ /** Only a successful, readable envelope can represent an empty list. */
95
+ async function read(
96
+ fetcher: ValidatedFetch,
97
+ url: string,
98
+ credential: string,
99
+ accountId: string,
100
+ ): Promise<{ ok: boolean; data: Record<string, unknown> | null }> {
101
+ let response = await fetcher(url, {
102
+ method: "GET",
103
+ headers: headers(credential, accountId),
104
+ signal: AbortSignal.timeout(TIMEOUT_MS),
105
+ });
106
+ for (let attempt = 1; RETRY_STATUSES.has(response.status) && attempt < RETRY_TRIES; attempt += 1) {
107
+ await sleep(1_500 * attempt);
108
+ response = await fetcher(url, {
109
+ method: "GET",
110
+ headers: headers(credential, accountId),
111
+ signal: AbortSignal.timeout(TIMEOUT_MS),
112
+ });
113
+ }
114
+ const payload = asRecord(await response.json().catch(() => null));
115
+ if (!response.ok || !payload || payload["success"] === false) return { ok: false, data: null };
116
+ const code = payload["code"];
117
+ if (![0, 200, "0", "200"].includes(code as string | number)) return { ok: false, data: null };
118
+ // Successful empty lists omit data (or return null) on the app endpoints.
119
+ if (payload["data"] == null) return { ok: true, data: null };
120
+ const data = asRecord(payload["data"]);
121
+ return { ok: data !== undefined && data !== null, data: data ?? null };
122
+ }
123
+
124
+ /**
125
+ * Every plan the account may claim, once each. A `null` for a list means it
126
+ * did not read — never "nothing to claim".
127
+ */
128
+ async function toClaim(
129
+ fetcher: ValidatedFetch,
130
+ credential: string,
131
+ accountId: string,
132
+ ): Promise<{ plans: Array<{ planId: string; name: string | null }>; unread: string[] }> {
133
+ const plans: Array<{ planId: string; name: string | null }> = [];
134
+ const unread: string[] = [];
135
+ const seen = new Set<string>();
136
+ const add = (planId: string, name: string | null): void => {
137
+ if (seen.has(planId)) return;
138
+ seen.add(planId);
139
+ plans.push({ planId, name });
140
+ };
141
+
142
+ try {
143
+ const feed = await read(fetcher, `${TOUCH}?seq=0`, credential, accountId);
144
+ if (!feed.ok) unread.push("marketing feed did not read");
145
+ else {
146
+ const deliveries = feed.data?.["deliveries"];
147
+ if (deliveries != null && (!Array.isArray(deliveries) || deliveries.some((delivery) => !asRecord(delivery)))) {
148
+ unread.push("marketing feed has no delivery list");
149
+ }
150
+ for (const delivery of Array.isArray(deliveries) ? deliveries : []) {
151
+ const banner = bannerClaims(delivery);
152
+ if (banner.malformed) unread.push("marketing feed has an invalid claim action");
153
+ for (const claim of banner.plans) add(claim.planId, claim.name ?? claim.planId);
154
+ }
155
+ }
156
+ } catch {
157
+ unread.push("marketing feed did not read");
158
+ }
159
+
160
+ try {
161
+ const preview = await read(
162
+ fetcher,
163
+ `${BILLING}/preview?app_version=${APP_VERSION}&platform=${PLATFORM}`,
164
+ credential,
165
+ accountId,
166
+ );
167
+ if (!preview.ok) unread.push("billing preview did not read");
168
+ else {
169
+ const listed = preview.data?.["plans"];
170
+ if (listed != null && !Array.isArray(listed)) unread.push("billing preview has no plan list");
171
+ for (const entry of Array.isArray(listed) ? listed : []) {
172
+ const plan = asRecord(entry);
173
+ const planId = asTrimmedString(plan?.["plan_id"]);
174
+ if (planId === undefined) {
175
+ unread.push("billing preview has an invalid plan");
176
+ continue;
177
+ }
178
+ add(planId, asTrimmedString(plan?.["name"]) ?? planId);
179
+ }
180
+ }
181
+ } catch {
182
+ unread.push("billing preview did not read");
183
+ }
184
+
185
+ return { plans, unread };
186
+ }
187
+
188
+ /** Posts one claim and says what the body's own code means. */
189
+ async function claimOne(
190
+ fetcher: ValidatedFetch,
191
+ credential: string,
192
+ accountId: string,
193
+ planId: string,
194
+ ): Promise<"claimed" | "already_claimed" | "captcha" | "failed"> {
195
+ let response = await fetcher(`${BILLING}/claim`, {
196
+ method: "POST",
197
+ headers: headers(credential, accountId),
198
+ body: JSON.stringify({ plan_id: planId }),
199
+ signal: AbortSignal.timeout(TIMEOUT_MS),
200
+ });
201
+ for (let attempt = 1; RETRY_STATUSES.has(response.status) && attempt < RETRY_TRIES; attempt += 1) {
202
+ await sleep(1_500 * attempt);
203
+ response = await fetcher(`${BILLING}/claim`, {
204
+ method: "POST",
205
+ headers: headers(credential, accountId),
206
+ body: JSON.stringify({ plan_id: planId }),
207
+ signal: AbortSignal.timeout(TIMEOUT_MS),
208
+ });
209
+ }
210
+ const payload = asRecord(await response.json().catch(() => null));
211
+ const rawCode = payload?.["code"];
212
+ const code = typeof rawCode === "string" && rawCode.trim() !== "" ? Number(rawCode) : rawCode;
213
+ if (payload?.["success"] === false) return "failed";
214
+ if (code === CAPTCHA) return "captcha";
215
+ if (code === CLAIMED_ALREADY) return "already_claimed";
216
+ if (code === 0 && response.ok) return "claimed";
217
+ return "failed";
218
+ }
219
+
220
+ /** Claims every gift plan ZCode offers the account. */
221
+ export async function claimZcodeGifts(args: {
222
+ readonly accountId: string;
223
+ readonly credential: string;
224
+ readonly fetcher: ValidatedFetch;
225
+ }): Promise<ZcodeGiftResult> {
226
+ const { accountId, credential, fetcher } = args;
227
+ if (!credential) return { state: "error", claimed: [], detail: "account has no credential" };
228
+ try {
229
+ const { plans, unread } = await toClaim(fetcher, credential, accountId);
230
+ if (plans.length === 0) {
231
+ return unread.length > 0
232
+ ? { state: "error", claimed: [], detail: unread.join("; ") }
233
+ : { state: "nothing", claimed: [], detail: null };
234
+ }
235
+ const claimed: string[] = [];
236
+ const already: string[] = [];
237
+ const captcha: string[] = [];
238
+ const failed: string[] = [];
239
+ for (const plan of plans) {
240
+ const outcome = await claimOne(fetcher, credential, accountId, plan.planId).catch(() => "failed" as const);
241
+ const name = plan.name ?? plan.planId;
242
+ if (outcome === "claimed") claimed.push(name);
243
+ else if (outcome === "already_claimed") already.push(name);
244
+ else if (outcome === "captcha") captcha.push(name);
245
+ else failed.push(name);
246
+ }
247
+ const detail = [
248
+ captcha.length ? "CAPTCHA required; claim in the ZCode app" : "",
249
+ failed.length ? `${failed.length} gift claim(s) failed` : "",
250
+ ...unread,
251
+ ].filter(Boolean).join("; ");
252
+ const outcomes = [claimed.length > 0 || already.length > 0, captcha.length > 0, failed.length > 0 || unread.length > 0];
253
+ if (outcomes.filter(Boolean).length > 1) return { state: "partial", claimed, detail: detail || null };
254
+ if (failed.length > 0 || unread.length > 0) return { state: "error", claimed, detail: detail || null };
255
+ if (captcha.length > 0) return { state: "captcha", claimed, detail: detail || null };
256
+ if (claimed.length > 0) return { state: "claimed", claimed, detail: null };
257
+ return { state: "already_claimed", claimed, detail: null };
258
+ } catch {
259
+ return {
260
+ state: "error",
261
+ claimed: [],
262
+ detail: "Gift claim request failed",
263
+ };
264
+ }
265
+ }
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Zcode Start Plan sign-in.
3
+ *
4
+ * Not an RFC 6749 authorization-code flow: the plan endpoint uses the ZCode
5
+ * login JWT, not a Coding Plan API key or the separate Z.AI OAuth access token.
6
+ * It is minted by the CLI device flow:
7
+ *
8
+ * 1. `POST /api/v1/oauth/cli/init` (Bearer = a throwaway poll token) returns
9
+ * an authorize URL plus a flow id.
10
+ * 2. The operator opens the URL and approves it in a browser. Nothing comes
11
+ * back to this process — the browser lands on ZCode's own callback.
12
+ * 3. `GET /api/v1/oauth/cli/poll/{flow}` with the same poll token reports
13
+ * `status: "ready"` and hands over the JWT.
14
+ *
15
+ * There is no refresh grant. Store the credential as issued and discard the
16
+ * private poll token after completion; revoked sessions require a new sign-in.
17
+ */
18
+ import * as crypto from "node:crypto";
19
+
20
+ import type { FetchLike } from "../../authentication/oauth-client";
21
+ import { OAuthDeviceFlow } from "../../authentication/oauth-device-flow";
22
+ import { readJsonResponse } from "../../authentication/oauth-flow-store";
23
+ import type {
24
+ OAuthDeviceFlowContext,
25
+ OAuthDevicePollResult,
26
+ OAuthDeviceStartResult,
27
+ OAuthExchangeResult,
28
+ } from "../../authentication/oauth-flow-store";
29
+ import { asRecord } from "../../../shared/coerce";
30
+ import { parseJwt } from "../../authentication/jwt-validator";
31
+
32
+ const ZCODE_BASE = "https://zcode.z.ai" as const;
33
+ const INIT_URL = `${ZCODE_BASE}/api/v1/oauth/cli/init` as const;
34
+ const POLL_BASE = `${ZCODE_BASE}/api/v1/oauth/cli/poll` as const;
35
+ /** Public client id the ZCode CLI ships; not a secret. */
36
+ const ZCODE_CLIENT_ID = "client_P8X5CMWmlaRO9gyO-KSqtg" as const;
37
+ /** ZCode's flow id lives ~300 s; the console polls comfortably inside that. */
38
+ const SESSION_TTL_SECONDS = 900;
39
+ const POLL_INTERVAL_SECONDS = 3;
40
+ /**
41
+ * Tokens without an exp claim need a storage horizon rather than a real expiry.
42
+ * The credential resolver treats the resulting api_key account as static.
43
+ */
44
+ const NO_EXPIRY_MS = 10 * 365 * 24 * 60 * 60 * 1000;
45
+
46
+ const JSON_HEADERS = {
47
+ accept: "application/json",
48
+ "content-type": "application/json",
49
+ } as const;
50
+
51
+ export class ZcodeStartPlanOAuthClient extends OAuthDeviceFlow {
52
+ override readonly supportsDeviceCode = true;
53
+ override readonly supportsBrowserCode = false;
54
+
55
+ protected override readonly providerLabel = "Zcode";
56
+ protected override readonly clientId = ZCODE_CLIENT_ID;
57
+ protected override readonly tokenUrl = `${ZCODE_BASE}/api/v1/oauth/token`;
58
+ protected override readonly scopes = "";
59
+
60
+ constructor(fetchFn: FetchLike = globalThis.fetch) {
61
+ super(fetchFn);
62
+ }
63
+
64
+ override async startDeviceAuth(
65
+ _context?: OAuthDeviceFlowContext,
66
+ ): Promise<OAuthDeviceStartResult & { providerState: string }> {
67
+ const pollToken = crypto.randomBytes(32).toString("hex");
68
+ const response = await this.fetchFn(INIT_URL, {
69
+ method: "POST",
70
+ headers: { ...JSON_HEADERS, authorization: `Bearer ${pollToken}` },
71
+ body: JSON.stringify({ provider: "zai" }),
72
+ });
73
+ const payload = asRecord(await readJsonResponse(response, `${this.providerLabel} sign-in`));
74
+ const data = asRecord(payload?.data);
75
+ const authorizeUrl = typeof data?.authorize_url === "string" ? data.authorize_url : "";
76
+ const flowId = typeof data?.flow_id === "string" ? data.flow_id : "";
77
+ if (!authorizeUrl || !flowId) {
78
+ throw new Error(`${this.providerLabel} sign-in returned no authorize URL`);
79
+ }
80
+ return {
81
+ verificationUri: authorizeUrl,
82
+ userCode: "",
83
+ deviceAuthId: flowId,
84
+ intervalSeconds: POLL_INTERVAL_SECONDS,
85
+ expiresInSeconds: SESSION_TTL_SECONDS,
86
+ providerState: pollToken,
87
+ };
88
+ }
89
+
90
+ override async pollDeviceAuth(
91
+ deviceAuthId: string,
92
+ context?: OAuthDeviceFlowContext,
93
+ ): Promise<OAuthDevicePollResult> {
94
+ const pollToken = context?.providerState ?? "";
95
+ if (!pollToken) {
96
+ return { status: "failed", reason: "sign-in session lost its poll token" };
97
+ }
98
+ const response = await this.fetchFn(`${POLL_BASE}/${encodeURIComponent(deviceAuthId)}`, {
99
+ headers: { ...JSON_HEADERS, authorization: `Bearer ${pollToken}` },
100
+ });
101
+ if (response.status === 404) {
102
+ return { status: "failed", reason: "sign-in session expired — start again" };
103
+ }
104
+ if (response.status === 429) {
105
+ const retryAfter = Number(response.headers.get("retry-after"));
106
+ return {
107
+ status: "slow_down",
108
+ retryAfterSeconds: Number.isFinite(retryAfter) && retryAfter > 0 ? retryAfter : POLL_INTERVAL_SECONDS + 5,
109
+ };
110
+ }
111
+ if (response.status >= 500) {
112
+ return { status: "pending", retryAfterSeconds: POLL_INTERVAL_SECONDS + 5 };
113
+ }
114
+ if (!response.ok) {
115
+ return { status: "failed", reason: `sign-in poll failed (${response.status})` };
116
+ }
117
+ const payload = asRecord(await readJsonResponse(response, `${this.providerLabel} sign-in poll`));
118
+ const code = payload?.["code"];
119
+ if (!payload || payload["success"] === false ||
120
+ (code !== undefined && ![0, 200, "0", "200"].includes(code as string | number))) {
121
+ return { status: "failed", reason: "ZCode sign-in poll was rejected" };
122
+ }
123
+ const ready = asRecord(payload?.data);
124
+ const status = ready?.["status"];
125
+ if (status !== "ready") {
126
+ return status === "pending"
127
+ ? { status: "pending", retryAfterSeconds: POLL_INTERVAL_SECONDS }
128
+ : { status: "failed", reason: "ZCode sign-in was not authorized" };
129
+ }
130
+ const token = typeof ready?.token === "string" ? ready.token : "";
131
+ if (!token) {
132
+ return { status: "failed", reason: "ZCode authorized sign-in returned no token" };
133
+ }
134
+ const user = asRecord(ready?.user);
135
+ const email = typeof user?.email === "string" ? user.email : "";
136
+ const claims = parseJwt(token)?.payload;
137
+ const userId = claims?.user_id;
138
+ if (!email && (typeof userId !== "string" || !userId)) {
139
+ return { status: "failed", reason: "sign-in token has no account identity" };
140
+ }
141
+ const result: OAuthExchangeResult = {
142
+ access: token,
143
+ // No refresh grant exists for this token; the account is stored as static.
144
+ refresh: "",
145
+ expiresAt: new Date(typeof claims?.exp === "number" && Number.isFinite(claims.exp)
146
+ ? claims.exp * 1000 : Date.now() + NO_EXPIRY_MS),
147
+ accountLabel: email || String(userId),
148
+ auth_state: { credentialMode: "api_key", tokenKind: "zcode-plan-jwt" },
149
+ };
150
+ return { status: "complete", result };
151
+ }
152
+ }
153
+
154
+ export const zcodeStartPlanOAuthClient = new ZcodeStartPlanOAuthClient();
@@ -0,0 +1,131 @@
1
+ /**
2
+ * ZCode Start Plan uses the client's three-block Messages prompt fingerprint.
3
+ * Caller instructions remain inside the third block; a fourth block is refused.
4
+ * The bundled prompt/version pair is kept together to preserve upstream bytes.
5
+ * Reference provenance and bounded live acceptance evidence: provider guide.
6
+ */
7
+ import { randomUUID } from "node:crypto";
8
+ import { release as osRelease } from "node:os";
9
+
10
+ import type { ApiKeyProviderSpec } from "../../configured-provider";
11
+ import { defineModel } from "../../provider-model-definition";
12
+ import type { ModelDefinition } from "../../provider-model-definition";
13
+ import { getOrCreateInstallId } from "../shared/install-id";
14
+ import prompt from "./zcode_prompt.json";
15
+
16
+ const CLI_PREFIX: string = prompt.cliPrefix;
17
+ const STABLE_SECTIONS: readonly string[] = prompt.stableSections;
18
+ const ENVIRONMENT_TEMPLATE: string = prompt.environmentTemplate;
19
+
20
+ export const ZCODE_START_PLAN_PROVIDER_ID = "zcode-start" as const;
21
+ export const ZCODE_START_PLAN_ENDPOINT_PATH = "/v1/messages" as const;
22
+ export const ZCODE_START_PLAN_BASE_URL = "https://zcode.z.ai/api/v1/zcode-plan/anthropic" as const;
23
+
24
+ /** Client version the plan endpoint expects in the identity headers. */
25
+ const APP_VERSION = "3.14.5";
26
+
27
+ type Loose = Record<string, unknown>;
28
+ type TextBlock = { type: "text"; text: string; cache_control?: { type: "ephemeral" } };
29
+
30
+ function cached(text: string): TextBlock {
31
+ return { type: "text", text, cache_control: { type: "ephemeral" } };
32
+ }
33
+
34
+ /** Fills the environment block; the whole text is data, not layout. */
35
+ function environmentBlock(provider: string, model: string): string {
36
+ return ENVIRONMENT_TEMPLATE.replace("{cwd}", process.cwd())
37
+ .replace("{platform}", "linux")
38
+ .replace("{shell}", "bash")
39
+ .replace("{provider}", provider)
40
+ .replace("{model}", model);
41
+ }
42
+
43
+ /** Identity headers every dispatch carries; the adapter adds Authorization. */
44
+ async function identityHeaders(): Promise<Record<string, string>> {
45
+ return {
46
+ "user-agent": `ZCode/${APP_VERSION} ai-sdk/anthropic/3.0.81`,
47
+ "http-referer": "https://zcode.z.ai",
48
+ "x-title": "Z Code@cli",
49
+ "x-zcode-app-version": APP_VERSION,
50
+ "x-zcode-agent": "glm",
51
+ "x-release-channel": "production",
52
+ "x-client-language": "en-US",
53
+ "x-client-timezone": "Asia/Jakarta",
54
+ "x-platform": "linux",
55
+ "x-os-category": "linux",
56
+ "x-os-version": osRelease(),
57
+ "x-request-id": randomUUID(),
58
+ "x-zcode-session-type": "main",
59
+ "x-zcode-trace-id": randomUUID(),
60
+ // Keep the persisted install-id filename stable across the provider-ID rename.
61
+ "x-device-mid": await getOrCreateInstallId("zcode-start-plan"),
62
+ "anthropic-version": "2023-06-01",
63
+ };
64
+ }
65
+
66
+ /**
67
+ * Replaces the payload's system prompt with the ZCode three-block fingerprint.
68
+ * A caller-supplied system prompt is folded into the third block, after the
69
+ * environment text: a separate block is rejected with 3012.
70
+ */
71
+ function dress(payload: Loose, provider = "zcode"): void {
72
+ const model = typeof payload.model === "string" ? payload.model : "";
73
+ const own: string[] = [];
74
+ const system = payload.system;
75
+ if (typeof system === "string") {
76
+ if (system.trim()) own.push(system);
77
+ } else if (Array.isArray(system)) {
78
+ for (const block of system) {
79
+ if (
80
+ block !== null &&
81
+ typeof block === "object" &&
82
+ (block as Loose).type === "text" &&
83
+ typeof (block as Loose).text === "string" &&
84
+ (block as Loose).text
85
+ ) {
86
+ own.push((block as Loose).text as string);
87
+ }
88
+ }
89
+ }
90
+ const tail = [environmentBlock(provider, model), ...own].join("\n\n");
91
+ payload.system = [
92
+ cached(CLI_PREFIX),
93
+ cached(STABLE_SECTIONS.join("\n\n")),
94
+ cached(tail),
95
+ ];
96
+ }
97
+
98
+ export const ZCODE_START_PLAN_MODELS: readonly ModelDefinition[] = [
99
+ defineModel({
100
+ id: "glm-5.3",
101
+ providerId: ZCODE_START_PLAN_PROVIDER_ID,
102
+ wireFamily: "messages",
103
+ endpoint: ZCODE_START_PLAN_ENDPOINT_PATH,
104
+ ctx: 1_000_000,
105
+ out: 131_072,
106
+ reasoning: true,
107
+ toolCall: true,
108
+ }),
109
+ defineModel({
110
+ id: "glm-5.3-flash",
111
+ providerId: ZCODE_START_PLAN_PROVIDER_ID,
112
+ wireFamily: "messages",
113
+ endpoint: ZCODE_START_PLAN_ENDPOINT_PATH,
114
+ ctx: 1_000_000,
115
+ out: 131_072,
116
+ vision: true,
117
+ reasoning: true,
118
+ toolCall: true,
119
+ }),
120
+ ];
121
+
122
+ /** Start Plan adapter spec: direct upstream, prompt fingerprint, no sidecar. */
123
+ export const ZCODE_START_PLAN_SPEC: ApiKeyProviderSpec = {
124
+ provider_id: ZCODE_START_PLAN_PROVIDER_ID,
125
+ base_url: ZCODE_START_PLAN_BASE_URL,
126
+ endpoint_paths_by_wire_family: { messages: ZCODE_START_PLAN_ENDPOINT_PATH },
127
+ buildExtraHeaders: () => identityHeaders(),
128
+ prePayload: (payload) => {
129
+ dress(payload as Loose);
130
+ },
131
+ };