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