@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
@@ -0,0 +1,721 @@
1
+ import { promisify } from "node:util";
2
+ import { zstdCompress } from "node:zlib";
3
+
4
+ import { z } from "zod";
5
+
6
+ import {
7
+ isJsonObject,
8
+ type JsonObject,
9
+ type JsonValue,
10
+ jsonValueSchema,
11
+ } from "../common/provider-types";
12
+ import { type GrokReasoningEffort } from "./grok-constants";
13
+
14
+ // ---------------------------------------------------------------------------
15
+ // Request body
16
+ // ---------------------------------------------------------------------------
17
+
18
+ export type GrokInputContentPart =
19
+ | { type: "input_text"; text: string }
20
+ | { type: "input_image"; image_url: string }
21
+ | { type: "output_text"; text: string };
22
+
23
+ export type GrokInputItem =
24
+ | { type: "message"; role: "user" | "assistant"; content: string | GrokInputContentPart[] }
25
+ | { type: "function_call"; call_id: string; name: string; arguments: string; id?: string }
26
+ | { type: "function_call_output"; call_id: string; output: string }
27
+ | {
28
+ type: "reasoning";
29
+ id?: string;
30
+ summary?: Array<{ type: "summary_text"; text: string }>;
31
+ encrypted_content?: string;
32
+ };
33
+
34
+ export type GrokFunctionTool = {
35
+ type: "function";
36
+ name: string;
37
+ description?: string;
38
+ parameters: JsonValue;
39
+ strict: boolean;
40
+ };
41
+
42
+ export type GrokTool = GrokFunctionTool | { type: "web_search" } | { type: "x_search" };
43
+
44
+ export type GrokToolChoice = "auto" | "none" | "required" | { type: "function"; name: string };
45
+
46
+ export interface GrokResponsesOptions {
47
+ model: string;
48
+ /** Sent as the first `input` item; grok-build never uses `instructions`. */
49
+ systemPrompt?: string;
50
+ /** Full conversation history; qgrid replays it every turn (`store: false`). */
51
+ history: readonly GrokInputItem[];
52
+ /** grok-build sends the conversation id here. */
53
+ promptCacheKey: string;
54
+ effort: GrokReasoningEffort;
55
+ outputSchema?: { name?: string; schema: JsonValue };
56
+ tools?: readonly GrokTool[];
57
+ toolChoice?: GrokToolChoice;
58
+ maxOutputTokens?: number;
59
+ }
60
+
61
+ export type GrokInputWireItem =
62
+ | { type: "message"; role: "system"; content: string }
63
+ | Exclude<GrokInputItem, { type: "reasoning" }>
64
+ | {
65
+ type: "reasoning";
66
+ id?: string;
67
+ summary: Array<{ type: "summary_text"; text: string }>;
68
+ encrypted_content: string;
69
+ };
70
+
71
+ export interface GrokResponsesRequest {
72
+ include: ["reasoning.encrypted_content", "no_inline_citations"];
73
+ input: GrokInputWireItem[];
74
+ model: string;
75
+ prompt_cache_key: string;
76
+ reasoning: { effort: GrokReasoningEffort; summary: "concise" };
77
+ store: false;
78
+ stream: true;
79
+ text?: {
80
+ format: { type: "json_schema"; name: string; strict: true; schema: JsonValue };
81
+ };
82
+ tools?: GrokTool[];
83
+ tool_choice?: GrokToolChoice;
84
+ max_output_tokens?: number;
85
+ }
86
+
87
+ export const GROK_DEFAULT_OUTPUT_SCHEMA_NAME = "qgrid_output";
88
+
89
+ function replayItem(item: GrokInputItem): GrokInputWireItem | undefined {
90
+ if (item.type !== "reasoning") return item;
91
+
92
+ // With store:false the proxy cannot resolve a reasoning item by id; without the encrypted
93
+ // payload (for example reasoning from another account) the item is dropped, not replayed.
94
+ if (!item.encrypted_content) return undefined;
95
+
96
+ const replayed: Extract<GrokInputWireItem, { type: "reasoning" }> = {
97
+ type: "reasoning",
98
+ summary: item.summary ?? [],
99
+ encrypted_content: item.encrypted_content,
100
+ };
101
+
102
+ if (item.id) replayed.id = item.id;
103
+
104
+ return replayed;
105
+ }
106
+
107
+ /** Builds the `/responses` body in the key order of the 1.0.60 golden capture. */
108
+ export function buildGrokResponsesRequest(options: GrokResponsesOptions): GrokResponsesRequest {
109
+ if (!options.model) throw new TypeError("Grok model is required");
110
+
111
+ if (!options.promptCacheKey) throw new TypeError("Grok prompt_cache_key is required");
112
+
113
+ if (
114
+ options.maxOutputTokens !== undefined &&
115
+ (!Number.isSafeInteger(options.maxOutputTokens) || options.maxOutputTokens <= 0)
116
+ )
117
+ throw new TypeError("maxOutputTokens must be a positive integer");
118
+
119
+ const input: GrokInputWireItem[] = [];
120
+
121
+ if (options.systemPrompt)
122
+ input.push({ type: "message", role: "system", content: options.systemPrompt });
123
+
124
+ for (const item of options.history) {
125
+ const wire = replayItem(item);
126
+
127
+ if (wire) input.push(wire);
128
+ }
129
+
130
+ const request: GrokResponsesRequest = {
131
+ include: ["reasoning.encrypted_content", "no_inline_citations"],
132
+ input,
133
+ model: options.model,
134
+ prompt_cache_key: options.promptCacheKey,
135
+ reasoning: { effort: options.effort, summary: "concise" },
136
+ store: false,
137
+ stream: true,
138
+ };
139
+
140
+ if (options.outputSchema) {
141
+ request.text = {
142
+ format: {
143
+ type: "json_schema",
144
+ name: options.outputSchema.name ?? GROK_DEFAULT_OUTPUT_SCHEMA_NAME,
145
+ strict: true,
146
+ schema: options.outputSchema.schema,
147
+ },
148
+ };
149
+ }
150
+
151
+ if (options.tools?.length) request.tools = [...options.tools];
152
+
153
+ if (options.toolChoice !== undefined) request.tool_choice = options.toolChoice;
154
+
155
+ if (options.maxOutputTokens !== undefined) request.max_output_tokens = options.maxOutputTokens;
156
+
157
+ return request;
158
+ }
159
+
160
+ export interface GrokEncodedBody {
161
+ bytes: Uint8Array;
162
+ contentEncoding: "zstd" | undefined;
163
+ }
164
+
165
+ const zstdCompressAsync = promisify(zstdCompress);
166
+
167
+ /** zstd-compressed JSON body, as the 1.0.60 binary sends it (`content-encoding: zstd`). */
168
+ export async function encodeGrokRequestBody(
169
+ body: GrokResponsesRequest,
170
+ ): Promise<GrokEncodedBody & { contentEncoding: "zstd" }> {
171
+ const compressed = await zstdCompressAsync(Buffer.from(JSON.stringify(body), "utf8"));
172
+
173
+ return {
174
+ bytes: new Uint8Array(compressed.buffer, compressed.byteOffset, compressed.byteLength),
175
+ contentEncoding: "zstd",
176
+ };
177
+ }
178
+
179
+ /** Plain JSON body; the proxy accepts it too (U0 item 1). */
180
+ export function encodeGrokRequestBodyPlain(
181
+ body: GrokResponsesRequest,
182
+ ): GrokEncodedBody & { contentEncoding: undefined } {
183
+ return { bytes: new TextEncoder().encode(JSON.stringify(body)), contentEncoding: undefined };
184
+ }
185
+
186
+ // ---------------------------------------------------------------------------
187
+ // SSE events
188
+ // ---------------------------------------------------------------------------
189
+
190
+ export class GrokProtocolError extends Error {
191
+ readonly code: string | undefined;
192
+
193
+ constructor(message: string, code?: string) {
194
+ super(message);
195
+ this.name = "GrokProtocolError";
196
+ this.code = code;
197
+ }
198
+ }
199
+
200
+ export interface GrokUsage {
201
+ inputTokens: number;
202
+ cachedInputTokens: number;
203
+ outputTokens: number;
204
+ reasoningTokens: number;
205
+ totalTokens: number;
206
+ numSourcesUsed?: number;
207
+ numServerSideToolsUsed?: number;
208
+ /** 1 tick = GROK_USD_PER_TICK USD. */
209
+ costInUsdTicks?: number;
210
+ /** Live context size (`context_details`), distinct from cumulative input tokens. */
211
+ contextInputTokens?: number;
212
+ contextOutputTokens?: number;
213
+ }
214
+
215
+ export type GrokOutputItem = { type: string } & JsonObject;
216
+
217
+ export type GrokNormalizedEvent =
218
+ | { type: "created"; responseId?: string; model?: string }
219
+ | { type: "text-delta"; text: string; itemId?: string }
220
+ | { type: "reasoning-summary-delta"; text: string; itemId?: string }
221
+ | { type: "output-item"; item: GrokOutputItem; completed: boolean }
222
+ | {
223
+ type: "completed";
224
+ terminal: true;
225
+ responseId: string;
226
+ model?: string;
227
+ usage?: GrokUsage;
228
+ output?: GrokOutputItem[];
229
+ }
230
+ | {
231
+ type: "incomplete";
232
+ terminal: true;
233
+ responseId: string;
234
+ reason?: string;
235
+ model?: string;
236
+ usage?: GrokUsage;
237
+ }
238
+ | { type: "error"; terminal: true; error: GrokProtocolError };
239
+
240
+ const count = z.number().int().nonnegative();
241
+
242
+ const WireUsage = z.object({
243
+ input_tokens: count.optional(),
244
+ input_tokens_details: z.object({ cached_tokens: count.optional() }).nullish(),
245
+ output_tokens: count.optional(),
246
+ output_tokens_details: z.object({ reasoning_tokens: count.optional() }).nullish(),
247
+ total_tokens: count.optional(),
248
+ num_sources_used: count.optional(),
249
+ num_server_side_tools_used: count.optional(),
250
+ cost_in_usd_ticks: count.optional(),
251
+ context_details: z
252
+ .object({ input_tokens: count.optional(), output_tokens: count.optional() })
253
+ .nullish(),
254
+ });
255
+
256
+ // Items arrive from JSON.parse, so every extra member is a JSON value.
257
+ const WireItem = z.object({ type: z.string() }).catchall(jsonValueSchema);
258
+
259
+ const WireResponse = z.looseObject({
260
+ id: z.string().optional(),
261
+ model: z.string().optional(),
262
+ status: z.string().optional(),
263
+ usage: WireUsage.nullish(),
264
+ output: z.array(WireItem).optional(),
265
+ incomplete_details: z.object({ reason: z.string().optional() }).nullish(),
266
+ error: z.object({ message: z.string().optional(), code: z.string().optional() }).nullish(),
267
+ });
268
+
269
+ const WireEvent = z.looseObject({
270
+ type: z.string(),
271
+ response: WireResponse.optional(),
272
+ item: WireItem.optional(),
273
+ item_id: z.string().optional(),
274
+ delta: z.string().optional(),
275
+ message: z.string().optional(),
276
+ code: z.string().nullish(),
277
+ error: z.object({ message: z.string().optional(), code: z.string().optional() }).nullish(),
278
+ });
279
+
280
+ export function grokUsageFrom(usage: z.infer<typeof WireUsage>): GrokUsage {
281
+ const inputTokens = usage.input_tokens ?? 0;
282
+ const outputTokens = usage.output_tokens ?? 0;
283
+
284
+ const result: GrokUsage = {
285
+ inputTokens,
286
+ cachedInputTokens: usage.input_tokens_details?.cached_tokens ?? 0,
287
+ outputTokens,
288
+ reasoningTokens: usage.output_tokens_details?.reasoning_tokens ?? 0,
289
+ totalTokens: usage.total_tokens ?? inputTokens + outputTokens,
290
+ };
291
+
292
+ if (usage.num_sources_used !== undefined) result.numSourcesUsed = usage.num_sources_used;
293
+
294
+ if (usage.num_server_side_tools_used !== undefined) {
295
+ result.numServerSideToolsUsed = usage.num_server_side_tools_used;
296
+ }
297
+
298
+ if (usage.cost_in_usd_ticks !== undefined) result.costInUsdTicks = usage.cost_in_usd_ticks;
299
+
300
+ if (usage.context_details?.input_tokens !== undefined) {
301
+ result.contextInputTokens = usage.context_details.input_tokens;
302
+ }
303
+
304
+ if (usage.context_details?.output_tokens !== undefined) {
305
+ result.contextOutputTokens = usage.context_details.output_tokens;
306
+ }
307
+
308
+ return result;
309
+ }
310
+
311
+ export interface GrokRawSSEEvent {
312
+ event?: string;
313
+ data: string;
314
+ }
315
+
316
+ /**
317
+ * Normalizes one SSE block. Returns `undefined` for well-formed events that carry nothing a
318
+ * caller consumes (`response.in_progress`, part/done bookkeeping). Terminal events are
319
+ * `response.completed | response.incomplete | response.failed | error`; the proxy does not
320
+ * send `[DONE]`, and a `[DONE]` sentinel is ignored if one ever appears.
321
+ */
322
+ export function normalizeGrokEvent(raw: GrokRawSSEEvent): GrokNormalizedEvent | undefined {
323
+ if (raw.data.trim() === "[DONE]") return undefined;
324
+ let json: JsonValue;
325
+
326
+ try {
327
+ // JSON.parse without a reviver yields only JSON values.
328
+ json = JSON.parse(raw.data);
329
+ } catch (error) {
330
+ throw new GrokProtocolError(`Invalid Grok SSE JSON: ${String(error)}`);
331
+ }
332
+
333
+ // An SSE `event:` line names the type when the payload object omits it.
334
+ const withType =
335
+ isJsonObject(json) && !("type" in json) && raw.event ? { ...json, type: raw.event } : json;
336
+
337
+ const parsed = WireEvent.safeParse(withType);
338
+
339
+ if (!parsed.success)
340
+ throw new GrokProtocolError(`Unexpected Grok SSE event shape: ${parsed.error.message}`);
341
+ const event = parsed.data;
342
+ const response = event.response;
343
+
344
+ switch (event.type) {
345
+ case "response.created": {
346
+ const created: GrokNormalizedEvent = { type: "created" };
347
+
348
+ if (response?.id) created.responseId = response.id;
349
+
350
+ if (response?.model) created.model = response.model;
351
+
352
+ return created;
353
+ }
354
+
355
+ case "response.output_text.delta":
356
+ if (event.delta === undefined) return undefined;
357
+
358
+ return event.item_id
359
+ ? { type: "text-delta", text: event.delta, itemId: event.item_id }
360
+ : { type: "text-delta", text: event.delta };
361
+ case "response.reasoning_summary_text.delta":
362
+ if (event.delta === undefined) return undefined;
363
+
364
+ return event.item_id
365
+ ? { type: "reasoning-summary-delta", text: event.delta, itemId: event.item_id }
366
+ : { type: "reasoning-summary-delta", text: event.delta };
367
+ case "response.output_item.added":
368
+ case "response.output_item.done":
369
+ if (!event.item) return undefined;
370
+
371
+ return {
372
+ type: "output-item",
373
+ item: event.item,
374
+ completed: event.type === "response.output_item.done",
375
+ };
376
+ case "response.completed": {
377
+ const usage = response?.usage ? grokUsageFrom(response.usage) : undefined;
378
+
379
+ const completed: GrokNormalizedEvent = {
380
+ type: "completed",
381
+ terminal: true,
382
+ responseId: response?.id ?? "",
383
+ };
384
+
385
+ if (response?.model) completed.model = response.model;
386
+
387
+ if (usage) completed.usage = usage;
388
+
389
+ if (response?.output) completed.output = response.output;
390
+
391
+ return completed;
392
+ }
393
+
394
+ case "response.incomplete": {
395
+ const usage = response?.usage ? grokUsageFrom(response.usage) : undefined;
396
+ const reason = response?.incomplete_details?.reason;
397
+
398
+ const incomplete: GrokNormalizedEvent = {
399
+ type: "incomplete",
400
+ terminal: true,
401
+ responseId: response?.id ?? "",
402
+ };
403
+
404
+ if (reason) incomplete.reason = reason;
405
+
406
+ if (response?.model) incomplete.model = response.model;
407
+
408
+ if (usage) incomplete.usage = usage;
409
+
410
+ return incomplete;
411
+ }
412
+
413
+ case "response.failed":
414
+ case "error": {
415
+ const nested = event.error ?? response?.error ?? undefined;
416
+ const message = nested?.message ?? event.message ?? `Grok stream ended with ${event.type}`;
417
+ const code = nested?.code ?? event.code ?? undefined;
418
+
419
+ return { type: "error", terminal: true, error: new GrokProtocolError(message, code) };
420
+ }
421
+
422
+ default:
423
+ return undefined;
424
+ }
425
+ }
426
+
427
+ function parseSSEBlock(block: string): GrokRawSSEEvent | undefined {
428
+ const data: string[] = [];
429
+ let event: string | undefined;
430
+
431
+ for (const line of block.split("\n")) {
432
+ if (line.startsWith(":")) continue;
433
+ const separator = line.indexOf(":");
434
+ const field = separator < 0 ? line : line.slice(0, separator);
435
+ let value = separator < 0 ? "" : line.slice(separator + 1);
436
+
437
+ if (value.startsWith(" ")) value = value.slice(1);
438
+
439
+ if (field === "data") data.push(value);
440
+ else if (field === "event") event = value;
441
+ }
442
+
443
+ if (!data.length) return undefined;
444
+
445
+ const parsed: GrokRawSSEEvent = { data: data.join("\n") };
446
+
447
+ if (event !== undefined) parsed.event = event;
448
+
449
+ return parsed;
450
+ }
451
+
452
+ /** Splits a byte stream into SSE blocks across arbitrary UTF-8/chunk boundaries. */
453
+ export async function* parseGrokSSE(
454
+ body: ReadableStream<Uint8Array>,
455
+ ): AsyncGenerator<GrokRawSSEEvent> {
456
+ const reader = body.getReader();
457
+ const decoder = new TextDecoder();
458
+ let buffer = "";
459
+ // A trailing CR may be the first half of a CRLF split across chunks; hold it back.
460
+ let pending = "";
461
+ let first = true;
462
+
463
+ try {
464
+ while (true) {
465
+ const { done, value } = await reader.read();
466
+ let chunk = pending + decoder.decode(value, { stream: !done });
467
+ pending = "";
468
+
469
+ if (first && chunk.length) {
470
+ if (chunk.startsWith("\uFEFF")) chunk = chunk.slice(1);
471
+ first = false;
472
+ }
473
+
474
+ if (!done && chunk.endsWith("\r")) {
475
+ pending = "\r";
476
+ chunk = chunk.slice(0, -1);
477
+ }
478
+
479
+ buffer += chunk.replaceAll("\r\n", "\n").replaceAll("\r", "\n");
480
+ let index: number;
481
+
482
+ while ((index = buffer.indexOf("\n\n")) >= 0) {
483
+ const block = parseSSEBlock(buffer.slice(0, index));
484
+ buffer = buffer.slice(index + 2);
485
+
486
+ if (block) yield block;
487
+ }
488
+
489
+ if (done) break;
490
+ }
491
+
492
+ if (buffer.trim()) {
493
+ const block = parseSSEBlock(buffer);
494
+
495
+ if (block) yield block;
496
+ }
497
+ } finally {
498
+ reader.releaseLock();
499
+ }
500
+ }
501
+
502
+ /** Normalized stream that ends at the first terminal event and rejects a truncated stream. */
503
+ export async function* normalizeGrokSSE(
504
+ body: ReadableStream<Uint8Array>,
505
+ ): AsyncGenerator<GrokNormalizedEvent> {
506
+ for await (const raw of parseGrokSSE(body)) {
507
+ const event = normalizeGrokEvent(raw);
508
+
509
+ if (!event) continue;
510
+ yield event;
511
+
512
+ if ("terminal" in event) return;
513
+ }
514
+
515
+ throw new GrokProtocolError("Grok SSE connection closed before a terminal event");
516
+ }
517
+
518
+ // ---------------------------------------------------------------------------
519
+ // Response headers and HTTP errors
520
+ // ---------------------------------------------------------------------------
521
+
522
+ type HeaderSource = Headers | Readonly<Record<string, string | undefined>>;
523
+
524
+ function headerValue(headers: HeaderSource, name: string): string | undefined {
525
+ if (headers instanceof Headers) return headers.get(name) ?? undefined;
526
+ const key = Object.keys(headers).find((candidate) => candidate.toLowerCase() === name);
527
+
528
+ return key === undefined ? undefined : headers[key];
529
+ }
530
+
531
+ function integerHeader(headers: HeaderSource, name: string): number | undefined {
532
+ const value = headerValue(headers, name)?.trim();
533
+
534
+ if (!value || !/^\d+$/.test(value)) return undefined;
535
+ const parsed = Number(value);
536
+
537
+ return Number.isSafeInteger(parsed) ? parsed : undefined;
538
+ }
539
+
540
+ /** `Retry-After` as whole seconds (delta-seconds or HTTP-date). Uncapped; callers clamp. */
541
+ export function parseRetryAfterSec(
542
+ headers: HeaderSource,
543
+ now: number = Date.now(),
544
+ ): number | undefined {
545
+ const value = headerValue(headers, "retry-after")?.trim();
546
+
547
+ if (!value) return undefined;
548
+
549
+ if (/^\d+$/.test(value)) return Number(value);
550
+ const date = Date.parse(value);
551
+
552
+ if (Number.isNaN(date)) return undefined;
553
+
554
+ return Math.max(0, Math.ceil((date - now) / 1000));
555
+ }
556
+
557
+ export function parseShouldRetry(headers: HeaderSource): boolean | undefined {
558
+ const value = headerValue(headers, "x-should-retry")?.trim().toLowerCase();
559
+
560
+ if (value === "true") return true;
561
+
562
+ if (value === "false") return false;
563
+
564
+ return undefined;
565
+ }
566
+
567
+ export interface GrokResponseHeaderInfo {
568
+ contextWindow?: number;
569
+ maxCompletionTokens?: number;
570
+ modelsEtag?: string;
571
+ requestId?: string;
572
+ rateLimitLimitTokens?: number;
573
+ rateLimitRemainingTokens?: number;
574
+ rateLimitLimitRequests?: number;
575
+ rateLimitRemainingRequests?: number;
576
+ /** `x-zero-data-retention: true`: the account has Zero Data Retention on (U0, plan §11). */
577
+ zeroDataRetention?: boolean;
578
+ }
579
+
580
+ /** Response headers grok-build reads (client.rs:187-224) plus the observed rate-limit set. */
581
+ export function readGrokResponseHeaders(headers: HeaderSource): GrokResponseHeaderInfo {
582
+ const zdr = headerValue(headers, "x-zero-data-retention")?.trim().toLowerCase();
583
+
584
+ const entries: Array<[keyof GrokResponseHeaderInfo, number | string | boolean | undefined]> = [
585
+ ["contextWindow", integerHeader(headers, "x-grok-context-window")],
586
+ ["maxCompletionTokens", integerHeader(headers, "x-grok-max-completion-tokens")],
587
+ ["modelsEtag", headerValue(headers, "x-models-etag")],
588
+ ["requestId", headerValue(headers, "x-request-id")],
589
+ ["rateLimitLimitTokens", integerHeader(headers, "x-ratelimit-limit-tokens")],
590
+ ["rateLimitRemainingTokens", integerHeader(headers, "x-ratelimit-remaining-tokens")],
591
+ ["rateLimitLimitRequests", integerHeader(headers, "x-ratelimit-limit-requests")],
592
+ ["rateLimitRemainingRequests", integerHeader(headers, "x-ratelimit-remaining-requests")],
593
+ ["zeroDataRetention", zdr === "true" ? true : zdr === "false" ? false : undefined],
594
+ ];
595
+
596
+ return Object.fromEntries(entries.filter(([, value]) => value !== undefined));
597
+ }
598
+
599
+ export type GrokHttpErrorKind =
600
+ | "auth"
601
+ | "version_gate"
602
+ | "rate_limited"
603
+ | "quota_exhausted"
604
+ | "entitlement"
605
+ | "invalid_request"
606
+ | "transient"
607
+ | "permanent";
608
+
609
+ export interface GrokHttpErrorClassification {
610
+ kind: GrokHttpErrorKind;
611
+ status: number;
612
+ retryAfterSec?: number;
613
+ code?: string;
614
+ message?: string;
615
+ /** `x-should-retry` override from the server; callers must honor it over `kind`. */
616
+ shouldRetry?: boolean;
617
+ /** Minimum CLI version named by a 426 body. */
618
+ minClientVersion?: string;
619
+ }
620
+
621
+ const MAX_ERROR_MESSAGE_LENGTH = 500;
622
+ const SUBSCRIPTION_CODE_PATTERN = /subscription:[a-z0-9][a-z0-9_.-]*/i;
623
+
624
+ const ErrorObject = z.looseObject({
625
+ code: z.string().optional(),
626
+ message: z.string().optional(),
627
+ type: z.string().optional(),
628
+ });
629
+
630
+ const ErrorBody = z.looseObject({
631
+ code: z.string().optional(),
632
+ message: z.string().optional(),
633
+ error: z.union([z.string(), ErrorObject]).optional(),
634
+ });
635
+
636
+ interface GrokErrorBody {
637
+ code?: string;
638
+ message?: string;
639
+ }
640
+
641
+ function parseErrorBody(bodyText: string): GrokErrorBody {
642
+ let json: JsonValue;
643
+
644
+ try {
645
+ // JSON.parse without a reviver yields only JSON values.
646
+ json = JSON.parse(bodyText);
647
+ } catch {
648
+ return bodyText.trim() ? { message: bodyText.trim() } : {};
649
+ }
650
+
651
+ const parsed = ErrorBody.safeParse(json);
652
+
653
+ if (!parsed.success) return bodyText.trim() ? { message: bodyText.trim() } : {};
654
+ const { error } = parsed.data;
655
+ const errorText = z.string().safeParse(error).data;
656
+ const errorObject = ErrorObject.safeParse(error).data;
657
+ const code = parsed.data.code ?? errorObject?.code;
658
+ const message = errorText ?? errorObject?.message ?? parsed.data.message;
659
+ const body: GrokErrorBody = {};
660
+
661
+ if (code) body.code = code;
662
+
663
+ if (message) body.message = message;
664
+
665
+ return body;
666
+ }
667
+
668
+ /**
669
+ * Classifies a non-2xx proxy or api.x.ai response. Pass `status = 0` for a network failure.
670
+ * The body is not trusted to be JSON.
671
+ */
672
+ export function classifyGrokHttpError(
673
+ status: number,
674
+ bodyText: string,
675
+ headers: HeaderSource,
676
+ ): GrokHttpErrorClassification {
677
+ const body = parseErrorBody(bodyText);
678
+
679
+ const message =
680
+ body.message === undefined ? undefined : body.message.slice(0, MAX_ERROR_MESSAGE_LENGTH);
681
+
682
+ const shouldRetry = parseShouldRetry(headers);
683
+ const retryAfterSec = parseRetryAfterSec(headers);
684
+
685
+ const base: Omit<GrokHttpErrorClassification, "kind"> = { status };
686
+
687
+ if (body.code) base.code = body.code;
688
+
689
+ if (message !== undefined) base.message = message;
690
+
691
+ if (shouldRetry !== undefined) base.shouldRetry = shouldRetry;
692
+
693
+ if (retryAfterSec !== undefined) base.retryAfterSec = retryAfterSec;
694
+
695
+ const subscriptionCode = SUBSCRIPTION_CODE_PATTERN.exec(bodyText)?.[0];
696
+
697
+ if (status === 401) return { kind: "auth", ...base };
698
+
699
+ if (status === 426) {
700
+ const minClientVersion = /\bversion\s+(\d+\.\d+\.\d+)\s+or later/i.exec(bodyText)?.[1];
701
+ const gate: GrokHttpErrorClassification = { kind: "version_gate", ...base };
702
+
703
+ if (minClientVersion) gate.minClientVersion = minClientVersion;
704
+
705
+ return gate;
706
+ }
707
+
708
+ if (status === 429) {
709
+ if (subscriptionCode) return { kind: "quota_exhausted", ...base, code: subscriptionCode };
710
+
711
+ return { kind: "rate_limited", ...base };
712
+ }
713
+
714
+ if (status === 403) return { kind: "entitlement", ...base };
715
+
716
+ if (status === 400 || status === 422) return { kind: "invalid_request", ...base };
717
+
718
+ if (status === 0 || status === 408 || status >= 500) return { kind: "transient", ...base };
719
+
720
+ return { kind: "permanent", ...base };
721
+ }