@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
|
@@ -1,14 +1,21 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* conv-routing — 대화 연속성(cache affinity) 좌표 검증/구성.
|
|
3
5
|
*
|
|
4
6
|
* 모든 turn은 현재 input과 전체 history를 전달한다.
|
|
5
|
-
* OpenAI의 epoch=-1 좌표는 system/model hash와 opaque affinity를 검증한 뒤
|
|
7
|
+
* Direct provider(OpenAI, Grok)의 epoch=-1 좌표는 system/model hash와 opaque affinity를 검증한 뒤
|
|
6
8
|
* token 선택과 prompt-cache 힌트로만 사용한다.
|
|
7
9
|
*/
|
|
8
|
-
import {
|
|
10
|
+
import { z } from "zod";
|
|
9
11
|
|
|
10
12
|
import { type ReuseThreadCoord } from "../../utils/providers/common/provider-dispatcher";
|
|
11
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
jsonValueSchema,
|
|
15
|
+
type JsonValue,
|
|
16
|
+
type ProviderId,
|
|
17
|
+
type UserInput,
|
|
18
|
+
} from "../../utils/providers/common/provider-types";
|
|
12
19
|
import { type QgridThreadCoord, type QueryInput, type QgridToolResultInput } from "./qgrid.types";
|
|
13
20
|
|
|
14
21
|
export function systemHash(system?: string, modelNamespace?: string): string {
|
|
@@ -23,8 +30,10 @@ function toolResultsToText(toolResults: QgridToolResultInput[]): string {
|
|
|
23
30
|
const lines = toolResults.map((tr) => {
|
|
24
31
|
const name = tr.toolName ? ` (${tr.toolName})` : "";
|
|
25
32
|
const errMark = tr.isError ? " [error]" : "";
|
|
33
|
+
|
|
26
34
|
return `Tool result for call ${tr.toolCallId}${name}${errMark}: ${tr.output}`;
|
|
27
35
|
});
|
|
36
|
+
|
|
28
37
|
return `${lines.join("\n")}\n\nNow continue answering the user's request using these results.`;
|
|
29
38
|
}
|
|
30
39
|
|
|
@@ -40,22 +49,31 @@ export interface ConvDecision {
|
|
|
40
49
|
preferredTokenId?: number;
|
|
41
50
|
}
|
|
42
51
|
|
|
52
|
+
// HTTPS direct transport 로 prompt_cache_key affinity 를 쓰는 provider.
|
|
53
|
+
export type DirectProviderId = Extract<ProviderId, "openai" | "grok">;
|
|
54
|
+
|
|
43
55
|
export interface ConvRoutingOptions {
|
|
44
|
-
|
|
56
|
+
directProvider?: DirectProviderId;
|
|
57
|
+
// 보통 `<provider>/<model>`. 같은 system 이라도 provider/model 이 다르면 좌표를 공유하지 않는다.
|
|
45
58
|
modelNamespace?: string;
|
|
46
59
|
}
|
|
47
60
|
|
|
48
|
-
// 입력과 전체 history를 구성하고, 검증된
|
|
61
|
+
// 입력과 전체 history를 구성하고, 검증된 direct-provider cache affinity만 부가한다.
|
|
49
62
|
export function decideConvRouting(
|
|
50
63
|
input: QueryInput,
|
|
51
64
|
options: ConvRoutingOptions = {},
|
|
52
65
|
): ConvDecision {
|
|
66
|
+
const directProvider = options.directProvider;
|
|
67
|
+
|
|
53
68
|
const sysHash = systemHash(
|
|
54
69
|
input.system,
|
|
55
|
-
|
|
70
|
+
directProvider === undefined
|
|
71
|
+
? undefined
|
|
72
|
+
: (options.modelNamespace ?? input.model ?? directProvider),
|
|
56
73
|
);
|
|
74
|
+
|
|
57
75
|
const history: Array<JsonValue> | undefined = input.history
|
|
58
|
-
? (JSON.parse(input.history)
|
|
76
|
+
? z.array(jsonValueSchema).parse(JSON.parse(input.history))
|
|
59
77
|
: undefined;
|
|
60
78
|
|
|
61
79
|
const coord = input.runContext?.threadCoord;
|
|
@@ -63,14 +81,15 @@ export function decideConvRouting(
|
|
|
63
81
|
// 재사용 자격: 좌표 존재 + system 동일. sessionKey 격리 + systemHash 로 대화 동일성이
|
|
64
82
|
// 보장되고, 공통 prefix 는 백엔드가 prompt_cache_key 고정으로 알아서 캐시한다.
|
|
65
83
|
const directCoordEligible =
|
|
66
|
-
|
|
84
|
+
directProvider !== undefined &&
|
|
67
85
|
coord?.epoch === -1 &&
|
|
68
86
|
coord.systemHash === sysHash &&
|
|
69
87
|
input.cacheAffinityKey !== undefined &&
|
|
70
88
|
coord.threadId === input.cacheAffinityKey;
|
|
89
|
+
|
|
71
90
|
// affinity 를 요청하지 않은 one-shot 요청에 임의 키를 붙이면 transport 가 그 소켓을
|
|
72
91
|
// affinity 소켓으로 오인해 재사용되지 않을 연결을 계속 붙들어 둔다 → 키를 비워 둔다.
|
|
73
|
-
const cacheKey =
|
|
92
|
+
const cacheKey = directProvider === undefined ? undefined : input.cacheAffinityKey;
|
|
74
93
|
|
|
75
94
|
return {
|
|
76
95
|
// tool follow-up도 실행 user 줄에 결과를 사용해 계속 답하라는 안내를 담는다.
|
|
@@ -87,19 +106,25 @@ function buildDeltaInput(input: QueryInput): Array<UserInput> {
|
|
|
87
106
|
if (input.toolResults && input.toolResults.length > 0) {
|
|
88
107
|
return [{ type: "text", text: toolResultsToText(input.toolResults), text_elements: [] }];
|
|
89
108
|
}
|
|
109
|
+
|
|
90
110
|
if (input.input && input.input.length > 0) {
|
|
91
111
|
const hasText = input.input.some((part) => part.type === "text");
|
|
112
|
+
|
|
92
113
|
const parts: Array<UserInput> = input.input.map((part) => {
|
|
93
114
|
if (part.type === "text") {
|
|
94
115
|
return { type: "text", text: part.text, text_elements: part.text_elements };
|
|
95
116
|
}
|
|
117
|
+
|
|
96
118
|
return { type: "image", url: part.url };
|
|
97
119
|
});
|
|
120
|
+
|
|
98
121
|
if (!hasText && input.prompt.length > 0) {
|
|
99
122
|
return [{ type: "text", text: input.prompt, text_elements: [] }, ...parts];
|
|
100
123
|
}
|
|
124
|
+
|
|
101
125
|
return parts;
|
|
102
126
|
}
|
|
127
|
+
|
|
103
128
|
return [{ type: "text", text: input.prompt, text_elements: [] }];
|
|
104
129
|
}
|
|
105
130
|
|
|
@@ -117,6 +142,7 @@ export function issueConvContext(
|
|
|
117
142
|
systemHash: decision.systemHash,
|
|
118
143
|
};
|
|
119
144
|
}
|
|
145
|
+
|
|
120
146
|
return {
|
|
121
147
|
workerId: threadCoord.workerId,
|
|
122
148
|
threadId: threadCoord.threadId,
|
|
@@ -45,12 +45,16 @@ export function buildReminderContext(
|
|
|
45
45
|
userMap: Map<string, string>,
|
|
46
46
|
): string {
|
|
47
47
|
const showLabel = tokens.length > 1;
|
|
48
|
+
|
|
48
49
|
const lines = tokens.map((token) => {
|
|
49
50
|
const mention = mentionFor(token.name, userMap);
|
|
50
51
|
const label = token.name ?? "unnamed";
|
|
52
|
+
|
|
51
53
|
if (!showLabel) return mention;
|
|
54
|
+
|
|
52
55
|
return mention ? `${mention} ${label}` : label;
|
|
53
56
|
});
|
|
57
|
+
|
|
54
58
|
return [...lines, "재로그인이 필요합니다"].filter(Boolean).join("\n");
|
|
55
59
|
}
|
|
56
60
|
|
|
@@ -59,6 +63,7 @@ async function sendReminder(
|
|
|
59
63
|
mode: "scheduled" | "manual",
|
|
60
64
|
): Promise<number> {
|
|
61
65
|
const expired = await deps.findReauthRequired();
|
|
66
|
+
|
|
62
67
|
if (expired.length === 0) return 0;
|
|
63
68
|
|
|
64
69
|
const userMap = deps.getSlackUserMap();
|
|
@@ -72,6 +77,7 @@ async function sendReminder(
|
|
|
72
77
|
urgent: mode === "manual",
|
|
73
78
|
throwOnFailure: mode === "manual",
|
|
74
79
|
});
|
|
80
|
+
|
|
75
81
|
return expired.length;
|
|
76
82
|
}
|
|
77
83
|
|
|
@@ -95,12 +101,14 @@ function scheduleExpiredTokenReminder(runNow: boolean, deps: ExpiredTokenReminde
|
|
|
95
101
|
// 주기 값과 별개인 스위치다. 꺼도 주기는 남아 있어 다시 켤 때 고르던 값이 그대로다.
|
|
96
102
|
if (deps.readSetting("slack.remindersEnabled", "SLACK_REMINDERS_ENABLED") === "false") {
|
|
97
103
|
logger.info("expired token reminder disabled");
|
|
104
|
+
|
|
98
105
|
return;
|
|
99
106
|
}
|
|
100
107
|
|
|
101
108
|
const minutes = Number(
|
|
102
109
|
deps.readSetting("slack.expiryReminderMinutes", "SLACK_EXPIRY_REMINDER_INTERVAL_MINUTES") ?? 0,
|
|
103
110
|
);
|
|
111
|
+
|
|
104
112
|
if (!Number.isFinite(minutes) || minutes <= 0) return;
|
|
105
113
|
|
|
106
114
|
logger.info(
|
|
@@ -109,7 +117,7 @@ function scheduleExpiredTokenReminder(runNow: boolean, deps: ExpiredTokenReminde
|
|
|
109
117
|
|
|
110
118
|
const run = () =>
|
|
111
119
|
sendReminder(deps, "scheduled").catch((e) =>
|
|
112
|
-
logger.warn(`reminder failed: ${
|
|
120
|
+
logger.warn(`reminder failed: ${e instanceof Error ? e.message : String(e)}`),
|
|
113
121
|
);
|
|
114
122
|
|
|
115
123
|
if (runNow) void run();
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { createHash, randomBytes } from "node:crypto";
|
|
5
5
|
|
|
6
6
|
import { getLogger } from "@logtape/logtape";
|
|
7
|
+
import { z } from "zod";
|
|
7
8
|
|
|
8
9
|
export type AnthropicUsageRaw = {
|
|
9
10
|
error?: string;
|
|
@@ -11,6 +12,35 @@ export type AnthropicUsageRaw = {
|
|
|
11
12
|
seven_day?: { utilization: number | null; resets_at: string | null } | null;
|
|
12
13
|
seven_day_overage_included?: { utilization: number | null; resets_at: string | null } | null;
|
|
13
14
|
};
|
|
15
|
+
|
|
16
|
+
const usageWindowSchema = z
|
|
17
|
+
.object({ utilization: z.number().nullable(), resets_at: z.string().nullable() })
|
|
18
|
+
.nullable()
|
|
19
|
+
.optional();
|
|
20
|
+
|
|
21
|
+
const anthropicUsageRawSchema: z.ZodType<AnthropicUsageRaw> = z.looseObject({
|
|
22
|
+
error: z.string().optional(),
|
|
23
|
+
five_hour: usageWindowSchema,
|
|
24
|
+
seven_day: usageWindowSchema,
|
|
25
|
+
seven_day_overage_included: usageWindowSchema,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const tokenExchangeResponseSchema = z.object({
|
|
29
|
+
access_token: z.string(),
|
|
30
|
+
refresh_token: z.string(),
|
|
31
|
+
expires_in: z.number(),
|
|
32
|
+
scope: z.string(),
|
|
33
|
+
account: z.object({ uuid: z.string(), email_address: z.string() }).optional(),
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// A refresh response may omit refresh_token; the caller then keeps the current one.
|
|
37
|
+
const tokenRefreshResponseSchema = z.object({
|
|
38
|
+
access_token: z.string(),
|
|
39
|
+
refresh_token: z.string().optional(),
|
|
40
|
+
expires_in: z.number(),
|
|
41
|
+
scope: z.string(),
|
|
42
|
+
});
|
|
43
|
+
|
|
14
44
|
export type AnthropicUsageWithMeta = {
|
|
15
45
|
data: AnthropicUsageRaw;
|
|
16
46
|
cachedAt: number;
|
|
@@ -21,6 +51,7 @@ const logger = getLogger(["qgrid", "oauth"]);
|
|
|
21
51
|
const CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
|
|
22
52
|
const AUTHORIZE_URL = "https://claude.com/cai/oauth/authorize";
|
|
23
53
|
const TOKEN_URL = "https://platform.claude.com/v1/oauth/token";
|
|
54
|
+
|
|
24
55
|
// client 허용 목록에 있는 콘솔 콜백. 인증 후 콘솔 페이지가 `code#state`를 표시하고
|
|
25
56
|
// 사용자가 붙여넣는 코드 플로우(Claude Code CLI와 동일)에 사용한다.
|
|
26
57
|
export const CONSOLE_CALLBACK_URL = "https://console.anthropic.com/oauth/code/callback";
|
|
@@ -48,10 +79,17 @@ function base64URLEncode(buffer: Buffer): string {
|
|
|
48
79
|
return buffer.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
49
80
|
}
|
|
50
81
|
|
|
51
|
-
export
|
|
82
|
+
export interface PKCEChallenge {
|
|
83
|
+
codeVerifier: string;
|
|
84
|
+
codeChallenge: string;
|
|
85
|
+
state: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function generatePKCE(): PKCEChallenge {
|
|
52
89
|
const codeVerifier = base64URLEncode(randomBytes(32));
|
|
53
90
|
const codeChallenge = base64URLEncode(createHash("sha256").update(codeVerifier).digest());
|
|
54
91
|
const state = base64URLEncode(randomBytes(32));
|
|
92
|
+
|
|
55
93
|
return { codeVerifier, codeChallenge, state };
|
|
56
94
|
}
|
|
57
95
|
|
|
@@ -65,6 +103,7 @@ export function buildAuthUrl(codeChallenge: string, state: string, redirectUri:
|
|
|
65
103
|
url.searchParams.append("code_challenge", codeChallenge);
|
|
66
104
|
url.searchParams.append("code_challenge_method", "S256");
|
|
67
105
|
url.searchParams.append("state", state);
|
|
106
|
+
|
|
68
107
|
return url.toString();
|
|
69
108
|
}
|
|
70
109
|
|
|
@@ -95,18 +134,13 @@ export async function exchangeCodeForTokens(
|
|
|
95
134
|
state,
|
|
96
135
|
}),
|
|
97
136
|
});
|
|
137
|
+
|
|
98
138
|
if (!res.ok) {
|
|
99
139
|
const text = await res.text();
|
|
100
140
|
throw new Error(`Token exchange failed (${res.status}): ${text}`);
|
|
101
141
|
}
|
|
102
142
|
|
|
103
|
-
const data = (await res.json())
|
|
104
|
-
access_token: string;
|
|
105
|
-
refresh_token: string;
|
|
106
|
-
expires_in: number;
|
|
107
|
-
scope: string;
|
|
108
|
-
account?: { uuid: string; email_address: string };
|
|
109
|
-
};
|
|
143
|
+
const data = tokenExchangeResponseSchema.parse(await res.json());
|
|
110
144
|
|
|
111
145
|
return {
|
|
112
146
|
accessToken: data.access_token,
|
|
@@ -148,16 +182,13 @@ export async function refreshAccessToken(refreshToken: string): Promise<OAuthTok
|
|
|
148
182
|
scope: REFRESH_SCOPES.join(" "),
|
|
149
183
|
}),
|
|
150
184
|
});
|
|
185
|
+
|
|
151
186
|
if (!res.ok) {
|
|
152
187
|
const text = await res.text();
|
|
153
188
|
throw new RefreshFailedError(res.status, text);
|
|
154
189
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
refresh_token: string;
|
|
158
|
-
expires_in: number;
|
|
159
|
-
scope: string;
|
|
160
|
-
};
|
|
190
|
+
|
|
191
|
+
const data = tokenRefreshResponseSchema.parse(await res.json());
|
|
161
192
|
|
|
162
193
|
return {
|
|
163
194
|
accessToken: data.access_token,
|
|
@@ -181,6 +212,7 @@ export async function fetchUsage(accessToken: string): Promise<AnthropicUsageRaw
|
|
|
181
212
|
export async function fetchUsageWithMeta(accessToken: string): Promise<AnthropicUsageWithMeta> {
|
|
182
213
|
const cacheKey = accessToken.slice(-10);
|
|
183
214
|
const cached = usageCache[cacheKey];
|
|
215
|
+
|
|
184
216
|
if (cached && Date.now() - cached.cachedAt < USAGE_API_CACHE_TTL) {
|
|
185
217
|
return cached;
|
|
186
218
|
}
|
|
@@ -193,11 +225,13 @@ export async function fetchUsageWithMeta(accessToken: string): Promise<Anthropic
|
|
|
193
225
|
},
|
|
194
226
|
signal: AbortSignal.timeout(5000),
|
|
195
227
|
});
|
|
228
|
+
|
|
196
229
|
if (!res.ok) {
|
|
197
230
|
const text = await res.text();
|
|
198
231
|
|
|
199
232
|
// 파싱 시도해서 에러 메시지 추출
|
|
200
233
|
let errorMessage = `Error ${res.status}`;
|
|
234
|
+
|
|
201
235
|
try {
|
|
202
236
|
const parsed = JSON.parse(text);
|
|
203
237
|
errorMessage = parsed.error?.message ?? errorMessage;
|
|
@@ -214,12 +248,14 @@ export async function fetchUsageWithMeta(accessToken: string): Promise<Anthropic
|
|
|
214
248
|
const errorResult = { error: errorMessage };
|
|
215
249
|
const entry = { data: errorResult, cachedAt: Date.now() };
|
|
216
250
|
usageCache[cacheKey] = entry;
|
|
251
|
+
|
|
217
252
|
return entry;
|
|
218
253
|
}
|
|
219
254
|
|
|
220
|
-
const data = (await res.json())
|
|
255
|
+
const data = anthropicUsageRawSchema.parse(await res.json());
|
|
221
256
|
// cache invalidate
|
|
222
257
|
const entry = { data, cachedAt: Date.now() };
|
|
223
258
|
usageCache[cacheKey] = entry;
|
|
259
|
+
|
|
224
260
|
return entry;
|
|
225
261
|
}
|
|
@@ -42,6 +42,7 @@ export function resolveImageGenerationOptions(
|
|
|
42
42
|
options: ImageGenerationOptions | undefined,
|
|
43
43
|
): ResolvedImageGenerationOptions {
|
|
44
44
|
const size = options?.size;
|
|
45
|
+
|
|
45
46
|
return {
|
|
46
47
|
quality: options?.quality ?? DEFAULT_IMAGE_GENERATION_QUALITY,
|
|
47
48
|
// Unknown/custom sizes use the default price, without changing output hints.
|
|
@@ -61,7 +62,9 @@ export function imageGenerationCostMethod(
|
|
|
61
62
|
) {
|
|
62
63
|
return "estimated:gpt-image-2:reported-usage:public-prices:conservative";
|
|
63
64
|
}
|
|
65
|
+
|
|
64
66
|
const resolved = resolveImageGenerationOptions(options);
|
|
67
|
+
|
|
65
68
|
return `assumed:${CODEX_IMAGE_GENERATION_MODEL}:${resolved.quality}:${resolved.size}:png`;
|
|
66
69
|
}
|
|
67
70
|
|
|
@@ -71,8 +74,10 @@ export function estimateImageGenerationCostMicroUsd(
|
|
|
71
74
|
): number | null {
|
|
72
75
|
const images = result.content.filter((item) => item.type === "image");
|
|
73
76
|
const imageCount = images.length;
|
|
77
|
+
|
|
74
78
|
if (imageCount === 0) return null;
|
|
75
79
|
const usage = images.find((image) => image.generation?.usage)?.generation?.usage;
|
|
80
|
+
|
|
76
81
|
if (usage) {
|
|
77
82
|
// Response-level image usage is carried by its first image only.
|
|
78
83
|
// Do not multiply it by output count or price it as the requested text driver.
|
|
@@ -82,15 +87,19 @@ export function estimateImageGenerationCostMicroUsd(
|
|
|
82
87
|
// Use a consistent reported split; unknown input is conservatively priced as
|
|
83
88
|
// images. Cache discounts and private subscription billing remain unknown.
|
|
84
89
|
const details = usage.input_tokens_details;
|
|
90
|
+
|
|
85
91
|
const textTokens =
|
|
86
92
|
details && details.text_tokens + details.image_tokens <= usage.input_tokens
|
|
87
93
|
? details.text_tokens
|
|
88
94
|
: 0;
|
|
95
|
+
|
|
89
96
|
return Math.round(
|
|
90
97
|
textTokens * 5 + (usage.input_tokens - textTokens) * 8 + usage.output_tokens * 30,
|
|
91
98
|
);
|
|
92
99
|
}
|
|
100
|
+
|
|
93
101
|
const resolved = resolveImageGenerationOptions(options);
|
|
94
102
|
const unitCost = IMAGE_OUTPUT_COST_MICRO_USD[resolved.quality][resolved.size];
|
|
103
|
+
|
|
95
104
|
return imageCount * unitCost;
|
|
96
105
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type JsonValue } from "../../utils/providers/common/provider-types";
|
|
1
2
|
import {
|
|
2
3
|
CODEX_IMAGE_GENERATION_MODEL,
|
|
3
4
|
resolveImageGenerationOptions,
|
|
@@ -26,7 +27,9 @@ export function formatResponseForLog(result: QueryOutput): string {
|
|
|
26
27
|
return result.content
|
|
27
28
|
.flatMap((item) => {
|
|
28
29
|
if (item.type === "text") return [item.text];
|
|
30
|
+
|
|
29
31
|
if (item.type === "image") return [formatImagePartForLog(item)];
|
|
32
|
+
|
|
30
33
|
return [];
|
|
31
34
|
})
|
|
32
35
|
.filter((part) => part.length > 0)
|
|
@@ -39,6 +42,7 @@ export function getImageParts(result: QueryOutput): Extract<QgridContent, { type
|
|
|
39
42
|
|
|
40
43
|
export function formatImagePartForLog(image: Extract<QgridContent, { type: "image" }>): string {
|
|
41
44
|
const alt = escapeHtmlAttribute(image.revisedPrompt ?? "generated image");
|
|
45
|
+
|
|
42
46
|
return `<img src="data:${image.mediaType ?? "image/png"};base64,${image.data}" alt="${alt}" />`;
|
|
43
47
|
}
|
|
44
48
|
|
|
@@ -47,29 +51,38 @@ export function imageGenerationToolArgs(
|
|
|
47
51
|
options: { includeInputImages?: boolean; generation?: ImageGenerationMetadata } = {},
|
|
48
52
|
): string {
|
|
49
53
|
const resolved = resolveImageGenerationOptions(args.imageGenerationOptions);
|
|
54
|
+
|
|
50
55
|
const inputImages =
|
|
51
56
|
options.includeInputImages === false ? [] : extractInputImagesForToolArgs(args);
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
57
|
+
|
|
58
|
+
// Keys are assigned in their serialized order; request logs store this JSON text.
|
|
59
|
+
const toolArgs: Record<string, JsonValue> = {};
|
|
60
|
+
toolArgs.prompt = args.prompt;
|
|
61
|
+
|
|
62
|
+
if (inputImages.length > 0) toolArgs.inputImages = inputImages;
|
|
63
|
+
toolArgs.driverModel = args.model ?? null;
|
|
64
|
+
const tool: Record<string, JsonValue> = {};
|
|
65
|
+
Object.assign(tool, CODEX_IMAGE_GENERATION_TOOL_CONFIG);
|
|
66
|
+
|
|
67
|
+
if (args.imageGenerationOptions?.outputFormat) {
|
|
68
|
+
tool.outputFormat = args.imageGenerationOptions.outputFormat;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
toolArgs.tool = tool;
|
|
72
|
+
|
|
73
|
+
if (args.imageGenerationOptions) toolArgs.requestedOptions = args.imageGenerationOptions;
|
|
74
|
+
|
|
75
|
+
if (options.generation) {
|
|
76
|
+
toolArgs.observedGeneration = options.generation;
|
|
77
|
+
} else {
|
|
78
|
+
toolArgs.pricingAssumption = {
|
|
79
|
+
model: CODEX_IMAGE_GENERATION_MODEL,
|
|
80
|
+
quality: resolved.quality,
|
|
81
|
+
size: resolved.size,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return JSON.stringify(toolArgs);
|
|
73
86
|
}
|
|
74
87
|
|
|
75
88
|
export function buildImageGenerationToolSteps(
|
|
@@ -101,16 +114,21 @@ export function buildImageGenerationToolSteps(
|
|
|
101
114
|
}));
|
|
102
115
|
}
|
|
103
116
|
|
|
104
|
-
|
|
117
|
+
type LoggedInputImage = {
|
|
105
118
|
mediaType?: string;
|
|
106
119
|
data?: string;
|
|
107
120
|
url?: string;
|
|
108
121
|
byteSize?: number;
|
|
109
|
-
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export function extractInputImagesForToolArgs(args: QueryInput): LoggedInputImage[] {
|
|
110
125
|
const images = args.input?.filter((item) => item.type === "image") ?? [];
|
|
126
|
+
|
|
111
127
|
return images.map((image) => {
|
|
112
128
|
const dataUrl = parseDataUrl(image.url);
|
|
129
|
+
|
|
113
130
|
if (!dataUrl) return { url: image.url };
|
|
131
|
+
|
|
114
132
|
if (dataUrl.isBase64 && dataUrl.mediaType.toLowerCase().startsWith("image/")) {
|
|
115
133
|
return {
|
|
116
134
|
mediaType: dataUrl.mediaType,
|
|
@@ -118,11 +136,15 @@ function extractInputImagesForToolArgs(args: QueryInput): Array<{
|
|
|
118
136
|
byteSize: base64ByteSize(dataUrl.data),
|
|
119
137
|
};
|
|
120
138
|
}
|
|
121
|
-
|
|
139
|
+
|
|
140
|
+
const logged: LoggedInputImage = {
|
|
122
141
|
mediaType: dataUrl.mediaType,
|
|
123
142
|
url: `[data-url ${image.url.length} chars]`,
|
|
124
|
-
...(dataUrl.isBase64 ? { byteSize: base64ByteSize(dataUrl.data) } : {}),
|
|
125
143
|
};
|
|
144
|
+
|
|
145
|
+
if (dataUrl.isBase64) logged.byteSize = base64ByteSize(dataUrl.data);
|
|
146
|
+
|
|
147
|
+
return logged;
|
|
126
148
|
});
|
|
127
149
|
}
|
|
128
150
|
|
|
@@ -130,13 +152,16 @@ function parseDataUrl(
|
|
|
130
152
|
value: string,
|
|
131
153
|
): { mediaType: string; data: string; isBase64: boolean } | null {
|
|
132
154
|
const match = /^data:([^;,]+)((?:;[^,]*)*),(.*)$/is.exec(value);
|
|
155
|
+
|
|
133
156
|
if (!match) return null;
|
|
134
157
|
const params = match[2]!.toLowerCase().split(";").filter(Boolean);
|
|
158
|
+
|
|
135
159
|
return { mediaType: match[1]!, data: match[3]!, isBase64: params.includes("base64") };
|
|
136
160
|
}
|
|
137
161
|
|
|
138
162
|
function base64ByteSize(value: string): number {
|
|
139
163
|
const normalized = /\s/.test(value) ? value.replace(/\s/g, "") : value;
|
|
140
164
|
const padding = normalized.endsWith("==") ? 2 : normalized.endsWith("=") ? 1 : 0;
|
|
165
|
+
|
|
141
166
|
return Math.max(Math.floor((normalized.length * 3) / 4) - padding, 0);
|
|
142
167
|
}
|
|
@@ -112,6 +112,25 @@ describe("qgrid run lifecycle start", () => {
|
|
|
112
112
|
});
|
|
113
113
|
});
|
|
114
114
|
|
|
115
|
+
it.each([undefined, "Caller system"])(
|
|
116
|
+
"logs the Anthropic schema instructions with system=%s",
|
|
117
|
+
async (system) => {
|
|
118
|
+
const jsonSchema = '{"type":"object","properties":{"answer":{"type":"string"}}}';
|
|
119
|
+
await beforeQuery({
|
|
120
|
+
prompt: "hi",
|
|
121
|
+
model: "anthropic/claude-opus-5-5",
|
|
122
|
+
system,
|
|
123
|
+
jsonSchema,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
const saved = createRunMock.mock.calls[0]![0];
|
|
127
|
+
expect(saved.system_prompt).toContain("## Output Format");
|
|
128
|
+
expect(saved.system_prompt).toContain(`<output-json-schema>\n${jsonSchema}\n</output-json-schema>`);
|
|
129
|
+
if (system) expect(saved.system_prompt).toMatch(/^Caller system\n\n/);
|
|
130
|
+
expect(saved.json_schema).toBe(jsonSchema);
|
|
131
|
+
},
|
|
132
|
+
);
|
|
133
|
+
|
|
115
134
|
it.each([
|
|
116
135
|
["openai/gpt-6-sol", "fast", "fast"],
|
|
117
136
|
["openai/gpt-6-sol", "flex", "flex"],
|
|
@@ -122,6 +141,20 @@ describe("qgrid run lifecycle start", () => {
|
|
|
122
141
|
expect(createRunMock).toHaveBeenCalledWith(expect.objectContaining({ service_tier: expected }));
|
|
123
142
|
});
|
|
124
143
|
|
|
144
|
+
it("logs current-turn input images on the run", async () => {
|
|
145
|
+
await beforeQuery({
|
|
146
|
+
prompt: "describe",
|
|
147
|
+
model: "openai/gpt-6-sol",
|
|
148
|
+
input: [
|
|
149
|
+
{ type: "text", text: "describe", text_elements: [] },
|
|
150
|
+
{ type: "image", url: "data:image/jpeg;base64,AQID" },
|
|
151
|
+
],
|
|
152
|
+
});
|
|
153
|
+
expect(createRunMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
154
|
+
input_images: [{ mediaType: "image/jpeg", data: "AQID", byteSize: 3 }],
|
|
155
|
+
}));
|
|
156
|
+
});
|
|
157
|
+
|
|
125
158
|
it.each([false, true, undefined])("does not log ignored effort when thinking is %s", async (thinking) => {
|
|
126
159
|
await beforeQuery({ prompt: "hi", model: "openai/gpt-6-sol", thinking, effort: "high" });
|
|
127
160
|
expect(createRunMock).toHaveBeenCalledWith(expect.objectContaining({
|