@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
@@ -12,6 +12,7 @@ import {
12
12
  } from "sonamu";
13
13
 
14
14
  import { SD } from "../../i18n/sd.generated";
15
+ import { isProviderId, type ProviderId } from "../../utils/providers/common/provider-types";
15
16
  import { type TokenSubsetKey, type TokenSubsetMapping } from "../sonamu.generated";
16
17
  import { tokenLoaderQueries, tokenSubsetQueries } from "../sonamu.generated.sso";
17
18
  import { type TokenCredentials, type TokenListParams, type TokenSaveParams } from "./token.types";
@@ -29,13 +30,40 @@ export type TokenUpdateFields = {
29
30
  keepalive_enabled?: boolean;
30
31
  };
31
32
 
33
+ // provider 별로 같은 계정을 식별하는 credentials JSONB 키. 재로그인 dedup 과 계정 조회가 함께 쓴다.
34
+ export const TOKEN_IDENTITY_KEYS = {
35
+ anthropic: "accountUuid",
36
+ openai: "accountId",
37
+ grok: "userId",
38
+ } as const satisfies Record<ProviderId, string>;
39
+
40
+ export type TokenIdentityKey = (typeof TOKEN_IDENTITY_KEYS)[ProviderId];
41
+
42
+ export class UnknownTokenProviderError extends Error {
43
+ readonly provider: string;
44
+
45
+ constructor(provider: string) {
46
+ super(`Unknown token provider: ${provider}`);
47
+ this.name = "UnknownTokenProviderError";
48
+ this.provider = provider;
49
+ }
50
+ }
51
+
52
+ export function tokenIdentityKey(provider: string): TokenIdentityKey {
53
+ if (!isProviderId(provider)) throw new UnknownTokenProviderError(provider);
54
+
55
+ return TOKEN_IDENTITY_KEYS[provider];
56
+ }
57
+
32
58
  function applyCreateDefaults(sp: TokenSaveParams): TokenSaveParams {
33
59
  if (sp.id !== undefined) return sp;
34
- return {
35
- ...sp,
36
- ...(sp.quota_threshold === undefined ? { quota_threshold: DEFAULT_QUOTA_THRESHOLD } : {}),
37
- ...(sp.weight === undefined ? { weight: DEFAULT_WEIGHT } : {}),
38
- };
60
+ const withDefaults: TokenSaveParams = { ...sp };
61
+
62
+ if (sp.quota_threshold === undefined) withDefaults.quota_threshold = DEFAULT_QUOTA_THRESHOLD;
63
+
64
+ if (sp.weight === undefined) withDefaults.weight = DEFAULT_WEIGHT;
65
+
66
+ return withDefaults;
39
67
  }
40
68
 
41
69
  class TokenModelClass extends BaseModelClass<
@@ -51,9 +79,11 @@ class TokenModelClass extends BaseModelClass<
51
79
  @api({ httpMethod: "GET", clients: ["axios", "tanstack-query"], resourceName: "Token" })
52
80
  async findById<T extends TokenSubsetKey>(subset: T, id: number): Promise<TokenSubsetMapping[T]> {
53
81
  const { rows } = await this.findMany(subset, { id, num: 1, page: 1, queryMode: "list" });
82
+
54
83
  if (!rows[0]) {
55
84
  throw new NotFoundException(SD("error.entityNotFound")("Token", id));
56
85
  }
86
+
57
87
  return rows[0];
58
88
  }
59
89
 
@@ -67,6 +97,7 @@ class TokenModelClass extends BaseModelClass<
67
97
  page: 1,
68
98
  queryMode: "list",
69
99
  });
100
+
70
101
  return rows[0] ?? null;
71
102
  }
72
103
 
@@ -119,14 +150,16 @@ class TokenModelClass extends BaseModelClass<
119
150
  accountId: string,
