@cartanova/qgrid-cli 2.10.10 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/dist/_virtual/_rolldown/runtime.js +1 -10
- package/bundle/dist/application/monit/log-buffer.js +12 -6
- package/bundle/dist/application/monit/monit.frame.js +11 -3
- package/bundle/dist/application/monit/monit.types.js +1 -1
- package/bundle/dist/application/qgrid/conv-routing.js +9 -6
- package/bundle/dist/application/qgrid/expired-token-reminder.js +2 -2
- package/bundle/dist/application/qgrid/oauth.js +31 -4
- package/bundle/dist/application/qgrid/qgrid-image-generation.js +1 -1
- package/bundle/dist/application/qgrid/qgrid-response-format.js +21 -19
- package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +40 -33
- package/bundle/dist/application/qgrid/qgrid.dispatcher.js +128 -93
- package/bundle/dist/application/qgrid/qgrid.frame.js +930 -49
- package/bundle/dist/application/qgrid/qgrid.types.js +212 -5
- package/bundle/dist/application/qgrid/schema-prompt.js +75 -48
- package/bundle/dist/application/qgrid/slack-user-map.js +1 -1
- package/bundle/dist/application/qgrid/token-death.js +1 -1
- package/bundle/dist/application/qgrid/token-subscriber.js +83 -30
- package/bundle/dist/application/qgrid/token-trigger-setup.js +1 -1
- package/bundle/dist/application/qgrid/token-window-keepalive.js +8 -6
- package/bundle/dist/application/qgrid/tool-emulation-schema.js +13 -13
- package/bundle/dist/application/qgrid/tool-emulation.js +19 -15
- package/bundle/dist/application/request-log/json-schema-type-text.js +29 -12
- package/bundle/dist/application/request-log/request-log.model.js +83 -70
- package/bundle/dist/application/request-log/request-log.types.js +1 -1
- package/bundle/dist/application/request-log/zod-code-format.js +1 -1
- package/bundle/dist/application/request-log-step/request-log-step.model.js +1 -1
- package/bundle/dist/application/request-log-step/request-log-step.types.js +1 -1
- package/bundle/dist/application/setting/setting.constant.js +1 -1
- package/bundle/dist/application/setting/setting.model.js +2 -2
- package/bundle/dist/application/setting/setting.store.js +2 -2
- package/bundle/dist/application/setting/setting.types.js +1 -1
- package/bundle/dist/application/sonamu.generated.js +32 -16
- package/bundle/dist/application/sonamu.generated.sso.js +1 -1
- package/bundle/dist/application/token/token.model.js +26 -9
- package/bundle/dist/application/token/token.types.js +20 -3
- package/bundle/dist/i18n/en.js +15 -1
- package/bundle/dist/i18n/ko.js +15 -1
- package/bundle/dist/i18n/sd.generated.js +1 -1
- package/bundle/dist/migrations/20260807133553_manual__backfill_request_log_cost.js +8 -6
- package/bundle/dist/server-bootstrap.js +4 -2
- package/bundle/dist/server-error-handler.js +1 -1
- package/bundle/dist/sonamu.config.js +37 -8
- package/bundle/dist/startup-migrations.js +17 -7
- package/bundle/dist/testing/global.js +1 -1
- package/bundle/dist/testing/schema-bench.js +0 -0
- package/bundle/dist/testing/test-database-name.js +1 -1
- package/bundle/dist/utils/providers/anthropic/anthropic-constants.js +1 -1
- package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +11 -5
- package/bundle/dist/utils/providers/anthropic/anthropic-quota.js +4 -4
- package/bundle/dist/utils/providers/anthropic/anthropic-thinking.js +1 -1
- package/bundle/dist/utils/providers/anthropic/claude-session.js +20 -19
- package/bundle/dist/utils/providers/anthropic/fence-strip.js +1 -1
- package/bundle/dist/utils/providers/anthropic/stream-json-adapter.js +49 -23
- package/bundle/dist/utils/providers/common/credentials.js +5 -1
- package/bundle/dist/utils/providers/common/effort.js +3 -3
- package/bundle/dist/utils/providers/common/model-cost.js +69 -14
- package/bundle/dist/utils/providers/common/provider-types.js +29 -1
- package/bundle/dist/utils/providers/common/schema-validation.js +78 -40
- package/bundle/dist/utils/providers/common/smooth-weighted-round-robin.js +1 -1
- package/bundle/dist/utils/providers/common/strictifier.js +62 -43
- package/bundle/dist/utils/providers/common/thinking.js +3 -2
- package/bundle/dist/utils/providers/common/ttft.js +1 -1
- package/bundle/dist/utils/providers/grok/grok-backend-protocol.js +427 -0
- package/bundle/dist/utils/providers/grok/grok-constants.js +55 -0
- package/bundle/dist/utils/providers/grok/grok-direct-client.js +196 -0
- package/bundle/dist/utils/providers/grok/grok-dispatcher.js +1313 -0
- package/bundle/dist/utils/providers/grok/grok-headers.js +118 -0
- package/bundle/dist/utils/providers/grok/grok-media-client.js +420 -0
- package/bundle/dist/utils/providers/grok/grok-models.js +114 -0
- package/bundle/dist/utils/providers/grok/grok-oauth.js +455 -0
- package/bundle/dist/utils/providers/grok/grok-quota.js +119 -0
- package/bundle/dist/utils/providers/grok/grok-refresh.js +192 -0
- package/bundle/dist/utils/providers/grok/grok-types.js +186 -0
- package/bundle/dist/utils/providers/grok/grok-voice-client.js +199 -0
- package/bundle/dist/utils/providers/grok/index.js +11 -0
- package/bundle/dist/utils/providers/openai/openai-backend-protocol.js +111 -83
- package/bundle/dist/utils/providers/openai/openai-callback-relay.js +3 -2
- package/bundle/dist/utils/providers/openai/openai-constants.js +1 -1
- package/bundle/dist/utils/providers/openai/openai-direct-client.js +23 -7
- package/bundle/dist/utils/providers/openai/openai-dispatcher.js +143 -106
- package/bundle/dist/utils/providers/openai/openai-image-generation.js +48 -33
- package/bundle/dist/utils/providers/openai/openai-oauth.js +28 -13
- package/bundle/dist/utils/providers/openai/openai-quota.js +38 -27
- package/bundle/dist/utils/providers/openai/openai-refresh.js +17 -9
- package/bundle/dist/utils/providers/openai/openai-sse.js +1 -1
- package/bundle/dist/utils/providers/openai/openai-transport-config.js +1 -1
- package/bundle/dist/utils/quiet-hours.js +1 -1
- package/bundle/dist/utils/slack-notify.js +14 -8
- package/bundle/dist/utils/subset-loaders.js +4 -5
- package/bundle/src/application/monit/log-buffer.ts +23 -9
- package/bundle/src/application/monit/monit.frame.ts +22 -5
- package/bundle/src/application/monit/monit.types.ts +6 -0
- package/bundle/src/application/qgrid/conv-routing.test.ts +76 -4
- package/bundle/src/application/qgrid/conv-routing.ts +35 -9
- package/bundle/src/application/qgrid/expired-token-reminder.ts +9 -1
- package/bundle/src/application/qgrid/oauth.ts +51 -15
- package/bundle/src/application/qgrid/qgrid-image-generation.ts +9 -0
- package/bundle/src/application/qgrid/qgrid-response-format.ts +50 -25
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +19 -0
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +84 -40
- package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +97 -0
- package/bundle/src/application/qgrid/qgrid.dispatcher.ts +274 -126
- package/bundle/src/application/qgrid/qgrid.frame.test.ts +1013 -3
- package/bundle/src/application/qgrid/qgrid.frame.ts +1415 -60
- package/bundle/src/application/qgrid/qgrid.types.ts +335 -0
- package/bundle/src/application/qgrid/schema-prompt.ts +105 -41
- package/bundle/src/application/qgrid/slack-user-map.ts +5 -0
- package/bundle/src/application/qgrid/token-death.ts +4 -0
- package/bundle/src/application/qgrid/token-subscriber.test.ts +21 -19
- package/bundle/src/application/qgrid/token-subscriber.ts +186 -53
- package/bundle/src/application/qgrid/token-trigger-setup.ts +2 -0
- package/bundle/src/application/qgrid/token-window-keepalive.ts +49 -6
- package/bundle/src/application/qgrid/tool-emulation-schema.ts +33 -29
- package/bundle/src/application/qgrid/tool-emulation.ts +52 -27
- package/bundle/src/application/request-log/json-schema-type-text.test.ts +5 -5
- package/bundle/src/application/request-log/json-schema-type-text.ts +81 -26
- package/bundle/src/application/request-log/request-log.model.test.ts +111 -4
- package/bundle/src/application/request-log/request-log.model.ts +277 -146
- package/bundle/src/application/request-log/request-log.types.ts +6 -0
- package/bundle/src/application/request-log/zod-code-format.ts +11 -0
- package/bundle/src/application/request-log-step/request-log-step.model.ts +1 -0
- package/bundle/src/application/request-log-step/request-log-step.types.ts +2 -0
- package/bundle/src/application/setting/setting.constant.ts +9 -0
- package/bundle/src/application/setting/setting.model.ts +12 -2
- package/bundle/src/application/setting/setting.store.ts +5 -1
- package/bundle/src/application/setting/setting.types.ts +8 -0
- package/bundle/src/application/sonamu.generated.http +133 -0
- package/bundle/src/application/sonamu.generated.sso.ts +2 -0
- package/bundle/src/application/sonamu.generated.ts +15 -0
- package/bundle/src/application/token/token.identity.test.ts +20 -0
- package/bundle/src/application/token/token.model.ts +66 -7
- package/bundle/src/application/token/token.types.ts +24 -1
- package/bundle/src/i18n/en.ts +19 -0
- package/bundle/src/i18n/ko.ts +21 -0
- package/bundle/src/i18n/sd.generated.ts +23 -2
- package/bundle/src/migrations/20260807133553_manual__backfill_request_log_cost.ts +16 -8
- package/bundle/src/server-bootstrap.ts +4 -2
- package/bundle/src/server-error-handler.ts +1 -0
- package/bundle/src/sonamu.config.ts +69 -7
- package/bundle/src/startup-migrations.ts +27 -9
- package/bundle/src/testing/global.ts +20 -0
- package/bundle/src/testing/schema-bench.ts +105 -30
- package/bundle/src/testing/test-database-name.ts +2 -0
- package/bundle/src/utils/providers/anthropic/anthropic-constants.ts +8 -0
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +41 -6
- package/bundle/src/utils/providers/anthropic/anthropic-quota.ts +7 -3
- package/bundle/src/utils/providers/anthropic/anthropic-thinking.ts +6 -0
- package/bundle/src/utils/providers/anthropic/claude-session.ts +58 -24
- package/bundle/src/utils/providers/anthropic/fence-strip.ts +11 -0
- package/bundle/src/utils/providers/anthropic/stream-json-adapter.ts +110 -45
- package/bundle/src/utils/providers/common/credentials.ts +8 -0
- package/bundle/src/utils/providers/common/effort.ts +9 -2
- package/bundle/src/utils/providers/common/model-cost.test.ts +48 -1
- package/bundle/src/utils/providers/common/model-cost.ts +259 -158
- package/bundle/src/utils/providers/common/provider-dispatcher.ts +98 -2
- package/bundle/src/utils/providers/common/provider-types.ts +46 -3
- package/bundle/src/utils/providers/common/schema-validation.test.ts +5 -1
- package/bundle/src/utils/providers/common/schema-validation.ts +124 -56
- package/bundle/src/utils/providers/common/smooth-weighted-round-robin.ts +4 -0
- package/bundle/src/utils/providers/common/strictifier.ts +185 -59
- package/bundle/src/utils/providers/common/thinking.ts +2 -2
- package/bundle/src/utils/providers/common/ttft.ts +4 -2
- package/bundle/src/utils/providers/grok/__fixtures__/golden-responses-1.0.60.json +164 -0
- package/bundle/src/utils/providers/grok/grok-backend-protocol.test.ts +325 -0
- package/bundle/src/utils/providers/grok/grok-backend-protocol.ts +721 -0
- package/bundle/src/utils/providers/grok/grok-constants.ts +105 -0
- package/bundle/src/utils/providers/grok/grok-direct-client.test.ts +179 -0
- package/bundle/src/utils/providers/grok/grok-direct-client.ts +313 -0
- package/bundle/src/utils/providers/grok/grok-dispatcher.test.ts +1395 -0
- package/bundle/src/utils/providers/grok/grok-dispatcher.ts +2105 -0
- package/bundle/src/utils/providers/grok/grok-headers.test.ts +149 -0
- package/bundle/src/utils/providers/grok/grok-headers.ts +199 -0
- package/bundle/src/utils/providers/grok/grok-media-client.test.ts +446 -0
- package/bundle/src/utils/providers/grok/grok-media-client.ts +703 -0
- package/bundle/src/utils/providers/grok/grok-models.test.ts +96 -0
- package/bundle/src/utils/providers/grok/grok-models.ts +161 -0
- package/bundle/src/utils/providers/grok/grok-oauth.test.ts +406 -0
- package/bundle/src/utils/providers/grok/grok-oauth.ts +771 -0
- package/bundle/src/utils/providers/grok/grok-quota.test.ts +142 -0
- package/bundle/src/utils/providers/grok/grok-quota.ts +198 -0
- package/bundle/src/utils/providers/grok/grok-refresh.test.ts +239 -0
- package/bundle/src/utils/providers/grok/grok-refresh.ts +325 -0
- package/bundle/src/utils/providers/grok/grok-types.test.ts +252 -0
- package/bundle/src/utils/providers/grok/grok-types.ts +374 -0
- package/bundle/src/utils/providers/grok/grok-voice-client.test.ts +321 -0
- package/bundle/src/utils/providers/grok/grok-voice-client.ts +284 -0
- package/bundle/src/utils/providers/grok/index.ts +20 -0
- package/bundle/src/utils/providers/openai/openai-backend-protocol.ts +221 -137
- package/bundle/src/utils/providers/openai/openai-callback-relay.ts +12 -1
- package/bundle/src/utils/providers/openai/openai-constants.ts +2 -0
- package/bundle/src/utils/providers/openai/openai-direct-client.ts +111 -21
- package/bundle/src/utils/providers/openai/openai-dispatcher.ts +322 -169
- package/bundle/src/utils/providers/openai/openai-image-generation.ts +116 -36
- package/bundle/src/utils/providers/openai/openai-oauth.ts +48 -20
- package/bundle/src/utils/providers/openai/openai-quota.ts +77 -46
- package/bundle/src/utils/providers/openai/openai-refresh.ts +42 -18
- package/bundle/src/utils/providers/openai/openai-sse.ts +27 -3
- package/bundle/src/utils/providers/openai/openai-transport-config.ts +2 -0
- package/bundle/src/utils/quiet-hours.ts +12 -1
- package/bundle/src/utils/slack-notify.ts +44 -13
- package/bundle/src/utils/subset-loaders.ts +7 -7
- package/bundle/web-dist/client/assets/clsx-5XM_pHvN.js +1 -0
- package/bundle/web-dist/client/assets/index-BA7uQ-6c.js +31 -0
- package/bundle/web-dist/client/assets/index-Be2qCZmI.css +1 -0
- package/bundle/web-dist/client/assets/logs-C47OJGEI.js +1 -0
- package/bundle/web-dist/client/assets/monit-BS9no0dU.js +4 -0
- package/bundle/web-dist/client/assets/plus-sdACTfH0.js +1 -0
- package/bundle/web-dist/client/assets/refresh-cw-CY8o_1cT.js +1 -0
- package/bundle/web-dist/client/assets/request-model-BRtFuZvj.js +1 -0
- package/bundle/web-dist/client/assets/routes-kqgkUxE8.js +5 -0
- package/bundle/web-dist/client/assets/{services.generated-NP-ValHd.js → services.generated-CefiDXEv.js} +5 -5
- package/bundle/web-dist/client/assets/settings-DNDvFGSw.js +1 -0
- package/bundle/web-dist/client/assets/show-u8Np69q3.js +2 -0
- package/bundle/web-dist/client/assets/tokens-QvP410NW.js +1 -0
- package/bundle/web-dist/client/assets/total-cost-MnfKU8IN.js +1 -0
- package/bundle/web-dist/client/assets/use-oauth-login-flow-Bzdh28Ws.js +1 -0
- package/bundle/web-dist/client/assets/use-update-token-mutation-CfJKaxmR.js +1 -0
- package/bundle/web-dist/client/assets/vendor-react-CUFFrVN9.js +244 -0
- package/bundle/web-dist/client/assets/vendor-tanstack-Bf_jag9G.js +1 -0
- package/bundle/web-dist/client/index.html +6 -6
- package/bundle/web-dist/server/assets/clsx-D_N5PN_2.js +16 -0
- package/bundle/web-dist/server/assets/{lazyRouteComponent-CgBdabgd.js → lazyRouteComponent-D8iTIHyn.js} +129 -2
- package/bundle/web-dist/server/assets/logs-B3OTd9hy.js +825 -0
- package/bundle/web-dist/server/assets/{monit-ZPt66W5M.js → monit-B2hqorPe.js} +385 -126
- package/bundle/web-dist/server/assets/plus-DwG7h9kq.js +28 -0
- package/bundle/web-dist/server/assets/{react-dom-Ds75e4Jl.js → react-dom-BIYQzBqG.js} +2 -129
- package/bundle/web-dist/server/assets/refresh-cw-mMBkwOq0.js +44 -0
- package/bundle/web-dist/server/assets/{request-model-DjGldb-h.js → request-model-I6OdODSH.js} +15 -6
- package/bundle/web-dist/server/assets/{routes-Ct-k7nBA.js → routes-B95YlUv2.js} +760 -213
- package/bundle/web-dist/server/assets/{services.generated-BA4AcAf5.js → services.generated-DQATJ6qf.js} +12820 -12194
- package/bundle/web-dist/server/assets/settings-C3gbGk0m.js +830 -0
- package/bundle/web-dist/server/assets/{show-LSFIzvO2.js → show-Bxaj3rhH.js} +1350 -418
- package/bundle/web-dist/server/assets/tokens-CZjH3cB7.js +1038 -0
- package/bundle/web-dist/server/assets/total-cost-fTE9Xy82.js +18 -0
- package/bundle/web-dist/server/assets/use-oauth-login-flow-CKDHgc3U.js +2379 -0
- package/bundle/web-dist/server/assets/{use-update-token-mutation-pkArIzCP.js → use-update-token-mutation-BEbgOzaa.js} +1 -1
- package/bundle/web-dist/server/entry-server.generated.js +4295 -22810
- package/dist/cli.js +9 -9
- package/package.json +4 -11
- package/postinstall.mjs +12 -0
- package/skills/qgrid/SKILL.md +1 -0
- package/skills/qgrid/references/cli-env-and-server-boot.md +4 -1
- package/skills/qgrid/references/decision-rationale.md +23 -0
- package/skills/qgrid/references/grok-runtime.md +89 -0
- package/skills/qgrid/references/provider-runtime-differences.md +30 -29
- package/skills/qgrid/references/repo-map.md +10 -0
- package/skills/qgrid/references/token-auth-quota-lifecycle.md +56 -3
- package/bundle/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +0 -406
- package/bundle/dist/node_modules/.pnpm/@vitest_expect@4.1.10/node_modules/@vitest/expect/dist/index.js +0 -1507
- package/bundle/dist/node_modules/.pnpm/@vitest_pretty-format@4.1.10/node_modules/@vitest/pretty-format/dist/index.js +0 -887
- package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/chunk-artifact.js +0 -2756
- package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/index.js +0 -8
- package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/utils.js +0 -8
- package/bundle/dist/node_modules/.pnpm/@vitest_snapshot@4.1.10/node_modules/@vitest/snapshot/dist/index.js +0 -922
- package/bundle/dist/node_modules/.pnpm/@vitest_spy@4.1.10/node_modules/@vitest/spy/dist/index.js +0 -386
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +0 -121
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/constants.js +0 -51
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/diff.js +0 -1317
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/display.js +0 -561
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/error.js +0 -40
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/helpers.js +0 -272
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/offset.js +0 -27
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/serialize.js +0 -77
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/source-map.js +0 -381
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/timers.js +0 -51
- package/bundle/dist/node_modules/.pnpm/chai@6.2.2/node_modules/chai/index.js +0 -2986
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.js +0 -10
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.js +0 -109
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.js +0 -10
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.js +0 -10
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.js +0 -10
- package/bundle/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +0 -1126
- package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.js +0 -21
- package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +0 -432
- package/bundle/dist/node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.js +0 -517
- package/bundle/dist/node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js +0 -101
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- package/bundle/dist/testing/setup-mocks.js +0 -16
- package/bundle/src/testing/setup-mocks.ts +0 -44
- package/bundle/web-dist/client/assets/index-Bw2s88Ot.css +0 -1
- package/bundle/web-dist/client/assets/index-DZwzUfI-.js +0 -106
- package/bundle/web-dist/client/assets/logs-Cog79DU5.js +0 -1
- package/bundle/web-dist/client/assets/monit-2auznBys.js +0 -1
- package/bundle/web-dist/client/assets/plus-B62CuqT8.js +0 -1
- package/bundle/web-dist/client/assets/refresh-cw-NNcU0Cmq.js +0 -1
- package/bundle/web-dist/client/assets/request-model-CojtinqK.js +0 -1
- package/bundle/web-dist/client/assets/routes-B0lTeLK-.js +0 -5
- package/bundle/web-dist/client/assets/settings-D8ZxZGSJ.js +0 -1
- package/bundle/web-dist/client/assets/show-CFSERlnM.js +0 -2
- package/bundle/web-dist/client/assets/tokens-CZXUyI7O.js +0 -1
- package/bundle/web-dist/client/assets/use-oauth-login-flow-hboOs3wG.js +0 -1
- package/bundle/web-dist/client/assets/use-update-token-mutation-BQHS0byG.js +0 -1
- package/bundle/web-dist/client/assets/vendor-react-DH4kUfK2.js +0 -9
- package/bundle/web-dist/client/assets/vendor-tanstack-DJRQAbrY.js +0 -1
- package/bundle/web-dist/server/assets/logs-BMyR98rU.js +0 -509
- package/bundle/web-dist/server/assets/plus-BZ9I0VgC.js +0 -19
- package/bundle/web-dist/server/assets/refresh-cw-CztCFis-.js +0 -23
- package/bundle/web-dist/server/assets/settings-CBUZ47Xx.js +0 -461
- package/bundle/web-dist/server/assets/tokens-DxrBW512.js +0 -448
- package/bundle/web-dist/server/assets/use-oauth-login-flow-Gn8flMK5.js +0 -178
- package/dist/cli.d.ts +0 -10
- /package/bundle/web-dist/client/assets/{cost-DH2jZbrw.js → cost-DB3HbU7T.js} +0 -0
- /package/bundle/web-dist/client/assets/{preload-helper-ca-nBW7U.js → preload-helper-DWTEM3RW.js} +0 -0
- /package/bundle/web-dist/server/assets/{cost-eEHeTRT5.js → cost-BC9yzyA9.js} +0 -0
|
@@ -8,14 +8,23 @@
|
|
|
8
8
|
* - recursive 처리 (nested objects, arrays, allOf/anyOf/oneOf)
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
|
|
11
13
|
import {
|
|
12
14
|
SCHEMA_ARRAY_KEYWORDS,
|
|
13
15
|
SCHEMA_MAP_KEYWORDS,
|
|
14
16
|
SCHEMA_SINGLE_KEYWORDS,
|
|
15
17
|
UNSUPPORTED_REFERENCE_KEYWORDS,
|
|
16
18
|
} from "./json-schema-keywords";
|
|
19
|
+
import {
|
|
20
|
+
isJsonObject,
|
|
21
|
+
type JsonObject,
|
|
22
|
+
type JsonValue,
|
|
23
|
+
type ReadonlyJsonObject,
|
|
24
|
+
} from "./provider-types";
|
|
17
25
|
|
|
18
|
-
|
|
26
|
+
/** An object-form JSON Schema node. Boolean schemas and malformed members stay plain JSON values. */
|
|
27
|
+
export type JsonSchema = JsonObject;
|
|
19
28
|
|
|
20
29
|
export interface StrictifierOptions {
|
|
21
30
|
provider?: string;
|
|
@@ -31,14 +40,24 @@ export class StrictifierError extends Error {
|
|
|
31
40
|
}
|
|
32
41
|
}
|
|
33
42
|
|
|
34
|
-
export function strictify(
|
|
43
|
+
export function strictify(input: ReadonlyJsonObject, options: StrictifierOptions = {}): JsonSchema {
|
|
44
|
+
// Work on the JSON the provider will receive: a fresh copy, with undefined members dropped as
|
|
45
|
+
// serialization drops them. JSON.parse without a reviver yields only JSON values.
|
|
46
|
+
const serialized: JsonValue = JSON.parse(JSON.stringify(input));
|
|
47
|
+
|
|
48
|
+
if (!isSchemaObject(serialized)) throw new StrictifierError("schema must be an object", "$");
|
|
49
|
+
const schema = serialized;
|
|
50
|
+
|
|
35
51
|
if (options.provider === "openai" || options.provider === "anthropic") {
|
|
36
52
|
assertNormalizationCompatibility(schema, options.provider);
|
|
37
53
|
}
|
|
54
|
+
|
|
38
55
|
const result = strictifyNode(schema, "$", options.provider);
|
|
56
|
+
|
|
39
57
|
if (options.provider === "openai" || options.provider === "anthropic") {
|
|
40
58
|
assertNormalizationCompatibility(result, options.provider);
|
|
41
59
|
}
|
|
60
|
+
|
|
42
61
|
return result;
|
|
43
62
|
}
|
|
44
63
|
|
|
@@ -70,6 +89,7 @@ function positionEntries(keywords: readonly string[]): ReadonlyArray<readonly [s
|
|
|
70
89
|
|
|
71
90
|
const SCHEMA_SCAN_MAP_KEYWORDS = positionEntries(SCHEMA_MAP_KEYWORDS);
|
|
72
91
|
const SCHEMA_SCAN_ARRAY_KEYWORDS = positionEntries(SCHEMA_ARRAY_KEYWORDS);
|
|
92
|
+
|
|
73
93
|
// items/additionalItems 는 tuple 분기에서 직접 다루므로 단일 위치 스캔에서 제외한다.
|
|
74
94
|
const SCHEMA_SCAN_SINGLE_KEYWORDS = positionEntries(
|
|
75
95
|
SCHEMA_SINGLE_KEYWORDS.filter((keyword) => keyword !== "items" && keyword !== "additionalItems"),
|
|
@@ -88,6 +108,7 @@ function assertNormalizationCompatibility(
|
|
|
88
108
|
provider: "openai" | "anthropic",
|
|
89
109
|
): void {
|
|
90
110
|
const references: Array<{ value: string; path: string }> = [];
|
|
111
|
+
|
|
91
112
|
const stack: Array<{ node: JsonSchema; path: string; normalizable: boolean }> = [
|
|
92
113
|
{ node: schema, path: "$", normalizable: true },
|
|
93
114
|
];
|
|
@@ -103,19 +124,22 @@ function assertNormalizationCompatibility(
|
|
|
103
124
|
collectSchemaReference(current, references);
|
|
104
125
|
|
|
105
126
|
if (legacyTuple || prefixTuple) {
|
|
106
|
-
const tuple =
|
|
127
|
+
const tuple = legacyTuple ? itemsValue : prefixTuple ? prefixItemsValue : [];
|
|
128
|
+
|
|
107
129
|
if (provider === "anthropic" && tuple.length > 0) {
|
|
108
130
|
throw new StrictifierError(
|
|
109
131
|
"positional tuple schemas are not supported on Anthropic because Claude Code cannot preserve item positions",
|
|
110
132
|
current.path,
|
|
111
133
|
);
|
|
112
134
|
}
|
|
135
|
+
|
|
113
136
|
if (!current.normalizable) {
|
|
114
137
|
throw new StrictifierError(
|
|
115
138
|
"positional tuple schemas are not supported in this schema position",
|
|
116
139
|
current.path,
|
|
117
140
|
);
|
|
118
141
|
}
|
|
142
|
+
|
|
119
143
|
if (ownValue(current.node, "type") !== "array") {
|
|
120
144
|
throw new StrictifierError(
|
|
121
145
|
'positional tuple schemas must declare type "array"; express nullable tuples with anyOf',
|
|
@@ -126,7 +150,9 @@ function assertNormalizationCompatibility(
|
|
|
126
150
|
|
|
127
151
|
for (const [keyword, keywordNormalizable] of SCHEMA_SCAN_MAP_KEYWORDS) {
|
|
128
152
|
const schemas = ownValue(current.node, keyword);
|
|
153
|
+
|
|
129
154
|
if (!isSchemaObject(schemas)) continue;
|
|
155
|
+
|
|
130
156
|
for (const [name, child] of Object.entries(schemas)) {
|
|
131
157
|
if (!isSchemaObject(child)) continue;
|
|
132
158
|
stack.push({
|
|
@@ -138,6 +164,7 @@ function assertNormalizationCompatibility(
|
|
|
138
164
|
}
|
|
139
165
|
|
|
140
166
|
const dependencies = ownValue(current.node, "dependencies");
|
|
167
|
+
|
|
141
168
|
if (isSchemaObject(dependencies)) {
|
|
142
169
|
for (const [name, child] of Object.entries(dependencies)) {
|
|
143
170
|
if (!isSchemaObject(child)) continue;
|
|
@@ -151,9 +178,12 @@ function assertNormalizationCompatibility(
|
|
|
151
178
|
|
|
152
179
|
for (const [keyword, keywordNormalizable] of SCHEMA_SCAN_ARRAY_KEYWORDS) {
|
|
153
180
|
const schemas = ownValue(current.node, keyword);
|
|
181
|
+
|
|
154
182
|
if (!Array.isArray(schemas)) continue;
|
|
183
|
+
|
|
155
184
|
for (let index = 0; index < schemas.length; index += 1) {
|
|
156
185
|
const child = schemas[index];
|
|
186
|
+
|
|
157
187
|
if (!isSchemaObject(child)) continue;
|
|
158
188
|
stack.push({
|
|
159
189
|
node: child,
|
|
@@ -164,6 +194,7 @@ function assertNormalizationCompatibility(
|
|
|
164
194
|
}
|
|
165
195
|
|
|
166
196
|
const items = ownValue(current.node, "items");
|
|
197
|
+
|
|
167
198
|
if (isSchemaObject(items)) {
|
|
168
199
|
stack.push({
|
|
169
200
|
node: items,
|
|
@@ -173,6 +204,7 @@ function assertNormalizationCompatibility(
|
|
|
173
204
|
} else if (Array.isArray(items)) {
|
|
174
205
|
for (let index = 0; index < items.length; index += 1) {
|
|
175
206
|
const child = items[index];
|
|
207
|
+
|
|
176
208
|
if (!isSchemaObject(child)) continue;
|
|
177
209
|
stack.push({
|
|
178
210
|
node: child,
|
|
@@ -183,6 +215,7 @@ function assertNormalizationCompatibility(
|
|
|
183
215
|
}
|
|
184
216
|
|
|
185
217
|
const additionalItems = ownValue(current.node, "additionalItems");
|
|
218
|
+
|
|
186
219
|
if (isSchemaObject(additionalItems)) {
|
|
187
220
|
stack.push({
|
|
188
221
|
node: additionalItems,
|
|
@@ -193,6 +226,7 @@ function assertNormalizationCompatibility(
|
|
|
193
226
|
|
|
194
227
|
for (const [keyword, keywordNormalizable] of SCHEMA_SCAN_SINGLE_KEYWORDS) {
|
|
195
228
|
const child = ownValue(current.node, keyword);
|
|
229
|
+
|
|
196
230
|
if (!isSchemaObject(child)) continue;
|
|
197
231
|
stack.push({
|
|
198
232
|
node: child,
|
|
@@ -220,9 +254,12 @@ function collectSchemaReference(
|
|
|
220
254
|
if (!Object.hasOwn(current.node, "$ref")) return;
|
|
221
255
|
|
|
222
256
|
const reference = current.node.$ref;
|
|
223
|
-
|
|
257
|
+
const referenceText = z.string().safeParse(reference);
|
|
258
|
+
|
|
259
|
+
if (!referenceText.success) {
|
|
224
260
|
throw new StrictifierError("$ref must be a string", `${current.path}.$ref`);
|
|
225
261
|
}
|
|
262
|
+
|
|
226
263
|
if (!current.normalizable) {
|
|
227
264
|
throw new StrictifierError(
|
|
228
265
|
"schema references are not supported in this schema position",
|
|
@@ -230,7 +267,7 @@ function collectSchemaReference(
|
|
|
230
267
|
);
|
|
231
268
|
}
|
|
232
269
|
|
|
233
|
-
references.push({ value:
|
|
270
|
+
references.push({ value: referenceText.data, path: `${current.path}.$ref` });
|
|
234
271
|
}
|
|
235
272
|
|
|
236
273
|
function assertReferenceTargets(
|
|
@@ -239,28 +276,33 @@ function assertReferenceTargets(
|
|
|
239
276
|
): void {
|
|
240
277
|
for (const reference of references) {
|
|
241
278
|
const tokens = parseLocalJsonPointer(reference.value, reference.path);
|
|
279
|
+
|
|
242
280
|
if (!isDefinitionRootPointer(tokens)) {
|
|
243
281
|
throw new StrictifierError(
|
|
244
282
|
"$ref target must be the document root or a definition root",
|
|
245
283
|
reference.path,
|
|
246
284
|
);
|
|
247
285
|
}
|
|
286
|
+
|
|
248
287
|
resolveDefinitionRoot(root, tokens, reference.path);
|
|
249
288
|
}
|
|
250
289
|
}
|
|
251
290
|
|
|
252
291
|
function isDefinitionRootPointer(tokens: string[]): boolean {
|
|
253
292
|
if (tokens.length === 0) return true;
|
|
293
|
+
|
|
254
294
|
if (tokens.length % 2 !== 0) return false;
|
|
255
295
|
|
|
256
296
|
for (let index = 0; index < tokens.length; index += 2) {
|
|
257
297
|
if (tokens[index] !== "$defs" && tokens[index] !== "definitions") return false;
|
|
258
298
|
}
|
|
299
|
+
|
|
259
300
|
return true;
|
|
260
301
|
}
|
|
261
302
|
|
|
262
303
|
function parseLocalJsonPointer(reference: string, path: string): string[] {
|
|
263
304
|
if (reference === "#") return [];
|
|
305
|
+
|
|
264
306
|
if (!reference.startsWith("#/")) {
|
|
265
307
|
throw new StrictifierError(
|
|
266
308
|
"only local root-relative JSON Pointer $ref values are supported",
|
|
@@ -269,11 +311,13 @@ function parseLocalJsonPointer(reference: string, path: string): string[] {
|
|
|
269
311
|
}
|
|
270
312
|
|
|
271
313
|
let fragment: string;
|
|
314
|
+
|
|
272
315
|
try {
|
|
273
316
|
fragment = decodeURIComponent(reference.slice(1));
|
|
274
317
|
} catch {
|
|
275
318
|
throw new StrictifierError("$ref contains invalid percent encoding", path);
|
|
276
319
|
}
|
|
320
|
+
|
|
277
321
|
if (!fragment.startsWith("/")) {
|
|
278
322
|
throw new StrictifierError(
|
|
279
323
|
"only local root-relative JSON Pointer $ref values are supported",
|
|
@@ -289,31 +333,39 @@ function parseLocalJsonPointer(reference: string, path: string): string[] {
|
|
|
289
333
|
|
|
290
334
|
function resolveDefinitionRoot(root: JsonSchema, tokens: string[], path: string): void {
|
|
291
335
|
let current = root;
|
|
336
|
+
|
|
292
337
|
for (let index = 0; index < tokens.length; index += 2) {
|
|
293
338
|
const keyword = tokens[index]!;
|
|
294
339
|
const name = tokens[index + 1]!;
|
|
295
340
|
const definitions = ownValue(current, keyword);
|
|
341
|
+
|
|
296
342
|
if (!isSchemaObject(definitions) || !Object.hasOwn(definitions, name)) {
|
|
297
343
|
throw new StrictifierError("$ref does not resolve inside the caller schema", path);
|
|
298
344
|
}
|
|
345
|
+
|
|
299
346
|
const target = definitions[name];
|
|
347
|
+
|
|
300
348
|
if (!isSchemaObject(target)) {
|
|
301
349
|
throw new StrictifierError("$ref target must be an object schema", path);
|
|
302
350
|
}
|
|
351
|
+
|
|
303
352
|
current = target;
|
|
304
353
|
}
|
|
305
354
|
}
|
|
306
355
|
|
|
307
356
|
function decodeJsonPointerToken(rawToken: string, path: string): string {
|
|
308
357
|
let token = "";
|
|
358
|
+
|
|
309
359
|
for (let index = 0; index < rawToken.length; index += 1) {
|
|
310
360
|
const character = rawToken[index]!;
|
|
361
|
+
|
|
311
362
|
if (character !== "~") {
|
|
312
363
|
token += character;
|
|
313
364
|
continue;
|
|
314
365
|
}
|
|
315
366
|
|
|
316
367
|
const escaped = rawToken[index + 1];
|
|
368
|
+
|
|
317
369
|
if (escaped === "0") {
|
|
318
370
|
token += "~";
|
|
319
371
|
} else if (escaped === "1") {
|
|
@@ -321,17 +373,17 @@ function decodeJsonPointerToken(rawToken: string, path: string): string {
|
|
|
321
373
|
} else {
|
|
322
374
|
throw new StrictifierError("$ref contains an invalid JSON Pointer escape", path);
|
|
323
375
|
}
|
|
376
|
+
|
|
324
377
|
index += 1;
|
|
325
378
|
}
|
|
379
|
+
|
|
326
380
|
return token;
|
|
327
381
|
}
|
|
328
382
|
|
|
329
383
|
function strictifyNode(node: JsonSchema, path: string, provider?: string): JsonSchema {
|
|
330
|
-
if (typeof node !== "object" || node === null) return node;
|
|
331
|
-
|
|
332
384
|
const dialectNeutralNode = provider === "openai" ? omitKeys(node, ["$schema"]) : node;
|
|
333
385
|
let result = strictifySchemaMaps(dialectNeutralNode, path, provider);
|
|
334
|
-
const type = ownValue(result, "type")
|
|
386
|
+
const type = ownValue(result, "type");
|
|
335
387
|
|
|
336
388
|
if (type === "object" || Object.hasOwn(result, "properties")) {
|
|
337
389
|
result = strictifyObject(result, path, provider);
|
|
@@ -344,6 +396,11 @@ function strictifyNode(node: JsonSchema, path: string, provider?: string): JsonS
|
|
|
344
396
|
return strictifySchemaArrays(result, path, provider);
|
|
345
397
|
}
|
|
346
398
|
|
|
399
|
+
/** Boolean and other non-object subschemas pass through unchanged. */
|
|
400
|
+
function strictifySubschema(schema: JsonValue, path: string, provider?: string): JsonValue {
|
|
401
|
+
return isSchemaObject(schema) ? strictifyNode(schema, path, provider) : schema;
|
|
402
|
+
}
|
|
403
|
+
|
|
347
404
|
// 재작성 패스는 정의 맵만 재귀한다. properties 는 strictifyObject 가 별도로 처리하므로
|
|
348
405
|
// 공유 위치 목록(SCHEMA_MAP_KEYWORDS)과 의도적으로 범위가 다르다.
|
|
349
406
|
const DEFINITION_MAP_KEYWORDS = ["$defs", "definitions"] as const;
|
|
@@ -353,14 +410,15 @@ function strictifySchemaMaps(node: JsonSchema, path: string, provider?: string):
|
|
|
353
410
|
|
|
354
411
|
for (const keyword of DEFINITION_MAP_KEYWORDS) {
|
|
355
412
|
const schemas = ownValue(node, keyword);
|
|
413
|
+
|
|
356
414
|
if (!isSchemaObject(schemas)) continue;
|
|
357
415
|
|
|
358
416
|
result[keyword] = Object.fromEntries(
|
|
359
417
|
Object.entries(schemas).map(([name, schema]) => [
|
|
360
418
|
name,
|
|
361
|
-
|
|
362
|
-
?
|
|
363
|
-
: schema,
|
|
419
|
+
schema === undefined
|
|
420
|
+
? schema
|
|
421
|
+
: strictifySubschema(schema, `${path}.${keyword}.${name}`, provider),
|
|
364
422
|
]),
|
|
365
423
|
);
|
|
366
424
|
}
|
|
@@ -376,9 +434,15 @@ function strictifySchemaArrays(node: JsonSchema, path: string, provider?: string
|
|
|
376
434
|
|
|
377
435
|
for (const keyword of COMBINATOR_KEYWORDS) {
|
|
378
436
|
const schemas = ownValue(node, keyword);
|
|
437
|
+
|
|
379
438
|
if (!schemas) continue;
|
|
380
|
-
|
|
381
|
-
|
|
439
|
+
|
|
440
|
+
if (!Array.isArray(schemas)) {
|
|
441
|
+
throw new StrictifierError(`${keyword} must be an array of schemas`, `${path}.${keyword}`);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
result[keyword] = schemas.map((schema, index) =>
|
|
445
|
+
strictifySubschema(schema, `${path}.${keyword}[${index}]`, provider),
|
|
382
446
|
);
|
|
383
447
|
}
|
|
384
448
|
|
|
@@ -386,35 +450,48 @@ function strictifySchemaArrays(node: JsonSchema, path: string, provider?: string
|
|
|
386
450
|
}
|
|
387
451
|
|
|
388
452
|
function strictifyObject(node: JsonSchema, path: string, provider?: string): JsonSchema {
|
|
389
|
-
const properties = ownValue(node, "properties")
|
|
453
|
+
const properties = ownValue(node, "properties");
|
|
454
|
+
|
|
390
455
|
if (!properties) {
|
|
391
456
|
return { ...node, additionalProperties: false };
|
|
392
457
|
}
|
|
393
458
|
|
|
394
|
-
|
|
459
|
+
if (!isSchemaObject(properties)) {
|
|
460
|
+
throw new StrictifierError("properties must be an object", `${path}.properties`);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const required = ownValue(node, "required");
|
|
464
|
+
|
|
465
|
+
const existingRequired = new Set(
|
|
466
|
+
Array.isArray(required) ? required.flatMap((key) => z.string().safeParse(key).data ?? []) : [],
|
|
467
|
+
);
|
|
468
|
+
|
|
395
469
|
const allKeys = Object.keys(properties);
|
|
396
470
|
|
|
471
|
+
// Object.fromEntries defines own data properties, so names such as "__proto__" stay ordinary keys.
|
|
397
472
|
const strictProps = Object.fromEntries(
|
|
398
|
-
allKeys.
|
|
399
|
-
const prop = properties[key]
|
|
400
|
-
const strictProp = strictifyNode(prop, `${path}.${key}`, provider);
|
|
473
|
+
allKeys.flatMap((key) => {
|
|
474
|
+
const prop = properties[key];
|
|
401
475
|
|
|
402
|
-
|
|
476
|
+
if (prop === undefined) return [];
|
|
477
|
+
const strictProp = strictifySubschema(prop, `${path}.${key}`, provider);
|
|
478
|
+
|
|
479
|
+
return [[key, existingRequired.has(key) ? strictProp : makeNullable(strictProp)]];
|
|
403
480
|
}),
|
|
404
|
-
)
|
|
481
|
+
);
|
|
405
482
|
|
|
406
|
-
|
|
483
|
+
return {
|
|
407
484
|
...node,
|
|
408
485
|
type: "object",
|
|
409
486
|
properties: strictProps,
|
|
410
487
|
required: allKeys,
|
|
411
488
|
additionalProperties: false,
|
|
412
489
|
};
|
|
413
|
-
|
|
414
|
-
return result;
|
|
415
490
|
}
|
|
416
491
|
|
|
417
|
-
|
|
492
|
+
function unreachableTupleTailSchema(): JsonSchema {
|
|
493
|
+
return { type: "string" };
|
|
494
|
+
}
|
|
418
495
|
|
|
419
496
|
function strictifyArray(node: JsonSchema, path: string, provider?: string): JsonSchema {
|
|
420
497
|
if (
|
|
@@ -425,20 +502,21 @@ function strictifyArray(node: JsonSchema, path: string, provider?: string): Json
|
|
|
425
502
|
}
|
|
426
503
|
|
|
427
504
|
const result = { ...node };
|
|
428
|
-
const items = ownValue(node, "items")
|
|
505
|
+
const items = ownValue(node, "items");
|
|
429
506
|
|
|
430
507
|
if (Array.isArray(items)) {
|
|
431
508
|
result.items = items.map((schema, index) =>
|
|
432
|
-
|
|
509
|
+
strictifySubschema(schema, `${path}.items[${index}]`, provider),
|
|
433
510
|
);
|
|
434
511
|
} else if (items !== undefined) {
|
|
435
|
-
result.items =
|
|
512
|
+
result.items = strictifySubschema(items, `${path}.items`, provider);
|
|
436
513
|
}
|
|
437
514
|
|
|
438
|
-
const prefixItems = ownValue(node, "prefixItems")
|
|
515
|
+
const prefixItems = ownValue(node, "prefixItems");
|
|
516
|
+
|
|
439
517
|
if (Array.isArray(prefixItems)) {
|
|
440
518
|
result.prefixItems = prefixItems.map((schema, index) =>
|
|
441
|
-
|
|
519
|
+
strictifySubschema(schema, `${path}.prefixItems[${index}]`, provider),
|
|
442
520
|
);
|
|
443
521
|
}
|
|
444
522
|
|
|
@@ -454,15 +532,18 @@ function normalizeTuple(
|
|
|
454
532
|
const prefixItems = ownValue(node, "prefixItems");
|
|
455
533
|
const legacyTuple = Array.isArray(items);
|
|
456
534
|
const prefixTuple = Array.isArray(prefixItems);
|
|
535
|
+
|
|
457
536
|
if (legacyTuple && prefixTuple) {
|
|
458
537
|
throw new StrictifierError("items and prefixItems tuple forms cannot be combined", path);
|
|
459
538
|
}
|
|
539
|
+
|
|
460
540
|
if (prefixTuple && Object.hasOwn(node, "additionalItems")) {
|
|
461
541
|
throw new StrictifierError("additionalItems cannot be combined with prefixItems", path);
|
|
462
542
|
}
|
|
463
543
|
|
|
464
|
-
const rawTuple =
|
|
544
|
+
const rawTuple = legacyTuple ? items : prefixTuple ? prefixItems : [];
|
|
465
545
|
const tuplePath = legacyTuple ? `${path}.items` : `${path}.prefixItems`;
|
|
546
|
+
|
|
466
547
|
const tuple = rawTuple.map((schema, index) => {
|
|
467
548
|
if (!isSchemaObject(schema)) {
|
|
468
549
|
throw new StrictifierError(
|
|
@@ -470,21 +551,26 @@ function normalizeTuple(
|
|
|
470
551
|
`${tuplePath}[${index}]`,
|
|
471
552
|
);
|
|
472
553
|
}
|
|
554
|
+
|
|
473
555
|
const memberPath = `${tuplePath}[${index}]`;
|
|
474
556
|
const member = strictifyNode(schema, memberPath, provider);
|
|
557
|
+
|
|
475
558
|
if (!hasProviderSchemaEntryPoint(member)) {
|
|
476
559
|
throw new StrictifierError(
|
|
477
560
|
"tuple member must define a provider-representable schema",
|
|
478
561
|
memberPath,
|
|
479
562
|
);
|
|
480
563
|
}
|
|
564
|
+
|
|
481
565
|
return member;
|
|
482
566
|
});
|
|
483
567
|
|
|
484
568
|
const rawTail = legacyTuple ? ownValue(node, "additionalItems") : items;
|
|
569
|
+
|
|
485
570
|
if (rawTail === true) {
|
|
486
571
|
throw new StrictifierError("an unrestricted tuple rest is not supported", path);
|
|
487
572
|
}
|
|
573
|
+
|
|
488
574
|
if (rawTail !== undefined && rawTail !== false && !isSchemaObject(rawTail)) {
|
|
489
575
|
throw new StrictifierError("tuple rest must be an object schema or false", path);
|
|
490
576
|
}
|
|
@@ -492,22 +578,37 @@ function normalizeTuple(
|
|
|
492
578
|
const tail = isSchemaObject(rawTail)
|
|
493
579
|
? strictifyNode(rawTail, legacyTuple ? `${path}.additionalItems` : `${path}.items`, provider)
|
|
494
580
|
: undefined;
|
|
581
|
+
|
|
495
582
|
if (tail !== undefined && !hasProviderSchemaEntryPoint(tail)) {
|
|
496
583
|
throw new StrictifierError("an unrestricted tuple rest is not supported", path);
|
|
497
584
|
}
|
|
585
|
+
|
|
498
586
|
const tailMode = tail !== undefined ? "typed" : rawTail === false ? "closed" : "implicit";
|
|
499
587
|
const bounds = normalizeTupleBounds(node, tuple.length, tailMode, path);
|
|
500
|
-
|
|
588
|
+
|
|
589
|
+
const result = omitKeys(node, [
|
|
590
|
+
"items",
|
|
591
|
+
"prefixItems",
|
|
592
|
+
"additionalItems",
|
|
593
|
+
"minItems",
|
|
594
|
+
"maxItems",
|
|
595
|
+
]);
|
|
501
596
|
|
|
502
597
|
// Anthropic 은 assertNormalizationCompatibility 가 비어 있지 않은 tuple 을 이미 거부했으므로
|
|
503
|
-
// 여기 도달하는 tuple 은 빈 tuple 뿐이고, 그 경우 prefixItems
|
|
598
|
+
// 여기 도달하는 tuple 은 빈 tuple 뿐이고, 그 경우 prefixItems 는 생략된다 —
|
|
504
599
|
// provider 분기 없이 한 형태로 두 provider 모두를 표현한다.
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
600
|
+
if (tuple.length > 0) result.prefixItems = tuple;
|
|
601
|
+
result.items = tail ?? unreachableTupleTailSchema();
|
|
602
|
+
result.minItems = bounds.minItems;
|
|
603
|
+
|
|
604
|
+
if (bounds.maxItems !== undefined) result.maxItems = bounds.maxItems;
|
|
605
|
+
|
|
606
|
+
return result;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
interface TupleBounds {
|
|
610
|
+
minItems: number;
|
|
611
|
+
maxItems?: number;
|
|
511
612
|
}
|
|
512
613
|
|
|
513
614
|
function normalizeTupleBounds(
|
|
@@ -515,9 +616,10 @@ function normalizeTupleBounds(
|
|
|
515
616
|
tupleLength: number,
|
|
516
617
|
tailMode: "typed" | "closed" | "implicit",
|
|
517
618
|
path: string,
|
|
518
|
-
):
|
|
619
|
+
): TupleBounds {
|
|
519
620
|
const callerMinItems = integerBound(ownValue(node, "minItems"), "minItems", path);
|
|
520
621
|
const callerMaxItems = integerBound(ownValue(node, "maxItems"), "maxItems", path);
|
|
622
|
+
|
|
521
623
|
if (tailMode === "implicit" && callerMaxItems !== undefined && callerMaxItems > tupleLength) {
|
|
522
624
|
throw new StrictifierError(
|
|
523
625
|
"implicit tuple rest cannot be represented when maxItems exceeds the tuple length",
|
|
@@ -526,6 +628,7 @@ function normalizeTupleBounds(
|
|
|
526
628
|
}
|
|
527
629
|
|
|
528
630
|
const minItems = callerMinItems ?? (callerMaxItems === undefined ? tupleLength : 0);
|
|
631
|
+
|
|
529
632
|
const maxItems =
|
|
530
633
|
tailMode === "typed" ? callerMaxItems : Math.min(callerMaxItems ?? tupleLength, tupleLength);
|
|
531
634
|
|
|
@@ -533,25 +636,37 @@ function normalizeTupleBounds(
|
|
|
533
636
|
throw new StrictifierError("tuple minItems cannot exceed maxItems", path);
|
|
534
637
|
}
|
|
535
638
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
639
|
+
const bounds: TupleBounds = { minItems };
|
|
640
|
+
|
|
641
|
+
if (maxItems !== undefined) bounds.maxItems = maxItems;
|
|
642
|
+
|
|
643
|
+
return bounds;
|
|
540
644
|
}
|
|
541
645
|
|
|
542
|
-
|
|
646
|
+
const nonNegativeSafeInteger = z
|
|
647
|
+
.number()
|
|
648
|
+
.refine((value) => Number.isSafeInteger(value) && value >= 0);
|
|
649
|
+
|
|
650
|
+
function integerBound(
|
|
651
|
+
value: JsonValue | undefined,
|
|
652
|
+
keyword: string,
|
|
653
|
+
path: string,
|
|
654
|
+
): number | undefined {
|
|
543
655
|
if (value === undefined) return undefined;
|
|
544
|
-
|
|
656
|
+
const bound = nonNegativeSafeInteger.safeParse(value);
|
|
657
|
+
|
|
658
|
+
if (!bound.success) {
|
|
545
659
|
throw new StrictifierError(`${keyword} must be a non-negative safe integer`, path);
|
|
546
660
|
}
|
|
547
|
-
|
|
661
|
+
|
|
662
|
+
return bound.data;
|
|
548
663
|
}
|
|
549
664
|
|
|
550
|
-
function isSchemaObject(value:
|
|
551
|
-
return
|
|
665
|
+
function isSchemaObject(value: JsonValue | undefined): value is JsonSchema {
|
|
666
|
+
return isJsonObject(value);
|
|
552
667
|
}
|
|
553
668
|
|
|
554
|
-
function ownValue(schema: JsonSchema, keyword: string):
|
|
669
|
+
function ownValue(schema: JsonSchema, keyword: string): JsonValue | undefined {
|
|
555
670
|
return Object.hasOwn(schema, keyword) ? schema[keyword] : undefined;
|
|
556
671
|
}
|
|
557
672
|
|
|
@@ -570,27 +685,38 @@ function hasProviderSchemaEntryPoint(schema: JsonSchema): boolean {
|
|
|
570
685
|
|
|
571
686
|
function omitKeys(node: JsonSchema, keys: readonly string[]): JsonSchema {
|
|
572
687
|
const omitted = new Set(keys);
|
|
688
|
+
|
|
573
689
|
return Object.fromEntries(Object.entries(node).filter(([key]) => !omitted.has(key)));
|
|
574
690
|
}
|
|
575
691
|
|
|
576
|
-
function
|
|
692
|
+
function hasNullVariant(variants: JsonValue[]): boolean {
|
|
693
|
+
return variants.some(
|
|
694
|
+
(variant) => isSchemaObject(variant) && ownValue(variant, "type") === "null",
|
|
695
|
+
);
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
function makeNullable(schema: JsonValue): JsonValue {
|
|
699
|
+
const nullSchema: JsonSchema = { type: "null" };
|
|
700
|
+
|
|
701
|
+
if (!isSchemaObject(schema)) return { anyOf: [schema, nullSchema] };
|
|
702
|
+
|
|
577
703
|
if (ownValue(schema, "type") === "null") return schema;
|
|
578
704
|
|
|
579
705
|
const anyOf = ownValue(schema, "anyOf");
|
|
706
|
+
|
|
580
707
|
if (anyOf) {
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
return { anyOf: [...variants, { type: "null" }] };
|
|
708
|
+
if (!Array.isArray(anyOf)) throw new StrictifierError("anyOf must be an array of schemas", "$");
|
|
709
|
+
|
|
710
|
+
return hasNullVariant(anyOf) ? schema : { anyOf: [...anyOf, nullSchema] };
|
|
585
711
|
}
|
|
586
712
|
|
|
587
713
|
const oneOf = ownValue(schema, "oneOf");
|
|
714
|
+
|
|
588
715
|
if (oneOf) {
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
return { oneOf: [...variants, { type: "null" }] };
|
|
716
|
+
if (!Array.isArray(oneOf)) throw new StrictifierError("oneOf must be an array of schemas", "$");
|
|
717
|
+
|
|
718
|
+
return hasNullVariant(oneOf) ? schema : { oneOf: [...oneOf, nullSchema] };
|
|
593
719
|
}
|
|
594
720
|
|
|
595
|
-
return { anyOf: [schema,
|
|
721
|
+
return { anyOf: [schema, nullSchema] };
|
|
596
722
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { BadRequestException } from "sonamu";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { SD } from "../../../i18n/sd.generated";
|
|
4
4
|
|
|
5
5
|
export class ThinkingValidationError extends BadRequestException {
|
|
6
6
|
constructor(message: string) {
|
|
7
|
-
super(message
|
|
7
|
+
super(SD("error.detail")(message));
|
|
8
8
|
this.name = "ThinkingValidationError";
|
|
9
9
|
}
|
|
10
10
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface TtftTracker {
|
|
2
2
|
markStart: () => void;
|
|
3
3
|
recordFirstDelta: () => void;
|
|
4
4
|
value: () => number | null;
|
|
5
5
|
wrapDelta: (onDelta: (text: string) => void) => (text: string) => void;
|
|
6
|
-
}
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function createTtftTracker(now: () => number = Date.now): TtftTracker {
|
|
7
9
|
let startedAt: number | null = null;
|
|
8
10
|
let ttftMs: number | null = null;
|
|
9
11
|
|