@cartanova/qgrid-cli 2.10.10 → 2.11.0

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 (313) 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-BA7uQ-6c.js +31 -0
  204. package/bundle/web-dist/client/assets/index-Be2qCZmI.css +1 -0
  205. package/bundle/web-dist/client/assets/logs-C47OJGEI.js +1 -0
  206. package/bundle/web-dist/client/assets/monit-BS9no0dU.js +4 -0
  207. package/bundle/web-dist/client/assets/plus-sdACTfH0.js +1 -0
  208. package/bundle/web-dist/client/assets/refresh-cw-CY8o_1cT.js +1 -0
  209. package/bundle/web-dist/client/assets/request-model-BRtFuZvj.js +1 -0
  210. package/bundle/web-dist/client/assets/routes-kqgkUxE8.js +5 -0
  211. package/bundle/web-dist/client/assets/{services.generated-NP-ValHd.js → services.generated-CefiDXEv.js} +5 -5
  212. package/bundle/web-dist/client/assets/settings-DNDvFGSw.js +1 -0
  213. package/bundle/web-dist/client/assets/show-u8Np69q3.js +2 -0
  214. package/bundle/web-dist/client/assets/tokens-QvP410NW.js +1 -0
  215. package/bundle/web-dist/client/assets/total-cost-MnfKU8IN.js +1 -0
  216. package/bundle/web-dist/client/assets/use-oauth-login-flow-Bzdh28Ws.js +1 -0
  217. package/bundle/web-dist/client/assets/use-update-token-mutation-CfJKaxmR.js +1 -0
  218. package/bundle/web-dist/client/assets/vendor-react-CUFFrVN9.js +244 -0
  219. package/bundle/web-dist/client/assets/vendor-tanstack-Bf_jag9G.js +1 -0
  220. package/bundle/web-dist/client/index.html +6 -6
  221. package/bundle/web-dist/server/assets/clsx-D_N5PN_2.js +16 -0
  222. package/bundle/web-dist/server/assets/{lazyRouteComponent-CgBdabgd.js → lazyRouteComponent-D8iTIHyn.js} +129 -2
  223. package/bundle/web-dist/server/assets/logs-B3OTd9hy.js +825 -0
  224. package/bundle/web-dist/server/assets/{monit-ZPt66W5M.js → monit-B2hqorPe.js} +385 -126
  225. package/bundle/web-dist/server/assets/plus-DwG7h9kq.js +28 -0
  226. package/bundle/web-dist/server/assets/{react-dom-Ds75e4Jl.js → react-dom-BIYQzBqG.js} +2 -129
  227. package/bundle/web-dist/server/assets/refresh-cw-mMBkwOq0.js +44 -0
  228. package/bundle/web-dist/server/assets/{request-model-DjGldb-h.js → request-model-I6OdODSH.js} +15 -6
  229. package/bundle/web-dist/server/assets/{routes-Ct-k7nBA.js → routes-B95YlUv2.js} +760 -213
  230. package/bundle/web-dist/server/assets/{services.generated-BA4AcAf5.js → services.generated-DQATJ6qf.js} +12820 -12194
  231. package/bundle/web-dist/server/assets/settings-C3gbGk0m.js +830 -0
  232. package/bundle/web-dist/server/assets/{show-LSFIzvO2.js → show-Bxaj3rhH.js} +1350 -418
  233. package/bundle/web-dist/server/assets/tokens-CZjH3cB7.js +1038 -0
  234. package/bundle/web-dist/server/assets/total-cost-fTE9Xy82.js +18 -0
  235. package/bundle/web-dist/server/assets/use-oauth-login-flow-CKDHgc3U.js +2379 -0
  236. package/bundle/web-dist/server/assets/{use-update-token-mutation-pkArIzCP.js → use-update-token-mutation-BEbgOzaa.js} +1 -1
  237. package/bundle/web-dist/server/entry-server.generated.js +4295 -22810
  238. package/dist/cli.js +9 -9
  239. package/package.json +4 -11
  240. package/postinstall.mjs +12 -0
  241. package/skills/qgrid/SKILL.md +1 -0
  242. package/skills/qgrid/references/cli-env-and-server-boot.md +4 -1
  243. package/skills/qgrid/references/decision-rationale.md +23 -0
  244. package/skills/qgrid/references/grok-runtime.md +89 -0
  245. package/skills/qgrid/references/provider-runtime-differences.md +30 -29
  246. package/skills/qgrid/references/repo-map.md +10 -0
  247. package/skills/qgrid/references/token-auth-quota-lifecycle.md +56 -3
  248. package/bundle/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +0 -406
  249. package/bundle/dist/node_modules/.pnpm/@vitest_expect@4.1.10/node_modules/@vitest/expect/dist/index.js +0 -1507
  250. package/bundle/dist/node_modules/.pnpm/@vitest_pretty-format@4.1.10/node_modules/@vitest/pretty-format/dist/index.js +0 -887
  251. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/chunk-artifact.js +0 -2756
  252. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/index.js +0 -8
  253. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/utils.js +0 -8
  254. package/bundle/dist/node_modules/.pnpm/@vitest_snapshot@4.1.10/node_modules/@vitest/snapshot/dist/index.js +0 -922
  255. package/bundle/dist/node_modules/.pnpm/@vitest_spy@4.1.10/node_modules/@vitest/spy/dist/index.js +0 -386
  256. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +0 -121
  257. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/constants.js +0 -51
  258. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/diff.js +0 -1317
  259. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/display.js +0 -561
  260. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/error.js +0 -40
  261. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/helpers.js +0 -272
  262. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/offset.js +0 -27
  263. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/serialize.js +0 -77
  264. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/source-map.js +0 -381
  265. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/timers.js +0 -51
  266. package/bundle/dist/node_modules/.pnpm/chai@6.2.2/node_modules/chai/index.js +0 -2986
  267. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.js +0 -10
  268. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.js +0 -109
  269. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.js +0 -10
  270. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.js +0 -10
  271. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.js +0 -10
  272. package/bundle/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +0 -1126
  273. package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.js +0 -21
  274. package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +0 -432
  275. package/bundle/dist/node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.js +0 -517
  276. package/bundle/dist/node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js +0 -101
  277. 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
  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/_commonjsHelpers.D26ty3Ew.js +0 -9
  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/benchmark.CX_oY03V.js +0 -41
  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/evaluatedModules.Dg1zASAC.js +0 -19
  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/index.Chj8NDwU.js +0 -202
  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/chunks/index.DdgEv5B1.js +0 -46
  283. 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
  284. 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
  285. 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
  286. 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
  287. package/bundle/dist/testing/setup-mocks.js +0 -16
  288. package/bundle/src/testing/setup-mocks.ts +0 -44
  289. package/bundle/web-dist/client/assets/index-Bw2s88Ot.css +0 -1
  290. package/bundle/web-dist/client/assets/index-DZwzUfI-.js +0 -106
  291. package/bundle/web-dist/client/assets/logs-Cog79DU5.js +0 -1
  292. package/bundle/web-dist/client/assets/monit-2auznBys.js +0 -1
  293. package/bundle/web-dist/client/assets/plus-B62CuqT8.js +0 -1
  294. package/bundle/web-dist/client/assets/refresh-cw-NNcU0Cmq.js +0 -1
  295. package/bundle/web-dist/client/assets/request-model-CojtinqK.js +0 -1
  296. package/bundle/web-dist/client/assets/routes-B0lTeLK-.js +0 -5
  297. package/bundle/web-dist/client/assets/settings-D8ZxZGSJ.js +0 -1
  298. package/bundle/web-dist/client/assets/show-CFSERlnM.js +0 -2
  299. package/bundle/web-dist/client/assets/tokens-CZXUyI7O.js +0 -1
  300. package/bundle/web-dist/client/assets/use-oauth-login-flow-hboOs3wG.js +0 -1
  301. package/bundle/web-dist/client/assets/use-update-token-mutation-BQHS0byG.js +0 -1
  302. package/bundle/web-dist/client/assets/vendor-react-DH4kUfK2.js +0 -9
  303. package/bundle/web-dist/client/assets/vendor-tanstack-DJRQAbrY.js +0 -1
  304. package/bundle/web-dist/server/assets/logs-BMyR98rU.js +0 -509
  305. package/bundle/web-dist/server/assets/plus-BZ9I0VgC.js +0 -19
  306. package/bundle/web-dist/server/assets/refresh-cw-CztCFis-.js +0 -23
  307. package/bundle/web-dist/server/assets/settings-CBUZ47Xx.js +0 -461
  308. package/bundle/web-dist/server/assets/tokens-DxrBW512.js +0 -448
  309. package/bundle/web-dist/server/assets/use-oauth-login-flow-Gn8flMK5.js +0 -178
  310. package/dist/cli.d.ts +0 -10
  311. /package/bundle/web-dist/client/assets/{cost-DH2jZbrw.js → cost-DB3HbU7T.js} +0 -0
  312. /package/bundle/web-dist/client/assets/{preload-helper-ca-nBW7U.js → preload-helper-DWTEM3RW.js} +0 -0
  313. /package/bundle/web-dist/server/assets/{cost-eEHeTRT5.js → cost-BC9yzyA9.js} +0 -0
