@cartanova/qgrid-cli 2.10.10 → 2.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (302) hide show
  1. package/bundle/dist/_virtual/_rolldown/runtime.js +1 -10
  2. package/bundle/dist/application/monit/log-buffer.js +12 -6
  3. package/bundle/dist/application/monit/monit.frame.js +11 -3
  4. package/bundle/dist/application/monit/monit.types.js +1 -1
  5. package/bundle/dist/application/qgrid/conv-routing.js +9 -6
  6. package/bundle/dist/application/qgrid/expired-token-reminder.js +2 -2
  7. package/bundle/dist/application/qgrid/oauth.js +31 -4
  8. package/bundle/dist/application/qgrid/qgrid-image-generation.js +1 -1
  9. package/bundle/dist/application/qgrid/qgrid-response-format.js +21 -19
  10. package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +40 -33
  11. package/bundle/dist/application/qgrid/qgrid.dispatcher.js +128 -93
  12. package/bundle/dist/application/qgrid/qgrid.frame.js +930 -49
  13. package/bundle/dist/application/qgrid/qgrid.types.js +212 -5
  14. package/bundle/dist/application/qgrid/schema-prompt.js +75 -48
  15. package/bundle/dist/application/qgrid/slack-user-map.js +1 -1
  16. package/bundle/dist/application/qgrid/token-death.js +1 -1
  17. package/bundle/dist/application/qgrid/token-subscriber.js +83 -30
  18. package/bundle/dist/application/qgrid/token-trigger-setup.js +1 -1
  19. package/bundle/dist/application/qgrid/token-window-keepalive.js +8 -6
  20. package/bundle/dist/application/qgrid/tool-emulation-schema.js +13 -13
  21. package/bundle/dist/application/qgrid/tool-emulation.js +19 -15
  22. package/bundle/dist/application/request-log/json-schema-type-text.js +29 -12
  23. package/bundle/dist/application/request-log/request-log.model.js +83 -70
  24. package/bundle/dist/application/request-log/request-log.types.js +1 -1
  25. package/bundle/dist/application/request-log/zod-code-format.js +1 -1
  26. package/bundle/dist/application/request-log-step/request-log-step.model.js +1 -1
  27. package/bundle/dist/application/request-log-step/request-log-step.types.js +1 -1
  28. package/bundle/dist/application/setting/setting.constant.js +1 -1
  29. package/bundle/dist/application/setting/setting.model.js +2 -2
  30. package/bundle/dist/application/setting/setting.store.js +2 -2
  31. package/bundle/dist/application/setting/setting.types.js +1 -1
  32. package/bundle/dist/application/sonamu.generated.js +32 -16
  33. package/bundle/dist/application/sonamu.generated.sso.js +1 -1
  34. package/bundle/dist/application/token/token.model.js +26 -9
  35. package/bundle/dist/application/token/token.types.js +20 -3
  36. package/bundle/dist/i18n/en.js +15 -1
  37. package/bundle/dist/i18n/ko.js +15 -1
  38. package/bundle/dist/i18n/sd.generated.js +1 -1
  39. package/bundle/dist/migrations/20260807133553_manual__backfill_request_log_cost.js +8 -6
  40. package/bundle/dist/server-bootstrap.js +4 -2
  41. package/bundle/dist/server-error-handler.js +1 -1
  42. package/bundle/dist/sonamu.config.js +37 -8
  43. package/bundle/dist/startup-migrations.js +17 -7
  44. package/bundle/dist/testing/global.js +1 -1
  45. package/bundle/dist/testing/schema-bench.js +0 -0
  46. package/bundle/dist/testing/test-database-name.js +1 -1
  47. package/bundle/dist/utils/providers/anthropic/anthropic-constants.js +1 -1
  48. package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +11 -5
  49. package/bundle/dist/utils/providers/anthropic/anthropic-quota.js +4 -4
  50. package/bundle/dist/utils/providers/anthropic/anthropic-thinking.js +1 -1
  51. package/bundle/dist/utils/providers/anthropic/claude-session.js +20 -19
  52. package/bundle/dist/utils/providers/anthropic/fence-strip.js +1 -1
  53. package/bundle/dist/utils/providers/anthropic/stream-json-adapter.js +49 -23
  54. package/bundle/dist/utils/providers/common/credentials.js +5 -1
  55. package/bundle/dist/utils/providers/common/effort.js +3 -3
  56. package/bundle/dist/utils/providers/common/model-cost.js +69 -14
  57. package/bundle/dist/utils/providers/common/provider-types.js +29 -1
  58. package/bundle/dist/utils/providers/common/schema-validation.js +78 -40
  59. package/bundle/dist/utils/providers/common/smooth-weighted-round-robin.js +1 -1
  60. package/bundle/dist/utils/providers/common/strictifier.js +62 -43
  61. package/bundle/dist/utils/providers/common/thinking.js +3 -2
  62. package/bundle/dist/utils/providers/common/ttft.js +1 -1
  63. package/bundle/dist/utils/providers/grok/grok-backend-protocol.js +427 -0
  64. package/bundle/dist/utils/providers/grok/grok-constants.js +55 -0
  65. package/bundle/dist/utils/providers/grok/grok-direct-client.js +196 -0
  66. package/bundle/dist/utils/providers/grok/grok-dispatcher.js +1313 -0
  67. package/bundle/dist/utils/providers/grok/grok-headers.js +118 -0
  68. package/bundle/dist/utils/providers/grok/grok-media-client.js +420 -0
  69. package/bundle/dist/utils/providers/grok/grok-models.js +114 -0
  70. package/bundle/dist/utils/providers/grok/grok-oauth.js +455 -0
  71. package/bundle/dist/utils/providers/grok/grok-quota.js +119 -0
  72. package/bundle/dist/utils/providers/grok/grok-refresh.js +192 -0
  73. package/bundle/dist/utils/providers/grok/grok-types.js +186 -0
  74. package/bundle/dist/utils/providers/grok/grok-voice-client.js +199 -0
  75. package/bundle/dist/utils/providers/grok/index.js +11 -0
  76. package/bundle/dist/utils/providers/openai/openai-backend-protocol.js +111 -83
  77. package/bundle/dist/utils/providers/openai/openai-callback-relay.js +3 -2
  78. package/bundle/dist/utils/providers/openai/openai-constants.js +1 -1
  79. package/bundle/dist/utils/providers/openai/openai-direct-client.js +23 -7
  80. package/bundle/dist/utils/providers/openai/openai-dispatcher.js +143 -106
  81. package/bundle/dist/utils/providers/openai/openai-image-generation.js +48 -33
  82. package/bundle/dist/utils/providers/openai/openai-oauth.js +28 -13
  83. package/bundle/dist/utils/providers/openai/openai-quota.js +38 -27
  84. package/bundle/dist/utils/providers/openai/openai-refresh.js +17 -9
  85. package/bundle/dist/utils/providers/openai/openai-sse.js +1 -1
  86. package/bundle/dist/utils/providers/openai/openai-transport-config.js +1 -1
  87. package/bundle/dist/utils/quiet-hours.js +1 -1
  88. package/bundle/dist/utils/slack-notify.js +14 -8
  89. package/bundle/dist/utils/subset-loaders.js +4 -5
  90. package/bundle/src/application/monit/log-buffer.ts +23 -9
  91. package/bundle/src/application/monit/monit.frame.ts +22 -5
  92. package/bundle/src/application/monit/monit.types.ts +6 -0
  93. package/bundle/src/application/qgrid/conv-routing.test.ts +76 -4
  94. package/bundle/src/application/qgrid/conv-routing.ts +35 -9
  95. package/bundle/src/application/qgrid/expired-token-reminder.ts +9 -1
  96. package/bundle/src/application/qgrid/oauth.ts +51 -15
  97. package/bundle/src/application/qgrid/qgrid-image-generation.ts +9 -0
  98. package/bundle/src/application/qgrid/qgrid-response-format.ts +50 -25
  99. package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +19 -0
  100. package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +84 -40
  101. package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +97 -0
  102. package/bundle/src/application/qgrid/qgrid.dispatcher.ts +274 -126
  103. package/bundle/src/application/qgrid/qgrid.frame.test.ts +1013 -3
  104. package/bundle/src/application/qgrid/qgrid.frame.ts +1415 -60
  105. package/bundle/src/application/qgrid/qgrid.types.ts +335 -0
  106. package/bundle/src/application/qgrid/schema-prompt.ts +105 -41
  107. package/bundle/src/application/qgrid/slack-user-map.ts +5 -0
  108. package/bundle/src/application/qgrid/token-death.ts +4 -0
  109. package/bundle/src/application/qgrid/token-subscriber.test.ts +21 -19
  110. package/bundle/src/application/qgrid/token-subscriber.ts +186 -53
  111. package/bundle/src/application/qgrid/token-trigger-setup.ts +2 -0
  112. package/bundle/src/application/qgrid/token-window-keepalive.ts +49 -6
  113. package/bundle/src/application/qgrid/tool-emulation-schema.ts +33 -29
  114. package/bundle/src/application/qgrid/tool-emulation.ts +52 -27
  115. package/bundle/src/application/request-log/json-schema-type-text.test.ts +5 -5
  116. package/bundle/src/application/request-log/json-schema-type-text.ts +81 -26
  117. package/bundle/src/application/request-log/request-log.model.test.ts +111 -4
  118. package/bundle/src/application/request-log/request-log.model.ts +277 -146
  119. package/bundle/src/application/request-log/request-log.types.ts +6 -0
  120. package/bundle/src/application/request-log/zod-code-format.ts +11 -0
  121. package/bundle/src/application/request-log-step/request-log-step.model.ts +1 -0
  122. package/bundle/src/application/request-log-step/request-log-step.types.ts +2 -0
  123. package/bundle/src/application/setting/setting.constant.ts +9 -0
  124. package/bundle/src/application/setting/setting.model.ts +12 -2
  125. package/bundle/src/application/setting/setting.store.ts +5 -1
  126. package/bundle/src/application/setting/setting.types.ts +8 -0
  127. package/bundle/src/application/sonamu.generated.http +133 -0
  128. package/bundle/src/application/sonamu.generated.sso.ts +2 -0
  129. package/bundle/src/application/sonamu.generated.ts +15 -0
  130. package/bundle/src/application/token/token.identity.test.ts +20 -0
  131. package/bundle/src/application/token/token.model.ts +66 -7
  132. package/bundle/src/application/token/token.types.ts +24 -1
  133. package/bundle/src/i18n/en.ts +19 -0
  134. package/bundle/src/i18n/ko.ts +21 -0
  135. package/bundle/src/i18n/sd.generated.ts +23 -2
  136. package/bundle/src/migrations/20260807133553_manual__backfill_request_log_cost.ts +16 -8
  137. package/bundle/src/server-bootstrap.ts +4 -2
  138. package/bundle/src/server-error-handler.ts +1 -0
  139. package/bundle/src/sonamu.config.ts +69 -7
  140. package/bundle/src/startup-migrations.ts +27 -9
  141. package/bundle/src/testing/global.ts +20 -0
  142. package/bundle/src/testing/schema-bench.ts +105 -30
  143. package/bundle/src/testing/test-database-name.ts +2 -0
  144. package/bundle/src/utils/providers/anthropic/anthropic-constants.ts +8 -0
  145. package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +41 -6
  146. package/bundle/src/utils/providers/anthropic/anthropic-quota.ts +7 -3
  147. package/bundle/src/utils/providers/anthropic/anthropic-thinking.ts +6 -0
  148. package/bundle/src/utils/providers/anthropic/claude-session.ts +58 -24
  149. package/bundle/src/utils/providers/anthropic/fence-strip.ts +11 -0
  150. package/bundle/src/utils/providers/anthropic/stream-json-adapter.ts +110 -45
  151. package/bundle/src/utils/providers/common/credentials.ts +8 -0
  152. package/bundle/src/utils/providers/common/effort.ts +9 -2
  153. package/bundle/src/utils/providers/common/model-cost.test.ts +48 -1
  154. package/bundle/src/utils/providers/common/model-cost.ts +259 -158
  155. package/bundle/src/utils/providers/common/provider-dispatcher.ts +98 -2
  156. package/bundle/src/utils/providers/common/provider-types.ts +46 -3
  157. package/bundle/src/utils/providers/common/schema-validation.test.ts +5 -1
  158. package/bundle/src/utils/providers/common/schema-validation.ts +124 -56
  159. package/bundle/src/utils/providers/common/smooth-weighted-round-robin.ts +4 -0
  160. package/bundle/src/utils/providers/common/strictifier.ts +185 -59
  161. package/bundle/src/utils/providers/common/thinking.ts +2 -2
  162. package/bundle/src/utils/providers/common/ttft.ts +4 -2
  163. package/bundle/src/utils/providers/grok/__fixtures__/golden-responses-1.0.60.json +164 -0
  164. package/bundle/src/utils/providers/grok/grok-backend-protocol.test.ts +325 -0
  165. package/bundle/src/utils/providers/grok/grok-backend-protocol.ts +721 -0
  166. package/bundle/src/utils/providers/grok/grok-constants.ts +105 -0
  167. package/bundle/src/utils/providers/grok/grok-direct-client.test.ts +179 -0
  168. package/bundle/src/utils/providers/grok/grok-direct-client.ts +313 -0
  169. package/bundle/src/utils/providers/grok/grok-dispatcher.test.ts +1395 -0
  170. package/bundle/src/utils/providers/grok/grok-dispatcher.ts +2105 -0
  171. package/bundle/src/utils/providers/grok/grok-headers.test.ts +149 -0
  172. package/bundle/src/utils/providers/grok/grok-headers.ts +199 -0
  173. package/bundle/src/utils/providers/grok/grok-media-client.test.ts +446 -0
  174. package/bundle/src/utils/providers/grok/grok-media-client.ts +703 -0
  175. package/bundle/src/utils/providers/grok/grok-models.test.ts +96 -0
  176. package/bundle/src/utils/providers/grok/grok-models.ts +161 -0
  177. package/bundle/src/utils/providers/grok/grok-oauth.test.ts +406 -0
  178. package/bundle/src/utils/providers/grok/grok-oauth.ts +771 -0
  179. package/bundle/src/utils/providers/grok/grok-quota.test.ts +142 -0
  180. package/bundle/src/utils/providers/grok/grok-quota.ts +198 -0
  181. package/bundle/src/utils/providers/grok/grok-refresh.test.ts +239 -0
  182. package/bundle/src/utils/providers/grok/grok-refresh.ts +325 -0
  183. package/bundle/src/utils/providers/grok/grok-types.test.ts +252 -0
  184. package/bundle/src/utils/providers/grok/grok-types.ts +374 -0
  185. package/bundle/src/utils/providers/grok/grok-voice-client.test.ts +321 -0
  186. package/bundle/src/utils/providers/grok/grok-voice-client.ts +284 -0
  187. package/bundle/src/utils/providers/grok/index.ts +20 -0
  188. package/bundle/src/utils/providers/openai/openai-backend-protocol.ts +221 -137
  189. package/bundle/src/utils/providers/openai/openai-callback-relay.ts +12 -1
  190. package/bundle/src/utils/providers/openai/openai-constants.ts +2 -0
  191. package/bundle/src/utils/providers/openai/openai-direct-client.ts +111 -21
  192. package/bundle/src/utils/providers/openai/openai-dispatcher.ts +322 -169
  193. package/bundle/src/utils/providers/openai/openai-image-generation.ts +116 -36
  194. package/bundle/src/utils/providers/openai/openai-oauth.ts +48 -20
  195. package/bundle/src/utils/providers/openai/openai-quota.ts +77 -46
  196. package/bundle/src/utils/providers/openai/openai-refresh.ts +42 -18
  197. package/bundle/src/utils/providers/openai/openai-sse.ts +27 -3
  198. package/bundle/src/utils/providers/openai/openai-transport-config.ts +2 -0
  199. package/bundle/src/utils/quiet-hours.ts +12 -1
  200. package/bundle/src/utils/slack-notify.ts +44 -13
  201. package/bundle/src/utils/subset-loaders.ts +7 -7
  202. package/bundle/web-dist/client/assets/clsx-5XM_pHvN.js +1 -0
  203. package/bundle/web-dist/client/assets/index-Be2qCZmI.css +1 -0
  204. package/bundle/web-dist/client/assets/index-C96h3feE.js +32 -0
  205. package/bundle/web-dist/client/assets/logs-DBM6U0QD.js +1 -0
  206. package/bundle/web-dist/client/assets/monit-BBjXa7vB.js +1 -0
  207. package/bundle/web-dist/client/assets/routes-Crz_PQzi.js +5 -0
  208. package/bundle/web-dist/client/assets/{services.generated-NP-ValHd.js → services.generated-B5lc3aIC.js} +5 -5
  209. package/bundle/web-dist/client/assets/settings-Cdwm3OBB.js +1 -0
  210. package/bundle/web-dist/client/assets/show-DBUhALT1.js +2 -0
  211. package/bundle/web-dist/client/assets/tokens-CVQAVJTo.js +1 -0
  212. package/bundle/web-dist/client/assets/total-cost-MnfKU8IN.js +1 -0
  213. package/bundle/web-dist/client/assets/use-oauth-login-flow-BfxYI4Oh.js +1 -0
  214. package/bundle/web-dist/client/assets/use-update-token-mutation-qKBC2sn7.js +1 -0
  215. package/bundle/web-dist/client/assets/{vendor-tanstack-DJRQAbrY.js → vendor-tanstack-DRPs09ai.js} +1 -1
  216. package/bundle/web-dist/client/index.html +5 -5
  217. package/bundle/web-dist/server/assets/clsx-D_N5PN_2.js +16 -0
  218. package/bundle/web-dist/server/assets/{lazyRouteComponent-CgBdabgd.js → lazyRouteComponent-AKiHfZWp.js} +129 -2
  219. package/bundle/web-dist/server/assets/{logs-BMyR98rU.js → logs-B7QmGJq3.js} +18 -14
  220. package/bundle/web-dist/server/assets/{monit-ZPt66W5M.js → monit-DFt7x3bh.js} +13 -12
  221. package/bundle/web-dist/server/assets/{plus-BZ9I0VgC.js → plus-DaYQRpBt.js} +1 -1
  222. package/bundle/web-dist/server/assets/{react-dom-Ds75e4Jl.js → react-dom-Cv23mm1K.js} +2 -129
  223. package/bundle/web-dist/server/assets/{refresh-cw-CztCFis-.js → refresh-cw-BpXNsAy-.js} +1 -1
  224. package/bundle/web-dist/server/assets/{request-model-DjGldb-h.js → request-model-eHE6YbaF.js} +1 -1
  225. package/bundle/web-dist/server/assets/{routes-Ct-k7nBA.js → routes-_Y-PJfgO.js} +110 -39
  226. package/bundle/web-dist/server/assets/{services.generated-BA4AcAf5.js → services.generated-CMJ8AHbO.js} +582 -172
  227. package/bundle/web-dist/server/assets/{settings-CBUZ47Xx.js → settings-JwJKxn2e.js} +14 -14
  228. package/bundle/web-dist/server/assets/{show-LSFIzvO2.js → show-BEv6z1v_.js} +90 -60
  229. package/bundle/web-dist/server/assets/{tokens-DxrBW512.js → tokens-CNT4mI-f.js} +162 -50
  230. package/bundle/web-dist/server/assets/total-cost-fTE9Xy82.js +18 -0
  231. package/bundle/web-dist/server/assets/use-oauth-login-flow-jkAkT3X6.js +2345 -0
  232. package/bundle/web-dist/server/assets/{use-update-token-mutation-pkArIzCP.js → use-update-token-mutation-Sm6kh02m.js} +1 -1
  233. package/bundle/web-dist/server/entry-server.generated.js +1644 -21655
  234. package/dist/cli.js +9 -9
  235. package/package.json +4 -11
  236. package/postinstall.mjs +12 -0
  237. package/skills/qgrid/SKILL.md +1 -0
  238. package/skills/qgrid/references/cli-env-and-server-boot.md +4 -1
  239. package/skills/qgrid/references/decision-rationale.md +23 -0
  240. package/skills/qgrid/references/grok-runtime.md +89 -0
  241. package/skills/qgrid/references/provider-runtime-differences.md +30 -29
  242. package/skills/qgrid/references/repo-map.md +10 -0
  243. package/skills/qgrid/references/token-auth-quota-lifecycle.md +56 -3
  244. package/bundle/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +0 -406
  245. package/bundle/dist/node_modules/.pnpm/@vitest_expect@4.1.10/node_modules/@vitest/expect/dist/index.js +0 -1507
  246. package/bundle/dist/node_modules/.pnpm/@vitest_pretty-format@4.1.10/node_modules/@vitest/pretty-format/dist/index.js +0 -887
  247. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/chunk-artifact.js +0 -2756
  248. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/index.js +0 -8
  249. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/utils.js +0 -8
  250. package/bundle/dist/node_modules/.pnpm/@vitest_snapshot@4.1.10/node_modules/@vitest/snapshot/dist/index.js +0 -922
  251. package/bundle/dist/node_modules/.pnpm/@vitest_spy@4.1.10/node_modules/@vitest/spy/dist/index.js +0 -386
  252. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +0 -121
  253. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/constants.js +0 -51
  254. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/diff.js +0 -1317
  255. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/display.js +0 -561
  256. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/error.js +0 -40
  257. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/helpers.js +0 -272
  258. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/offset.js +0 -27
  259. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/serialize.js +0 -77
  260. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/source-map.js +0 -381
  261. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/timers.js +0 -51
  262. package/bundle/dist/node_modules/.pnpm/chai@6.2.2/node_modules/chai/index.js +0 -2986
  263. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.js +0 -10
  264. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.js +0 -109
  265. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.js +0 -10
  266. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.js +0 -10
  267. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.js +0 -10
  268. package/bundle/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +0 -1126
  269. package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.js +0 -21
  270. package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +0 -432
  271. package/bundle/dist/node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.js +0 -517
  272. package/bundle/dist/node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js +0 -101
  273. package/bundle/dist/node_modules/.pnpm/vite@8.0.3_@emnapi_core@1.11.2_@emnapi_runtime@1.11.2_@types_node@25.0.7_esbuild@0.27.4_5b35fc1fb85d2af4d105e0d74f940f50/node_modules/vite/dist/node/module-runner.js +0 -1265
  274. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js +0 -9
  275. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/benchmark.CX_oY03V.js +0 -41
  276. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/evaluatedModules.Dg1zASAC.js +0 -19
  277. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/index.Chj8NDwU.js +0 -202
  278. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/index.DdgEv5B1.js +0 -46
  279. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/rpc.MzXet3jl.js +0 -119
  280. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/test.DNmyFkvJ.js +0 -3044
  281. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.js +0 -59
  282. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/index.js +0 -28
  283. package/bundle/dist/testing/setup-mocks.js +0 -16
  284. package/bundle/src/testing/setup-mocks.ts +0 -44
  285. package/bundle/web-dist/client/assets/index-Bw2s88Ot.css +0 -1
  286. package/bundle/web-dist/client/assets/index-DZwzUfI-.js +0 -106
  287. package/bundle/web-dist/client/assets/logs-Cog79DU5.js +0 -1
  288. package/bundle/web-dist/client/assets/monit-2auznBys.js +0 -1
  289. package/bundle/web-dist/client/assets/routes-B0lTeLK-.js +0 -5
  290. package/bundle/web-dist/client/assets/settings-D8ZxZGSJ.js +0 -1
  291. package/bundle/web-dist/client/assets/show-CFSERlnM.js +0 -2
  292. package/bundle/web-dist/client/assets/tokens-CZXUyI7O.js +0 -1
  293. package/bundle/web-dist/client/assets/use-oauth-login-flow-hboOs3wG.js +0 -1
  294. package/bundle/web-dist/client/assets/use-update-token-mutation-BQHS0byG.js +0 -1
  295. package/bundle/web-dist/server/assets/use-oauth-login-flow-Gn8flMK5.js +0 -178
  296. package/dist/cli.d.ts +0 -10
  297. /package/bundle/web-dist/client/assets/{cost-DH2jZbrw.js → cost-DB3HbU7T.js} +0 -0
  298. /package/bundle/web-dist/client/assets/{plus-B62CuqT8.js → plus-BsQdY7PS.js} +0 -0
  299. /package/bundle/web-dist/client/assets/{preload-helper-ca-nBW7U.js → preload-helper-DWTEM3RW.js} +0 -0
  300. /package/bundle/web-dist/client/assets/{refresh-cw-NNcU0Cmq.js → refresh-cw-D9IUmT23.js} +0 -0
  301. /package/bundle/web-dist/client/assets/{request-model-CojtinqK.js → request-model-Bpp_rkK8.js} +0 -0
  302. /package/bundle/web-dist/server/assets/{cost-eEHeTRT5.js → cost-BC9yzyA9.js} +0 -0
