@cartanova/qgrid-cli 2.10.9 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (318) 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 +22 -20
  10. package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +43 -34
  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 -69
  24. package/bundle/dist/application/request-log/request-log.types.js +8 -2
  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 +40 -16
  33. package/bundle/dist/application/sonamu.generated.sso.js +2 -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 +2 -1
  39. package/bundle/dist/migrations/20260807133553_manual__backfill_request_log_cost.js +8 -6
  40. package/bundle/dist/migrations/20261018215031_alter_request_logs_add1_alter1.js +15 -0
  41. package/bundle/dist/server-bootstrap.js +4 -2
  42. package/bundle/dist/server-error-handler.js +1 -1
  43. package/bundle/dist/sonamu.config.js +37 -8
  44. package/bundle/dist/startup-migrations.js +17 -7
  45. package/bundle/dist/testing/global.js +1 -1
  46. package/bundle/dist/testing/schema-bench.js +0 -0
  47. package/bundle/dist/testing/test-database-name.js +1 -1
  48. package/bundle/dist/utils/providers/anthropic/anthropic-constants.js +1 -1
  49. package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +11 -5
  50. package/bundle/dist/utils/providers/anthropic/anthropic-quota.js +4 -4
  51. package/bundle/dist/utils/providers/anthropic/anthropic-thinking.js +1 -1
  52. package/bundle/dist/utils/providers/anthropic/claude-session.js +20 -19
  53. package/bundle/dist/utils/providers/anthropic/fence-strip.js +1 -1
  54. package/bundle/dist/utils/providers/anthropic/stream-json-adapter.js +49 -23
  55. package/bundle/dist/utils/providers/common/credentials.js +5 -1
  56. package/bundle/dist/utils/providers/common/effort.js +3 -3
  57. package/bundle/dist/utils/providers/common/model-cost.js +69 -14
  58. package/bundle/dist/utils/providers/common/provider-types.js +29 -1
  59. package/bundle/dist/utils/providers/common/schema-validation.js +78 -40
  60. package/bundle/dist/utils/providers/common/smooth-weighted-round-robin.js +1 -1
  61. package/bundle/dist/utils/providers/common/strictifier.js +62 -43
  62. package/bundle/dist/utils/providers/common/thinking.js +3 -2
  63. package/bundle/dist/utils/providers/common/ttft.js +1 -1
  64. package/bundle/dist/utils/providers/grok/grok-backend-protocol.js +427 -0
  65. package/bundle/dist/utils/providers/grok/grok-constants.js +55 -0
  66. package/bundle/dist/utils/providers/grok/grok-direct-client.js +196 -0
  67. package/bundle/dist/utils/providers/grok/grok-dispatcher.js +1313 -0
  68. package/bundle/dist/utils/providers/grok/grok-headers.js +118 -0
  69. package/bundle/dist/utils/providers/grok/grok-media-client.js +420 -0
  70. package/bundle/dist/utils/providers/grok/grok-models.js +114 -0
  71. package/bundle/dist/utils/providers/grok/grok-oauth.js +455 -0
  72. package/bundle/dist/utils/providers/grok/grok-quota.js +119 -0
  73. package/bundle/dist/utils/providers/grok/grok-refresh.js +192 -0
  74. package/bundle/dist/utils/providers/grok/grok-types.js +186 -0
  75. package/bundle/dist/utils/providers/grok/grok-voice-client.js +199 -0
  76. package/bundle/dist/utils/providers/grok/index.js +11 -0
  77. package/bundle/dist/utils/providers/openai/openai-backend-protocol.js +111 -83
  78. package/bundle/dist/utils/providers/openai/openai-callback-relay.js +3 -2
  79. package/bundle/dist/utils/providers/openai/openai-constants.js +1 -1
  80. package/bundle/dist/utils/providers/openai/openai-direct-client.js +23 -7
  81. package/bundle/dist/utils/providers/openai/openai-dispatcher.js +143 -106
  82. package/bundle/dist/utils/providers/openai/openai-image-generation.js +48 -33
  83. package/bundle/dist/utils/providers/openai/openai-oauth.js +28 -13
  84. package/bundle/dist/utils/providers/openai/openai-quota.js +38 -27
  85. package/bundle/dist/utils/providers/openai/openai-refresh.js +17 -9
  86. package/bundle/dist/utils/providers/openai/openai-sse.js +1 -1
  87. package/bundle/dist/utils/providers/openai/openai-transport-config.js +1 -1
  88. package/bundle/dist/utils/quiet-hours.js +1 -1
  89. package/bundle/dist/utils/slack-notify.js +14 -8
  90. package/bundle/dist/utils/subset-loaders.js +4 -5
  91. package/bundle/src/application/monit/log-buffer.ts +23 -9
  92. package/bundle/src/application/monit/monit.frame.ts +22 -5
  93. package/bundle/src/application/monit/monit.types.ts +6 -0
  94. package/bundle/src/application/qgrid/conv-routing.test.ts +76 -4
  95. package/bundle/src/application/qgrid/conv-routing.ts +35 -9
  96. package/bundle/src/application/qgrid/expired-token-reminder.ts +9 -1
  97. package/bundle/src/application/qgrid/oauth.ts +51 -15
  98. package/bundle/src/application/qgrid/qgrid-image-generation.ts +9 -0
  99. package/bundle/src/application/qgrid/qgrid-response-format.ts +50 -25
  100. package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +33 -0
  101. package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +87 -40
  102. package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +97 -0
  103. package/bundle/src/application/qgrid/qgrid.dispatcher.ts +274 -126
  104. package/bundle/src/application/qgrid/qgrid.frame.test.ts +1013 -3
  105. package/bundle/src/application/qgrid/qgrid.frame.ts +1415 -60
  106. package/bundle/src/application/qgrid/qgrid.types.ts +335 -0
  107. package/bundle/src/application/qgrid/schema-prompt.ts +105 -41
  108. package/bundle/src/application/qgrid/slack-user-map.ts +5 -0
  109. package/bundle/src/application/qgrid/token-death.ts +4 -0
  110. package/bundle/src/application/qgrid/token-subscriber.test.ts +21 -19
  111. package/bundle/src/application/qgrid/token-subscriber.ts +186 -53
  112. package/bundle/src/application/qgrid/token-trigger-setup.ts +2 -0
  113. package/bundle/src/application/qgrid/token-window-keepalive.ts +49 -6
  114. package/bundle/src/application/qgrid/tool-emulation-schema.ts +33 -29
  115. package/bundle/src/application/qgrid/tool-emulation.ts +52 -27
  116. package/bundle/src/application/request-log/json-schema-type-text.test.ts +5 -5
  117. package/bundle/src/application/request-log/json-schema-type-text.ts +81 -26
  118. package/bundle/src/application/request-log/request-log.entity.json +8 -0
  119. package/bundle/src/application/request-log/request-log.model.test.ts +111 -4
  120. package/bundle/src/application/request-log/request-log.model.ts +279 -145
  121. package/bundle/src/application/request-log/request-log.types.ts +17 -0
  122. package/bundle/src/application/request-log/zod-code-format.ts +11 -0
  123. package/bundle/src/application/request-log-step/request-log-step.model.ts +1 -0
  124. package/bundle/src/application/request-log-step/request-log-step.types.ts +2 -0
  125. package/bundle/src/application/setting/setting.constant.ts +9 -0
  126. package/bundle/src/application/setting/setting.model.ts +12 -2
  127. package/bundle/src/application/setting/setting.store.ts +5 -1
  128. package/bundle/src/application/setting/setting.types.ts +8 -0
  129. package/bundle/src/application/sonamu.generated.http +135 -0
  130. package/bundle/src/application/sonamu.generated.sso.ts +3 -0
  131. package/bundle/src/application/sonamu.generated.ts +29 -0
  132. package/bundle/src/application/token/token.identity.test.ts +20 -0
  133. package/bundle/src/application/token/token.model.ts +66 -7
  134. package/bundle/src/application/token/token.types.ts +24 -1
  135. package/bundle/src/i18n/en.ts +19 -0
  136. package/bundle/src/i18n/ko.ts +21 -0
  137. package/bundle/src/i18n/sd.generated.ts +24 -2
  138. package/bundle/src/migrations/20260807133553_manual__backfill_request_log_cost.ts +16 -8
  139. package/bundle/src/migrations/20261018215031_alter_request_logs_add1_alter1.ts +15 -0
  140. package/bundle/src/server-bootstrap.ts +4 -2
  141. package/bundle/src/server-error-handler.ts +1 -0
  142. package/bundle/src/sonamu.config.ts +69 -7
  143. package/bundle/src/startup-migrations.ts +27 -9
  144. package/bundle/src/testing/global.ts +20 -0
  145. package/bundle/src/testing/schema-bench.ts +105 -30
  146. package/bundle/src/testing/test-database-name.ts +2 -0
  147. package/bundle/src/utils/providers/anthropic/anthropic-constants.ts +8 -0
  148. package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +41 -6
  149. package/bundle/src/utils/providers/anthropic/anthropic-quota.ts +7 -3
  150. package/bundle/src/utils/providers/anthropic/anthropic-thinking.ts +6 -0
  151. package/bundle/src/utils/providers/anthropic/claude-session.ts +58 -24
  152. package/bundle/src/utils/providers/anthropic/fence-strip.ts +11 -0
  153. package/bundle/src/utils/providers/anthropic/stream-json-adapter.ts +110 -45
  154. package/bundle/src/utils/providers/common/credentials.ts +8 -0
  155. package/bundle/src/utils/providers/common/effort.ts +9 -2
  156. package/bundle/src/utils/providers/common/model-cost.test.ts +48 -1
  157. package/bundle/src/utils/providers/common/model-cost.ts +259 -158
  158. package/bundle/src/utils/providers/common/provider-dispatcher.ts +98 -2
  159. package/bundle/src/utils/providers/common/provider-types.ts +46 -3
  160. package/bundle/src/utils/providers/common/schema-validation.test.ts +5 -1
  161. package/bundle/src/utils/providers/common/schema-validation.ts +124 -56
  162. package/bundle/src/utils/providers/common/smooth-weighted-round-robin.ts +4 -0
  163. package/bundle/src/utils/providers/common/strictifier.ts +185 -59
  164. package/bundle/src/utils/providers/common/thinking.ts +2 -2
  165. package/bundle/src/utils/providers/common/ttft.ts +4 -2
  166. package/bundle/src/utils/providers/grok/__fixtures__/golden-responses-1.0.60.json +164 -0
  167. package/bundle/src/utils/providers/grok/grok-backend-protocol.test.ts +325 -0
  168. package/bundle/src/utils/providers/grok/grok-backend-protocol.ts +721 -0
  169. package/bundle/src/utils/providers/grok/grok-constants.ts +105 -0
  170. package/bundle/src/utils/providers/grok/grok-direct-client.test.ts +179 -0
  171. package/bundle/src/utils/providers/grok/grok-direct-client.ts +313 -0
  172. package/bundle/src/utils/providers/grok/grok-dispatcher.test.ts +1395 -0
  173. package/bundle/src/utils/providers/grok/grok-dispatcher.ts +2105 -0
  174. package/bundle/src/utils/providers/grok/grok-headers.test.ts +149 -0
  175. package/bundle/src/utils/providers/grok/grok-headers.ts +199 -0
  176. package/bundle/src/utils/providers/grok/grok-media-client.test.ts +446 -0
  177. package/bundle/src/utils/providers/grok/grok-media-client.ts +703 -0
  178. package/bundle/src/utils/providers/grok/grok-models.test.ts +96 -0
  179. package/bundle/src/utils/providers/grok/grok-models.ts +161 -0
  180. package/bundle/src/utils/providers/grok/grok-oauth.test.ts +406 -0
  181. package/bundle/src/utils/providers/grok/grok-oauth.ts +771 -0
  182. package/bundle/src/utils/providers/grok/grok-quota.test.ts +142 -0
  183. package/bundle/src/utils/providers/grok/grok-quota.ts +198 -0
  184. package/bundle/src/utils/providers/grok/grok-refresh.test.ts +239 -0
  185. package/bundle/src/utils/providers/grok/grok-refresh.ts +325 -0
  186. package/bundle/src/utils/providers/grok/grok-types.test.ts +252 -0
  187. package/bundle/src/utils/providers/grok/grok-types.ts +374 -0
  188. package/bundle/src/utils/providers/grok/grok-voice-client.test.ts +321 -0
  189. package/bundle/src/utils/providers/grok/grok-voice-client.ts +284 -0
  190. package/bundle/src/utils/providers/grok/index.ts +20 -0
  191. package/bundle/src/utils/providers/openai/openai-backend-protocol.ts +221 -137
  192. package/bundle/src/utils/providers/openai/openai-callback-relay.ts +12 -1
  193. package/bundle/src/utils/providers/openai/openai-constants.ts +2 -0
  194. package/bundle/src/utils/providers/openai/openai-direct-client.ts +111 -21
  195. package/bundle/src/utils/providers/openai/openai-dispatcher.ts +322 -169
  196. package/bundle/src/utils/providers/openai/openai-image-generation.ts +116 -36
  197. package/bundle/src/utils/providers/openai/openai-oauth.ts +48 -20
  198. package/bundle/src/utils/providers/openai/openai-quota.ts +77 -46
  199. package/bundle/src/utils/providers/openai/openai-refresh.ts +42 -18
  200. package/bundle/src/utils/providers/openai/openai-sse.ts +27 -3
  201. package/bundle/src/utils/providers/openai/openai-transport-config.ts +2 -0
  202. package/bundle/src/utils/quiet-hours.ts +12 -1
  203. package/bundle/src/utils/slack-notify.ts +44 -13
  204. package/bundle/src/utils/subset-loaders.ts +7 -7
  205. package/bundle/web-dist/client/assets/clsx-5XM_pHvN.js +1 -0
  206. package/bundle/web-dist/client/assets/index-BA7uQ-6c.js +31 -0
  207. package/bundle/web-dist/client/assets/index-Be2qCZmI.css +1 -0
  208. package/bundle/web-dist/client/assets/logs-C47OJGEI.js +1 -0
  209. package/bundle/web-dist/client/assets/monit-BS9no0dU.js +4 -0
  210. package/bundle/web-dist/client/assets/plus-sdACTfH0.js +1 -0
  211. package/bundle/web-dist/client/assets/refresh-cw-CY8o_1cT.js +1 -0
  212. package/bundle/web-dist/client/assets/request-model-BRtFuZvj.js +1 -0
  213. package/bundle/web-dist/client/assets/routes-kqgkUxE8.js +5 -0
  214. package/bundle/web-dist/client/assets/{services.generated-BsieU37H.js → services.generated-CefiDXEv.js} +5 -5
  215. package/bundle/web-dist/client/assets/settings-DNDvFGSw.js +1 -0
  216. package/bundle/web-dist/client/assets/show-u8Np69q3.js +2 -0
  217. package/bundle/web-dist/client/assets/tokens-QvP410NW.js +1 -0
  218. package/bundle/web-dist/client/assets/total-cost-MnfKU8IN.js +1 -0
  219. package/bundle/web-dist/client/assets/use-oauth-login-flow-Bzdh28Ws.js +1 -0
  220. package/bundle/web-dist/client/assets/use-update-token-mutation-CfJKaxmR.js +1 -0
  221. package/bundle/web-dist/client/assets/vendor-react-CUFFrVN9.js +244 -0
  222. package/bundle/web-dist/client/assets/vendor-tanstack-Bf_jag9G.js +1 -0
  223. package/bundle/web-dist/client/index.html +6 -6
  224. package/bundle/web-dist/server/assets/clsx-D_N5PN_2.js +16 -0
  225. package/bundle/web-dist/server/assets/{lazyRouteComponent-Dtd0NR4r.js → lazyRouteComponent-D8iTIHyn.js} +129 -2
  226. package/bundle/web-dist/server/assets/logs-B3OTd9hy.js +825 -0
  227. package/bundle/web-dist/server/assets/{monit-DvzribSE.js → monit-B2hqorPe.js} +385 -126
  228. package/bundle/web-dist/server/assets/plus-DwG7h9kq.js +28 -0
  229. package/bundle/web-dist/server/assets/{react-dom-B4a6-uuR.js → react-dom-BIYQzBqG.js} +2 -129
  230. package/bundle/web-dist/server/assets/refresh-cw-mMBkwOq0.js +44 -0
  231. package/bundle/web-dist/server/assets/{request-model-CbqfnQOJ.js → request-model-I6OdODSH.js} +15 -6
  232. package/bundle/web-dist/server/assets/{routes-BAPWTizT.js → routes-B95YlUv2.js} +760 -213
  233. package/bundle/web-dist/server/assets/{services.generated-CEbGjsI0.js → services.generated-DQATJ6qf.js} +12821 -12194
  234. package/bundle/web-dist/server/assets/settings-C3gbGk0m.js +830 -0
  235. package/bundle/web-dist/server/assets/{show-CxVZTAdv.js → show-Bxaj3rhH.js} +1355 -419
  236. package/bundle/web-dist/server/assets/tokens-CZjH3cB7.js +1038 -0
  237. package/bundle/web-dist/server/assets/total-cost-fTE9Xy82.js +18 -0
  238. package/bundle/web-dist/server/assets/use-oauth-login-flow-CKDHgc3U.js +2379 -0
  239. package/bundle/web-dist/server/assets/{use-update-token-mutation-CfYmk_4_.js → use-update-token-mutation-BEbgOzaa.js} +1 -1
  240. package/bundle/web-dist/server/entry-server.generated.js +4303 -22810
  241. package/dist/cli.js +9 -9
  242. package/package.json +4 -11
  243. package/postinstall.mjs +12 -0
  244. package/skills/qgrid/SKILL.md +1 -0
  245. package/skills/qgrid/references/cli-env-and-server-boot.md +4 -1
  246. package/skills/qgrid/references/decision-rationale.md +24 -1
  247. package/skills/qgrid/references/grok-runtime.md +89 -0
  248. package/skills/qgrid/references/provider-runtime-differences.md +30 -29
  249. package/skills/qgrid/references/repo-map.md +10 -0
  250. package/skills/qgrid/references/request-log-run-lifecycle.md +1 -1
  251. package/skills/qgrid/references/sonamu-api-web-flow.md +1 -1
  252. package/skills/qgrid/references/token-auth-quota-lifecycle.md +56 -3
  253. package/bundle/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +0 -406
  254. package/bundle/dist/node_modules/.pnpm/@vitest_expect@4.1.10/node_modules/@vitest/expect/dist/index.js +0 -1507
  255. package/bundle/dist/node_modules/.pnpm/@vitest_pretty-format@4.1.10/node_modules/@vitest/pretty-format/dist/index.js +0 -887
  256. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/chunk-artifact.js +0 -2756
  257. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/index.js +0 -8
  258. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/utils.js +0 -8
  259. package/bundle/dist/node_modules/.pnpm/@vitest_snapshot@4.1.10/node_modules/@vitest/snapshot/dist/index.js +0 -922
  260. package/bundle/dist/node_modules/.pnpm/@vitest_spy@4.1.10/node_modules/@vitest/spy/dist/index.js +0 -386
  261. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +0 -121
  262. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/constants.js +0 -51
  263. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/diff.js +0 -1317
  264. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/display.js +0 -561
  265. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/error.js +0 -40
  266. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/helpers.js +0 -272
  267. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/offset.js +0 -27
  268. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/serialize.js +0 -77
  269. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/source-map.js +0 -381
  270. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/timers.js +0 -51
  271. package/bundle/dist/node_modules/.pnpm/chai@6.2.2/node_modules/chai/index.js +0 -2986
  272. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.js +0 -10
  273. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.js +0 -109
  274. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.js +0 -10
  275. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.js +0 -10
  276. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.js +0 -10
  277. package/bundle/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +0 -1126
  278. package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.js +0 -21
  279. package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +0 -432
  280. package/bundle/dist/node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.js +0 -517
  281. package/bundle/dist/node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js +0 -101
  282. 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
  283. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js +0 -9
  284. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/benchmark.CX_oY03V.js +0 -41
  285. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/evaluatedModules.Dg1zASAC.js +0 -19
  286. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/index.Chj8NDwU.js +0 -202
  287. 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
  288. 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
  289. 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
  290. 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
  291. 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
  292. package/bundle/dist/testing/setup-mocks.js +0 -16
  293. package/bundle/src/testing/setup-mocks.ts +0 -44
  294. package/bundle/web-dist/client/assets/index-Bw2s88Ot.css +0 -1
  295. package/bundle/web-dist/client/assets/index-CrXKu_J8.js +0 -106
  296. package/bundle/web-dist/client/assets/logs-B2SmWJXA.js +0 -1
  297. package/bundle/web-dist/client/assets/monit-D-JwXXoA.js +0 -1
  298. package/bundle/web-dist/client/assets/plus-B62CuqT8.js +0 -1
  299. package/bundle/web-dist/client/assets/refresh-cw-NNcU0Cmq.js +0 -1
  300. package/bundle/web-dist/client/assets/request-model-CojtinqK.js +0 -1
  301. package/bundle/web-dist/client/assets/routes-C5r4gTvY.js +0 -5
  302. package/bundle/web-dist/client/assets/settings-D3tDSAck.js +0 -1
  303. package/bundle/web-dist/client/assets/show-Cah_kUKC.js +0 -2
  304. package/bundle/web-dist/client/assets/tokens-DU2Iyxxd.js +0 -1
  305. package/bundle/web-dist/client/assets/use-oauth-login-flow-D0UaR9_e.js +0 -1
  306. package/bundle/web-dist/client/assets/use-update-token-mutation-DAq0F8p-.js +0 -1
  307. package/bundle/web-dist/client/assets/vendor-react-DH4kUfK2.js +0 -9
  308. package/bundle/web-dist/client/assets/vendor-tanstack-DJRQAbrY.js +0 -1
  309. package/bundle/web-dist/server/assets/logs-l91avYif.js +0 -509
  310. package/bundle/web-dist/server/assets/plus-KZrECewT.js +0 -19
  311. package/bundle/web-dist/server/assets/refresh-cw-BND93JrF.js +0 -23
  312. package/bundle/web-dist/server/assets/settings-BZR5HSAL.js +0 -461
  313. package/bundle/web-dist/server/assets/tokens-D1hb4eKk.js +0 -448
  314. package/bundle/web-dist/server/assets/use-oauth-login-flow-Cvdy0zF8.js +0 -178
  315. package/dist/cli.d.ts +0 -10
  316. /package/bundle/web-dist/client/assets/{cost-DH2jZbrw.js → cost-DB3HbU7T.js} +0 -0
  317. /package/bundle/web-dist/client/assets/{preload-helper-ca-nBW7U.js → preload-helper-DWTEM3RW.js} +0 -0
  318. /package/bundle/web-dist/server/assets/{cost-eEHeTRT5.js → cost-BC9yzyA9.js} +0 -0
@@ -1,6 +1,8 @@
1
1
  import { TokenModel } from "../../../application/token/token.model.js";
2
2
  import { deactivateAuthDeadToken } from "../../../application/qgrid/token-death.js";
3
+ import { OpenAICredentials } from "../../../application/token/token.types.js";
3
4
  import { OPENAI_CLIENT_ID, OPENAI_TOKEN_URL } from "./openai-constants.js";
5
+ import { z } from "zod";
4
6
  import { getLogger } from "@logtape/logtape";
5
7
  //#region src/utils/providers/openai/openai-refresh.ts
6
8
  /**
@@ -17,6 +19,14 @@ const PERMANENT_FAILURE_CODES = /* @__PURE__ */ new Set([
17
19
  "refresh_token_reused",
18
20
  "refresh_token_invalidated"
19
21
  ]);
22
+ const refreshErrorCodeSchema = z.string().regex(/^[a-z_]{1,80}$/);
23
+ const refreshErrorBodySchema = z.looseObject({ error: z.union([refreshErrorCodeSchema, z.looseObject({ code: refreshErrorCodeSchema }).transform((error) => error.code)]).optional() });
24
+ const refreshResponseSchema = z.object({
25
+ access_token: z.string(),
26
+ refresh_token: z.string().nullish(),
27
+ expires_in: z.number().nullish(),
28
+ id_token: z.string().nullish()
29
+ });
20
30
  const inflightRefresh = /* @__PURE__ */ new Map();
