@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
@@ -8,11 +8,20 @@
8
8
  * The only executable user line is the current input.
9
9
  */
10
10
 
11
+ import { z } from "zod";
12
+
11
13
  import {
12
14
  type ModelFallback,
13
15
  type ProviderTokenUsageBreakdown,
14
16
  } from "../common/provider-dispatcher";
15
- import { type JsonValue, type UserInput } from "../common/provider-types";
17
+ import {
18
+ isJsonObject,
19
+ type JsonObject,
20
+ jsonNumber,
21
+ jsonString,
22
+ type JsonValue,
23
+ type UserInput,
24
+ } from "../common/provider-types";
16
25
  import { stripFences } from "./fence-strip";
17
26
 
18
27
  // ── 입력 어댑터 ────────────────────────────────────────────────────
@@ -27,10 +36,7 @@ export interface ClaudeStreamJsonLine {
27
36
  }
28
37
 
29
38
  function userInputToText(input: Array<UserInput>): string {
30
- return input
31
- .filter((i): i is Extract<UserInput, { type: "text" }> => i.type === "text")
32
- .map((i) => i.text)
33
- .join("\n");
39
+ return input.flatMap((i) => (i.type === "text" ? [i.text] : [])).join("\n");
34
40
  }
35
41
 
36
42
  function textBlock(text: string): Array<{ type: "text"; text: string }> {
@@ -43,19 +49,22 @@ function textBlock(text: string): Array<{ type: "text"; text: string }> {
43
49
  // { type:"message", role:"assistant", content:[{type:"output_text", text}] }
44
50
  // { type:"function_call", name, arguments, call_id }
45
51
  // { type:"function_call_output", call_id, output }
46
- type ResponseItem = { [key: string]: JsonValue | undefined };
52
+ type ResponseItem = JsonObject;
47
53
 
48
54
  function asObject(v: JsonValue | undefined): ResponseItem | null {
49
- return typeof v === "object" && v !== null && !Array.isArray(v) ? (v as ResponseItem) : null;
55
+ return isJsonObject(v) ? v : null;
50
56
  }
51
57
 
52
58
  function responseItemText(item: ResponseItem): string {
53
59
  const content = item.content;
60
+
54
61
  if (!Array.isArray(content)) return "";
62
+
55
63
  return content
56
64
  .map((c) => {
57
65
  const obj = asObject(c);
58
- return obj && typeof obj.text === "string" ? obj.text : "";
66
+
67
+ return (obj && jsonString(obj.text)) ?? "";
59
68
  })
60
69
  .filter(Boolean)
61
70
  .join("\n");
@@ -63,8 +72,10 @@ function responseItemText(item: ResponseItem): string {
63
72
 
64
73
  function flattenColdHistory(coldHistory: Array<JsonValue>): string {
65
74
  const parts: Array<string> = [];
75
+
66
76
  for (const raw of coldHistory) {
67
77
  const item = asObject(raw);
78
+
68
79
  if (!item) continue;
69
80
 
70
81
  if (item.type === "message" && item.role === "assistant") {
@@ -72,16 +83,17 @@ function flattenColdHistory(coldHistory: Array<JsonValue>): string {
72
83
  } else if (item.type === "message" && item.role === "user") {
73
84
  parts.push(`User: ${responseItemText(item)}`);
74
85
  } else if (item.type === "function_call") {
75
- const name = typeof item.name === "string" ? item.name : "";
76
- const args =
77
- typeof item.arguments === "string" ? item.arguments : JSON.stringify(item.arguments ?? {});
86
+ const name = jsonString(item.name) ?? "";
87
+ const args = jsonString(item.arguments) ?? JSON.stringify(item.arguments ?? {});
88
+
78
89
  parts.push(`Tool call: ${name}(${args})`);
79
90
  } else if (item.type === "function_call_output") {
80
- const output =
81
- typeof item.output === "string" ? item.output : JSON.stringify(item.output ?? "");
91
+ const output = jsonString(item.output) ?? JSON.stringify(item.output ?? "");
92
+
82
93
  parts.push(`Tool result: ${output}`);
83
94
  }
84
95
  }
96
+
85
97
  return parts.join("\n");
86
98
  }
87
99
 
@@ -93,6 +105,7 @@ export function buildStreamJsonInput(opts: {
93
105
 
94
106
  if (opts.coldHistory && opts.coldHistory.length > 0) {
95
107
  const flattened = flattenColdHistory(opts.coldHistory);
108
+
96
109
  if (flattened) {
97
110
  lines.push({
98
111
  type: "assistant",
@@ -120,20 +133,21 @@ export function serializeStreamJsonInput(lines: Array<ClaudeStreamJsonLine>): st
120
133
  //
121
134
  // Claude stdout(JSONL)을 qgrid deltas + final result 로 변환한다.
122
135
 
123
- interface ClaudeUsage {
124
- input_tokens?: number;
125
- output_tokens?: number;
126
- cache_creation_input_tokens?: number;
127
- cache_read_input_tokens?: number;
128
- cache_creation?: {
129
- ephemeral_5m_input_tokens?: number;
130
- ephemeral_1h_input_tokens?: number;
131
- };
132
- iterations?: Array<{
133
- type?: string;
134
- model?: string;
135
- }>;
136
- }
136
+ // Usage fields are read only when they hold numbers; anything else counts as absent.
137
+ const optionalCount = z.number().optional().catch(undefined);
138
+
139
+ const ClaudeUsage = z.object({
140
+ input_tokens: optionalCount,
141
+ output_tokens: optionalCount,
142
+ cache_creation_input_tokens: optionalCount,
143
+ cache_read_input_tokens: optionalCount,
144
+ cache_creation: z
145
+ .object({ ephemeral_5m_input_tokens: optionalCount, ephemeral_1h_input_tokens: optionalCount })
146
+ .optional()
147
+ .catch(undefined),
148
+ });
149
+
150
+ type ClaudeUsage = z.infer<typeof ClaudeUsage>;
137
151
 
138
152
  export interface ClaudeStreamResult {
139
153
  text: string;
@@ -183,26 +197,34 @@ function toUsageBreakdown(u: ClaudeUsage): ProviderTokenUsageBreakdown {
183
197
  const totalInput = input + cacheCreate + cacheRead;
184
198
  const cacheCreate5m = u.cache_creation?.ephemeral_5m_input_tokens;
185
199
  const cacheCreate1h = u.cache_creation?.ephemeral_1h_input_tokens;
186
- return {
200
+
201
+ const usage: ProviderTokenUsageBreakdown = {
187
202
  totalTokens: totalInput + output,
188
203
  inputTokens: totalInput,
189
204
  cachedInputTokens: cacheRead,
190
205
  cacheCreationInputTokens: cacheCreate,
191
- ...(typeof cacheCreate5m === "number" ? { cacheCreationInputTokens5m: cacheCreate5m } : {}),
192
- ...(typeof cacheCreate1h === "number" ? { cacheCreationInputTokens1h: cacheCreate1h } : {}),
193
206
  outputTokens: output,
194
207
  reasoningOutputTokens: 0,
195
208
  };
209
+
210
+ if (cacheCreate5m !== undefined) usage.cacheCreationInputTokens5m = cacheCreate5m;
211
+
212
+ if (cacheCreate1h !== undefined) usage.cacheCreationInputTokens1h = cacheCreate1h;
213
+
214
+ return usage;
196
215
  }
197
216
 
198
217
  function structuredOutputToolUseText(j: ResponseItem): string | undefined {
199
218
  const message = asObject(j.message);
200
219
  const content = message?.content;
220
+
201
221
  if (!Array.isArray(content)) return undefined;
202
222
 
203
223
  for (const raw of content) {
204
224
  const block = asObject(raw);
225
+
205
226
  if (!block) continue;
227
+
206
228
  if (
207
229
  block.type === "tool_use" &&
208
230
  block.name === "StructuredOutput" &&
@@ -211,37 +233,43 @@ function structuredOutputToolUseText(j: ResponseItem): string | undefined {
211
233
  return JSON.stringify(block.input);
212
234
  }
213
235
  }
236
+
214
237
  return undefined;
215
238
  }
216
239
 
217
240
  function canonicalEventModel(model: string): string {
218
241
  const withoutProvider = model.startsWith("anthropic/") ? model.slice("anthropic/".length) : model;
242
+
219
243
  return withoutProvider.replace(/\[1m\]$/, "");
220
244
  }
221
245
 
222
246
  function optionalString(value: JsonValue | undefined): string | undefined {
223
- return typeof value === "string" && value.length > 0 ? value : undefined;
247
+ return jsonString(value) || undefined;
224
248
  }
225
249
 
226
250
  function recordFallback(state: ClaudeStreamJsonState | undefined, fallback: ModelFallback): void {
227
251
  if (!state) return;
252
+
228
253
  const normalized: ModelFallback = {
229
254
  ...fallback,
230
255
  fromModel: canonicalEventModel(fallback.fromModel),
231
256
  toModel: canonicalEventModel(fallback.toModel),
232
257
  };
258
+
233
259
  const existing = state.modelFallbacks?.find(
234
260
  (item) =>
235
261
  item.trigger === normalized.trigger &&
236
262
  item.fromModel === normalized.fromModel &&
237
263
  item.toModel === normalized.toModel,
238
264
  );
265
+
239
266
  if (existing) {
240
267
  existing.category ??= normalized.category;
241
268
  existing.explanation ??= normalized.explanation;
242
269
  } else {
243
270
  (state.modelFallbacks ??= []).push(normalized);
244
271
  }
272
+
245
273
  state.servedModel = normalized.toModel;
246
274
  state.refusalWithoutFallback = false;
247
275
  }
@@ -253,13 +281,17 @@ function updateRoutingFromUsage(
253
281
  if (!state || !usage || !Array.isArray(usage.iterations)) return;
254
282
 
255
283
  let previousModel: string | undefined;
284
+
256
285
  for (const raw of usage.iterations) {
257
286
  const iteration = asObject(raw);
287
+
258
288
  if (!iteration) continue;
259
289
  const model = optionalString(iteration.model);
260
290
  const type = optionalString(iteration.type);
291
+
261
292
  if (!model) continue;
262
293
  const canonicalModel = canonicalEventModel(model);
294
+
263
295
  if (type === "fallback_message" && previousModel) {
264
296
  recordFallback(state, {
265
297
  trigger: "refusal",
@@ -267,6 +299,7 @@ function updateRoutingFromUsage(
267
299
  toModel: canonicalModel,
268
300
  });
269
301
  }
302
+
270
303
  previousModel = canonicalModel;
271
304
  state.servedModel = canonicalModel;
272
305
  }
@@ -279,10 +312,13 @@ function updateRoutingFromMessage(
279
312
  if (!state || !message) return;
280
313
  const model = optionalString(message.model);
281
314
  const canonicalModel = model ? canonicalEventModel(model) : undefined;
315
+
282
316
  if (canonicalModel) state.servedModel = canonicalModel;
283
317
  const stopReason = optionalString(message.stop_reason);
318
+
284
319
  if (stopReason) {
285
320
  state.stopReason = stopReason;
321
+
286
322
  if (stopReason === "refusal") state.refusalWithoutFallback = true;
287
323
  else if (state.modelFallbacks?.some((fallback) => fallback.toModel === canonicalModel)) {
288
324
  state.refusalWithoutFallback = false;
@@ -290,12 +326,14 @@ function updateRoutingFromMessage(
290
326
  }
291
327
 
292
328
  const stopDetails = asObject(message.stop_details);
329
+
293
330
  if (stopDetails?.type === "refusal" || stopReason === "refusal") {
294
331
  state.refusal = {
295
332
  category: optionalString(stopDetails?.category),
296
333
  explanation: optionalString(stopDetails?.explanation),
297
334
  };
298
335
  }
336
+
299
337
  updateRoutingFromUsage(asObject(message.usage), state);
300
338
  }
301
339
 
@@ -308,49 +346,63 @@ export function handleStreamJsonLine(
308
346
  const structuredOutput = opts?.structuredOutput ?? false;
309
347
  const state = opts?.state;
310
348
  const trimmed = line.trim();
349
+
311
350
  if (!trimmed) return null;
312
351
 
313
- let j: { [key: string]: JsonValue | undefined };
352
+ let parsed: JsonValue;
353
+
314
354
  try {
315
- j = JSON.parse(trimmed) as { [key: string]: JsonValue | undefined };
355
+ // JSON.parse without a reviver yields only JSON values.
356
+ parsed = JSON.parse(trimmed);
316
357
  } catch {
317
358
  return null;
318
359
  }
319
360
 
361
+ // Every Claude stream-json line is an object; other JSON values carry no event.
362
+ const j = asObject(parsed) ?? {};
363
+
320
364
  if (j.type === "stream_event") {
321
365
  const event = asObject(j.event);
366
+
322
367
  if (event?.type === "message_start") {
323
368
  updateRoutingFromMessage(asObject(event.message), state);
324
369
  } else if (event?.type === "message_delta") {
325
370
  const delta = asObject(event.delta);
326
371
  const stopReason = optionalString(delta?.stop_reason);
372
+
327
373
  if (state && stopReason) {
328
374
  state.stopReason = stopReason;
375
+
329
376
  if (stopReason === "refusal") state.refusalWithoutFallback = true;
330
377
  }
331
378
  }
379
+
332
380
  if (event && event.type === "content_block_delta") {
333
381
  const delta = asObject(event.delta);
382
+
334
383
  if (delta) {
335
384
  if (structuredOutput) {
336
- if (delta.type === "input_json_delta" && typeof delta.partial_json === "string") {
337
- onDelta(delta.partial_json);
338
- }
385
+ const partialJson = jsonString(delta.partial_json);
386
+
387
+ if (delta.type === "input_json_delta" && partialJson !== undefined) onDelta(partialJson);
339
388
  } else {
340
- if (delta.type === "text_delta" && typeof delta.text === "string") {
341
- onDelta(delta.text);
342
- }
389
+ const deltaText = jsonString(delta.text);
390
+
391
+ if (delta.type === "text_delta" && deltaText !== undefined) onDelta(deltaText);
343
392
  }
344
393
  }
345
394
  }
395
+
346
396
  return null;
347
397
  }
348
398
 
349
399
  if (j.type === "system") {
350
400
  const subtype = optionalString(j.subtype);
401
+
351
402
  if (subtype === "model_refusal_fallback") {
352
403
  const fromModel = optionalString(j.originalModel) ?? optionalString(j.original_model);
353
404
  const toModel = optionalString(j.fallbackModel) ?? optionalString(j.fallback_model);
405
+
354
406
  if (fromModel && toModel) {
355
407
  recordFallback(state, {
356
408
  trigger: "refusal",
@@ -370,6 +422,7 @@ export function handleStreamJsonLine(
370
422
  }
371
423
  } else if (subtype === "model_refusal_no_fallback" && state) {
372
424
  const originalModel = optionalString(j.originalModel) ?? optionalString(j.original_model);
425
+
373
426
  if (originalModel) state.servedModel = canonicalEventModel(originalModel);
374
427
  state.stopReason = "refusal";
375
428
  state.refusalWithoutFallback = true;
@@ -386,27 +439,34 @@ export function handleStreamJsonLine(
386
439
  optionalString(j.refusal_explanation),
387
440
  };
388
441
  }
442
+
389
443
  return null;
390
444
  }
391
445
 
392
446
  if (j.type === "assistant") {
393
447
  updateRoutingFromMessage(asObject(j.message), state);
448
+
394
449
  if (structuredOutput && state && state.structuredOutputText === undefined) {
395
450
  const text = structuredOutputToolUseText(j);
451
+
396
452
  if (text !== undefined) state.structuredOutputText = text;
397
453
  }
454
+
398
455
  return null;
399
456
  }
400
457
 
401
458
  if (j.type === "result") {
402
- const subtype = typeof j.subtype === "string" ? j.subtype : undefined;
403
- const terminalReason = typeof j.terminal_reason === "string" ? j.terminal_reason : undefined;
459
+ const subtype = jsonString(j.subtype);
460
+ const terminalReason = jsonString(j.terminal_reason);
461
+
404
462
  const resultSucceeded =
405
463
  j.is_error !== true &&
406
464
  terminalReason !== "model_error" &&
407
465
  (subtype === undefined || subtype === "success");
466
+
408
467
  let text: string;
409
468
  const preservedStructuredOutput = structuredOutput ? state?.structuredOutputText : undefined;
469
+
410
470
  // Claude Code는 StructuredOutput 스키마 검증 실패 후 내부 재시도를 할 수 있다. assistant
411
471
  // 이벤트의 첫 tool input은 거절된 시도일 수 있으므로, 성공 result가 제공한 최종 검증값을
412
472
  // 우선한다. 첫 입력 보존값은 max_turns/retry 초과처럼 성공 result가 없는 진단 경로용이다.
@@ -417,21 +477,26 @@ export function handleStreamJsonLine(
417
477
  } else if (j.structured_output !== undefined) {
418
478
  text = JSON.stringify(j.structured_output);
419
479
  } else {
420
- text = stripFences(typeof j.result === "string" ? j.result : "");
480
+ text = stripFences(jsonString(j.result) ?? "");
421
481
  }
422
482
 
423
483
  const rawUsage = asObject(j.usage) ?? {};
424
484
  updateRoutingFromUsage(rawUsage, state);
425
485
  const resultModel = optionalString(j.model);
486
+
426
487
  if (state && resultModel && !state.servedModel) {
427
488
  state.servedModel = canonicalEventModel(resultModel);
428
489
  }
490
+
429
491
  const resultStopReason = optionalString(j.stop_reason);
492
+
430
493
  if (state && resultStopReason) {
431
494
  state.stopReason = resultStopReason;
495
+
432
496
  if (resultStopReason === "refusal") state.refusalWithoutFallback = true;
433
497
  }
434
- const usage = toUsageBreakdown(rawUsage as ClaudeUsage);
498
+
499
+ const usage = toUsageBreakdown(ClaudeUsage.parse(rawUsage));
435
500
  const quotaExhausted = text.startsWith("You've hit");
436
501
 
437
502
  // SON-495: 비정상 종료(error_max_structured_output_retries 등)는 정직하게 에러로 처리한다.
@@ -450,8 +515,8 @@ export function handleStreamJsonLine(
450
515
  return {
451
516
  text,
452
517
  usage,
453
- durationMs: typeof j.duration_ms === "number" ? j.duration_ms : 0,
454
- costUsd: typeof j.total_cost_usd === "number" ? j.total_cost_usd : 0,
518
+ durationMs: jsonNumber(j.duration_ms) ?? 0,
519
+ costUsd: jsonNumber(j.total_cost_usd) ?? 0,
455
520
  quotaExhausted,
456
521
  isError,
457
522
  subtype,
@@ -13,7 +13,15 @@ export function getRefreshToken(creds: TokenCredentials): string | undefined {
13
13
  }
14
14
 
15
15
  export function getExpiresAt(creds: TokenCredentials): number {
16
+ // Grok credentials (authMode "oauth") store RFC 3339; an unparseable value reads as expired.
17
+ if ("authMode" in creds) {
18
+ const parsed = Date.parse(creds.expiresAt);
19
+
20
+ return Number.isNaN(parsed) ? 0 : parsed;
21
+ }
22
+
16
23
  if ("expiresAt" in creds) return creds.expiresAt;
24
+
17
25
  return creds.accessTokenExpiresAt;
18
26
  }
19
27
 
@@ -16,11 +16,13 @@ const logger = getLogger(["qgrid", "effort"]);
16
16
  // Codex 구독 백엔드 모델 카탈로그(~/.codex/models_cache.json) 의 supported_reasoning_levels 합집합.
17
17
  // Public effort options exclude none/minimal. thinking:false maps to wire-level none separately.
18
18
  export const OPENAI_EFFORTS = ["low", "medium", "high", "xhigh", "max", "ultra"] as const;
19
+
19
20
  export type OpenAIEffort = (typeof OPENAI_EFFORTS)[number];
20
21
 
21
22
  // Claude Code `--effort` 허용값. 모델별 상한(xhigh_effort / max_effort capability)은 Claude Code 가
22
23
  // 스스로 처리하므로 qgrid 는 provider 집합만 검사한다.
23
24
  export const ANTHROPIC_EFFORTS = ["low", "medium", "high", "xhigh", "max"] as const;
25
+
24
26
  export type AnthropicEffort = (typeof ANTHROPIC_EFFORTS)[number];
25
27
 
26
28
  // 어휘 안에 있고 상한(있다면) 이하인 값만 통과시킨다. 나머지는 debug 로그 후 미지정.
@@ -31,16 +33,21 @@ function resolveWithin<T extends string>(
31
33
  target: string,
32
34
  ): T | undefined {
33
35
  if (effort === undefined) return undefined;
34
- const rank = levels.indexOf(effort as T);
36
+ const rank = levels.findIndex((level) => level === effort);
37
+
35
38
  if (rank < 0) {
36
39
  logger.debug(`ignoring effort "${effort}" for ${target}: not in ${levels.join("/")}`);
40
+
37
41
  return undefined;
38
42
  }
43
+
39
44
  if (max !== undefined && rank > levels.indexOf(max)) {
40
45
  logger.debug(`ignoring effort "${effort}" for ${target}: model supports up to "${max}"`);
46
+
41
47
  return undefined;
42
48
  }
43
- return effort as T;
49
+
50
+ return levels[rank];
44
51
  }
45
52
 
46
53
  /** canonical OpenAI model(`openai/` prefix 제거 후) 기준으로 effort 를 판정한다. */
@@ -1,6 +1,53 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
 
3
- import { calculateCostUsd, getModelCosts } from "./model-cost";
3
+ import {
4
+ calculateCostUsd,
5
+ getModelCosts,
6
+ grokImageCost,
7
+ grokReportedCost,
8
+ usdFromGrokTicks,
9
+ } from "./model-cost";
10
+
11
+ describe("Grok cost", () => {
12
+ it("converts provider ticks at 1e-10 USD", () => {
13
+ expect(usdFromGrokTicks(500_000_000)).toBe(0.05);
14
+ expect(usdFromGrokTicks(33_760_000)).toBeCloseTo(0.003376, 12);
15
+ });
16
+
17
+ it.each(["grok-4.7", "grok-4.6", "grok-4.5", "grok/grok-4.7"])(
18
+ "prices %s from the catalog ticks when the provider omitted the cost",
19
+ (model) => {
20
+ expect(getModelCosts(model)).toEqual({ inputTokens: 2, cachedInputTokens: 0.5, outputTokens: 6 });
21
+ // 1M input of which 400k cached, 100k output: 0.6*2 + 0.4*0.5 + 0.1*6.
22
+ expect(
23
+ calculateCostUsd(model, {
24
+ inputTokens: 1_000_000,
25
+ cachedInputTokens: 400_000,
26
+ outputTokens: 100_000,
27
+ }),
28
+ ).toBeCloseTo(2.0, 10);
29
+ },
30
+ );
31
+
32
+ it("prefers reported image ticks and falls back to the catalog per-image price", () => {
33
+ expect(grokImageCost("grok/grok-imagine-image-quality", 2, 700_000_000)).toEqual({
34
+ costUsd: 0.07,
35
+ costSource: "provider",
36
+ ticks: 700_000_000,
37
+ });
38
+ expect(grokImageCost("grok-imagine-image-quality", 2)).toEqual({
39
+ costUsd: 0.1,
40
+ costSource: "pricing_table",
41
+ ticks: 1_000_000_000,
42
+ });
43
+ expect(grokImageCost("grok-imagine-image-unknown", 1)).toBeUndefined();
44
+ });
45
+
46
+ it("reports video/voice cost only when xAI reported it", () => {
47
+ expect(grokReportedCost(undefined)).toBeUndefined();
48
+ expect(grokReportedCost(0)).toEqual({ costUsd: 0, costSource: "provider", ticks: 0 });
49
+ });
50
+ });
4
51
 
5
52
  describe("calculateCostUsd", () => {
6
53
  it.each([