@@ -1,7 +1,17 @@
1
1
  import os from "node:os";
2
2
 
3
+ import { z } from "zod";
4
+
3
5
  import { ImageGenerationMetadata } from "../../../application/qgrid/qgrid.types";
4
6
  import { type OpenAIEffort } from "../common/effort";
7
+ import {
8
+ isJsonObject,
9
+ type JsonObject,
10
+ type JsonValue,
11
+ jsonString,
12
+ } from "../common/provider-types";
13
+
14
+ export { type JsonValue } from "../common/provider-types";
5
15
 
6
16
  export const CHATGPT_CODEX_RESPONSES_URL =
7
17
  "https://chatgpt.com/backend-api/codex/responses" as const;
@@ -22,8 +32,10 @@ function codexPlatform(): CodexUserAgentPlatform {
22
32
  linux: "Linux",
23
33
  win32: "Windows",
24
34
  };
35
+
25
36
  const terminal = process.env.TERM_PROGRAM;
26
37
  const terminalVersion = process.env.TERM_PROGRAM_VERSION;
38
+
27
39
  return {
28
40
  osType: names[process.platform] ?? process.platform,
29
41
  osVersion: os.release(),
@@ -37,16 +49,8 @@ export function codexCliUserAgent(platform: CodexUserAgentPlatform = codexPlatfo
37
49
  return `codex_cli_rs/${CODEX_CLI_VERSION} (${platform.osType} ${platform.osVersion}; ${platform.architecture}) ${platform.terminal}`;
38
50
  }
39
51
 
40
- export type JsonValue =
41
- | null
42
- | boolean
43
- | number
44
- | string
45
- | JsonValue[]
46
- | { [key: string]: JsonValue };
47
-
48
52
  /** Raw Responses API items. Keeping these opaque preserves the complete conversation history. */
49
- export type OpenAIResponseItem = Record<string, unknown>;
53
+ export type OpenAIResponseItem = JsonObject;
50
54
 
51
55
  export interface OpenAIOutputSchema {
52
56
  name?: string;
@@ -56,7 +60,8 @@ export interface OpenAIOutputSchema {
56
60
  export interface OpenAIResponsesOptions {
57
61
  model: string;
58
62
  instructions?: string;
59
- history: readonly OpenAIResponseItem[];
63
+ /** Raw conversation items, forwarded unchanged. */
64
+ history: readonly JsonValue[];
60
65
  tools?: readonly OpenAIResponseItem[];
61
66
  toolChoice?: string | OpenAIResponseItem;
62
67
  parallelToolCalls?: boolean;
@@ -74,7 +79,7 @@ export interface OpenAIResponsesOptions {
74
79
  export interface OpenAIResponsesRequest {
75
80
  model: string;
76
81
  instructions?: string;
77
- input: OpenAIResponseItem[];
82
+ input: JsonValue[];
78
83
  tools?: OpenAIResponseItem[];
79
84
  tool_choice: string | OpenAIResponseItem;
80
85
  parallel_tool_calls: boolean;
@@ -84,14 +89,16 @@ export interface OpenAIResponsesRequest {
84
89
  include: string[];
85
90
  service_tier?: string;
86
91
  prompt_cache_key?: string;
87
- text?: {
88
- verbosity?: "low" | "medium" | "high";
89
- format?: {
90
- type: "json_schema";
91
- strict: true;
92
- schema: JsonValue;
93
- name: string;
94
- };
92
+ text?: OpenAIResponsesText;
93
+ }
94
+
95
+ export interface OpenAIResponsesText {
96
+ verbosity?: "low" | "medium" | "high";
97
+ format?: {
98
+ type: "json_schema";
99
+ strict: true;
100
+ schema: JsonValue;
101
+ name: string;
95
102
  };
96
103
  }
97
104
 
@@ -99,6 +106,7 @@ export function buildOpenAIResponsesRequest(
99
106
  options: OpenAIResponsesOptions,
100
107
  ): OpenAIResponsesRequest {
101
108
  const tools = options.tools ? [...options.tools] : [];
109
+
102
110
  if (options.imageGeneration) {
103
111
  tools.push(
104
112
  options.imageGeneration === true
@@ -107,57 +115,80 @@ export function buildOpenAIResponsesRequest(
107
115
  );
108
116
  }
109
117
 
110
- const text =
111
- options.verbosity || options.outputSchema
112
- ? {
113
- ...(options.verbosity ? { verbosity: options.verbosity } : {}),
114
- ...(options.outputSchema
115
- ? {
116
- format: {
117
- type: "json_schema" as const,
118
- strict: true as const,
119
- schema: options.outputSchema.schema,
120
- name: options.outputSchema.name ?? "codex_output_schema",
121
- },
122
- }
123
- : {}),
124
- }
125
- : undefined;
126
-
127
- return {
118
+ const request: OpenAIResponsesRequest = {
128
119
  model: options.model,
129
- ...(options.instructions ? { instructions: options.instructions } : {}),
130
120
  // Copy the array, not its items: raw items must arrive byte-for-byte equivalent.
131
121
  input: [...options.history],
132
- ...(tools.length ? { tools } : {}),
133
122
  tool_choice: options.toolChoice ?? "auto",
134
123
  parallel_tool_calls: options.parallelToolCalls ?? true,
135
124
  reasoning: options.reasoning ?? null,
136
125
  store: false,
137
126
  stream: true,
138
127
  include: ["reasoning.encrypted_content"],
139
- ...(options.serviceTier ? { service_tier: options.serviceTier } : {}),
140
- ...(options.promptCacheKey ? { prompt_cache_key: options.promptCacheKey } : {}),
141
- ...(text ? { text } : {}),
142
128
  };
129
+
130
+ if (options.instructions) request.instructions = options.instructions;
131
+
132
+ if (tools.length) request.tools = tools;
133
+
134
+ if (options.serviceTier) request.service_tier = options.serviceTier;
135
+
136
+ if (options.promptCacheKey) request.prompt_cache_key = options.promptCacheKey;
137
+
138
+ if (options.verbosity || options.outputSchema) {
139
+ const text: OpenAIResponsesText = {};
140
+
141
+ if (options.verbosity) text.verbosity = options.verbosity;
142
+
143
+ if (options.outputSchema) {
144
+ text.format = {
145
+ type: "json_schema",
146
+ strict: true,
147
+ schema: options.outputSchema.schema,
148
+ name: options.outputSchema.name ?? "codex_output_schema",
149
+ };
150
+ }
151
+
152
+ request.text = text;
153
+ }
154
+
155
+ return request;
143
156
  }
144
157
 
158
+ /** Codex CLI identity headers; correlation headers are present only when supplied. */
159
+ export type CodexIdentityHeaders = {
160
+ Accept: "text/event-stream";
161
+ Authorization: string;
162
+ "ChatGPT-Account-ID": string;
163
+ "Content-Type": "application/json";
164
+ originator: typeof CODEX_CLI_ORIGINATOR;
165
+ "User-Agent": string;
166
+ "session-id"?: string;
167
+ "thread-id"?: string;
168
+ "x-client-request-id"?: string;
169
+ };
170
+
145
171
  export function buildCodexIdentityHeaders(
146
172
  accessToken: string,
147
173
  accountId: string,
148
174
  correlation?: { sessionId?: string; threadId?: string; clientRequestId?: string },
149
- ): Record<string, string> {
150
- return {
175
+ ): CodexIdentityHeaders {
176
+ const headers: CodexIdentityHeaders = {
151
177
  Accept: "text/event-stream",
152
178
  Authorization: `Bearer ${accessToken}`,
153
179
  "ChatGPT-Account-ID": accountId,
154
180
  "Content-Type": "application/json",
155
181
  originator: CODEX_CLI_ORIGINATOR,
156
182
  "User-Agent": codexCliUserAgent(),
157
- ...(correlation?.sessionId ? { "session-id": correlation.sessionId } : {}),
158
- ...(correlation?.threadId ? { "thread-id": correlation.threadId } : {}),
159
- ...(correlation?.clientRequestId ? { "x-client-request-id": correlation.clientRequestId } : {}),
160
183
  };
184
+
185
+ if (correlation?.sessionId) headers["session-id"] = correlation.sessionId;
186
+
187
+ if (correlation?.threadId) headers["thread-id"] = correlation.threadId;
188
+
189
+ if (correlation?.clientRequestId) headers["x-client-request-id"] = correlation.clientRequestId;
190
+
191
+ return headers;
161
192
  }
162
193
 
163
194
  export interface OpenAIUsage {
@@ -201,130 +232,183 @@ export class OpenAIProtocolError extends Error {
201
232
  }
202
233
  }
203
234
 
204
- function usageFrom(value: unknown): OpenAIUsage | undefined {
205
- if (!value || typeof value !== "object") return undefined;
206
- const usage = value as Record<string, unknown>;
207
- const inputDetails = (usage.input_tokens_details ?? {}) as Record<string, unknown>;
208
- const outputDetails = (usage.output_tokens_details ?? {}) as Record<string, unknown>;
235
+ const tokenCount = z.coerce.number().catch(0);
236
+
237
+ function jsonObjectOrEmpty(value: JsonValue | undefined): JsonObject {
238
+ return isJsonObject(value) ? value : {};
239
+ }
240
+
241
+ function usageFrom(value: JsonObject): OpenAIUsage {
242
+ const inputDetails = jsonObjectOrEmpty(value.input_tokens_details);
243
+ const outputDetails = jsonObjectOrEmpty(value.output_tokens_details);
244
+
209
245
  return {
210
- inputTokens: Number(usage.input_tokens ?? 0),
211
- cachedInputTokens: Number(inputDetails.cached_tokens ?? 0),
212
- outputTokens: Number(usage.output_tokens ?? 0),
213
- reasoningTokens: Number(outputDetails.reasoning_tokens ?? 0),
214
- totalTokens: Number(usage.total_tokens ?? 0),
246
+ inputTokens: tokenCount.parse(value.input_tokens ?? 0),
247
+ cachedInputTokens: tokenCount.parse(inputDetails.cached_tokens ?? 0),
248
+ outputTokens: tokenCount.parse(value.output_tokens ?? 0),
249
+ reasoningTokens: tokenCount.parse(outputDetails.reasoning_tokens ?? 0),
250
+ totalTokens: tokenCount.parse(value.total_tokens ?? 0),
215
251
  };
216
252
  }
217
253
 
218
254
  export function imageMimeType(
219
255
  base64: string,
220
- outputFormat?: unknown,
256
+ outputFormat?: JsonValue,
221
257
  ): "image/png" | "image/jpeg" | "image/webp" {
222
258
  // Inspect only the header, without decoding a potentially large image twice.
223
259
  const header = Buffer.from(base64.slice(0, 24), "base64");
260
+
224
261
  if (header.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10])))
225
262
  return "image/png";
263
+
226
264
  if (header[0] === 255 && header[1] === 216 && header[2] === 255) return "image/jpeg";
265
+
227
266
  if (header.toString("ascii", 0, 4) === "RIFF" && header.toString("ascii", 8, 12) === "WEBP")
228
267
  return "image/webp";
268
+
229
269
  if (outputFormat === "jpeg") return "image/jpeg";
270
+
230
271
  if (outputFormat === "webp") return "image/webp";
272
+
231
273
  if (outputFormat === undefined || outputFormat === "png") return "image/png";
232
- throw new OpenAIProtocolError(`Unsupported image output format: ${String(outputFormat)}`);
274
+ const label = jsonString(outputFormat) ?? JSON.stringify(outputFormat);
275
+ throw new OpenAIProtocolError(`Unsupported image output format: ${label}`);
276
+ }
277
+
278
+ type OpenAIImageEvent = Extract<OpenAINormalizedEvent, { type: "image" }>;
279
+
280
+ function imageEvent(item: JsonObject, result: string): OpenAIImageEvent {
281
+ // PNG exposes dimensions in its fixed header. Other formats retain the
282
+ // backend's observed size; never substitute requested image controls.
283
+ const header = Buffer.from(result.slice(0, 32), "base64");
284
+
285
+ const pngSize =
286
+ header.length >= 24 &&
287
+ header.subarray(0, 8).equals(Buffer.from("89504e470d0a1a0a", "hex")) &&
288
+ header.readUInt32BE(16) > 0 &&
289
+ header.readUInt32BE(20) > 0
290
+ ? `${header.readUInt32BE(16)}x${header.readUInt32BE(20)}`
291
+ : undefined;
292
+
293
+ const reportedSize = jsonString(item.size);
294
+
295
+ const size =
296
+ pngSize ??
297
+ (reportedSize !== undefined && /^[1-9]\d*x[1-9]\d*$/.test(reportedSize)
298
+ ? reportedSize
299
+ : undefined);
300
+
301
+ const id = jsonString(item.id);
302
+ const model = jsonString(item.model);
303
+ const quality = jsonString(item.quality);
304
+ const background = jsonString(item.background);
305
+ const revisedPrompt = jsonString(item.revised_prompt) ?? jsonString(item.revisedPrompt);
306
+ const generation: ImageGenerationMetadata = { route: "codex-responses" };
307
+
308
+ if (size) generation.size = size;
309
+
310
+ if (model !== undefined) generation.model = model;
311
+
312
+ if (quality !== undefined) generation.quality = quality;
313
+
314
+ if (background !== undefined) generation.background = background;
315
+
316
+ const event: OpenAIImageEvent = { type: "image", base64: result, mimeType: "image/png" };
317
+
318
+ if (id !== undefined) event.id = id;
319
+ event.base64 = result;
320
+ event.mimeType = imageMimeType(result, item.output_format);
321
+ event.generation = generation;
322
+
323
+ if (revisedPrompt !== undefined) event.revisedPrompt = revisedPrompt;
324
+
325
+ return event;
233
326
  }
234
327
 
235
- export function normalizeOpenAIEvent(raw: unknown): OpenAINormalizedEvent | undefined {
236
- if (!raw || typeof raw !== "object") return undefined;
237
- const event = raw as Record<string, unknown>;
238
- const type = String(event.type ?? "");
328
+ type OpenAICompletedEvent = Extract<OpenAINormalizedEvent, { type: "completed" }>;
329
+
330
+ function completedEvent(response: JsonObject): OpenAICompletedEvent {
331
+ const toolUsage = jsonObjectOrEmpty(response.tool_usage);
332
+ const parsedImageUsage = ImageGenerationMetadata.shape.usage.safeParse(toolUsage.image_gen);
333
+ const imageUsage = parsedImageUsage.success ? parsedImageUsage.data : undefined;
334
+
335
+ const imageTool = Array.isArray(response.tools)
336
+ ? response.tools.find((tool) => isJsonObject(tool) && tool.type === "image_generation")
337
+ : undefined;
338
+
339
+ const imageModel = isJsonObject(imageTool) ? jsonString(imageTool.model) : undefined;
340
+ const model = jsonString(response.model);
341
+
342
+ const event: OpenAICompletedEvent = {
343
+ type: "completed",
344
+ responseId: jsonString(response.id) ?? "",
345
+ };
346
+
347
+ if (isJsonObject(response.usage)) event.usage = usageFrom(response.usage);
348
+
349
+ if (model !== undefined) event.model = model;
350
+
351
+ if (imageUsage || imageModel) {
352
+ const imageGeneration: ImageGenerationMetadata = { route: "codex-responses" };
353
+
354
+ if (imageModel) imageGeneration.model = imageModel;
355
+
356
+ if (imageUsage) imageGeneration.usage = imageUsage;
357
+ event.imageGeneration = imageGeneration;
358
+ }
359
+
360
+ return event;
361
+ }
362
+
363
+ export function normalizeOpenAIEvent(raw: JsonValue): OpenAINormalizedEvent | undefined {
364
+ if (!isJsonObject(raw)) return undefined;
365
+ const event = raw;
366
+ const type = jsonString(event.type) ?? "";
367
+
239
368
  if (type === "response.created") {
240
- const response = event.response as Record<string, unknown> | undefined;
241
- return { type: "created", ...(response?.id ? { responseId: String(response.id) } : {}) };
369
+ const responseId = isJsonObject(event.response) ? jsonString(event.response.id) : undefined;
370
+
371
+ return responseId ? { type: "created", responseId } : { type: "created" };
242
372
  }
243
- if (type === "response.output_text.delta" && typeof event.delta === "string") {
244
- return {
245
- type: "text-delta",
246
- text: event.delta,
247
- ...(typeof event.item_id === "string" ? { itemId: event.item_id } : {}),
248
- };
373
+
374
+ const delta = jsonString(event.delta);
375
+
376
+ if (type === "response.output_text.delta" && delta !== undefined) {
377
+ const itemId = jsonString(event.item_id);
378
+
379
+ return itemId === undefined
380
+ ? { type: "text-delta", text: delta }
381
+ : { type: "text-delta", text: delta, itemId };
249
382
  }
383
+
250
384
  if (
251
385
  (type === "response.output_item.added" || type === "response.output_item.done") &&
252
- event.item &&
253
- typeof event.item === "object"
386
+ isJsonObject(event.item)
254
387
  ) {
255
- const item = event.item as OpenAIResponseItem;
256
- if (item.type === "image_generation_call" && typeof item.result === "string") {
257
- // PNG exposes dimensions in its fixed header. Other formats retain the
258
- // backend's observed size; never substitute requested image controls.
259
- const header = Buffer.from(item.result.slice(0, 32), "base64");
260
- const pngSize =
261
- header.length >= 24 &&
262
- header.subarray(0, 8).equals(Buffer.from("89504e470d0a1a0a", "hex")) &&
263
- header.readUInt32BE(16) > 0 &&
264
- header.readUInt32BE(20) > 0
265
- ? `${header.readUInt32BE(16)}x${header.readUInt32BE(20)}`
266
- : undefined;
267
- const size =
268
- pngSize ??
269
- (typeof item.size === "string" && /^[1-9]\d*x[1-9]\d*$/.test(item.size)
270
- ? item.size
271
- : undefined);
272
- return {
273
- type: "image",
274
- ...(typeof item.id === "string" ? { id: item.id } : {}),
275
- base64: item.result,
276
- mimeType: imageMimeType(item.result, item.output_format),
277
- generation: {
278
- route: "codex-responses",
279
- ...(size ? { size } : {}),
280
- ...(typeof item.model === "string" ? { model: item.model } : {}),
281
- ...(typeof item.quality === "string" ? { quality: item.quality } : {}),
282
- ...(typeof item.background === "string" ? { background: item.background } : {}),
283
- },
284
- ...(typeof item.revised_prompt === "string"
285
- ? { revisedPrompt: item.revised_prompt }
286
- : typeof item.revisedPrompt === "string"
287
- ? { revisedPrompt: item.revisedPrompt }
288
- : {}),
289
- };
388
+ const item = event.item;
389
+ const result = jsonString(item.result);
390
+
391
+ if (item.type === "image_generation_call" && result !== undefined) {
392
+ return imageEvent(item, result);
290
393
  }
394
+
291
395
  return { type: "output-item", item, completed: type === "response.output_item.done" };
292
396
  }
293
- if (type === "response.completed") {
294
- const response = (event.response ?? {}) as Record<string, unknown>;
295
- const toolUsage = response.tool_usage as Record<string, unknown> | undefined;
296
- const parsedImageUsage = ImageGenerationMetadata.shape.usage.safeParse(toolUsage?.image_gen);
297
- const imageUsage = parsedImageUsage.success ? parsedImageUsage.data : undefined;
298
- const imageTool = Array.isArray(response.tools)
299
- ? response.tools.find((tool) => tool?.type === "image_generation")
300
- : undefined;
301
- const imageModel = typeof imageTool?.model === "string" ? imageTool.model : undefined;
302
- return {
303
- type: "completed",
304
- responseId: String(response.id ?? ""),
305
- ...(response.usage ? { usage: usageFrom(response.usage) } : {}),
306
- ...(typeof response.model === "string" ? { model: response.model } : {}),
307
- ...(imageUsage || imageModel
308
- ? {
309
- imageGeneration: {
310
- route: "codex-responses" as const,
311
- ...(imageModel ? { model: imageModel } : {}),
312
- ...(imageUsage ? { usage: imageUsage } : {}),
313
- },
314
- }
315
- : {}),
316
- };
317
- }
397
+
398
+ if (type === "response.completed") return completedEvent(jsonObjectOrEmpty(event.response));
399
+
318
400
  if (type === "error" || type === "response.failed" || type === "response.incomplete") {
319
- const source = (event.error ?? event.response ?? event) as Record<string, unknown>;
320
- const nested = (source.error ?? source) as Record<string, unknown>;
401
+ const source = jsonObjectOrEmpty(event.error ?? event.response ?? event);
402
+ const nested = jsonObjectOrEmpty(source.error ?? source);
403
+
321
404
  return {
322
405
  type: "error",
323
406
  error: new OpenAIProtocolError(
324
- String(nested.message ?? `OpenAI stream ended with ${type}`),
325
- typeof nested.code === "string" ? nested.code : undefined,
407
+ jsonString(nested.message) ?? `OpenAI stream ended with ${type}`,
408
+ jsonString(nested.code),
326
409
  ),
327
410
  };
328
411
  }
412
+
329
413
  return undefined;
330
414
  }
@@ -1,6 +1,7 @@
1
1
  import http from "node:http";
2
2
 
3
3
  import { getLogger } from "@logtape/logtape";
4
+ import { z } from "zod";
4
5
 
5
6
  const logger = getLogger(["qgrid", "oauth"]);
6
7
 
@@ -30,19 +31,24 @@ let relay: Relay | null = null;
30
31
  function forward(request: http.IncomingMessage, response: http.ServerResponse): void {
31
32
  const current = relay;
32
33
  const incoming = new URL(request.url ?? "/", "http://localhost");
34
+
33
35
  if (!current || incoming.pathname !== OPENAI_CALLBACK_PATH) {
34
36
  response.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
35
37
  response.end("not found");
38
+
36
39
  return;
37
40
  }
38
41
 
39
42
  // Only the two OAuth result fields cross over, onto a fixed loopback base. The request never
40
43
  // contributes scheme, authority, or path bytes to the redirect target.
41
44
  const target = new URL(OPENAI_CALLBACK_PATH, current.dashboardBase);
45
+
42
46
  for (const field of ["code", "state"] as const) {
43
47
  const value = incoming.searchParams.get(field);
48
+
44
49
  if (value) target.searchParams.set(field, value);
45
50
  }
51
+
46
52
  response.writeHead(302, { Location: target.toString(), "Cache-Control": "no-store" });
47
53
  response.end();
48
54
  }
@@ -52,6 +58,7 @@ function listenOn(port: number): Promise<http.Server | null> {
52
58
  const server = http.createServer(forward);
53
59
  server.once("error", (error: NodeJS.ErrnoException) => {
54
60
  server.close();
61
+
55
62
  if (error.code === "EADDRINUSE" || error.code === "EACCES") resolve(null);
56
63
  else reject(error);
57
64
  });
@@ -73,17 +80,20 @@ export async function startOpenAICallbackRelay(
73
80
  if (relay) {
74
81
  relay.dashboardBase = dashboardBase;
75
82
  relay.expiryTimer.refresh();
83
+
76
84
  return relay.redirectUri;
77
85
  }
78
86
 
79
87
  for (const port of ports) {
80
88
  const server = await listenOn(port);
89
+
81
90
  if (!server) continue;
82
91
 
83
92
  const expiryTimer = setTimeout(() => stopOpenAICallbackRelay(), ttlMs);
84
93
  expiryTimer.unref();
85
94
  const address = server.address();
86
- const boundPort = typeof address === "object" && address ? address.port : port;
95
+ // server.address() is an AddressInfo for TCP listeners, a string for pipes, or null.
96
+ const boundPort = z.looseObject({ port: z.number() }).safeParse(address).data?.port ?? port;
87
97
  relay = {
88
98
  server,
89
99
  redirectUri: openAICallbackRedirectUri(boundPort),
@@ -91,6 +101,7 @@ export async function startOpenAICallbackRelay(
91
101
  expiryTimer,
92
102
  };
93
103
  logger.info(`openai oauth callback relay listening on 127.0.0.1:${boundPort}`);
104
+
94
105
  return relay.redirectUri;
95
106
  }
96
107
 
@@ -2,6 +2,8 @@ export const OPENAI_ISSUER = "https://auth.openai.com";
2
2
  export const OPENAI_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
3
3
  export const OPENAI_AUTHORIZE_URL = `${OPENAI_ISSUER}/oauth/authorize`;
4
4
  export const OPENAI_TOKEN_URL = `${OPENAI_ISSUER}/oauth/token`;
5
+
5
6
  export const OPENAI_SCOPES =
6
7
  "openid profile email offline_access api.connectors.read api.connectors.invoke";
8
+
7
9
  export const OPENAI_ORIGINATOR = "codex_cli_rs";