cartethyia 2.7.7 → 2.7.9

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 (372) hide show
  1. package/.env.example +0 -1
  2. package/README.md +29 -59
  3. package/dist/dashboard/assets/BannedPage-BxoG1MrL.js +1 -0
  4. package/dist/dashboard/assets/BannedPage-BxoG1MrL.js.gz +0 -0
  5. package/dist/dashboard/assets/{CliToolDetailPage-CLUhmjUy.js → CliToolDetailPage-ixwgKk53.js} +1 -1
  6. package/dist/dashboard/assets/CliToolDetailPage-ixwgKk53.js.gz +0 -0
  7. package/dist/dashboard/assets/{CliToolsPage-CQmrqqrk.js → CliToolsPage-BmttNV3U.js} +1 -1
  8. package/dist/dashboard/assets/CliToolsPage-BmttNV3U.js.gz +0 -0
  9. package/dist/dashboard/assets/CombosPage-BE3qwwfC.js +1 -0
  10. package/dist/dashboard/assets/CombosPage-BE3qwwfC.js.gz +0 -0
  11. package/dist/dashboard/assets/ConsoleLogPage-CRZdmMIX.js +1 -0
  12. package/dist/dashboard/assets/ConsoleLogPage-CRZdmMIX.js.gz +0 -0
  13. package/dist/dashboard/assets/CustomizationPage-Dv_FJ6Er.js +1 -0
  14. package/dist/dashboard/assets/CustomizationPage-Dv_FJ6Er.js.gz +0 -0
  15. package/dist/dashboard/assets/HealthEventsModal-CoVrw2sM.js +1 -0
  16. package/dist/dashboard/assets/HealthEventsModal-CoVrw2sM.js.gz +0 -0
  17. package/dist/dashboard/assets/{InjectSystemPromptPanel-C-e2AMz6.js → InjectSystemPromptPanel-BOoO8rpz.js} +2 -2
  18. package/dist/dashboard/assets/InjectSystemPromptPanel-BOoO8rpz.js.gz +0 -0
  19. package/dist/dashboard/assets/{LoginPage-J8wPbmfT.js → LoginPage-ChJuNNVN.js} +1 -1
  20. package/dist/dashboard/assets/LoginPage-ChJuNNVN.js.gz +0 -0
  21. package/dist/dashboard/assets/{ModelPicker-C6WlpU5E.js → ModelPicker-BZAJtPg1.js} +1 -1
  22. package/dist/dashboard/assets/ModelPicker-BZAJtPg1.js.gz +0 -0
  23. package/dist/dashboard/assets/OverviewPage-BE40s3u5.js +1 -0
  24. package/dist/dashboard/assets/OverviewPage-BE40s3u5.js.gz +0 -0
  25. package/dist/dashboard/assets/ProviderDetailPage-sfLoQtPV.js +8 -0
  26. package/dist/dashboard/assets/ProviderDetailPage-sfLoQtPV.js.gz +0 -0
  27. package/dist/dashboard/assets/ProviderIcon-CQ6bPUf_.js +1 -0
  28. package/dist/dashboard/assets/ProviderIcon-CQ6bPUf_.js.gz +0 -0
  29. package/dist/dashboard/assets/ProvidersPage-DcepmPWo.js +1 -0
  30. package/dist/dashboard/assets/ProvidersPage-DcepmPWo.js.gz +0 -0
  31. package/dist/dashboard/assets/{ProxyPage-BBTRBAQ3.js → ProxyPage-BJ87Pp0U.js} +1 -1
  32. package/dist/dashboard/assets/ProxyPage-BJ87Pp0U.js.gz +0 -0
  33. package/dist/dashboard/assets/{QuotaPage-B2WqMSG1.js → QuotaPage-gkSyRAKa.js} +1 -1
  34. package/dist/dashboard/assets/QuotaPage-gkSyRAKa.js.gz +0 -0
  35. package/dist/dashboard/assets/SettingsPage-C5HPWqEv.js +1 -0
  36. package/dist/dashboard/assets/SettingsPage-C5HPWqEv.js.gz +0 -0
  37. package/dist/dashboard/assets/{SetupPage-LND6_Ss7.js → SetupPage-CFNcATJJ.js} +1 -1
  38. package/dist/dashboard/assets/SetupPage-CFNcATJJ.js.gz +0 -0
  39. package/dist/dashboard/assets/{StudioPage-BzNnm6Bi.js → StudioPage-YoD4tY5l.js} +1 -1
  40. package/dist/dashboard/assets/StudioPage-YoD4tY5l.js.gz +0 -0
  41. package/dist/dashboard/assets/UsagePage-DxjaAhb_.js +56 -0
  42. package/dist/dashboard/assets/UsagePage-DxjaAhb_.js.gz +0 -0
  43. package/dist/dashboard/assets/api-keys-BTlkq_Uk.js +1 -0
  44. package/dist/dashboard/assets/api-keys-BTlkq_Uk.js.gz +0 -0
  45. package/dist/dashboard/assets/app-BX2nnKqs.css +2 -0
  46. package/dist/dashboard/assets/app-BX2nnKqs.css.gz +0 -0
  47. package/dist/dashboard/assets/assert-CndthXFQ.js +1 -0
  48. package/dist/dashboard/assets/assert-CndthXFQ.js.gz +0 -0
  49. package/dist/dashboard/assets/{badge-BaX2GTrn.js → badge-DdbT_7Am.js} +1 -1
  50. package/dist/dashboard/assets/badge-DdbT_7Am.js.gz +0 -0
  51. package/dist/dashboard/assets/ban-durations-B58FyRxC.js +1 -0
  52. package/dist/dashboard/assets/ban-durations-B58FyRxC.js.gz +0 -0
  53. package/dist/dashboard/assets/{banner-DFH4Bkte.js → banner-CsGN-nbm.js} +1 -1
  54. package/dist/dashboard/assets/banner-CsGN-nbm.js.gz +0 -0
  55. package/dist/dashboard/assets/brand/bansos_page.webp +0 -0
  56. package/dist/dashboard/assets/brand/denia_bansos.webp +0 -0
  57. package/dist/dashboard/assets/brand/favicon.webp +0 -0
  58. package/dist/dashboard/assets/brand/login_register.webp +0 -0
  59. package/dist/dashboard/assets/brand/login_register_initial.webp +0 -0
  60. package/dist/dashboard/assets/brand/og_bansos.webp +0 -0
  61. package/dist/dashboard/assets/brand/og_image.webp +0 -0
  62. package/dist/dashboard/assets/brand/sidebar_ico.webp +0 -0
  63. package/dist/dashboard/assets/{card-CxDw0lK6.js → card-mgZ_TLLZ.js} +1 -1
  64. package/dist/dashboard/assets/card-mgZ_TLLZ.js.gz +0 -0
  65. package/dist/dashboard/assets/cli-tools-A1-v8-03.js +1 -0
  66. package/dist/dashboard/assets/cli-tools-A1-v8-03.js.gz +0 -0
  67. package/dist/dashboard/assets/{clipboard-button-DfS1ntiq.js → clipboard-button-CJ4Zty89.js} +1 -1
  68. package/dist/dashboard/assets/clipboard-button-CJ4Zty89.js.gz +0 -0
  69. package/dist/dashboard/assets/{dialog-BK-NRr5u.js → dialog-B5L2jPQ_.js} +1 -1
  70. package/dist/dashboard/assets/dialog-B5L2jPQ_.js.gz +0 -0
  71. package/dist/dashboard/assets/{drawer-QqPul6sC.js → drawer-DkjUouAj.js} +1 -1
  72. package/dist/dashboard/assets/drawer-DkjUouAj.js.gz +0 -0
  73. package/dist/dashboard/assets/{entry-BMlYJVFj.js → entry-B-LVLV6o.js} +1 -1
  74. package/dist/dashboard/assets/entry-B-LVLV6o.js.gz +0 -0
  75. package/dist/dashboard/assets/entry-CAhdYl3B.js +1 -0
  76. package/dist/dashboard/assets/entry-CAhdYl3B.js.gz +0 -0
  77. package/dist/dashboard/assets/entry-D2xD0Tmd.js +4 -0
  78. package/dist/dashboard/assets/entry-D2xD0Tmd.js.gz +0 -0
  79. package/dist/dashboard/assets/{formatters-DP-5E01-.js → formatters-CrsdLVsn.js} +1 -1
  80. package/dist/dashboard/assets/formatters-CrsdLVsn.js.gz +0 -0
  81. package/dist/dashboard/assets/{index-D36vCZht.js → index-BU64Lqvp.js} +2 -2
  82. package/dist/dashboard/assets/index-BU64Lqvp.js.gz +0 -0
  83. package/dist/dashboard/assets/{inline-CHJQwxLa.js → inline-B2aDLyyg.js} +1 -1
  84. package/dist/dashboard/assets/inline-B2aDLyyg.js.gz +0 -0
  85. package/dist/dashboard/assets/{input-BlmlizVV.js → input-BCVkdR9d.js} +1 -1
  86. package/dist/dashboard/assets/input-BCVkdR9d.js.gz +0 -0
  87. package/dist/dashboard/assets/{layout-Bz93I-yE.js → layout-DNcAdMK-.js} +1 -1
  88. package/dist/dashboard/assets/layout-DNcAdMK-.js.gz +0 -0
  89. package/dist/dashboard/assets/{list-row-Ml16KCfu.js → list-row-DgrIH0hw.js} +1 -1
  90. package/dist/dashboard/assets/list-row-DgrIH0hw.js.gz +0 -0
  91. package/dist/dashboard/assets/{live-7_QpnYGu.js → live-Cae01iu8.js} +1 -1
  92. package/dist/dashboard/assets/live-Cae01iu8.js.gz +0 -0
  93. package/dist/dashboard/assets/{mutation-GU7XdEjz.js → mutation-BQ0ccH_A.js} +1 -1
  94. package/dist/dashboard/assets/mutation-BQ0ccH_A.js.gz +0 -0
  95. package/dist/dashboard/assets/{network-CuMDaTzT.js → network-CRib7H_2.js} +1 -1
  96. package/dist/dashboard/assets/network-CRib7H_2.js.gz +0 -0
  97. package/dist/dashboard/assets/{numbers-CoqpaDMx.js → numbers-BKQE8Xpz.js} +1 -1
  98. package/dist/dashboard/assets/numbers-BKQE8Xpz.js.gz +0 -0
  99. package/dist/dashboard/assets/{pagination-B5aOoweZ.js → pagination-ecPvG_8g.js} +1 -1
  100. package/dist/dashboard/assets/pagination-ecPvG_8g.js.gz +0 -0
  101. package/dist/dashboard/assets/providers/devin.svg +9 -0
  102. package/dist/dashboard/assets/providers/devin.svg.gz +0 -0
  103. package/dist/dashboard/assets/providers/windsurf.svg +10 -0
  104. package/dist/dashboard/assets/providers/windsurf.svg.gz +0 -0
  105. package/dist/dashboard/assets/{query-keys-YSoQOUh6.js → query-keys-IKLh0YFd.js} +1 -1
  106. package/dist/dashboard/assets/query-keys-IKLh0YFd.js.gz +0 -0
  107. package/dist/dashboard/assets/routing-Ckm1UXuC.js +1 -0
  108. package/dist/dashboard/assets/routing-Ckm1UXuC.js.gz +0 -0
  109. package/dist/dashboard/assets/{select-C9Ssle9b.js → select-ChoFWyKz.js} +1 -1
  110. package/dist/dashboard/assets/select-ChoFWyKz.js.gz +0 -0
  111. package/dist/dashboard/assets/settings-CKjFPlKW.js +1 -0
  112. package/dist/dashboard/assets/settings-CKjFPlKW.js.gz +0 -0
  113. package/dist/dashboard/assets/{stack-j7cXjgYX.js → stack-DWCwU3fh.js} +1 -1
  114. package/dist/dashboard/assets/stack-DWCwU3fh.js.gz +0 -0
  115. package/dist/dashboard/assets/{state-DHmEnLa2.js → state-Cg3VL5J_.js} +1 -1
  116. package/dist/dashboard/assets/state-Cg3VL5J_.js.gz +0 -0
  117. package/dist/dashboard/assets/story/25817331.webp +0 -0
  118. package/dist/dashboard/assets/story/Shorekeeper.webp +0 -0
  119. package/dist/dashboard/assets/story/cartethyia-god.webp +0 -0
  120. package/dist/dashboard/assets/story/fleurdelys_plus.webp +0 -0
  121. package/dist/dashboard/assets/story/jinhsi-blossom.webp +0 -0
  122. package/dist/dashboard/assets/story/phrolova-a.webp +0 -0
  123. package/dist/dashboard/assets/story/requestdeniawokkjpg.webp +0 -0
  124. package/dist/dashboard/assets/story/wuthering-waves-hiyuki-aemeath-hiyuki-rover.webp +0 -0
  125. package/dist/dashboard/assets/{switch-DmZcyTIC.js → switch-Db70BMix.js} +1 -1
  126. package/dist/dashboard/assets/switch-Db70BMix.js.gz +0 -0
  127. package/dist/dashboard/assets/{useMutation-CbCP4w1o.js → useMutation-BqdE0LuM.js} +1 -1
  128. package/dist/dashboard/assets/useMutation-BqdE0LuM.js.gz +0 -0
  129. package/dist/dashboard/console-backgrounds.webp +0 -0
  130. package/dist/dashboard/console-backgrounds_initial.webp +0 -0
  131. package/dist/dashboard/donation/qris-risun-marke.webp +0 -0
  132. package/dist/dashboard/index.html +3 -3
  133. package/dist/dashboard/index.html.gz +0 -0
  134. package/dist/dashboard/precompressed-assets.json +57 -55
  135. package/migrations/full-postgres/0044_add_models_warning_metadata.sql +10 -0
  136. package/migrations/full-postgres/0045_migrate_workbuddy_to_codebuddy.sql +156 -0
  137. package/migrations/lite-sqlite3/0044_add_models_warning_metadata.sql +11 -0
  138. package/migrations/lite-sqlite3/0045_migrate_workbuddy_to_codebuddy.sql +156 -0
  139. package/package.json +1 -1
  140. package/src/boot/dependencies.ts +11 -3
  141. package/src/config/cooldowns.ts +1 -1
  142. package/src/config/spec.ts +0 -6
  143. package/src/console/api-keys/routes.ts +11 -4
  144. package/src/console/console-router.ts +7 -0
  145. package/src/console/dashboard-assets.ts +5 -5
  146. package/src/console/domain-registration.ts +27 -0
  147. package/src/console/ip-bans/routes.ts +99 -0
  148. package/src/console/providers/catalog/catalog-projections.ts +5 -2
  149. package/src/console/providers/catalog/contracts.ts +123 -0
  150. package/src/console/providers/catalog/model-operations.ts +122 -10
  151. package/src/console/providers/catalog/provider-operations.ts +116 -8
  152. package/src/console/providers/catalog/public-model-store.ts +0 -0
  153. package/src/console/providers/catalog/routes.ts +64 -4
  154. package/src/console/providers/catalog/store-helpers.ts +30 -1
  155. package/src/console/providers/catalog/store.ts +243 -3
  156. package/src/console/quota/account-quota-global.ts +89 -1
  157. package/src/console/quota/native-identity.ts +2 -0
  158. package/src/console/settings/contracts.ts +18 -0
  159. package/src/console/settings/store.ts +32 -0
  160. package/src/console/system-prompt/contracts.ts +0 -1
  161. package/src/main.ts +1 -0
  162. package/src/observability/event-query.ts +18 -4
  163. package/src/persistence/dialect.ts +12 -0
  164. package/src/persistence/schema.ts +20 -2
  165. package/src/protocol/dsml.ts +1 -1
  166. package/src/protocol/gateway-error.ts +1 -0
  167. package/src/protocol/reasoning.ts +1 -1
  168. package/src/protocol/request/chat.ts +4 -4
  169. package/src/protocol/request/messages.ts +1 -1
  170. package/src/protocol/response/gemini.ts +6 -1
  171. package/src/protocol/sse-decoder.ts +25 -8
  172. package/src/protocol/stream-error-frames.ts +13 -3
  173. package/src/protocol/translation/quirks.ts +1 -1
  174. package/src/protocol/translation/tool-repair.ts +2 -2
  175. package/src/protocol/upstream/send-claude-messages.ts +15 -4
  176. package/src/protocol/upstream-parsing.ts +1 -1
  177. package/src/providers/adapters/compatible-adapter.ts +7 -5
  178. package/src/providers/authentication/oauth-refresh-service.ts +149 -36
  179. package/src/providers/default-registry.ts +68 -3
  180. package/src/providers/discovery/discovery-types.ts +12 -0
  181. package/src/providers/discovery/probe-phases.ts +61 -30
  182. package/src/providers/discovery/probing-service.ts +279 -164
  183. package/src/providers/integrations/antigravity/antigravity-protocol.ts +117 -2
  184. package/src/providers/integrations/antigravity/antigravity.ts +13 -2
  185. package/src/providers/integrations/buddy/buddy-catalog-shared.ts +72 -34
  186. package/src/providers/integrations/buddy/buddy-chat-shared.ts +18 -18
  187. package/src/providers/integrations/buddy/buddy-checkin.ts +17 -39
  188. package/src/providers/integrations/buddy/buddy-conversation-headers.ts +2 -2
  189. package/src/providers/integrations/buddy/buddy-discovery-shared.ts +5 -5
  190. package/src/providers/integrations/buddy/buddy-identity.ts +70 -0
  191. package/src/providers/integrations/buddy/buddy-media.ts +4 -5
  192. package/src/providers/integrations/buddy/buddy-oauth-shared.ts +2 -2
  193. package/src/providers/integrations/buddy/buddy-quota-shared.ts +1 -1
  194. package/src/providers/integrations/buddy/buddy-usage-shared.ts +1 -3
  195. package/src/providers/integrations/buddy/capabilities.ts +4 -41
  196. package/src/providers/integrations/buddy/codebuddy/cn-catalog.ts +2 -1
  197. package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +20 -1
  198. package/src/providers/integrations/buddy/codebuddy/provider.ts +2 -2
  199. package/src/providers/integrations/buddy/codebuddy/shared.ts +6 -10
  200. package/src/providers/integrations/cursor/cursor-catalog.ts +2 -0
  201. package/src/providers/integrations/cursor/cursor-exec.ts +738 -0
  202. package/src/providers/integrations/cursor/cursor-http2.ts +2 -0
  203. package/src/providers/integrations/cursor/cursor-request.ts +9 -8
  204. package/src/providers/integrations/cursor/cursor-shared.ts +19 -1
  205. package/src/providers/integrations/cursor/cursor.ts +50 -30
  206. package/src/providers/integrations/cursor/protocol/tool-canonical.ts +26 -100
  207. package/src/providers/integrations/devin/devin-auth.ts +353 -0
  208. package/src/providers/integrations/devin/devin-catalog.ts +207 -0
  209. package/src/providers/integrations/devin/devin-http.ts +91 -0
  210. package/src/providers/integrations/devin/devin-quota.ts +214 -0
  211. package/src/providers/integrations/devin/devin-shared.ts +111 -0
  212. package/src/providers/integrations/devin/devin.ts +539 -0
  213. package/src/providers/integrations/devin/protocol/devin-proto.ts +584 -0
  214. package/src/providers/integrations/devin/protocol/framing.ts +124 -0
  215. package/src/providers/integrations/factory/factory.ts +2 -2
  216. package/src/providers/integrations/freepi/freepi-catalog.ts +60 -0
  217. package/src/providers/integrations/freepi/freepi-discovery.ts +82 -0
  218. package/src/providers/integrations/freepi/freepi-headers.ts +21 -0
  219. package/src/providers/integrations/freepi/freepi-oauth.ts +142 -0
  220. package/src/providers/integrations/freepi/freepi-protocol.ts +242 -0
  221. package/src/providers/integrations/freepi/freepi-quota.ts +126 -0
  222. package/src/providers/integrations/freepi/freepi-realm.ts +35 -0
  223. package/src/providers/integrations/freepi/freepi.ts +292 -0
  224. package/src/providers/integrations/gemini.ts +2 -2
  225. package/src/providers/integrations/hermes/hermes-oauth.ts +94 -0
  226. package/src/providers/integrations/hermes.ts +4 -12
  227. package/src/providers/integrations/opencode/fingerprint.ts +1 -1
  228. package/src/providers/integrations/perch/perch-catalog.ts +105 -0
  229. package/src/providers/integrations/perch/perch-oauth.ts +170 -0
  230. package/src/providers/integrations/perch/perch-protocol.ts +211 -0
  231. package/src/providers/integrations/perch/perch-quota.ts +137 -0
  232. package/src/providers/integrations/perch/perch-realm.ts +82 -0
  233. package/src/providers/integrations/perch/perch-system-prompt.ts +13 -0
  234. package/src/providers/integrations/perch/perch.ts +315 -0
  235. package/src/providers/integrations/perch/saffron-system-prompt.txt +8 -0
  236. package/src/providers/integrations/qoder/chat-proto.ts +328 -328
  237. package/src/providers/integrations/qoder/claim-qoder-credits.ts +1 -1
  238. package/src/providers/integrations/qoder/qoder-adapter.ts +89 -28
  239. package/src/providers/integrations/qoder/qoder-cache.ts +32 -0
  240. package/src/providers/integrations/qoder/qoder-catalog.ts +6 -1
  241. package/src/providers/integrations/qoder/qoder-checkin.ts +2 -2
  242. package/src/providers/integrations/qoder/qoder-grpc.ts +209 -5
  243. package/src/providers/integrations/qoder/qoder-ide.ts +5 -1
  244. package/src/providers/integrations/qoder/qoder-identity-cache.ts +184 -0
  245. package/src/providers/integrations/qoder/qoder-native-identity-store.ts +83 -18
  246. package/src/providers/integrations/qoder/qoder-realm.ts +9 -6
  247. package/src/providers/integrations/qoder/qoder-umid.ts +109 -342
  248. package/src/providers/integrations/qoder/qoder-virtual.ts +33 -1
  249. package/src/providers/integrations/qoder/qoder.ts +3 -6
  250. package/src/providers/integrations/trae/trae-catalog.ts +9 -14
  251. package/src/providers/integrations/trae/trae-headers.ts +36 -11
  252. package/src/providers/integrations/trae/trae-oauth.ts +14 -17
  253. package/src/providers/integrations/trae/trae-protocol.ts +3 -6
  254. package/src/providers/integrations/trae/trae-quota.ts +103 -21
  255. package/src/providers/integrations/trae/trae-realm.ts +36 -15
  256. package/src/providers/integrations/trae/trae.ts +97 -7
  257. package/src/providers/operations/account-error-classification.ts +66 -1
  258. package/src/providers/operations/account-health-service.ts +192 -26
  259. package/src/providers/operations/account-refresh-status.ts +284 -0
  260. package/src/providers/operations/account-tier.ts +67 -0
  261. package/src/providers/operations/byok-wire-profile.ts +9 -12
  262. package/src/providers/operations/client-versions.ts +37 -99
  263. package/src/providers/operations/cooldown-rules.ts +61 -0
  264. package/src/providers/operations/provider-catalog-seeder.ts +4 -0
  265. package/src/providers/provider-contracts.ts +29 -0
  266. package/src/providers/provider-metadata.ts +59 -4
  267. package/src/providers/provider-model-definition.ts +36 -0
  268. package/src/providers/quota/refresh.ts +21 -0
  269. package/src/security/abuse.ts +71 -0
  270. package/src/transport/dispatch/proxy-request.ts +1 -0
  271. package/src/transport/dispatch/streaming/stream.ts +1 -0
  272. package/src/transport/dispatch/upstream.ts +4 -1
  273. package/src/transport/failure-policy.ts +113 -7
  274. package/src/transport/routing/router.ts +25 -1
  275. package/src/transport/surface/messages/adapter.ts +2 -1
  276. package/src/transport/surface/responses/encode.ts +12 -1
  277. package/src/workers/daily-checkin.ts +1 -1
  278. package/src/workers/quota-refresh-sweep.ts +1 -1
  279. package/src/workers/scheduler.ts +22 -4
  280. package/dist/dashboard/assets/BannedPage-B05aF8Dg.js +0 -1
  281. package/dist/dashboard/assets/BannedPage-B05aF8Dg.js.gz +0 -0
  282. package/dist/dashboard/assets/CliToolDetailPage-CLUhmjUy.js.gz +0 -0
  283. package/dist/dashboard/assets/CliToolsPage-CQmrqqrk.js.gz +0 -0
  284. package/dist/dashboard/assets/CombosPage-CHG_1Wr3.js +0 -1
  285. package/dist/dashboard/assets/CombosPage-CHG_1Wr3.js.gz +0 -0
  286. package/dist/dashboard/assets/ConsoleLogPage-DPgbklad.js +0 -1
  287. package/dist/dashboard/assets/ConsoleLogPage-DPgbklad.js.gz +0 -0
  288. package/dist/dashboard/assets/CustomizationPage-pnfAqr_-.js +0 -1
  289. package/dist/dashboard/assets/CustomizationPage-pnfAqr_-.js.gz +0 -0
  290. package/dist/dashboard/assets/HealthEventsModal-DGJuU2A6.js +0 -1
  291. package/dist/dashboard/assets/HealthEventsModal-DGJuU2A6.js.gz +0 -0
  292. package/dist/dashboard/assets/InjectSystemPromptPanel-C-e2AMz6.js.gz +0 -0
  293. package/dist/dashboard/assets/LoginPage-J8wPbmfT.js.gz +0 -0
  294. package/dist/dashboard/assets/ModelPicker-C6WlpU5E.js.gz +0 -0
  295. package/dist/dashboard/assets/OverviewPage-BSQnF2Lp.js +0 -1
  296. package/dist/dashboard/assets/OverviewPage-BSQnF2Lp.js.gz +0 -0
  297. package/dist/dashboard/assets/ProviderDetailPage-DK_e0FJz.js +0 -7
  298. package/dist/dashboard/assets/ProviderDetailPage-DK_e0FJz.js.gz +0 -0
  299. package/dist/dashboard/assets/ProviderIcon-jjqXJDA3.js +0 -1
  300. package/dist/dashboard/assets/ProviderIcon-jjqXJDA3.js.gz +0 -0
  301. package/dist/dashboard/assets/ProvidersPage-D_a3r6Gc.js +0 -1
  302. package/dist/dashboard/assets/ProvidersPage-D_a3r6Gc.js.gz +0 -0
  303. package/dist/dashboard/assets/ProxyPage-BBTRBAQ3.js.gz +0 -0
  304. package/dist/dashboard/assets/QuotaPage-B2WqMSG1.js.gz +0 -0
  305. package/dist/dashboard/assets/SettingsPage-D7xp5Ij_.js +0 -1
  306. package/dist/dashboard/assets/SettingsPage-D7xp5Ij_.js.gz +0 -0
  307. package/dist/dashboard/assets/SetupPage-LND6_Ss7.js.gz +0 -0
  308. package/dist/dashboard/assets/StudioPage-BzNnm6Bi.js.gz +0 -0
  309. package/dist/dashboard/assets/UsagePage-C1TbL24N.js +0 -56
  310. package/dist/dashboard/assets/UsagePage-C1TbL24N.js.gz +0 -0
  311. package/dist/dashboard/assets/api-keys-KvX83mRe.js +0 -1
  312. package/dist/dashboard/assets/api-keys-KvX83mRe.js.gz +0 -0
  313. package/dist/dashboard/assets/app-mweRcsKp.css +0 -2
  314. package/dist/dashboard/assets/app-mweRcsKp.css.gz +0 -0
  315. package/dist/dashboard/assets/assert-CidQVoNo.js +0 -1
  316. package/dist/dashboard/assets/assert-CidQVoNo.js.gz +0 -0
  317. package/dist/dashboard/assets/badge-BaX2GTrn.js.gz +0 -0
  318. package/dist/dashboard/assets/banner-DFH4Bkte.js.gz +0 -0
  319. package/dist/dashboard/assets/brand/bansos_page.png +0 -0
  320. package/dist/dashboard/assets/brand/denia_bansos.jpg +0 -0
  321. package/dist/dashboard/assets/brand/favicon.jpg +0 -0
  322. package/dist/dashboard/assets/brand/login_register.jpg +0 -0
  323. package/dist/dashboard/assets/brand/login_register_initial.jpg +0 -0
  324. package/dist/dashboard/assets/brand/og_bansos.jpg +0 -0
  325. package/dist/dashboard/assets/brand/og_image.jpg +0 -0
  326. package/dist/dashboard/assets/brand/sidebar_ico.jpg +0 -0
  327. package/dist/dashboard/assets/card-CxDw0lK6.js.gz +0 -0
  328. package/dist/dashboard/assets/cli-tools-Bwv5-zGZ.js +0 -1
  329. package/dist/dashboard/assets/cli-tools-Bwv5-zGZ.js.gz +0 -0
  330. package/dist/dashboard/assets/clipboard-button-DfS1ntiq.js.gz +0 -0
  331. package/dist/dashboard/assets/dialog-BK-NRr5u.js.gz +0 -0
  332. package/dist/dashboard/assets/drawer-QqPul6sC.js.gz +0 -0
  333. package/dist/dashboard/assets/entry-BMlYJVFj.js.gz +0 -0
  334. package/dist/dashboard/assets/entry-Dmx7gBiN.js +0 -1
  335. package/dist/dashboard/assets/entry-Dmx7gBiN.js.gz +0 -0
  336. package/dist/dashboard/assets/entry-vqGb8yVz.js +0 -4
  337. package/dist/dashboard/assets/entry-vqGb8yVz.js.gz +0 -0
  338. package/dist/dashboard/assets/formatters-DP-5E01-.js.gz +0 -0
  339. package/dist/dashboard/assets/index-D36vCZht.js.gz +0 -0
  340. package/dist/dashboard/assets/inline-CHJQwxLa.js.gz +0 -0
  341. package/dist/dashboard/assets/input-BlmlizVV.js.gz +0 -0
  342. package/dist/dashboard/assets/layout-Bz93I-yE.js.gz +0 -0
  343. package/dist/dashboard/assets/list-row-Ml16KCfu.js.gz +0 -0
  344. package/dist/dashboard/assets/live-7_QpnYGu.js.gz +0 -0
  345. package/dist/dashboard/assets/minimize-2-BTmMTK4o.js +0 -1
  346. package/dist/dashboard/assets/minimize-2-BTmMTK4o.js.gz +0 -0
  347. package/dist/dashboard/assets/mutation-GU7XdEjz.js.gz +0 -0
  348. package/dist/dashboard/assets/network-CuMDaTzT.js.gz +0 -0
  349. package/dist/dashboard/assets/numbers-CoqpaDMx.js.gz +0 -0
  350. package/dist/dashboard/assets/pagination-B5aOoweZ.js.gz +0 -0
  351. package/dist/dashboard/assets/query-keys-YSoQOUh6.js.gz +0 -0
  352. package/dist/dashboard/assets/routing-fnCsxgNO.js +0 -1
  353. package/dist/dashboard/assets/routing-fnCsxgNO.js.gz +0 -0
  354. package/dist/dashboard/assets/select-C9Ssle9b.js.gz +0 -0
  355. package/dist/dashboard/assets/settings-BxslsErn.js +0 -1
  356. package/dist/dashboard/assets/settings-BxslsErn.js.gz +0 -0
  357. package/dist/dashboard/assets/stack-j7cXjgYX.js.gz +0 -0
  358. package/dist/dashboard/assets/state-DHmEnLa2.js.gz +0 -0
  359. package/dist/dashboard/assets/switch-DmZcyTIC.js.gz +0 -0
  360. package/dist/dashboard/assets/useMutation-CbCP4w1o.js.gz +0 -0
  361. package/dist/dashboard/console-backgrounds.jpg +0 -0
  362. package/dist/dashboard/console-backgrounds_initial.jpg +0 -0
  363. package/dist/dashboard/donation/qris-risun-marke.png +0 -0
  364. package/src/providers/integrations/buddy/turing-device-token.ts +0 -262
  365. package/src/providers/integrations/buddy/workbuddy/cn-oauth.ts +0 -30
  366. package/src/providers/integrations/buddy/workbuddy/cn-provider.ts +0 -58
  367. package/src/providers/integrations/buddy/workbuddy/oauth.ts +0 -31
  368. package/src/providers/integrations/buddy/workbuddy/provider.ts +0 -209
  369. package/src/providers/integrations/buddy/workbuddy/quota.ts +0 -161
  370. package/src/providers/integrations/buddy/workbuddy/shared.ts +0 -285
  371. /package/dist/dashboard/assets/{app-DRnQLhsc.js → app-B7kIWFm5.js} +0 -0
  372. /package/dist/dashboard/assets/{app-DRnQLhsc.js.gz → app-B7kIWFm5.js.gz} +0 -0