120
151
  ): Promise<TokenSubsetMapping[T][]> {
121
152
  const { qb } = this.getSubsetQueries(subset);
153
+ const jsonKey = tokenIdentityKey(provider);
122
154
  qb.where("tokens.provider", provider);
123
- const jsonKey = provider === "anthropic" ? "accountUuid" : "accountId";
124
155
  qb.whereRaw(`tokens.credentials->>'${jsonKey}' = ?`, [accountId]);
156
+
125
157
  const result = await this.executeSubsetQuery({
126
158
  subset,
127
159
  qb,
128
160
  params: { num: 0, page: 1, queryMode: "list" },
129
161
  });
162
+
130
163
  return result.rows;
131
164
  }
132
165
 
@@ -137,11 +170,13 @@ class TokenModelClass extends BaseModelClass<
137
170
  const { qb } = this.getSubsetQueries(subset);
138
171
  qb.where("tokens.active", true);
139
172
  qb.where("tokens.provider", provider);
173
+
140
174
  const result = await this.executeSubsetQuery({
141
175
  subset,
142
176
  qb,
143
177
  params: { num: 0, page: 1, queryMode: "list" },
144
178
  });
179
+
145
180
  return result.rows;
146
181
  }
147
182
 
@@ -154,11 +189,13 @@ class TokenModelClass extends BaseModelClass<
154
189
  qb.where("tokens.active", true);
155
190
  qb.where("tokens.provider", provider);
156
191
  qb.where("tokens.name", name);
192
+
157
193
  const result = await this.executeSubsetQuery({
158
194
  subset,
159
195
  qb,
160
196
  params: { num: 1, page: 1, queryMode: "list" },
161
197
  });
198
+
162
199
  return result.rows[0];
163
200
  }
164
201
 
@@ -167,22 +204,26 @@ class TokenModelClass extends BaseModelClass<
167
204
  const { qb } = this.getSubsetQueries(subset);
168
205
  qb.where("tokens.reauth_required", true);
169
206
  qb.orderBy("tokens.name", "asc");
207
+
170
208
  const result = await this.executeSubsetQuery({
171
209
  subset,
172
210
  qb,
173
211
  params: { num: 0, page: 1, queryMode: "list" },
174
212
  });
213
+
175
214
  return result.rows;
176
215
  }
177
216
 
178
217
  async findActive<T extends TokenSubsetKey>(subset: T): Promise<TokenSubsetMapping[T][]> {
179
218
  const { qb } = this.getSubsetQueries(subset);
180
219
  qb.where("tokens.active", true);
220
+
181
221
  const result = await this.executeSubsetQuery({
182
222
  subset,
183
223
  qb,
184
224
  params: { num: 0, page: 1, queryMode: "list" },
185
225
  });
226
+
186
227
  return result.rows;
187
228
  }
188
229
 
@@ -191,6 +232,7 @@ class TokenModelClass extends BaseModelClass<
191
232
  spa.forEach((sp) => {
192
233
  wdb.ubRegister("tokens", applyCreateDefaults(sp));
193
234
  });
235
+
194
236
  return wdb.transaction(async (trx) => {
195
237
  return trx.ubUpsert("tokens");
196
238
  });
@@ -198,11 +240,13 @@ class TokenModelClass extends BaseModelClass<
198
240
 
199
241
  async updateFields(id: number, fields: TokenUpdateFields): Promise<number> {
200
242
  const wdb = this.getPuri("w");
243
+
201
244
  return wdb.transaction((trx) => trx.table("tokens").where("id", id).update(fields));
202
245
  }
203
246
 
204
247
  async toggleActive(id: number): Promise<{ active: boolean; reauthRequired: boolean } | null> {
205
248
  const wdb = this.getPuri("w");
249
+
206
250
  return wdb.transaction(async (trx) => {
207
251
  const token = await trx
208
252
  .from("tokens")
@@ -210,13 +254,16 @@ class TokenModelClass extends BaseModelClass<
210
254
  .where("id", id)
211
255
  .forUpdate()
212
256
  .first();
257
+
213
258
  if (!token) return null;
259
+
214
260
  if (!token.active && token.reauth_required) {
215
261
  return { active: false, reauthRequired: true };
216
262
  }
217
263
 
218
264
  const active = !token.active;
219
265
  await trx.from("tokens").where("id", id).update({ active });
266
+
220
267
  return { active, reauthRequired: false };
221
268
  });
222
269
  }