21
31
  const lastRefreshTime = /* @__PURE__ */ new Map();
22
32
  const REFRESH_MIN_INTERVAL_MS = 5e3;
@@ -44,7 +54,7 @@ async function handleChatgptAuthTokensRefresh(tokenId) {
44
54
  async function readCurrentCreds(tokenId) {
45
55
  const token = await TokenModel.findOne("A", { id: tokenId });
46
56
  if (!token || token.provider !== "openai") throw new Error(`token ${tokenId} not found`);
47
- const creds = token.credentials;
57
+ const creds = OpenAICredentials.parse(token.credentials);
48
58
  return {
49
59
  accessToken: creds.accessToken,
50
60
  chatgptAccountId: creds.accountId,
@@ -54,7 +64,7 @@ async function readCurrentCreds(tokenId) {
54
64
  async function doRefresh(tokenId) {
55
65
  const token = await TokenModel.findOne("A", { id: tokenId });
56
66
  if (!token || token.provider !== "openai") throw new Error(`token ${tokenId} not found or not openai`);
57
- const creds = token.credentials;
67
+ const creds = OpenAICredentials.loose().parse(token.credentials);
58
68
  if (!creds.refreshToken) throw new Error(`token ${tokenId} has no refreshToken`);
59
69
  logger.info(`refreshing token ${token.name} (id=${tokenId})`);
60
70
  const resp = await fetch(OPENAI_TOKEN_URL, {
@@ -70,9 +80,7 @@ async function doRefresh(tokenId) {
70
80
  const body = await resp.text().catch(() => "");
71
81
  let errorCode;
72
82
  try {
73
- const error = JSON.parse(body).error;
74
- const code = typeof error === "string" ? error : error && typeof error === "object" && "code" in error ? error.code : void 0;
75
- if (typeof code === "string" && /^[a-z_]{1,80}$/.test(code)) errorCode = code;
83
+ errorCode = refreshErrorBodySchema.safeParse(JSON.parse(body)).data?.error;
76
84
  } catch {}
77
85
  logger.error(`OpenAI refresh FAILED token=${token.name}(id=${tokenId}) status=${resp.status} code=${errorCode ?? "unknown"}`);
78
86
  if (errorCode && PERMANENT_FAILURE_CODES.has(errorCode)) await deactivateAuthDeadToken({
@@ -83,7 +91,7 @@ async function doRefresh(tokenId) {
83
91
  }, `openai:${errorCode}`);
84
92
  throw new Error(`OpenAI refresh failed: ${resp.status} ${errorCode ?? "unknown"}`);
85
93
  }
86
- const data = await resp.json();
94
+ const data = refreshResponseSchema.parse(await resp.json());
87
95
  const newRefreshToken = data.refresh_token ?? creds.refreshToken;
88
96
  const rotated = data.refresh_token !== null && data.refresh_token !== void 0 && data.refresh_token !== creds.refreshToken;
89
97
  if (rotated) logger.info(`refresh_token rotated for token ${token.name}`);
@@ -91,9 +99,9 @@ async function doRefresh(tokenId) {
91
99
  ...creds,
92
100
  accessToken: data.access_token,
93
101
  refreshToken: newRefreshToken,
94
- accessTokenExpiresAt: data.expires_in ? Date.now() + data.expires_in * 1e3 : creds.accessTokenExpiresAt,
95
- ...data.id_token ? { idToken: data.id_token } : {}
102
+ accessTokenExpiresAt: data.expires_in ? Date.now() + data.expires_in * 1e3 : creds.accessTokenExpiresAt
96
103
  };
104
+ if (data.id_token) updatedCreds.idToken = data.id_token;
97
105
  try {
98
106
  await TokenModel.save([{
99
107
  id: tokenId,
@@ -116,4 +124,4 @@ async function doRefresh(tokenId) {
116
124
  //#endregion
117
125
  export { handleChatgptAuthTokensRefresh };
118
126
 
119
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLXJlZnJlc2guanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9vcGVuYWkvb3BlbmFpLXJlZnJlc2gudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBPcGVuQUkgY2hhdGdwdEF1dGhUb2tlbnMgcmVmcmVzaCBoYW5kbGVyLlxuICpcbiAqIC0gZGlyZWN0IHRyYW5zcG9ydOyZgCBxdW90YSDsobDtmozsnZggNDAx7JeQ7IScIOqwmeydgCByZWZyZXNoIOqyveuhnOulvCDsgqzsmqntlahcbiAqIC0gcWdyaWQg6rCAIERCIOydmCByZWZyZXNoX3Rva2VuIOycvOuhnCDsg4ggYWNjZXNzX3Rva2VuIOydhCDrsJzquInrsJvslYQg7J2R64u1XG4gKiAtIHBlci10b2tlbiBpbmZsaWdodCBwcm9taXNlIOuhnCBjb25jdXJyZW50IHJlZnJlc2ggZGVkdXBcbiAqIC0gcm90YXRpb24g6rCQ7KeAOiDsg4ggcmVmcmVzaF90b2tlbiDsnojsnLzrqbQgREIg7KaJ7IucIOyXheuNsOydtO2KuFxuICovXG5pbXBvcnQgeyBnZXRMb2dnZXIgfSBmcm9tIFwiQGxvZ3RhcGUvbG9ndGFwZVwiO1xuXG5pbXBvcnQgeyBkZWFjdGl2YXRlQXV0aERlYWRUb2tlbiB9IGZyb20gXCIuLi8uLi8uLi9hcHBsaWNhdGlvbi9xZ3JpZC90b2tlbi1kZWF0aFwiO1xuaW1wb3J0IHsgVG9rZW5Nb2RlbCB9IGZyb20gXCIuLi8uLi8uLi9hcHBsaWNhdGlvbi90b2tlbi90b2tlbi5tb2RlbFwiO1xuaW1wb3J0IHsgdHlwZSBPcGVuQUlDcmVkZW50aWFscyB9IGZyb20gXCIuLi8uLi8uLi9hcHBsaWNhdGlvbi90b2tlbi90b2tlbi50eXBlc1wiO1xuXG5jb25zdCBsb2dnZXIgPSBnZXRMb2dnZXIoW1wicWdyaWRcIiwgXCJvcGVuYWktcmVmcmVzaFwiXSk7XG5cbmltcG9ydCB7IE9QRU5BSV9DTElFTlRfSUQsIE9QRU5BSV9UT0tFTl9VUkwgfSBmcm9tIFwiLi9vcGVuYWktY29uc3RhbnRzXCI7XG5cbi8vIOyerOuhnOq3uOyduCDsmbgg67O16rWsIOu2iOqwgO2VnCByZWZyZXNoIOyLpO2MqCDsvZTrk5wuIOyWtOuKkCDqsoPsnbTrk6Ag7Yag7YGw7J20IOyjveyXiOuLpOuKlCDtmZXsoJUg7Iug7Zi464ukLlxuY29uc3QgUEVSTUFORU5UX0ZBSUxVUkVfQ09ERVMgPSBuZXcgU2V0KFtcbiAgXCJyZWZyZXNoX3Rva2VuX2V4cGlyZWRcIixcbiAgXCJyZWZyZXNoX3Rva2VuX3JldXNlZFwiLFxuICBcInJlZnJlc2hfdG9rZW5faW52YWxpZGF0ZWRcIixcbl0pO1xuXG4vLyBwZXItdG9rZW4gaW5mbGlnaHQgcHJvbWlzZSBkZWR1cCArIG1pbmltdW0gaW50ZXJ2YWxcbmNvbnN0IGluZmxpZ2h0UmVmcmVzaCA9IG5ldyBNYXA8bnVtYmVyLCBQcm9taXNlPFJlZnJlc2hSZXN1bHQ+PigpO1xuY29uc3QgbGFzdFJlZnJlc2hUaW1lID0gbmV3IE1hcDxudW1iZXIsIG51bWJlcj4oKTtcbmNvbnN0IFJFRlJFU0hfTUlOX0lOVEVSVkFMX01TID0gNV8wMDA7XG5cbmludGVyZmFjZSBSZWZyZXNoUmVzdWx0IHtcbiAgYWNjZXNzVG9rZW46IHN0cmluZztcbiAgY2hhdGdwdEFjY291bnRJZDogc3RyaW5nO1xuICBjaGF0Z3B0UGxhblR5cGU/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVDaGF0Z3B0QXV0aFRva2Vuc1JlZnJlc2godG9rZW5JZDogbnVtYmVyKTogUHJvbWlzZTxSZWZyZXNoUmVzdWx0PiB7XG4gIGxvZ2dlci5pbmZvKGByZWZyZXNoIHJlcXVlc3RlZCBmb3IgdG9rZW4gJHt0b2tlbklkfSAocGlkPSR7cHJvY2Vzcy5waWR9KWApO1xuICBjb25zdCBleGlzdGluZyA9IGluZmxpZ2h0UmVmcmVzaC5nZXQodG9rZW5JZCk7XG4gIGlmIChleGlzdGluZykge1xuICAgIGxvZ2dlci5pbmZvKGByZWZyZXNoIGRlZHVwIGZvciB0b2tlbiAke3Rva2VuSWR9YCk7XG4gICAgcmV0dXJuIGV4aXN0aW5nO1xuICB9XG5cbiAgY29uc3QgbGFzdEF0ID0gbGFzdFJlZnJlc2hUaW1lLmdldCh0b2tlbklkKSA/PyAwO1xuICBpZiAoRGF0ZS5ub3coKSAtIGxhc3RBdCA8IFJFRlJFU0hfTUlOX0lOVEVSVkFMX01TKSB7XG4gICAgbG9nZ2VyLmluZm8oYHJlZnJlc2ggdG9vIHNvb24gZm9yIHRva2VuICR7dG9rZW5JZH0sIHJlYWRpbmcgY3VycmVudCBjcmVkcyBmcm9tIERCYCk7XG4gICAgcmV0dXJuIHJlYWRDdXJyZW50Q3JlZHModG9rZW5JZCk7XG4gIH1cblxuICBsYXN0UmVmcmVzaFRpbWUuc2V0KHRva2VuSWQsIERhdGUubm93KCkpO1xuICBjb25zdCBwcm9taXNlID0gZG9SZWZyZXNoKHRva2VuSWQpO1xuICBpbmZsaWdodFJlZnJlc2guc2V0KHRva2VuSWQsIHByb21pc2UpO1xuXG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IHByb21pc2U7XG4gIH0gZmluYWxseSB7XG4gICAgaW5mbGlnaHRSZWZyZXNoLmRlbGV0ZSh0b2tlbklkKTtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiByZWFkQ3VycmVudENyZWRzKHRva2VuSWQ6IG51bWJlcik6IFByb21pc2U8UmVmcmVzaFJlc3VsdD4ge1xuICBjb25zdCB0b2tlbiA9IGF3YWl0IFRva2VuTW9kZWwuZmluZE9uZShcIkFcIiwgeyBpZDogdG9rZW5JZCB9KTtcbiAgaWYgKCF0b2tlbiB8fCB0b2tlbi5wcm92aWRlciAhPT0gXCJvcGVuYWlcIikgdGhyb3cgbmV3IEVycm9yKGB0b2tlbiAke3Rva2VuSWR9IG5vdCBmb3VuZGApO1xuICBjb25zdCBjcmVkcyA9IHRva2VuLmNyZWRlbnRpYWxzIGFzIE9wZW5BSUNyZWRlbnRpYWxzO1xuICByZXR1cm4ge1xuICAgIGFjY2Vzc1Rva2VuOiBjcmVkcy5hY2Nlc3NUb2tlbixcbiAgICBjaGF0Z3B0QWNjb3VudElkOiBjcmVkcy5hY2NvdW50SWQsXG4gICAgY2hhdGdwdFBsYW5UeXBlOiBjcmVkcy5wbGFuVHlwZSxcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZG9SZWZyZXNoKHRva2VuSWQ6IG51bWJlcik6IFByb21pc2U8UmVmcmVzaFJlc3VsdD4ge1xuICBjb25zdCB0b2tlbiA9IGF3YWl0IFRva2VuTW9kZWwuZmluZE9uZShcIkFcIiwgeyBpZDogdG9rZW5JZCB9KTtcbiAgaWYgKCF0b2tlbiB8fCB0b2tlbi5wcm92aWRlciAhPT0gXCJvcGVuYWlcIikge1xuICAgIHRocm93IG5ldyBFcnJvcihgdG9rZW4gJHt0b2tlbklkfSBub3QgZm91bmQgb3Igbm90IG9wZW5haWApO1xuICB9XG5cbiAgY29uc3QgY3JlZHMgPSB0b2tlbi5jcmVkZW50aWFscyBhcyBPcGVuQUlDcmVkZW50aWFscztcbiAgaWYgKCFjcmVkcy5yZWZyZXNoVG9rZW4pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHRva2VuICR7dG9rZW5JZH0gaGFzIG5vIHJlZnJlc2hUb2tlbmApO1xuICB9XG5cbiAgbG9nZ2VyLmluZm8oYHJlZnJlc2hpbmcgdG9rZW4gJHt0b2tlbi5uYW1lfSAoaWQ9JHt0b2tlbklkfSlgKTtcblxuICBjb25zdCByZXNwID0gYXdhaXQgZmV0Y2goT1BFTkFJX1RPS0VOX1VSTCwge1xuICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgLy8g7Yag7YGwIOyXlOuTnO2PrOyduO2KuOuKlCBPQXV0aCDtkZzspIAgZm9ybSDsnbjsvZTrlKkg6rOE7JW97J2EIOqwleygnO2VnOuLpC4gSlNPTiDsnLzroZwg67O064K066m0XG4gICAgLy8gYWNjZXNzIHRva2VuIOunjOujjCDtm4TsnZgg66qo65OgIHJlZnJlc2gg6rCAIOqxsOu2gOuQmOyWtCDthqDtgbDsnbQg7Ya17Ke466GcIOyjveuKlOuLpC5cbiAgICBoZWFkZXJzOiB7IFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkXCIgfSxcbiAgICBib2R5OiBuZXcgVVJMU2VhcmNoUGFyYW1zKHtcbiAgICAgIGdyYW50X3R5cGU6IFwicmVmcmVzaF90b2tlblwiLFxuICAgICAgY2xpZW50X2lkOiBPUEVOQUlfQ0xJRU5UX0lELFxuICAgICAgcmVmcmVzaF90b2tlbjogY3JlZHMucmVmcmVzaFRva2VuLFxuICAgIH0pLFxuICB9KTtcblxuICBpZiAoIXJlc3Aub2spIHtcbiAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVzcC50ZXh0KCkuY2F0Y2goKCkgPT4gXCJcIik7XG4gICAgLy8gNDAxIOuzuOusuOydmCBlcnJvciDsvZTrk5zqsIAg7Yag7YGwIOyCrOunneydmCDqsrDsoJXsoIEg7IKs7J247J2064ukLlxuICAgIC8vICAgcmVmcmVzaF90b2tlbl9leHBpcmVkICAgICDihpIgcmVmcmVzaF90b2tlbiDsnpDssrQg66eM66OMXG4gICAgLy8gICByZWZyZXNoX3Rva2VuX3JldXNlZCAgICAgIOKGkiDsnbTrr7gg7IKs7Jqp65CcKO2ajOyghCDtj5DquLDrkJwpIHJlZnJlc2hfdG9rZW4g7J6s7IKs7JqpIOKGkiDtjKjrsIDrpqwg66y07Zqo7ZmUXG4gICAgLy8gICByZWZyZXNoX3Rva2VuX2ludmFsaWRhdGVkIOKGkiDshJzrsoTsuKEgcmV2b2tlXG4gICAgLy8g7JyEIDPqsJzripQg66qo65GQIOyYgeq1rCDsi6TtjKguIOyerOuTseuhnSDsmbgg67O16rWsIOu2iOqwgC5cbiAgICBsZXQgZXJyb3JDb2RlOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGVycm9yID0gKEpTT04ucGFyc2UoYm9keSkgYXMgeyBlcnJvcj86IHVua25vd24gfSkuZXJyb3I7XG4gICAgICBjb25zdCBjb2RlID1cbiAgICAgICAgdHlwZW9mIGVycm9yID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgPyBlcnJvclxuICAgICAgICAgIDogZXJyb3IgJiYgdHlwZW9mIGVycm9yID09PSBcIm9iamVjdFwiICYmIFwiY29kZVwiIGluIGVycm9yXG4gICAgICAgICAgICA/IGVycm9yLmNvZGVcbiAgICAgICAgICAgIDogdW5kZWZpbmVkO1xuICAgICAgaWYgKHR5cGVvZiBjb2RlID09PSBcInN0cmluZ1wiICYmIC9eW2Etel9dezEsODB9JC8udGVzdChjb2RlKSkgZXJyb3JDb2RlID0gY29kZTtcbiAgICB9IGNhdGNoIHt9XG4gICAgbG9nZ2VyLmVycm9yKFxuICAgICAgYE9wZW5BSSByZWZyZXNoIEZBSUxFRCB0b2tlbj0ke3Rva2VuLm5hbWV9KGlkPSR7dG9rZW5JZH0pIHN0YXR1cz0ke3Jlc3Auc3RhdHVzfSBgICtcbiAgICAgICAgYGNvZGU9JHtlcnJvckNvZGUgPz8gXCJ1bmtub3duXCJ9YCxcbiAgICApO1xuICAgIC8vIOyYgeq1rCDsi6TtjKjripQgZXJyb3JDb2RlIOuhnOunjCDtjJDsoJXtlZzri6Qg4oCUIHN0YXR1cyDrpbwg7ZWo6ruYIOyalOq1rO2VmOuptCBwcm92aWRlciDqsIBcbiAgICAvLyDsg4Htg5zsvZTrk5zrpbwg67CU6r+AIOuVjCDtjJDsoJXsnbQg7KGw7Jqp7Z6IIOupjuuKlOuLpC5cbiAgICBpZiAoZXJyb3JDb2RlICYmIFBFUk1BTkVOVF9GQUlMVVJFX0NPREVTLmhhcyhlcnJvckNvZGUpKSB7XG4gICAgICBhd2FpdCBkZWFjdGl2YXRlQXV0aERlYWRUb2tlbihcbiAgICAgICAgeyBpZDogdG9rZW5JZCwgbmFtZTogdG9rZW4ubmFtZSwgcHJvdmlkZXI6IFwib3BlbmFpXCIsIGNyZWRlbnRpYWxzOiBjcmVkcyB9LFxuICAgICAgICBgb3BlbmFpOiR7ZXJyb3JDb2RlfWAsXG4gICAgICApO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoYE9wZW5BSSByZWZyZXNoIGZhaWxlZDogJHtyZXNwLnN0YXR1c30gJHtlcnJvckNvZGUgPz8gXCJ1bmtub3duXCJ9YCk7XG4gIH1cblxuICBjb25zdCBkYXRhID0gKGF3YWl0IHJlc3AuanNvbigpKSBhcyB7XG4gICAgYWNjZXNzX3Rva2VuOiBzdHJpbmc7XG4gICAgcmVmcmVzaF90b2tlbj86IHN0cmluZztcbiAgICBleHBpcmVzX2luPzogbnVtYmVyO1xuICAgIGlkX3Rva2VuPzogc3RyaW5nO1xuICB9O1xuXG4gIGNvbnN0IG5ld1JlZnJlc2hUb2tlbiA9IGRhdGEucmVmcmVzaF90b2tlbiA/PyBjcmVkcy5yZWZyZXNoVG9rZW47XG4gIGNvbnN0IHJvdGF0ZWQgPVxuICAgIGRhdGEucmVmcmVzaF90b2tlbiAhPT0gbnVsbCAmJlxuICAgIGRhdGEucmVmcmVzaF90b2tlbiAhPT0gdW5kZWZpbmVkICYmXG4gICAgZGF0YS5yZWZyZXNoX3Rva2VuICE9PSBjcmVkcy5yZWZyZXNoVG9rZW47XG4gIGlmIChyb3RhdGVkKSB7XG4gICAgbG9nZ2VyLmluZm8oYHJlZnJlc2hfdG9rZW4gcm90YXRlZCBmb3IgdG9rZW4gJHt0b2tlbi5uYW1lfWApO1xuICB9XG5cbiAgY29uc3QgdXBkYXRlZENyZWRzOiBPcGVuQUlDcmVkZW50aWFscyA9IHtcbiAgICAuLi5jcmVkcyxcbiAgICBhY2Nlc3NUb2tlbjogZGF0YS5hY2Nlc3NfdG9rZW4sXG4gICAgcmVmcmVzaFRva2VuOiBuZXdSZWZyZXNoVG9rZW4sXG4gICAgYWNjZXNzVG9rZW5FeHBpcmVzQXQ6IGRhdGEuZXhwaXJlc19pblxuICAgICAgPyBEYXRlLm5vdygpICsgZGF0YS5leHBpcmVzX2luICogMTAwMFxuICAgICAgOiBjcmVkcy5hY2Nlc3NUb2tlbkV4cGlyZXNBdCxcbiAgICAuLi4oZGF0YS5pZF90b2tlbiA/IHsgaWRUb2tlbjogZGF0YS5pZF90b2tlbiB9IDoge30pLFxuICB9O1xuXG4gIC8vIO2ajOyghChyb3RhdGVkKeydtCDsnbzslrTrgqzripTrjbAg7J20IHNhdmUg6rCAIOyLpO2MqO2VmOuptCwgT3BlbkFJIOyqvSDsmJsgcmVmcmVzaF90b2tlbiDsnYAg7J2066+4XG4gIC8vIO2PkOq4sOuQnCDsg4Htg5zsl5DshJwgREIg7JeQ64qUIOyYmyDthqDtgbDsnbQg64Ko64qU64ukIOKGkiDri6TsnYwgcmVmcmVzaCDqsIAgcmVmcmVzaF90b2tlbl9yZXVzZWQg66GcXG4gIC8vIOyYgeq1rCDsgqzrp50uIOydtCDqtazqsIQg7Iuk7Yyo64qUIO2GoO2BsCDsgqzrp53snZgg7KeB7KCRIOybkOyduOydtOuvgOuhnCDrsJjrk5zsi5wg7YGs6rKMIOuCqOq4tOuLpC5cbiAgdHJ5IHtcbiAgICBhd2FpdCBUb2tlbk1vZGVsLnNhdmUoW1xuICAgICAge1xuICAgICAgICBpZDogdG9rZW5JZCxcbiAgICAgICAgcHJvdmlkZXI6IFwib3BlbmFpXCIsXG4gICAgICAgIGNyZWRlbnRpYWxzOiB1cGRhdGVkQ3JlZHMsXG4gICAgICAgIG5hbWU6IHRva2VuLm5hbWUsXG4gICAgICAgIHJlYXV0aF9yZXF1aXJlZDogZmFsc2UsXG4gICAgICB9LFxuICAgIF0pO1xuICB9IGNhdGNoIChlKSB7XG4gICAgbG9nZ2VyLmVycm9yKFxuICAgICAgYE9wZW5BSSByZWZyZXNoOiBEQiBzYXZlIEZBSUxFRCBhZnRlciByb3RhdGlvbihyb3RhdGVkPSR7cm90YXRlZH0pIGAgK1xuICAgICAgICBgdG9rZW49JHt0b2tlbi5uYW1lfShpZD0ke3Rva2VuSWR9KSDigJQg7JibIHJlZnJlc2hfdG9rZW4g7Y+Q6riw65CoLCBEQiDrr7jrsJjsmIEg4oaSIO2GoO2BsCDsgqzrp50g7JyE7ZeYLiBlcnI9JHtTdHJpbmcoZSl9YCxcbiAgICApO1xuICAgIHRocm93IGU7XG4gIH1cblxuICBsb2dnZXIuaW5mbyhgdG9rZW4gJHt0b2tlbi5uYW1lfSByZWZyZXNoZWQgc3VjY2Vzc2Z1bGx5IChyb3RhdGVkPSR7cm90YXRlZH0pYCk7XG5cbiAgcmV0dXJuIHtcbiAgICBhY2Nlc3NUb2tlbjogZGF0YS5hY2Nlc3NfdG9rZW4sXG4gICAgY2hhdGdwdEFjY291bnRJZDogY3JlZHMuYWNjb3VudElkLFxuICAgIGNoYXRncHRQbGFuVHlwZTogY3JlZHMucGxhblR5cGUsXG4gIH07XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7QUFjQSxN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
127
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLXJlZnJlc2guanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9vcGVuYWkvb3BlbmFpLXJlZnJlc2gudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBPcGVuQUkgY2hhdGdwdEF1dGhUb2tlbnMgcmVmcmVzaCBoYW5kbGVyLlxuICpcbiAqIC0gZGlyZWN0IHRyYW5zcG9ydOyZgCBxdW90YSDsobDtmozsnZggNDAx7JeQ7IScIOqwmeydgCByZWZyZXNoIOqyveuhnOulvCDsgqzsmqntlahcbiAqIC0gcWdyaWQg6rCAIERCIOydmCByZWZyZXNoX3Rva2VuIOycvOuhnCDsg4ggYWNjZXNzX3Rva2VuIOydhCDrsJzquInrsJvslYQg7J2R64u1XG4gKiAtIHBlci10b2tlbiBpbmZsaWdodCBwcm9taXNlIOuhnCBjb25jdXJyZW50IHJlZnJlc2ggZGVkdXBcbiAqIC0gcm90YXRpb24g6rCQ7KeAOiDsg4ggcmVmcmVzaF90b2tlbiDsnojsnLzrqbQgREIg7KaJ7IucIOyXheuNsOydtO2KuFxuICovXG5pbXBvcnQgeyBnZXRMb2dnZXIgfSBmcm9tIFwiQGxvZ3RhcGUvbG9ndGFwZVwiO1xuaW1wb3J0IHsgeiB9IGZyb20gXCJ6b2RcIjtcblxuaW1wb3J0IHsgZGVhY3RpdmF0ZUF1dGhEZWFkVG9rZW4gfSBmcm9tIFwiLi4vLi4vLi4vYXBwbGljYXRpb24vcWdyaWQvdG9rZW4tZGVhdGhcIjtcbmltcG9ydCB7IFRva2VuTW9kZWwgfSBmcm9tIFwiLi4vLi4vLi4vYXBwbGljYXRpb24vdG9rZW4vdG9rZW4ubW9kZWxcIjtcbmltcG9ydCB7IE9wZW5BSUNyZWRlbnRpYWxzIH0gZnJvbSBcIi4uLy4uLy4uL2FwcGxpY2F0aW9uL3Rva2VuL3Rva2VuLnR5cGVzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGdldExvZ2dlcihbXCJxZ3JpZFwiLCBcIm9wZW5haS1yZWZyZXNoXCJdKTtcblxuaW1wb3J0IHsgT1BFTkFJX0NMSUVOVF9JRCwgT1BFTkFJX1RPS0VOX1VSTCB9IGZyb20gXCIuL29wZW5haS1jb25zdGFudHNcIjtcblxuLy8g7J6s66Gc6re47J24IOyZuCDrs7Xqtawg67aI6rCA7ZWcIHJlZnJlc2gg7Iuk7YyoIOy9lOuTnC4g7Ja064qQIOqyg+ydtOuToCDthqDtgbDsnbQg7KO97JeI64uk64qUIO2ZleyglSDsi6DtmLjri6QuXG5jb25zdCBQRVJNQU5FTlRfRkFJTFVSRV9DT0RFUyA9IG5ldyBTZXQoW1xuICBcInJlZnJlc2hfdG9rZW5fZXhwaXJlZFwiLFxuICBcInJlZnJlc2hfdG9rZW5fcmV1c2VkXCIsXG4gIFwicmVmcmVzaF90b2tlbl9pbnZhbGlkYXRlZFwiLFxuXSk7XG5cbi8vIE9ubHkgc2hvcnQgc25ha2VfY2FzZSBjb2RlcyBhcmUgdHJ1c3RlZDsgYW55dGhpbmcgZWxzZSBpbiBhIDQwMSBib2R5IHJlYWRzIGFzIFwidW5rbm93blwiLlxuY29uc3QgcmVmcmVzaEVycm9yQ29kZVNjaGVtYSA9IHouc3RyaW5nKCkucmVnZXgoL15bYS16X117MSw4MH0kLyk7XG5cbi8vIGBlcnJvcmAgaXMgZWl0aGVyIHRoZSBjb2RlIGl0c2VsZiBvciBhbiBvYmplY3QgY2FycnlpbmcgYGNvZGVgLlxuY29uc3QgcmVmcmVzaEVycm9yQm9keVNjaGVtYSA9IHoubG9vc2VPYmplY3Qoe1xuICBlcnJvcjogelxuICAgIC51bmlvbihbXG4gICAgICByZWZyZXNoRXJyb3JDb2RlU2NoZW1hLFxuICAgICAgei5sb29zZU9iamVjdCh7IGNvZGU6IHJlZnJlc2hFcnJvckNvZGVTY2hlbWEgfSkudHJhbnNmb3JtKChlcnJvcikgPT4gZXJyb3IuY29kZSksXG4gICAgXSlcbiAgICAub3B0aW9uYWwoKSxcbn0pO1xuXG5jb25zdCByZWZyZXNoUmVzcG9uc2VTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIGFjY2Vzc190b2tlbjogei5zdHJpbmcoKSxcbiAgcmVmcmVzaF90b2tlbjogei5zdHJpbmcoKS5udWxsaXNoKCksXG4gIGV4cGlyZXNfaW46IHoubnVtYmVyKCkubnVsbGlzaCgpLFxuICBpZF90b2tlbjogei5zdHJpbmcoKS5udWxsaXNoKCksXG59KTtcblxuLy8gcGVyLXRva2VuIGluZmxpZ2h0IHByb21pc2UgZGVkdXAgKyBtaW5pbXVtIGludGVydmFsXG5jb25zdCBpbmZsaWdodFJlZnJlc2ggPSBuZXcgTWFwPG51bWJlciwgUHJvbWlzZTxSZWZyZXNoUmVzdWx0Pj4oKTtcbmNvbnN0IGxhc3RSZWZyZXNoVGltZSA9IG5ldyBNYXA8bnVtYmVyLCBudW1iZXI+KCk7XG5jb25zdCBSRUZSRVNIX01JTl9JTlRFUlZBTF9NUyA9IDVfMDAwO1xuXG5pbnRlcmZhY2UgUmVmcmVzaFJlc3VsdCB7XG4gIGFjY2Vzc1Rva2VuOiBzdHJpbmc7XG4gIGNoYXRncHRBY2NvdW50SWQ6IHN0cmluZztcbiAgY2hhdGdwdFBsYW5UeXBlPzogc3RyaW5nO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlQ2hhdGdwdEF1dGhUb2tlbnNSZWZyZXNoKHRva2VuSWQ6IG51bWJlcik6IFByb21pc2U8UmVmcmVzaFJlc3VsdD4ge1xuICBsb2dnZXIuaW5mbyhgcmVmcmVzaCByZXF1ZXN0ZWQgZm9yIHRva2VuICR7dG9rZW5JZH0gKHBpZD0ke3Byb2Nlc3MucGlkfSlgKTtcbiAgY29uc3QgZXhpc3RpbmcgPSBpbmZsaWdodFJlZnJlc2guZ2V0KHRva2VuSWQpO1xuXG4gIGlmIChleGlzdGluZykge1xuICAgIGxvZ2dlci5pbmZvKGByZWZyZXNoIGRlZHVwIGZvciB0b2tlbiAke3Rva2VuSWR9YCk7XG5cbiAgICByZXR1cm4gZXhpc3Rpbmc7XG4gIH1cblxuICBjb25zdCBsYXN0QXQgPSBsYXN0UmVmcmVzaFRpbWUuZ2V0KHRva2VuSWQpID8/IDA7XG5cbiAgaWYgKERhdGUubm93KCkgLSBsYXN0QXQgPCBSRUZSRVNIX01JTl9JTlRFUlZBTF9NUykge1xuICAgIGxvZ2dlci5pbmZvKGByZWZyZXNoIHRvbyBzb29uIGZvciB0b2tlbiAke3Rva2VuSWR9LCByZWFkaW5nIGN1cnJlbnQgY3JlZHMgZnJvbSBEQmApO1xuXG4gICAgcmV0dXJuIHJlYWRDdXJyZW50Q3JlZHModG9rZW5JZCk7XG4gIH1cblxuICBsYXN0UmVmcmVzaFRpbWUuc2V0KHRva2VuSWQsIERhdGUubm93KCkpO1xuICBjb25zdCBwcm9taXNlID0gZG9SZWZyZXNoKHRva2VuSWQpO1xuICBpbmZsaWdodFJlZnJlc2guc2V0KHRva2VuSWQsIHByb21pc2UpO1xuXG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IHByb21pc2U7XG4gIH0gZmluYWxseSB7XG4gICAgaW5mbGlnaHRSZWZyZXNoLmRlbGV0ZSh0b2tlbklkKTtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiByZWFkQ3VycmVudENyZWRzKHRva2VuSWQ6IG51bWJlcik6IFByb21pc2U8UmVmcmVzaFJlc3VsdD4ge1xuICBjb25zdCB0b2tlbiA9IGF3YWl0IFRva2VuTW9kZWwuZmluZE9uZShcIkFcIiwgeyBpZDogdG9rZW5JZCB9KTtcblxuICBpZiAoIXRva2VuIHx8IHRva2VuLnByb3ZpZGVyICE9PSBcIm9wZW5haVwiKSB0aHJvdyBuZXcgRXJyb3IoYHRva2VuICR7dG9rZW5JZH0gbm90IGZvdW5kYCk7XG4gIGNvbnN0IGNyZWRzID0gT3BlbkFJQ3JlZGVudGlhbHMucGFyc2UodG9rZW4uY3JlZGVudGlhbHMpO1xuXG4gIHJldHVybiB7XG4gICAgYWNjZXNzVG9rZW46IGNyZWRzLmFjY2Vzc1Rva2VuLFxuICAgIGNoYXRncHRBY2NvdW50SWQ6IGNyZWRzLmFjY291bnRJZCxcbiAgICBjaGF0Z3B0UGxhblR5cGU6IGNyZWRzLnBsYW5UeXBlLFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBkb1JlZnJlc2godG9rZW5JZDogbnVtYmVyKTogUHJvbWlzZTxSZWZyZXNoUmVzdWx0PiB7XG4gIGNvbnN0IHRva2VuID0gYXdhaXQgVG9rZW5Nb2RlbC5maW5kT25lKFwiQVwiLCB7IGlkOiB0b2tlbklkIH0pO1xuXG4gIGlmICghdG9rZW4gfHwgdG9rZW4ucHJvdmlkZXIgIT09IFwib3BlbmFpXCIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHRva2VuICR7dG9rZW5JZH0gbm90IGZvdW5kIG9yIG5vdCBvcGVuYWlgKTtcbiAgfVxuXG4gIGNvbnN0IGNyZWRzID0gT3BlbkFJQ3JlZGVudGlhbHMubG9vc2UoKS5wYXJzZSh0b2tlbi5jcmVkZW50aWFscyk7XG5cbiAgaWYgKCFjcmVkcy5yZWZyZXNoVG9rZW4pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHRva2VuICR7dG9rZW5JZH0gaGFzIG5vIHJlZnJlc2hUb2tlbmApO1xuICB9XG5cbiAgbG9nZ2VyLmluZm8oYHJlZnJlc2hpbmcgdG9rZW4gJHt0b2tlbi5uYW1lfSAoaWQ9JHt0b2tlbklkfSlgKTtcblxuICBjb25zdCByZXNwID0gYXdhaXQgZmV0Y2goT1BFTkFJX1RPS0VOX1VSTCwge1xuICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgLy8g7Yag7YGwIOyXlOuTnO2PrOyduO2KuOuKlCBPQXV0aCDtkZzspIAgZm9ybSDsnbjsvZTrlKkg6rOE7JW97J2EIOqwleygnO2VnOuLpC4gSlNPTiDsnLzroZwg67O064K066m0XG4gICAgLy8gYWNjZXNzIHRva2VuIOunjOujjCDtm4TsnZgg66qo65OgIHJlZnJlc2gg6rCAIOqxsOu2gOuQmOyWtCDthqDtgbDsnbQg7Ya17Ke466GcIOyjveuKlOuLpC5cbiAgICBoZWFkZXJzOiB7IFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkXCIgfSxcbiAgICBib2R5OiBuZXcgVVJMU2VhcmNoUGFyYW1zKHtcbiAgICAgIGdyYW50X3R5cGU6IFwicmVmcmVzaF90b2tlblwiLFxuICAgICAgY2xpZW50X2lkOiBPUEVOQUlfQ0xJRU5UX0lELFxuICAgICAgcmVmcmVzaF90b2tlbjogY3JlZHMucmVmcmVzaFRva2VuLFxuICAgIH0pLFxuICB9KTtcblxuICBpZiAoIXJlc3Aub2spIHtcbiAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVzcC50ZXh0KCkuY2F0Y2goKCkgPT4gXCJcIik7XG4gICAgLy8gNDAxIOuzuOusuOydmCBlcnJvciDsvZTrk5zqsIAg7Yag7YGwIOyCrOunneydmCDqsrDsoJXsoIEg7IKs7J247J2064ukLlxuICAgIC8vICAgcmVmcmVzaF90b2tlbl9leHBpcmVkICAgICDihpIgcmVmcmVzaF90b2tlbiDsnpDssrQg66eM66OMXG4gICAgLy8gICByZWZyZXNoX3Rva2VuX3JldXNlZCAgICAgIOKGkiDsnbTrr7gg7IKs7Jqp65CcKO2ajOyghCDtj5DquLDrkJwpIHJlZnJlc2hfdG9rZW4g7J6s7IKs7JqpIOKGkiDtjKjrsIDrpqwg66y07Zqo7ZmUXG4gICAgLy8gICByZWZyZXNoX3Rva2VuX2ludmFsaWRhdGVkIOKGkiDshJzrsoTsuKEgcmV2b2tlXG4gICAgLy8g7JyEIDPqsJzripQg66qo65GQIOyYgeq1rCDsi6TtjKguIOyerOuTseuhnSDsmbgg67O16rWsIOu2iOqwgC5cbiAgICBsZXQgZXJyb3JDb2RlOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgICB0cnkge1xuICAgICAgZXJyb3JDb2RlID0gcmVmcmVzaEVycm9yQm9keVNjaGVtYS5zYWZlUGFyc2UoSlNPTi5wYXJzZShib2R5KSkuZGF0YT8uZXJyb3I7XG4gICAgfSBjYXRjaCB7fVxuXG4gICAgbG9nZ2VyLmVycm9yKFxuICAgICAgYE9wZW5BSSByZWZyZXNoIEZBSUxFRCB0b2tlbj0ke3Rva2VuLm5hbWV9KGlkPSR7dG9rZW5JZH0pIHN0YXR1cz0ke3Jlc3Auc3RhdHVzfSBgICtcbiAgICAgICAgYGNvZGU9JHtlcnJvckNvZGUgPz8gXCJ1bmtub3duXCJ9YCxcbiAgICApO1xuXG4gICAgLy8g7JiB6rWsIOyLpO2MqOuKlCBlcnJvckNvZGUg66Gc66eMIO2MkOygle2VnOuLpCDigJQgc3RhdHVzIOulvCDtlajqu5gg7JqU6rWs7ZWY66m0IHByb3ZpZGVyIOqwgFxuICAgIC8vIOyDge2DnOy9lOuTnOulvCDrsJTqv4Ag65WMIO2MkOygleydtCDsobDsmqntnogg66mO64qU64ukLlxuICAgIGlmIChlcnJvckNvZGUgJiYgUEVSTUFORU5UX0ZBSUxVUkVfQ09ERVMuaGFzKGVycm9yQ29kZSkpIHtcbiAgICAgIGF3YWl0IGRlYWN0aXZhdGVBdXRoRGVhZFRva2VuKFxuICAgICAgICB7IGlkOiB0b2tlbklkLCBuYW1lOiB0b2tlbi5uYW1lLCBwcm92aWRlcjogXCJvcGVuYWlcIiwgY3JlZGVudGlhbHM6IGNyZWRzIH0sXG4gICAgICAgIGBvcGVuYWk6JHtlcnJvckNvZGV9YCxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGBPcGVuQUkgcmVmcmVzaCBmYWlsZWQ6ICR7cmVzcC5zdGF0dXN9ICR7ZXJyb3JDb2RlID8/IFwidW5rbm93blwifWApO1xuICB9XG5cbiAgY29uc3QgZGF0YSA9IHJlZnJlc2hSZXNwb25zZVNjaGVtYS5wYXJzZShhd2FpdCByZXNwLmpzb24oKSk7XG5cbiAgY29uc3QgbmV3UmVmcmVzaFRva2VuID0gZGF0YS5yZWZyZXNoX3Rva2VuID8/IGNyZWRzLnJlZnJlc2hUb2tlbjtcblxuICBjb25zdCByb3RhdGVkID1cbiAgICBkYXRhLnJlZnJlc2hfdG9rZW4gIT09IG51bGwgJiZcbiAgICBkYXRhLnJlZnJlc2hfdG9rZW4gIT09IHVuZGVmaW5lZCAmJlxuICAgIGRhdGEucmVmcmVzaF90b2tlbiAhPT0gY3JlZHMucmVmcmVzaFRva2VuO1xuXG4gIGlmIChyb3RhdGVkKSB7XG4gICAgbG9nZ2VyLmluZm8oYHJlZnJlc2hfdG9rZW4gcm90YXRlZCBmb3IgdG9rZW4gJHt0b2tlbi5uYW1lfWApO1xuICB9XG5cbiAgY29uc3QgdXBkYXRlZENyZWRzOiBPcGVuQUlDcmVkZW50aWFscyA9IHtcbiAgICAuLi5jcmVkcyxcbiAgICBhY2Nlc3NUb2tlbjogZGF0YS5hY2Nlc3NfdG9rZW4sXG4gICAgcmVmcmVzaFRva2VuOiBuZXdSZWZyZXNoVG9rZW4sXG4gICAgYWNjZXNzVG9rZW5FeHBpcmVzQXQ6IGRhdGEuZXhwaXJlc19pblxuICAgICAgPyBEYXRlLm5vdygpICsgZGF0YS5leHBpcmVzX2luICogMTAwMFxuICAgICAgOiBjcmVkcy5hY2Nlc3NUb2tlbkV4cGlyZXNBdCxcbiAgfTtcblxuICBpZiAoZGF0YS5pZF90b2tlbikgdXBkYXRlZENyZWRzLmlkVG9rZW4gPSBkYXRhLmlkX3Rva2VuO1xuXG4gIC8vIO2ajOyghChyb3RhdGVkKeydtCDsnbzslrTrgqzripTrjbAg7J20IHNhdmUg6rCAIOyLpO2MqO2VmOuptCwgT3BlbkFJIOyqvSDsmJsgcmVmcmVzaF90b2tlbiDsnYAg7J2066+4XG4gIC8vIO2PkOq4sOuQnCDsg4Htg5zsl5DshJwgREIg7JeQ64qUIOyYmyDthqDtgbDsnbQg64Ko64qU64ukIOKGkiDri6TsnYwgcmVmcmVzaCDqsIAgcmVmcmVzaF90b2tlbl9yZXVzZWQg66GcXG4gIC8vIOyYgeq1rCDsgqzrp50uIOydtCDqtazqsIQg7Iuk7Yyo64qUIO2GoO2BsCDsgqzrp53snZgg7KeB7KCRIOybkOyduOydtOuvgOuhnCDrsJjrk5zsi5wg7YGs6rKMIOuCqOq4tOuLpC5cbiAgdHJ5IHtcbiAgICBhd2FpdCBUb2tlbk1vZGVsLnNhdmUoW1xuICAgICAge1xuICAgICAgICBpZDogdG9rZW5JZCxcbiAgICAgICAgcHJvdmlkZXI6IFwib3BlbmFpXCIsXG4gICAgICAgIGNyZWRlbnRpYWxzOiB1cGRhdGVkQ3JlZHMsXG4gICAgICAgIG5hbWU6IHRva2VuLm5hbWUsXG4gICAgICAgIHJlYXV0aF9yZXF1aXJlZDogZmFsc2UsXG4gICAgICB9LFxuICAgIF0pO1xuICB9IGNhdGNoIChlKSB7XG4gICAgbG9nZ2VyLmVycm9yKFxuICAgICAgYE9wZW5BSSByZWZyZXNoOiBEQiBzYXZlIEZBSUxFRCBhZnRlciByb3RhdGlvbihyb3RhdGVkPSR7cm90YXRlZH0pIGAgK1xuICAgICAgICBgdG9rZW49JHt0b2tlbi5uYW1lfShpZD0ke3Rva2VuSWR9KSDigJQg7JibIHJlZnJlc2hfdG9rZW4g7Y+Q6riw65CoLCBEQiDrr7jrsJjsmIEg4oaSIO2GoO2BsCDsgqzrp50g7JyE7ZeYLiBlcnI9JHtTdHJpbmcoZSl9YCxcbiAgICApO1xuICAgIHRocm93IGU7XG4gIH1cblxuICBsb2dnZXIuaW5mbyhgdG9rZW4gJHt0b2tlbi5uYW1lfSByZWZyZXNoZWQgc3VjY2Vzc2Z1bGx5IChyb3RhdGVkPSR7cm90YXRlZH0pYCk7XG5cbiAgcmV0dXJuIHtcbiAgICBhY2Nlc3NUb2tlbjogZGF0YS5hY2Nlc3NfdG9rZW4sXG4gICAgY2hhdGdwdEFjY291bnRJZDogY3JlZHMuYWNjb3VudElkLFxuICAgIGNoYXRncHRQbGFuVHlwZTogY3JlZHMucGxhblR5cGUsXG4gIH07XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7OztBQWVBLE1BQU0sU0FBUyxVQUFVLENBQUMsU0FBUyxnQkFBZ0IsQ0FBQztBQUtwRCxNQUFNLDBDQUEwQixJQUFJLElBQUk7Q0FDdEM7Q0FDQTtDQUNBO0FBQ0YsQ0FBQztBQUdELE1BQU0seUJBQXlCLEVBQUUsT0FBTyxDQUFDLENBQUMsTUFBTSxnQkFBZ0I7QUFHaEUsTUFBTSx5QkFBeUIsRUFBRSxZQUFZLEVBQzNDLE9BQU8sRUFDSixNQUFNLENBQ0wsd0JBQ0EsRUFBRSxZQUFZLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQyxDQUFDLENBQUMsV0FBVyxVQUFVLE1BQU0sSUFBSSxDQUNqRixDQUFDLENBQUMsQ0FDRCxTQUFTLEVBQ2QsQ0FBQztBQUVELE1BQU0sd0JBQXdCLEVBQUUsT0FBTztDQUNyQyxjQUFjLEVBQUUsT0FBTztDQUN2QixlQUFlLEVBQUUsT0FBTyxDQUFDLENBQUMsUUFBUTtDQUNsQyxZQUFZLEVBQUUsT0FBTyxDQUFDLENBQUMsUUFBUTtDQUMvQixVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUMsUUFBUTtBQUMvQixDQUFDO0FBR0QsTUFBTSxrQ0FBa0IsSUFBSSxJQUFvQztBQUNoRSxNQUFNLGtDQUFrQixJQUFJLElBQW9CO0FBQ2hELE1BQU0sMEJBQTBCO0FB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
@@ -69,4 +69,4 @@ async function* normalizeOpenAISSE(body) {
69
69
  //#endregion
70
70
  export { normalizeOpenAISSE, parseOpenAISSE };
71
71
 
72
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLXNzZS5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdXRpbHMvcHJvdmlkZXJzL29wZW5haS9vcGVuYWktc3NlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIG5vcm1hbGl6ZU9wZW5BSUV2ZW50LFxuICBPcGVuQUlQcm90b2NvbEVycm9yLFxuICB0eXBlIE9wZW5BSU5vcm1hbGl6ZWRFdmVudCxcbn0gZnJvbSBcIi4vb3BlbmFpLWJhY2tlbmQtcHJvdG9jb2xcIjtcblxuZXhwb3J0IGludGVyZmFjZSBPcGVuQUlFdmVudFN0cmVhbSBleHRlbmRzIEFzeW5jSXRlcmFibGU8T3BlbkFJTm9ybWFsaXplZEV2ZW50PiB7fVxuXG5mdW5jdGlvbiBwYXJzZUJsb2NrKGJsb2NrOiBzdHJpbmcpOiB1bmtub3duIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgZGF0YTogc3RyaW5nW10gPSBbXTtcbiAgZm9yIChjb25zdCBsaW5lIG9mIGJsb2NrLnJlcGxhY2VBbGwoXCJcXHJcXG5cIiwgXCJcXG5cIikucmVwbGFjZUFsbChcIlxcclwiLCBcIlxcblwiKS5zcGxpdChcIlxcblwiKSkge1xuICAgIGlmIChsaW5lLnN0YXJ0c1dpdGgoXCI6XCIpKSBjb250aW51ZTtcbiAgICBjb25zdCBzZXBhcmF0b3IgPSBsaW5lLmluZGV4T2YoXCI6XCIpO1xuICAgIGNvbnN0IGZpZWxkID0gc2VwYXJhdG9yIDwgMCA/IGxpbmUgOiBsaW5lLnNsaWNlKDAsIHNlcGFyYXRvcik7XG4gICAgbGV0IHZhbHVlID0gc2VwYXJhdG9yIDwgMCA/IFwiXCIgOiBsaW5lLnNsaWNlKHNlcGFyYXRvciArIDEpO1xuICAgIGlmICh2YWx1ZS5zdGFydHNXaXRoKFwiIFwiKSkgdmFsdWUgPSB2YWx1ZS5zbGljZSgxKTtcbiAgICBpZiAoZmllbGQgPT09IFwiZGF0YVwiKSBkYXRhLnB1c2godmFsdWUpO1xuICB9XG4gIGlmICghZGF0YS5sZW5ndGgpIHJldHVybiB1bmRlZmluZWQ7XG4gIGNvbnN0IHBheWxvYWQgPSBkYXRhLmpvaW4oXCJcXG5cIik7XG4gIGlmIChwYXlsb2FkID09PSBcIltET05FXVwiKSByZXR1cm4gcGF5bG9hZDtcbiAgdHJ5IHtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShwYXlsb2FkKSBhcyB1bmtub3duO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHRocm93IG5ldyBPcGVuQUlQcm90b2NvbEVycm9yKGBJbnZhbGlkIE9wZW5BSSBTU0UgSlNPTjogJHtTdHJpbmcoZXJyb3IpfWApO1xuICB9XG59XG5cbi8qKiBQYXJzZXMgYXJiaXRyYXJ5IFVURi04L2NodW5rIGJvdW5kYXJpZXMgYW5kIGFsbCBjb21wbGV0ZSBTU0UgZXZlbnQgYmxvY2tzLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uKiBwYXJzZU9wZW5BSVNTRShib2R5OiBSZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5Pik6IEFzeW5jR2VuZXJhdG9yPHVua25vd24+IHtcbiAgY29uc3QgcmVhZGVyID0gYm9keS5nZXRSZWFkZXIoKTtcbiAgY29uc3QgZGVjb2RlciA9IG5ldyBUZXh0RGVjb2RlcigpO1xuICBsZXQgYnVmZmVyID0gXCJcIjtcbiAgdHJ5IHtcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgY29uc3QgeyBkb25lLCB2YWx1ZSB9ID0gYXdhaXQgcmVhZGVyLnJlYWQoKTtcbiAgICAgIGJ1ZmZlciArPSBkZWNvZGVyLmRlY29kZSh2YWx1ZSwgeyBzdHJlYW06ICFkb25lIH0pO1xuICAgICAgbGV0IG1hdGNoOiBSZWdFeHBFeGVjQXJyYXkgfCBudWxsO1xuICAgICAgd2hpbGUgKChtYXRjaCA9IC9cXHJcXG5cXHJcXG58XFxuXFxufFxcclxcci8uZXhlYyhidWZmZXIpKSkge1xuICAgICAgICBjb25zdCBibG9jayA9IGJ1ZmZlci5zbGljZSgwLCBtYXRjaC5pbmRleCk7XG4gICAgICAgIGJ1ZmZlciA9IGJ1ZmZlci5zbGljZShtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aCk7XG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlQmxvY2soYmxvY2spO1xuICAgICAgICBpZiAocGFyc2VkICE9PSB1bmRlZmluZWQpIHlpZWxkIHBhcnNlZDtcbiAgICAgIH1cbiAgICAgIGlmIChkb25lKSBicmVhaztcbiAgICB9XG4gICAgaWYgKGJ1ZmZlci50cmltKCkpIHtcbiAgICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlQmxvY2soYnVmZmVyKTtcbiAgICAgIGlmIChwYXJzZWQgIT09IHVuZGVmaW5lZCkgeWllbGQgcGFyc2VkO1xuICAgIH1cbiAgfSBmaW5hbGx5IHtcbiAgICByZWFkZXIucmVsZWFzZUxvY2soKTtcbiAgfVxufVxuXG4vKiogQ29udmVydHMgd2lyZSBldmVudHMgYW5kIGVuZm9yY2VzIGV4YWN0bHkgb25lIHN1Y2Nlc3NmdWwgdGVybWluYWwgcmVzcG9uc2UuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24qIG5vcm1hbGl6ZU9wZW5BSVNTRShcbiAgYm9keTogUmVhZGFibGVTdHJlYW08VWludDhBcnJheT4sXG4pOiBBc3luY0dlbmVyYXRvcjxPcGVuQUlOb3JtYWxpemVkRXZlbnQ+IHtcbiAgbGV0IHRlcm1pbmFsID0gZmFsc2U7XG4gIGZvciBhd2FpdCAoY29uc3QgcmF3IG9mIHBhcnNlT3BlbkFJU1NFKGJvZHkpKSB7XG4gICAgaWYgKHJhdyA9PT0gXCJbRE9ORV1cIikge1xuICAgICAgaWYgKCF0ZXJtaW5hbCkgdGhyb3cgbmV3IE9wZW5BSVByb3RvY29sRXJyb3IoXCJPcGVuQUkgc3RyZWFtIGVuZGVkIGJlZm9yZSByZXNwb25zZS5jb21wbGV0ZWRcIik7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICh0ZXJtaW5hbCkgdGhyb3cgbmV3IE9wZW5BSVByb3RvY29sRXJyb3IoXCJPcGVuQUkgc3RyZWFtIGVtaXR0ZWQgYW4gZXZlbnQgYWZ0ZXIgdGVybWluYXRpb25cIik7XG4gICAgY29uc3QgZXZlbnQgPSBub3JtYWxpemVPcGVuQUlFdmVudChyYXcpO1xuICAgIGlmICghZXZlbnQpIGNvbnRpbnVlO1xuICAgIGlmIChldmVudC50eXBlID09PSBcImVycm9yXCIpIHtcbiAgICAgIHRlcm1pbmFsID0gdHJ1ZTtcbiAgICAgIHlpZWxkIGV2ZW50O1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoZXZlbnQudHlwZSA9PT0gXCJjb21wbGV0ZWRcIikgdGVybWluYWwgPSB0cnVlO1xuICAgIHlpZWxkIGV2ZW50O1xuICB9XG4gIGlmICghdGVybWluYWwpXG4gICAgdGhyb3cgbmV3IE9wZW5BSVByb3RvY29sRXJyb3IoXCJPcGVuQUkgU1NFIGNvbm5lY3Rpb24gY2xvc2VkIGJlZm9yZSBhIHRlcm1pbmFsIGV2ZW50XCIpO1xufVxuIl0sIm1hcHBpbmdzIjoiOztBQVFBLFNBQVMsV0FBVyxPQUFvQztDQUN0RCxNQUFNLE9BQWlCLENBQUM7Q0FDeEIsS0FBSyxNQUFNLFFBQVEsTUFBTSxXQUFXLFFBQVEsSUFBSSxDQUFDLENBQUMsV0FBVyxNQUFNLElBQUksQ0FBQyxDQUFDLE1BQU0sSUFBSSxHQUFHO0VBQ3BGLElBQUksS0FBSyxXQUFXLEdBQUcsR0FBRztFQUMxQixNQUFNLFlBQVksS0FBSyxRQUFRLEdBQUc7RUFDbEMsTUFBTSxRQUFRLFlBQVksSUFBSSxPQUFPLEtBQUssTUFBTSxHQUFHLFNBQVM7RUFDNUQsSUFBSSxRQUFRLFlBQVksSUFBSSxLQUFLLEtBQUssTUFBTSxZQUFZLENBQUM7RUFDekQsSUFBSSxNQUFNLFdBQVcsR0FBRyxHQUFHLFFBQVEsTUFBTSxNQUFNLENBQUM7RUFDaEQsSUFBSSxVQUFVLFFBQVEsS0FBSyxLQUFLLEtBQUs7Q0FDdkM7Q0FDQSxJQUFJLENBQUMsS0FBSyxRQUFRLE9BQU87Q0FDekIsTUFBTSxVQUFVLEtBQUssS0FBSyxJQUFJO0NBQzlCLElBQUksWUFBWSxVQUFVLE9BQU87Q0FDakMsSUFBSTtFQUNGLE9BQU8sS0FBSyxNQUFNLE9BQU87Q0FDM0IsU0FBUyxPQUFPO0VBQ2QsTUFBTSxJQUFJLG9CQUFvQiw0QkFBNEIsT0FBTyxLQUFLLEdBQUc7Q0FDM0U7QUFDRjs7QUFHQSxnQkFBdUIsZUFBZSxNQUEyRDtDQUMvRixNQUFNLFNBQVMsS0FBSyxVQUFVO0NBQzlCLE1BQU0sVUFBVSxJQUFJLFlBQVk7Q0FDaEMsSUFBSSxTQUFTO0NBQ2IsSUFBSTtFQUNGLE9BQU8sTUFBTTtHQUNYLE1BQU0sRUFBRSxNQUFNLFVBQVUsTUFBTSxPQUFPLEtBQUs7R0FDMUMsVUFBVSxRQUFRLE9BQU8sT0FBTyxFQUFFLFFBQVEsQ0FBQyxLQUFLLENBQUM7R0FDakQsSUFBSTtHQUNKLE9BQVEsUUFBUSxxQkFBcUIsS0FBSyxNQUFNLEdBQUk7SUFDbEQsTUFBTSxRQUFRLE9BQU8sTUFBTSxHQUFHLE1BQU0sS0FBSztJQUN6QyxTQUFTLE9BQU8sTUFBTSxNQUFNLFFBQVEsTUFBTSxFQUFFLENBQUMsTUFBTTtJQUNuRCxNQUFNLFNBQVMsV0FBVyxLQUFLO0lBQy9CLElBQUksV0FBVyxRQUFXLE1BQU07R0FDbEM7R0FDQSxJQUFJLE1BQU07RUFDWjtFQUNBLElBQUksT0FBTyxLQUFLLEdBQUc7R0FDakIsTUFBTSxTQUFTLFdBQVcsTUFBTTtHQUNoQyxJQUFJLFdBQVcsUUFBVyxNQUFNO0VBQ2xDO0NBQ0YsVUFBVTtFQUNSLE9BQU8sWUFBWTtDQUNyQjtBQUNGOztBQUdBLGdCQUF1QixtQkFDckIsTUFDdUM7Q0FDdkMsSUFBSSxXQUFXO0NBQ2YsV0FBVyxNQUFNLE9BQU8sZUFBZSxJQUFJLEdBQUc7RUFDNUMsSUFBSSxRQUFRLFVBQVU7R0FDcEIsSUFBSSxDQUFDLFVBQVUsTUFBTSxJQUFJLG9CQUFvQiwrQ0FBK0M7R0FDNUY7RUFDRjtFQUNBLElBQUksVUFBVSxNQUFNLElBQUksb0JBQW9CLGtEQUFrRDtFQUM5RixNQUFNLFFBQVEscUJBQXFCLEdBQUc7RUFDdEMsSUFBSSxDQUFDLE9BQU87RUFDWixJQUFJLE1BQU0sU0FBUyxTQUFTO0dBQzFCLFdBQVc7R0FDWCxNQUFNO0dBQ047RUFDRjtFQUNBLElBQUksTUFBTSxTQUFTLGFBQWEsV0FBVztFQUMzQyxNQUFNO0NBQ1I7Q0FDQSxJQUFJLENBQUMsVUFDSCxNQUFNLElBQUksb0JBQW9CLHNEQUFzRDtBQUN4RiJ9
72
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLXNzZS5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdXRpbHMvcHJvdmlkZXJzL29wZW5haS9vcGVuYWktc3NlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIHR5cGUgSnNvblZhbHVlLFxuICBub3JtYWxpemVPcGVuQUlFdmVudCxcbiAgT3BlbkFJUHJvdG9jb2xFcnJvcixcbiAgdHlwZSBPcGVuQUlOb3JtYWxpemVkRXZlbnQsXG59IGZyb20gXCIuL29wZW5haS1iYWNrZW5kLXByb3RvY29sXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3BlbkFJRXZlbnRTdHJlYW0gZXh0ZW5kcyBBc3luY0l0ZXJhYmxlPE9wZW5BSU5vcm1hbGl6ZWRFdmVudD4ge31cblxuZnVuY3Rpb24gcGFyc2VCbG9jayhibG9jazogc3RyaW5nKTogSnNvblZhbHVlIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgZGF0YTogc3RyaW5nW10gPSBbXTtcblxuICBmb3IgKGNvbnN0IGxpbmUgb2YgYmxvY2sucmVwbGFjZUFsbChcIlxcclxcblwiLCBcIlxcblwiKS5yZXBsYWNlQWxsKFwiXFxyXCIsIFwiXFxuXCIpLnNwbGl0KFwiXFxuXCIpKSB7XG4gICAgaWYgKGxpbmUuc3RhcnRzV2l0aChcIjpcIikpIGNvbnRpbnVlO1xuICAgIGNvbnN0IHNlcGFyYXRvciA9IGxpbmUuaW5kZXhPZihcIjpcIik7XG4gICAgY29uc3QgZmllbGQgPSBzZXBhcmF0b3IgPCAwID8gbGluZSA6IGxpbmUuc2xpY2UoMCwgc2VwYXJhdG9yKTtcbiAgICBsZXQgdmFsdWUgPSBzZXBhcmF0b3IgPCAwID8gXCJcIiA6IGxpbmUuc2xpY2Uoc2VwYXJhdG9yICsgMSk7XG5cbiAgICBpZiAodmFsdWUuc3RhcnRzV2l0aChcIiBcIikpIHZhbHVlID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBpZiAoZmllbGQgPT09IFwiZGF0YVwiKSBkYXRhLnB1c2godmFsdWUpO1xuICB9XG5cbiAgaWYgKCFkYXRhLmxlbmd0aCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgY29uc3QgcGF5bG9hZCA9IGRhdGEuam9pbihcIlxcblwiKTtcblxuICBpZiAocGF5bG9hZCA9PT0gXCJbRE9ORV1cIikgcmV0dXJuIHBheWxvYWQ7XG5cbiAgdHJ5IHtcbiAgICAvLyBKU09OLnBhcnNlIHdpdGhvdXQgYSByZXZpdmVyIHlpZWxkcyBvbmx5IEpTT04gdmFsdWVzLlxuICAgIGNvbnN0IHBhcnNlZDogSnNvblZhbHVlID0gSlNPTi5wYXJzZShwYXlsb2FkKTtcblxuICAgIHJldHVybiBwYXJzZWQ7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgdGhyb3cgbmV3IE9wZW5BSVByb3RvY29sRXJyb3IoYEludmFsaWQgT3BlbkFJIFNTRSBKU09OOiAke1N0cmluZyhlcnJvcil9YCk7XG4gIH1cbn1cblxuLyoqIFBhcnNlcyBhcmJpdHJhcnkgVVRGLTgvY2h1bmsgYm91bmRhcmllcyBhbmQgYWxsIGNvbXBsZXRlIFNTRSBldmVudCBibG9ja3MuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24qIHBhcnNlT3BlbkFJU1NFKGJvZHk6IFJlYWRhYmxlU3RyZWFtPFVpbnQ4QXJyYXk+KTogQXN5bmNHZW5lcmF0b3I8SnNvblZhbHVlPiB7XG4gIGNvbnN0IHJlYWRlciA9IGJvZHkuZ2V0UmVhZGVyKCk7XG4gIGNvbnN0IGRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoKTtcbiAgbGV0IGJ1ZmZlciA9IFwiXCI7XG5cbiAgdHJ5IHtcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgY29uc3QgeyBkb25lLCB2YWx1ZSB9ID0gYXdhaXQgcmVhZGVyLnJlYWQoKTtcbiAgICAgIGJ1ZmZlciArPSBkZWNvZGVyLmRlY29kZSh2YWx1ZSwgeyBzdHJlYW06ICFkb25lIH0pO1xuICAgICAgbGV0IG1hdGNoOiBSZWdFeHBFeGVjQXJyYXkgfCBudWxsO1xuXG4gICAgICB3aGlsZSAoKG1hdGNoID0gL1xcclxcblxcclxcbnxcXG5cXG58XFxyXFxyLy5leGVjKGJ1ZmZlcikpKSB7XG4gICAgICAgIGNvbnN0IGJsb2NrID0gYnVmZmVyLnNsaWNlKDAsIG1hdGNoLmluZGV4KTtcbiAgICAgICAgYnVmZmVyID0gYnVmZmVyLnNsaWNlKG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoKTtcbiAgICAgICAgY29uc3QgcGFyc2VkID0gcGFyc2VCbG9jayhibG9jayk7XG5cbiAgICAgICAgaWYgKHBhcnNlZCAhPT0gdW5kZWZpbmVkKSB5aWVsZCBwYXJzZWQ7XG4gICAgICB9XG5cbiAgICAgIGlmIChkb25lKSBicmVhaztcbiAgICB9XG5cbiAgICBpZiAoYnVmZmVyLnRyaW0oKSkge1xuICAgICAgY29uc3QgcGFyc2VkID0gcGFyc2VCbG9jayhidWZmZXIpO1xuXG4gICAgICBpZiAocGFyc2VkICE9PSB1bmRlZmluZWQpIHlpZWxkIHBhcnNlZDtcbiAgICB9XG4gIH0gZmluYWxseSB7XG4gICAgcmVhZGVyLnJlbGVhc2VMb2NrKCk7XG4gIH1cbn1cblxuLyoqIENvbnZlcnRzIHdpcmUgZXZlbnRzIGFuZCBlbmZvcmNlcyBleGFjdGx5IG9uZSBzdWNjZXNzZnVsIHRlcm1pbmFsIHJlc3BvbnNlLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uKiBub3JtYWxpemVPcGVuQUlTU0UoXG4gIGJvZHk6IFJlYWRhYmxlU3RyZWFtPFVpbnQ4QXJyYXk+LFxuKTogQXN5bmNHZW5lcmF0b3I8T3BlbkFJTm9ybWFsaXplZEV2ZW50PiB7XG4gIGxldCB0ZXJtaW5hbCA9IGZhbHNlO1xuXG4gIGZvciBhd2FpdCAoY29uc3QgcmF3IG9mIHBhcnNlT3BlbkFJU1NFKGJvZHkpKSB7XG4gICAgaWYgKHJhdyA9PT0gXCJbRE9ORV1cIikge1xuICAgICAgaWYgKCF0ZXJtaW5hbCkgdGhyb3cgbmV3IE9wZW5BSVByb3RvY29sRXJyb3IoXCJPcGVuQUkgc3RyZWFtIGVuZGVkIGJlZm9yZSByZXNwb25zZS5jb21wbGV0ZWRcIik7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGVybWluYWwpIHRocm93IG5ldyBPcGVuQUlQcm90b2NvbEVycm9yKFwiT3BlbkFJIHN0cmVhbSBlbWl0dGVkIGFuIGV2ZW50IGFmdGVyIHRlcm1pbmF0aW9uXCIpO1xuICAgIGNvbnN0IGV2ZW50ID0gbm9ybWFsaXplT3BlbkFJRXZlbnQocmF3KTtcblxuICAgIGlmICghZXZlbnQpIGNvbnRpbnVlO1xuXG4gICAgaWYgKGV2ZW50LnR5cGUgPT09IFwiZXJyb3JcIikge1xuICAgICAgdGVybWluYWwgPSB0cnVlO1xuICAgICAgeWllbGQgZXZlbnQ7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoZXZlbnQudHlwZSA9PT0gXCJjb21wbGV0ZWRcIikgdGVybWluYWwgPSB0cnVlO1xuICAgIHlpZWxkIGV2ZW50O1xuICB9XG5cbiAgaWYgKCF0ZXJtaW5hbClcbiAgICB0aHJvdyBuZXcgT3BlbkFJUHJvdG9jb2xFcnJvcihcIk9wZW5BSSBTU0UgY29ubmVjdGlvbiBjbG9zZWQgYmVmb3JlIGEgdGVybWluYWwgZXZlbnRcIik7XG59XG4iXSwibWFwcGluZ3MiOiI7O0FBU0EsU0FBUyxXQUFXLE9BQXNDO0NBQ3hELE1BQU0sT0FBaUIsQ0FBQztDQUV4QixLQUFLLE1BQU0sUUFBUSxNQUFNLFdBQVcsUUFBUSxJQUFJLENBQUMsQ0FBQyxXQUFXLE1BQU0sSUFBSSxDQUFDLENBQUMsTUFBTSxJQUFJLEdBQUc7RUFDcEYsSUFBSSxLQUFLLFdBQVcsR0FBRyxHQUFHO0VBQzFCLE1BQU0sWUFBWSxLQUFLLFFBQVEsR0FBRztFQUNsQyxNQUFNLFFBQVEsWUFBWSxJQUFJLE9BQU8sS0FBSyxNQUFNLEdBQUcsU0FBUztFQUM1RCxJQUFJLFFBQVEsWUFBWSxJQUFJLEtBQUssS0FBSyxNQUFNLFlBQVksQ0FBQztFQUV6RCxJQUFJLE1BQU0sV0FBVyxHQUFHLEdBQUcsUUFBUSxNQUFNLE1BQU0sQ0FBQztFQUVoRCxJQUFJLFVBQVUsUUFBUSxLQUFLLEtBQUssS0FBSztDQUN2QztDQUVBLElBQUksQ0FBQyxLQUFLLFFBQVEsT0FBTztDQUN6QixNQUFNLFVBQVUsS0FBSyxLQUFLLElBQUk7Q0FFOUIsSUFBSSxZQUFZLFVBQVUsT0FBTztDQUVqQyxJQUFJO0VBSUYsT0FGMEIsS0FBSyxNQUFNLE9BRTlCO0NBQ1QsU0FBUyxPQUFPO0VBQ2QsTUFBTSxJQUFJLG9CQUFvQiw0QkFBNEIsT0FBTyxLQUFLLEdBQUc7Q0FDM0U7QUFDRjs7QUFHQSxnQkFBdUIsZUFBZSxNQUE2RDtDQUNqRyxNQUFNLFNBQVMsS0FBSyxVQUFVO0NBQzlCLE1BQU0sVUFBVSxJQUFJLFlBQVk7Q0FDaEMsSUFBSSxTQUFTO0NBRWIsSUFBSTtFQUNGLE9BQU8sTUFBTTtHQUNYLE1BQU0sRUFBRSxNQUFNLFVBQVUsTUFBTSxPQUFPLEtBQUs7R0FDMUMsVUFBVSxRQUFRLE9BQU8sT0FBTyxFQUFFLFFBQVEsQ0FBQyxLQUFLLENBQUM7R0FDakQsSUFBSTtHQUVKLE9BQVEsUUFBUSxxQkFBcUIsS0FBSyxNQUFNLEdBQUk7SUFDbEQsTUFBTSxRQUFRLE9BQU8sTUFBTSxHQUFHLE1BQU0sS0FBSztJQUN6QyxTQUFTLE9BQU8sTUFBTSxNQUFNLFFBQVEsTUFBTSxFQUFFLENBQUMsTUFBTTtJQUNuRCxNQUFNLFNBQVMsV0FBVyxLQUFLO0lBRS9CLElBQUksV0FBVyxRQUFXLE1BQU07R0FDbEM7R0FFQSxJQUFJLE1BQU07RUFDWjtFQUVBLElBQUksT0FBTyxLQUFLLEdBQUc7R0FDakIsTUFBTSxTQUFTLFdBQVcsTUFBTTtHQUVoQyxJQUFJLFdBQVcsUUFBVyxNQUFNO0VBQ2xDO0NBQ0YsVUFBVTtFQUNSLE9BQU8sWUFBWTtDQUNyQjtBQUNGOztBQUdBLGdCQUF1QixtQkFDckIsTUFDdUM7Q0FDdkMsSUFBSSxXQUFXO0NBRWYsV0FBVyxNQUFNLE9BQU8sZUFBZSxJQUFJLEdBQUc7RUFDNUMsSUFBSSxRQUFRLFVBQVU7R0FDcEIsSUFBSSxDQUFDLFVBQVUsTUFBTSxJQUFJLG9CQUFvQiwrQ0FBK0M7R0FFNUY7RUFDRjtFQUVBLElBQUksVUFBVSxNQUFNLElBQUksb0JBQW9CLGtEQUFrRDtFQUM5RixNQUFNLFFBQVEscUJBQXFCLEdBQUc7RUFFdEMsSUFBSSxDQUFDLE9BQU87RUFFWixJQUFJLE1BQU0sU0FBUyxTQUFTO0dBQzFCLFdBQVc7R0FDWCxNQUFNO0dBRU47RUFDRjtFQUVBLElBQUksTUFBTSxTQUFTLGFBQWEsV0FBVztFQUMzQyxNQUFNO0NBQ1I7Q0FFQSxJQUFJLENBQUMsVUFDSCxNQUFNLElBQUksb0JBQW9CLHNEQUFzRDtBQUN4RiJ9
@@ -11,4 +11,4 @@ function resolveOpenAITransportKind(env = process.env) {
11
11
  //#endregion
12
12
  export { resolveOpenAITransportKind };
13
13
 
14
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLXRyYW5zcG9ydC1jb25maWcuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9vcGVuYWkvb3BlbmFpLXRyYW5zcG9ydC1jb25maWcudHMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHR5cGUgT3BlbkFJVHJhbnNwb3J0S2luZCA9IFwiaHR0cHNcIiB8IFwid2Vic29ja2V0XCI7XG5cbi8qKlxuICogT3BlbkFJIOyghOyGoSDrsKnsi50g7ISg7YOdLiDrj5nsi5zshLEga25vYiDsnYAg7JeG64ukIOKAlCBkaXJlY3Qg7KCE7ZmY7Jy866GcIOyalOyyreydgCBBbnRocm9waWMg6rO8XG4gKiDrj5nsnbztlZjqsowg7IOB7ZWcIOyXhuydtCDrgpjqsIDrqbAsIOyDgeulmCDsoJztlZzsnYAg67Cx7JeU65OcIOydkeuLteydtCDsp4Tsi6TsnbTri6QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlT3BlbkFJVHJhbnNwb3J0S2luZChcbiAgZW52OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCB1bmRlZmluZWQ+ID0gcHJvY2Vzcy5lbnYsXG4pOiBPcGVuQUlUcmFuc3BvcnRLaW5kIHtcbiAgY29uc3QgdHJhbnNwb3J0ID0gZW52LlFHUklEX09QRU5BSV9UUkFOU1BPUlQgPz8gXCJ3ZWJzb2NrZXRcIjtcbiAgaWYgKHRyYW5zcG9ydCAhPT0gXCJodHRwc1wiICYmIHRyYW5zcG9ydCAhPT0gXCJ3ZWJzb2NrZXRcIikge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBJbnZhbGlkIFFHUklEX09QRU5BSV9UUkFOU1BPUlQgdmFsdWU6ICR7dHJhbnNwb3J0fS4gRXhwZWN0ZWQgaHR0cHMgb3Igd2Vic29ja2V0LmAsXG4gICAgKTtcbiAgfVxuICByZXR1cm4gdHJhbnNwb3J0O1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7OztBQU1BLFNBQWdCLDJCQUNkLE1BQTBDLFFBQVEsS0FDN0I7Q0FDckIsTUFBTSxZQUFZLElBQUksMEJBQTBCO0NBQ2hELElBQUksY0FBYyxXQUFXLGNBQWMsYUFDekMsTUFBTSxJQUFJLE1BQ1IseUNBQXlDLFVBQVUsK0JBQ3JEO0NBRUYsT0FBTztBQUNUIn0=
14
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLXRyYW5zcG9ydC1jb25maWcuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb3ZpZGVycy9vcGVuYWkvb3BlbmFpLXRyYW5zcG9ydC1jb25maWcudHMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHR5cGUgT3BlbkFJVHJhbnNwb3J0S2luZCA9IFwiaHR0cHNcIiB8IFwid2Vic29ja2V0XCI7XG5cbi8qKlxuICogT3BlbkFJIOyghOyGoSDrsKnsi50g7ISg7YOdLiDrj5nsi5zshLEga25vYiDsnYAg7JeG64ukIOKAlCBkaXJlY3Qg7KCE7ZmY7Jy866GcIOyalOyyreydgCBBbnRocm9waWMg6rO8XG4gKiDrj5nsnbztlZjqsowg7IOB7ZWcIOyXhuydtCDrgpjqsIDrqbAsIOyDgeulmCDsoJztlZzsnYAg67Cx7JeU65OcIOydkeuLteydtCDsp4Tsi6TsnbTri6QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlT3BlbkFJVHJhbnNwb3J0S2luZChcbiAgZW52OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCB1bmRlZmluZWQ+ID0gcHJvY2Vzcy5lbnYsXG4pOiBPcGVuQUlUcmFuc3BvcnRLaW5kIHtcbiAgY29uc3QgdHJhbnNwb3J0ID0gZW52LlFHUklEX09QRU5BSV9UUkFOU1BPUlQgPz8gXCJ3ZWJzb2NrZXRcIjtcblxuICBpZiAodHJhbnNwb3J0ICE9PSBcImh0dHBzXCIgJiYgdHJhbnNwb3J0ICE9PSBcIndlYnNvY2tldFwiKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYEludmFsaWQgUUdSSURfT1BFTkFJX1RSQU5TUE9SVCB2YWx1ZTogJHt0cmFuc3BvcnR9LiBFeHBlY3RlZCBodHRwcyBvciB3ZWJzb2NrZXQuYCxcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIHRyYW5zcG9ydDtcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFNQSxTQUFnQiwyQkFDZCxNQUEwQyxRQUFRLEtBQzdCO0NBQ3JCLE1BQU0sWUFBWSxJQUFJLDBCQUEwQjtDQUVoRCxJQUFJLGNBQWMsV0FBVyxjQUFjLGFBQ3pDLE1BQU0sSUFBSSxNQUNSLHlDQUF5QyxVQUFVLCtCQUNyRDtDQUdGLE9BQU87QUFDVCJ9
@@ -44,4 +44,4 @@ function isQuietHours(at, readSetting) {
44
44
  //#endregion
45
45
  export { DEFAULT_QUIET_FROM_HOUR, DEFAULT_QUIET_UNTIL_HOUR, isQuietHours };
46
46
 
47
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVpZXQtaG91cnMuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3F1aWV0LWhvdXJzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogU2xhY2sg7JWM66a8IOyhsOyaqSDsi5zqsIQuXG4gKlxuICog7Yag7YGwIOunjOujjOuKlCDsgqzrnozsnbQg7J6s66Gc6re47J247ZW07JW8IO2SgOumrOuKlOuNsCwg6re4IOyCrOuejOydtCDsnpDqsbDrgpgg7Ims64qUIOuPmeyViCDslYzroKTrj4Qg7ZWgIOyImCDsnojripRcbiAqIOydvOydtCDsl4bri6QuIOyXheustCDsi5zqsITsl5Drp4wg7JWM66as6rOgIOuCmOuouOyngOuKlCDri6TsnYwg6re866y0IOyLnOqwhOycvOuhnCDrr7jro6zri6Qg4oCUIOunjOujjCDslYzrprzsnYBcbiAqIOyjvOq4sOyggeycvOuhnCDrsJjrs7XrkJjrr4DroZwg7KGw7JqpIOyLnOqwhOyXkCDrsoTroKTrj4Qg7JWE7LmoIOyyqyDso7zquLDsl5Ag64uk7IucIOyYqOuLpC5cbiAqXG4gKiDri6Trp4wgcHJvdmlkZXIg7J2YIOuniOyngOuniSDthqDtgbDsnbQg7KO964qUIOqyg+ydgCDshJzruYTsiqQg7KCV7KeAIOyLoO2YuOudvCDsnbQg6rec7LmZ7JeQ7IScIOygnOyZuO2VnOuLpFxuICogKO2YuOy2nOu2gOqwgCBgdXJnZW50OiB0cnVlYCDroZwg67O064K066m0IOuQnOuLpCkuXG4gKi9cbmltcG9ydCB7IHR5cGUgZ2V0U2V0dGluZyB9IGZyb20gXCIuLi9hcHBsaWNhdGlvbi9zZXR0aW5nL3NldHRpbmcuc3RvcmVcIjtcblxuLyoqXG4gKiDshKTsoJUg7KGw7ZqMIO2VqOyImOydmCDtmJXtg5zrp4wg67mM66aw64ukIOKAlCBgdHlwZWAgaW1wb3J0IOudvCDrn7Dtg4DsnoQg7J2Y7KG07J20IOyDneq4sOyngCDslYrripTri6QuXG4gKlxuICog6rCSIOyekOyytOuKlCDtla3sg4Eg7Zi47Lac67aAKGBzbGFjay1ub3RpZnlgKeqwgCDrhJjquLTri6QuIOyXrOq4sOyEnCBgZ2V0U2V0dGluZ2Ag7J2EIOyLpOygnOuhnCBpbXBvcnQg7ZWY66m0XG4gKiBgc2V0dGluZy5zdG9yZSDihpIgc2V0dGluZy5tb2RlbCDihpIgdG9rZW4ubW9kZWxgIOydtCDrlLjroKTsmYAsIGB0b2tlbi5tb2RlbGAg7J2EIG1vY2sg7ZWY64qUXG4gKiDthYzsiqTtirjrk6TsnbQg7Iuk7KCcIOuqqOuTiOydhCDrqLzsoIAg66Gc65Oc7ZW0IOuyhOumsOuLpC4g7KGw7JqpIOyLnOqwhCDtjJDsoJXsnYAg7Iuc6rCBIOqzhOyCsOydtOyngCDshKTsoJUg7KGw7ZqM6rCAXG4gKiDslYTri4jrr4DroZwsIOydveuKlCDssYXsnoTsnYAg7J2066+4IOyEpOygleydhCDsnb3qs6Ag7J6I64qUIO2YuOy2nOu2gOyXkCDrkZTri6QuXG4gKi9cbnR5cGUgUmVhZFNldHRpbmcgPSB0eXBlb2YgZ2V0U2V0dGluZztcblxuLyoqIGBzZXR0aW5nLmNvbnN0YW50LnRzYCDsnZgg65GQIGZhbGxiYWNrIOqzvCDqsJnslYTslbwg7ZWc64ukLiDsnbzsuZgg7Jes67aA64qUIO2FjOyKpO2KuOqwgCDsp4Dtgqjri6QuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9RVUlFVF9GUk9NX0hPVVIgPSAyMDtcbmV4cG9ydCBjb25zdCBERUZBVUxUX1FVSUVUX1VOVElMX0hPVVIgPSA4O1xuXG4vKipcbiAqIOyEnOuyhOqwgCBVVEMg66GcIOuPjOyVhOuPhCDtlZzqta0g7Iuc6rCE7Jy866GcIO2MkOygle2VnOuLpC4gZGV2MCDripQgVVRDIOydtOuvgOuhnCBgZ2V0SG91cnMoKWAg66W8IOq3uOuMgOuhnFxuICog7JOw66m0IFwi7KCA64WBIDjsi5xcIuqwgCDtlZzqta0g7Iuc6rCEIOyDiOuyvSA17Iuc6rCAIOuQnOuLpC5cbiAqL1xuY29uc3QgU0VPVUxfRk9STUFUVEVSID0gbmV3IEludGwuRGF0ZVRpbWVGb3JtYXQoXCJlbi1VU1wiLCB7XG4gIHRpbWVab25lOiBcIkFzaWEvU2VvdWxcIixcbiAgaG91cjogXCJudW1lcmljXCIsXG4gIGhvdXIxMjogZmFsc2UsXG4gIHdlZWtkYXk6IFwic2hvcnRcIixcbn0pO1xuXG5mdW5jdGlvbiBzZW91bFBhcnRzKGF0OiBEYXRlKTogeyBob3VyOiBudW1iZXI7IHdlZWtkYXk6IHN0cmluZyB9IHtcbiAgY29uc3QgcGFydHMgPSBTRU9VTF9GT1JNQVRURVIuZm9ybWF0VG9QYXJ0cyhhdCk7XG4gIGNvbnN0IGhvdXIgPSBOdW1iZXIocGFydHMuZmluZCgocCkgPT4gcC50eXBlID09PSBcImhvdXJcIik/LnZhbHVlID8/IFwiMFwiKTtcbiAgY29uc3Qgd2Vla2RheSA9IHBhcnRzLmZpbmQoKHApID0+IHAudHlwZSA9PT0gXCJ3ZWVrZGF5XCIpPy52YWx1ZSA/PyBcIlwiO1xuICAvLyBJbnRsIOydgCDsnpDsoJXsnYQgMjQg66GcIOykhCDsiJgg7J6I64ukLiAwLi4yMyDsnLzroZwg66ee7LaY64ukLlxuICByZXR1cm4geyBob3VyOiBob3VyICUgMjQsIHdlZWtkYXkgfTtcbn1cblxuLyoqIDAuLjIzIOuylOychOulvCDrspfslrTrgpjqsbDrgpgg7Iir7J6Q6rCAIOyVhOuLiOuptCDquLDrs7jqsJLsnLzroZwg65ao7Ja07KeE64ukLiAqL1xuZnVuY3Rpb24gYm91bmRlZEhvdXIocmF3OiBzdHJpbmcgfCB1bmRlZmluZWQsIGZhbGxiYWNrOiBudW1iZXIpOiBudW1iZXIge1xuICBjb25zdCBwYXJzZWQgPSBOdW1iZXIocmF3KTtcbiAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKHBhcnNlZCkgfHwgcGFyc2VkIDwgMCB8fCBwYXJzZWQgPiAyMykgcmV0dXJuIGZhbGxiYWNrO1xuICByZXR1cm4gcGFyc2VkO1xufVxuXG4vKipcbiAqIOyhsOyaqSDsi5zqsITsnbjsp4Ag7YyQ7KCV7ZWc64ukLlxuICpcbiAqIOyLnOyekSA+IOyiheujjOuptCDsnpDsoJXsnYQg64SY64qUIOq1rOqwhCgyMOyLnH7snbXsnbwgOOyLnCksIOyLnOyekSA8IOyiheujjOuptCDqsJnsnYAg64KgIOq1rOqwhCgw7Iucfjjsi5zsspjrn7wpXG4gKiDsnLzroZwg7J2964qU64ukLiDslbzqsIQg6re866y07LKY65+8IOuCruyXkCDsobDsmqntlZjqs6Ag7Iu27J2AIO2MgOuPhCDsnojslrQg65Kk7KeR7Z6MIOqwkuydhCDrp4nsp4Ag7JWK64qU64ukLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNRdWlldEhvdXJzKGF0OiBEYXRlLCByZWFkU2V0dGluZzogUmVhZFNldHRpbmcpOiBib29sZWFuIHtcbiAgY29uc3QgeyBob3VyLCB3ZWVrZGF5IH0gPSBzZW91bFBhcnRzKGF0KTtcblxuICBjb25zdCBpc1dlZWtlbmQgPSB3ZWVrZGF5ID09PSBcIlNhdFwiIHx8IHdlZWtkYXkgPT09IFwiU3VuXCI7XG4gIGlmIChpc1dlZWtlbmQgJiYgcmVhZFNldHRpbmcoXCJzbGFjay5ub3RpZnlPbldlZWtlbmRzXCIsIFwiU0xBQ0tfTk9USUZZX09OX1dFRUtFTkRTXCIpICE9PSBcInRydWVcIikge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgY29uc3QgZnJvbSA9IGJvdW5kZWRIb3VyKFxuICAgIHJlYWRTZXR0aW5nKFwic2xhY2sucXVpZXRGcm9tSG91clwiLCBcIlNMQUNLX1FVSUVUX0ZST01fSE9VUlwiKSxcbiAgICBERUZBVUxUX1FVSUVUX0ZST01fSE9VUixcbiAgKTtcbiAgY29uc3QgdW50aWwgPSBib3VuZGVkSG91cihcbiAgICByZWFkU2V0dGluZyhcInNsYWNrLnF1aWV0VW50aWxIb3VyXCIsIFwiU0xBQ0tfUVVJRVRfVU5USUxfSE9VUlwiKSxcbiAgICBERUZBVUxUX1FVSUVUX1VOVElMX0hPVVIsXG4gICk7XG5cbiAgLy8g7Iuc7J6R6rO8IOyiheujjOqwgCDqsJnsnLzrqbQg6rWs6rCE7J20IOu5hOyWtCDsnojri6TripQg65y77Jy866GcIOydveyWtCDsobDsmqkg7Iuc6rCE7J2EIOuRkOyngCDslYrripTri6QuXG4gIGlmIChmcm9tID09PSB1bnRpbCkgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gZnJvbSA+IHVudGlsID8gaG91ciA+PSBmcm9tIHx8IGhvdXIgPCB1bnRpbCA6IGhvdXIgPj0gZnJvbSAmJiBob3VyIDwgdW50aWw7XG59XG4iXSwibWFwcGluZ3MiOiI7O0FBdUJBLE1BQWEsMEJBQTBCO0FBQ3ZDLE1BQWEsMkJBQTJCOzs7OztBQU14QyxNQUFNLGtCQUFrQixJQUFJLEtBQUssZUFBZSxTQUFTO0NBQ3ZELFVBQVU7Q0FDVixNQUFNO0NBQ04sUUFBUTtDQUNSLFNBQVM7QUFDWCxDQUFDO0FBRUQsU0FBUyxXQUFXLElBQTZDO0NBQy9ELE1BQU0sUUFBUSxnQkFBZ0IsY0FBYyxFQUFFO0NBQzlDLE1BQU0sT0FBTyxPQUFPLE1BQU0sTUFBTSxNQUFNLEVBQUUsU0FBUyxNQUFNLENBQUMsRUFBRSxTQUFTLEdBQUc7Q0FDdEUsTUFBTSxVQUFVLE1BQU0sTUFBTSxNQUFNLEVBQUUsU0FBUyxTQUFTLENBQUMsRUFBRSxTQUFTO0NBRWxFLE9BQU87RUFBRSxNQUFNLE9BQU87RUFBSTtDQUFRO0FBQ3BDOztBQUdBLFNBQVMsWUFBWSxLQUF5QixVQUEwQjtDQUN0RSxNQUFNLFNBQVMsT0FBTyxHQUFHO0NBQ3pCLElBQUksQ0FBQyxPQUFPLFVBQVUsTUFBTSxLQUFLLFNBQVMsS0FBSyxTQUFTLElBQUksT0FBTztDQUNuRSxPQUFPO0FBQ1Q7Ozs7Ozs7QUFRQSxTQUFnQixhQUFhLElBQVUsYUFBbUM7Q0FDeEUsTUFBTSxFQUFFLE1BQU0sWUFBWSxXQUFXLEVBQUU7Q0FHdkMsS0FEa0IsWUFBWSxTQUFTLFlBQVksVUFDbEMsWUFBWSwwQkFBMEIsMEJBQTBCLE1BQU0sUUFDckYsT0FBTztDQUdULE1BQU0sT0FBTyxZQUNYLFlBQVksdUJBQXVCLHVCQUF1QixHQUFBLEVBRTVEO0NBQ0EsTUFBTSxRQUFRLFlBQ1osWUFBWSx3QkFBd0Isd0JBQXdCLEdBQUEsQ0FFOUQ7Q0FHQSxJQUFJLFNBQVMsT0FBTyxPQUFPO0NBQzNCLE9BQU8sT0FBTyxRQUFRLFFBQVEsUUFBUSxPQUFPLFFBQVEsUUFBUSxRQUFRLE9BQU87QUFDOUUifQ==
47
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVpZXQtaG91cnMuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3F1aWV0LWhvdXJzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogU2xhY2sg7JWM66a8IOyhsOyaqSDsi5zqsIQuXG4gKlxuICog7Yag7YGwIOunjOujjOuKlCDsgqzrnozsnbQg7J6s66Gc6re47J247ZW07JW8IO2SgOumrOuKlOuNsCwg6re4IOyCrOuejOydtCDsnpDqsbDrgpgg7Ims64qUIOuPmeyViCDslYzroKTrj4Qg7ZWgIOyImCDsnojripRcbiAqIOydvOydtCDsl4bri6QuIOyXheustCDsi5zqsITsl5Drp4wg7JWM66as6rOgIOuCmOuouOyngOuKlCDri6TsnYwg6re866y0IOyLnOqwhOycvOuhnCDrr7jro6zri6Qg4oCUIOunjOujjCDslYzrprzsnYBcbiAqIOyjvOq4sOyggeycvOuhnCDrsJjrs7XrkJjrr4DroZwg7KGw7JqpIOyLnOqwhOyXkCDrsoTroKTrj4Qg7JWE7LmoIOyyqyDso7zquLDsl5Ag64uk7IucIOyYqOuLpC5cbiAqXG4gKiDri6Trp4wgcHJvdmlkZXIg7J2YIOuniOyngOuniSDthqDtgbDsnbQg7KO964qUIOqyg+ydgCDshJzruYTsiqQg7KCV7KeAIOyLoO2YuOudvCDsnbQg6rec7LmZ7JeQ7IScIOygnOyZuO2VnOuLpFxuICogKO2YuOy2nOu2gOqwgCBgdXJnZW50OiB0cnVlYCDroZwg67O064K066m0IOuQnOuLpCkuXG4gKi9cbmltcG9ydCB7IHR5cGUgZ2V0U2V0dGluZyB9IGZyb20gXCIuLi9hcHBsaWNhdGlvbi9zZXR0aW5nL3NldHRpbmcuc3RvcmVcIjtcblxuLyoqXG4gKiDshKTsoJUg7KGw7ZqMIO2VqOyImOydmCDtmJXtg5zrp4wg67mM66aw64ukIOKAlCBgdHlwZWAgaW1wb3J0IOudvCDrn7Dtg4DsnoQg7J2Y7KG07J20IOyDneq4sOyngCDslYrripTri6QuXG4gKlxuICog6rCSIOyekOyytOuKlCDtla3sg4Eg7Zi47Lac67aAKGBzbGFjay1ub3RpZnlgKeqwgCDrhJjquLTri6QuIOyXrOq4sOyEnCBgZ2V0U2V0dGluZ2Ag7J2EIOyLpOygnOuhnCBpbXBvcnQg7ZWY66m0XG4gKiBgc2V0dGluZy5zdG9yZSDihpIgc2V0dGluZy5tb2RlbCDihpIgdG9rZW4ubW9kZWxgIOydtCDrlLjroKTsmYAsIGB0b2tlbi5tb2RlbGAg7J2EIG1vY2sg7ZWY64qUXG4gKiDthYzsiqTtirjrk6TsnbQg7Iuk7KCcIOuqqOuTiOydhCDrqLzsoIAg66Gc65Oc7ZW0IOuyhOumsOuLpC4g7KGw7JqpIOyLnOqwhCDtjJDsoJXsnYAg7Iuc6rCBIOqzhOyCsOydtOyngCDshKTsoJUg7KGw7ZqM6rCAXG4gKiDslYTri4jrr4DroZwsIOydveuKlCDssYXsnoTsnYAg7J2066+4IOyEpOygleydhCDsnb3qs6Ag7J6I64qUIO2YuOy2nOu2gOyXkCDrkZTri6QuXG4gKi9cbnR5cGUgUmVhZFNldHRpbmcgPSB0eXBlb2YgZ2V0U2V0dGluZztcblxuLyoqIGBzZXR0aW5nLmNvbnN0YW50LnRzYCDsnZgg65GQIGZhbGxiYWNrIOqzvCDqsJnslYTslbwg7ZWc64ukLiDsnbzsuZgg7Jes67aA64qUIO2FjOyKpO2KuOqwgCDsp4Dtgqjri6QuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9RVUlFVF9GUk9NX0hPVVIgPSAyMDtcbmV4cG9ydCBjb25zdCBERUZBVUxUX1FVSUVUX1VOVElMX0hPVVIgPSA4O1xuXG4vKipcbiAqIOyEnOuyhOqwgCBVVEMg66GcIOuPjOyVhOuPhCDtlZzqta0g7Iuc6rCE7Jy866GcIO2MkOygle2VnOuLpC4gZGV2MCDripQgVVRDIOydtOuvgOuhnCBgZ2V0SG91cnMoKWAg66W8IOq3uOuMgOuhnFxuICog7JOw66m0IFwi7KCA64WBIDjsi5xcIuqwgCDtlZzqta0g7Iuc6rCEIOyDiOuyvSA17Iuc6rCAIOuQnOuLpC5cbiAqL1xuY29uc3QgU0VPVUxfRk9STUFUVEVSID0gbmV3IEludGwuRGF0ZVRpbWVGb3JtYXQoXCJlbi1VU1wiLCB7XG4gIHRpbWVab25lOiBcIkFzaWEvU2VvdWxcIixcbiAgaG91cjogXCJudW1lcmljXCIsXG4gIGhvdXIxMjogZmFsc2UsXG4gIHdlZWtkYXk6IFwic2hvcnRcIixcbn0pO1xuXG5pbnRlcmZhY2UgU2VvdWxUaW1lUGFydHMge1xuICBob3VyOiBudW1iZXI7XG4gIHdlZWtkYXk6IHN0cmluZztcbn1cblxuZnVuY3Rpb24gc2VvdWxQYXJ0cyhhdDogRGF0ZSk6IFNlb3VsVGltZVBhcnRzIHtcbiAgY29uc3QgcGFydHMgPSBTRU9VTF9GT1JNQVRURVIuZm9ybWF0VG9QYXJ0cyhhdCk7XG4gIGNvbnN0IGhvdXIgPSBOdW1iZXIocGFydHMuZmluZCgocCkgPT4gcC50eXBlID09PSBcImhvdXJcIik/LnZhbHVlID8/IFwiMFwiKTtcbiAgY29uc3Qgd2Vla2RheSA9IHBhcnRzLmZpbmQoKHApID0+IHAudHlwZSA9PT0gXCJ3ZWVrZGF5XCIpPy52YWx1ZSA/PyBcIlwiO1xuXG4gIC8vIEludGwg7J2AIOyekOygleydhCAyNCDroZwg7KSEIOyImCDsnojri6QuIDAuLjIzIOycvOuhnCDrp57stpjri6QuXG4gIHJldHVybiB7IGhvdXI6IGhvdXIgJSAyNCwgd2Vla2RheSB9O1xufVxuXG4vKiogMC4uMjMg67KU7JyE66W8IOuyl+yWtOuCmOqxsOuCmCDsiKvsnpDqsIAg7JWE64uI66m0IOq4sOuzuOqwkuycvOuhnCDrlqjslrTsp4Tri6QuICovXG5mdW5jdGlvbiBib3VuZGVkSG91cihyYXc6IHN0cmluZyB8IHVuZGVmaW5lZCwgZmFsbGJhY2s6IG51bWJlcik6IG51bWJlciB7XG4gIGNvbnN0IHBhcnNlZCA9IE51bWJlcihyYXcpO1xuXG4gIGlmICghTnVtYmVyLmlzSW50ZWdlcihwYXJzZWQpIHx8IHBhcnNlZCA8IDAgfHwgcGFyc2VkID4gMjMpIHJldHVybiBmYWxsYmFjaztcblxuICByZXR1cm4gcGFyc2VkO1xufVxuXG4vKipcbiAqIOyhsOyaqSDsi5zqsITsnbjsp4Ag7YyQ7KCV7ZWc64ukLlxuICpcbiAqIOyLnOyekSA+IOyiheujjOuptCDsnpDsoJXsnYQg64SY64qUIOq1rOqwhCgyMOyLnH7snbXsnbwgOOyLnCksIOyLnOyekSA8IOyiheujjOuptCDqsJnsnYAg64KgIOq1rOqwhCgw7Iucfjjsi5zsspjrn7wpXG4gKiDsnLzroZwg7J2964qU64ukLiDslbzqsIQg6re866y07LKY65+8IOuCruyXkCDsobDsmqntlZjqs6Ag7Iu27J2AIO2MgOuPhCDsnojslrQg65Kk7KeR7Z6MIOqwkuydhCDrp4nsp4Ag7JWK64qU64ukLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNRdWlldEhvdXJzKGF0OiBEYXRlLCByZWFkU2V0dGluZzogUmVhZFNldHRpbmcpOiBib29sZWFuIHtcbiAgY29uc3QgeyBob3VyLCB3ZWVrZGF5IH0gPSBzZW91bFBhcnRzKGF0KTtcblxuICBjb25zdCBpc1dlZWtlbmQgPSB3ZWVrZGF5ID09PSBcIlNhdFwiIHx8IHdlZWtkYXkgPT09IFwiU3VuXCI7XG5cbiAgaWYgKGlzV2Vla2VuZCAmJiByZWFkU2V0dGluZyhcInNsYWNrLm5vdGlmeU9uV2Vla2VuZHNcIiwgXCJTTEFDS19OT1RJRllfT05fV0VFS0VORFNcIikgIT09IFwidHJ1ZVwiKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBjb25zdCBmcm9tID0gYm91bmRlZEhvdXIoXG4gICAgcmVhZFNldHRpbmcoXCJzbGFjay5xdWlldEZyb21Ib3VyXCIsIFwiU0xBQ0tfUVVJRVRfRlJPTV9IT1VSXCIpLFxuICAgIERFRkFVTFRfUVVJRVRfRlJPTV9IT1VSLFxuICApO1xuXG4gIGNvbnN0IHVudGlsID0gYm91bmRlZEhvdXIoXG4gICAgcmVhZFNldHRpbmcoXCJzbGFjay5xdWlldFVudGlsSG91clwiLCBcIlNMQUNLX1FVSUVUX1VOVElMX0hPVVJcIiksXG4gICAgREVGQVVMVF9RVUlFVF9VTlRJTF9IT1VSLFxuICApO1xuXG4gIC8vIOyLnOyekeqzvCDsooXro4zqsIAg6rCZ7Jy866m0IOq1rOqwhOydtCDruYTslrQg7J6I64uk64qUIOucu+ycvOuhnCDsnb3slrQg7KGw7JqpIOyLnOqwhOydhCDrkZDsp4Ag7JWK64qU64ukLlxuICBpZiAoZnJvbSA9PT0gdW50aWwpIHJldHVybiBmYWxzZTtcblxuICByZXR1cm4gZnJvbSA+IHVudGlsID8gaG91ciA+PSBmcm9tIHx8IGhvdXIgPCB1bnRpbCA6IGhvdXIgPj0gZnJvbSAmJiBob3VyIDwgdW50aWw7XG59XG4iXSwibWFwcGluZ3MiOiI7O0FBdUJBLE1BQWEsMEJBQTBCO0FBQ3ZDLE1BQWEsMkJBQTJCOzs7OztBQU14QyxNQUFNLGtCQUFrQixJQUFJLEtBQUssZUFBZSxTQUFTO0NBQ3ZELFVBQVU7Q0FDVixNQUFNO0NBQ04sUUFBUTtDQUNSLFNBQVM7QUFDWCxDQUFDO0FBT0QsU0FBUyxXQUFXLElBQTBCO0NBQzVDLE1BQU0sUUFBUSxnQkFBZ0IsY0FBYyxFQUFFO0NBQzlDLE1BQU0sT0FBTyxPQUFPLE1BQU0sTUFBTSxNQUFNLEVBQUUsU0FBUyxNQUFNLENBQUMsRUFBRSxTQUFTLEdBQUc7Q0FDdEUsTUFBTSxVQUFVLE1BQU0sTUFBTSxNQUFNLEVBQUUsU0FBUyxTQUFTLENBQUMsRUFBRSxTQUFTO0NBR2xFLE9BQU87RUFBRSxNQUFNLE9BQU87RUFBSTtDQUFRO0FBQ3BDOztBQUdBLFNBQVMsWUFBWSxLQUF5QixVQUEwQjtDQUN0RSxNQUFNLFNBQVMsT0FBTyxHQUFHO0NBRXpCLElBQUksQ0FBQyxPQUFPLFVBQVUsTUFBTSxLQUFLLFNBQVMsS0FBSyxTQUFTLElBQUksT0FBTztDQUVuRSxPQUFPO0FBQ1Q7Ozs7Ozs7QUFRQSxTQUFnQixhQUFhLElBQVUsYUFBbUM7Q0FDeEUsTUFBTSxFQUFFLE1BQU0sWUFBWSxXQUFXLEVBQUU7Q0FJdkMsS0FGa0IsWUFBWSxTQUFTLFlBQVksVUFFbEMsWUFBWSwwQkFBMEIsMEJBQTBCLE1BQU0sUUFDckYsT0FBTztDQUdULE1BQU0sT0FBTyxZQUNYLFlBQVksdUJBQXVCLHVCQUF1QixHQUFBLEVBRTVEO0NBRUEsTUFBTSxRQUFRLFlBQ1osWUFBWSx3QkFBd0Isd0JBQXdCLEdBQUEsQ0FFOUQ7Q0FHQSxJQUFJLFNBQVMsT0FBTyxPQUFPO0NBRTNCLE9BQU8sT0FBTyxRQUFRLFFBQVEsUUFBUSxPQUFPLFFBQVEsUUFBUSxRQUFRLE9BQU87QUFDOUUifQ==
@@ -1,5 +1,6 @@
1
1
  import { getSetting } from "../application/setting/setting.store.js";
2
2
  import { isQuietHours } from "./quiet-hours.js";
3
+ import { z } from "zod";
3
4
  import { getLogger } from "@logtape/logtape";
4
5
  //#region src/utils/slack-notify.ts
5
6
  /**
@@ -9,6 +10,10 @@ import { getLogger } from "@logtape/logtape";
9
10
  * 조용 시간(주말·20~8시)에는 `urgent` 가 아닌 알림을 보내지 않는다.
10
11
  * 알림 경로가 토큰 라우팅이나 오류 전파를 지연·차단해서는 안 된다.
11
12
  */
13
+ const slackPostMessageResponseSchema = z.looseObject({
14
+ ok: z.boolean().optional(),
15
+ error: z.string().optional().catch(void 0)
16
+ });
12
17
  const logger = getLogger(["qgrid", "slack"]);
13
18
  const SLACK_POST_MESSAGE_URL = "https://slack.com/api/chat.postMessage";
14
19
  const SLACK_TIMEOUT_MS = 5e3;
@@ -50,6 +55,11 @@ async function notifySlack(notification, readSetting = getSetting) {
50
55
  }]
51
56
  });
52
57
  try {
58
+ const attachment = {
59
+ fallback: subject ? `${title} — ${subject}` : title,
60
+ blocks
61
+ };
62
+ if (color) attachment.color = color;
53
63
  const res = await fetch(SLACK_POST_MESSAGE_URL, {
54
64
  method: "POST",
55
65
  headers: {
@@ -58,16 +68,12 @@ async function notifySlack(notification, readSetting = getSetting) {
58
68
  },
59
69
  body: JSON.stringify({
60
70
  channel,
61
- attachments: [{
62
- fallback: subject ? `${title} — ${subject}` : title,
63
- ...color ? { color } : {},
64
- blocks
65
- }]
71
+ attachments: [attachment]
66
72
  }),
67
73
  signal: AbortSignal.timeout(SLACK_TIMEOUT_MS)
68
74
  });
69
- const body = await res.json().catch(() => null);
70
- if (!res.ok || body?.ok !== true) throw new SlackNotificationError(`Slack 알림 발송 실패: ${typeof body?.error === "string" && /^[a-z_]{1,80}$/.test(body.error) ? body.error : `HTTP ${res.status}`}`);
75
+ const body = slackPostMessageResponseSchema.safeParse(await res.json().catch(() => null)).data;
76
+ if (!res.ok || body?.ok !== true) throw new SlackNotificationError(`Slack 알림 발송 실패: ${body?.error !== void 0 && /^[a-z_]{1,80}$/.test(body.error) ? body.error : `HTTP ${res.status}`}`);
71
77
  } catch (e) {
72
78
  const error = e instanceof SlackNotificationError ? e : new SlackNotificationError("Slack 알림 발송 실패: 네트워크 오류 또는 응답 시간 초과");
73
79
  logger.warn(error.message);
@@ -77,4 +83,4 @@ async function notifySlack(notification, readSetting = getSetting) {
77
83
  //#endregion
78
84
  export { SLACK_COLOR, SlackNotificationError, notifySlack };
79
85
 
80
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2xhY2stbm90aWZ5LmpzIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9zbGFjay1ub3RpZnkudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBTbGFjayDslYzrprwgKGNoYXQucG9zdE1lc3NhZ2UpLlxuICpcbiAqIGZhaWwtb3BlbjogZW52IOuvuOyEpOygleydtOuptCDsobDsmqntnoggbm8tb3Ag7J206rOgLCDsoITshqEg7Iuk7Yyo64qUIHdhcm4g66Gc6re466Gc66eMIOuCqOq4tOuLpC5cbiAqIOyhsOyaqSDsi5zqsIQo7KO866eQwrcyMH447IucKeyXkOuKlCBgdXJnZW50YCDqsIAg7JWE64uMIOyVjOumvOydhCDrs7TrgrTsp4Ag7JWK64qU64ukLlxuICog7JWM66a8IOqyveuhnOqwgCDthqDtgbAg65287Jqw7YyF7J2064KYIOyYpOulmCDsoITtjIzrpbwg7KeA7JewwrfssKjri6jtlbTshJzripQg7JWIIOuQnOuLpC5cbiAqL1xuaW1wb3J0IHsgZ2V0TG9nZ2VyIH0gZnJvbSBcIkBsb2d0YXBlL2xvZ3RhcGVcIjtcblxuaW1wb3J0IHsgZ2V0U2V0dGluZyB9IGZyb20gXCIuLi9hcHBsaWNhdGlvbi9zZXR0aW5nL3NldHRpbmcuc3RvcmVcIjtcbmltcG9ydCB7IGlzUXVpZXRIb3VycyB9IGZyb20gXCIuL3F1aWV0LWhvdXJzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGdldExvZ2dlcihbXCJxZ3JpZFwiLCBcInNsYWNrXCJdKTtcblxuY29uc3QgU0xBQ0tfUE9TVF9NRVNTQUdFX1VSTCA9IFwiaHR0cHM6Ly9zbGFjay5jb20vYXBpL2NoYXQucG9zdE1lc3NhZ2VcIjtcbmNvbnN0IFNMQUNLX1RJTUVPVVRfTVMgPSA1XzAwMDtcblxuZXhwb3J0IGNsYXNzIFNsYWNrTm90aWZpY2F0aW9uRXJyb3IgZXh0ZW5kcyBFcnJvciB7fVxuXG4vKiog7IOB7YOc66W8IOyDieycvOuhnCDrqLzsoIAg7J297Z6I6rKMIO2VmOuKlCBhdHRhY2htZW50IOyDieyDgSDrsJQuICovXG5leHBvcnQgY29uc3QgU0xBQ0tfQ09MT1IgPSB7XG4gIGdvb2Q6IFwiIzJlYjg4NlwiLFxuICBiYWQ6IFwiI2UwMWU1YVwiLFxufSBhcyBjb25zdDtcblxuZXhwb3J0IHR5cGUgU2xhY2tOb3RpZmljYXRpb24gPSB7XG4gIC8qKiDtlZwg7KSEIOygnOuqqS4g66y07IqoIOydvOydtCDsnbzslrTrgqzripTsp4Drp4wg64u064qU64ukLiAqL1xuICB0aXRsZTogc3RyaW5nO1xuICAvKiog7KCc66qpIOyYhiDsvZTrk5wg7Iqk7YOA7J2866GcIOu2meuKlCDrjIDsg4Eg7Iud67OE7J6QLiAqL1xuICBzdWJqZWN0Pzogc3RyaW5nO1xuICAvKiog7KCc66qpIOyVhOuemCDsnpHsnYAg6riA7JSo66GcIOuCtOugpOqwgOuKlCDrtoDqsIAg7KCV67O0IOKAlCDsnb3sp4Ag7JWK7JWE64+EIOuQmOuKlCDqsoPrk6QuICovXG4gIGNvbnRleHQ/OiBzdHJpbmc7XG4gIGNvbG9yPzogKHR5cGVvZiBTTEFDS19DT0xPUilba2V5b2YgdHlwZW9mIFNMQUNLX0NPTE9SXTtcbiAgLyoqXG4gICAqIOyhsOyaqSDsi5zqsIQo7KO866eQwrcyMH447IucKeyXkOuPhCDrs7Trgrjri6QuIOyEnOu5hOyKpOqwgCDrqYjstpgg7IOB7YOc7LKY65+8IOyngOq4iCDslYzsp4Ag7JWK7Jy866m0IOyGkO2VtOqwgFxuICAgKiDsu6Tsp4DripQg7IKs6rG07JeQ66eMIOyTtOuLpCDigJQg64Ko7Jqp7ZWY66m0IOyhsOyaqSDsi5zqsIQg7J6Q7LK06rCAIOustOydmOuvuO2VtOynhOuLpC5cbiAgICovXG4gIHVyZ2VudD86IGJvb2xlYW47XG4gIC8qKiBNYW51YWwgc2VuZHMgbXVzdCByZXBvcnQgZGVsaXZlcnkgZmFpbHVyZXM7IGJhY2tncm91bmQgbm90aWZpY2F0aW9ucyByZW1haW4gZmFpbC1vcGVuLiAqL1xuICB0aHJvd09uRmFpbHVyZT86IGJvb2xlYW47XG4gIC8qKiDsobDsmqkg7Iuc6rCEIO2MkOyglSDquLDspIAg7Iuc6rCBLiDthYzsiqTtirjsl5DshJwg7Iuc6rOE66W8IOqzoOygle2VoCDrlYzrp4wg64SY6ri064ukLiAqL1xuICBub3c/OiBEYXRlO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG5vdGlmeVNsYWNrKFxuICBub3RpZmljYXRpb246IFNsYWNrTm90aWZpY2F0aW9uLFxuICByZWFkU2V0dGluZzogdHlwZW9mIGdldFNldHRpbmcgPSBnZXRTZXR0aW5nLFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGJvdFRva2VuID0gcmVhZFNldHRpbmcoXCJzbGFjay5ib3RUb2tlblwiLCBcIlNMQUNLX0JPVF9UT0tFTlwiKTtcbiAgY29uc3QgY2hhbm5lbCA9IHJlYWRTZXR0aW5nKFwic2xhY2suY2hhbm5lbElkXCIsIFwiU0xBQ0tfQ0hBTk5FTF9JRFwiKTtcbiAgY29uc3QgeyB0aXRsZSwgc3ViamVjdCwgY29udGV4dCwgY29sb3IsIHVyZ2VudCwgbm93IH0gPSBub3RpZmljYXRpb247XG4gIGlmICghYm90VG9rZW4gfHwgIWNoYW5uZWwpIHtcbiAgICBsb2dnZXIuZGVidWcoYHNsYWNrIG5vdCBjb25maWd1cmVkLCBza2lwcGluZyBub3RpZmljYXRpb246ICR7dGl0bGV9ICR7c3ViamVjdCA/PyBcIlwifWApO1xuICAgIGlmIChub3RpZmljYXRpb24udGhyb3dPbkZhaWx1cmUpIHtcbiAgICAgIHRocm93IG5ldyBTbGFja05vdGlmaWNhdGlvbkVycm9yKFwiU2xhY2sg67SHIO2GoO2BsOqzvCDssYTrhJAgSUTrpbwg7ISk7KCV7ZW0IOyjvOyEuOyalFwiKTtcbiAgICB9XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8g7Jew7Zy07LKY65+8IOq3nOy5meycvOuhnCDsnqHsnYQg7IiYIOyXhuuKlCDquLDqsITsl5Ag6rSA66as7J6Q6rCAIOuCtOumrOuKlCDsiqTsnITsuZguIHVyZ2VudCDripQg7Ya16rO87Iuc7YKo64ukIOKAlFxuICAvLyDrgYgg7IOB7YOc66GcIHByb3ZpZGVyIOqwgCDsoITrtoAg7KO97Jy866m0IOyXsO2ctCDrgrTrgrQg7ISc67mE7Iqk6rCAIOupiOy2mCDspIQg7JWE66y064+EIOuqqOuluOuLpC5cbiAgaWYgKCF1cmdlbnQgJiYgcmVhZFNldHRpbmcoXCJzbGFjay5lbmFibGVkXCIsIFwiU0xBQ0tfRU5BQkxFRFwiKSA9PT0gXCJmYWxzZVwiKSB7XG4gICAgbG9nZ2VyLmRlYnVnKGBzbGFjayBkaXNhYmxlZCwgc2tpcHBpbmcgbm90aWZpY2F0aW9uOiAke3RpdGxlfSAke3N1YmplY3QgPz8gXCJcIn1gKTtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyDrp4zro4wg7JWM66a87J2AIOyjvOq4sOyggeycvOuhnCDrsJjrs7XrkJjrr4DroZwg7Jes6riw7IScIOuyhOugpOuPhCDri6TsnYwg6re866y0IOyLnOqwhCDssqsg7KO86riw7JeQIOuLpOyLnCDsmKjri6QuXG4gIGlmICghdXJnZW50ICYmIGlzUXVpZXRIb3Vycyhub3cgPz8gbmV3IERhdGUoKSwgcmVhZFNldHRpbmcpKSB7XG4gICAgbG9nZ2VyLmRlYnVnKGBxdWlldCBob3Vycywgc2tpcHBpbmcgbm90aWZpY2F0aW9uOiAke3RpdGxlfSAke3N1YmplY3QgPz8gXCJcIn1gKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBibG9ja3M6IHVua25vd25bXSA9IFtcbiAgICB7XG4gICAgICB0eXBlOiBcInNlY3Rpb25cIixcbiAgICAgIHRleHQ6IHsgdHlwZTogXCJtcmtkd25cIiwgdGV4dDogc3ViamVjdCA/IGAqJHt0aXRsZX0qICBcXGAke3N1YmplY3R9XFxgYCA6IGAqJHt0aXRsZX0qYCB9LFxuICAgIH0sXG4gIF07XG4gIGlmIChjb250ZXh0KSB7XG4gICAgYmxvY2tzLnB1c2goeyB0eXBlOiBcImNvbnRleHRcIiwgZWxlbWVudHM6IFt7IHR5cGU6IFwibXJrZHduXCIsIHRleHQ6IGNvbnRleHQgfV0gfSk7XG4gIH1cblxuICB0cnkge1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IGZldGNoKFNMQUNLX1BPU1RfTUVTU0FHRV9VUkwsIHtcbiAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgIFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD11dGYtOFwiLFxuICAgICAgICBBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7Ym90VG9rZW59YCxcbiAgICAgIH0sXG4gICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIGNoYW5uZWwsXG4gICAgICAgIC8vIGZhbGxiYWNrIOydgCBhdHRhY2htZW50IOyViOyXkCDrkZTri6QuIOy1nOyDgeychCB0ZXh0IOuhnCDrs7TrgrTrqbQgYmxvY2tzIOqwgCDsoJXsg4Eg66CM642U65CY64qUXG4gICAgICAgIC8vIO2ZlOuptOyXkOyEnOuPhCDtlajqu5gg7Lac66Cl64+8IOygnOuqqeydtCDrkZAg67KIIOuztOyduOuLpC4gYXR0YWNobWVudCBmYWxsYmFjayDsnYAgYmxvY2tzIOulvFxuICAgICAgICAvLyDrqrsg6re466as64qUIO2BtOudvOydtOyWuO2KuOyZgCDtkbjsi5wg7JWM66a87JeQ7ISc66eMIOyTsOyduOuLpC5cbiAgICAgICAgYXR0YWNobWVudHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBmYWxsYmFjazogc3ViamVjdCA/IGAke3RpdGxlfSDigJQgJHtzdWJqZWN0fWAgOiB0aXRsZSxcbiAgICAgICAgICAgIC4uLihjb2xvciA/IHsgY29sb3IgfSA6IHt9KSxcbiAgICAgICAgICAgIGJsb2NrcyxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSksXG4gICAgICBzaWduYWw6IEFib3J0U2lnbmFsLnRpbWVvdXQoU0xBQ0tfVElNRU9VVF9NUyksXG4gICAgfSk7XG5cbiAgICAvLyBib3Qg66+47LSI64yAKG5vdF9pbl9jaGFubmVsKcK37J6Y66q765CcIOyxhOuEkCDrk7Eg6rCA7J6lIO2dlO2VnCDsmKTshKTsoJXsnYAgSFRUUCAyMDAgKyBvazpmYWxzZSDroZwg7Jio64ukLlxuICAgIC8vIHN0YXR1cyDrp4wg67O066m0IOyhsOyaqe2eiCDshLHqs7Ug7LKY66as64+8IOyVjOumvOydtCDthrXsp7jroZwg7IKs65287KeE64ukLlxuICAgIGNvbnN0IGJvZHkgPSAoYXdhaXQgcmVzLmpzb24oKS5jYXRjaCgoKSA9PiBudWxsKSkgYXMgeyBvaz86IGJvb2xlYW47IGVycm9yPzogc3RyaW5nIH0gfCBudWxsO1xuICAgIGlmICghcmVzLm9rIHx8IGJvZHk/Lm9rICE9PSB0cnVlKSB7XG4gICAgICBjb25zdCBjb2RlID1cbiAgICAgICAgdHlwZW9mIGJvZHk/LmVycm9yID09PSBcInN0cmluZ1wiICYmIC9eW2Etel9dezEsODB9JC8udGVzdChib2R5LmVycm9yKVxuICAgICAgICAgID8gYm9keS5lcnJvclxuICAgICAgICAgIDogYEhUVFAgJHtyZXMuc3RhdHVzfWA7XG4gICAgICB0aHJvdyBuZXcgU2xhY2tOb3RpZmljYXRpb25FcnJvcihgU2xhY2sg7JWM66a8IOuwnOyGoSDsi6TtjKg6ICR7Y29kZX1gKTtcbiAgICB9XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBjb25zdCBlcnJvciA9XG4gICAgICBlIGluc3RhbmNlb2YgU2xhY2tOb3RpZmljYXRpb25FcnJvclxuICAgICAgICA/IGVcbiAgICAgICAgOiBuZXcgU2xhY2tOb3RpZmljYXRpb25FcnJvcihcIlNsYWNrIOyVjOumvCDrsJzshqEg7Iuk7YyoOiDrhKTtirjsm4ztgawg7Jik66WYIOuYkOuKlCDsnZHri7Ug7Iuc6rCEIOy0iOqzvFwiKTtcbiAgICBsb2dnZXIud2FybihlcnJvci5tZXNzYWdlKTtcbiAgICBpZiAobm90aWZpY2F0aW9uLnRocm93T25GYWlsdXJlKSB0aHJvdyBlcnJvcjtcbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztBQVlBLE1BQU0sU0FBUyxVQUFVLENBQUMsU0FBUyxPQUFPLENBQUM7QUFFM0MsTUFBTSx5QkFBeUI7QUFDL0IsTUFBTSxtQkFBbUI7QUFFekIsSUFBYSx5QkFBYixjQUE0QyxNQUFNLENBQUM7O0FBR25ELE1BQWEsY0FBYztDQUN6QixNQUFNO0NBQ04sS0FBSztBQUNQO0FBcUJBLGVBQXNCLFlBQ3BCLGNBQ0EsY0FBaUMsWUFDbEI7Q0FDZixNQUFNLFdBQVcsWUFBWSxrQkFBa0IsaUJBQWlCO0NBQ2hFLE1BQU0sVUFBVSxZQUFZLG1CQUFtQixrQkFBa0I7Q0FDakUsTUFBTSxFQUFFLE9BQU8sU0FBUyxTQUFTLE9BQU8sUUFBUSxRQUFRO0NBQ3hELElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUztFQUN6QixPQUFPLE1BQU0sZ0RBQWdELE1BQU0sR0FBRyxXQUFXLElBQUk7RUFDckYsSUFBSSxhQUFhLGdCQUNmLE1BQU0sSUFBSSx1QkFBdUIsNEJBQTRCO0VBRS9EO0NBQ0Y7Q0FJQSxJQUFJLENBQUMsVUFBVSxZQUFZLGlCQUFpQixlQUFlLE1BQU0sU0FBUztFQUN4RSxPQUFPLE1BQU0sMENBQTBDLE1BQU0sR0FBRyxXQUFXLElBQUk7RUFDL0U7Q0FDRjtDQUdBLElBQUksQ0FBQyxVQUFVLGFBQWEsdUJBQU8sSUFBSSxLQUFLLEdBQUcsV0FBVyxHQUFHO0VBQzNELE9BQU8sTUFBTSx1Q0FBdUMsTUFBTSxHQUFHLFdBQVcsSUFBSTtFQUM1RTtDQUNGO0NBRUEsTUFBTSxTQUFvQixDQUN4QjtFQUNFLE1BQU07RUFDTixNQUFNO0dBQUUsTUFBTTtHQUFVLE1BQU0sVUFBVSxJQUFJLE1BQU0sT0FBTyxRQUFRLE1BQU0sSUFBSSxNQUFNO0VBQUc7Q0FDdEYsQ0FDRjtDQUNBLElBQUksU0FDRixPQUFPLEtBQUs7RUFBRSxNQUFNO0VBQVcsVUFBVSxDQUFDO0dBQUUsTUFBTTtHQUFVLE1BQU07RUFBUSxDQUFDO0NBQUUsQ0FBQztDQUdoRixJQUFJO0VBQ0YsTUFBTSxNQUFNLE1BQU0sTUFBTSx3QkFBd0I7R0FDOUMsUUFBUTtHQUNSLFNBQVM7SUFDUCxnQkFBZ0I7SUFDaEIsZUFBZSxVQUFVO0dBQzNCO0dBQ0EsTUFBTSxLQUFLLFVBQVU7SUFDbkI7SUFJQSxhQUFhLENBQ1g7S0FDRSxVQUFVLFVBQVUsR0FBRyxNQUFNLEtBQUssWUFBWTtLQUM5QyxHQUFJLFFBQVEsRUFBRSxNQUFNLElBQUksQ0FBQztLQUN6QjtJQUNGLENBQ0Y7R0FDRixDQUFDO0dBQ0QsUUFBUSxZQUFZLFFBQVEsZ0JBQWdCO0VBQzlDLENBQUM7RUFJRCxNQUFNLE9BQVEsTUFBTSxJQUFJLEtBQUssQ0FBQyxDQUFDLFlBQVksSUFBSTtFQUMvQyxJQUFJLENBQUMsSUFBSSxNQUFNLE1BQU0sT0FBTyxNQUsxQixNQUFNLElBQUksdUJBQXVCLG1CQUgvQixPQUFPLE1BQU0sVUFBVSxZQUFZLGlCQUFpQixLQUFLLEtBQUssS0FBSyxJQUMvRCxLQUFLLFFBQ0wsUUFBUSxJQUFJLFVBQ3dDO0NBRTlELFNBQVMsR0FBRztFQUNWLE1BQU0sUUFDSixhQUFhLHlCQUNULElBQ0EsSUFBSSx1QkFBdUIscUNBQXFDO0VBQ3RFLE9BQU8sS0FBSyxNQUFNLE9BQU87RUFDekIsSUFBSSxhQUFhLGdCQUFnQixNQUFNO0NBQ3pDO0FBQ0YifQ==
86
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2xhY2stbm90aWZ5LmpzIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9zbGFjay1ub3RpZnkudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBTbGFjayDslYzrprwgKGNoYXQucG9zdE1lc3NhZ2UpLlxuICpcbiAqIGZhaWwtb3BlbjogZW52IOuvuOyEpOygleydtOuptCDsobDsmqntnoggbm8tb3Ag7J206rOgLCDsoITshqEg7Iuk7Yyo64qUIHdhcm4g66Gc6re466Gc66eMIOuCqOq4tOuLpC5cbiAqIOyhsOyaqSDsi5zqsIQo7KO866eQwrcyMH447IucKeyXkOuKlCBgdXJnZW50YCDqsIAg7JWE64uMIOyVjOumvOydhCDrs7TrgrTsp4Ag7JWK64qU64ukLlxuICog7JWM66a8IOqyveuhnOqwgCDthqDtgbAg65287Jqw7YyF7J2064KYIOyYpOulmCDsoITtjIzrpbwg7KeA7JewwrfssKjri6jtlbTshJzripQg7JWIIOuQnOuLpC5cbiAqL1xuaW1wb3J0IHsgZ2V0TG9nZ2VyIH0gZnJvbSBcIkBsb2d0YXBlL2xvZ3RhcGVcIjtcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5cbmltcG9ydCB7IGdldFNldHRpbmcgfSBmcm9tIFwiLi4vYXBwbGljYXRpb24vc2V0dGluZy9zZXR0aW5nLnN0b3JlXCI7XG5pbXBvcnQgeyBpc1F1aWV0SG91cnMgfSBmcm9tIFwiLi9xdWlldC1ob3Vyc1wiO1xuXG50eXBlIFNsYWNrVGV4dE9iamVjdCA9IHsgdHlwZTogXCJtcmtkd25cIjsgdGV4dDogc3RyaW5nIH07XG5cbnR5cGUgU2xhY2tCbG9jayA9XG4gIHwgeyB0eXBlOiBcInNlY3Rpb25cIjsgdGV4dDogU2xhY2tUZXh0T2JqZWN0IH1cbiAgfCB7IHR5cGU6IFwiY29udGV4dFwiOyBlbGVtZW50czogU2xhY2tUZXh0T2JqZWN0W10gfTtcblxuaW50ZXJmYWNlIFNsYWNrQXR0YWNobWVudCB7XG4gIGZhbGxiYWNrOiBzdHJpbmc7XG4gIGNvbG9yPzogc3RyaW5nO1xuICBibG9ja3M6IFNsYWNrQmxvY2tbXTtcbn1cblxuLy8gY2hhdC5wb3N0TWVzc2FnZSBhbnN3ZXJzIEhUVFAgMjAwIHdpdGggb2s6ZmFsc2UgZm9yIG1vc3QgY29uZmlndXJhdGlvbiBlcnJvcnMuIEEgbWFsZm9ybWVkXG4vLyBlcnJvciBmaWVsZCBtdXN0IG5vdCBoaWRlIG9rOnRydWUsIHNvIGl0IGRlZ3JhZGVzIHRvIHVuZGVmaW5lZCBpbnN0ZWFkIG9mIGZhaWxpbmcgdGhlIHBhcnNlLlxuY29uc3Qgc2xhY2tQb3N0TWVzc2FnZVJlc3BvbnNlU2NoZW1hID0gei5sb29zZU9iamVjdCh7XG4gIG9rOiB6LmJvb2xlYW4oKS5vcHRpb25hbCgpLFxuICBlcnJvcjogei5zdHJpbmcoKS5vcHRpb25hbCgpLmNhdGNoKHVuZGVmaW5lZCksXG59KTtcblxuY29uc3QgbG9nZ2VyID0gZ2V0TG9nZ2VyKFtcInFncmlkXCIsIFwic2xhY2tcIl0pO1xuXG5jb25zdCBTTEFDS19QT1NUX01FU1NBR0VfVVJMID0gXCJodHRwczovL3NsYWNrLmNvbS9hcGkvY2hhdC5wb3N0TWVzc2FnZVwiO1xuY29uc3QgU0xBQ0tfVElNRU9VVF9NUyA9IDVfMDAwO1xuXG5leHBvcnQgY2xhc3MgU2xhY2tOb3RpZmljYXRpb25FcnJvciBleHRlbmRzIEVycm9yIHt9XG5cbi8qKiDsg4Htg5zrpbwg7IOJ7Jy866GcIOuovOyggCDsnb3tnojqsowg7ZWY64qUIGF0dGFjaG1lbnQg7IOJ7IOBIOuwlC4gKi9cbmV4cG9ydCBjb25zdCBTTEFDS19DT0xPUiA9IHtcbiAgZ29vZDogXCIjMmViODg2XCIsXG4gIGJhZDogXCIjZTAxZTVhXCIsXG59IGFzIGNvbnN0O1xuXG5leHBvcnQgdHlwZSBTbGFja05vdGlmaWNhdGlvbiA9IHtcbiAgLyoqIO2VnCDspIQg7KCc66qpLiDrrLTsiqgg7J287J20IOydvOyWtOuCrOuKlOyngOunjCDri7TripTri6QuICovXG4gIHRpdGxlOiBzdHJpbmc7XG4gIC8qKiDsoJzrqqkg7JiGIOy9lOuTnCDsiqTtg4DsnbzroZwg67aZ64qUIOuMgOyDgSDsi53rs4TsnpAuICovXG4gIHN1YmplY3Q/OiBzdHJpbmc7XG4gIC8qKiDsoJzrqqkg7JWE656YIOyekeydgCDquIDslKjroZwg64K066Ck6rCA64qUIOu2gOqwgCDsoJXrs7Qg4oCUIOydveyngCDslYrslYTrj4Qg65CY64qUIOqyg+uTpC4gKi9cbiAgY29udGV4dD86IHN0cmluZztcbiAgY29sb3I/OiAodHlwZW9mIFNMQUNLX0NPTE9SKVtrZXlvZiB0eXBlb2YgU0xBQ0tfQ09MT1JdO1xuICAvKipcbiAgICog7KGw7JqpIOyLnOqwhCjso7zrp5DCtzIwfjjsi5wp7JeQ64+EIOuztOuCuOuLpC4g7ISc67mE7Iqk6rCAIOupiOy2mCDsg4Htg5zsspjrn7wg7KeA6riIIOyVjOyngCDslYrsnLzrqbQg7IaQ7ZW06rCAXG4gICAqIOy7pOyngOuKlCDsgqzqsbTsl5Drp4wg7JO064ukIOKAlCDrgqjsmqntlZjrqbQg7KGw7JqpIOyLnOqwhCDsnpDssrTqsIAg66y07J2Y66+47ZW07KeE64ukLlxuICAgKi9cbiAgdXJnZW50PzogYm9vbGVhbjtcbiAgLyoqIE1hbnVhbCBzZW5kcyBtdXN0IHJlcG9ydCBkZWxpdmVyeSBmYWlsdXJlczsgYmFja2dyb3VuZCBub3RpZmljYXRpb25zIHJlbWFpbiBmYWlsLW9wZW4uICovXG4gIHRocm93T25GYWlsdXJlPzogYm9vbGVhbjtcbiAgLyoqIOyhsOyaqSDsi5zqsIQg7YyQ7KCVIOq4sOykgCDsi5zqsIEuIO2FjOyKpO2KuOyXkOyEnCDsi5zqs4Trpbwg6rOg7KCV7ZWgIOuVjOunjCDrhJjquLTri6QuICovXG4gIG5vdz86IERhdGU7XG59O1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbm90aWZ5U2xhY2soXG4gIG5vdGlmaWNhdGlvbjogU2xhY2tOb3RpZmljYXRpb24sXG4gIHJlYWRTZXR0aW5nOiB0eXBlb2YgZ2V0U2V0dGluZyA9IGdldFNldHRpbmcsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgYm90VG9rZW4gPSByZWFkU2V0dGluZyhcInNsYWNrLmJvdFRva2VuXCIsIFwiU0xBQ0tfQk9UX1RPS0VOXCIpO1xuICBjb25zdCBjaGFubmVsID0gcmVhZFNldHRpbmcoXCJzbGFjay5jaGFubmVsSWRcIiwgXCJTTEFDS19DSEFOTkVMX0lEXCIpO1xuICBjb25zdCB7IHRpdGxlLCBzdWJqZWN0LCBjb250ZXh0LCBjb2xvciwgdXJnZW50LCBub3cgfSA9IG5vdGlmaWNhdGlvbjtcblxuICBpZiAoIWJvdFRva2VuIHx8ICFjaGFubmVsKSB7XG4gICAgbG9nZ2VyLmRlYnVnKGBzbGFjayBub3QgY29uZmlndXJlZCwgc2tpcHBpbmcgbm90aWZpY2F0aW9uOiAke3RpdGxlfSAke3N1YmplY3QgPz8gXCJcIn1gKTtcblxuICAgIGlmIChub3RpZmljYXRpb24udGhyb3dPbkZhaWx1cmUpIHtcbiAgICAgIHRocm93IG5ldyBTbGFja05vdGlmaWNhdGlvbkVycm9yKFwiU2xhY2sg67SHIO2GoO2BsOqzvCDssYTrhJAgSUTrpbwg7ISk7KCV7ZW0IOyjvOyEuOyalFwiKTtcbiAgICB9XG5cbiAgICByZXR1cm47XG4gIH1cblxuICAvLyDsl7DtnLTsspjrn7wg6rec7LmZ7Jy866GcIOyeoeydhCDsiJgg7JeG64qUIOq4sOqwhOyXkCDqtIDrpqzsnpDqsIAg64K066as64qUIOyKpOychOy5mC4gdXJnZW50IOuKlCDthrXqs7zsi5ztgqjri6Qg4oCUXG4gIC8vIOuBiCDsg4Htg5zroZwgcHJvdmlkZXIg6rCAIOyghOu2gCDso73snLzrqbQg7Jew7Zy0IOuCtOuCtCDshJzruYTsiqTqsIAg66mI7LaYIOykhCDslYTrrLTrj4Qg66qo66W464ukLlxuICBpZiAoIXVyZ2VudCAmJiByZWFkU2V0dGluZyhcInNsYWNrLmVuYWJsZWRcIiwgXCJTTEFDS19FTkFCTEVEXCIpID09PSBcImZhbHNlXCIpIHtcbiAgICBsb2dnZXIuZGVidWcoYHNsYWNrIGRpc2FibGVkLCBza2lwcGluZyBub3RpZmljYXRpb246ICR7dGl0bGV9ICR7c3ViamVjdCA/PyBcIlwifWApO1xuXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8g66eM66OMIOyVjOumvOydgCDso7zquLDsoIHsnLzroZwg67CY67O165CY66+A66GcIOyXrOq4sOyEnCDrsoTroKTrj4Qg64uk7J2MIOq3vOustCDsi5zqsIQg7LKrIOyjvOq4sOyXkCDri6Tsi5wg7Jio64ukLlxuICBpZiAoIXVyZ2VudCAmJiBpc1F1aWV0SG91cnMobm93ID8/IG5ldyBEYXRlKCksIHJlYWRTZXR0aW5nKSkge1xuICAgIGxvZ2dlci5kZWJ1ZyhgcXVpZXQgaG91cnMsIHNraXBwaW5nIG5vdGlmaWNhdGlvbjogJHt0aXRsZX0gJHtzdWJqZWN0ID8/IFwiXCJ9YCk7XG5cbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBibG9ja3M6IFNsYWNrQmxvY2tbXSA9IFtcbiAgICB7XG4gICAgICB0eXBlOiBcInNlY3Rpb25cIixcbiAgICAgIHRleHQ6IHsgdHlwZTogXCJtcmtkd25cIiwgdGV4dDogc3ViamVjdCA/IGAqJHt0aXRsZX0qICBcXGAke3N1YmplY3R9XFxgYCA6IGAqJHt0aXRsZX0qYCB9LFxuICAgIH0sXG4gIF07XG5cbiAgaWYgKGNvbnRleHQpIHtcbiAgICBibG9ja3MucHVzaCh7IHR5cGU6IFwiY29udGV4dFwiLCBlbGVtZW50czogW3sgdHlwZTogXCJtcmtkd25cIiwgdGV4dDogY29udGV4dCB9XSB9KTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgLy8gZmFsbGJhY2sg7J2AIGF0dGFjaG1lbnQg7JWI7JeQIOuRlOuLpC4g7LWc7IOB7JyEIHRleHQg66GcIOuztOuCtOuptCBibG9ja3Mg6rCAIOygleyDgSDroIzrjZTrkJjripRcbiAgICAvLyDtmZTrqbTsl5DshJzrj4Qg7ZWo6ruYIOy2nOugpeuPvCDsoJzrqqnsnbQg65GQIOuyiCDrs7Tsnbjri6QuIGF0dGFjaG1lbnQgZmFsbGJhY2sg7J2AIGJsb2NrcyDrpbxcbiAgICAvLyDrqrsg6re466as64qUIO2BtOudvOydtOyWuO2KuOyZgCDtkbjsi5wg7JWM66a87JeQ7ISc66eMIOyTsOyduOuLpC5cbiAgICBjb25zdCBhdHRhY2htZW50OiBTbGFja0F0dGFjaG1lbnQgPSB7XG4gICAgICBmYWxsYmFjazogc3ViamVjdCA/IGAke3RpdGxlfSDigJQgJHtzdWJqZWN0fWAgOiB0aXRsZSxcbiAgICAgIGJsb2NrcyxcbiAgICB9O1xuXG4gICAgaWYgKGNvbG9yKSBhdHRhY2htZW50LmNvbG9yID0gY29sb3I7XG5cbiAgICBjb25zdCByZXMgPSBhd2FpdCBmZXRjaChTTEFDS19QT1NUX01FU1NBR0VfVVJMLCB7XG4gICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9dXRmLThcIixcbiAgICAgICAgQXV0aG9yaXphdGlvbjogYEJlYXJlciAke2JvdFRva2VufWAsXG4gICAgICB9LFxuICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICBjaGFubmVsLFxuICAgICAgICBhdHRhY2htZW50czogW2F0dGFjaG1lbnRdLFxuICAgICAgfSksXG4gICAgICBzaWduYWw6IEFib3J0U2lnbmFsLnRpbWVvdXQoU0xBQ0tfVElNRU9VVF9NUyksXG4gICAgfSk7XG5cbiAgICAvLyBib3Qg66+47LSI64yAKG5vdF9pbl9jaGFubmVsKcK37J6Y66q765CcIOyxhOuEkCDrk7Eg6rCA7J6lIO2dlO2VnCDsmKTshKTsoJXsnYAgSFRUUCAyMDAgKyBvazpmYWxzZSDroZwg7Jio64ukLlxuICAgIC8vIHN0YXR1cyDrp4wg67O066m0IOyhsOyaqe2eiCDshLHqs7Ug7LKY66as64+8IOyVjOumvOydtCDthrXsp7jroZwg7IKs65287KeE64ukLlxuICAgIGNvbnN0IGJvZHkgPSBzbGFja1Bvc3RNZXNzYWdlUmVzcG9uc2VTY2hlbWEuc2FmZVBhcnNlKGF3YWl0IHJlcy5qc29uKCkuY2F0Y2goKCkgPT4gbnVsbCkpLmRhdGE7XG5cbiAgICBpZiAoIXJlcy5vayB8fCBib2R5Py5vayAhPT0gdHJ1ZSkge1xuICAgICAgY29uc3QgY29kZSA9XG4gICAgICAgIGJvZHk/LmVycm9yICE9PSB1bmRlZmluZWQgJiYgL15bYS16X117MSw4MH0kLy50ZXN0KGJvZHkuZXJyb3IpXG4gICAgICAgICAgPyBib2R5LmVycm9yXG4gICAgICAgICAgOiBgSFRUUCAke3Jlcy5zdGF0dXN9YDtcblxuICAgICAgdGhyb3cgbmV3IFNsYWNrTm90aWZpY2F0aW9uRXJyb3IoYFNsYWNrIOyVjOumvCDrsJzshqEg7Iuk7YyoOiAke2NvZGV9YCk7XG4gICAgfVxuICB9IGNhdGNoIChlKSB7XG4gICAgY29uc3QgZXJyb3IgPVxuICAgICAgZSBpbnN0YW5jZW9mIFNsYWNrTm90aWZpY2F0aW9uRXJyb3JcbiAgICAgICAgPyBlXG4gICAgICAgIDogbmV3IFNsYWNrTm90aWZpY2F0aW9uRXJyb3IoXCJTbGFjayDslYzrprwg67Cc7IahIOyLpO2MqDog64Sk7Yq47JuM7YGsIOyYpOulmCDrmJDripQg7J2R64u1IOyLnOqwhCDstIjqs7xcIik7XG5cbiAgICBsb2dnZXIud2FybihlcnJvci5tZXNzYWdlKTtcblxuICAgIGlmIChub3RpZmljYXRpb24udGhyb3dPbkZhaWx1cmUpIHRocm93IGVycm9yO1xuICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQTJCQSxNQUFNLGlDQUFpQyxFQUFFLFlBQVk7Q0FDbkQsSUFBSSxFQUFFLFFBQVEsQ0FBQyxDQUFDLFNBQVM7Q0FDekIsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLE1BQU0sTUFBUztBQUM5QyxDQUFDO0FBRUQsTUFBTSxTQUFTLFVBQVUsQ0FBQyxTQUFTLE9BQU8sQ0FBQztBQUUzQyxNQUFNLHlCQUF5QjtBQUMvQixNQUFNLG1CQUFtQjtBQUV6QixJQUFhLHlCQUFiLGNBQTRDLE1BQU0sQ0FBQzs7QUFHbkQsTUFBYSxjQUFjO0NBQ3pCLE1BQU07Q0FDTixLQUFLO0FBQ1A7QUFxQkEsZUFBc0IsWUFDcEIsY0FDQSxjQUFpQyxZQUNsQjtDQUNmLE1BQU0sV0FBVyxZQUFZLGtCQUFrQixpQkFBaUI7Q0FDaEUsTUFBTSxVQUFVLFlBQVksbUJBQW1CLGtCQUFrQjtDQUNqRSxNQUFNLEVBQUUsT0FBTyxTQUFTLFNBQVMsT0FBTyxRQUFRLFFBQVE7Q0FFeEQsSUFBSSxDQUFDLFlBQVksQ0FBQyxTQUFTO0VBQ3pCLE9BQU8sTUFBTSxnREFBZ0QsTUFBTSxHQUFHLFdBQVcsSUFBSTtFQUVyRixJQUFJLGFBQWEsZ0JBQ2YsTUFBTSxJQUFJLHVCQUF1Qiw0QkFBNEI7RUFHL0Q7Q0FDRjtDQUlBLElBQUksQ0FBQyxVQUFVLFlBQVksaUJBQWlCLGVBQWUsTUFBTSxTQUFTO0VBQ3hFLE9BQU8sTUFBTSwwQ0FBMEMsTUFBTSxHQUFHLFdBQVcsSUFBSTtFQUUvRTtDQUNGO0NBR0EsSUFBSSxDQUFDLFVBQVUsYUFBYSx1QkFBTyxJQUFJLEtBQUssR0FBRyxXQUFXLEdBQUc7RUFDM0QsT0FBTyxNQUFNLHVDQUF1QyxNQUFNLEdBQUcsV0FBVyxJQUFJO0VBRTVFO0NBQ0Y7Q0FFQSxNQUFNLFNBQXVCLENBQzNCO0VBQ0UsTUFBTTtFQUNOLE1BQU07R0FBRSxNQUFNO0dBQVUsTUFBTSxVQUFVLElBQUksTUFBTSxPQUFPLFFBQVEsTUFBTSxJQUFJLE1BQU07RUFBRztDQUN0RixDQUNGO0NBRUEsSUFBSSxTQUNGLE9BQU8sS0FBSztFQUFFLE1BQU07RUFBVyxVQUFVLENBQUM7R0FBRSxNQUFNO0dBQVUsTUFBTTtFQUFRLENBQUM7Q0FBRSxDQUFDO0NBR2hGLElBQUk7RUFJRixNQUFNLGFBQThCO0dBQ2xDLFVBQVUsVUFBVSxHQUFHLE1BQU0sS0FBSyxZQUFZO0dBQzlDO0VBQ0Y7RUFFQSxJQUFJLE9BQU8sV0FBVyxRQUFRO0VBRTlCLE1BQU0sTUFBTSxNQUFNLE1BQU0sd0JBQXdCO0dBQzlDLFFBQVE7R0FDUixTQUFTO0lBQ1AsZ0JBQWdCO0lBQ2hCLGVBQWUsVUFBVTtHQUMzQjtHQUNBLE1BQU0sS0FBSyxVQUFVO0lBQ25CO0lBQ0EsYUFBYSxDQUFDLFVBQVU7R0FDMUIsQ0FBQztHQUNELFFBQVEsWUFBWSxRQUFRLGdCQUFnQjtFQUM5QyxDQUFDO0VBSUQsTUFBTSxPQUFPLCtCQUErQixVQUFVLE1BQU0sSUFBSSxLQUFLLENBQUMsQ0FBQyxZQUFZLElBQUksQ0FBQyxDQUFDLENBQUM7RUFFMUYsSUFBSSxDQUFDLElBQUksTUFBTSxNQUFNLE9BQU8sTUFNMUIsTUFBTSxJQUFJLHVCQUF1QixtQkFKL0IsTUFBTSxVQUFVLFVBQWEsaUJBQWlCLEtBQUssS0FBSyxLQUFLLElBQ3pELEtBQUssUUFDTCxRQUFRLElBQUksVUFFd0M7Q0FFOUQsU0FBUyxHQUFHO0VBQ1YsTUFBTSxRQUNKLGFBQWEseUJBQ1QsSUFDQSxJQUFJLHVCQUF1QixxQ0FBcUM7RUFFdEUsT0FBTyxLQUFLLE1BQU0sT0FBTztFQUV6QixJQUFJLGFBQWEsZ0JBQWdCLE1BQU07Q0FDekM7QUFDRiJ9
@@ -1,11 +1,10 @@
1
1
  //#region src/utils/subset-loaders.ts
2
2
  function getSubsetLoaders(subsets, subsetQueries) {
3
- return subsets.reduce((acc, subset) => {
4
- acc[subset] = subsetQueries[subset]?.loaders ?? [];
5
- return acc;
6
- }, {});
3
+ const loaders = {};
4
+ for (const subset of subsets) loaders[subset] = subsetQueries[subset]?.loaders ?? [];
5
+ return loaders;
7
6
  }
8
7
  //#endregion
9
8
  export { getSubsetLoaders };
10
9
 
11
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3Vic2V0LWxvYWRlcnMuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3N1YnNldC1sb2FkZXJzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHR5cGUgU3Vic2V0UXVlcnkgfSBmcm9tIFwic29uYW11XCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdWJzZXRMb2FkZXJzKHN1YnNldHM6IHN0cmluZ1tdLCBzdWJzZXRRdWVyaWVzOiBSZWNvcmQ8c3RyaW5nLCBTdWJzZXRRdWVyeT4pIHtcbiAgcmV0dXJuIHN1YnNldHMucmVkdWNlKFxuICAgIChhY2MsIHN1YnNldCkgPT4ge1xuICAgICAgYWNjW3N1YnNldF0gPSBzdWJzZXRRdWVyaWVzW3N1YnNldF0/LmxvYWRlcnMgPz8gW107XG4gICAgICByZXR1cm4gYWNjO1xuICAgIH0sXG4gICAge30gYXMgUmVjb3JkPHN0cmluZywgU3Vic2V0UXVlcnlbXCJsb2FkZXJzXCJdPixcbiAgKTtcbn1cbiJdLCJtYXBwaW5ncyI6IjtBQUVBLFNBQWdCLGlCQUFpQixTQUFtQixlQUE0QztDQUM5RixPQUFPLFFBQVEsUUFDWixLQUFLLFdBQVc7RUFDZixJQUFJLFVBQVUsY0FBYyxPQUFPLEVBQUUsV0FBVyxDQUFDO0VBQ2pELE9BQU87Q0FDVCxHQUNBLENBQUMsQ0FDSDtBQUNGIn0=
10
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3Vic2V0LWxvYWRlcnMuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3N1YnNldC1sb2FkZXJzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHR5cGUgU3Vic2V0UXVlcnkgfSBmcm9tIFwic29uYW11XCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdWJzZXRMb2FkZXJzKHN1YnNldHM6IHN0cmluZ1tdLCBzdWJzZXRRdWVyaWVzOiBSZWNvcmQ8c3RyaW5nLCBTdWJzZXRRdWVyeT4pIHtcbiAgY29uc3QgbG9hZGVyczogUmVjb3JkPHN0cmluZywgU3Vic2V0UXVlcnlbXCJsb2FkZXJzXCJdPiA9IHt9O1xuXG4gIGZvciAoY29uc3Qgc3Vic2V0IG9mIHN1YnNldHMpIHtcbiAgICBsb2FkZXJzW3N1YnNldF0gPSBzdWJzZXRRdWVyaWVzW3N1YnNldF0/LmxvYWRlcnMgPz8gW107XG4gIH1cblxuICByZXR1cm4gbG9hZGVycztcbn1cbiJdLCJtYXBwaW5ncyI6IjtBQUVBLFNBQWdCLGlCQUFpQixTQUFtQixlQUE0QztDQUM5RixNQUFNLFVBQWtELENBQUM7Q0FFekQsS0FBSyxNQUFNLFVBQVUsU0FDbkIsUUFBUSxVQUFVLGNBQWMsT0FBTyxFQUFFLFdBQVcsQ0FBQztDQUd2RCxPQUFPO0FBQ1QifQ==
@@ -1,8 +1,9 @@
1
+ import { type LogRecord, type Sink } from "@logtape/logtape";
1
2
  /**
2
3
  * 재시작하면 초기화되는 Monit 로그 버퍼.
3
4
  * timestamp/processStartedAt은 web의 dateReviver 변환을 피하고 동등성 비교를 유지하도록 epoch ms를 쓴다.
4
5
  */
5
- import { type LogRecord, type Sink } from "@logtape/logtape";
6
+ import { z } from "zod";
6
7
 
7
8
  const DEFAULT_CAPACITY = 2_000;
8
9
  const DEFAULT_MAX_TEXT_LENGTH = 4_000;
@@ -23,21 +24,28 @@ export interface MonitLogChunk {
23
24
  dropped: number;
24
25
  }
25
26
 
26
- // logtape message 배열은 홀수 길이 — 짝수 인덱스가 템플릿 텍스트, 홀수가 보간 값.
27
- function flattenMessage(message: readonly unknown[]): string {
28
- return message
29
- .map((part, index) => (index % 2 === 0 ? String(part ?? "") : renderValue(part)))
30
- .join("");
31
- }
27
+ // Interpolated log values are arbitrary; this decodes one into its console text.
28
+ const renderedLogValue = z.unknown().transform((value): string => {
29
+ const text = z.string().safeParse(value);
30
+
31
+ if (text.success) return text.data;
32
32
 
33
- function renderValue(value: unknown): string {
34
- if (typeof value === "string") return value;
35
33
  if (value instanceof Error) return value.message;
34
+
36
35
  try {
37
36
  return JSON.stringify(value) ?? String(value);
38
37
  } catch {
39
38
  return String(value);
40
39
  }
40
+ });
41
+
42
+ // logtape message 배열은 홀수 길이 — 짝수 인덱스가 템플릿 텍스트(문자열), 홀수가 보간 값.
43
+ function flattenMessage(message: readonly unknown[]): string {
44
+ return message
45
+ .map((part, index) =>
46
+ index % 2 === 0 ? (z.string().safeParse(part).data ?? "") : renderedLogValue.parse(part),
47
+ )
48
+ .join("");
41
49
  }
42
50
 
43
51
  export class MonitLogBuffer {
@@ -53,9 +61,11 @@ export class MonitLogBuffer {
53
61
  push(record: LogRecord): void {
54
62
  try {
55
63
  let text = flattenMessage(record.message);
64
+
56
65
  if (text.length > this.maxTextLength) {
57
66
  text = `${text.slice(0, this.maxTextLength)}…`;
58
67
  }
68
+
59
69
  this.entries.push({
60
70
  seq: this.nextSeq++,
61
71
  timestamp: record.timestamp,
@@ -63,6 +73,7 @@ export class MonitLogBuffer {
63
73
  category: [...record.category],
64
74
  text,
65
75
  });
76
+
66
77
  if (this.entries.length > this.capacity) {
67
78
  this.entries.splice(0, this.entries.length - this.capacity);
68
79
  }
@@ -75,8 +86,10 @@ export class MonitLogBuffer {
75
86
  after(cursor: number | undefined, limit: number): MonitLogChunk {
76
87
  const latestSeq = this.nextSeq - 1;
77
88
  const oldestSeq = this.entries[0]?.seq ?? this.nextSeq;
89
+
78
90
  if (cursor === undefined) {
79
91
  const entries = this.entries.slice(-limit);
92
+
80
93
  return {
81
94
  entries,
82
95
  nextCursor: entries.at(-1)?.seq ?? latestSeq,
@@ -92,6 +105,7 @@ export class MonitLogBuffer {
92
105
  const dropped = Math.max(oldestSeq - cursor - 1, 0);
93
106
  const startIndex = this.entries.findIndex((entry) => entry.seq > cursor);
94
107
  const entries = startIndex === -1 ? [] : this.entries.slice(startIndex, startIndex + limit);
108
+
95
109
  return {
96
110
  entries,
97
111
  nextCursor: entries.at(-1)?.seq ?? cursor + dropped,
@@ -1,5 +1,6 @@
1
- // 읽기 전용 모니터링 API. 조회 자체는 request log에 남기지 않는다.
2
1
  import { api, BaseFrameClass, DB } from "sonamu";
2
+ // 읽기 전용 모니터링 API. 조회 자체는 request log에 남기지 않는다.
3
+ import { z } from "zod";
3
4
 
4
5
  import { resolveOpenAITransportKind } from "../../utils/providers/openai/openai-transport-config";
5
6
  import { QgridDispatcher } from "../qgrid/qgrid.dispatcher";
@@ -36,6 +37,7 @@ class MonitFrameClass extends BaseFrameClass {
36
37
  const host = process.env.HOST ?? "localhost";
37
38
  const port = process.env.PORT ?? "44900";
38
39
  const conn = activeDbConnection();
40
+
39
41
  return {
40
42
  serverUrl: `http://${host}:${port}`,
41
43
  dbHost: conn.host ?? "localhost",
@@ -49,12 +51,14 @@ class MonitFrameClass extends BaseFrameClass {
49
51
  async monitStats(): Promise<MonitStats> {
50
52
  const windowMinutes = 60;
51
53
  const since = new Date(Date.now() - windowMinutes * 60_000);
54
+
52
55
  return { windowMinutes, providers: await RequestLogModel.providerStatsSince(since) };
53
56
  }
54
57
  }
55
58
 
56
59
  function currentVitals(): MonitVitals {
57
60
  const anthropic = QgridDispatcher.anthropicDispatcher;
61
+
58
62
  return {
59
63
  openaiInFlight: QgridDispatcher.openaiDispatcher?.inFlight ?? 0,
60
64
  openaiQuotaByToken: QgridDispatcher.openaiDispatcher?.getQuotaSnapshot() ?? [],
@@ -68,15 +72,28 @@ function currentVitals(): MonitVitals {
68
72
 
69
73
  // 실제 활성 knex 연결에서 읽는다 — dev 서버의 통합 테스트 러너가 process.env.SONAMU_DB_NAME 을
70
74
  // 테스트 DB 이름으로 덮어쓰므로 env 는 신뢰할 수 없다. DB 미초기화(부팅 전) 시에만 env 폴백.
71
- function activeDbConnection(): { host?: string; database?: string } {
75
+ interface DbConnectionInfo {
76
+ host?: string;
77
+ database?: string;
78
+ }
79
+
80
+ // knex accepts a connection string, object, or factory; only the object form carries these fields.
81
+ const dbConnectionInfoSchema = z.looseObject({
82
+ host: z.string().optional(),
83
+ database: z.string().optional(),
84
+ });
85
+
86
+ function activeDbConnection(): DbConnectionInfo {
72
87
  try {
73
- const connection = DB.getDBConfig("w").connection;
74
- if (typeof connection === "object" && connection !== null) {
75
- return connection as { host?: string; database?: string };
88
+ const connection = dbConnectionInfoSchema.safeParse(DB.getDBConfig("w").connection);
89
+
90
+ if (connection.success) {
91
+ return { host: connection.data.host, database: connection.data.database };
76
92
  }
77
93
  } catch {
78
94
  // DB config 미초기화 — env 폴백으로 진행
79
95
  }
96
+
80
97
  return { host: process.env.SONAMU_DB_HOST, database: process.env.SONAMU_DB_NAME };
81
98
  }
82
99
 
@@ -13,6 +13,7 @@ export const MonitLogEntry = z.object({
13
13
  category: z.array(z.string()),
14
14
  text: z.string(),
15
15
  });
16
+
16
17
  export type MonitLogEntry = z.infer<typeof MonitLogEntry>;
17
18
 
18
19
  // 폴링에 편승하는 라이브 카운트 — 깊은 토큰 진단은 audit 대시보드(별도)의 몫이고,
@@ -40,6 +41,7 @@ export const MonitVitals = z.object({
40
41
  // 지금 실행 중인 Claude Code 프로세스 수
41
42
  anthropicInFlight: z.number(),
42
43
  });
44
+
43
45
  export type MonitVitals = z.infer<typeof MonitVitals>;
44
46
 
45
47
  export const MonitLogChunk = z.object({
@@ -50,6 +52,7 @@ export const MonitLogChunk = z.object({
50
52
  dropped: z.number(),
51
53
  vitals: MonitVitals,
52
54
  });
55
+
53
56
  export type MonitLogChunk = z.infer<typeof MonitLogChunk>;
54
57
 
55
58
  // 프로세스 단위 정적 환경 정보 — 어느 서버/DB 를 보고 있는지 한눈에 확인하는 용도.
@@ -63,6 +66,7 @@ export const MonitServerInfo = z.object({
63
66
  transport: z.string(),
64
67
  }),
65
68
  });
69
+
66
70
  export type MonitServerInfo = z.infer<typeof MonitServerInfo>;
67
71
 
68
72
  // 최근 1시간 provider 별 요청 통계 — request_logs 를 집계한다. vitals 와 달리 DB 를
@@ -74,10 +78,12 @@ export const MonitProviderStats = z.object({
74
78
  inputTokens: z.number(),
75
79
  cacheReadTokens: z.number(),
76
80
  });
81
+
77
82
  export type MonitProviderStats = z.infer<typeof MonitProviderStats>;
78
83
 
79
84
  export const MonitStats = z.object({
80
85
  windowMinutes: z.number(),
81
86
  providers: z.array(MonitProviderStats),
82
87
  });
88
+
83
89
  export type MonitStats = z.infer<typeof MonitStats>;
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
 
3
- import { decideConvRouting, systemHash } from "./conv-routing";
3
+ import { decideConvRouting, issueConvContext, systemHash } from "./conv-routing";
4
4
  import { type QueryInput } from "./qgrid.types";
5
5
 
6
6
  function input(overrides: Partial<QueryInput> = {}): QueryInput {
@@ -104,7 +104,7 @@ describe("decideConvRouting", () => {
104
104
  },
105
105
  },
106
106
  }),
107
- { directOpenAI: true, modelNamespace: model },
107
+ { directProvider: "openai", modelNamespace: model },
108
108
  );
109
109
 
110
110
  expect(decision.coldHistory).toEqual([{ role: "user", content: "first" }]);
@@ -128,7 +128,7 @@ describe("decideConvRouting", () => {
128
128
  },
129
129
  },
130
130
  }),
131
- { directOpenAI: true, modelNamespace: "openai/gpt-5.5" },
131
+ { directProvider: "openai", modelNamespace: "openai/gpt-5.5" },
132
132
  );
133
133
 
134
134
  expect(decision.promptCacheKey).toBe(cacheAffinityKey);
@@ -141,11 +141,83 @@ describe("decideConvRouting", () => {
141
141
 
142
142
  it("direct OpenAI 요청에 affinity key 가 없으면 cache key 를 만들지 않는다", () => {
143
143
  const decision = decideConvRouting(input({ model: "openai/gpt-5.5" }), {
144
- directOpenAI: true,
144
+ directProvider: "openai",
145
145
  modelNamespace: "openai/gpt-5.5",
146
146
  });
147
147
 
148
148
  expect(decision.promptCacheKey).toBeUndefined();
149
149
  expect(decision.preferredTokenId).toBeUndefined();
150
150
  });
151
+
152
+ it("direct Grok 도 epoch=-1 좌표를 같은 규칙으로 검증하고 재발급한다", () => {
153
+ const cacheAffinityKey = "c".repeat(64);
154
+ const model = "grok/grok-4.7";
155
+ const decision = decideConvRouting(
156
+ input({
157
+ prompt: "next",
158
+ model,
159
+ system: "same",
160
+ cacheAffinityKey,
161
+ runContext: {
162
+ threadCoord: {
163
+ workerId: 9,
164
+ threadId: cacheAffinityKey,
165
+ epoch: -1,
166
+ systemHash: systemHash("same", model),
167
+ },
168
+ },
169
+ }),
170
+ { directProvider: "grok", modelNamespace: model },
171
+ );
172
+
173
+ expect(decision.systemHash).toBe(systemHash("same", model));
174
+ expect(decision.promptCacheKey).toBe(cacheAffinityKey);
175
+ expect(decision.preferredTokenId).toBe(9);
176
+ expect(issueConvContext({ workerId: 11, threadId: "upstream", epoch: 0 }, decision)).toEqual({
177
+ workerId: 11,
178
+ threadId: cacheAffinityKey,
179
+ epoch: -1,
180
+ systemHash: systemHash("same", model),
181
+ });
182
+ });
183
+
184
+ it("OpenAI 좌표는 같은 system/model 이름이라도 Grok 요청에서 재사용되지 않는다", () => {
185
+ const cacheAffinityKey = "d".repeat(64);
186
+ const decision = decideConvRouting(
187
+ input({
188
+ model: "grok/gpt-5.5",
189
+ system: "same",
190
+ cacheAffinityKey,
191
+ runContext: {
192
+ threadCoord: {
193
+ workerId: 3,
194
+ threadId: cacheAffinityKey,
195
+ epoch: -1,
196
+ systemHash: systemHash("same", "openai/gpt-5.5"),
197
+ },
198
+ },
199
+ }),
200
+ { directProvider: "grok", modelNamespace: "grok/gpt-5.5" },
201
+ );
202
+
203
+ expect(decision.promptCacheKey).toBe(cacheAffinityKey);
204
+ expect(decision.preferredTokenId).toBeUndefined();
205
+ });
206
+
207
+ it("directProvider 가 없으면 cache key 와 namespace 를 쓰지 않는다", () => {
208
+ const decision = decideConvRouting(
209
+ input({ model: "anthropic/claude-sonnet-4-6", system: "same", cacheAffinityKey: "e" }),
210
+ );
211
+
212
+ expect(decision.systemHash).toBe(systemHash("same"));
213
+ expect(decision.promptCacheKey).toBeUndefined();
214
+ });
215
+
216
+ it("modelNamespace 가 없으면 input.model 로 namespace 를 정한다", () => {
217
+ const decision = decideConvRouting(input({ model: "grok/grok-4.7", system: "s" }), {
218
+ directProvider: "grok",
219
+ });
220
+
221
+ expect(decision.systemHash).toBe(systemHash("s", "grok/grok-4.7"));
222
+ });
151
223
  });