@@ -1,161 +0,0 @@
1
- import type { FetchLike, ProviderQuotaResult } from "../../../quota/quota-contracts";
2
- import type { QuotaCollectionContext } from "../../../quota/quota-support";
3
- import { providerBaseUrl } from "../../../provider-metadata";
4
- import {
5
- buildWorkBuddyUserAgent,
6
- getWorkBuddyClientVersion,
7
- getWorkBuddyCnClientVersion,
8
- getWorkBuddyCliVersion,
9
- } from "../../../operations/client-versions";
10
- import { WORKBUDDY_DOMAIN } from "./shared";
11
- import { fetchTencentBillingQuota } from "../buddy-quota-shared";
12
- import { fetchBuddyRequestUsage, type BuddyUsageResult } from "../buddy-usage-shared";
13
- import { buddyAccountUid } from "../buddy-oauth-shared";
14
-
15
- /**
16
- * WorkBuddy international billing quota.
17
- *
18
- * Endpoint: POST https://www.workbuddy.ai/v2/billing/meter/get-user-resource
19
- * Request: Authorization: Bearer <accessToken||apiKey>, desktop-client headers,
20
- * X-User-Id for the account UID, and the reference filter envelope
21
- * (ProductCode p_tcaca, statuses [0, 3], 101-year package window).
22
- * Response: { code: 0, data: { Response: { Data: { Accounts: [...] } } } }
23
- *
24
- * Same Tencent billing envelope as CodeBuddy CN, so the parsing is the shared
25
- * one in `buddy-quota-shared.ts`; only the endpoint and identity headers are
26
- * WorkBuddy-specific.
27
- */
28
-
29
- /**
30
- * The CN billing realm's host.
31
- *
32
- * The reference bills the CN realm here rather than on the CN chat host
33
- * (`www.workbuddy.cn`): billing is a separate service, and the chat host does
34
- * not serve the meter path.
35
- */
36
- const WORKBUDDY_CN_BILLING_BASE_URL = "https://www.codebuddy.cn";
37
-
38
- export const WORKBUDDY_USAGE_URL =
39
- `${providerBaseUrl("workbuddy")}/v2/billing/meter/get-user-resource`;
40
-
41
- async function billingHeaders(
42
- domain: string,
43
- clientVersion: string,
44
- enterpriseId?: string,
45
- ): Promise<Record<string, string>> {
46
- return {
47
- "User-Agent": buildWorkBuddyUserAgent(clientVersion, getWorkBuddyCliVersion()),
48
- "X-Product": "SaaS",
49
- "X-Domain": domain,
50
- "X-Requested-With": "XMLHttpRequest",
51
- "X-CodeBuddy-Request": "1",
52
- "Accept-Language": "en-US",
53
- ...(enterpriseId === undefined || enterpriseId.length === 0
54
- ? {}
55
- : { "X-Tenant-Id": enterpriseId, "X-Enterprise-Id": enterpriseId }),
56
- };
57
- }
58
-
59
- /**
60
- * Fetches WorkBuddy quota via the Tencent billing endpoint.
61
- *
62
- * Auth: `Authorization: Bearer <credential>` (api_key and oauth both use
63
- * Bearer; the caller passes the resolved secret).
64
- */
65
- export async function fetchWorkBuddyQuota(
66
- credential: string,
67
- fetcher: FetchLike,
68
- context?: QuotaCollectionContext,
69
- ): Promise<ProviderQuotaResult> {
70
- return fetchWorkBuddyQuotaFor({
71
- providerId: "workbuddy",
72
- display: "WorkBuddy",
73
- domain: WORKBUDDY_DOMAIN,
74
- credential,
75
- fetcher,
76
- ...(context === undefined ? {} : { context }),
77
- });
78
- }
79
-
80
- export async function fetchWorkBuddyCnQuota(
81
- credential: string,
82
- fetcher: FetchLike,
83
- context?: QuotaCollectionContext,
84
- ): Promise<ProviderQuotaResult> {
85
- return fetchWorkBuddyQuotaFor({
86
- providerId: "workbuddycn",
87
- display: "WorkBuddy CN",
88
- domain: "www.workbuddy.cn",
89
- credential,
90
- fetcher,
91
- ...(context === undefined ? {} : { context }),
92
- });
93
- }
94
-
95
- async function fetchWorkBuddyQuotaFor(args: {
96
- readonly providerId: "workbuddy" | "workbuddycn";
97
- readonly display: string;
98
- readonly domain: string;
99
- readonly credential: string;
100
- readonly fetcher: FetchLike;
101
- readonly context?: QuotaCollectionContext;
102
- }): Promise<ProviderQuotaResult> {
103
- const { providerId, display, domain, credential, fetcher, context } = args;
104
- const authState = typeof context?.auth_state === "object" && context?.auth_state !== null
105
- ? (context.auth_state as Record<string, unknown>)
106
- : undefined;
107
- const enterpriseId = typeof authState?.enterpriseId === "string" ? authState.enterpriseId : undefined;
108
- const clientVersion = providerId === "workbuddycn"
109
- ? getWorkBuddyCnClientVersion()
110
- : getWorkBuddyClientVersion();
111
- // The reference bills the CN realm on `www.codebuddy.cn`, not the chat host:
112
- // the billing realm is a different service from the one that serves chat,
113
- // and the CN chat host answers the meter path with an HTML error page.
114
- const billingBase = providerId === "workbuddycn" ? WORKBUDDY_CN_BILLING_BASE_URL : providerBaseUrl(providerId);
115
- return fetchTencentBillingQuota({
116
- source: providerId,
117
- display,
118
- url: `${billingBase}/v2/billing/meter/get-user-resource`,
119
- headers: await billingHeaders(domain, clientVersion, enterpriseId),
120
- credential,
121
- fetcher,
122
- defaultPlan: display,
123
- uid: buddyAccountUid(credential),
124
- });
125
- }
126
-
127
- /**
128
- * Real credit deductions for one WorkBuddy account.
129
- *
130
- * Mirrors {@link fetchWorkBuddyQuotaFor} in every respect but the endpoint —
131
- * same billing host, same client-version identity headers, same account UID —
132
- * because the usage-detail surface is the billing meter's other read.
133
- */
134
- export async function fetchWorkBuddyRequestUsage(
135
- credential: string,
136
- fetcher: FetchLike,
137
- args: {
138
- readonly providerId?: "workbuddy" | "workbuddycn";
139
- readonly days?: number;
140
- readonly context?: QuotaCollectionContext;
141
- } = {},
142
- ): Promise<BuddyUsageResult> {
143
- const providerId = args.providerId ?? "workbuddy";
144
- const domain = providerId === "workbuddycn" ? "www.workbuddy.cn" : WORKBUDDY_DOMAIN;
145
- const authState = typeof args.context?.auth_state === "object" && args.context?.auth_state !== null
146
- ? (args.context.auth_state as Record<string, unknown>)
147
- : undefined;
148
- const enterpriseId = typeof authState?.enterpriseId === "string" ? authState.enterpriseId : undefined;
149
- const clientVersion = providerId === "workbuddycn"
150
- ? getWorkBuddyCnClientVersion()
151
- : getWorkBuddyClientVersion();
152
- return fetchBuddyRequestUsage({
153
- url: `${providerBaseUrl(providerId)}/billing/meter/get-user-request-usage`,
154
- headers: await billingHeaders(domain, clientVersion, enterpriseId),
155
- credential,
156
- fetcher,
157
- days: args.days ?? 30,
158
- uid: buddyAccountUid(credential),
159
- });
160
- }
161
-
@@ -1,285 +0,0 @@
1
- import { createHash } from "node:crypto";
2
- import { readFileSync } from "node:fs";
3
-
4
- import type { OpenAICompatibleAdapterConfig } from "../../../adapters/compatible-adapter";
5
- import { withBearerAuthentication } from "../../../adapters/compatible-adapter";
6
- import type { CanonicalRequest } from "../../../../protocol/canonical-model";
7
- import type { ProviderDispatchContext, ProviderDispatchTarget, ProviderId } from "../../../provider-contracts";
8
- import { resolveInboundSessionId } from "../../../operations/session-resolution";
9
- import { buddyConversationHeaders } from "../buddy-conversation-headers";
10
- import { buddyCliHeaders, buddyCliTraceHeaders } from "../buddy-cli-headers";
11
- import {
12
- buddyAgentPurpose,
13
- buddyEnterprise,
14
- buddyOAuthIdentityHeaders,
15
- buddyPrivateData,
16
- buddyUserId,
17
- resolveBuddyDeviceBinding,
18
- resolveBuddyIdentity,
19
- } from "../buddy-identity";
20
- import {
21
- buildWorkBuddyUserAgent,
22
- getWorkBuddyClientVersion,
23
- getWorkBuddyCliVersion,
24
- } from "../../../operations/client-versions";
25
- import {
26
- getTuringDeviceTokenService,
27
- resolveTuringSdkRoot,
28
- type TuringSdkConfig,
29
- WORKBUDDY_TURING_CONFIG,
30
- } from "../turing-device-token";
31
-
32
- /**
33
- * WorkBuddy serves chat from a versioned path on a base URL that carries no
34
- * version segment (billing uses the unversioned `/billing/…` path), so both the
35
- * adapter config and the static catalog rows must state it. The generic
36
- * `/chat/completions` default would join into
37
- * `https://www.workbuddy.ai/chat/completions`, which that upstream answers with
38
- * a 405 HTML error page.
39
- */
40
- export const WORKBUDDY_CHAT_PATH = "/v2/chat/completions" as const;
41
-
42
- export {
43
- buildWorkBuddyUserAgent,
44
- getWorkBuddyClientVersion,
45
- getWorkBuddyCliVersion,
46
- };
47
-
48
- /** WorkBuddy international gateway domain (Origin/Referer/X-Domain). */
49
- export const WORKBUDDY_DOMAIN = "www.workbuddy.ai";
50
-
51
- /**
52
- * Stable per-account device identifiers.
53
- *
54
- * WorkBuddy's desktop client presents one fixed virtual device per account.
55
- * Deriving `X-Machine-ID` / `X-Session-ID` from the account id (sha256, 36 hex)
56
- * keeps them constant across restarts while staying distinct per account, so
57
- * multiple pooled accounts are not correlated by a missing or drifting device
58
- * fingerprint. Mirrors the reference gateway's `wb2a:<purpose>:<uid>` scheme.
59
- */
60
- function deriveAccountStableId(accountId: string, purpose: string): string {
61
- const sum = createHash("sha256").update(`wb2a:${purpose}:${accountId}`).digest("hex");
62
- return sum.slice(0, 36);
63
- }
64
-
65
- /**
66
- * Per-request WorkBuddy chat headers — the exact desktop-client contract.
67
- *
68
- * The international gateway gates chat on the desktop `User-Agent` (platform
69
- * brand `WorkBuddy AI`, carried on the wire as the token `workbuddy-ai`;
70
- * the wrong token trips 403 code 11140), plus the `X-CodeBuddy-Request` risk
71
- * gate and the account-scoped device headers.
72
- * The background client-version monitor keeps this value fresh; dispatch only
73
- * reads the cached value and never waits on a version endpoint.
74
- *
75
- * `cliIdentity` selects the reference CLI contract instead. The two are not
76
- * variations of one set: the CLI drops every browser header and the device
77
- * token, and adds the agent envelope. Left unset, nothing changes.
78
- */
79
- export async function workbuddyHeaders(
80
- context?: ProviderDispatchContext,
81
- request?: CanonicalRequest,
82
- domain = WORKBUDDY_DOMAIN,
83
- clientVersion = getWorkBuddyClientVersion(),
84
- cliIdentity?: boolean,
85
- ): Promise<Record<string, string>> {
86
- const identity = resolveBuddyIdentity(context, cliIdentity);
87
- const conversation = buddyConversationHeaders({
88
- ...(resolveInboundSessionId(context, request) === undefined
89
- ? {}
90
- : { conversationId: resolveInboundSessionId(context, request) }),
91
- // The reference emits dashed-UUID message/request ids on the WorkBuddy
92
- // desktop product and 32-hex on CLI traffic (build_attempt_headers converts
93
- // only the message/request ids, and only for the WorkBuddy profiles).
94
- messageIdStyle: identity === "desktop" ? "uuid" : "hex",
95
- });
96
- const accountId = context?.credential.account_id;
97
- const purpose = buddyAgentPurpose(context, request);
98
- if (identity === "cli") {
99
- const inbound = context?.request_headers;
100
- const rootRequestId = inbound?.["x-root-request-id"]?.trim();
101
- const parentConversationId = inbound?.["x-parent-conversation-id"]?.trim();
102
- // The reference CLI: issued by the OpenAI Node SDK, so no browser
103
- // *transport* header (origin/referer/accept-language) and no device token,
104
- // and the machine/session device pair does not exist — only `X-User-Id`,
105
- // which is `anonymous` without a uid. It keeps the request-shape markers
106
- // (`x-requested-with`, `x-codebuddy-request`) the reference sends on every
107
- // call regardless of transport.
108
- return {
109
- accept: "application/json",
110
- "user-agent": `CLI/${getWorkBuddyCliVersion()} CodeBuddy/${getWorkBuddyCliVersion()}`,
111
- "x-requested-with": "XMLHttpRequest",
112
- "x-codebuddy-request": "1",
113
- "x-domain": domain,
114
- ...(purpose === undefined ? {} : { "x-agent-purpose": purpose }),
115
- "x-ide-name": "CLI",
116
- "x-ide-type": "CLI",
117
- "x-ide-version": getWorkBuddyCliVersion(),
118
- "x-product": "SaaS",
119
- "x-no-enterprise-id": "1",
120
- ...conversation,
121
- ...(rootRequestId === undefined ? {} : { "x-root-request-id": rootRequestId }),
122
- ...(parentConversationId === undefined
123
- ? {}
124
- : { "x-parent-conversation-id": parentConversationId }),
125
- ...buddyCliTraceHeaders(conversation),
126
- ...buddyOAuthIdentityHeaders(context),
127
- ...buddyCliHeaders({
128
- userId: buddyUserId(context),
129
- enterpriseId: buddyEnterprise(context),
130
- privateData: buddyPrivateData(context),
131
- }),
132
- };
133
- }
134
- const headers: Record<string, string> = {
135
- accept: "application/json, text/event-stream",
136
- "user-agent": buildWorkBuddyUserAgent(clientVersion, getWorkBuddyCliVersion()),
137
- origin: `https://${domain}`,
138
- referer: `https://${domain}/`,
139
- "accept-language": "en-US",
140
- "x-requested-with": "XMLHttpRequest",
141
- "x-codebuddy-request": "1",
142
- "x-domain": domain,
143
- ...(purpose === undefined ? {} : { "x-agent-purpose": purpose }),
144
- "x-ide-name": "WorkBuddy",
145
- "x-ide-type": "WorkBuddy",
146
- "x-ide-version": clientVersion,
147
- // Both references send the literal `SaaS` here. `WorkBuddy` was a value
148
- // this repo invented; the desktop product name belongs in `x-ide-name`,
149
- // and the CN test below compares the two realms against each other rather
150
- // than to a hard-coded string.
151
- "x-product": "SaaS",
152
- // Personal international accounts carry no enterprise id: declare it
153
- // explicitly so upstream risk control does not treat the omission as
154
- // suspicious.
155
- "x-no-enterprise-id": "1",
156
- };
157
- // The conversation/tracing family the upstream's channel check looks for. A
158
- // live request carrying only `x-session-id` was refused for a missing
159
- // conversation id; the aggregation key below is the one the reference marks
160
- // mandatory.
161
- Object.assign(headers, conversation);
162
- if (accountId) {
163
- headers["x-user-id"] = accountId;
164
- headers["x-machine-id"] = deriveAccountStableId(accountId, "machine");
165
- headers["x-session-id"] = deriveAccountStableId(accountId, "session");
166
- }
167
- // Per-account device binding: distinct device identity per account (see
168
- // resolveBuddyDeviceBinding). Sent as the desktop's X-Device-Id-List.
169
- const binding = resolveBuddyDeviceBinding(context);
170
- if (binding !== undefined) {
171
- headers["x-device-id-list"] = JSON.stringify({ qimei36: binding });
172
- }
173
- Object.assign(headers, await buddyDeviceTokenHeaders({
174
- realm: domain.endsWith(".cn") ? "cn" : "intl",
175
- context,
176
- cliIdentity,
177
- }));
178
- return headers;
179
- }
180
-
181
- /**
182
- * Desktop risk token, sent only when the account actually has one.
183
- *
184
- * The account's own `auth_state` wins. When it carries none, a file the
185
- * desktop client writes (`CARTETHYIA_DEVICE_TOKEN_FILE`, default
186
- * `/app/data/device_token`) is read instead — cached for five minutes, and
187
- * ignored when it is larger than 1 KB, because a token file that size is not
188
- * a token. A missing file is the normal case and reads as "no token".
189
- */
190
- const DEVICE_TOKEN_FILE_MAX_BYTES = 1024;
191
- const DEVICE_TOKEN_FILE_TTL_MS = 5 * 60_000;
192
- let deviceTokenFileCache: { readonly value: string | undefined; readonly readAt: number } | undefined;
193
-
194
- export function readBuddyDeviceToken(context?: ProviderDispatchContext): string | undefined {
195
- const state = context?.credential.auth_state;
196
- const value = state?.["deviceToken"] ?? state?.["device_token"];
197
- if (typeof value === "string" && value.trim().length > 0) return value.trim();
198
- return readDeviceTokenFile();
199
- }
200
-
201
- /**
202
- * The reference `X-Device-Token` pair, per the official desktop app.
203
- *
204
- * The desktop client (WorkBuddyAI, channel 400111) always presents one of the
205
- * two on chat traffic — a real token from the TuringShield SDK, or an
206
- * `X-Device-Token-Error` when the SDK cannot produce one. It never omits both,
207
- * and it sends the header on every realm (Intl and CN alike). The SDK is a
208
- * proprietary native addon; when it is not configured we fall back to a
209
- * captured token (auth_state / `CARTETHYIA_DEVICE_TOKEN_FILE`) and only then
210
- * to the official failure state.
211
- *
212
- * - `CARTETHYIA_TURING_SDK_PATH` → real token via `TuringDeviceTokenService`.
213
- * - Legacy token (auth_state/file) → used when the SDK is unavailable.
214
- * - CLI identity never carries a device token (the CLI has no device).
215
- */
216
- export async function buddyDeviceTokenHeaders(args: {
217
- realm: "intl" | "cn";
218
- context: ProviderDispatchContext | undefined;
219
- cliIdentity: boolean | undefined;
220
- turingConfig?: TuringSdkConfig;
221
- }): Promise<Record<string, string>> {
222
- const { context, cliIdentity, turingConfig } = args;
223
- void args.realm; // the desktop client sends the token on both realms
224
- if (resolveBuddyIdentity(context, cliIdentity) === "cli") return {};
225
- // Native SDK first (real token), when configured.
226
- if (resolveTuringSdkRoot() !== null) {
227
- const sdkHeaders = await getTuringDeviceTokenService(turingConfig ?? WORKBUDDY_TURING_CONFIG).headersForRequest(false);
228
- if (sdkHeaders["x-device-token"] !== undefined) return sdkHeaders;
229
- // SDK configured but could not produce a token: mirror its failure state,
230
- // like the desktop client does — do not fall back to a stale file token.
231
- return sdkHeaders;
232
- }
233
- // No SDK on this deployment: a captured token is better than nothing.
234
- const token = readBuddyDeviceToken(context);
235
- if (token !== undefined) return { "x-device-token": token };
236
- return { "x-device-token-error": "sdk_not_initialized" };
237
- }
238
-
239
- function readDeviceTokenFile(): string | undefined {
240
- const now = Date.now();
241
- if (deviceTokenFileCache !== undefined && now - deviceTokenFileCache.readAt < DEVICE_TOKEN_FILE_TTL_MS) {
242
- return deviceTokenFileCache.value;
243
- }
244
- const path = process.env["CARTETHYIA_DEVICE_TOKEN_FILE"] ?? "/app/data/device_token";
245
- let value: string | undefined;
246
- try {
247
- const raw = readFileSync(path);
248
- if (raw.byteLength > 0 && raw.byteLength <= DEVICE_TOKEN_FILE_MAX_BYTES) {
249
- const text = raw.toString("utf8").trim();
250
- if (text.length > 0) value = text;
251
- }
252
- } catch {
253
- value = undefined;
254
- }
255
- deviceTokenFileCache = { value, readAt: now };
256
- return value;
257
- }
258
-
259
- /**
260
- * Shared OpenAI-compatible chat-adapter config for WorkBuddy: bearer auth
261
- * (api_key and oauth both use `Authorization: Bearer`), `/v2/chat/completions`
262
- * endpoint, per-request desktop-client headers, and the payload hook.
263
- */
264
- export function workbuddyAdapterConfig(args: {
265
- providerId: ProviderId;
266
- baseUrl: string;
267
- domain?: string;
268
- prePayload: (
269
- payload: Record<string, unknown>,
270
- request: CanonicalRequest,
271
- candidate: ProviderDispatchTarget,
272
- ) => void;
273
- fetchImpl?: typeof fetch;
274
- cliIdentity?: boolean;
275
- }): OpenAICompatibleAdapterConfig {
276
- return withBearerAuthentication({
277
- provider_id: args.providerId,
278
- base_url: args.baseUrl,
279
- endpoint_paths_by_wire_family: { chat: WORKBUDDY_CHAT_PATH },
280
- buildExtraHeaders: (context, request) =>
281
- workbuddyHeaders(context, request, args.domain ?? WORKBUDDY_DOMAIN, undefined, args.cliIdentity),
282
- prePayload: args.prePayload,
283
- ...(args.fetchImpl ? { fetchImpl: args.fetchImpl } : {}),
284
- });
285
- }