@@ -232,10 +279,11 @@ class TokenModelClass extends BaseModelClass<
232
279
  accountId: string | undefined,
233
280
  saveParams: TokenSaveParams,
234
281
  ): Promise<void> {
282
+ const jsonKey = tokenIdentityKey(provider);
235
283
  await this.getPuri("w").transaction(async (trx) => {
236
284
  let replacement = saveParams;
285
+
237
286
  if (accountId) {
238
- const jsonKey = provider === "anthropic" ? "accountUuid" : "accountId";
239
287
  const oldEntries = await trx
240
288
  .from("tokens")
241
289
  .select({
@@ -249,7 +297,9 @@ class TokenModelClass extends BaseModelClass<
249
297
  .whereRaw(`credentials->>'${jsonKey}' = ?`, [accountId])
250
298
  .orderBy("id", "asc")
251
299
  .forUpdate();
300
+
252
301
  const first = oldEntries[0];
302
+
253
303
  if (first) {
254
304
  replacement = {
255
305
  ...saveParams,
@@ -290,6 +340,7 @@ class TokenModelClass extends BaseModelClass<
290
340
  expectedCredentials: TokenCredentials,
291
341
  ): Promise<{ marked: boolean; wasLastActive: boolean; staleCredentials: boolean }> {
292
342
  const wdb = this.getPuri("w");
343
+
293
344
  return wdb.transaction(async (trx) => {
294
345
  const token = await trx
295
346
  .from("tokens")
@@ -301,9 +352,11 @@ class TokenModelClass extends BaseModelClass<
301
352
  .where("id", id)
302
353
  .forUpdate()
303
354
  .first();
355
+
304
356
  if (!token || token.reauth_required) {
305
357
  return { marked: false, wasLastActive: false, staleCredentials: false };
306
358
  }
359
+
307
360
  if (!isDeepStrictEqual(token.credentials, expectedCredentials)) {
308
361
  return { marked: false, wasLastActive: false, staleCredentials: true };
309
362
  }
@@ -312,6 +365,7 @@ class TokenModelClass extends BaseModelClass<
312
365
  TOKEN_AUTH_DEATH_LOCK_CLASS_ID,
313
366
  token.provider,
314
367
  ]);
368
+
315
369
  const updated = await trx.knex.raw<{ rows: { was_last_active: boolean }[] }>(
316
370
  `WITH previous AS (
317
371
  SELECT active AND NOT EXISTS (
@@ -327,12 +381,15 @@ class TokenModelClass extends BaseModelClass<
327
381
  RETURNING (SELECT was_last_active FROM previous) AS was_last_active`,
328
382
  [id, id],
329
383
  );
384
+
330
385
  const marked = updated.rows[0];
386
+
331
387
  if (!marked) return { marked: false, wasLastActive: false, staleCredentials: false };
332
388
 
333
389
  if (marked.was_last_active) {
334
390
  logger.error(`deactivated expired token ${id}: no usable provider tokens remain`);
335
391
  }
392
+
336
393
  return { marked: true, wasLastActive: marked.was_last_active, staleCredentials: false };
337
394
  });
338
395
  }
@@ -354,6 +411,7 @@ class TokenModelClass extends BaseModelClass<
354
411
  await trx.table("tokens").where("id", ids[i]!).update({ ord: i });
355
412
  }
356
413
  });
414
+
357
415
  return { done: true };
358
416
  }
359
417
 
@@ -363,6 +421,7 @@ class TokenModelClass extends BaseModelClass<
363
421
  await wdb.transaction(async (trx) => {
364
422
  return trx.table("tokens").whereIn("tokens.id", ids).delete();
365
423
  });
424
+
366
425
  return ids.length;
367
426
  }