package/dist/cli.js CHANGED
@@ -39,7 +39,7 @@ function runSelfUpdate(params, dependencies) {
39
39
  try {
40
40
  latest = latestVersion(packageName);
41
41
  } catch (cause) {
42
- warn(`Warning: failed to check for qgrid-cli updates: ${cause.message}`);
42
+ warn(`Warning: failed to check for qgrid-cli updates: ${cause instanceof Error ? cause.message : String(cause)}`);
43
43
  warn(`Continuing with qgrid-cli ${currentVersion}.`);
44
44
  return { kind: "continue" };
45
45
  }
@@ -60,7 +60,8 @@ function runSelfUpdate(params, dependencies) {
60
60
  return { kind: "continue" };
61
61
  }
62
62
  } catch (cause) {
63
- warn(`Warning: failed to update qgrid-cli to ${latest}: ${cause.message}`);
63
+ const message = cause instanceof Error ? cause.message : String(cause);
64
+ warn(`Warning: failed to update qgrid-cli to ${latest}: ${message}`);
64
65
  warn(`Continuing with qgrid-cli ${currentVersion}; fix the global ${packageManager} install.`);
65
66
  return { kind: "continue" };
66
67
  }
@@ -213,13 +214,12 @@ function ensureLatestRuntimeCliDependencies() {
213
214
  installedOutput = commandVersion(dep.command);
214
215
  }
