@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
|
@@ -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;
|
|
@@ -235,6 +239,7 @@ const entityLabels = {
|
|
|
235
239
|
"entity.RequestLog.service_tier": "Requested OpenAI service tier",
|
|
236
240
|
"entity.RequestLog.effort": "effort level",
|
|
237
241
|
"entity.RequestLog.history": "inject_items 히스토리",
|
|
242
|
+
"entity.RequestLog.input_images": "현재 user turn 입력 이미지",
|
|
238
243
|
"entity.RequestLog.tools": "요청에 장착된 tool 정의 목록",
|
|
239
244
|
"entity.RequestLog.json_schema":
|
|
240
245
|
"structured output 요청의 JSON Schema 원문 (detail 의 response 타입 표시용)",
|
|
@@ -331,8 +336,11 @@ const entityLabels = {
|
|
|
331
336
|
|
|
332
337
|
// defaultLocale의 dictionary를 기준으로 키 추출
|
|
333
338
|
type RCKeys = typeof rcKeysKo;
|
|
339
|
+
|
|
334
340
|
type ProjectDictionary = typeof ko;
|
|
341
|
+
|
|
335
342
|
type EntityLabels = typeof entityLabels;
|
|
343
|
+
|
|
336
344
|
type RawMergedDictionary = RCKeys &
|
|
337
345
|
Omit<EntityLabels, keyof (RCKeys & ProjectDictionary)> &
|
|
338
346
|
ProjectDictionary;
|
|
@@ -343,7 +351,9 @@ export type MergedDictionary = {
|
|
|
343
351
|
? (...args: P) => string
|
|
344
352
|
: string;
|
|
345
353
|
};
|
|
354
|
+
|
|
346
355
|
export type DictKey = keyof MergedDictionary;
|
|
356
|
+
|
|
347
357
|
export type LocalizedString = string & { __brand: "LocalizedString" };
|
|
348
358
|
|
|
349
359
|
export function defineLocale(dict: Partial<MergedDictionary>) {
|
|
@@ -363,6 +373,7 @@ type SDReturnType<K extends DictKey> = MergedDictionary[K] extends (...args: inf
|
|
|
363
373
|
function getDictValue<K extends DictKey>(key: K, locale: string): SDReturnType<K> {
|
|
364
374
|
// 1. 지정된 locale에서 조회
|
|
365
375
|
const dict = dictionaries[locale];
|
|
376
|
+
|
|
366
377
|
if (dict?.[key] !== undefined) {
|
|
367
378
|
return dict[key] as unknown as SDReturnType<K>;
|
|
368
379
|
}
|
|
@@ -395,6 +406,7 @@ function getDictValue<K extends DictKey>(key: K, locale: string): SDReturnType<K
|
|
|
395
406
|
*/
|
|
396
407
|
export function SD<K extends DictKey>(key: K): SDReturnType<K> {
|
|
397
408
|
const locale = getCurrentLocale();
|
|
409
|
+
|
|
398
410
|
return getDictValue(key, locale);
|
|
399
411
|
}
|
|
400
412
|
|
|
@@ -429,12 +441,15 @@ type LocalizedBaseColumn<T> = {
|
|
|
429
441
|
* localizedColumn(tag, "name")
|
|
430
442
|
*/
|
|
431
443
|
type LocalizedColumnScalarValue = string | number | boolean | bigint;
|
|
444
|
+
|
|
432
445
|
type LocalizedColumnValue = string | string[];
|
|
446
|
+
|
|
433
447
|
type NestedLocalizedColumnValueFrom<V> = V extends string
|
|
434
448
|
? string
|
|
435
449
|
: V extends readonly string[]
|
|
436
450
|
? string[]
|
|
437
451
|
: never;
|
|
452
|
+
|
|
438
453
|
type LocalizedColumnValueFrom<V> = V extends string
|
|
439
454
|
? string
|
|
440
455
|
: V extends readonly string[]
|
|
@@ -444,6 +459,7 @@ type LocalizedColumnValueFrom<V> = V extends string
|
|
|
444
459
|
: V extends Partial<Record<(typeof SUPPORTED_LOCALES)[number], infer LV>>
|
|
445
460
|
? NestedLocalizedColumnValueFrom<LV>
|
|
446
461
|
: never;
|
|
462
|
+
|
|
447
463
|
type LocalizedColumnCandidate<T, K extends string> =
|
|
448
464
|
| (K extends keyof T ? T[K] : never)
|
|
449
465
|
| {
|
|
@@ -451,9 +467,11 @@ type LocalizedColumnCandidate<T, K extends string> =
|
|
|
451
467
|
? T[`${K}_${L}`]
|
|
452
468
|
: never;
|
|
453
469
|
}[(typeof SUPPORTED_LOCALES)[number]];
|
|
470
|
+
|
|
454
471
|
type LocalizedColumnReturn<T, K extends string> =
|
|
455
472
|
| LocalizedColumnValueFrom<LocalizedColumnCandidate<T, K>>
|
|
456
473
|
| undefined;
|
|
474
|
+
|
|
457
475
|
type LocaleValueMap = Partial<Record<(typeof SUPPORTED_LOCALES)[number], unknown>>;
|
|
458
476
|
|
|
459
477
|
function isLocalizedColumnValue(value: unknown): value is LocalizedColumnValue {
|
|
@@ -471,12 +489,13 @@ function isEmptyLocalizedColumnValue(value: unknown): value is null | undefined
|
|
|
471
489
|
return value === null || value === undefined || value === "";
|
|
472
490
|
}
|
|
473
491
|
|
|
474
|
-
function getNestedLocaleValue<T extends Record<string, unknown
|
|
492
|
+
function getNestedLocaleValue<T extends Record<string, unknown>>(
|
|
475
493
|
row: T,
|
|
476
|
-
column:
|
|
494
|
+
column: LocalizedBaseColumn<T>,
|
|
477
495
|
locale: (typeof SUPPORTED_LOCALES)[number],
|
|
478
496
|
): unknown {
|
|
479
497
|
const columnValue = row[column];
|
|
498
|
+
|
|
480
499
|
if (columnValue === null || typeof columnValue !== "object" || Array.isArray(columnValue)) {
|
|
481
500
|
return undefined;
|
|
482
501
|
}
|
|
@@ -495,6 +514,7 @@ export function localizedColumn<
|
|
|
495
514
|
);
|
|
496
515
|
const localizedKey = (column: K, locale: (typeof SUPPORTED_LOCALES)[number]) =>
|
|
497
516
|
`${column}_${locale}`;
|
|
517
|
+
|
|
498
518
|
const values = [
|
|
499
519
|
{ value: row[localizedKey(column, locale)], source: "direct" },
|
|
500
520
|
{ value: getNestedLocaleValue(row, column, locale), source: "nested" },
|
|
@@ -511,6 +531,7 @@ export function localizedColumn<
|
|
|
511
531
|
if (!isEmptyLocalizedColumnValue(value) && isLocalizedColumnValue(value)) {
|
|
512
532
|
return value as LocalizedColumnReturn<T, K>;
|
|
513
533
|
}
|
|
534
|
+
|
|
514
535
|
if (
|
|
515
536
|
source === "direct" &&
|
|
516
537
|
!isEmptyLocalizedColumnValue(value) &&
|
|
@@ -538,6 +559,7 @@ SD.enumLabels = (enumName: string): Record<string, LocalizedString> => {
|
|
|
538
559
|
}
|
|
539
560
|
|
|
540
561
|
const dictKey = `enum.${enumName}.${key}` as DictKey;
|
|
562
|
+
|
|
541
563
|
return getDictValue(dictKey, getCurrentLocale());
|
|
542
564
|
},
|
|
543
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 ...) 로 왕복을 줄인다.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type Knex } from "knex";
|
|
2
|
+
|
|
3
|
+
export async function up(knex: Knex): Promise<void> {
|
|
4
|
+
await knex.schema.alterTable("request_logs", (table) => {
|
|
5
|
+
// add
|
|
6
|
+
table.jsonb("input_images").nullable();
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export async function down(knex: Knex): Promise<void> {
|
|
11
|
+
await knex.schema.alterTable("request_logs", (table) => {
|
|
12
|
+
// rollback - add
|
|
13
|
+
table.dropColumns("input_images");
|
|
14
|
+
});
|
|
15
|
+
}
|
|
@@ -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) &&
|