@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.
- 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 +22 -20
- package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +43 -34
- 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 -69
- package/bundle/dist/application/request-log/request-log.types.js +8 -2
- 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 +40 -16
- package/bundle/dist/application/sonamu.generated.sso.js +2 -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 +2 -1
- package/bundle/dist/migrations/20260807133553_manual__backfill_request_log_cost.js +8 -6
- package/bundle/dist/migrations/20261018215031_alter_request_logs_add1_alter1.js +15 -0
- 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 +33 -0
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +87 -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.entity.json +8 -0
- package/bundle/src/application/request-log/request-log.model.test.ts +111 -4
- package/bundle/src/application/request-log/request-log.model.ts +279 -145
- package/bundle/src/application/request-log/request-log.types.ts +17 -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 +135 -0
- package/bundle/src/application/sonamu.generated.sso.ts +3 -0
- package/bundle/src/application/sonamu.generated.ts +29 -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 +24 -2
- package/bundle/src/migrations/20260807133553_manual__backfill_request_log_cost.ts +16 -8
- package/bundle/src/migrations/20261018215031_alter_request_logs_add1_alter1.ts +15 -0
- 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-BsieU37H.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-Dtd0NR4r.js → lazyRouteComponent-D8iTIHyn.js} +129 -2
- package/bundle/web-dist/server/assets/logs-B3OTd9hy.js +825 -0
- package/bundle/web-dist/server/assets/{monit-DvzribSE.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-B4a6-uuR.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-CbqfnQOJ.js → request-model-I6OdODSH.js} +15 -6
- package/bundle/web-dist/server/assets/{routes-BAPWTizT.js → routes-B95YlUv2.js} +760 -213
- package/bundle/web-dist/server/assets/{services.generated-CEbGjsI0.js → services.generated-DQATJ6qf.js} +12821 -12194
- package/bundle/web-dist/server/assets/settings-C3gbGk0m.js +830 -0
- package/bundle/web-dist/server/assets/{show-CxVZTAdv.js → show-Bxaj3rhH.js} +1355 -419
- 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-CfYmk_4_.js → use-update-token-mutation-BEbgOzaa.js} +1 -1
- package/bundle/web-dist/server/entry-server.generated.js +4303 -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 +24 -1
- 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/request-log-run-lifecycle.md +1 -1
- package/skills/qgrid/references/sonamu-api-web-flow.md +1 -1
- 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-CrXKu_J8.js +0 -106
- package/bundle/web-dist/client/assets/logs-B2SmWJXA.js +0 -1
- package/bundle/web-dist/client/assets/monit-D-JwXXoA.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-C5r4gTvY.js +0 -5
- package/bundle/web-dist/client/assets/settings-D3tDSAck.js +0 -1
- package/bundle/web-dist/client/assets/show-Cah_kUKC.js +0 -2
- package/bundle/web-dist/client/assets/tokens-DU2Iyxxd.js +0 -1
- package/bundle/web-dist/client/assets/use-oauth-login-flow-D0UaR9_e.js +0 -1
- package/bundle/web-dist/client/assets/use-update-token-mutation-DAq0F8p-.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-l91avYif.js +0 -509
- package/bundle/web-dist/server/assets/plus-KZrECewT.js +0 -19
- package/bundle/web-dist/server/assets/refresh-cw-BND93JrF.js +0 -23
- package/bundle/web-dist/server/assets/settings-BZR5HSAL.js +0 -461
- package/bundle/web-dist/server/assets/tokens-D1hb4eKk.js +0 -448
- package/bundle/web-dist/server/assets/use-oauth-login-flow-Cvdy0zF8.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,20 +8,32 @@ import { createFenceStripTransform } from "../../utils/providers/anthropic/fence
|
|
|
8
8
|
import { getAccessToken } from "../../utils/providers/common/credentials";
|
|
9
9
|
import { calculateCostUsd } from "../../utils/providers/common/model-cost";
|
|
10
10
|
import {
|
|
11
|
+
type GenerateRequest,
|
|
11
12
|
type GenerateResult,
|
|
13
|
+
type GenerateStreamCallbacks,
|
|
14
|
+
type MediaDispatcher,
|
|
15
|
+
type ProviderDispatcher,
|
|
12
16
|
type StreamCallbacks,
|
|
17
|
+
type VoiceDispatcher,
|
|
13
18
|
} from "../../utils/providers/common/provider-dispatcher";
|
|
14
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
isJsonObject,
|
|
21
|
+
isProviderId,
|
|
22
|
+
type JsonValue,
|
|
23
|
+
type ProviderId,
|
|
24
|
+
} from "../../utils/providers/common/provider-types";
|
|
15
25
|
import {
|
|
16
26
|
parseAndValidateCallerSchemas,
|
|
17
27
|
serializeAndValidateDispatchSchema,
|
|
18
28
|
} from "../../utils/providers/common/schema-validation";
|
|
19
29
|
import { strictify } from "../../utils/providers/common/strictifier";
|
|
30
|
+
import { type GrokTokenStateSnapshot } from "../../utils/providers/grok/grok-dispatcher";
|
|
20
31
|
import {
|
|
21
32
|
ImageGenerationError,
|
|
22
33
|
type OpenAIDispatcher,
|
|
23
34
|
} from "../../utils/providers/openai/openai-dispatcher";
|
|
24
35
|
import { type TokenSubsetA } from "../sonamu.generated";
|
|
36
|
+
import { type TokenCredentials } from "../token/token.types";
|
|
25
37
|
import { decideConvRouting, issueConvContext } from "./conv-routing";
|
|
26
38
|
import {
|
|
27
39
|
maskToken,
|
|
@@ -41,6 +53,61 @@ export type InternalQueryInput = QueryInput & {
|
|
|
41
53
|
requirePreferredToken?: boolean;
|
|
42
54
|
};
|
|
43
55
|
|
|
56
|
+
// qgrid 상위가 provider 에 요구하는 실행 계약. 스트리밍은 공통 ProviderDispatcher 에 아직 없어서
|
|
57
|
+
// 여기서 합친다.
|
|
58
|
+
export type StreamingProviderDispatcher = ProviderDispatcher & {
|
|
59
|
+
generateStream(req: GenerateRequest, cb: GenerateStreamCallbacks): Promise<void>;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// TokenSubscriber 가 grok row 를 전달하는 계약. credentials 는 DB JSONB 원본이며 dispatcher 가
|
|
63
|
+
// 자체 스키마로 검증한다.
|
|
64
|
+
export type GrokTokenRow = {
|
|
65
|
+
id: number;
|
|
66
|
+
name: string;
|
|
67
|
+
credentials: TokenCredentials;
|
|
68
|
+
quotaThreshold: number | null;
|
|
69
|
+
weight: number;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export interface GrokTokenSink {
|
|
73
|
+
onTokenAdded(
|
|
74
|
+
id: number,
|
|
75
|
+
name: string,
|
|
76
|
+
credentials: TokenCredentials,
|
|
77
|
+
quotaThreshold: number | null,
|
|
78
|
+
weight: number,
|
|
79
|
+
): void | Promise<void>;
|
|
80
|
+
onTokenUpdated(
|
|
81
|
+
id: number,
|
|
82
|
+
name: string,
|
|
83
|
+
credentials: TokenCredentials,
|
|
84
|
+
quotaThreshold: number | null,
|
|
85
|
+
weight: number,
|
|
86
|
+
): void | Promise<void>;
|
|
87
|
+
onTokenRemoved(id: number): void | Promise<void>;
|
|
88
|
+
replaceTokens(rows: GrokTokenRow[]): void | Promise<void>;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Observability the concrete Grok dispatcher exposes beyond routing. */
|
|
92
|
+
export interface GrokTokenStateSource {
|
|
93
|
+
tokenStates(): GrokTokenStateSnapshot[];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Media, voice, and token-state reporting are optional capabilities of a Grok dispatcher. */
|
|
97
|
+
export type GrokProviderDispatcher = StreamingProviderDispatcher &
|
|
98
|
+
GrokTokenSink &
|
|
99
|
+
Partial<MediaDispatcher & VoiceDispatcher & GrokTokenStateSource>;
|
|
100
|
+
|
|
101
|
+
export type QgridDispatcherOptions = {
|
|
102
|
+
grokDispatcher?: GrokProviderDispatcher | null;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const PROVIDER_LABELS: Record<ProviderId, string> = {
|
|
106
|
+
openai: "OpenAI",
|
|
107
|
+
anthropic: "Anthropic",
|
|
108
|
+
grok: "Grok",
|
|
109
|
+
};
|
|
110
|
+
|
|
44
111
|
export class QgridDispatcherClass {
|
|
45
112
|
tokens = new Map<number, TokenSubsetA>();
|
|
46
113
|
|
|
@@ -49,23 +116,76 @@ export class QgridDispatcherClass {
|
|
|
49
116
|
requestCounts = new Map<string, number>();
|
|
50
117
|
|
|
51
118
|
subscriber: TokenSubscriber | null = null;
|
|
52
|
-
|
|
53
|
-
|
|
119
|
+
|
|
120
|
+
// provider route prefix → 실행 dispatcher. 등록되지 않은 provider 는 not-ready 로 응답한다.
|
|
121
|
+
readonly dispatchers = new Map<ProviderId, StreamingProviderDispatcher>();
|
|
122
|
+
#openaiDispatcher: OpenAIDispatcher | null = null;
|
|
123
|
+
#anthropicDispatcher: AnthropicDispatcher | null = null;
|
|
124
|
+
#grokDispatcher: GrokProviderDispatcher | null = null;
|
|
54
125
|
|
|
55
126
|
// HTTP가 dispatcher보다 먼저 열리므로 초기화 중과 초기화 실패를 구분한다.
|
|
56
|
-
|
|
127
|
+
// grok 은 bootstrap 이 붙기 전까지 상태가 없으며, 없으면 기동 중으로 본다.
|
|
128
|
+
startupState: Record<"openai" | "anthropic", ProviderStartupState> &
|
|
129
|
+
Partial<Record<"grok", ProviderStartupState>> = {
|
|
57
130
|
openai: "starting",
|
|
58
131
|
anthropic: "starting",
|
|
59
132
|
};
|
|
60
133
|
|
|
134
|
+
constructor(options: QgridDispatcherOptions = {}) {
|
|
135
|
+
if (options.grokDispatcher) this.grokDispatcher = options.grokDispatcher;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
get openaiDispatcher(): OpenAIDispatcher | null {
|
|
139
|
+
return this.#openaiDispatcher;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
set openaiDispatcher(dispatcher: OpenAIDispatcher | null) {
|
|
143
|
+
this.#openaiDispatcher = dispatcher;
|
|
144
|
+
this.register("openai", dispatcher);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
get anthropicDispatcher(): AnthropicDispatcher | null {
|
|
148
|
+
return this.#anthropicDispatcher;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
set anthropicDispatcher(dispatcher: AnthropicDispatcher | null) {
|
|
152
|
+
this.#anthropicDispatcher = dispatcher;
|
|
153
|
+
this.register("anthropic", dispatcher);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
get grokDispatcher(): GrokProviderDispatcher | null {
|
|
157
|
+
return this.#grokDispatcher;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
set grokDispatcher(dispatcher: GrokProviderDispatcher | null) {
|
|
161
|
+
this.#grokDispatcher = dispatcher;
|
|
162
|
+
this.register("grok", dispatcher);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
register(provider: ProviderId, dispatcher: StreamingProviderDispatcher | null): void {
|
|
166
|
+
if (dispatcher) this.dispatchers.set(provider, dispatcher);
|
|
167
|
+
else this.dispatchers.delete(provider);
|
|
168
|
+
}
|
|
169
|
+
|
|
61
170
|
// 초기화 중에는 503 + Retry-After, 초기화 실패에는 500을 반환한다.
|
|
62
|
-
notReadyError(provider:
|
|
63
|
-
const label = provider
|
|
171
|
+
notReadyError(provider: ProviderId): Error {
|
|
172
|
+
const label = PROVIDER_LABELS[provider];
|
|
173
|
+
|
|
64
174
|
return this.startupState[provider] === "failed"
|
|
65
175
|
? new InternalServerErrorException(SD("qgrid.dispatcherFailed")(label))
|
|
66
176
|
: new ServiceUnavailableException(SD("qgrid.dispatcherStarting")(label));
|
|
67
177
|
}
|
|
68
178
|
|
|
179
|
+
// prefix 없는/미지원 prefix 는 기존대로 ProcessError, 지원 provider 의 미등록은 not-ready.
|
|
180
|
+
resolveDispatcher(input: QueryInput, provider: string | undefined): ResolvedDispatcher {
|
|
181
|
+
if (!isProviderId(provider)) throw directLlmApiFallbackNotImplemented(input);
|
|
182
|
+
const dispatcher = this.dispatchers.get(provider);
|
|
183
|
+
|
|
184
|
+
if (!dispatcher) throw this.notReadyError(provider);
|
|
185
|
+
|
|
186
|
+
return { provider, dispatcher };
|
|
187
|
+
}
|
|
188
|
+
|
|
69
189
|
recordCompleted(provider: string, tokenName: string): void {
|
|
70
190
|
const key = `${provider}\0${tokenName}`;
|
|
71
191
|
this.requestCounts.set(key, (this.requestCounts.get(key) ?? 0) + 1);
|
|
@@ -88,55 +208,12 @@ export class QgridDispatcherClass {
|
|
|
88
208
|
const route = parseProviderRoute(input.model);
|
|
89
209
|
const outputSchema = buildAndValidateStrictOutputSchema(input, route.provider);
|
|
90
210
|
const answerKind = input.jsonSchema ? ("json" as const) : ("text" as const);
|
|
211
|
+
const { provider, dispatcher } = this.resolveDispatcher(input, route.provider);
|
|
91
212
|
|
|
92
|
-
if (
|
|
93
|
-
if (!this.openaiDispatcher) throw this.notReadyError("openai");
|
|
94
|
-
|
|
95
|
-
const decision = decideConvRouting(input, {
|
|
96
|
-
directOpenAI: true,
|
|
97
|
-
modelNamespace: `openai/${route.model}`,
|
|
98
|
-
});
|
|
99
|
-
const result = await this.openaiDispatcher.generate({
|
|
100
|
-
model: route.model,
|
|
101
|
-
systemPrompt: input.system,
|
|
102
|
-
outputSchema,
|
|
103
|
-
stopAfterOutputMessage: input.tools?.length
|
|
104
|
-
? (text, phase) => isToolCallEnvelope(text, input.tools!, answerKind, phase)
|
|
105
|
-
: undefined,
|
|
106
|
-
thinking: input.thinking,
|
|
107
|
-
effort: input.thinking === false ? undefined : input.effort,
|
|
108
|
-
verbosity: input.verbosity,
|
|
109
|
-
reasoningSummary: input.reasoningSummary,
|
|
110
|
-
serviceTier: input.serviceTier,
|
|
111
|
-
timeoutMs: input.timeout,
|
|
112
|
-
coldInput: decision.coldInput,
|
|
113
|
-
coldHistory: decision.coldHistory,
|
|
114
|
-
promptCacheKey: input.imageGeneration ? undefined : decision.promptCacheKey,
|
|
115
|
-
preferredTokenId:
|
|
116
|
-
input.preferredTokenId ?? (input.imageGeneration ? undefined : decision.preferredTokenId),
|
|
117
|
-
requirePreferredToken: input.requirePreferredToken,
|
|
118
|
-
abortSignal,
|
|
119
|
-
imageGeneration: input.imageGeneration,
|
|
120
|
-
imageGenerationOptions: input.imageGenerationOptions,
|
|
121
|
-
});
|
|
122
|
-
this.recordCompleted("openai", result.tokenName);
|
|
123
|
-
|
|
124
|
-
// 이미지 요청은 cold-only(R8)라 재사용 좌표를 발급하지 않는다. 좌표를 실으면
|
|
125
|
-
// sessionKey 소비자의 warm 좌표를 죽은 좌표로 덮어써 다음 텍스트 turn 이 cold 로 떨어진다.
|
|
126
|
-
const coord = input.imageGeneration
|
|
127
|
-
? undefined
|
|
128
|
-
: issueConvContext(result.threadCoord, decision, result.threadCoord.workerId);
|
|
129
|
-
|
|
130
|
-
return applyToolCallEmulation(toEmulationResult(result, input.serviceTier), input.tools, {
|
|
131
|
-
threadCoord: coord,
|
|
132
|
-
images: result.images,
|
|
133
|
-
answerKind,
|
|
134
|
-
});
|
|
135
|
-
} else if (route.provider === "anthropic") {
|
|
136
|
-
if (!this.anthropicDispatcher) throw this.notReadyError("anthropic");
|
|
137
|
-
|
|
213
|
+
if (provider === "anthropic") {
|
|
138
214
|
const decision = decideConvRouting(input);
|
|
139
|
-
|
|
215
|
+
|
|
216
|
+
const result = await dispatcher.generate({
|
|
140
217
|
model: input.model,
|
|
141
218
|
systemPrompt: composeSystemWithSchemaContract(input.system, input),
|
|
142
219
|
thinking: input.thinking,
|
|
@@ -149,7 +226,8 @@ export class QgridDispatcherClass {
|
|
|
149
226
|
imageGeneration: input.imageGeneration,
|
|
150
227
|
imageGenerationOptions: input.imageGenerationOptions,
|
|
151
228
|
});
|
|
152
|
-
|
|
229
|
+
|
|
230
|
+
this.recordCompleted(provider, result.tokenName);
|
|
153
231
|
|
|
154
232
|
return applyToolCallEmulation(toEmulationResult(result), input.tools, {
|
|
155
233
|
threadCoord: issueConvContext(result.threadCoord, decision),
|
|
@@ -157,7 +235,33 @@ export class QgridDispatcherClass {
|
|
|
157
235
|
});
|
|
158
236
|
}
|
|
159
237
|
|
|
160
|
-
|
|
238
|
+
const decision = decideConvRouting(input, {
|
|
239
|
+
directProvider: provider,
|
|
240
|
+
modelNamespace: `${provider}/${route.model}`,
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
const result = await dispatcher.generate({
|
|
244
|
+
...buildDirectRequest(input, route.model, outputSchema, answerKind, abortSignal),
|
|
245
|
+
promptCacheKey: input.imageGeneration ? undefined : decision.promptCacheKey,
|
|
246
|
+
preferredTokenId:
|
|
247
|
+
input.preferredTokenId ?? (input.imageGeneration ? undefined : decision.preferredTokenId),
|
|
248
|
+
coldInput: decision.coldInput,
|
|
249
|
+
coldHistory: decision.coldHistory,
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
this.recordCompleted(provider, result.tokenName);
|
|
253
|
+
|
|
254
|
+
// 이미지 요청은 cold-only(R8)라 재사용 좌표를 발급하지 않는다. 좌표를 실으면
|
|
255
|
+
// sessionKey 소비자의 warm 좌표를 죽은 좌표로 덮어써 다음 텍스트 turn 이 cold 로 떨어진다.
|
|
256
|
+
const coord = input.imageGeneration
|
|
257
|
+
? undefined
|
|
258
|
+
: issueConvContext(result.threadCoord, decision, result.threadCoord.workerId);
|
|
259
|
+
|
|
260
|
+
return applyToolCallEmulation(toEmulationResult(result, input.serviceTier), input.tools, {
|
|
261
|
+
threadCoord: coord,
|
|
262
|
+
images: result.images,
|
|
263
|
+
answerKind,
|
|
264
|
+
});
|
|
161
265
|
}
|
|
162
266
|
|
|
163
267
|
async queryStream(
|
|
@@ -168,77 +272,23 @@ export class QgridDispatcherClass {
|
|
|
168
272
|
const route = parseProviderRoute(input.model);
|
|
169
273
|
const outputSchema = buildAndValidateStrictOutputSchema(input, route.provider);
|
|
170
274
|
const answerKind = input.jsonSchema ? ("json" as const) : ("text" as const);
|
|
275
|
+
const { provider, dispatcher } = this.resolveDispatcher(input, route.provider);
|
|
171
276
|
|
|
172
|
-
if (
|
|
173
|
-
if (!this.openaiDispatcher) throw this.notReadyError("openai");
|
|
174
|
-
|
|
175
|
-
const decision = decideConvRouting(input, {
|
|
176
|
-
directOpenAI: true,
|
|
177
|
-
modelNamespace: `openai/${route.model}`,
|
|
178
|
-
});
|
|
179
|
-
await this.openaiDispatcher.generateStream(
|
|
180
|
-
{
|
|
181
|
-
model: route.model,
|
|
182
|
-
systemPrompt: input.system,
|
|
183
|
-
outputSchema,
|
|
184
|
-
stopAfterOutputMessage: input.tools?.length
|
|
185
|
-
? (text, phase) => isToolCallEnvelope(text, input.tools!, answerKind, phase)
|
|
186
|
-
: undefined,
|
|
187
|
-
thinking: input.thinking,
|
|
188
|
-
effort: input.thinking === false ? undefined : input.effort,
|
|
189
|
-
verbosity: input.verbosity,
|
|
190
|
-
reasoningSummary: input.reasoningSummary,
|
|
191
|
-
serviceTier: input.serviceTier,
|
|
192
|
-
timeoutMs: input.timeout,
|
|
193
|
-
coldInput: decision.coldInput,
|
|
194
|
-
coldHistory: decision.coldHistory,
|
|
195
|
-
promptCacheKey: decision.promptCacheKey,
|
|
196
|
-
preferredTokenId: input.preferredTokenId ?? decision.preferredTokenId,
|
|
197
|
-
requirePreferredToken: input.requirePreferredToken,
|
|
198
|
-
abortSignal,
|
|
199
|
-
imageGeneration: input.imageGeneration,
|
|
200
|
-
imageGenerationOptions: input.imageGenerationOptions,
|
|
201
|
-
},
|
|
202
|
-
{
|
|
203
|
-
onDelta: cb.onDelta,
|
|
204
|
-
onThreadId: cb.onThreadId,
|
|
205
|
-
onTurnId: cb.onTurnId,
|
|
206
|
-
onComplete: (turnResult) => {
|
|
207
|
-
this.recordCompleted("openai", turnResult.tokenName);
|
|
208
|
-
cb.onComplete(
|
|
209
|
-
applyToolCallEmulation(
|
|
210
|
-
toEmulationResult(turnResult, input.serviceTier),
|
|
211
|
-
input.tools,
|
|
212
|
-
{
|
|
213
|
-
threadCoord: issueConvContext(
|
|
214
|
-
turnResult.threadCoord,
|
|
215
|
-
decision,
|
|
216
|
-
turnResult.threadCoord.workerId,
|
|
217
|
-
),
|
|
218
|
-
answerKind,
|
|
219
|
-
},
|
|
220
|
-
),
|
|
221
|
-
);
|
|
222
|
-
},
|
|
223
|
-
onError: cb.onError,
|
|
224
|
-
},
|
|
225
|
-
);
|
|
226
|
-
return;
|
|
227
|
-
} else if (route.provider === "anthropic") {
|
|
228
|
-
if (!this.anthropicDispatcher) throw this.notReadyError("anthropic");
|
|
229
|
-
|
|
277
|
+
if (provider === "anthropic") {
|
|
230
278
|
// 구조화 응답은 최종 텍스트와 델타 모두 코드펜스를 제거한다.
|
|
231
279
|
const hasSchemaContract = input.jsonSchema !== undefined || Boolean(input.tools?.length);
|
|
232
280
|
const fenceStrip = hasSchemaContract ? createFenceStripTransform() : undefined;
|
|
281
|
+
|
|
233
282
|
const emitDelta = fenceStrip
|
|
234
283
|
? (text: string) => {
|
|
235
284
|
const safe = fenceStrip.push(text);
|
|
285
|
+
|
|
236
286
|
if (safe) cb.onDelta(safe);
|
|
237
287
|
}
|
|
238
288
|
: cb.onDelta;
|
|
239
289
|
|
|
240
290
|
const decision = decideConvRouting(input);
|
|
241
|
-
await
|
|
291
|
+
await dispatcher.generateStream(
|
|
242
292
|
{
|
|
243
293
|
model: input.model,
|
|
244
294
|
systemPrompt: composeSystemWithSchemaContract(input.system, input),
|
|
@@ -256,9 +306,10 @@ export class QgridDispatcherClass {
|
|
|
256
306
|
onDelta: emitDelta,
|
|
257
307
|
onThreadId: cb.onThreadId,
|
|
258
308
|
onComplete: (turnResult) => {
|
|
259
|
-
this.recordCompleted(
|
|
309
|
+
this.recordCompleted(provider, turnResult.tokenName);
|
|
260
310
|
// 닫는 펜스 판정 때문에 보류한 텍스트를 완료 전에 방출한다.
|
|
261
311
|
const rest = fenceStrip?.flush();
|
|
312
|
+
|
|
262
313
|
if (rest) cb.onDelta(rest);
|
|
263
314
|
|
|
264
315
|
const issuedCoord = issueConvContext(turnResult.threadCoord, decision);
|
|
@@ -272,20 +323,98 @@ export class QgridDispatcherClass {
|
|
|
272
323
|
onError: cb.onError,
|
|
273
324
|
},
|
|
274
325
|
);
|
|
326
|
+
|
|
275
327
|
return;
|
|
276
328
|
}
|
|
277
329
|
|
|
278
|
-
|
|
330
|
+
const decision = decideConvRouting(input, {
|
|
331
|
+
directProvider: provider,
|
|
332
|
+
modelNamespace: `${provider}/${route.model}`,
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
await dispatcher.generateStream(
|
|
336
|
+
{
|
|
337
|
+
...buildDirectRequest(input, route.model, outputSchema, answerKind, abortSignal),
|
|
338
|
+
promptCacheKey: decision.promptCacheKey,
|
|
339
|
+
preferredTokenId: input.preferredTokenId ?? decision.preferredTokenId,
|
|
340
|
+
coldInput: decision.coldInput,
|
|
341
|
+
coldHistory: decision.coldHistory,
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
onDelta: cb.onDelta,
|
|
345
|
+
onThreadId: cb.onThreadId,
|
|
346
|
+
onTurnId: cb.onTurnId,
|
|
347
|
+
onComplete: (turnResult) => {
|
|
348
|
+
this.recordCompleted(provider, turnResult.tokenName);
|
|
349
|
+
cb.onComplete(
|
|
350
|
+
applyToolCallEmulation(toEmulationResult(turnResult, input.serviceTier), input.tools, {
|
|
351
|
+
threadCoord: issueConvContext(
|
|
352
|
+
turnResult.threadCoord,
|
|
353
|
+
decision,
|
|
354
|
+
turnResult.threadCoord.workerId,
|
|
355
|
+
),
|
|
356
|
+
answerKind,
|
|
357
|
+
}),
|
|
358
|
+
);
|
|
359
|
+
},
|
|
360
|
+
onError: cb.onError,
|
|
361
|
+
},
|
|
362
|
+
);
|
|
279
363
|
}
|
|
280
364
|
}
|
|
281
365
|
|
|
282
|
-
|
|
366
|
+
// Direct provider(OpenAI, Grok) 공통 요청 필드. cache affinity 필드는 stream 여부에 따라 호출부가 채운다.
|
|
367
|
+
function buildDirectRequest(
|
|
368
|
+
input: InternalQueryInput,
|
|
369
|
+
model: string,
|
|
370
|
+
outputSchema: JsonValue | undefined,
|
|
371
|
+
answerKind: "json" | "text",
|
|
372
|
+
abortSignal: AbortSignal | undefined,
|
|
373
|
+
): Omit<GenerateRequest, "coldInput" | "coldHistory" | "promptCacheKey" | "preferredTokenId"> {
|
|
374
|
+
const request: Omit<
|
|
375
|
+
GenerateRequest,
|
|
376
|
+
"coldInput" | "coldHistory" | "promptCacheKey" | "preferredTokenId"
|
|
377
|
+
> = {
|
|
378
|
+
model,
|
|
379
|
+
systemPrompt: input.system,
|
|
380
|
+
outputSchema,
|
|
381
|
+
stopAfterOutputMessage: input.tools?.length
|
|
382
|
+
? (text, phase) => isToolCallEnvelope(text, input.tools!, answerKind, phase)
|
|
383
|
+
: undefined,
|
|
384
|
+
thinking: input.thinking,
|
|
385
|
+
effort: input.thinking === false ? undefined : input.effort,
|
|
386
|
+
verbosity: input.verbosity,
|
|
387
|
+
reasoningSummary: input.reasoningSummary,
|
|
388
|
+
serviceTier: input.serviceTier,
|
|
389
|
+
timeoutMs: input.timeout,
|
|
390
|
+
requirePreferredToken: input.requirePreferredToken,
|
|
391
|
+
abortSignal,
|
|
392
|
+
imageGeneration: input.imageGeneration,
|
|
393
|
+
imageGenerationOptions: input.imageGenerationOptions,
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
// Opaque namespaces; the Grok dispatcher reads `xai`, OpenAI ignores it.
|
|
397
|
+
if (input.providerOptions?.xai) {
|
|
398
|
+
request.providerOptions = { xai: { ...input.providerOptions.xai } };
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
return request;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
interface ProviderRoute {
|
|
405
|
+
provider?: string;
|
|
406
|
+
model: string;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
function parseProviderRoute(model: string | undefined): ProviderRoute {
|
|
283
410
|
if (!model?.includes("/")) {
|
|
284
411
|
return { model: model ?? "" };
|
|
285
412
|
}
|
|
286
413
|
|
|
287
414
|
const [provider, routedModel] = model.split("/", 2);
|
|
415
|
+
|
|
288
416
|
if (!provider || !routedModel) throw new ProcessError("unknown model");
|
|
417
|
+
|
|
289
418
|
return { provider, model: routedModel };
|
|
290
419
|
}
|
|
291
420
|
|
|
@@ -301,9 +430,10 @@ export function buildStrictOutputSchema(
|
|
|
301
430
|
): JsonValue | undefined {
|
|
302
431
|
const outputSchema = buildRawOutputSchema(input);
|
|
303
432
|
|
|
304
|
-
return
|
|
305
|
-
|
|
306
|
-
|
|
433
|
+
if (!outputSchema) return undefined;
|
|
434
|
+
|
|
435
|
+
// Boolean and other non-object schemas have nothing to tighten and pass through unchanged.
|
|
436
|
+
return isJsonObject(outputSchema) ? strictify(outputSchema, { provider }) : outputSchema;
|
|
307
437
|
}
|
|
308
438
|
|
|
309
439
|
export function buildAndValidateStrictOutputSchema(
|
|
@@ -314,11 +444,13 @@ export function buildAndValidateStrictOutputSchema(
|
|
|
314
444
|
// Anthropic은 원본 스키마를 검증한 뒤 프롬프트로 전달하고, 응답 검증은 소비자에 맡긴다.
|
|
315
445
|
if (provider === "anthropic") {
|
|
316
446
|
parseAndValidateCallerSchemas(input);
|
|
447
|
+
|
|
317
448
|
return undefined;
|
|
318
449
|
}
|
|
319
450
|
|
|
320
451
|
const outputSchema = buildStrictOutputSchema(input, provider);
|
|
321
452
|
serializeAndValidateDispatchSchema(outputSchema, provider);
|
|
453
|
+
|
|
322
454
|
return outputSchema;
|
|
323
455
|
}
|
|
324
456
|
|
|
@@ -333,11 +465,12 @@ function buildRawOutputSchema(
|
|
|
333
465
|
}
|
|
334
466
|
|
|
335
467
|
export function completedDriverFromImageFailure(
|
|
336
|
-
|
|
468
|
+
cause: unknown,
|
|
337
469
|
serviceTier?: string,
|
|
338
470
|
): QueryOutput | undefined {
|
|
339
|
-
if (!(
|
|
340
|
-
|
|
471
|
+
if (!(cause instanceof ImageGenerationError) || !cause.completedDriver) return undefined;
|
|
472
|
+
|
|
473
|
+
return applyToolCallEmulation(toEmulationResult(cause.completedDriver, serviceTier), undefined, {
|
|
341
474
|
answerKind: "text",
|
|
342
475
|
});
|
|
343
476
|
}
|
|
@@ -347,8 +480,12 @@ function toEmulationResult(
|
|
|
347
480
|
result: GenerateResult,
|
|
348
481
|
serviceTier?: string,
|
|
349
482
|
): Omit<QueryOutput, "content" | "finishReason" | "runContext"> {
|
|
350
|
-
|
|
351
|
-
|
|
483
|
+
// A provider that labels its own cost (Grok ticks) is authoritative even at 0; otherwise only a
|
|
484
|
+
// positive provider cost (Claude Code total_cost_usd) wins over the price table.
|
|
485
|
+
const hasProviderCost =
|
|
486
|
+
result.costUsd !== undefined && (result.costSource === "provider" || result.costUsd > 0);
|
|
487
|
+
|
|
488
|
+
const emulationResult: Omit<QueryOutput, "content" | "finishReason" | "runContext"> = {
|
|
352
489
|
text: result.text,
|
|
353
490
|
tokenName: result.tokenName,
|
|
354
491
|
model: result.model,
|
|
@@ -379,8 +516,19 @@ function toEmulationResult(
|
|
|
379
516
|
},
|
|
380
517
|
serviceTier,
|
|
381
518
|
),
|
|
382
|
-
costSource: hasProviderCost ? "provider" : "pricing_table",
|
|
519
|
+
costSource: hasProviderCost ? (result.costSource ?? "provider") : "pricing_table",
|
|
383
520
|
};
|
|
521
|
+
|
|
522
|
+
if (result.providerMetadata?.xai) {
|
|
523
|
+
emulationResult.providerMetadata = { xai: result.providerMetadata.xai };
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
return emulationResult;
|
|
384
527
|
}
|
|
385
528
|
|
|
386
529
|
export const QgridDispatcher = new QgridDispatcherClass();
|
|
530
|
+
|
|
531
|
+
interface ResolvedDispatcher {
|
|
532
|
+
provider: ProviderId;
|
|
533
|
+
dispatcher: StreamingProviderDispatcher;
|
|
534
|
+
}
|