215
216
  } catch (e) {
216
- console.warn(`Warning: failed to update ${dep.label}: ${e.message}`);
217
+ console.warn(`Warning: failed to update ${dep.label}: ${e instanceof Error ? e.message : String(e)}`);
217
218
  }
218
219
  if (!installedOutput) warnMissingRuntimeCliDependency(dep);
219
220
  }
220
221
  }
221
- function normalizePort(port) {
222
- const value = String(port);
222
+ function normalizePort(value) {
223
223
  const numeric = Number(value);
224
224
  if (!/^\d+$/.test(value) || numeric < 1 || numeric > 65535) {
225
225
  console.error(`Invalid port: ${value}`);
@@ -303,10 +303,10 @@ program.name("qgrid").version(pkg.version).description("Qgrid — LLM subscripti
303
303
  await client.connect();
304
304
  await client.end();
305
305
  } catch (e) {
306
- const err = e;
306
+ const message = e instanceof Error ? e.message : String(e);
307
307
  console.error(`Error: Cannot connect to PostgreSQL at ${dbHost}:${dbPort}/${dbName}`);
308
- console.error(`error: ${err.message}`);
309
- if (err.message.includes("timeout expired")) console.error(`cannot connect to the database server. Please check if the database is running and accessible.`);
308
+ console.error(`error: ${message}`);
309
+ if (message.includes("timeout expired")) console.error(`cannot connect to the database server. Please check if the database is running and accessible.`);
310
310
  console.error(`\nProvide DB connection via --db flag or QGRID_DB_* env vars:`);
311
311
  console.error(` qgrid --db postgres://user:password@host:port/dbname`);
312
312
  process.exit(1);
@@ -314,7 +314,7 @@ program.name("qgrid").version(pkg.version).description("Qgrid — LLM subscripti
314
314
  try {
315
315
  await import(serverEntry);
316
316
  } catch (e) {
317
- console.error("Failed to start server:", e.stack ?? e.message);
317
+ console.error("Failed to start server:", e instanceof Error ? e.stack ?? e.message : e);
318
318
  process.exit(1);
319
319
  }
320
320
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cartanova/qgrid-cli",
3
- "version": "2.10.10",
3
+ "version": "2.11.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/cartanova-ai/qgrid"
@@ -20,20 +20,15 @@
20
20
  "@ai-sdk/anthropic": "^3.0.0",
21
21
  "@ai-sdk/provider": "^3.0.0",
22
22
  "@ai-sdk/provider-utils": "^4.0.0",
23
- "@anthropic-ai/sdk": "^0.81.0",
24
23
  "@better-auth/core": "~1.6.0",
25
24
  "@better-auth/passkey": "~1.6.0",
26
25
  "@better-auth/sso": "~1.6.0",
27
26
  "@logtape/logtape": "2.0.0",
28
27
  "@logtape/pretty": "2.0.0",
29
- "@logtape/redaction": "2.0.0",
30
- "@oxc-project/runtime": "^0.79.0",
28
+ "@oxc-project/runtime": "^0.79.1",
31
29
  "ai": "^6.0.1",
32
- "bcrypt": "^6.0.0",
33
30
  "better-auth": "~1.6.0",
34
- "chalk": "^4.1.2",
35
31
  "commander": "^13.0.0",
36
- "date-fns": "^4.1.0",
37
32
  "dotenv": "^16",
38
33
  "fastify": "^4",
39
34
  "ioredis": "^5.8.2",
@@ -41,16 +36,14 @@
41
36
  "knex": "^3.2.9",
42
37
  "pg": "^8.16.3",
43
38
  "pngjs": "^7.0.0",
44
- "radashi": "^12.2.0",
45
- "sonamu": "0.10.3",
46
- "typescript": "6.0.3",
39
+ "sonamu": "0.11.16",
40
+ "typescript": "7.1.0-dev.20260831.1",
47
41
  "ws": "8.20.0",
48
42
  "zod": "^4.3.6"
49
43
  },
50
44
  "devDependencies": {
51
45
  "@types/node": "25.0.7",
52
46
  "@types/pg": "^8.20.0",
53
- "@types/ws": "8.18.1",
54
47
  "semver": "^7.7.4",
55
48
  "tsdown": "^0.22.3",
56
49
  "yaml": "^2.8.2"
package/postinstall.mjs CHANGED
@@ -28,6 +28,7 @@ function findProjectRoot(startDir) {
28
28
  }
29
29
 
30
30
  const parent = path.dirname(current);
31
+
31
32
  if (parent === current) return packageJsonRoot ?? path.resolve(startDir);
32
33
  current = parent;
33
34
  }
@@ -35,15 +36,19 @@ function findProjectRoot(startDir) {
35
36
 
36
37
  function defaultProjectRoot() {
37
38
  if (process.env.QGRID_SKILLS_CWD) return findProjectRoot(process.env.QGRID_SKILLS_CWD);
39
+
38
40
  if (process.env.INIT_CWD) return findProjectRoot(process.env.INIT_CWD);
39
41
 
40
42
  const cwd = process.cwd();
43
+
41
44
  if (cwd.includes(`${path.sep}node_modules${path.sep}`)) return null;
45
+
42
46
  return findProjectRoot(cwd);
43
47
  }
44
48
 
45
49
  function isInside(parentDir, childDir) {
46
50
  const relative = path.relative(path.resolve(parentDir), path.resolve(childDir));
51
+
47
52
  return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
48
53
  }
49
54
 
@@ -55,9 +60,11 @@ function defaultTargets() {
55
60
  const codexHome = process.env.CODEX_HOME
56
61
  ? path.resolve(process.env.CODEX_HOME)
57
62
  : path.join(os.homedir(), ".codex");
63
+
58
64
  const claudeHome = process.env.CLAUDE_HOME
59
65
  ? path.resolve(process.env.CLAUDE_HOME)
60
66
  : path.join(os.homedir(), ".claude");
67
+
61
68
  return [
62
69
  { label: "Codex", target: path.join(codexHome, "skills", "qgrid"), useSymlink: false },
63
70
  { label: "Claude Code", target: path.join(claudeHome, "skills", "qgrid"), useSymlink: false },
@@ -65,10 +72,13 @@ function defaultTargets() {
65
72
  }
66
73
 
67
74
  const projectRoot = defaultProjectRoot();
75
+
68
76
  if (!projectRoot) return null;
69
77
  const isInstalledPackage = packageDir.split(path.sep).includes("node_modules");
78
+
70
79
  if (!isInstalledPackage && isInside(projectRoot, sourceSkillsDir)) {
71
80
  console.log("qgrid skill sync skipped: running inside qgrid repository.");
81
+
72
82
  return [];
73
83
  }
74
84
 
@@ -89,6 +99,7 @@ function defaultTargets() {
89
99
  async function syncSkill({ label, target, useSymlink }) {
90
100
  if (!existsSync(path.join(sourceSkillsDir, "SKILL.md"))) {
91
101
  console.log("qgrid skill source not found in qgrid CLI package.");
102
+
92
103
  return;
93
104
  }
94
105
 
@@ -99,6 +110,7 @@ async function syncSkill({ label, target, useSymlink }) {
99
110
  try {
100
111
  await symlink(sourceSkillsDir, target, "dir");
101
112
  console.log(`qgrid skill linked for ${label}: ${target}`);
113
+
102
114
  return;
103
115
  } catch (error) {
104
116
  console.log(
@@ -21,6 +21,7 @@ Before changing code, identify the affected path:
21
21
  - OpenAI direct transport, permits, routing, cache affinity, OAuth, or quota behavior: read `references/openai-codex-runtime.md`.
22
22
  - Adding an OpenAI model, its pricing, or reasoning levels: follow the model-addition checklist in `references/openai-codex-runtime.md`.
23
23
  - Anthropic models or Claude Code spawn/stream-json behavior: read `references/anthropic-claude-code-runtime.md`.
24
+ - Grok fingerprinting, OAuth, quota routing, media, voice, or retry behavior: read `references/grok-runtime.md`.
24
25
  - Token registration, OAuth, token sync, active/inactive behavior, quota thresholds, or weighted token routing: read `references/token-auth-quota-lifecycle.md`.
25
26
  - Provider comparisons, routing, or cross-provider bugs: read `references/provider-runtime-differences.md`.
26
27
  - Tool calling, AI SDK multi-step loops, or tool-call request logs: read `references/tool-calling-and-multiturn.md`.
@@ -66,6 +66,8 @@ When helping a user set up qgrid locally, check for `QGRID_PROJECT_NAME` or conf
66
66
  |---|---:|---|
67
67
  | `QGRID_OPENAI_TRANSPORT` | `websocket` | OpenAI transport selector (`https` or `websocket`). Invalid values fail at dispatcher configuration time. This is the only OpenAI runtime knob; there is no concurrency cap. |
68
68
  | `QGRID_OPENAI_AUTOSCALE` / `QGRID_OPENAI_MIN_WORKERS_PER_TOKEN` / `QGRID_OPENAI_MAX_WORKERS_PER_TOKEN` / `QGRID_OPENAI_PERMITS_PER_TOKEN` | ignored | Removed. OpenAI requests run uncapped like Anthropic (stateless per-request execution); setting these has no effect. |
69
+ | `QGRID_GROK_MAX_INFLIGHT_PER_TOKEN` | unset (uncapped) | Optional positive-integer per-account Grok cap. Accounts at the cap are excluded from selection rather than queued. Invalid values are ignored with a warning (`packages/api/src/utils/providers/grok/grok-dispatcher.ts`). |
70
+ | `QGRID_GROK_LIVE_TOKEN_ID` | unset | Reserved token-row selector for opt-in Grok live tests. Keep it unset in CI and ordinary server runs. The live-test gate is specified in `docs/plans/2026-10-16-grok-provider-integration-plan.md` §7; no current server runtime behavior reads it. |
69
71
  | `QGRID_TOKEN_WINDOW_KEEPALIVE_ENABLED` | off | Marks this instance as the Anthropic 5-hour window keepalive runner (2.8.0, `ea7feb3`). Only the literal `true` enables it; set it on exactly one instance per shared DB so developer instances do not fire duplicates. Two more gates apply: the global setting `qgrid.tokenWindowKeepaliveEnabled` (`false` turns everything off; changing it reschedules immediately) and the per-token `tokens.keepalive_enabled` flag (default `false`, dashboard settings-panel toggle). In 2.7.6 this env was a default-on global switch with no per-token opt-in. |
70
72
  | `MAX_STRUCTURED_OUTPUT_RETRIES` | `1` for structured Anthropic streaming calls | Claude Code structured-output retry count for streaming only, clamped to at least 1 by qgrid. Non-streaming `generate` leaves the variable unset and uses Claude Code's default retry budget. |
71
73
 
@@ -81,7 +83,8 @@ When helping a user set up qgrid locally, check for `QGRID_PROJECT_NAME` or conf
81
83
  1. Ensures PostgreSQL `tokens_changed` triggers.
82
84
  2. Starts `TokenSubscriber` for LISTEN/NOTIFY plus periodic reconcile.
83
85
  3. Starts `OpenAIDispatcher` and `AnthropicDispatcher`.
84
- 4. Logs server URL and provider readiness counts.
86
+ 4. Constructs `GrokRefreshCoordinator`, `GrokMediaClient`, and `GrokVoiceClient`, injects them into `GrokDispatcher`, starts it, then reconciles Grok tokens (`packages/api/src/sonamu.config.ts`).
87
+ 5. Logs server URL and provider readiness counts.
85
88
 
86
89
  On shutdown, it stops provider dispatchers and the token subscriber.
87
90
 
@@ -10,6 +10,7 @@ Do not copy these notes blindly into implementation. Use them to find the releva
10
10
  - Tool calling and request-log lifecycle
11
11
  - OpenAI/Codex runtime
12
12
  - Anthropic/Claude Code runtime
13
+ - Grok (xAI subscription) runtime
13
14
  - Token sync and quota thresholds
14
15
  - Weighted token routing
15
16
  - Request logs, metrics, and dashboard
@@ -133,6 +134,28 @@ Key decisions:
133
134
  - `--setting-sources project` is required for shared-service isolation. User/local Claude settings can load hooks or memory and leak context across requests.
134
135
  - Claude Code OAuth prompt cache sharing across tokens in the same workspace is an observed cost behavior, not a product contract. Monitor it; do not promise it.
135
136
 
137
+ ## Grok (xAI Subscription) Runtime
138
+
139
+ Sources:
140
+
141
+ - `docs/plans/2026-10-16-grok-provider-integration-plan.md`
142
+ - `docs/diagnosis/2026-10-16-grok-live-probe.md`
143
+ - `packages/api/src/utils/providers/grok/*`
144
+ - `packages/api/src/application/qgrid/qgrid.dispatcher.ts`
145
+
146
+ Key decisions:
147
+
148
+ - **D1 — accepted terms risk:** The user accepted the risk of using an xAI subscription token from a non-official client and authorized the bounded live probe. This is recorded acceptance, not a claim that xAI permits every deployment.
149
+ - **D2 — reproduce grok-build:** Qgrid sends the full installed grok-build fingerprint. `GROK_BUILD_VERSION` is a source pin, not an environment override; changing it requires a new installed-binary capture, golden fixture, build id, and fingerprint test.
150
+ - **D3 — subscription OAuth only:** Grok tokens must be `at+jwt` OAuth credentials issued by `auth.x.ai`. Raw xAI API keys are outside qgrid's subscription-pooling purpose.
151
+ - **D4 — URL video delivery:** Return the upstream `api.x.ai` video URL in the AI SDK URL result. Qgrid does not download, proxy, or persist video bytes.
152
+ - **D5 — no new workspace package:** Grok runtime code lives under `packages/api/src/utils/providers/grok/`; SDK adapters stay in `packages/ai-sdk/src/`.
153
+ - **D6 — exclude on-demand billing:** An account with `/settings.on_demand_enabled = true` is ineligible. There is no per-token override because the exclusion closes accidental paid usage.
154
+ - **D7 — shared weighted routing:** Grok uses the common `SmoothWeightedRoundRobin` with `tokens.weight`, after quota, on-demand, cooldown, entitlement, and optional in-flight gates.
155
+ - **D8 — preserve tool emulation:** Grok remains on qgrid's shared strict action-envelope tool contract. The provider can emit native function calls, but qgrid callers continue to receive the same emulated AI SDK multi-step lifecycle as the other routes.
156
+
157
+ Current implementation evidence is in `grok-constants.ts`, `grok-dispatcher.ts`, `grok-oauth.ts`, `grok-media-client.ts`, `packages/api/src/application/qgrid/qgrid.frame.ts`, and `qgrid.dispatcher.ts`. See `references/grok-runtime.md` for operational details and unverified gaps.
158
+
136
159
  ## Token Sync And Quota Thresholds
137
160
 
138
161
  Sources:
@@ -0,0 +1,89 @@
1
+ # Grok Direct Runtime
2
+
3
+ Use this reference before changing Grok chat transport, fingerprinting, OAuth, quota routing, media, voice, cost accounting, or retry behavior.
4
+
5
+ ## Source files
6
+
7
+ - Fingerprint constants and headers: `packages/api/src/utils/providers/grok/grok-constants.ts`, `grok-headers.ts`.
8
+ - Chat protocol, transport, models, and dispatch: `grok-backend-protocol.ts`, `grok-direct-client.ts`, `grok-models.ts`, `grok-dispatcher.ts`.
9
+ - OAuth, refresh, billing, and settings: `grok-oauth.ts`, `grok-refresh.ts`, `grok-quota.ts`.
10
+ - Image/video and voice clients: `grok-media-client.ts`, `grok-voice-client.ts`.
11
+ - API limits and endpoints: `packages/api/src/application/qgrid/qgrid.types.ts`, `qgrid.frame.ts`.
12
+ - Probe evidence and design decisions: `docs/diagnosis/2026-10-16-grok-live-probe.md`, `docs/plans/2026-10-16-grok-provider-integration-plan.md`.
13
+
14
+ ## Hosts and fingerprint
15
+
16
+ Grok uses the same xAI subscription OAuth bearer on two hosts, but the header families are not interchangeable (`grok-constants.ts`, `grok-headers.ts`):
17
+
18
+ | Host | Operations | Identity headers |
19
+ | --- | --- | --- |
20
+ | `https://cli-chat-proxy.grok.com/v1` | `/responses`, `/settings`, `/models`, `/billing`, `/user` | `grok-shell/1.0.60 (<os>; <arch>)`, client version and identifier, client mode, and the proxy auth headers. `/responses` also sends the captured `x-grok-*` conversation headers, trace context, loop guards, and zstd encoding. |
21
+ | `https://api.x.ai/v1` | image generation/editing, video start/status, STT, TTS | Media uses `xai-grok-build/1.0.60`; voice uses the shell user agent. Both send the client version and identifier, but never the proxy auth trio. |
22
+
23
+ D2 requires the installed grok-build fingerprint. `GROK_BUILD_VERSION` is pinned to `1.0.60` and `GROK_BUILD_COMMIT` to build `01a8e1c591c0`; the golden request came from the installed binary, not the older public source (`grok-constants.ts`, `grok-headers.test.ts`, `docs/diagnosis/2026-10-16-grok-live-probe.md`).
24
+
25
+ Handle the pin like OpenAI's `CODEX_CLI_VERSION`: keep it as a source constant with no runtime override. To bump it:
26
+
27
+ 1. Edit `GROK_BUILD_VERSION` in `grok-constants.ts`.
28
+ 2. Run the newly installed grok-build binary through an intercepting proxy and re-capture the redacted golden request fixture.
29
+ 3. Update `GROK_BUILD_COMMIT` with that binary's build id.
30
+ 4. Run `grok-headers.test.ts` and the golden fingerprint test before release.
31
+
32
+ The proxy treats the client version as a floor. The 2026-10-16 probe saw `/settings.min_client_version = 1.0.13`; a lower client received HTTP 426. The dispatcher trips a chat-only fast gate for 10 minutes and reports the bump routine (`docs/diagnosis/2026-10-16-grok-live-probe.md`, `grok-dispatcher.ts`).
33
+
34
+ ## OAuth, credentials, and refresh
35
+
36
+ Grok login uses OIDC discovery under `https://auth.x.ai`, public client id `b1a00492-073a-47ea-816f-4c329264a828`, S256 PKCE, `referrer=grok-build`, and these frozen scopes: `openid profile email offline_access grok-cli:access api:access conversations:read conversations:write workspaces:read workspaces:write` (`grok-constants.ts`, `grok-oauth.ts`).
37
+
38
+ Browser login uses a random `127.0.0.1` callback and accepts either the full callback URL or a pasted bare code. Qgrid exposes this as code-paste completion because it does not serve the random callback. Device login uses `/oauth2/device/code`, polls `/oauth2/token` at the returned interval, and adds five seconds after `slow_down` (`grok-oauth.ts`, `packages/api/src/application/qgrid/qgrid.frame.ts`).
39
+
40
+ Stored credentials contain OAuth access/refresh tokens, RFC 3339 expiry, issuer, client id, scopes, `userId`, stable session/agent ids, and an optional tier. Registration accepts only an `at+jwt` issued by `auth.x.ai`; the post-login `/user` lookup resolves the account (`grok-types.ts`, `grok-oauth.ts`). `userId` is the token identity key, so signing in again replaces the prior row for the same account while preserving token settings (`packages/api/src/application/token/token.model.ts`).
41
+
42
+ Refresh starts 300 seconds plus stable 0–60 second per-account jitter before expiry, coalesces concurrent refreshes, persists before publishing credentials, and retains the old refresh token when xAI does not rotate it. Only `invalid_grant` and `invalid_client` require a new login; network errors, 429, 5xx, and unknown OAuth errors remain transient. An upstream 401 permits one forced refresh and one same-token retry (`grok-refresh.ts`, `grok-dispatcher.ts`).
43
+
44
+ ## Quota, billing, and token selection
45
+
46
+ `/billing?format=credits` is camelCase: qgrid reads `config.creditUsagePercent`, `config.currentPeriod`, and `config.prepaidBalance.val`. The observed period was seven days anchored at subscription start. Results are cached for 60 seconds; lookup failure fails open (`grok-quota.ts`, `grok-dispatcher.ts`, `docs/diagnosis/2026-10-16-grok-live-probe.md`).
47
+
48
+ D6 excludes accounts when `/settings.on_demand_enabled` is `true`; `null`, `false`, or absence allows routing. Billing does not carry this field. D7 selects eligible accounts through the shared `SmoothWeightedRoundRobin`, using `tokens.weight`; a valid cache-affinity token remains preferred. `QGRID_GROK_MAX_INFLIGHT_PER_TOKEN` optionally excludes accounts at the cap, while omission leaves Grok uncapped (`grok-quota.ts`, `grok-dispatcher.ts`, `packages/api/src/utils/providers/common/smooth-weighted-round-robin.ts`).
49
+
50
+ ## Failure and failover rules
51
+
52
+ The dispatcher implements the plan §5.4 state machine (`grok-backend-protocol.ts`, `grok-direct-client.ts`, `grok-dispatcher.ts`, `grok-media-client.ts`):
53
+
54
+ | Condition | State and retry behavior |
55
+ | --- | --- |
56
+ | 429 with `Retry-After` | Set a request-class cooldown, capped at 120 seconds; fail over within the hop budget. If every candidate is cooling down, wait once for at most 30 seconds, then return a rate-limit error. |
57
+ | 429 exhaustion | Block the request class until the billing period ends, or one hour when the end is unavailable; invalidate billing and fail over. |
58
+ | 403 | Chat fails permanently without refresh or failover. Public API sets a one-hour entitlement block for that request class and may fail over once. |
59
+ | HTTP 426 | Trip the chat-only version gate. Media and voice remain available. |
60
+ | 401 | Refresh once and retry the same account; a second 401 marks it for re-authentication and may fail over. |
61
+ | `x-should-retry: false` | Return the error without retry or failover. |
62
+ | Chat 5xx/connect/idle failure | Fail over only before any event was forwarded and before upstream execution was observed. |
63
+ | Media/voice transport failure | Fail over only for a classified pre-send connection failure. Never replay a sent POST or a timeout that may have executed upstream. |
64
+
65
+ ## Chat, tools, usage, and cost
66
+
67
+ Chat sends complete Responses-format history over HTTPS/SSE. It preserves image data/HTTPS inputs, strict structured output, prompt-cache affinity, reasoning effort, and the fixed include/store fields captured from grok-build. A stream succeeds only after `response.completed` (`grok-backend-protocol.ts`, `grok-direct-client.ts`, `grok-dispatcher.ts`, `docs/diagnosis/2026-10-16-grok-live-probe.md`).
68
+
69
+ D8 keeps qgrid's shared structured-output tool emulation: caller tools become the strict action envelope, the AI SDK executes returned tool calls, and a follow-up turn replays results. Do not replace this with Grok-native function execution without reopening the cross-provider contract (`packages/api/src/application/qgrid/qgrid.dispatcher.ts`, `tool-emulation.ts`, `tool-emulation-schema.ts`).
70
+
71
+ Provider `cost_in_usd_ticks` is authoritative, including zero; one tick is `1e-10` USD. If ticks are absent, qgrid uses catalog-seeded language/image prices and marks `costSource: "pricing_table"`; reported ticks use `costSource: "provider"` (`grok-dispatcher.ts`, `packages/api/src/utils/providers/common/model-cost.ts`, `docs/diagnosis/2026-10-16-grok-live-probe.md`).
72
+
73
+ ## Media and voice
74
+
75
+ Qgrid exposes image generation/editing, asynchronous video start/status, transcription, and speech through `api.x.ai`. Reference images select `/images/edits`; video uses `/videos/generations` and `/videos/{request_id}`; voice uses multipart `/stt` and JSON `/tts` (`grok-media-client.ts`, `grok-voice-client.ts`, `packages/api/src/application/qgrid/qgrid.frame.ts`).
76
+
77
+ Inline audio, each inline image, and the aggregate inline images in one request are capped at 7 MiB decoded. The server maps Fastify's oversized-body error to HTTP 413 (`packages/api/src/application/qgrid/qgrid.types.ts`, `qgrid.frame.ts`).
78
+
79
+ Video starts return a random 128-bit in-memory job handle. Handles expire after 24 hours, polling stays pinned to the starting token, and `projectName` must match the owner supplied at start. D4 returns the upstream `api.x.ai` video URL unchanged; qgrid does not fetch, proxy, or store the bytes (`qgrid.frame.ts`, `grok-media-client.ts`, `packages/ai-sdk/README.md`).
80
+
81
+ **ZDR and video.** xAI refuses `POST /v1/videos/generations` for Zero Data Retention accounts with HTTP 400 `invalid_request`: "Zero Data Retention teams must provide output.upload_url for video generation." The dispatcher therefore keeps a per-token `zdr` state and excludes `zdr === true` tokens from video only; chat, image, STT, and TTS still route. The primary signal is `codingDataRetentionOptOut` on `GET /user?include=subscription`, re-read on the 60 s prefetch with settings; `x-zero-data-retention: true` on a chat-proxy response confirms it, but its absence never clears it. Unknown state, or a failed `/user` read with no prior value, routes (fail open). If a video start still gets the ZDR 400, the token is marked ZDR, video is entitlement-blocked for an hour, and the start fails over under the media rules. With no eligible video token the caller gets `GrokZdrVideoUnavailableError` (HTTP 503) naming the tokens; usage exposes `zdrVideoExcluded`. Both signals were inferred from one account (plan §11). grok-build's remedy, a user-owned S3 presigned `output.upload_url`, is not implemented (`grok-dispatcher.ts`, `grok-quota.ts`).
82
+
83
+ ## Known gaps and residual risks
84
+
85
+ - **Verified 2026-10-16:** video generation succeeded through the SDK once the account's data-retention opt-out was off (8 s H.264 mp4 on vidgen.x.ai, $0.64; plan section 11). ZDR accounts are refused upstream and are excluded from the video class (see ZDR and video).
86
+ - Node/undici adds headers such as `accept-language` and `sec-fetch-mode` that the captured reqwest client did not send. Transport fingerprinting remains residual risk 10; D1/D2 do not authorize anti-detection work (`docs/plans/2026-10-16-grok-provider-integration-plan.md`, risk 10).
87
+ - **Unverified:** The capture pins chat header order. Media header order has not been verified through an installed-binary capture (`grok-headers.ts`, `docs/diagnosis/2026-10-16-grok-live-probe.md`).
88
+ - **Observed 2026-10-16, not represented in the catalog fixture:** `grok-composer` ids silently remapped to `grok-4.5-build`. Treat the returned serving model as authoritative; the captured catalog itself lists only the four documented model ids (`docs/diagnosis/2026-10-16-grok-live-probe.md`, `grok-models.ts`).
89
+ - `QGRID_GROK_LIVE_TOKEN_ID` is reserved by the plan for opt-in live tests and must stay unset in ordinary/CI runs; no current server runtime behavior depends on it (`docs/plans/2026-10-16-grok-provider-integration-plan.md`, §7).
@@ -1,31 +1,31 @@
1
1
  # Provider Runtime Differences
2
2
 
3
- Use this reference when comparing OpenAI and Anthropic behavior, debugging provider-specific bugs, or reviewing cross-provider changes.
4
-
5
- | Topic | OpenAI via Codex | Anthropic via Claude Code |
6
- |---|---|---|
7
- | Process lifetime | No child process; direct HTTPS/SSE request | Fresh `claude` process per request |
8
- | Worker pool | None; in-memory token pool only | None; in-memory token pool only |
9
- | Worker id | Legacy coordinate field carries token id | `tokenId` |
10
- | Epoch | Legacy compatibility value; not a process generation | Always `0` |
11
- | Request concurrency | Uncapped; stateless HTTPS/WS request per call | Uncapped; fresh process per request |
12
- | Token selection | Smooth weighted RR over quota-eligible tokens; valid affinity may prefer its token | Smooth weighted RR over quota-eligible tokens per request |
13
- | Model routing | `openai/*`; qgrid strips provider prefix before provider call | `anthropic/*`; provider canonicalizes model and strips prefix/`[1m]` |
14
- | Prefix-less models | Fallback not implemented | Fallback not implemented |
15
- | Effort vocabulary | Codex catalog levels `low`..`ultra` (Astra, GPT-6 Sol, GPT-5.6 Sol/Terra through `ultra`; GPT-6/5.6 Luna through `max`); public-API `none`/`minimal` absent | Claude Code `--effort` levels `low`..`max`; per-model caps handled by Claude Code |
16
- | Unsupported effort | Server drops it silently before the request (`resolveOpenAIEffort`), backend default applies | Server drops it silently (`resolveAnthropicEffort`), qgrid default `low` applies |
17
- | Thread/session | No provider thread retained | Fresh Claude `--session-id` per request |
18
- | `sessionKey` | AI SDK derives and replays opaque `prompt_cache_key` affinity | AI SDK intentionally disables storage/replay |
19
- | Multi-turn | Full Responses-format history is sent on every request | Fresh spawn receives flattened full history through stream-json |
20
- | Cache key | Opaque model-scoped affinity key plus stable serialized prefix | Anthropic prefix cache via Claude Code; fresh spawn still can cache stable prefixes |
21
- | Built-in tools | Direct Responses request includes only requested qgrid tools/options | Claude tools disabled via `--tools ""` on every call |
22
- | AI SDK tools | Emulated via qgrid structured output schema, then mapped to AI SDK `tool-call` content | Emulated via envelope contract rendered as prompt text (SON-532); reply parsed by `parseEnvelope`; not native Claude Code tools |
23
- | Structured output | Strict JSON schema is sent in the direct Responses request; schema changes can affect prefix cache | Schema delivered as prompt text appended to the system prompt (no `--json-schema`, no strictify); server strips fences; validation is the consumer's |
24
- | Usage accounting | Responses usage reports input including cached input | Native Anthropic categories are mutually exclusive; qgrid sums them into total input |
25
- | Cost source | qgrid model price fallback | Prefer Claude Code `total_cost_usd`, else qgrid price fallback |
26
- | Settings isolation | Per-token credentials in memory | Shared project cwd plus per-token `CLAUDE_CONFIG_DIR` |
27
- | Streaming close | `AbortSignal` cancels queue wait, retry delay, or `fetch` | Abort kills the fresh child process |
28
- | Image generation | Implemented as an opt-in direct Responses `image_generation` tool path; non-stream only | Explicitly unsupported |
3
+ Use this reference when comparing OpenAI, Anthropic, and Grok behavior, debugging provider-specific bugs, or reviewing cross-provider changes. Sources: `packages/api/src/utils/providers/{openai,anthropic,grok}/*`, `packages/api/src/application/qgrid/qgrid.dispatcher.ts`, and `references/grok-runtime.md`.
4
+
5
+ | Topic | OpenAI via Codex | Anthropic via Claude Code | Grok via grok-build fingerprint |
6
+ |---|---|---|---|
7
+ | Process lifetime | No child process; direct HTTPS/SSE or WebSocket request | Fresh `claude` process per request | No child process; direct HTTPS/SSE request |
8
+ | Worker pool | None; in-memory token pool only | None; in-memory token pool only | None; in-memory token/account pool only |
9
+ | Worker id | Legacy coordinate field carries token id | `tokenId` | Legacy coordinate field carries token id |
10
+ | Epoch | Legacy compatibility value; not a process generation | Always `0` | `-1`; not a process generation |
11
+ | Request concurrency | Uncapped; stateless request per call | Uncapped; fresh process per request | Uncapped by default; optional `QGRID_GROK_MAX_INFLIGHT_PER_TOKEN` excludes accounts at the cap |
12
+ | Token selection | Smooth weighted RR over quota-eligible tokens; valid affinity may prefer its token | Smooth weighted RR over quota-eligible tokens per request | Smooth weighted RR after quota, on-demand, cooldown, entitlement, and capacity gates; valid affinity may prefer its token |
13
+ | Model routing | `openai/*`; qgrid strips provider prefix before provider call | `anthropic/*`; provider canonicalizes model and strips prefix/`[1m]` | `grok/*`; qgrid strips the provider prefix and validates against the seeded/live catalog |
14
+ | Prefix-less models | Fallback not implemented | Fallback not implemented | Fallback not implemented |
15
+ | Effort vocabulary | Codex catalog levels `low`..`ultra` | Claude Code `--effort` levels `low`..`max` | Catalog levels `low`, `medium`, `high`, `xhigh`; thinking-off is unverified and rejected |
16
+ | Unsupported effort | Server drops it before the request; backend default applies | Server drops it; qgrid default `low` applies | Server drops it; catalog default applies |
17
+ | Thread/session | No provider thread retained | Fresh Claude `--session-id` per request | No provider thread retained; stable account session/agent ids are fingerprint headers |
18
+ | `sessionKey` | AI SDK derives and replays opaque `prompt_cache_key` affinity | AI SDK intentionally disables storage/replay | AI SDK derives and replays account-affine `prompt_cache_key` coordinates |
19
+ | Multi-turn | Full Responses-format history is sent on every request | Fresh spawn receives flattened full history through stream-json | Full Responses-format history is sent on every request |
20
+ | Cache key | Opaque model-scoped affinity key plus stable serialized prefix | Anthropic prefix cache via Claude Code | Opaque model-scoped affinity key, also used to derive Grok conversation ids |
21
+ | Built-in tools | Direct request includes only requested qgrid tools/options | Claude tools disabled via `--tools ""` | Captured proxy supports `web_search`/`x_search`, but qgrid's public tool path remains the shared emulation contract |
22
+ | AI SDK tools | Emulated via qgrid structured output schema | Emulated via prompt envelope; not native Claude Code tools | Emulated via the strict qgrid action envelope (D8), not provider-executed function tools |
23
+ | Structured output | Strict JSON schema is sent in the direct Responses request | Schema is prompt text; consumer validation owns correctness | Strict JSON schema is sent in the direct Responses request |
24
+ | Usage accounting | Input includes cached input | Native categories are summed into total input | Responses reports cached/reasoning/context tokens and `cost_in_usd_ticks` |
25
+ | Cost source | qgrid model price fallback | Prefer Claude Code `total_cost_usd`, else qgrid fallback | Provider ticks are authoritative; catalog-seeded fallback when ticks are absent |
26
+ | Settings isolation | Per-token credentials in memory | Shared project cwd plus per-token `CLAUDE_CONFIG_DIR` | Per-token OAuth credentials and stable ids in memory |
27
+ | Streaming close | `AbortSignal` cancels selection or active transport | Abort kills the fresh child process | `AbortSignal` cancels selection or active SSE; success requires `response.completed` |
28
+ | Media/voice | OpenAI image routes only | Explicitly unsupported | Image generation/editing, async video URL jobs, STT, and TTS on `api.x.ai` |
29
29
 
30
30
  ## Routing contract
31
31
 
@@ -33,13 +33,14 @@ Provider routing happens in `packages/api/src/application/qgrid/qgrid.dispatcher
33
33
 
34
34
  - `openai/<model>` routes to `OpenAIDispatcher`.
35
35
  - `anthropic/<model>` routes to `AnthropicDispatcher`.
36
+ - `grok/<model>` routes to `GrokDispatcher`.
36
37
  - models without provider prefix produce "Direct LLM API fallback not implemented".
37
38
 
38
39
  Do not silently route prefix-less Claude model names such as `claude-sonnet-4-6` to Anthropic. Tests intentionally guard against this.
39
40
 
40
41
  ## Shared contracts
41
42
 
42
- Both providers return `GenerateResult` with:
43
+ All three providers return `GenerateResult` with:
43
44
 
44
45
  - `text`
45
46
  - `tokenName`
@@ -52,6 +53,6 @@ Both providers return `GenerateResult` with:
52
53
 
53
54
  `qgrid.dispatcher.ts` maps this into `QueryOutput`, applies tool-call emulation, calculates fallback cost, and keeps the legacy `QgridThreadCoord` response shape for opaque OpenAI cache affinity.
54
55
 
55
- Both providers receive strictified output schemas from `buildStrictOutputSchema`.
56
+ OpenAI and Grok receive strictified output schemas from `buildStrictOutputSchema`; Anthropic receives the original schema as prompt text.
56
57
 
57
- Tool calling uses this shared strict-schema path. It is not native provider tool calling on either route.
58
+ Tool calling uses qgrid's shared action-envelope path. It is not native provider tool execution on any public route (`packages/api/src/application/qgrid/qgrid.dispatcher.ts`, `tool-emulation.ts`).
@@ -25,6 +25,7 @@ Use this map to orient qgrid work quickly.
25
25
  - Token trigger setup: `packages/api/src/application/qgrid/token-trigger-setup.ts`.
26
26
  - OpenAI direct backend transport, OAuth, quota, and dispatcher: `packages/api/src/utils/providers/openai/*`.
27
27
  - Anthropic Claude Code runtime: `packages/api/src/utils/providers/anthropic/*`.
28
+ - Grok chat fingerprint/transport, OAuth/refresh, quota/models, dispatcher, media, and voice: `packages/api/src/utils/providers/grok/{grok-constants.ts,grok-headers.ts,grok-backend-protocol.ts,grok-direct-client.ts,grok-oauth.ts,grok-refresh.ts,grok-quota.ts,grok-models.ts,grok-dispatcher.ts,grok-media-client.ts,grok-voice-client.ts,grok-types.ts}`. See `packages/cli/skills/qgrid/references/grok-runtime.md`.
28
29
  - Cost/usage accounting: `packages/api/src/utils/providers/common/model-cost.ts`.
29
30
  - Weighted token selection: `packages/api/src/utils/providers/common/smooth-weighted-round-robin.ts`.
30
31
  - Boot order and startup migrations: `packages/api/src/server-bootstrap.ts`, `packages/api/src/startup-migrations.ts`.
@@ -38,3 +39,12 @@ Use this map to orient qgrid work quickly.
38
39
  - Generated API files: `packages/api/src/application/sonamu.generated*`, `packages/web/src/services` when present, generated route/client files.
39
40
  - Dashboard components: `packages/web/src/components/qgrid/*`.
40
41
  - Dashboard routes: `packages/web/src/routes/*`.
42
+
43
+ ## Grok SDK and API surfaces
44
+
45
+ - Public AI SDK language/options integration: `packages/ai-sdk/src/index.ts`, `index.types.ts`, `grok-options.ts`.
46
+ - Grok image/video/transcription/speech adapters: `packages/ai-sdk/src/image-model.ts`, `video-model.ts`, `transcription-model.ts`, `speech-model.ts`.
47
+ - Grok OAuth, media, voice, limits, and video job handles: `packages/api/src/application/qgrid/qgrid.frame.ts`, `qgrid.types.ts`.
48
+ - Grok dispatcher construction and lifecycle: `packages/api/src/sonamu.config.ts`.
49
+
50
+ These paths are documented by `packages/ai-sdk/README.md` and `packages/cli/skills/qgrid/references/grok-runtime.md`.
@@ -9,6 +9,7 @@ Use this reference before changing token storage, OAuth flows, token activation,
9
9
  - Token APIs
10
10
  - Anthropic OAuth flow
11
11
  - OpenAI OAuth and refresh flow
12
+ - Grok OAuth, refresh, and quota flow
12
13
  - Token sync and reconcile
13
14
  - Provider runtime consequences
14
15
  - Quota threshold semantics
@@ -24,7 +25,8 @@ Use this reference before changing token storage, OAuth flows, token activation,
24
25
  - Token subscriber: `packages/api/src/application/qgrid/token-subscriber.ts`.
25
26
  - OpenAI direct OAuth/refresh/quota: `packages/api/src/utils/providers/openai/openai-oauth.ts`, `openai-refresh.ts`, `openai-quota.ts`.
26
27
  - Anthropic quota: `packages/api/src/utils/providers/anthropic/anthropic-quota.ts`.
27
- - Provider token event handlers: `openai-dispatcher.ts`, `anthropic-dispatcher.ts`.
28
+ - Grok OAuth/refresh/quota: `packages/api/src/utils/providers/grok/grok-oauth.ts`, `grok-refresh.ts`, `grok-quota.ts`.
29
+ - Provider token event handlers: `openai-dispatcher.ts`, `anthropic-dispatcher.ts`, `grok-dispatcher.ts`.
28
30
 
29
31
  ## Token Table Contract
30
32
 
@@ -71,10 +73,29 @@ Anthropic credentials:
71
73
  }
72
74
  ```
73
75
 
74
- Duplicate account replacement is account-identifier based:
76
+ Grok credentials (`packages/api/src/utils/providers/grok/grok-types.ts`):
77
+
78
+ ```ts
79
+ {
80
+ authMode: "oauth";
81
+ accessToken: string;
82
+ refreshToken: string;
83
+ expiresAt: string;
84
+ issuer: "https://auth.x.ai";
85
+ clientId: string;
86
+ scopes: string[];
87
+ userId: string;
88
+ sessionId: string;
89
+ agentId: string;
90
+ subscriptionTier?: string;
91
+ }
92
+ ```
93
+
94
+ Duplicate account replacement is account-identifier based (`packages/api/src/application/token/token.model.ts`):
75
95
 
76
96
  - OpenAI: `credentials.accountId`.
77
97
  - Anthropic: `credentials.accountUuid`.
98
+ - Grok: `credentials.userId`.
78
99
 
79
100
  ## Token APIs
80
101
 
@@ -152,6 +173,26 @@ Usage/quota:
152
173
  - Threshold uses primary `usedPercent`.
153
174
  - Usage lookup failure is fail-open for routing.
154
175
 
176
+ ## Grok OAuth, Refresh, And Quota Flow
177
+
178
+ Grok supports two OAuth entry paths (`grok-oauth.ts`, `packages/api/src/application/qgrid/qgrid.frame.ts`):
179
+
180
+ 1. Browser PKCE uses xAI OIDC discovery, a random `127.0.0.1` callback, the grok-build client id/scopes/referrer, and code-paste completion from either a full callback URL or bare code.
181
+ 2. Device code starts at `auth.x.ai/oauth2/device/code` and polls the token endpoint at the returned interval; `slow_down` adds five seconds.
182
+
183
+ The resulting access token must be an `at+jwt` issued by `auth.x.ai`. Qgrid confirms identity through `/user?include=subscription` and stores `userId` as the account identity key (`grok-oauth.ts`, `grok-types.ts`, `token.model.ts`).
184
+
185
+ Refresh starts 300 seconds plus stable 0–60 second jitter before expiry, is single-flight per token, keeps the previous refresh token when xAI does not rotate it, and persists rotated credentials before exposing them. `invalid_grant` and `invalid_client` require re-login; other failures remain transient. A generation 401 permits one forced refresh and same-token retry (`grok-refresh.ts`, `grok-dispatcher.ts`).
186
+
187
+ Quota and spending controls use two proxy reads (`grok-quota.ts`, `grok-dispatcher.ts`):
188
+
189
+ | Read | Routing fields | Cache/failure policy |
190
+ |---|---|---|
191
+ | `/billing?format=credits` | camelCase `config.creditUsagePercent`, weekly `currentPeriod`, prepaid balance | 60-second cache; lookup failure fails open |
192
+ | `/settings` | `on_demand_enabled`, minimum client version, feature/tier flags | 60-second cache; `true` excludes the account under D6; lookup failure fails open |
193
+
194
+ The observed weekly billing window begins at subscription start, not a calendar boundary (`docs/diagnosis/2026-10-16-grok-live-probe.md`). Quota exhaustion blocks only the affected request class until period end (one-hour fallback); a fresh below-threshold billing read clears blocks (`grok-dispatcher.ts`).
195
+
155
196
  ## Token Sync And Reconcile
156
197
 
157
198
  On server start, qgrid creates PostgreSQL triggers for `tokens_changed`.
@@ -176,7 +217,8 @@ On DELETE or missing row:
176
217
 
177
218
  - remove from `QgridDispatcher.tokens`;
178
219
  - call OpenAI `onTokenRemoved`;
179
- - call Anthropic `onTokenRemoved`.
220
+ - call Anthropic `onTokenRemoved`;
221
+ - call Grok `onTokenRemoved`.
180
222
 
181
223
  OpenAI row changes:
182
224
 
@@ -192,6 +234,12 @@ Anthropic row changes:
192
234
  - inactive row: remove from pool.
193
235
  - reconcile uses active Anthropic rows to replace the in-memory pool.
194
236
 
237
+ Grok row changes (`packages/api/src/application/qgrid/token-subscriber.ts`, `grok-dispatcher.ts`):
238
+
239
+ - active INSERT/UPDATE: validate credentials and upsert account metadata plus selector weight.
240
+ - inactive or deleted row: remove it from the in-memory pool and weighted selector.
241
+ - reconcile uses active Grok rows to replace the in-memory pool.
242
+
195
243
  ## Provider Runtime Consequences
196
244
 
197
245
  OpenAI token changes create, update, deactivate, or remove in-memory credential metadata.
@@ -202,6 +250,8 @@ OpenAI token changes create, update, deactivate, or remove in-memory credential
202
250
 
203
251
  Anthropic token changes only affect the in-memory token pool because every request fresh-spawns Claude Code.
204
252
 
253
+ Grok token changes update the in-memory OAuth credentials, quota/settings cache generation, and weighted selector. Grok has no child process; media and chat reserve the selected account for the request (`grok-dispatcher.ts`).
254
+
205
255
  ## Auth-Dead Detection And Token Registration
206
256
 
207
257
  When a refresh fails in a way that only re-login can fix, qgrid removes the token from routing instead of letting every subsequent request 401.
@@ -232,6 +282,9 @@ When a refresh fails in a way that only re-login can fix, qgrid removes the toke
232
282
  `recovered` once a later quota check falls below the threshold. Metadata generations prevent an
233
283
  in-flight lookup from restoring a block after a threshold or lifecycle change. The state is not
234
284
  persisted across server restarts.
285
+ - Grok also keeps threshold and exhaustion blocks in memory. Its exhaustion block is request-class
286
+ scoped, and `/settings.on_demand_enabled = true` independently excludes the entire account
287
+ (`packages/api/src/utils/providers/grok/grok-dispatcher.ts`).
235
288
  - If all ready/eligible tokens are over threshold, qgrid throws `QuotaThresholdExceededError`.
236
289
  - Log messages use `quota_threshold gate` with reasons such as `over_threshold`, `lookup_fail_open`, and `all_exceeded`.
237
290