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