368
427
  }
@@ -10,6 +10,7 @@ export const AnthropicCredentials = z.object({
10
10
  expiresAt: z.number(),
11
11
  accountUuid: z.string(),
12
12
  });
13
+
13
14
  export type AnthropicCredentials = z.infer<typeof AnthropicCredentials>;
14
15
 
15
16
  export const OpenAICredentials = z.object({
@@ -21,13 +22,34 @@ export const OpenAICredentials = z.object({
21
22
  accountId: z.string(),
22
23
  planType: z.string().optional(),
23
24
  });
25
+
24
26
  export type OpenAICredentials = z.infer<typeof OpenAICredentials>;
25
27
 
26
- export const TokenCredentials = z.union([AnthropicCredentials, OpenAICredentials]);
28
+ // Web-safe storage shape only. Registration and refresh validate with the strict schema in
29
+ // utils/providers/grok/grok-types.ts (at+jwt from auth.x.ai, GUID ids).
30
+ export const GrokCredentials = z.object({
31
+ authMode: z.literal("oauth"),
32
+ accessToken: z.string(),
33
+ refreshToken: z.string(),
34
+ expiresAt: z.string(),
35
+ issuer: z.literal("https://auth.x.ai"),
36
+ clientId: z.string(),
37
+ scopes: z.array(z.string()),
38
+ userId: z.string(),
39
+ sessionId: z.string(),
40
+ agentId: z.string(),
41
+ subscriptionTier: z.string().optional(),
42
+ });
43
+
44
+ export type GrokCredentials = z.infer<typeof GrokCredentials>;
45
+
46
+ export const TokenCredentials = z.union([AnthropicCredentials, OpenAICredentials, GrokCredentials]);
47
+
27
48
  export type TokenCredentials = z.infer<typeof TokenCredentials>;
28
49
 
29
50
  // Token - ListParams
30
51
  export const TokenListParams = TokenBaseListParams;
52
+
31
53
  export type TokenListParams = z.infer<typeof TokenListParams>;
32
54
 
33
55
  const TokenQuotaThreshold = z.int().min(1).max(100).nullable();
@@ -47,4 +69,5 @@ export const TokenSaveParams = TokenBaseSchema.partial({
47
69
  quota_threshold: TokenQuotaThreshold.optional(),
48
70
  weight: TokenWeight.optional(),
49
71
  });
72
+
50
73
  export type TokenSaveParams = z.infer<typeof TokenSaveParams>;
@@ -42,6 +42,7 @@ export default {
42
42
  "entity.listManage": (name: string) => `Manage ${name} List`,
43
43
  "error.alreadyProcessed": "Already processed",
44
44
  "error.badRequest": "Bad request",
45
+ "error.detail": (detail: string) => detail,
45
46
  "error.duplicateRow": "Duplicate data",
46
47
  "error.forbidden": "Forbidden",
47
48
  "error.internalServerError": "Internal server error",
@@ -52,6 +53,24 @@ export default {
52
53
  "qgrid.dispatcherFailed": (provider: string) => `${provider} dispatcher failed to initialize`,
53
54
  "qgrid.dispatcherStarting": (provider: string) =>
54
55
  `${provider} dispatcher is starting up. Please retry shortly`,
56
+ "qgrid.grokCapabilityUnavailable": (detail: string) => `Grok capability unavailable: ${detail}`,
57
+ "qgrid.grokCapacity": "All Grok tokens are at their in-flight request cap. Please retry shortly",
58
+ "qgrid.grokContentPolicy": (detail: string) =>
59
+ `Grok generation blocked by content policy: ${detail}`,
60
+ "qgrid.grokInvalidRequest": (detail: string) => `Invalid Grok request: ${detail}`,
61
+ "qgrid.grokLoginFailed": (detail: string) => `Grok login failed: ${detail}`,
62
+ "qgrid.grokNotOAuthToken": "Grok login returned credentials that are not an xAI OAuth token",
63
+ "qgrid.grokNoWorkers": (detail: string) => `No Grok token is available: ${detail}`,
64
+ "qgrid.grokRateLimited": (retryAfterSec: number) =>
65
+ `All Grok tokens are rate limited. Retry after ${retryAfterSec} seconds`,
66
+ "qgrid.grokOnDemandExcluded": (tokens: string) =>
67
+ `All Grok tokens are excluded because on-demand billing is enabled at xAI: ${tokens}. Turn off on-demand billing, or add another account`,
68
+ "qgrid.grokZdrVideoUnavailable": (tokens: string) =>
69
+ `Grok video is unavailable because Zero Data Retention is on for: ${tokens}. Turn off the data-retention opt-out at xAI, or use a non-ZDR account`,
70
+ "qgrid.invalidInput": (detail: string) => `qgrid: invalid input: ${detail}`,
71
+ "qgrid.requestBodyTooLarge": (limitMiB: number) =>
72
+ `Request body exceeds the ${limitMiB} MiB limit`,
73
+ "qgrid.videoJobNotFound": "video job not found",
55
74
  "error.unauthorized": "Unauthorized",
56
75
  notFound: (name: string, id: number) => `${name} ID ${id} not found`,
57
76
  "validation.email": "Invalid email format",
@@ -40,6 +40,8 @@ export default {
40
40
  "entity.listManage": (name: string) => `${name} 목록 관리`,
41
41
  "error.alreadyProcessed": "이미 처리되었습니다",
42
42
  "error.badRequest": "잘못된 요청입니다",
43
+ // Upstream and validation messages that are shown to the caller verbatim in every locale.
44
+ "error.detail": (detail: string) => detail,
43
45
  "error.duplicateRow": "중복된 데이터입니다",
44
46
  "error.entityNotFound": (name: string, id: number | string) => `존재하지 않는 ${name} ID ${id}`,
45
47
  "error.forbidden": "권한이 없습니다",
@@ -51,6 +53,25 @@ export default {
51
53
  "qgrid.dispatcherFailed": (provider: string) => `${provider} dispatcher 초기화에 실패했습니다`,
52
54
  "qgrid.dispatcherStarting": (provider: string) =>
53
55
  `${provider} dispatcher 기동 중입니다. 잠시 후 다시 시도해주세요`,
56
+ "qgrid.grokCapabilityUnavailable": (detail: string) =>
57
+ `Grok 기능을 사용할 수 없습니다: ${detail}`,
58
+ "qgrid.grokCapacity": "모든 Grok 토큰이 동시 요청 한도에 도달했습니다. 잠시 후 다시 시도해주세요",
59
+ "qgrid.grokContentPolicy": (detail: string) =>
60
+ `콘텐츠 정책 위반으로 Grok 생성이 차단되었습니다: ${detail}`,
61
+ "qgrid.grokInvalidRequest": (detail: string) => `잘못된 Grok 요청입니다: ${detail}`,
62
+ "qgrid.grokLoginFailed": (detail: string) => `Grok 로그인에 실패했습니다: ${detail}`,
63
+ "qgrid.grokNotOAuthToken": "Grok 로그인 결과가 xAI OAuth 토큰이 아닙니다",
64
+ "qgrid.grokNoWorkers": (detail: string) => `사용 가능한 Grok 토큰이 없습니다: ${detail}`,
65
+ "qgrid.grokRateLimited": (retryAfterSec: number) =>
66
+ `모든 Grok 토큰이 요청 한도에 걸렸습니다. ${retryAfterSec}초 후 다시 시도해주세요`,
67
+ "qgrid.grokOnDemandExcluded": (tokens: string) =>
68
+ `xAI에서 on-demand 과금이 켜져 있어 모든 Grok 토큰이 제외되었습니다: ${tokens}. on-demand 과금을 끄거나 다른 계정을 추가해주세요`,
69
+ "qgrid.grokZdrVideoUnavailable": (tokens: string) =>
70
+ `Zero Data Retention이 켜져 있어 Grok 비디오를 사용할 수 없습니다: ${tokens}. xAI에서 data-retention opt-out을 끄거나 ZDR이 아닌 계정을 사용해주세요`,
71
+ "qgrid.invalidInput": (detail: string) => `qgrid: 잘못된 입력입니다: ${detail}`,
72
+ "qgrid.requestBodyTooLarge": (limitMiB: number) =>
73
+ `요청 본문이 ${limitMiB} MiB 제한을 초과했습니다`,
74
+ "qgrid.videoJobNotFound": "비디오 작업을 찾을 수 없습니다",
54
75
  "error.unauthorized": "인증이 필요합니다",
55
76
  "error.unknownSearchField": (field: string) => `구현되지 않은 검색 필드 ${field}`,
56
77
  notFound: (name: string, id: number) => `존재하지 않는 ${name} ID ${id}`,
@@ -2,14 +2,18 @@
2
2
  * @generated
3
3
  * 직접 수정하지 마세요.
4
4
  */
5
+ // Sonamu 생성 코드의 타입 계약을 유지하기 위해 anti-slop 검사만 제외합니다.
6
+ /* oxlint-disable anti-slop/no-chained-type-assertions, anti-slop/no-conditional-empty-object-spread, anti-slop/no-known-value-widening, anti-slop/no-module-mocking, anti-slop/no-object-parameters, anti-slop/no-reflect-apply, anti-slop/no-reflect-get, anti-slop/no-runtime-typeof, anti-slop/no-shape-in-symbol-names, anti-slop/no-unknown-parameters, anti-slop/no-unknown-returns, anti-slop/no-unknown-type-aliases, anti-slop/no-unsafe-dictionary-type, anti-slop/no-widen-then-assert, anti-slop/require-safety-comment-for-type-assertion */
5
7
 
6
8
  import { Sonamu } from "sonamu";
7
9
 
8
10
  const DEFAULT_LOCALE = "ko" as const;
9
11
  const SUPPORTED_LOCALES = ["ko", "en"] as const;
12
+
10
13
  function getCurrentLocale(): (typeof SUPPORTED_LOCALES)[number] {
11
14
  try {
12
15
  const ctx = Sonamu.getContext();
16
+
13
17
  return (ctx.locale as (typeof SUPPORTED_LOCALES)[number]) ?? DEFAULT_LOCALE;
14
18
  } catch {
15
19
  return DEFAULT_LOCALE;
@@ -332,8 +336,11 @@ const entityLabels = {
332
336
 
333
337
  // defaultLocale의 dictionary를 기준으로 키 추출
334
338
  type RCKeys = typeof rcKeysKo;
339
+
335
340
  type ProjectDictionary = typeof ko;
341
+
336
342
  type EntityLabels = typeof entityLabels;
343
+
337
344
  type RawMergedDictionary = RCKeys &
338
345
  Omit<EntityLabels, keyof (RCKeys & ProjectDictionary)> &
339
346
  ProjectDictionary;
@@ -344,7 +351,9 @@ export type MergedDictionary = {
344
351
  ? (...args: P) => string
345
352
  : string;
346
353
  };
354
+
347
355
  export type DictKey = keyof MergedDictionary;
356
+
348
357
  export type LocalizedString = string & { __brand: "LocalizedString" };
349
358
 
350
359
  export function defineLocale(dict: Partial<MergedDictionary>) {
@@ -364,6 +373,7 @@ type SDReturnType<K extends DictKey> = MergedDictionary[K] extends (...args: inf
364
373
  function getDictValue<K extends DictKey>(key: K, locale: string): SDReturnType<K> {
365
374
  // 1. 지정된 locale에서 조회
366
375
  const dict = dictionaries[locale];
376
+
367
377
  if (dict?.[key] !== undefined) {
368
378
  return dict[key] as unknown as SDReturnType<K>;
369
379
  }
@@ -396,6 +406,7 @@ function getDictValue<K extends DictKey>(key: K, locale: string): SDReturnType<K
396
406
  */
397
407
  export function SD<K extends DictKey>(key: K): SDReturnType<K> {
398
408
  const locale = getCurrentLocale();
409
+
399
410
  return getDictValue(key, locale);
400
411
  }
401
412
 
@@ -430,12 +441,15 @@ type LocalizedBaseColumn<T> = {
430
441
  * localizedColumn(tag, "name")
431
442
  */
432
443
  type LocalizedColumnScalarValue = string | number | boolean | bigint;
444
+
433
445
  type LocalizedColumnValue = string | string[];
446
+
434
447
  type NestedLocalizedColumnValueFrom<V> = V extends string
435
448
  ? string
436
449
  : V extends readonly string[]
437
450
  ? string[]
438
451
  : never;
452
+
439
453
  type LocalizedColumnValueFrom<V> = V extends string
440
454
  ? string
441
455
  : V extends readonly string[]
@@ -445,6 +459,7 @@ type LocalizedColumnValueFrom<V> = V extends string
445
459
  : V extends Partial<Record<(typeof SUPPORTED_LOCALES)[number], infer LV>>
446
460
  ? NestedLocalizedColumnValueFrom<LV>
447
461
  : never;
462
+
448
463
  type LocalizedColumnCandidate<T, K extends string> =
449
464
  | (K extends keyof T ? T[K] : never)
450
465
  | {
@@ -452,9 +467,11 @@ type LocalizedColumnCandidate<T, K extends string> =
452
467
  ? T[`${K}_${L}`]
453
468
  : never;
454
469
  }[(typeof SUPPORTED_LOCALES)[number]];
470
+
455
471
  type LocalizedColumnReturn<T, K extends string> =
456
472
  | LocalizedColumnValueFrom<LocalizedColumnCandidate<T, K>>
457
473
  | undefined;
474
+
458
475
  type LocaleValueMap = Partial<Record<(typeof SUPPORTED_LOCALES)[number], unknown>>;
459
476
 
460
477
  function isLocalizedColumnValue(value: unknown): value is LocalizedColumnValue {
@@ -472,12 +489,13 @@ function isEmptyLocalizedColumnValue(value: unknown): value is null | undefined
472
489
  return value === null || value === undefined || value === "";
473
490
  }
474
491
 
475
- function getNestedLocaleValue<T extends Record<string, unknown>, K extends LocalizedBaseColumn<T>>(
492
+ function getNestedLocaleValue<T extends Record<string, unknown>>(
476
493
  row: T,
477
- column: K,
494
+ column: LocalizedBaseColumn<T>,
478
495
  locale: (typeof SUPPORTED_LOCALES)[number],
479
496
  ): unknown {
480
497
  const columnValue = row[column];
498
+
481
499
  if (columnValue === null || typeof columnValue !== "object" || Array.isArray(columnValue)) {
482
500
  return undefined;
483
501
  }
@@ -496,6 +514,7 @@ export function localizedColumn<
496
514
  );
497
515
  const localizedKey = (column: K, locale: (typeof SUPPORTED_LOCALES)[number]) =>
498
516
  `${column}_${locale}`;
517
+
499
518
  const values = [
500
519
  { value: row[localizedKey(column, locale)], source: "direct" },
501
520
  { value: getNestedLocaleValue(row, column, locale), source: "nested" },
@@ -512,6 +531,7 @@ export function localizedColumn<
512
531
  if (!isEmptyLocalizedColumnValue(value) && isLocalizedColumnValue(value)) {
513
532
  return value as LocalizedColumnReturn<T, K>;
514
533
  }
534
+
515
535
  if (
516
536
  source === "direct" &&
517
537
  !isEmptyLocalizedColumnValue(value) &&
@@ -539,6 +559,7 @@ SD.enumLabels = (enumName: string): Record<string, LocalizedString> => {
539
559
  }
540
560
 
541
561
  const dictKey = `enum.${enumName}.${key}` as DictKey;
562
+
542
563
  return getDictValue(dictKey, getCurrentLocale());
543
564
  },
544
565
  });
@@ -52,23 +52,30 @@ function backfilledCostMicroUsd(row: LegacyRow): number {
52
52
  // 이를 합치지 않아 input_tokens 가 작게 남은 row 를 복원한다.
53
53
  const splitInput =
54
54
  isAnthropicRow(row) && row.input_tokens < row.cache_read_tokens + row.cache_creation_tokens;
55
+
55
56
  const inputTokens = splitInput
56
57
  ? row.input_tokens + row.cache_read_tokens + row.cache_creation_tokens
57
58
  : row.input_tokens;
58
59
 
59
60
  const model = row.model_name.includes("/") ? row.model_name.split("/").pop()! : row.model_name;
60
- const usd = calculateCostUsd(model, {
61
+
62
+ const usage: Parameters<typeof calculateCostUsd>[1] = {
61
63
  inputTokens,
62
64
  outputTokens: row.output_tokens,
63
65
  cachedInputTokens: row.cache_read_tokens,
64
66
  cacheCreationInputTokens: row.cache_creation_tokens,
65
- ...(row.cache_creation_5m_tokens !== null
66
- ? { cacheCreationInputTokens5m: row.cache_creation_5m_tokens }
67
- : {}),
68
- ...(row.cache_creation_1h_tokens !== null
69
- ? { cacheCreationInputTokens1h: row.cache_creation_1h_tokens }
70
- : {}),
71
- });
67
+ };
68
+
69
+ if (row.cache_creation_5m_tokens !== null) {
70
+ usage.cacheCreationInputTokens5m = row.cache_creation_5m_tokens;
71
+ }
72
+
73
+ if (row.cache_creation_1h_tokens !== null) {
74
+ usage.cacheCreationInputTokens1h = row.cache_creation_1h_tokens;
75
+ }
76
+
77
+ const usd = calculateCostUsd(model, usage);
78
+
72
79
  return Math.max(Math.round(usd * MICRO_USD), 0);
73
80
  }
74
81
 
@@ -87,6 +94,7 @@ export async function up(knex: Knex): Promise<void> {
87
94
  LIMIT ?`,
88
95
  [lastId, CHUNK_SIZE],
89
96
  );
97
+
90
98
  if (rows.length === 0) break;
91
99
 
92
100
  // chunk 당 한 번의 UPDATE ... FROM (VALUES ...) 로 왕복을 줄인다.
@@ -5,14 +5,16 @@ import { runRequiredMigrations } from "./startup-migrations";
5
5
  type BootstrapSteps = {
6
6
  init: () => Promise<void>;
7
7
  migrate: () => Promise<void>;
8
- listen: () => Promise<unknown>;
8
+ listen: () => Promise<void>;
9
9
  };
10
10
 
11
11
  export async function bootstrapServer(
12
12
  steps: BootstrapSteps = {
13
13
  init: () => Sonamu.init(),
14
14
  migrate: runRequiredMigrations,
15
- listen: () => Sonamu.createServer(),
15
+ listen: async () => {
16
+ await Sonamu.createServer();
17
+ },
16
18
  },
17
19
  ): Promise<void> {
18
20
  await steps.init();
@@ -13,6 +13,7 @@ const RETRY_AFTER_SECONDS = "30";
13
13
  // upstream 예외를 통과시킨다. 여기서는 instanceof 로 실제 계약을 확인한다.
14
14
  export function handleServerError(error: Error, reply: FastifyReply): void {
15
15
  getLogger(["qgrid"]).error(`${error}`);
16
+
16
17
  const statusCode =
17
18
  error instanceof SoException &&
18
19
  Number.isInteger(error.statusCode) &&