@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
|
@@ -10,20 +10,27 @@ import {
|
|
|
10
10
|
Puri,
|
|
11
11
|
transactional,
|
|
12
12
|
} from "sonamu";
|
|
13
|
+
import { z } from "zod";
|
|
13
14
|
|
|
14
15
|
import { SD } from "../../i18n/sd.generated";
|
|
15
16
|
import { calculateCostUsd } from "../../utils/providers/common/model-cost";
|
|
17
|
+
import {
|
|
18
|
+
isJsonObject,
|
|
19
|
+
isProviderId,
|
|
20
|
+
type JsonValue,
|
|
21
|
+
jsonValueSchema,
|
|
22
|
+
type ProviderId,
|
|
23
|
+
} from "../../utils/providers/common/provider-types";
|
|
24
|
+
import { type RequestLogStepSaveParams } from "../request-log-step/request-log-step.types";
|
|
16
25
|
import { type RequestLogSubsetKey, type RequestLogSubsetMapping } from "../sonamu.generated";
|
|
17
26
|
import { requestLogLoaderQueries, requestLogSubsetQueries } from "../sonamu.generated.sso";
|
|
27
|
+
import { renderJsonSchemaZodText, renderParsedJsonSchemaTypeText } from "./json-schema-type-text";
|
|
18
28
|
import {
|
|
19
|
-
|
|
20
|
-
renderParsedJsonSchemaTypeText,
|
|
21
|
-
} from "./json-schema-type-text";
|
|
22
|
-
import {
|
|
29
|
+
type HistoryItems,
|
|
23
30
|
type RequestLogListParams,
|
|
24
31
|
type RequestLogSaveParams,
|
|
25
32
|
type InputImages,
|
|
26
|
-
|
|
33
|
+
ToolDefinitions,
|
|
27
34
|
type ToolView,
|
|
28
35
|
} from "./request-log.types";
|
|
29
36
|
import { formatZodCode } from "./zod-code-format";
|
|
@@ -33,11 +40,28 @@ export const MICRO_USD = 1_000_000;
|
|
|
33
40
|
const REQUEST_LOG_RUN_LOCK_CLASS_ID = 718;
|
|
34
41
|
const TOOL_ENUM_VALUE_LIMIT = 6;
|
|
35
42
|
|
|
36
|
-
|
|
43
|
+
/**
|
|
44
|
+
* 비용을 알 수 없는 non-token 요청(Grok STT/TTS, ticks 없는 video). provider 비용 없이
|
|
45
|
+
* 토큰 0 으로 성공 저장되므로 SUM 은 건너뛰고 legacy 재계산도 $0 으로 매긴다 — 합계에
|
|
46
|
+
* 빠졌다는 신호를 따로 센다. 실패/중단/진행 중 row 는 과금 대상이 아니라 제외하고,
|
|
47
|
+
* 이미지 row 는 `unknownImageCostCount` 가 이미 센다.
|
|
48
|
+
*/
|
|
49
|
+
export const UNKNOWN_MEDIA_COST_PREDICATE =
|
|
50
|
+
"request_logs.status = 'succeeded' AND request_logs.cost_usd IS NULL AND request_logs.cost_source IS NULL" +
|
|
51
|
+
" AND request_logs.is_image_generation = false AND request_logs.input_tokens = 0 AND request_logs.output_tokens = 0";
|
|
52
|
+
|
|
53
|
+
/** Numeric aggregate column that node-postgres may deliver as bigint text. */
|
|
54
|
+
const bigintAggregate = z.coerce.number();
|
|
55
|
+
|
|
56
|
+
function decodeStoredTools(
|
|
57
|
+
value: ToolDefinitions | string | null | undefined,
|
|
58
|
+
): ToolDefinitions | null {
|
|
37
59
|
if (!value) return null;
|
|
38
|
-
|
|
60
|
+
|
|
61
|
+
if (Array.isArray(value)) return value;
|
|
62
|
+
|
|
39
63
|
try {
|
|
40
|
-
return JSON.parse(value)
|
|
64
|
+
return ToolDefinitions.safeParse(JSON.parse(value)).data ?? null;
|
|
41
65
|
} catch {
|
|
42
66
|
return null;
|
|
43
67
|
}
|
|
@@ -49,6 +73,47 @@ type ToolResultContinuation = {
|
|
|
49
73
|
isError?: boolean;
|
|
50
74
|
};
|
|
51
75
|
|
|
76
|
+
type RequestLogRunRow = Partial<RequestLogSaveParams>;
|
|
77
|
+
|
|
78
|
+
export type RequestLogStatus = NonNullable<RequestLogSaveParams["status"]>;
|
|
79
|
+
|
|
80
|
+
/** Step columns the caller supplies; `request_log_id` is bound by `appendStep`. */
|
|
81
|
+
export type RequestLogStepFields = Partial<Omit<RequestLogStepSaveParams, "request_log_id">> &
|
|
82
|
+
Pick<RequestLogStepSaveParams, "step_index" | "type">;
|
|
83
|
+
|
|
84
|
+
export interface FinishRunParams {
|
|
85
|
+
status: RequestLogStatus;
|
|
86
|
+
response?: string;
|
|
87
|
+
token_name?: string;
|
|
88
|
+
input_tokens?: number;
|
|
89
|
+
output_tokens?: number;
|
|
90
|
+
cache_read_tokens?: number;
|
|
91
|
+
cache_creation_tokens?: number;
|
|
92
|
+
cache_creation_5m_tokens?: number | null;
|
|
93
|
+
cache_creation_1h_tokens?: number | null;
|
|
94
|
+
duration_ms?: number;
|
|
95
|
+
requested_model_name?: string | null;
|
|
96
|
+
model_name?: string | null;
|
|
97
|
+
service_tier?: string | null;
|
|
98
|
+
fallback_count?: number | null;
|
|
99
|
+
cost_usd?: number | null;
|
|
100
|
+
cost_source?: string | null;
|
|
101
|
+
history?: HistoryItems;
|
|
102
|
+
error_message?: string;
|
|
103
|
+
tool_call_count?: number;
|
|
104
|
+
image_cost_usd?: number | null;
|
|
105
|
+
image_cost_method?: string | null;
|
|
106
|
+
is_image_generation?: boolean;
|
|
107
|
+
response_json_ok?: boolean | null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
type FinishRunUpdate = Partial<FinishRunParams> & { id: number; ttft_ms?: number };
|
|
111
|
+
|
|
112
|
+
/** Copies `key` only when the caller supplied it, so omitted columns stay untouched. */
|
|
113
|
+
function copyDefined<T, K extends keyof T>(target: Partial<T>, source: T, key: K): void {
|
|
114
|
+
if (source[key] !== undefined) target[key] = source[key];
|
|
115
|
+
}
|
|
116
|
+
|
|
52
117
|
type RequestLogStepAggregate = {
|
|
53
118
|
input_tokens: number;
|
|
54
119
|
output_tokens: number;
|
|
@@ -75,23 +140,24 @@ const STEP_AGGREGATE_SELECT = {
|
|
|
75
140
|
cost_source: "cost_source",
|
|
76
141
|
} as const;
|
|
77
142
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
143
|
+
type StepAggregateNumberField = Exclude<keyof typeof STEP_AGGREGATE_SELECT, "cost_source">;
|
|
144
|
+
|
|
145
|
+
type StepAggregateRow = { [K in StepAggregateNumberField]: number | null } & {
|
|
146
|
+
cost_source: string | null;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
function aggregateGenerateStepRows(rows: StepAggregateRow[]): RequestLogStepAggregate {
|
|
150
|
+
const sum = (field: StepAggregateNumberField): number =>
|
|
151
|
+
rows.reduce((total, row) => total + (row[field] ?? 0), 0);
|
|
152
|
+
|
|
153
|
+
const optionalSum = (field: StepAggregateNumberField): number | undefined =>
|
|
154
|
+
rows.some((row) => row[field] !== null) ? sum(field) : undefined;
|
|
155
|
+
|
|
156
|
+
const costSources = [
|
|
157
|
+
...new Set(rows.flatMap((row) => (row.cost_source ? [row.cost_source] : []))),
|
|
158
|
+
];
|
|
159
|
+
|
|
160
|
+
const aggregate: RequestLogStepAggregate = {
|
|
95
161
|
input_tokens: sum("input_tokens"),
|
|
96
162
|
output_tokens: sum("output_tokens"),
|
|
97
163
|
cache_read_tokens: sum("cache_read_tokens"),
|
|
@@ -101,8 +167,13 @@ function aggregateGenerateStepRows(rows: Array<Record<string, unknown>>): Reques
|
|
|
101
167
|
duration_ms: sum("duration_ms"),
|
|
102
168
|
fallback_count: sum("fallback_count"),
|
|
103
169
|
cost_usd: sum("cost_usd"),
|
|
104
|
-
cost_source: collapse("cost_source"),
|
|
105
170
|
};
|
|
171
|
+
|
|
172
|
+
if (costSources.length > 0) {
|
|
173
|
+
aggregate.cost_source = costSources.length === 1 ? costSources[0] : "mixed";
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return aggregate;
|
|
106
177
|
}
|
|
107
178
|
|
|
108
179
|
type RequestLogUsageRow = {
|
|
@@ -126,11 +197,19 @@ function isAnthropicUsageRow(row: Pick<RequestLogUsageRow, "token_name" | "model
|
|
|
126
197
|
);
|
|
127
198
|
}
|
|
128
199
|
|
|
200
|
+
/** Provider of a provider-qualified model id (`openai/`, `anthropic/`, `grok/`); legacy ids are unknown. */
|
|
201
|
+
export function providerOfModelName(modelName: string | null | undefined): ProviderId | "unknown" {
|
|
202
|
+
const slash = modelName?.indexOf("/") ?? -1;
|
|
203
|
+
const prefix = slash > 0 ? modelName?.slice(0, slash) : undefined;
|
|
204
|
+
|
|
205
|
+
return isProviderId(prefix) ? prefix : "unknown";
|
|
206
|
+
}
|
|
207
|
+
|
|
129
208
|
function canonicalModelName(modelName: string): string {
|
|
130
209
|
return modelName.includes("/") ? modelName.split("/").pop()! : modelName;
|
|
131
210
|
}
|
|
132
211
|
|
|
133
|
-
|
|
212
|
+
interface UsageForCost {
|
|
134
213
|
model: string | null;
|
|
135
214
|
inputTokens: number;
|
|
136
215
|
outputTokens: number;
|
|
@@ -138,36 +217,47 @@ function normalizedUsageForCost(row: RequestLogUsageRow): {
|
|
|
138
217
|
cacheCreationInputTokens: number;
|
|
139
218
|
cacheCreationInputTokens5m?: number;
|
|
140
219
|
cacheCreationInputTokens1h?: number;
|
|
141
|
-
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function normalizedUsageForCost(row: RequestLogUsageRow): UsageForCost {
|
|
142
223
|
const cacheRead = row.cache_read_tokens;
|
|
143
224
|
const cacheCreation = row.cache_creation_tokens;
|
|
144
225
|
const storedInput = row.input_tokens;
|
|
226
|
+
|
|
145
227
|
const legacyAnthropicSplitInput =
|
|
146
228
|
isAnthropicUsageRow(row) && storedInput < cacheRead + cacheCreation;
|
|
147
|
-
|
|
229
|
+
|
|
230
|
+
const usage: UsageForCost = {
|
|
148
231
|
model: row.model_name ? canonicalModelName(row.model_name) : null,
|
|
149
232
|
inputTokens: legacyAnthropicSplitInput ? storedInput + cacheRead + cacheCreation : storedInput,
|
|
150
233
|
outputTokens: row.output_tokens,
|
|
151
234
|
cachedInputTokens: cacheRead,
|
|
152
235
|
cacheCreationInputTokens: cacheCreation,
|
|
153
|
-
...(row.cache_creation_5m_tokens !== null && row.cache_creation_5m_tokens !== undefined
|
|
154
|
-
? { cacheCreationInputTokens5m: row.cache_creation_5m_tokens }
|
|
155
|
-
: {}),
|
|
156
|
-
...(row.cache_creation_1h_tokens !== null && row.cache_creation_1h_tokens !== undefined
|
|
157
|
-
? { cacheCreationInputTokens1h: row.cache_creation_1h_tokens }
|
|
158
|
-
: {}),
|
|
159
236
|
};
|
|
237
|
+
|
|
238
|
+
if (row.cache_creation_5m_tokens !== null && row.cache_creation_5m_tokens !== undefined) {
|
|
239
|
+
usage.cacheCreationInputTokens5m = row.cache_creation_5m_tokens;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (row.cache_creation_1h_tokens !== null && row.cache_creation_1h_tokens !== undefined) {
|
|
243
|
+
usage.cacheCreationInputTokens1h = row.cache_creation_1h_tokens;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return usage;
|
|
160
247
|
}
|
|
161
248
|
|
|
162
249
|
function normalizeLegacyAnthropicRow<T extends RequestLogUsageRow>(row: T): T {
|
|
163
250
|
// 새 row 는 당시의 provider/가격표 비용을 확정 저장한다. 현재 가격표로 덮어쓰지 않는다.
|
|
164
251
|
if (row.cost_source) return row;
|
|
165
252
|
const usage = normalizedUsageForCost(row);
|
|
253
|
+
|
|
166
254
|
if (usage.inputTokens === row.input_tokens) return row;
|
|
167
255
|
const normalized = { ...row, input_tokens: usage.inputTokens };
|
|
256
|
+
|
|
168
257
|
if (usage.model) {
|
|
169
258
|
normalized.cost_usd = Math.round(calculateCostUsd(usage.model, usage) * MICRO_USD);
|
|
170
259
|
}
|
|
260
|
+
|
|
171
261
|
return normalized;
|
|
172
262
|
}
|
|
173
263
|
|
|
@@ -190,20 +280,25 @@ const ORDERABLE_COLUMNS = {
|
|
|
190
280
|
cost_usd: "request_logs.cost_usd",
|
|
191
281
|
} as const;
|
|
192
282
|
|
|
283
|
+
const ORDERABLE_COLUMN_BY_KEY = new Map(Object.entries(ORDERABLE_COLUMNS));
|
|
284
|
+
|
|
193
285
|
function applyOrderBy(
|
|
194
286
|
qb: ReturnType<RequestLogModelClass["getSubsetQueries"]>["qb"],
|
|
195
287
|
orderBy: string,
|
|
196
288
|
): void {
|
|
197
289
|
const separator = orderBy.lastIndexOf("-");
|
|
198
|
-
const key = orderBy.slice(0, separator)
|
|
290
|
+
const key = orderBy.slice(0, separator);
|
|
199
291
|
const direction = orderBy.slice(separator + 1) === "asc" ? "asc" : "desc";
|
|
200
|
-
const column =
|
|
292
|
+
const column = ORDERABLE_COLUMN_BY_KEY.get(key);
|
|
201
293
|
|
|
202
294
|
if (!column) {
|
|
203
295
|
qb.orderBy("request_logs.id", "desc");
|
|
296
|
+
|
|
204
297
|
return;
|
|
205
298
|
}
|
|
299
|
+
|
|
206
300
|
qb.orderBy(column, direction);
|
|
301
|
+
|
|
207
302
|
// 동점 행의 순서가 페이지마다 흔들리지 않게 고유 컬럼으로 tie-break 한다.
|
|
208
303
|
if (key !== "id") qb.orderBy("request_logs.id", "desc");
|
|
209
304
|
}
|
|
@@ -232,6 +327,7 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
232
327
|
page: 1,
|
|
233
328
|
queryMode: "list",
|
|
234
329
|
});
|
|
330
|
+
|
|
235
331
|
if (!rows[0]) {
|
|
236
332
|
throw new NotFoundException(SD("error.entityNotFound")("RequestLog", id));
|
|
237
333
|
}
|
|
@@ -332,9 +428,7 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
332
428
|
const wdb = this.getPuri("w");
|
|
333
429
|
|
|
334
430
|
// register
|
|
335
|
-
spa.
|
|
336
|
-
wdb.ubRegister("request_logs", sp);
|
|
337
|
-
});
|
|
431
|
+
for (const sp of spa) wdb.ubRegister("request_logs", sp);
|
|
338
432
|
|
|
339
433
|
// transaction
|
|
340
434
|
return wdb.transaction(async (trx) => {
|
|
@@ -360,7 +454,8 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
360
454
|
}>
|
|
361
455
|
> {
|
|
362
456
|
const rdb = this.getPuri("r");
|
|
363
|
-
|
|
457
|
+
|
|
458
|
+
const rows = await rdb
|
|
364
459
|
.from("request_logs")
|
|
365
460
|
.select({
|
|
366
461
|
requested_model_name: "request_logs.requested_model_name",
|
|
@@ -368,36 +463,31 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
368
463
|
input_tokens: "request_logs.input_tokens",
|
|
369
464
|
cache_read_tokens: "request_logs.cache_read_tokens",
|
|
370
465
|
})
|
|
371
|
-
.where("request_logs.created_at", ">=", since)
|
|
372
|
-
requested_model_name: string | null;
|
|
373
|
-
status: string;
|
|
374
|
-
input_tokens: number;
|
|
375
|
-
cache_read_tokens: number;
|
|
376
|
-
}>;
|
|
466
|
+
.where("request_logs.created_at", ">=", since);
|
|
377
467
|
|
|
378
468
|
const byProvider = new Map<
|
|
379
469
|
string,
|
|
380
470
|
{ requests: number; errors: number; inputTokens: number; cacheReadTokens: number }
|
|
381
471
|
>();
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
const provider =
|
|
385
|
-
|
|
386
|
-
: model.startsWith("anthropic/")
|
|
387
|
-
? "anthropic"
|
|
388
|
-
: "unknown";
|
|
472
|
+
|
|
473
|
+
for (const row of rows) {
|
|
474
|
+
const provider = providerOfModelName(row.requested_model_name);
|
|
475
|
+
|
|
389
476
|
const agg = byProvider.get(provider) ?? {
|
|
390
477
|
requests: 0,
|
|
391
478
|
errors: 0,
|
|
392
479
|
inputTokens: 0,
|
|
393
480
|
cacheReadTokens: 0,
|
|
394
481
|
};
|
|
482
|
+
|
|
395
483
|
agg.requests += 1;
|
|
484
|
+
|
|
396
485
|
if (row.status === "error") agg.errors += 1;
|
|
397
486
|
agg.inputTokens += row.input_tokens;
|
|
398
487
|
agg.cacheReadTokens += row.cache_read_tokens;
|
|
399
488
|
byProvider.set(provider, agg);
|
|
400
|
-
}
|
|
489
|
+
}
|
|
490
|
+
|
|
401
491
|
return [...byProvider.entries()]
|
|
402
492
|
.map(([provider, agg]) => ({ provider, ...agg }))
|
|
403
493
|
.toSorted((a, b) => a.provider.localeCompare(b.provider));
|
|
@@ -415,27 +505,35 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
415
505
|
zod: string | null;
|
|
416
506
|
}> {
|
|
417
507
|
const rdb = this.getPuri("r");
|
|
418
|
-
|
|
508
|
+
|
|
509
|
+
const rows = await rdb
|
|
419
510
|
.from("request_logs")
|
|
420
511
|
.select({ json_schema: "request_logs.json_schema" })
|
|
421
|
-
.where("request_logs.id", id)
|
|
512
|
+
.where("request_logs.id", id);
|
|
513
|
+
|
|
422
514
|
const schema = rows[0]?.json_schema;
|
|
515
|
+
|
|
423
516
|
if (!schema) return { typescript: null, zod: null };
|
|
424
517
|
|
|
425
|
-
let parsed:
|
|
518
|
+
let parsed: JsonValue;
|
|
519
|
+
|
|
426
520
|
try {
|
|
521
|
+
// JSON.parse without a reviver yields only JSON values.
|
|
427
522
|
parsed = JSON.parse(schema);
|
|
428
523
|
} catch {
|
|
429
524
|
return { typescript: null, zod: null };
|
|
430
525
|
}
|
|
526
|
+
|
|
431
527
|
let zod: string | null = null;
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
528
|
+
|
|
529
|
+
if (isJsonObject(parsed) || parsed === true || parsed === false) {
|
|
530
|
+
try {
|
|
531
|
+
zod = formatZodCode(jsonSchemaToZod(parsed, { module: "none" }));
|
|
532
|
+
} catch {
|
|
533
|
+
zod = null;
|
|
534
|
+
}
|
|
438
535
|
}
|
|
536
|
+
|
|
439
537
|
return { typescript: renderParsedJsonSchemaTypeText(parsed), zod };
|
|
440
538
|
}
|
|
441
539
|
|
|
@@ -450,28 +548,38 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
450
548
|
*/
|
|
451
549
|
@api({ httpMethod: "GET", clients: ["axios", "tanstack-query"] })
|
|
452
550
|
async toolsView(id: number): Promise<ToolView[]> {
|
|
453
|
-
const row =
|
|
551
|
+
const row = await this.getPuri("r")
|
|
454
552
|
.from("request_logs")
|
|
455
553
|
.select({ tools: "request_logs.tools" })
|
|
456
554
|
.where("request_logs.id", id)
|
|
457
|
-
.first()
|
|
555
|
+
.first();
|
|
556
|
+
|
|
458
557
|
const tools = decodeStoredTools(row?.tools);
|
|
558
|
+
|
|
459
559
|
if (!tools) return [];
|
|
460
560
|
|
|
461
561
|
return tools.map((tool) => {
|
|
462
|
-
const inputSchema = (tool.inputSchema ?? {})
|
|
463
|
-
properties?: Record<string, unknown>;
|
|
464
|
-
};
|
|
465
|
-
const inputZod = renderJsonSchemaZodShapeText(inputSchema, TOOL_ENUM_VALUE_LIMIT);
|
|
466
|
-
const fullInputZod = renderJsonSchemaZodShapeText(inputSchema);
|
|
562
|
+
const inputSchema = jsonValueSchema.safeParse(tool.inputSchema ?? {}).data ?? {};
|
|
467
563
|
|
|
468
|
-
|
|
564
|
+
const inputZod = renderJsonSchemaZodText(inputSchema, TOOL_ENUM_VALUE_LIMIT);
|
|
565
|
+
const fullInputZod = renderJsonSchemaZodText(inputSchema);
|
|
566
|
+
|
|
567
|
+
const properties =
|
|
568
|
+
isJsonObject(inputSchema) && isJsonObject(inputSchema.properties)
|
|
569
|
+
? inputSchema.properties
|
|
570
|
+
: {};
|
|
571
|
+
|
|
572
|
+
const view: ToolView = {
|
|
469
573
|
name: tool.name,
|
|
470
|
-
|
|
471
|
-
parameterCount: Object.keys(inputSchema.properties ?? {}).length,
|
|
574
|
+
parameterCount: Object.keys(properties).length,
|
|
472
575
|
inputZod,
|
|
473
|
-
...(inputZod !== fullInputZod ? { fullInputZod } : {}),
|
|
474
576
|
};
|
|
577
|
+
|
|
578
|
+
if (tool.description !== undefined) view.description = tool.description;
|
|
579
|
+
|
|
580
|
+
if (inputZod !== fullInputZod) view.fullInputZod = fullInputZod;
|
|
581
|
+
|
|
582
|
+
return view;
|
|
475
583
|
});
|
|
476
584
|
}
|
|
477
585
|
|
|
@@ -484,7 +592,7 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
484
592
|
effort?: string | null;
|
|
485
593
|
service_tier?: string | null;
|
|
486
594
|
project_name?: string | null;
|
|
487
|
-
history?:
|
|
595
|
+
history?: HistoryItems;
|
|
488
596
|
input_images?: InputImages;
|
|
489
597
|
tools?: ToolDefinitions;
|
|
490
598
|
is_image_generation?: boolean;
|
|
@@ -492,7 +600,8 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
492
600
|
json_schema?: string | null;
|
|
493
601
|
}): Promise<number> {
|
|
494
602
|
const wdb = this.getPuri("w");
|
|
495
|
-
|
|
603
|
+
|
|
604
|
+
const row: RequestLogRunRow = {
|
|
496
605
|
user_prompt: params.user_prompt,
|
|
497
606
|
system_prompt: params.system_prompt ?? null,
|
|
498
607
|
// provider 실행 전이므로 serving model은 아직 알 수 없다.
|
|
@@ -514,60 +623,44 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
514
623
|
json_schema: params.json_schema ?? null,
|
|
515
624
|
is_structured:
|
|
516
625
|
params.is_structured ?? (params.json_schema !== null && params.json_schema !== undefined),
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
if (params.history !== undefined) row.history = params.history;
|
|
629
|
+
|
|
630
|
+
if (params.input_images) row.input_images = params.input_images;
|
|
631
|
+
|
|
632
|
+
if (params.tools !== undefined) row.tools = params.tools;
|
|
633
|
+
wdb.ubRegister("request_logs", row);
|
|
634
|
+
|
|
521
635
|
return wdb.transaction(async (trx) => {
|
|
522
636
|
const ids = await trx.ubUpsert("request_logs");
|
|
637
|
+
|
|
523
638
|
return ids[0]!;
|
|
524
639
|
});
|
|
525
640
|
}
|
|
526
641
|
|
|
527
|
-
async appendStep(requestLogId: number, step:
|
|
642
|
+
async appendStep(requestLogId: number, step: RequestLogStepFields): Promise<number> {
|
|
528
643
|
const wdb = this.getPuri("w");
|
|
529
644
|
wdb.ubRegister("request_log_steps", { request_log_id: requestLogId, ...step });
|
|
645
|
+
|
|
530
646
|
return wdb.transaction(async (trx) => {
|
|
531
647
|
const ids = await trx.ubUpsert("request_log_steps");
|
|
648
|
+
|
|
532
649
|
if (step.type === "tool_call") {
|
|
533
650
|
await trx.from("request_logs").where("id", requestLogId).increment("tool_call_count", 1);
|
|
534
651
|
}
|
|
652
|
+
|
|
535
653
|
return ids[0]!;
|
|
536
654
|
});
|
|
537
655
|
}
|
|
538
656
|
|
|
539
|
-
async finishRun(
|
|
540
|
-
requestLogId: number,
|
|
541
|
-
params: {
|
|
542
|
-
status: string;
|
|
543
|
-
response?: string;
|
|
544
|
-
token_name?: string;
|
|
545
|
-
input_tokens?: number;
|
|
546
|
-
output_tokens?: number;
|
|
547
|
-
cache_read_tokens?: number;
|
|
548
|
-
cache_creation_tokens?: number;
|
|
549
|
-
cache_creation_5m_tokens?: number | null;
|
|
550
|
-
cache_creation_1h_tokens?: number | null;
|
|
551
|
-
duration_ms?: number;
|
|
552
|
-
requested_model_name?: string | null;
|
|
553
|
-
model_name?: string | null;
|
|
554
|
-
service_tier?: string | null;
|
|
555
|
-
fallback_count?: number | null;
|
|
556
|
-
cost_usd?: number | null;
|
|
557
|
-
cost_source?: string | null;
|
|
558
|
-
history?: unknown;
|
|
559
|
-
error_message?: string;
|
|
560
|
-
tool_call_count?: number;
|
|
561
|
-
image_cost_usd?: number | null;
|
|
562
|
-
image_cost_method?: string | null;
|
|
563
|
-
is_image_generation?: boolean;
|
|
564
|
-
response_json_ok?: boolean | null;
|
|
565
|
-
},
|
|
566
|
-
): Promise<void> {
|
|
657
|
+
async finishRun(requestLogId: number, params: FinishRunParams): Promise<void> {
|
|
567
658
|
if (params.status === "succeeded" && !params.token_name) {
|
|
568
659
|
throw new Error("tokenName is required for succeeded runs");
|
|
569
660
|
}
|
|
570
|
-
|
|
661
|
+
|
|
662
|
+
const update: FinishRunUpdate = { id: requestLogId, status: params.status };
|
|
663
|
+
|
|
571
664
|
const fields = [
|
|
572
665
|
"response",
|
|
573
666
|
"token_name",
|
|
@@ -591,9 +684,9 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
591
684
|
"is_image_generation",
|
|
592
685
|
"response_json_ok",
|
|
593
686
|
] as const;
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
687
|
+
|
|
688
|
+
for (const key of fields) copyDefined(update, params, key);
|
|
689
|
+
|
|
597
690
|
if (params.history !== undefined) update.history = params.history;
|
|
598
691
|
update.ttft_ms = (await this.firstGenerateStepTtft(requestLogId)) ?? 0;
|
|
599
692
|
|
|
@@ -609,9 +702,12 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
609
702
|
.select({ model_name: "model_name" })
|
|
610
703
|
.where("id", requestLogId)
|
|
611
704
|
.first();
|
|
705
|
+
|
|
612
706
|
const effectiveModelName = params.model_name ?? row?.model_name;
|
|
707
|
+
|
|
613
708
|
if (effectiveModelName) {
|
|
614
709
|
const model = canonicalModelName(effectiveModelName);
|
|
710
|
+
|
|
615
711
|
const usage = normalizedUsageForCost({
|
|
616
712
|
token_name: params.token_name,
|
|
617
713
|
model_name: effectiveModelName,
|
|
@@ -622,6 +718,7 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
622
718
|
cache_creation_5m_tokens: params.cache_creation_5m_tokens,
|
|
623
719
|
cache_creation_1h_tokens: params.cache_creation_1h_tokens,
|
|
624
720
|
});
|
|
721
|
+
|
|
625
722
|
update.cost_usd = Math.round(
|
|
626
723
|
calculateCostUsd(model, {
|
|
627
724
|
inputTokens: usage.inputTokens,
|
|
@@ -653,7 +750,8 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
653
750
|
.orderBy("step_index", "asc")
|
|
654
751
|
.orderBy("id", "asc")
|
|
655
752
|
.first();
|
|
656
|
-
|
|
753
|
+
|
|
754
|
+
return row?.ttft_ms ?? null;
|
|
657
755
|
}
|
|
658
756
|
|
|
659
757
|
async aggregateStepUsage(requestLogId: number): Promise<RequestLogStepAggregate> {
|
|
@@ -662,7 +760,8 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
662
760
|
.select(STEP_AGGREGATE_SELECT)
|
|
663
761
|
.where("request_log_id", requestLogId)
|
|
664
762
|
.where("type", "generate");
|
|
665
|
-
|
|
763
|
+
|
|
764
|
+
return aggregateGenerateStepRows(rows);
|
|
666
765
|
}
|
|
667
766
|
|
|
668
767
|
/**
|
|
@@ -678,11 +777,13 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
678
777
|
const threshold = new Date(Date.now() - thresholdMs);
|
|
679
778
|
const candidateIds = await this.findStaleToolWaitingRunCandidates(threshold, limit);
|
|
680
779
|
const expiredIds: number[] = [];
|
|
780
|
+
|
|
681
781
|
for (const requestLogId of candidateIds) {
|
|
682
782
|
if (await this.tryExpireStaleToolWaitingRun(requestLogId, threshold, errorMessage)) {
|
|
683
783
|
expiredIds.push(requestLogId);
|
|
684
784
|
}
|
|
685
785
|
}
|
|
786
|
+
|
|
686
787
|
return expiredIds;
|
|
687
788
|
}
|
|
688
789
|
|
|
@@ -698,6 +799,7 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
698
799
|
.where("request_log_steps.tool_result", null)
|
|
699
800
|
.where("request_log_steps.error", null)
|
|
700
801
|
.limit(limit);
|
|
802
|
+
|
|
701
803
|
return rows.map(({ id }) => id);
|
|
702
804
|
}
|
|
703
805
|
|
|
@@ -708,10 +810,12 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
708
810
|
errorMessage: string,
|
|
709
811
|
): Promise<boolean> {
|
|
710
812
|
const wdb = this.getPuri("w");
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
813
|
+
|
|
814
|
+
const lockResult = await wdb.knex.raw<{ rows?: Array<{ acquired?: boolean }> }>(
|
|
815
|
+
"SELECT pg_try_advisory_xact_lock(?, ?) AS acquired",
|
|
816
|
+
[REQUEST_LOG_RUN_LOCK_CLASS_ID, requestLogId],
|
|
817
|
+
);
|
|
818
|
+
|
|
715
819
|
if (lockResult.rows?.[0]?.acquired !== true) return false;
|
|
716
820
|
|
|
717
821
|
// The follow-up path uses the same writer transaction lock. Recheck after
|
|
@@ -725,6 +829,7 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
725
829
|
.where("tool_result", null)
|
|
726
830
|
.where("error", null)
|
|
727
831
|
.first();
|
|
832
|
+
|
|
728
833
|
if (!unresolved) return false;
|
|
729
834
|
|
|
730
835
|
const stepRows = await wdb
|
|
@@ -732,7 +837,9 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
732
837
|
.select(STEP_AGGREGATE_SELECT)
|
|
733
838
|
.where("request_log_id", requestLogId)
|
|
734
839
|
.where("type", "generate");
|
|
735
|
-
|
|
840
|
+
|
|
841
|
+
const aggregate = aggregateGenerateStepRows(stepRows);
|
|
842
|
+
|
|
736
843
|
const firstTtft = await wdb
|
|
737
844
|
.from("request_log_steps")
|
|
738
845
|
.select({ ttft_ms: "ttft_ms" })
|
|
@@ -743,32 +850,36 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
743
850
|
.orderBy("id", "asc")
|
|
744
851
|
.first();
|
|
745
852
|
|
|
853
|
+
const expiry: Partial<RequestLogSaveParams> = {
|
|
854
|
+
status: "error",
|
|
855
|
+
error_message: errorMessage,
|
|
856
|
+
input_tokens: aggregate.input_tokens,
|
|
857
|
+
output_tokens: aggregate.output_tokens,
|
|
858
|
+
cache_read_tokens: aggregate.cache_read_tokens,
|
|
859
|
+
cache_creation_tokens: aggregate.cache_creation_tokens,
|
|
860
|
+
};
|
|
861
|
+
|
|
862
|
+
if (aggregate.cache_creation_5m_tokens !== undefined) {
|
|
863
|
+
expiry.cache_creation_5m_tokens = aggregate.cache_creation_5m_tokens;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
if (aggregate.cache_creation_1h_tokens !== undefined) {
|
|
867
|
+
expiry.cache_creation_1h_tokens = aggregate.cache_creation_1h_tokens;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
expiry.duration_ms = aggregate.duration_ms;
|
|
871
|
+
expiry.fallback_count = aggregate.fallback_count;
|
|
872
|
+
expiry.cost_usd = aggregate.cost_usd;
|
|
873
|
+
|
|
874
|
+
if (aggregate.cost_source !== undefined) expiry.cost_source = aggregate.cost_source;
|
|
875
|
+
expiry.ttft_ms = firstTtft?.ttft_ms ?? 0;
|
|
876
|
+
|
|
746
877
|
const updated = await wdb
|
|
747
878
|
.from("request_logs")
|
|
748
879
|
.where("id", requestLogId)
|
|
749
880
|
.where("status", "running")
|
|
750
|
-
.update(
|
|
751
|
-
|
|
752
|
-
error_message: errorMessage,
|
|
753
|
-
input_tokens: aggregate.input_tokens,
|
|
754
|
-
output_tokens: aggregate.output_tokens,
|
|
755
|
-
cache_read_tokens: aggregate.cache_read_tokens,
|
|
756
|
-
cache_creation_tokens: aggregate.cache_creation_tokens,
|
|
757
|
-
...(aggregate.cache_creation_5m_tokens !== undefined
|
|
758
|
-
? { cache_creation_5m_tokens: aggregate.cache_creation_5m_tokens }
|
|
759
|
-
: {}),
|
|
760
|
-
...(aggregate.cache_creation_1h_tokens !== undefined
|
|
761
|
-
? { cache_creation_1h_tokens: aggregate.cache_creation_1h_tokens }
|
|
762
|
-
: {}),
|
|
763
|
-
duration_ms: aggregate.duration_ms,
|
|
764
|
-
fallback_count: aggregate.fallback_count,
|
|
765
|
-
cost_usd: aggregate.cost_usd,
|
|
766
|
-
...(aggregate.cost_source !== undefined ? { cost_source: aggregate.cost_source } : {}),
|
|
767
|
-
ttft_ms:
|
|
768
|
-
firstTtft?.ttft_ms === null || firstTtft?.ttft_ms === undefined
|
|
769
|
-
? 0
|
|
770
|
-
: Number(firstTtft.ttft_ms),
|
|
771
|
-
});
|
|
881
|
+
.update(expiry);
|
|
882
|
+
|
|
772
883
|
return updated > 0;
|
|
773
884
|
}
|
|
774
885
|
|
|
@@ -792,7 +903,9 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
792
903
|
.select({ status: "status" })
|
|
793
904
|
.where("id", requestLogId)
|
|
794
905
|
.first();
|
|
906
|
+
|
|
795
907
|
if (!run) throw new Error(`request log run ${requestLogId} not found`);
|
|
908
|
+
|
|
796
909
|
if (run.status !== "running") {
|
|
797
910
|
throw new Error(`request log run ${requestLogId} is already ${run.status}`);
|
|
798
911
|
}
|
|
@@ -811,6 +924,7 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
811
924
|
.select({ max_step: Puri.max("step_index") })
|
|
812
925
|
.where("request_log_id", requestLogId)
|
|
813
926
|
.first();
|
|
927
|
+
|
|
814
928
|
return (row?.max_step ?? -1) + 1;
|
|
815
929
|
}
|
|
816
930
|
|
|
@@ -829,7 +943,7 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
829
943
|
*/
|
|
830
944
|
async totalCost(
|
|
831
945
|
rawParams: RequestLogListParams = { num: 0, page: 1 },
|
|
832
|
-
): Promise<{ usd: number; unknownImageCostCount: number }> {
|
|
946
|
+
): Promise<{ usd: number; unknownImageCostCount: number; unknownCostCount: number }> {
|
|
833
947
|
const params = {
|
|
834
948
|
num: 0,
|
|
835
949
|
page: 1,
|
|
@@ -839,10 +953,13 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
839
953
|
|
|
840
954
|
const { qb: totalQb } = this.getSubsetQueries("C");
|
|
841
955
|
this.applyListFilters(totalQb, params);
|
|
956
|
+
|
|
842
957
|
const sonamuFilter = params.sonamuFilter
|
|
843
958
|
? normalizeFilterQuery(params.sonamuFilter)
|
|
844
959
|
: undefined;
|
|
960
|
+
|
|
845
961
|
this.applySonamuFilters(totalQb, sonamuFilter);
|
|
962
|
+
|
|
846
963
|
// subset qb 는 컬럼 목록이 이미 SELECT 에 박혀 있어 집계를 얹으면 GROUP BY 에러가 난다.
|
|
847
964
|
// executeCountQuery 와 같은 방식으로 select 를 비우고 집계만 남긴다.
|
|
848
965
|
const stored = await totalQb
|
|
@@ -855,12 +972,14 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
855
972
|
unknownImageCostCount: Puri.rawNumber(
|
|
856
973
|
"COUNT(*) FILTER (WHERE request_logs.is_image_generation = true AND request_logs.image_cost_usd IS NULL)",
|
|
857
974
|
),
|
|
975
|
+
unknownCostCount: Puri.rawNumber(`COUNT(*) FILTER (WHERE ${UNKNOWN_MEDIA_COST_PREDICATE})`),
|
|
858
976
|
})
|
|
859
977
|
.first();
|
|
860
978
|
|
|
861
979
|
const { qb: legacyQb } = this.getSubsetQueries("C");
|
|
862
980
|
this.applyListFilters(legacyQb, params);
|
|
863
981
|
this.applySonamuFilters(legacyQb, sonamuFilter);
|
|
982
|
+
|
|
864
983
|
const legacyRows = await legacyQb
|
|
865
984
|
.whereRaw("request_logs.cost_source IS NULL OR request_logs.cost_usd IS NULL")
|
|
866
985
|
.clear("select")
|
|
@@ -876,13 +995,17 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
876
995
|
cost_usd: "request_logs.cost_usd",
|
|
877
996
|
});
|
|
878
997
|
|
|
879
|
-
|
|
998
|
+
// Postgres returns SUM/COUNT as bigint, which node-postgres delivers as text
|
|
999
|
+
// even though `Puri.rawNumber` types it as number.
|
|
1000
|
+
const storedTotal = bigintAggregate.parse(stored?.total ?? 0) / MICRO_USD;
|
|
880
1001
|
|
|
881
1002
|
// legacy row 는 위 SUM 에 저장값으로 이미 포함되어 있다. 재계산값과의 차액만 더한다.
|
|
882
1003
|
const usd = legacyRows.reduce((sum, row) => {
|
|
883
1004
|
const alreadySummed = Math.max(row.cost_usd ?? 0, 0) / MICRO_USD;
|
|
884
1005
|
const usage = normalizedUsageForCost(row);
|
|
1006
|
+
|
|
885
1007
|
if (!usage.model) return sum;
|
|
1008
|
+
|
|
886
1009
|
return (
|
|
887
1010
|
sum +
|
|
888
1011
|
calculateCostUsd(usage.model, {
|
|
@@ -896,7 +1019,12 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
896
1019
|
alreadySummed
|
|
897
1020
|
);
|
|
898
1021
|
}, storedTotal);
|
|
899
|
-
|
|
1022
|
+
|
|
1023
|
+
return {
|
|
1024
|
+
usd,
|
|
1025
|
+
unknownImageCostCount: bigintAggregate.parse(stored?.unknownImageCostCount ?? 0),
|
|
1026
|
+
unknownCostCount: bigintAggregate.parse(stored?.unknownCostCount ?? 0),
|
|
1027
|
+
};
|
|
900
1028
|
}
|
|
901
1029
|
|
|
902
1030
|
async distinctProjectNames(): Promise<string[]> {
|
|
@@ -908,6 +1036,7 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
908
1036
|
.select({
|
|
909
1037
|
project_name: "project_name",
|
|
910
1038
|
});
|
|
1039
|
+
|
|
911
1040
|
return rows.map((r) => r.project_name!);
|
|
912
1041
|
}
|
|
913
1042
|
|
|
@@ -920,6 +1049,7 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
920
1049
|
.select({
|
|
921
1050
|
model_name: "model_name",
|
|
922
1051
|
});
|
|
1052
|
+
|
|
923
1053
|
return rows.map((r) => r.model_name!);
|
|
924
1054
|
}
|
|
925
1055
|
|
|
@@ -933,6 +1063,7 @@ class RequestLogModelClass extends BaseModelClass<
|
|
|
933
1063
|
.table("request_log_steps")
|
|
934
1064
|
.whereIn("request_log_steps.request_log_id", ids)
|
|
935
1065
|
.delete();
|
|
1066
|
+
|
|
936
1067
|
return trx.table("request_logs").whereIn("request_logs.id", ids).delete();
|
|
937
1068
|
});
|
|
938
1069
|
|