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
@@ -168,10 +168,11 @@ export function normalizeBuddyToolNames(payload: Record<string, unknown>): void
168
168
  * Both realms have a "let the backend choose" id, and the reference rewrites
169
169
  * `auto` onto it before anything downstream keys on the name — so eligibility,
170
170
  * cooldowns and the catalog all see one id. CN's is `default`; intl's is
171
- * `default-model`.
171
+ * `default-model` (confirmed from live CLI session logs, which send
172
+ * `model=default-model` for the intl auto path).
172
173
  */
173
174
  const BUDDY_AUTO_TARGET: Readonly<Record<"intl" | "cn", string>> = {
174
- intl: "auto",
175
+ intl: "default-model",
175
176
  cn: "default",
176
177
  };
177
178
 
@@ -348,8 +349,8 @@ const DSH_MINIMAL_PATTERN = buddyTemplatePattern("You are a helpful software eng
348
349
  const DSH_DIRECT_PATTERN = buddyTemplatePattern("You are DeepSeek Harness");
349
350
  const DSH_WEB_GUI_PATTERN = buddyTemplatePattern("DeepSeek Harness Web GUI");
350
351
 
351
- /** The identity DSH role prompts are rewritten to; matches the donor gateway. */
352
- const DSH_WORKBUDDY_IDENTITY = "You are WorkBuddy, a powerful AI assistant";
352
+ /** The identity DSH role prompts are rewritten to; neutral and minimal. */
353
+ const DSH_WORKBUDDY_IDENTITY = "You are a helpful assistant";
353
354
 
354
355
  /**
355
356
  * Rewrites DeepSeek Harness role identities in one message's text back to the
@@ -425,6 +426,20 @@ export const clineReasoningReplayPrepares: readonly ((
425
426
  },
426
427
  ];
427
428
 
429
+ /**
430
+ * The reference injects `cache_retention` on every chat body: `long` by
431
+ * default, `short` when prompt caching for 1h is disabled
432
+ * (`CODEBUDDY_DISABLE_PROMPT_CACHING_1H`). Matching the client keeps the
433
+ * upstream's prompt-caching behavior and price on the same path the CLI uses.
434
+ */
435
+ function injectBuddyCacheRetention(payload: Record<string, unknown>): void {
436
+ if (payload["cache_retention"] !== undefined) return;
437
+ const disabled =
438
+ process.env.CODEBUDDY_DISABLE_PROMPT_CACHING_1H?.trim() === "1" ||
439
+ process.env.CODEBUDDY_DISABLE_PROMPT_CACHING_1H?.trim().toLowerCase() === "true";
440
+ payload["cache_retention"] = disabled ? "short" : "long";
441
+ }
442
+
428
443
  /**
429
444
  * Payload prefix shared by the buddy pre-payload hooks: force `stream=true`,
430
445
  * apply the provider's DeepSeek thinking contract, opt `reasoning_summary` in
@@ -437,6 +452,7 @@ export function buddyPrePayloadCommon(
437
452
  context?: ProviderDispatchContext,
438
453
  ): void {
439
454
  injectBuddyPromptCacheKey(payload, request, context);
455
+ injectBuddyCacheRetention(payload);
440
456
  // `auto` and `default-model` are the same upstream model under two names, and
441
457
  // the reference resolves one to the other everywhere — catalog, eligibility,
442
458
  // cooldown keys. Treating them as two independent rows meant a client that
@@ -3,51 +3,19 @@
3
3
  *
4
4
  * Everything here comes from the two reference gateways, which agree: the
5
5
  * desktop product sends conversation/tracing headers and a device token, while
6
- * the CLI sends the agent envelope plus the OpenAI Node SDK fingerprint. The
7
- * CLI still drops the browser *transport* headers (`origin`, `referer`,
8
- * `accept-language`) and the device token, but keeps the request-shape markers
9
- * (`x-requested-with`, `x-codebuddy-request`) the reference sends on every call
10
- * regardless of transport — see the CLI branches in each provider's
11
- * `*-shared.ts`.
6
+ * the CLI sends the agent envelope. The CLI still drops the browser *transport*
7
+ * headers (`origin`, `referer`, `accept-language`) and the device token, but
8
+ * keeps the request-shape markers (`x-requested-with`, `x-codebuddy-request`)
9
+ * the reference sends on every call regardless of transport — see the CLI
10
+ * branches in each provider's `*-shared.ts`.
12
11
  *
13
- * The SDK fingerprint is pinned, not host-derived. Both references pin a fixed
14
- * set (codebuddy2api pins Linux/x64/v24.21.0); this gateway pins the macOS set
15
- * instead, so every CLI dispatch presents one consistent client fingerprint no
16
- * matter which machine the gateway runs on. A host-derived fingerprint would
17
- * advertise whatever OS the process happens to run under — a value no upstream
18
- * risk model has seen for this client brand, and an easy outlier to key on.
12
+ * The CLI's cloud chat transport is axios (`RestOperations`), not the OpenAI
13
+ * Node SDK, so it sends **no** `x-stainless-*` fingerprint. The reference's
14
+ * chat request helper sets only `Content-Type`, `Accept`, and `Authorization`
15
+ * before the conversation/agent/identity headers are injected; the stainless
16
+ * set belongs to the SDK-backed secondary clients, not to CodeBuddy chat.
19
17
  */
20
18
 
21
- /** OpenAI Node SDK 6.25.0 `x-stainless-*` fingerprint; both references agree. */
22
- const STAINLESS_PACKAGE_VERSION = "6.25.0";
23
-
24
- /**
25
- * The pinned Node runtime the fingerprint claims. Held constant across
26
- * dispatches: a drifting `process.version` would advertise a different Node
27
- * build per deployment, which is not what one installed client looks like.
28
- */
29
- const STAINLESS_RUNTIME_VERSION = "v24.21.0";
30
-
31
- /**
32
- * The SDK fingerprint headers.
33
- *
34
- * `x-stainless-timeout` is in the hub only and `x-stainless-retry-count` is in
35
- * both; the SDK sends both, so both go out. The OS/arch pair is the pinned
36
- * macOS fingerprint rather than this process's host.
37
- */
38
- export function buddyStainlessHeaders(): Record<string, string> {
39
- return {
40
- "x-stainless-lang": "js",
41
- "x-stainless-package-version": STAINLESS_PACKAGE_VERSION,
42
- "x-stainless-os": "MacOS",
43
- "x-stainless-arch": "x64",
44
- "x-stainless-runtime": "node",
45
- "x-stainless-runtime-version": STAINLESS_RUNTIME_VERSION,
46
- "x-stainless-retry-count": "0",
47
- "x-stainless-timeout": "1200",
48
- };
49
- }
50
-
51
19
  /**
52
20
  * The trace family the CLI carries as a child span.
53
21
  *
@@ -69,13 +37,18 @@ export function buddyCliTraceHeaders(
69
37
  /**
70
38
  * The full CLI identity envelope, minus what each caller already supplies.
71
39
  *
72
- * The caller keeps ownership of `User-Agent`, `X-IDE-*`, `X-Domain`, and the
73
- * conversation family, because those vary by provider and realm: only the
74
- * headers that are the same for every CLI dispatch are built here.
40
+ * The caller keeps ownership of `User-Agent`, `X-IDE-*`, `X-Domain`, the
41
+ * conversation family, and the OAuth identity headers; only the headers that
42
+ * are the same for every CLI dispatch are built here.
43
+ *
44
+ * No `x-stainless-*` fingerprint: the CLI's chat transport is axios, not the
45
+ * OpenAI Node SDK. `X-Private-Data` is added by the caller only when the
46
+ * dispatch is actually private — the reference never sends it as `false`.
75
47
  */
76
48
  export function buddyCliHeaders(args: {
77
49
  readonly userId: string;
78
50
  readonly enterpriseId?: string | undefined;
51
+ readonly privateData?: boolean;
79
52
  }): Record<string, string> {
80
53
  const enterpriseId =
81
54
  args.enterpriseId !== undefined && args.enterpriseId.trim().length > 0
@@ -89,12 +62,7 @@ export function buddyCliHeaders(args: {
89
62
  // of the three, so "other" is the honest value rather than a guess.
90
63
  "X-Agent-Runtime": "other",
91
64
  "X-User-Id": args.userId,
92
- // The reference sends the flag either way, `true` only for an enterprise
93
- // id. A personal account stays `false`; an enterprise account flips to
94
- // `true` and names the enterprise, because the two travel together — a
95
- // `true` with no id, or an id under `false`, is a combination no real
96
- // client produces.
97
- "X-Private-Data": enterpriseId === undefined ? "false" : "true",
65
+ ...(args.privateData === true ? { "X-Private-Data": "true" } : {}),
98
66
  ...(enterpriseId === undefined
99
67
  ? {}
100
68
  : {
@@ -104,6 +72,5 @@ export function buddyCliHeaders(args: {
104
72
  // reads both.
105
73
  "X-Tenant-Id": enterpriseId,
106
74
  }),
107
- ...buddyStainlessHeaders(),
108
75
  };
109
76
  }
@@ -1,6 +1,8 @@
1
1
  import type { ProviderDispatchContext } from "../../provider-contracts";
2
2
  import { createHash } from "node:crypto";
3
3
  import { decodeJwtPayload } from "../../authentication/oauth-flow-store";
4
+ import { buddyAccountUid } from "./buddy-oauth-shared";
5
+ import type { CanonicalRequest } from "../../../protocol/canonical-model";
4
6
 
5
7
  /**
6
8
  * Which upstream client a buddy provider presents itself as.
@@ -41,8 +43,17 @@ export function resolveBuddyIdentity(
41
43
  * The reference CLI sends the literal `anonymous` when it has no uid rather
42
44
  * than omitting the header, so an unauthenticated dispatch still looks like a
43
45
  * client rather than like a caller that forgot a header.
46
+ *
47
+ * When the credential carries a JWT, the `sub` claim is the upstream uid and
48
+ * wins over the gateway's internal account id — the two can differ after an
49
+ * import, and the channel check keys on the upstream identity. Opaque API keys
50
+ * carry no identity, so the internal account id is the fallback.
44
51
  */
45
52
  export function buddyUserId(context?: ProviderDispatchContext): string {
53
+ const secret = context?.credential?.secret;
54
+ const token = secret ? new TextDecoder().decode(secret).trim() : "";
55
+ const uid = buddyAccountUid(token);
56
+ if (uid !== undefined) return uid;
46
57
  const accountId = context?.credential.account_id;
47
58
  return accountId !== undefined && accountId.length > 0 ? accountId : "anonymous";
48
59
  }
@@ -142,3 +153,78 @@ export function materializeBuddyDeviceBinding(
142
153
  const derived = createHash("sha256").update(`wb2a:qimei36:${accountId}`).digest("hex").slice(0, 32);
143
154
  return { ...(authState ?? {}), qimei36: derived };
144
155
  }
156
+
157
+ /**
158
+ * The OAuth identity header family the reference ships on every cloud API call
159
+ * (`runIdentityHeaders`): `X-User-Id` plus the base64 `X-Userinfo` envelope and
160
+ * the auth-method / id-source markers.
161
+ *
162
+ * The JWT `sub` is the uid; the base64 envelope mirrors the reference exactly:
163
+ * `{ uin, owner_uin?, id_source?, token_source? }` — one leg per identity
164
+ * field that exists, so a personal account sends `{uin}` while an enterprise
165
+ * account adds `owner_uin`. `X-Auth-Method` / `X-Id-Source` are only sent when
166
+ * the operator pinned them in `auth_state` (there is no reliable source to
167
+ * invent them from). An opaque API key carries no uid and yields nothing.
168
+ */
169
+ export function buddyOAuthIdentityHeaders(
170
+ context?: ProviderDispatchContext,
171
+ ): Record<string, string> {
172
+ const secret = context?.credential?.secret;
173
+ const token = secret ? new TextDecoder().decode(secret).trim() : "";
174
+ const uid = buddyAccountUid(token) ?? context?.credential.account_id ?? "";
175
+ if (uid.length === 0) return {};
176
+ const enterpriseId = buddyEnterprise(context);
177
+ const state = context?.credential.auth_state;
178
+ const idSource =
179
+ typeof state?.["idSource"] === "string" && (state["idSource"] as string).trim().length > 0
180
+ ? (state["idSource"] as string).trim()
181
+ : undefined;
182
+ const method =
183
+ typeof state?.["authMethod"] === "string" && (state["authMethod"] as string).trim().length > 0
184
+ ? (state["authMethod"] as string).trim()
185
+ : undefined;
186
+ const headers: Record<string, string> = { "X-User-Id": uid };
187
+ if (method !== undefined) headers["X-Auth-Method"] = method;
188
+ if (idSource !== undefined) headers["X-Id-Source"] = idSource;
189
+ if (enterpriseId !== undefined || idSource !== undefined || method !== undefined) {
190
+ const info: Record<string, string> = { uin: uid };
191
+ if (enterpriseId !== undefined) info["owner_uin"] = enterpriseId;
192
+ if (idSource !== undefined) info["id_source"] = idSource;
193
+ if (method !== undefined) info["token_source"] = method;
194
+ headers["X-Userinfo"] = Buffer.from(JSON.stringify(info), "utf-8").toString("base64");
195
+ }
196
+ return headers;
197
+ }
198
+
199
+ /**
200
+ * Whether this dispatch is in the reference's private-data mode. The CLI only
201
+ * sends `X-Private-Data: true` while the session is private; otherwise the
202
+ * header is deleted, never sent as `false`. The gateway has no session-level
203
+ * private flag, so the operator pins one per account in `auth_state.privateData`.
204
+ */
205
+ export function buddyPrivateData(context?: ProviderDispatchContext): boolean {
206
+ return context?.credential.auth_state?.["privateData"] === true;
207
+ }
208
+
209
+ /**
210
+ * The effective agent purpose for one dispatch, matching the reference's
211
+ * `getEffectiveAgentPurpose` behavior as closely as the gateway can:
212
+ *
213
+ * - `PERSONAL_AGENT_ROLE` set → `person_agent` (same env the CLI reads);
214
+ * - otherwise an inbound `x-agent-purpose` header is preserved (the caller
215
+ * already stated a purpose — same shape the reference passes through);
216
+ * - otherwise the header is omitted. The reference does not invent `conversation`.
217
+ */
218
+ export function buddyAgentPurpose(
219
+ context?: ProviderDispatchContext,
220
+ request?: CanonicalRequest,
221
+ ): string | undefined {
222
+ if (process.env.PERSONAL_AGENT_ROLE && process.env.PERSONAL_AGENT_ROLE.trim().length > 0) {
223
+ return "person_agent";
224
+ }
225
+ const inbound = context?.request_headers?.["x-agent-purpose"]?.trim();
226
+ if (inbound !== undefined && inbound.length > 0) return inbound;
227
+ const fromRequest = request?.metadata?.["agent_purpose"];
228
+ if (typeof fromRequest === "string" && fromRequest.trim().length > 0) return fromRequest.trim();
229
+ return undefined;
230
+ }
@@ -120,7 +120,7 @@ export function buddyAccountUid(accessToken: string): string | undefined {
120
120
  * Falls back to `undefined` when the token carries no usable identity, letting
121
121
  * the console keep the operator-supplied label.
122
122
  */
123
- export function buddyAccountLabel(accessToken: string): string | undefined {
123
+ function buddyAccountLabel(accessToken: string): string | undefined {
124
124
  const claims = decodeJwtPayload(accessToken);
125
125
  if (!claims) return undefined;
126
126
  const email = nonEmptyTrimmedString(claims.email) ?? nonEmptyTrimmedString(claims.preferred_username);
@@ -48,8 +48,7 @@ function isAgentPromptText(text: string): boolean {
48
48
  );
49
49
  }
50
50
 
51
- const CODEBUDDY_CN_NEUTRAL_PROMPT =
52
- "You are a helpful AI assistant that helps with software engineering tasks.";
51
+ const CODEBUDDY_CN_NEUTRAL_PROMPT = "You are a helpful assistant.";
53
52
 
54
53
  function flattenContent(content: unknown): string {
55
54
  if (typeof content === "string") return content;
@@ -51,22 +51,11 @@ export const CODEBUDDY_BASE_URL = providerBaseUrl("cb");
51
51
  *
52
52
  * The wire contract is that the request *opens* with a `system` turn (code
53
53
  * `11128`); the gateway replaces any caller `system`/`developer` turn with this
54
- * fixed prompt. The text is the CodeBuddy CLI's own leading prompt — the same
55
- * one the reference client (and the donor gateway's `prepend` prompt mode)
56
- * sends — so a proxied request is byte-faithful to an official client rather
57
- * than a neutral stand-in.
58
- *
59
- * Keeping the official identity is forward-compatible: the upstream is not
60
- * observed to validate this text today, but a proxy that claims the real
61
- * client's identity cannot be caught out if it starts to. A previous neutral
62
- * persona ("You are a pragmatic and direct software engineering assistant…")
63
- * worked, but diverged from every request the official CLI emits.
54
+ * fixed prompt. Deliberately neutral: a simple helpful-assistant persona with
55
+ * no client/CLI branding, kept minimal so the text reads naturally to any
56
+ * model and does not advertise a channel identity upstream.
64
57
  */
65
- export const CODEBUDDY_SYSTEM_PROMPT =
66
- "You are CodeBuddy Code.\n\n" +
67
- "You are an interactive CLI tool that helps users with software engineering tasks. " +
68
- "Use the instructions below and the tools available to you to assist the user. " +
69
- "Your main goal is to follow the USER's instructions at each message, denoted by the <user_query> tag.";
58
+ export const CODEBUDDY_SYSTEM_PROMPT = "You are a helpful assistant.";
70
59
 
71
60
  function codeBuddyIntlPrePayload(
72
61
  payload: Record<string, unknown>,
@@ -3,7 +3,15 @@ import type { CanonicalRequest } from "../../../../protocol/canonical-model";
3
3
  import type { ProviderDispatchContext, ProviderDispatchTarget, ProviderId } from "../../../provider-contracts";
4
4
  import { resolveInboundSessionId } from "../../../operations/session-resolution";
5
5
  import { buddyConversationHeaders } from "../buddy-conversation-headers";
6
- import { buddyEnterprise, buddyUserId, resolveBuddyDeviceBinding, resolveBuddyIdentity } from "../buddy-identity";
6
+ import {
7
+ buddyAgentPurpose,
8
+ buddyEnterprise,
9
+ buddyOAuthIdentityHeaders,
10
+ buddyPrivateData,
11
+ buddyUserId,
12
+ resolveBuddyDeviceBinding,
13
+ resolveBuddyIdentity,
14
+ } from "../buddy-identity";
7
15
  import { buildCodeBuddyUserAgent, getCodeBuddyCnVersion, getCodeBuddyVersion } from "../../../operations/client-versions";
8
16
  import { buddyDeviceTokenHeaders } from "../workbuddy/shared";
9
17
  import { CODEBUDDY_TURING_CONFIG } from "../turing-device-token";
@@ -40,6 +48,13 @@ export async function codebuddyHeaders(
40
48
  ...(conversationId === undefined ? {} : { conversationId }),
41
49
  });
42
50
  if (resolveBuddyIdentity(context, cliIdentity) === "cli") {
51
+ const purpose = buddyAgentPurpose(context, request);
52
+ // Root/parent conversation context is forwarded only when the caller
53
+ // actually supplied it — the reference emits these conditionally for
54
+ // subagent/root chains and never invents them.
55
+ const inbound = context?.request_headers;
56
+ const rootRequestId = inbound?.["x-root-request-id"]?.trim();
57
+ const parentConversationId = inbound?.["x-parent-conversation-id"]?.trim();
43
58
  return {
44
59
  // The CLI sends `Accept: application/json` and no device token. It keeps
45
60
  // the request-shape markers (`X-Requested-With`, `X-CodeBuddy-Request`)
@@ -55,19 +70,24 @@ export async function codebuddyHeaders(
55
70
  "X-Domain": codebuddyDomain(variant),
56
71
  "x-requested-with": "XMLHttpRequest",
57
72
  "x-codebuddy-request": "1",
58
- // The conversation purpose the reference client states. Not required —
59
- // verified against the live API that a request succeeds without it — but
60
- // it is part of the client's real request, and matching the client is the
61
- // defence against a channel check tightening later.
62
- "X-Agent-Purpose": "conversation",
73
+ ...(purpose === undefined ? {} : { "X-Agent-Purpose": purpose }),
63
74
  ...conversation,
75
+ ...(rootRequestId === undefined ? {} : { "X-Root-Request-ID": rootRequestId }),
76
+ ...(parentConversationId === undefined
77
+ ? {}
78
+ : { "X-Parent-Conversation-ID": parentConversationId }),
64
79
  ...buddyCliTraceHeaders(conversation),
80
+ // The CLI's OAuth identity family: X-User-Id from the JWT sub plus the
81
+ // base64 X-Userinfo envelope when identity fields exist.
82
+ ...buddyOAuthIdentityHeaders(context),
65
83
  ...buddyCliHeaders({
66
84
  userId: buddyUserId(context),
67
85
  enterpriseId: buddyEnterprise(context),
86
+ privateData: buddyPrivateData(context),
68
87
  }),
69
88
  };
70
89
  }
90
+ const purpose = buddyAgentPurpose(context, request);
71
91
  return {
72
92
  accept: "text/event-stream",
73
93
  "User-Agent": ua,
@@ -81,9 +101,10 @@ export async function codebuddyHeaders(
81
101
  "X-Domain": codebuddyDomain(variant),
82
102
  "x-requested-with": "XMLHttpRequest",
83
103
  "x-codebuddy-request": "1",
84
- // Same value the CLI branch sends, for the same reason: part of the
85
- // client's real request, harmless when the channel check does not read it.
86
- "X-Agent-Purpose": "conversation",
104
+ // The effective agent purpose, matching the reference's dynamic value.
105
+ // The reference does not invent `conversation`; it sends the purpose only
106
+ // when one exists.
107
+ ...(purpose === undefined ? {} : { "X-Agent-Purpose": purpose }),
87
108
  // Same family WorkBuddy sends: the upstream's channel check reads the
88
109
  // turn-level aggregation key, and a chat request without it is refused for a
89
110
  // missing conversation id.
@@ -56,15 +56,11 @@ export const WORKBUDDY_BASE_URL = providerBaseUrl("workbuddy");
56
56
  * channel"`. So this prompt is a wire contract, not merely a product choice —
57
57
  * see the sibling in `codebuddy.ts`.
58
58
  *
59
- * The text is WorkBuddy's own leading prompt, matching what the official client
60
- * (and the donor gateway's `prepend` prompt mode) sends, so a proxied request
61
- * carries the real client's identity instead of a neutral stand-in. A previous
62
- * neutral persona was accepted but diverged from every request the official
63
- * desktop client emits.
59
+ * The text is deliberately neutral: a simple helpful-assistant persona with no
60
+ * client/CLI branding, kept minimal so it reads naturally to any model and
61
+ * does not advertise a channel identity upstream.
64
62
  */
65
- export const WORKBUDDY_SYSTEM_PROMPT =
66
- "You are WorkBuddy, a powerful AI assistant.\n\n" +
67
- "Your main goal is to follow the USER's instructions at each message, denoted by the <user_query> tag.";
63
+ export const WORKBUDDY_SYSTEM_PROMPT = "You are a helpful assistant.";
68
64
 
69
65
  /**
70
66
  * Reconstructs generic function declarations when a later tool-history turn
@@ -156,7 +152,7 @@ export function workbuddyPrePayload(
156
152
  // declared reasoning-effort scale.
157
153
  const WORKBUDDY_RAW: readonly BuddyRawEntry[] = BUDDY_SHARED_RAW;
158
154
 
159
- export function makeWorkBuddyModels(providerId: "workbuddy" | "workbuddycn"): readonly ModelDefinition[] {
155
+ function makeWorkBuddyModels(providerId: "workbuddy" | "workbuddycn"): readonly ModelDefinition[] {
160
156
  return [
161
157
  ...WORKBUDDY_RAW.filter(
162
158
  (entry) => !BUDDY_IMAGE_MODEL_ID_SET.has(entry[0]) && !BUDDY_VIDEO_MODEL_ID_SET.has(entry[0]),
@@ -8,7 +8,15 @@ import type { ProviderDispatchContext, ProviderDispatchTarget, ProviderId } from
8
8
  import { resolveInboundSessionId } from "../../../operations/session-resolution";
9
9
  import { buddyConversationHeaders } from "../buddy-conversation-headers";
10
10
  import { buddyCliHeaders, buddyCliTraceHeaders } from "../buddy-cli-headers";
11
- import { buddyEnterprise, buddyUserId, resolveBuddyDeviceBinding, resolveBuddyIdentity } from "../buddy-identity";
11
+ import {
12
+ buddyAgentPurpose,
13
+ buddyEnterprise,
14
+ buddyOAuthIdentityHeaders,
15
+ buddyPrivateData,
16
+ buddyUserId,
17
+ resolveBuddyDeviceBinding,
18
+ resolveBuddyIdentity,
19
+ } from "../buddy-identity";
12
20
  import {
13
21
  buildWorkBuddyUserAgent,
14
22
  getWorkBuddyClientVersion,
@@ -86,7 +94,11 @@ export async function workbuddyHeaders(
86
94
  messageIdStyle: identity === "desktop" ? "uuid" : "hex",
87
95
  });
88
96
  const accountId = context?.credential.account_id;
97
+ const purpose = buddyAgentPurpose(context, request);
89
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();
90
102
  // The reference CLI: issued by the OpenAI Node SDK, so no browser
91
103
  // *transport* header (origin/referer/accept-language) and no device token,
92
104
  // and the machine/session device pair does not exist — only `X-User-Id`,
@@ -99,17 +111,23 @@ export async function workbuddyHeaders(
99
111
  "x-requested-with": "XMLHttpRequest",
100
112
  "x-codebuddy-request": "1",
101
113
  "x-domain": domain,
102
- "x-agent-purpose": "conversation",
114
+ ...(purpose === undefined ? {} : { "x-agent-purpose": purpose }),
103
115
  "x-ide-name": "CLI",
104
116
  "x-ide-type": "CLI",
105
117
  "x-ide-version": getWorkBuddyCliVersion(),
106
118
  "x-product": "SaaS",
107
119
  "x-no-enterprise-id": "1",
108
120
  ...conversation,
121
+ ...(rootRequestId === undefined ? {} : { "x-root-request-id": rootRequestId }),
122
+ ...(parentConversationId === undefined
123
+ ? {}
124
+ : { "x-parent-conversation-id": parentConversationId }),
109
125
  ...buddyCliTraceHeaders(conversation),
126
+ ...buddyOAuthIdentityHeaders(context),
110
127
  ...buddyCliHeaders({
111
128
  userId: buddyUserId(context),
112
129
  enterpriseId: buddyEnterprise(context),
130
+ privateData: buddyPrivateData(context),
113
131
  }),
114
132
  };
115
133
  }
@@ -122,7 +140,7 @@ export async function workbuddyHeaders(
122
140
  "x-requested-with": "XMLHttpRequest",
123
141
  "x-codebuddy-request": "1",
124
142
  "x-domain": domain,
125
- "x-agent-purpose": "conversation",
143
+ ...(purpose === undefined ? {} : { "x-agent-purpose": purpose }),
126
144
  "x-ide-name": "WorkBuddy",
127
145
  "x-ide-type": "WorkBuddy",
128
146
  "x-ide-version": clientVersion,