@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
@@ -11,6 +11,8 @@
11
11
  * → "Composing Tools With A User Output Schema"
12
12
  */
13
13
 
14
+ import { z } from "zod";
15
+
14
16
  import {
15
17
  SCHEMA_ARRAY_KEYWORDS,
16
18
  SCHEMA_DEPENDENCIES_KEYWORD,
@@ -18,7 +20,11 @@ import {
18
20
  SCHEMA_SINGLE_KEYWORDS,
19
21
  UNSUPPORTED_REFERENCE_KEYWORDS,
20
22
  } from "../../utils/providers/common/json-schema-keywords";
21
- import { type JsonValue } from "../../utils/providers/common/provider-types";
23
+ import {
24
+ isJsonObject,
25
+ type JsonObject,
26
+ type JsonValue,
27
+ } from "../../utils/providers/common/provider-types";
22
28
  import { type QgridTool } from "./qgrid.types";
23
29
 
24
30
  const USER_OUTPUT_DEFINITION = "__qgrid_user_output";
@@ -44,6 +50,7 @@ export function buildToolCallSchema(tools: QgridTool[], answerSchema?: JsonValue
44
50
  const toolDescriptions = tools
45
51
  .map((tool) => {
46
52
  const schema = JSON.stringify(tool.inputSchema);
53
+
47
54
  return `- ${tool.name}: ${tool.description ?? ""}\n inputSchema: ${schema}`;
48
55
  })
49
56
  .join("\n");
@@ -51,7 +58,7 @@ export function buildToolCallSchema(tools: QgridTool[], answerSchema?: JsonValue
51
58
  const normalizedAnswerSchema =
52
59
  answerSchema === undefined ? undefined : rebaseUserOutputSchema(answerSchema);
53
60
 
54
- return {
61
+ const envelope: JsonObject = {
55
62
  type: "object",
56
63
  description:
57
64
  "Return exactly one JSON object matching this schema as your final response, including when requesting a tool. This object is the response body, not a call to a built-in tool. To request client-side tools, set result.action to tool_call and include result.toolCalls, then end your turn. The client executes those tools and supplies their results in a later request. Do not invent tool results or emit an answer before receiving the required results.",
@@ -108,29 +115,28 @@ export function buildToolCallSchema(tools: QgridTool[], answerSchema?: JsonValue
108
115
  },
109
116
  required: ["result"],
110
117
  additionalProperties: false,
111
- ...(normalizedAnswerSchema === undefined
112
- ? {}
113
- : {
114
- $defs: {
115
- [USER_OUTPUT_DEFINITION]: normalizedAnswerSchema,
116
- },
117
- }),
118
118
  };
119
+
120
+ if (normalizedAnswerSchema !== undefined) {
121
+ envelope.$defs = { [USER_OUTPUT_DEFINITION]: normalizedAnswerSchema };
122
+ }
123
+
124
+ return envelope;
119
125
  }
120
126
 
121
127
  function rebaseUserOutputSchema(schema: JsonValue): JsonValue {
122
- return rewriteSchemaNode(schema, "$");
128
+ return rewriteSchemaNode(schema, "$") ?? schema;
123
129
  }
124
130
 
125
131
  const MAP_KEYWORDS = new Set<string>(SCHEMA_MAP_KEYWORDS);
126
132
  const ARRAY_KEYWORDS = new Set<string>(SCHEMA_ARRAY_KEYWORDS);
127
133
  const SINGLE_KEYWORDS = new Set<string>(SCHEMA_SINGLE_KEYWORDS);
128
134
 
129
- function rewriteSchemaNode(value: JsonValue, path: string): JsonValue {
130
- if (value === null || typeof value !== "object" || Array.isArray(value)) return value;
135
+ function rewriteSchemaNode(value: JsonValue | undefined, path: string): JsonValue | undefined {
136
+ if (!isJsonObject(value)) return value;
131
137
 
132
- const source = value as Record<string, JsonValue>;
133
- const result: Record<string, JsonValue> = { ...source };
138
+ const source = value;
139
+ const result: JsonObject = { ...source };
134
140
 
135
141
  for (const unsupportedKeyword of UNSUPPORTED_REFERENCE_KEYWORDS) {
136
142
  if (Object.hasOwn(source, unsupportedKeyword)) {
@@ -142,13 +148,15 @@ function rewriteSchemaNode(value: JsonValue, path: string): JsonValue {
142
148
  }
143
149
 
144
150
  if ("$ref" in source) {
145
- const ref = source.$ref;
146
- if (typeof ref !== "string" || (ref !== "#" && !ref.startsWith("#/"))) {
151
+ const ref = z.string().safeParse(source.$ref).data;
152
+
153
+ if (ref === undefined || (ref !== "#" && !ref.startsWith("#/"))) {
147
154
  throw new ToolSchemaCompositionError(
148
155
  "only root-relative JSON Pointer $ref values are supported",
149
156
  `${path}.$ref`,
150
157
  );
151
158
  }
159
+
152
160
  result.$ref = `${USER_OUTPUT_REF}${ref.slice(1)}`;
153
161
  }
154
162
 
@@ -161,7 +169,7 @@ function rewriteSchemaNode(value: JsonValue, path: string): JsonValue {
161
169
  name,
162
170
  rewriteSchemaNode(schema, `${keywordPath}.${name}`),
163
171
  ]),
164
- ) as JsonValue;
172
+ );
165
173
  } else if (keyword === SCHEMA_DEPENDENCIES_KEYWORD && isJsonObject(child)) {
166
174
  result[keyword] = Object.fromEntries(
167
175
  Object.entries(child).map(([name, dependency]) => [
@@ -170,25 +178,21 @@ function rewriteSchemaNode(value: JsonValue, path: string): JsonValue {
170
178
  ? dependency
171
179
  : rewriteSchemaNode(dependency, `${keywordPath}.${name}`),
172
180
  ]),
173
- ) as JsonValue;
181
+ );
174
182
  } else if (ARRAY_KEYWORDS.has(keyword) && Array.isArray(child)) {
175
- result[keyword] = child.map((schema, index) =>
176
- rewriteSchemaNode(schema, `${keywordPath}[${index}]`),
177
- ) as JsonValue;
183
+ result[keyword] = child.map(
184
+ (schema, index) => rewriteSchemaNode(schema, `${keywordPath}[${index}]`) ?? schema,
185
+ );
178
186
  } else if (SINGLE_KEYWORDS.has(keyword)) {
179
187
  if (keyword === "items" && Array.isArray(child)) {
180
- result[keyword] = child.map((schema, index) =>
181
- rewriteSchemaNode(schema, `${keywordPath}[${index}]`),
182
- ) as JsonValue;
188
+ result[keyword] = child.map(
189
+ (schema, index) => rewriteSchemaNode(schema, `${keywordPath}[${index}]`) ?? schema,
190
+ );
183
191
  } else {
184
192
  result[keyword] = rewriteSchemaNode(child, keywordPath);
185
193
  }
186
194
  }
187
195
  }
188
196
 
189
- return result as JsonValue;
190
- }
191
-
192
- function isJsonObject(value: JsonValue): value is Record<string, JsonValue> {
193
- return value !== null && typeof value === "object" && !Array.isArray(value);
197
+ return result;
194
198
  }
@@ -3,6 +3,8 @@ import { Buffer } from "node:buffer";
3
3
  import { getLogger } from "@logtape/logtape";
4
4
  import { z } from "zod";
5
5
 
6
+ import { type JsonValue } from "../../utils/providers/common/provider-types";
7
+
6
8
  // 응답(모델 출력) envelope 의 자원 한도. caller 스키마 전처리 한도(CALLER_SCHEMA_LIMITS)와 값이
7
9
  // 같아 보여도 서로 다른 자원을 지키는 독립 상수다 — 스키마 깊이는 인스턴스 깊이를 bound 하지
8
10
  // 않으므로(재귀 $ref 허용) 캘러 한도를 조정해도 응답 수용 기준이 따라 움직여선 안 된다.
@@ -11,6 +13,7 @@ const STRUCTURED_ENVELOPE_LIMITS = {
11
13
  maxNodes: 20_000,
12
14
  maxDepth: 132,
13
15
  } as const;
16
+
14
17
  import {
15
18
  type ImageGenerationMetadata,
16
19
  type QgridContent,
@@ -22,6 +25,7 @@ import {
22
25
  const logger = getLogger(["qgrid", "tool-emulation"]);
23
26
 
24
27
  type EmulationResult = Omit<QueryOutput, "content" | "finishReason" | "runContext">;
28
+
25
29
  type ToolCall = { toolName: string; args: string };
26
30
 
27
31
  // envelope 는 {result: <union>} 한 겹 구조 — 스키마 근거는 tool-emulation-schema.ts 참조.
@@ -58,6 +62,7 @@ function buildEnvelopeSchema(answerKind: AnswerKind) {
58
62
 
59
63
  const TEXT_ENVELOPE = buildEnvelopeSchema("text");
60
64
  const JSON_ENVELOPE = buildEnvelopeSchema("json");
65
+
61
66
  type EnvelopeResponse = z.infer<typeof JSON_ENVELOPE>["result"];
62
67
 
63
68
  export class ToolCallEmulationError extends Error {
@@ -99,18 +104,23 @@ export function applyToolCallEmulation(
99
104
  }
100
105
 
101
106
  const parsed = parseEnvelope(result.text, tools, answerKind);
107
+
102
108
  if (parsed.action === "tool_call") {
103
109
  return toolCallOutput(result, parsed.toolCalls, images, runContext);
104
110
  }
105
111
 
106
112
  return answerOutput(
107
113
  result,
108
- answerKind === "text" ? (parsed.answer as string) : JSON.stringify(parsed.answer),
114
+ answerKind === "text" ? z.string().parse(parsed.answer) : JSON.stringify(parsed.answer),
109
115
  images,
110
116
  runContext,
111
117
  );
112
118
  }
113
119
 
120
+ const commentaryToolCallControl = z.looseObject({
121
+ result: z.looseObject({ action: z.literal("tool_call") }),
122
+ });
123
+
114
124
  export function isToolCallEnvelope(
115
125
  text: string,
116
126
  tools: QgridTool[],
@@ -120,23 +130,17 @@ export function isToolCallEnvelope(
120
130
  if (phase === "commentary") {
121
131
  // Commentary is not the structured answer. Only an explicit tool control
122
132
  // object is eligible, and that object must still pass the strict parser.
123
- let value: unknown;
133
+ let value: JsonValue;
134
+
124
135
  try {
125
136
  value = JSON.parse(text);
126
137
  } catch {
127
138
  return false;
128
139
  }
129
- if (
130
- !value ||
131
- typeof value !== "object" ||
132
- !("result" in value) ||
133
- !value.result ||
134
- typeof value.result !== "object" ||
135
- !("action" in value.result) ||
136
- value.result.action !== "tool_call"
137
- )
138
- return false;
140
+
141
+ if (!commentaryToolCallControl.safeParse(value).success) return false;
139
142
  }
143
+
140
144
  return parseEnvelope(text, tools, answerKind).action === "tool_call";
141
145
  }
142
146
 
@@ -147,7 +151,9 @@ function parseEnvelope(text: string, tools: QgridTool[], answerKind: AnswerKind)
147
151
  );
148
152
  }
149
153
 
150
- let value: unknown;
154
+ // JSON.parse without a reviver yields only JSON values.
155
+ let value: JsonValue;
156
+
151
157
  try {
152
158
  value = JSON.parse(text);
153
159
  } catch (error) {
@@ -159,15 +165,18 @@ function parseEnvelope(text: string, tools: QgridTool[], answerKind: AnswerKind)
159
165
  // 진단에는 위반 원문의 머리가 필요하다(SON-495 전례) — parse 에러 위치만으로는
160
166
  // "프로즈로 답했는지 / 펜스가 남았는지 / JSON 이 잘렸는지"를 구분할 수 없다.
161
167
  const head = JSON.stringify(text.slice(0, 200));
162
- logger.warn(`tool envelope parse failed: ${(error as Error).message}; head=${head}`);
168
+ logger.warn(
169
+ `tool envelope parse failed: ${error instanceof Error ? error.message : String(error)}; head=${head}`,
170
+ );
163
171
  throw new ToolCallEmulationError(
164
- `invalid tool envelope (response is not JSON — the model ignored the envelope contract; retry is the caller's decision): ${(error as Error).message}; response head: ${head}`,
172
+ `invalid tool envelope (response is not JSON — the model ignored the envelope contract; retry is the caller's decision): ${error instanceof Error ? error.message : String(error)}; response head: ${head}`,
165
173
  );
166
174
  }
167
175
 
168
176
  assertStructuredEnvelopeComplexity(value);
169
177
  const schema = answerKind === "text" ? TEXT_ENVELOPE : JSON_ENVELOPE;
170
178
  const validation = schema.safeParse(value);
179
+
171
180
  if (!validation.success) {
172
181
  const issue = validation.error.issues[0];
173
182
  const path = issue && issue.path.length > 0 ? ` at ${issue.path.join(".")}` : "";
@@ -181,15 +190,19 @@ function parseEnvelope(text: string, tools: QgridTool[], answerKind: AnswerKind)
181
190
  );
182
191
  }
183
192
 
184
- // Zod clones JSON objects and drops own "__proto__" keys. The parsed JSON is safe to return
185
- // after validation and preserves the caller's exact structured value.
193
+ // SAFETY: schema.safeParse(value) succeeded above, so value matches { result: EnvelopeResponse }.
194
+ // Zod clones JSON objects and drops own "__proto__" keys, so the validated raw value is returned
195
+ // to preserve the caller's exact structured answer.
186
196
  const response = (value as { result: EnvelopeResponse }).result;
197
+
187
198
  if (response.action === "tool_call") {
188
199
  const unknownTool = findUnknownTool(response.toolCalls, tools);
200
+
189
201
  if (unknownTool !== undefined) {
190
202
  throw new ToolCallEmulationError(`unknown emulated tool: ${unknownTool}`);
191
203
  }
192
204
  }
205
+
193
206
  return response;
194
207
  }
195
208
 
@@ -232,47 +245,59 @@ function answerOutput(
232
245
 
233
246
  function findUnknownTool(toolCalls: ToolCall[], tools: QgridTool[]): string | undefined {
234
247
  const knownToolNames = new Set(tools.map((tool) => tool.name));
248
+
235
249
  return toolCalls.find((toolCall) => !knownToolNames.has(toolCall.toolName))?.toolName;
236
250
  }
237
251
 
238
252
  function appendImages(content: QgridContent[], images?: EmulationImage[]): QgridContent[] {
239
253
  if (!images?.length) return content;
254
+
240
255
  return [
241
256
  ...content,
242
- ...images.map(
243
- (image): QgridContent => ({
257
+ ...images.map((image): QgridContent => {
258
+ const part: Extract<QgridContent, { type: "image" }> = {
244
259
  type: "image",
245
260
  data: image.data,
246
- ...(image.mediaType ? { mediaType: image.mediaType } : {}),
247
261
  revisedPrompt: image.revisedPrompt ?? null,
248
- ...(image.generation ? { generation: image.generation } : {}),
249
- }),
250
- ),
262
+ };
263
+
264
+ if (image.mediaType) part.mediaType = image.mediaType;
265
+
266
+ if (image.generation) part.generation = image.generation;
267
+
268
+ return part;
269
+ }),
251
270
  ];
252
271
  }
253
272
 
254
- function assertStructuredEnvelopeComplexity(root: unknown): void {
273
+ function assertStructuredEnvelopeComplexity(root: JsonValue): void {
255
274
  const maxDepth = STRUCTURED_ENVELOPE_LIMITS.maxDepth;
256
- const stack = [{ value: root, depth: 0 }];
275
+ const stack: Array<{ value: JsonValue | undefined; depth: number }> = [{ value: root, depth: 0 }];
257
276
  let nodes = 0;
258
277
 
259
278
  while (stack.length > 0) {
260
279
  const current = stack.pop()!;
261
280
  nodes += 1;
281
+
262
282
  if (nodes > STRUCTURED_ENVELOPE_LIMITS.maxNodes) {
263
283
  throw new ToolCallEmulationError(
264
284
  `structured-output envelope exceeds node limit of ${STRUCTURED_ENVELOPE_LIMITS.maxNodes}`,
265
285
  );
266
286
  }
287
+
267
288
  if (current.depth > maxDepth) {
268
289
  throw new ToolCallEmulationError(
269
290
  `structured-output envelope exceeds depth limit of ${maxDepth}`,
270
291
  );
271
292
  }
272
- if (typeof current.value === "number" && !Number.isFinite(current.value)) {
293
+
294
+ // JSON.parse turns out-of-range literals such as 1e999 into ±Infinity; it never yields NaN.
295
+ if (current.value === Infinity || current.value === -Infinity) {
273
296
  throw new ToolCallEmulationError("answer must be valid JSON");
274
297
  }
275
- if (current.value === null || typeof current.value !== "object") continue;
298
+
299
+ // Only JSON arrays and objects are Object instances; primitives and null are leaves.
300
+ if (!(current.value instanceof Object)) continue;
276
301
 
277
302
  for (const value of Object.values(current.value)) {
278
303
  stack.push({ value, depth: current.depth + 1 });
@@ -1,7 +1,7 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
 
3
3
  import {
4
- renderJsonSchemaZodShapeText,
4
+ renderJsonSchemaZodText,
5
5
  renderJsonSchemaTypeText,
6
6
  renderParsedJsonSchemaTypeText,
7
7
  } from "./json-schema-type-text";
@@ -133,10 +133,10 @@ describe("renderJsonSchemaTypeText", () => {
133
133
  });
134
134
  });
135
135
 
136
- describe("renderJsonSchemaZodShapeText", () => {
136
+ describe("renderJsonSchemaZodText", () => {
137
137
  it("renders a compact object shape with required, optional, and default annotations", () => {
138
138
  expect(
139
- renderJsonSchemaZodShapeText(
139
+ renderJsonSchemaZodText(
140
140
  {
141
141
  type: "object",
142
142
  properties: {
@@ -159,7 +159,7 @@ describe("renderJsonSchemaZodShapeText", () => {
159
159
 
160
160
  it("shortens long string enums with an inline remainder comment", () => {
161
161
  expect(
162
- renderJsonSchemaZodShapeText(
162
+ renderJsonSchemaZodText(
163
163
  {
164
164
  type: "object",
165
165
  properties: {
@@ -180,7 +180,7 @@ describe("renderJsonSchemaZodShapeText", () => {
180
180
 
181
181
  it("renders nested objects, arrays, unions, literals, and unknown nodes", () => {
182
182
  expect(
183
- renderJsonSchemaZodShapeText({
183
+ renderJsonSchemaZodText({
184
184
  type: "object",
185
185
  properties: {
186
186
  filters: {
@@ -7,7 +7,13 @@
7
7
  * 모르는 키워드는 unknown 으로 접어 절대 던지지 않는다.
8
8
  */
9
9
 
10
- type SchemaNode = Record<string, unknown>;
10
+ import { z } from "zod";
11
+
12
+ import {
13
+ isJsonObject,
14
+ type JsonObject,
15
+ type JsonValue,
16
+ } from "../../utils/providers/common/provider-types";
11
17
 
12
18
  /** TS/zod 표시 코드 공용 식별자 판별 — zod-code-format 의 키 unquote 도 이걸 쓴다. */
13
19
  export const IDENT_SOURCE = "[A-Za-z_$][\\w$]*";
@@ -17,90 +23,127 @@ function renderKey(key: string): string {
17
23
  return IDENT_RE.test(key) ? key : JSON.stringify(key);
18
24
  }
19
25
 
20
- function renderPrimitive(type: unknown): string {
26
+ function renderPrimitive(type: JsonValue | undefined): string {
21
27
  if (type === "string") return "string";
28
+
22
29
  if (type === "number" || type === "integer") return "number";
30
+
23
31
  if (type === "boolean") return "boolean";
32
+
24
33
  if (type === "null") return "null";
34
+
25
35
  return "unknown";
26
36
  }
27
37
 
28
- function renderZodPrimitive(type: unknown): string {
38
+ function renderZodPrimitive(type: JsonValue | undefined): string {
29
39
  if (type === "string") return "z.string()";
40
+
30
41
  if (type === "number" || type === "integer") return "z.number()";
42
+
31
43
  if (type === "boolean") return "z.boolean()";
44
+
32
45
  if (type === "null") return "z.null()";
46
+
33
47
  return "z.unknown()";
34
48
  }
35
49
 
36
- function renderZodEnum(values: unknown[], enumValueLimit?: number): string {
50
+ function renderZodEnum(values: JsonValue[], enumValueLimit?: number): string {
37
51
  if (values.length === 0) return "z.never()";
38
52
 
39
53
  const visibleValues =
40
54
  enumValueLimit === undefined ? values : values.slice(0, Math.max(0, enumValueLimit));
55
+
41
56
  const omittedCount = values.length - visibleValues.length;
42
57
  const suffix = omittedCount > 0 ? ` /* +${omittedCount} */` : "";
43
58
 
44
- if (values.every((value) => typeof value === "string")) {
59
+ if (values.every((value) => z.string().safeParse(value).success)) {
45
60
  return `z.enum([${visibleValues.map((value) => JSON.stringify(value)).join(", ")}${suffix}])`;
46
61
  }
47
62
 
48
63
  const literals = visibleValues.map((value) => `z.literal(${JSON.stringify(value)})`);
64
+
49
65
  if (literals.length === 1 && omittedCount === 0) return literals[0] ?? "z.never()";
66
+
50
67
  return `z.union([${literals.join(", ")}${suffix}])`;
51
68
  }
52
69
 
53
- function renderZodNode(node: unknown, depth: number, enumValueLimit?: number): string {
70
+ function schemaProperties(schema: JsonObject): JsonObject {
71
+ return isJsonObject(schema.properties) ? schema.properties : {};
72
+ }
73
+
74
+ function requiredKeys(schema: JsonObject): Set<string> {
75
+ const required = schema.required;
76
+
77
+ return new Set(
78
+ Array.isArray(required) ? required.flatMap((key) => z.string().safeParse(key).data ?? []) : [],
79
+ );
80
+ }
81
+
82
+ function renderZodNode(
83
+ node: JsonValue | undefined,
84
+ depth: number,
85
+ enumValueLimit?: number,
86
+ ): string {
54
87
  if (node === true) return "z.unknown()";
55
- if (!node || typeof node !== "object" || Array.isArray(node)) return "z.unknown()";
56
- const schema = node as SchemaNode;
88
+
89
+ if (!isJsonObject(node)) return "z.unknown()";
90
+ const schema = node;
57
91
 
58
92
  if (Array.isArray(schema.enum)) return renderZodEnum(schema.enum, enumValueLimit);
93
+
59
94
  if (schema.const !== undefined) return `z.literal(${JSON.stringify(schema.const)})`;
60
95
 
61
- const variants = (schema.anyOf ?? schema.oneOf) as unknown;
96
+ const variants = schema.anyOf ?? schema.oneOf;
97
+
62
98
  if (Array.isArray(variants) && variants.length > 0) {
63
99
  const rendered = [
64
100
  ...new Set(variants.map((variant) => renderZodNode(variant, depth, enumValueLimit))),
65
101
  ];
102
+
66
103
  return rendered.length === 1
67
104
  ? (rendered[0] ?? "z.unknown()")
68
105
  : `z.union([${rendered.join(", ")}])`;
69
106
  }
70
107
 
71
108
  const type = schema.type;
109
+
72
110
  if (Array.isArray(type)) {
73
111
  const rendered = [...new Set(type.map(renderZodPrimitive))];
112
+
74
113
  return rendered.length === 1
75
114
  ? (rendered[0] ?? "z.unknown()")
76
115
  : `z.union([${rendered.join(", ")}])`;
77
116
  }
78
117
 
79
118
  if (type === "object" || (type === undefined && schema.properties)) {
80
- const properties = (schema.properties ?? {}) as Record<string, unknown>;
81
- const required = new Set(Array.isArray(schema.required) ? (schema.required as string[]) : []);
119
+ const properties = schemaProperties(schema);
120
+ const required = requiredKeys(schema);
82
121
  const keys = Object.keys(properties);
122
+
83
123
  if (keys.length === 0) return "z.object({})";
124
+
84
125
  const orderedKeys = [
85
126
  ...keys.filter((key) => required.has(key)),
86
127
  ...keys.filter((key) => !required.has(key)),
87
128
  ];
88
129
 
89
130
  const inner = " ".repeat(depth + 1);
131
+
90
132
  const lines = orderedKeys.map((key) => {
91
133
  const propertySchema = properties[key];
92
134
  const rendered = renderZodNode(propertySchema, depth + 1, enumValueLimit);
93
135
  const optional = required.has(key) ? rendered : `${rendered}.optional()`;
136
+
94
137
  const defaultValue =
95
- propertySchema &&
96
- typeof propertySchema === "object" &&
97
- !Array.isArray(propertySchema) &&
98
- Object.hasOwn(propertySchema, "default")
99
- ? JSON.stringify((propertySchema as SchemaNode).default)
138
+ isJsonObject(propertySchema) && Object.hasOwn(propertySchema, "default")
139
+ ? JSON.stringify(propertySchema.default)
100
140
  : undefined;
141
+
101
142
  const defaultComment = defaultValue === undefined ? "" : ` // default=${defaultValue}`;
143
+
102
144
  return `${inner}${renderKey(key)}: ${optional},${defaultComment}`;
103
145
  });
146
+
104
147
  return `z.object({\n${lines.join("\n")}\n${" ".repeat(depth)}})`;
105
148
  }
106
149
 
@@ -111,43 +154,52 @@ function renderZodNode(node: unknown, depth: number, enumValueLimit?: number): s
111
154
  return renderZodPrimitive(type);
112
155
  }
113
156
 
114
- function renderNode(node: unknown, depth: number): string {
157
+ function renderNode(node: JsonValue | undefined, depth: number): string {
115
158
  if (node === true) return "unknown";
116
- if (!node || typeof node !== "object" || Array.isArray(node)) return "unknown";
117
- const schema = node as SchemaNode;
159
+
160
+ if (!isJsonObject(node)) return "unknown";
161
+ const schema = node;
118
162
 
119
163
  if (Array.isArray(schema.enum)) {
120
164
  return schema.enum.map((value) => JSON.stringify(value)).join(" | ");
121
165
  }
166
+
122
167
  if (schema.const !== undefined) return JSON.stringify(schema.const);
123
168
 
124
- const variants = (schema.anyOf ?? schema.oneOf) as unknown;
169
+ const variants = schema.anyOf ?? schema.oneOf;
170
+
125
171
  if (Array.isArray(variants) && variants.length > 0) {
126
172
  return [...new Set(variants.map((variant) => renderNode(variant, depth)))].join(" | ");
127
173
  }
128
174
 
129
175
  const type = schema.type;
176
+
130
177
  if (Array.isArray(type)) {
131
178
  return [...new Set(type.map(renderPrimitive))].join(" | ");
132
179
  }
133
180
 
134
181
  if (type === "object" || (type === undefined && schema.properties)) {
135
- const properties = (schema.properties ?? {}) as Record<string, unknown>;
136
- const required = new Set(Array.isArray(schema.required) ? (schema.required as string[]) : []);
182
+ const properties = schemaProperties(schema);
183
+ const required = requiredKeys(schema);
137
184
  const keys = Object.keys(properties);
185
+
138
186
  if (keys.length === 0) return "Record<string, unknown>";
139
187
  const inner = " ".repeat(depth + 1);
188
+
140
189
  const lines = keys.map(
141
190
  (key) =>
142
191
  `${inner}${renderKey(key)}${required.has(key) ? "" : "?"}: ${renderNode(properties[key], depth + 1)}`,
143
192
  );
193
+
144
194
  return `{\n${lines.join("\n")}\n${" ".repeat(depth)}}`;
145
195
  }
146
196
 
147
197
  if (type === "array") {
148
198
  const item = renderNode(schema.items, depth);
199
+
149
200
  // 유니온 요소는 괄호가 없으면 `A | B[]` 로 잘못 읽힌다.
150
201
  if (item.includes(" | ")) return `(${item})[]`;
202
+
151
203
  return `${item}[]`;
152
204
  }
153
205
 
@@ -155,19 +207,22 @@ function renderNode(node: unknown, depth: number): string {
155
207
  }
156
208
 
157
209
  /** 이미 파싱된 스키마 값용 — 호출부가 같은 JSON 을 두 번 파싱하지 않게 한다. */
158
- export function renderParsedJsonSchemaTypeText(schema: unknown, name = "Response"): string {
210
+ export function renderParsedJsonSchemaTypeText(schema: JsonValue, name = "Response"): string {
159
211
  return `type ${name} = ${renderNode(schema, 0)}`;
160
212
  }
161
213
 
162
- /** Tool input 계약용 표시 전용 Zod shape. 검증 제약은 의도적으로 생략한다. */
163
- export function renderJsonSchemaZodShapeText(schema: unknown, enumValueLimit?: number): string {
214
+ /** Tool input 계약용 표시 전용 Zod 코드. 검증 제약은 의도적으로 생략한다. */
215
+ export function renderJsonSchemaZodText(schema: JsonValue, enumValueLimit?: number): string {
164
216
  return renderZodNode(schema, 0, enumValueLimit);
165
217
  }
166
218
 
167
219
  /** 실패(파싱 불가 등) 시 null — 호출부가 표시 자체를 생략한다. */
168
220
  export function renderJsonSchemaTypeText(schemaJson: string, name = "Response"): string | null {
169
221
  try {
170
- return renderParsedJsonSchemaTypeText(JSON.parse(schemaJson) as unknown, name);
222
+ // JSON.parse without a reviver yields only JSON values.
223
+ const schema: JsonValue = JSON.parse(schemaJson);
224
+
225
+ return renderParsedJsonSchemaTypeText(schema, name);
171
226
  } catch {
172
227
  return null;
173
228
  }