@cartanova/qgrid-cli 2.10.10 → 2.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/dist/_virtual/_rolldown/runtime.js +1 -10
- package/bundle/dist/application/monit/log-buffer.js +12 -6
- package/bundle/dist/application/monit/monit.frame.js +11 -3
- package/bundle/dist/application/monit/monit.types.js +1 -1
- package/bundle/dist/application/qgrid/conv-routing.js +9 -6
- package/bundle/dist/application/qgrid/expired-token-reminder.js +2 -2
- package/bundle/dist/application/qgrid/oauth.js +31 -4
- package/bundle/dist/application/qgrid/qgrid-image-generation.js +1 -1
- package/bundle/dist/application/qgrid/qgrid-response-format.js +21 -19
- package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +40 -33
- package/bundle/dist/application/qgrid/qgrid.dispatcher.js +128 -93
- package/bundle/dist/application/qgrid/qgrid.frame.js +930 -49
- package/bundle/dist/application/qgrid/qgrid.types.js +212 -5
- package/bundle/dist/application/qgrid/schema-prompt.js +75 -48
- package/bundle/dist/application/qgrid/slack-user-map.js +1 -1
- package/bundle/dist/application/qgrid/token-death.js +1 -1
- package/bundle/dist/application/qgrid/token-subscriber.js +83 -30
- package/bundle/dist/application/qgrid/token-trigger-setup.js +1 -1
- package/bundle/dist/application/qgrid/token-window-keepalive.js +8 -6
- package/bundle/dist/application/qgrid/tool-emulation-schema.js +13 -13
- package/bundle/dist/application/qgrid/tool-emulation.js +19 -15
- package/bundle/dist/application/request-log/json-schema-type-text.js +29 -12
- package/bundle/dist/application/request-log/request-log.model.js +83 -70
- package/bundle/dist/application/request-log/request-log.types.js +1 -1
- package/bundle/dist/application/request-log/zod-code-format.js +1 -1
- package/bundle/dist/application/request-log-step/request-log-step.model.js +1 -1
- package/bundle/dist/application/request-log-step/request-log-step.types.js +1 -1
- package/bundle/dist/application/setting/setting.constant.js +1 -1
- package/bundle/dist/application/setting/setting.model.js +2 -2
- package/bundle/dist/application/setting/setting.store.js +2 -2
- package/bundle/dist/application/setting/setting.types.js +1 -1
- package/bundle/dist/application/sonamu.generated.js +32 -16
- package/bundle/dist/application/sonamu.generated.sso.js +1 -1
- package/bundle/dist/application/token/token.model.js +26 -9
- package/bundle/dist/application/token/token.types.js +20 -3
- package/bundle/dist/i18n/en.js +15 -1
- package/bundle/dist/i18n/ko.js +15 -1
- package/bundle/dist/i18n/sd.generated.js +1 -1
- package/bundle/dist/migrations/20260807133553_manual__backfill_request_log_cost.js +8 -6
- package/bundle/dist/server-bootstrap.js +4 -2
- package/bundle/dist/server-error-handler.js +1 -1
- package/bundle/dist/sonamu.config.js +37 -8
- package/bundle/dist/startup-migrations.js +17 -7
- package/bundle/dist/testing/global.js +1 -1
- package/bundle/dist/testing/schema-bench.js +0 -0
- package/bundle/dist/testing/test-database-name.js +1 -1
- package/bundle/dist/utils/providers/anthropic/anthropic-constants.js +1 -1
- package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +11 -5
- package/bundle/dist/utils/providers/anthropic/anthropic-quota.js +4 -4
- package/bundle/dist/utils/providers/anthropic/anthropic-thinking.js +1 -1
- package/bundle/dist/utils/providers/anthropic/claude-session.js +20 -19
- package/bundle/dist/utils/providers/anthropic/fence-strip.js +1 -1
- package/bundle/dist/utils/providers/anthropic/stream-json-adapter.js +49 -23
- package/bundle/dist/utils/providers/common/credentials.js +5 -1
- package/bundle/dist/utils/providers/common/effort.js +3 -3
- package/bundle/dist/utils/providers/common/model-cost.js +69 -14
- package/bundle/dist/utils/providers/common/provider-types.js +29 -1
- package/bundle/dist/utils/providers/common/schema-validation.js +78 -40
- package/bundle/dist/utils/providers/common/smooth-weighted-round-robin.js +1 -1
- package/bundle/dist/utils/providers/common/strictifier.js +62 -43
- package/bundle/dist/utils/providers/common/thinking.js +3 -2
- package/bundle/dist/utils/providers/common/ttft.js +1 -1
- package/bundle/dist/utils/providers/grok/grok-backend-protocol.js +427 -0
- package/bundle/dist/utils/providers/grok/grok-constants.js +55 -0
- package/bundle/dist/utils/providers/grok/grok-direct-client.js +196 -0
- package/bundle/dist/utils/providers/grok/grok-dispatcher.js +1313 -0
- package/bundle/dist/utils/providers/grok/grok-headers.js +118 -0
- package/bundle/dist/utils/providers/grok/grok-media-client.js +420 -0
- package/bundle/dist/utils/providers/grok/grok-models.js +114 -0
- package/bundle/dist/utils/providers/grok/grok-oauth.js +455 -0
- package/bundle/dist/utils/providers/grok/grok-quota.js +119 -0
- package/bundle/dist/utils/providers/grok/grok-refresh.js +192 -0
- package/bundle/dist/utils/providers/grok/grok-types.js +186 -0
- package/bundle/dist/utils/providers/grok/grok-voice-client.js +199 -0
- package/bundle/dist/utils/providers/grok/index.js +11 -0
- package/bundle/dist/utils/providers/openai/openai-backend-protocol.js +111 -83
- package/bundle/dist/utils/providers/openai/openai-callback-relay.js +3 -2
- package/bundle/dist/utils/providers/openai/openai-constants.js +1 -1
- package/bundle/dist/utils/providers/openai/openai-direct-client.js +23 -7
- package/bundle/dist/utils/providers/openai/openai-dispatcher.js +143 -106
- package/bundle/dist/utils/providers/openai/openai-image-generation.js +48 -33
- package/bundle/dist/utils/providers/openai/openai-oauth.js +28 -13
- package/bundle/dist/utils/providers/openai/openai-quota.js +38 -27
- package/bundle/dist/utils/providers/openai/openai-refresh.js +17 -9
- package/bundle/dist/utils/providers/openai/openai-sse.js +1 -1
- package/bundle/dist/utils/providers/openai/openai-transport-config.js +1 -1
- package/bundle/dist/utils/quiet-hours.js +1 -1
- package/bundle/dist/utils/slack-notify.js +14 -8
- package/bundle/dist/utils/subset-loaders.js +4 -5
- package/bundle/src/application/monit/log-buffer.ts +23 -9
- package/bundle/src/application/monit/monit.frame.ts +22 -5
- package/bundle/src/application/monit/monit.types.ts +6 -0
- package/bundle/src/application/qgrid/conv-routing.test.ts +76 -4
- package/bundle/src/application/qgrid/conv-routing.ts +35 -9
- package/bundle/src/application/qgrid/expired-token-reminder.ts +9 -1
- package/bundle/src/application/qgrid/oauth.ts +51 -15
- package/bundle/src/application/qgrid/qgrid-image-generation.ts +9 -0
- package/bundle/src/application/qgrid/qgrid-response-format.ts +50 -25
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +19 -0
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +84 -40
- package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +97 -0
- package/bundle/src/application/qgrid/qgrid.dispatcher.ts +274 -126
- package/bundle/src/application/qgrid/qgrid.frame.test.ts +1013 -3
- package/bundle/src/application/qgrid/qgrid.frame.ts +1415 -60
- package/bundle/src/application/qgrid/qgrid.types.ts +335 -0
- package/bundle/src/application/qgrid/schema-prompt.ts +105 -41
- package/bundle/src/application/qgrid/slack-user-map.ts +5 -0
- package/bundle/src/application/qgrid/token-death.ts +4 -0
- package/bundle/src/application/qgrid/token-subscriber.test.ts +21 -19
- package/bundle/src/application/qgrid/token-subscriber.ts +186 -53
- package/bundle/src/application/qgrid/token-trigger-setup.ts +2 -0
- package/bundle/src/application/qgrid/token-window-keepalive.ts +49 -6
- package/bundle/src/application/qgrid/tool-emulation-schema.ts +33 -29
- package/bundle/src/application/qgrid/tool-emulation.ts +52 -27
- package/bundle/src/application/request-log/json-schema-type-text.test.ts +5 -5
- package/bundle/src/application/request-log/json-schema-type-text.ts +81 -26
- package/bundle/src/application/request-log/request-log.model.test.ts +111 -4
- package/bundle/src/application/request-log/request-log.model.ts +277 -146
- package/bundle/src/application/request-log/request-log.types.ts +6 -0
- package/bundle/src/application/request-log/zod-code-format.ts +11 -0
- package/bundle/src/application/request-log-step/request-log-step.model.ts +1 -0
- package/bundle/src/application/request-log-step/request-log-step.types.ts +2 -0
- package/bundle/src/application/setting/setting.constant.ts +9 -0
- package/bundle/src/application/setting/setting.model.ts +12 -2
- package/bundle/src/application/setting/setting.store.ts +5 -1
- package/bundle/src/application/setting/setting.types.ts +8 -0
- package/bundle/src/application/sonamu.generated.http +133 -0
- package/bundle/src/application/sonamu.generated.sso.ts +2 -0
- package/bundle/src/application/sonamu.generated.ts +15 -0
- package/bundle/src/application/token/token.identity.test.ts +20 -0
- package/bundle/src/application/token/token.model.ts +66 -7
- package/bundle/src/application/token/token.types.ts +24 -1
- package/bundle/src/i18n/en.ts +19 -0
- package/bundle/src/i18n/ko.ts +21 -0
- package/bundle/src/i18n/sd.generated.ts +23 -2
- package/bundle/src/migrations/20260807133553_manual__backfill_request_log_cost.ts +16 -8
- package/bundle/src/server-bootstrap.ts +4 -2
- package/bundle/src/server-error-handler.ts +1 -0
- package/bundle/src/sonamu.config.ts +69 -7
- package/bundle/src/startup-migrations.ts +27 -9
- package/bundle/src/testing/global.ts +20 -0
- package/bundle/src/testing/schema-bench.ts +105 -30
- package/bundle/src/testing/test-database-name.ts +2 -0
- package/bundle/src/utils/providers/anthropic/anthropic-constants.ts +8 -0
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +41 -6
- package/bundle/src/utils/providers/anthropic/anthropic-quota.ts +7 -3
- package/bundle/src/utils/providers/anthropic/anthropic-thinking.ts +6 -0
- package/bundle/src/utils/providers/anthropic/claude-session.ts +58 -24
- package/bundle/src/utils/providers/anthropic/fence-strip.ts +11 -0
- package/bundle/src/utils/providers/anthropic/stream-json-adapter.ts +110 -45
- package/bundle/src/utils/providers/common/credentials.ts +8 -0
- package/bundle/src/utils/providers/common/effort.ts +9 -2
- package/bundle/src/utils/providers/common/model-cost.test.ts +48 -1
- package/bundle/src/utils/providers/common/model-cost.ts +259 -158
- package/bundle/src/utils/providers/common/provider-dispatcher.ts +98 -2
- package/bundle/src/utils/providers/common/provider-types.ts +46 -3
- package/bundle/src/utils/providers/common/schema-validation.test.ts +5 -1
- package/bundle/src/utils/providers/common/schema-validation.ts +124 -56
- package/bundle/src/utils/providers/common/smooth-weighted-round-robin.ts +4 -0
- package/bundle/src/utils/providers/common/strictifier.ts +185 -59
- package/bundle/src/utils/providers/common/thinking.ts +2 -2
- package/bundle/src/utils/providers/common/ttft.ts +4 -2
- package/bundle/src/utils/providers/grok/__fixtures__/golden-responses-1.0.60.json +164 -0
- package/bundle/src/utils/providers/grok/grok-backend-protocol.test.ts +325 -0
- package/bundle/src/utils/providers/grok/grok-backend-protocol.ts +721 -0
- package/bundle/src/utils/providers/grok/grok-constants.ts +105 -0
- package/bundle/src/utils/providers/grok/grok-direct-client.test.ts +179 -0
- package/bundle/src/utils/providers/grok/grok-direct-client.ts +313 -0
- package/bundle/src/utils/providers/grok/grok-dispatcher.test.ts +1395 -0
- package/bundle/src/utils/providers/grok/grok-dispatcher.ts +2105 -0
- package/bundle/src/utils/providers/grok/grok-headers.test.ts +149 -0
- package/bundle/src/utils/providers/grok/grok-headers.ts +199 -0
- package/bundle/src/utils/providers/grok/grok-media-client.test.ts +446 -0
- package/bundle/src/utils/providers/grok/grok-media-client.ts +703 -0
- package/bundle/src/utils/providers/grok/grok-models.test.ts +96 -0
- package/bundle/src/utils/providers/grok/grok-models.ts +161 -0
- package/bundle/src/utils/providers/grok/grok-oauth.test.ts +406 -0
- package/bundle/src/utils/providers/grok/grok-oauth.ts +771 -0
- package/bundle/src/utils/providers/grok/grok-quota.test.ts +142 -0
- package/bundle/src/utils/providers/grok/grok-quota.ts +198 -0
- package/bundle/src/utils/providers/grok/grok-refresh.test.ts +239 -0
- package/bundle/src/utils/providers/grok/grok-refresh.ts +325 -0
- package/bundle/src/utils/providers/grok/grok-types.test.ts +252 -0
- package/bundle/src/utils/providers/grok/grok-types.ts +374 -0
- package/bundle/src/utils/providers/grok/grok-voice-client.test.ts +321 -0
- package/bundle/src/utils/providers/grok/grok-voice-client.ts +284 -0
- package/bundle/src/utils/providers/grok/index.ts +20 -0
- package/bundle/src/utils/providers/openai/openai-backend-protocol.ts +221 -137
- package/bundle/src/utils/providers/openai/openai-callback-relay.ts +12 -1
- package/bundle/src/utils/providers/openai/openai-constants.ts +2 -0
- package/bundle/src/utils/providers/openai/openai-direct-client.ts +111 -21
- package/bundle/src/utils/providers/openai/openai-dispatcher.ts +322 -169
- package/bundle/src/utils/providers/openai/openai-image-generation.ts +116 -36
- package/bundle/src/utils/providers/openai/openai-oauth.ts +48 -20
- package/bundle/src/utils/providers/openai/openai-quota.ts +77 -46
- package/bundle/src/utils/providers/openai/openai-refresh.ts +42 -18
- package/bundle/src/utils/providers/openai/openai-sse.ts +27 -3
- package/bundle/src/utils/providers/openai/openai-transport-config.ts +2 -0
- package/bundle/src/utils/quiet-hours.ts +12 -1
- package/bundle/src/utils/slack-notify.ts +44 -13
- package/bundle/src/utils/subset-loaders.ts +7 -7
- package/bundle/web-dist/client/assets/clsx-5XM_pHvN.js +1 -0
- package/bundle/web-dist/client/assets/index-Be2qCZmI.css +1 -0
- package/bundle/web-dist/client/assets/index-C96h3feE.js +32 -0
- package/bundle/web-dist/client/assets/logs-DBM6U0QD.js +1 -0
- package/bundle/web-dist/client/assets/monit-BBjXa7vB.js +1 -0
- package/bundle/web-dist/client/assets/routes-Crz_PQzi.js +5 -0
- package/bundle/web-dist/client/assets/{services.generated-NP-ValHd.js → services.generated-B5lc3aIC.js} +5 -5
- package/bundle/web-dist/client/assets/settings-Cdwm3OBB.js +1 -0
- package/bundle/web-dist/client/assets/show-DBUhALT1.js +2 -0
- package/bundle/web-dist/client/assets/tokens-CVQAVJTo.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-BfxYI4Oh.js +1 -0
- package/bundle/web-dist/client/assets/use-update-token-mutation-qKBC2sn7.js +1 -0
- package/bundle/web-dist/client/assets/{vendor-tanstack-DJRQAbrY.js → vendor-tanstack-DRPs09ai.js} +1 -1
- package/bundle/web-dist/client/index.html +5 -5
- package/bundle/web-dist/server/assets/clsx-D_N5PN_2.js +16 -0
- package/bundle/web-dist/server/assets/{lazyRouteComponent-CgBdabgd.js → lazyRouteComponent-AKiHfZWp.js} +129 -2
- package/bundle/web-dist/server/assets/{logs-BMyR98rU.js → logs-B7QmGJq3.js} +18 -14
- package/bundle/web-dist/server/assets/{monit-ZPt66W5M.js → monit-DFt7x3bh.js} +13 -12
- package/bundle/web-dist/server/assets/{plus-BZ9I0VgC.js → plus-DaYQRpBt.js} +1 -1
- package/bundle/web-dist/server/assets/{react-dom-Ds75e4Jl.js → react-dom-Cv23mm1K.js} +2 -129
- package/bundle/web-dist/server/assets/{refresh-cw-CztCFis-.js → refresh-cw-BpXNsAy-.js} +1 -1
- package/bundle/web-dist/server/assets/{request-model-DjGldb-h.js → request-model-eHE6YbaF.js} +1 -1
- package/bundle/web-dist/server/assets/{routes-Ct-k7nBA.js → routes-_Y-PJfgO.js} +110 -39
- package/bundle/web-dist/server/assets/{services.generated-BA4AcAf5.js → services.generated-CMJ8AHbO.js} +582 -172
- package/bundle/web-dist/server/assets/{settings-CBUZ47Xx.js → settings-JwJKxn2e.js} +14 -14
- package/bundle/web-dist/server/assets/{show-LSFIzvO2.js → show-BEv6z1v_.js} +90 -60
- package/bundle/web-dist/server/assets/{tokens-DxrBW512.js → tokens-CNT4mI-f.js} +162 -50
- package/bundle/web-dist/server/assets/total-cost-fTE9Xy82.js +18 -0
- package/bundle/web-dist/server/assets/use-oauth-login-flow-jkAkT3X6.js +2345 -0
- package/bundle/web-dist/server/assets/{use-update-token-mutation-pkArIzCP.js → use-update-token-mutation-Sm6kh02m.js} +1 -1
- package/bundle/web-dist/server/entry-server.generated.js +1644 -21655
- package/dist/cli.js +9 -9
- package/package.json +4 -11
- package/postinstall.mjs +12 -0
- package/skills/qgrid/SKILL.md +1 -0
- package/skills/qgrid/references/cli-env-and-server-boot.md +4 -1
- package/skills/qgrid/references/decision-rationale.md +23 -0
- package/skills/qgrid/references/grok-runtime.md +89 -0
- package/skills/qgrid/references/provider-runtime-differences.md +30 -29
- package/skills/qgrid/references/repo-map.md +10 -0
- package/skills/qgrid/references/token-auth-quota-lifecycle.md +56 -3
- package/bundle/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +0 -406
- package/bundle/dist/node_modules/.pnpm/@vitest_expect@4.1.10/node_modules/@vitest/expect/dist/index.js +0 -1507
- package/bundle/dist/node_modules/.pnpm/@vitest_pretty-format@4.1.10/node_modules/@vitest/pretty-format/dist/index.js +0 -887
- package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/chunk-artifact.js +0 -2756
- package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/index.js +0 -8
- package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/utils.js +0 -8
- package/bundle/dist/node_modules/.pnpm/@vitest_snapshot@4.1.10/node_modules/@vitest/snapshot/dist/index.js +0 -922
- package/bundle/dist/node_modules/.pnpm/@vitest_spy@4.1.10/node_modules/@vitest/spy/dist/index.js +0 -386
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +0 -121
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/constants.js +0 -51
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/diff.js +0 -1317
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/display.js +0 -561
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/error.js +0 -40
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/helpers.js +0 -272
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/offset.js +0 -27
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/serialize.js +0 -77
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/source-map.js +0 -381
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/timers.js +0 -51
- package/bundle/dist/node_modules/.pnpm/chai@6.2.2/node_modules/chai/index.js +0 -2986
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.js +0 -10
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.js +0 -109
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.js +0 -10
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.js +0 -10
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.js +0 -10
- package/bundle/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +0 -1126
- package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.js +0 -21
- package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +0 -432
- package/bundle/dist/node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.js +0 -517
- package/bundle/dist/node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js +0 -101
- package/bundle/dist/node_modules/.pnpm/vite@8.0.3_@emnapi_core@1.11.2_@emnapi_runtime@1.11.2_@types_node@25.0.7_esbuild@0.27.4_5b35fc1fb85d2af4d105e0d74f940f50/node_modules/vite/dist/node/module-runner.js +0 -1265
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js +0 -9
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/benchmark.CX_oY03V.js +0 -41
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/evaluatedModules.Dg1zASAC.js +0 -19
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/index.Chj8NDwU.js +0 -202
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/index.DdgEv5B1.js +0 -46
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/rpc.MzXet3jl.js +0 -119
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/test.DNmyFkvJ.js +0 -3044
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.js +0 -59
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/index.js +0 -28
- package/bundle/dist/testing/setup-mocks.js +0 -16
- package/bundle/src/testing/setup-mocks.ts +0 -44
- package/bundle/web-dist/client/assets/index-Bw2s88Ot.css +0 -1
- package/bundle/web-dist/client/assets/index-DZwzUfI-.js +0 -106
- package/bundle/web-dist/client/assets/logs-Cog79DU5.js +0 -1
- package/bundle/web-dist/client/assets/monit-2auznBys.js +0 -1
- package/bundle/web-dist/client/assets/routes-B0lTeLK-.js +0 -5
- package/bundle/web-dist/client/assets/settings-D8ZxZGSJ.js +0 -1
- package/bundle/web-dist/client/assets/show-CFSERlnM.js +0 -2
- package/bundle/web-dist/client/assets/tokens-CZXUyI7O.js +0 -1
- package/bundle/web-dist/client/assets/use-oauth-login-flow-hboOs3wG.js +0 -1
- package/bundle/web-dist/client/assets/use-update-token-mutation-BQHS0byG.js +0 -1
- package/bundle/web-dist/server/assets/use-oauth-login-flow-Gn8flMK5.js +0 -178
- package/dist/cli.d.ts +0 -10
- /package/bundle/web-dist/client/assets/{cost-DH2jZbrw.js → cost-DB3HbU7T.js} +0 -0
- /package/bundle/web-dist/client/assets/{plus-B62CuqT8.js → plus-BsQdY7PS.js} +0 -0
- /package/bundle/web-dist/client/assets/{preload-helper-ca-nBW7U.js → preload-helper-DWTEM3RW.js} +0 -0
- /package/bundle/web-dist/client/assets/{refresh-cw-NNcU0Cmq.js → refresh-cw-D9IUmT23.js} +0 -0
- /package/bundle/web-dist/client/assets/{request-model-CojtinqK.js → request-model-Bpp_rkK8.js} +0 -0
- /package/bundle/web-dist/server/assets/{cost-eEHeTRT5.js → cost-BC9yzyA9.js} +0 -0
|
@@ -8,11 +8,20 @@
|
|
|
8
8
|
* The only executable user line is the current input.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
|
|
11
13
|
import {
|
|
12
14
|
type ModelFallback,
|
|
13
15
|
type ProviderTokenUsageBreakdown,
|
|
14
16
|
} from "../common/provider-dispatcher";
|
|
15
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
isJsonObject,
|
|
19
|
+
type JsonObject,
|
|
20
|
+
jsonNumber,
|
|
21
|
+
jsonString,
|
|
22
|
+
type JsonValue,
|
|
23
|
+
type UserInput,
|
|
24
|
+
} from "../common/provider-types";
|
|
16
25
|
import { stripFences } from "./fence-strip";
|
|
17
26
|
|
|
18
27
|
// ── 입력 어댑터 ────────────────────────────────────────────────────
|
|
@@ -27,10 +36,7 @@ export interface ClaudeStreamJsonLine {
|
|
|
27
36
|
}
|
|
28
37
|
|
|
29
38
|
function userInputToText(input: Array<UserInput>): string {
|
|
30
|
-
return input
|
|
31
|
-
.filter((i): i is Extract<UserInput, { type: "text" }> => i.type === "text")
|
|
32
|
-
.map((i) => i.text)
|
|
33
|
-
.join("\n");
|
|
39
|
+
return input.flatMap((i) => (i.type === "text" ? [i.text] : [])).join("\n");
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
function textBlock(text: string): Array<{ type: "text"; text: string }> {
|
|
@@ -43,19 +49,22 @@ function textBlock(text: string): Array<{ type: "text"; text: string }> {
|
|
|
43
49
|
// { type:"message", role:"assistant", content:[{type:"output_text", text}] }
|
|
44
50
|
// { type:"function_call", name, arguments, call_id }
|
|
45
51
|
// { type:"function_call_output", call_id, output }
|
|
46
|
-
type ResponseItem =
|
|
52
|
+
type ResponseItem = JsonObject;
|
|
47
53
|
|
|
48
54
|
function asObject(v: JsonValue | undefined): ResponseItem | null {
|
|
49
|
-
return
|
|
55
|
+
return isJsonObject(v) ? v : null;
|
|
50
56
|
}
|
|
51
57
|
|
|
52
58
|
function responseItemText(item: ResponseItem): string {
|
|
53
59
|
const content = item.content;
|
|
60
|
+
|
|
54
61
|
if (!Array.isArray(content)) return "";
|
|
62
|
+
|
|
55
63
|
return content
|
|
56
64
|
.map((c) => {
|
|
57
65
|
const obj = asObject(c);
|
|
58
|
-
|
|
66
|
+
|
|
67
|
+
return (obj && jsonString(obj.text)) ?? "";
|
|
59
68
|
})
|
|
60
69
|
.filter(Boolean)
|
|
61
70
|
.join("\n");
|
|
@@ -63,8 +72,10 @@ function responseItemText(item: ResponseItem): string {
|
|
|
63
72
|
|
|
64
73
|
function flattenColdHistory(coldHistory: Array<JsonValue>): string {
|
|
65
74
|
const parts: Array<string> = [];
|
|
75
|
+
|
|
66
76
|
for (const raw of coldHistory) {
|
|
67
77
|
const item = asObject(raw);
|
|
78
|
+
|
|
68
79
|
if (!item) continue;
|
|
69
80
|
|
|
70
81
|
if (item.type === "message" && item.role === "assistant") {
|
|
@@ -72,16 +83,17 @@ function flattenColdHistory(coldHistory: Array<JsonValue>): string {
|
|
|
72
83
|
} else if (item.type === "message" && item.role === "user") {
|
|
73
84
|
parts.push(`User: ${responseItemText(item)}`);
|
|
74
85
|
} else if (item.type === "function_call") {
|
|
75
|
-
const name =
|
|
76
|
-
const args =
|
|
77
|
-
|
|
86
|
+
const name = jsonString(item.name) ?? "";
|
|
87
|
+
const args = jsonString(item.arguments) ?? JSON.stringify(item.arguments ?? {});
|
|
88
|
+
|
|
78
89
|
parts.push(`Tool call: ${name}(${args})`);
|
|
79
90
|
} else if (item.type === "function_call_output") {
|
|
80
|
-
const output =
|
|
81
|
-
|
|
91
|
+
const output = jsonString(item.output) ?? JSON.stringify(item.output ?? "");
|
|
92
|
+
|
|
82
93
|
parts.push(`Tool result: ${output}`);
|
|
83
94
|
}
|
|
84
95
|
}
|
|
96
|
+
|
|
85
97
|
return parts.join("\n");
|
|
86
98
|
}
|
|
87
99
|
|
|
@@ -93,6 +105,7 @@ export function buildStreamJsonInput(opts: {
|
|
|
93
105
|
|
|
94
106
|
if (opts.coldHistory && opts.coldHistory.length > 0) {
|
|
95
107
|
const flattened = flattenColdHistory(opts.coldHistory);
|
|
108
|
+
|
|
96
109
|
if (flattened) {
|
|
97
110
|
lines.push({
|
|
98
111
|
type: "assistant",
|
|
@@ -120,20 +133,21 @@ export function serializeStreamJsonInput(lines: Array<ClaudeStreamJsonLine>): st
|
|
|
120
133
|
//
|
|
121
134
|
// Claude stdout(JSONL)을 qgrid deltas + final result 로 변환한다.
|
|
122
135
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
136
|
+
// Usage fields are read only when they hold numbers; anything else counts as absent.
|
|
137
|
+
const optionalCount = z.number().optional().catch(undefined);
|
|
138
|
+
|
|
139
|
+
const ClaudeUsage = z.object({
|
|
140
|
+
input_tokens: optionalCount,
|
|
141
|
+
output_tokens: optionalCount,
|
|
142
|
+
cache_creation_input_tokens: optionalCount,
|
|
143
|
+
cache_read_input_tokens: optionalCount,
|
|
144
|
+
cache_creation: z
|
|
145
|
+
.object({ ephemeral_5m_input_tokens: optionalCount, ephemeral_1h_input_tokens: optionalCount })
|
|
146
|
+
.optional()
|
|
147
|
+
.catch(undefined),
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
type ClaudeUsage = z.infer<typeof ClaudeUsage>;
|
|
137
151
|
|
|
138
152
|
export interface ClaudeStreamResult {
|
|
139
153
|
text: string;
|
|
@@ -183,26 +197,34 @@ function toUsageBreakdown(u: ClaudeUsage): ProviderTokenUsageBreakdown {
|
|
|
183
197
|
const totalInput = input + cacheCreate + cacheRead;
|
|
184
198
|
const cacheCreate5m = u.cache_creation?.ephemeral_5m_input_tokens;
|
|
185
199
|
const cacheCreate1h = u.cache_creation?.ephemeral_1h_input_tokens;
|
|
186
|
-
|
|
200
|
+
|
|
201
|
+
const usage: ProviderTokenUsageBreakdown = {
|
|
187
202
|
totalTokens: totalInput + output,
|
|
188
203
|
inputTokens: totalInput,
|
|
189
204
|
cachedInputTokens: cacheRead,
|
|
190
205
|
cacheCreationInputTokens: cacheCreate,
|
|
191
|
-
...(typeof cacheCreate5m === "number" ? { cacheCreationInputTokens5m: cacheCreate5m } : {}),
|
|
192
|
-
...(typeof cacheCreate1h === "number" ? { cacheCreationInputTokens1h: cacheCreate1h } : {}),
|
|
193
206
|
outputTokens: output,
|
|
194
207
|
reasoningOutputTokens: 0,
|
|
195
208
|
};
|
|
209
|
+
|
|
210
|
+
if (cacheCreate5m !== undefined) usage.cacheCreationInputTokens5m = cacheCreate5m;
|
|
211
|
+
|
|
212
|
+
if (cacheCreate1h !== undefined) usage.cacheCreationInputTokens1h = cacheCreate1h;
|
|
213
|
+
|
|
214
|
+
return usage;
|
|
196
215
|
}
|
|
197
216
|
|
|
198
217
|
function structuredOutputToolUseText(j: ResponseItem): string | undefined {
|
|
199
218
|
const message = asObject(j.message);
|
|
200
219
|
const content = message?.content;
|
|
220
|
+
|
|
201
221
|
if (!Array.isArray(content)) return undefined;
|
|
202
222
|
|
|
203
223
|
for (const raw of content) {
|
|
204
224
|
const block = asObject(raw);
|
|
225
|
+
|
|
205
226
|
if (!block) continue;
|
|
227
|
+
|
|
206
228
|
if (
|
|
207
229
|
block.type === "tool_use" &&
|
|
208
230
|
block.name === "StructuredOutput" &&
|
|
@@ -211,37 +233,43 @@ function structuredOutputToolUseText(j: ResponseItem): string | undefined {
|
|
|
211
233
|
return JSON.stringify(block.input);
|
|
212
234
|
}
|
|
213
235
|
}
|
|
236
|
+
|
|
214
237
|
return undefined;
|
|
215
238
|
}
|
|
216
239
|
|
|
217
240
|
function canonicalEventModel(model: string): string {
|
|
218
241
|
const withoutProvider = model.startsWith("anthropic/") ? model.slice("anthropic/".length) : model;
|
|
242
|
+
|
|
219
243
|
return withoutProvider.replace(/\[1m\]$/, "");
|
|
220
244
|
}
|
|
221
245
|
|
|
222
246
|
function optionalString(value: JsonValue | undefined): string | undefined {
|
|
223
|
-
return
|
|
247
|
+
return jsonString(value) || undefined;
|
|
224
248
|
}
|
|
225
249
|
|
|
226
250
|
function recordFallback(state: ClaudeStreamJsonState | undefined, fallback: ModelFallback): void {
|
|
227
251
|
if (!state) return;
|
|
252
|
+
|
|
228
253
|
const normalized: ModelFallback = {
|
|
229
254
|
...fallback,
|
|
230
255
|
fromModel: canonicalEventModel(fallback.fromModel),
|
|
231
256
|
toModel: canonicalEventModel(fallback.toModel),
|
|
232
257
|
};
|
|
258
|
+
|
|
233
259
|
const existing = state.modelFallbacks?.find(
|
|
234
260
|
(item) =>
|
|
235
261
|
item.trigger === normalized.trigger &&
|
|
236
262
|
item.fromModel === normalized.fromModel &&
|
|
237
263
|
item.toModel === normalized.toModel,
|
|
238
264
|
);
|
|
265
|
+
|
|
239
266
|
if (existing) {
|
|
240
267
|
existing.category ??= normalized.category;
|
|
241
268
|
existing.explanation ??= normalized.explanation;
|
|
242
269
|
} else {
|
|
243
270
|
(state.modelFallbacks ??= []).push(normalized);
|
|
244
271
|
}
|
|
272
|
+
|
|
245
273
|
state.servedModel = normalized.toModel;
|
|
246
274
|
state.refusalWithoutFallback = false;
|
|
247
275
|
}
|
|
@@ -253,13 +281,17 @@ function updateRoutingFromUsage(
|
|
|
253
281
|
if (!state || !usage || !Array.isArray(usage.iterations)) return;
|
|
254
282
|
|
|
255
283
|
let previousModel: string | undefined;
|
|
284
|
+
|
|
256
285
|
for (const raw of usage.iterations) {
|
|
257
286
|
const iteration = asObject(raw);
|
|
287
|
+
|
|
258
288
|
if (!iteration) continue;
|
|
259
289
|
const model = optionalString(iteration.model);
|
|
260
290
|
const type = optionalString(iteration.type);
|
|
291
|
+
|
|
261
292
|
if (!model) continue;
|
|
262
293
|
const canonicalModel = canonicalEventModel(model);
|
|
294
|
+
|
|
263
295
|
if (type === "fallback_message" && previousModel) {
|
|
264
296
|
recordFallback(state, {
|
|
265
297
|
trigger: "refusal",
|
|
@@ -267,6 +299,7 @@ function updateRoutingFromUsage(
|
|
|
267
299
|
toModel: canonicalModel,
|
|
268
300
|
});
|
|
269
301
|
}
|
|
302
|
+
|
|
270
303
|
previousModel = canonicalModel;
|
|
271
304
|
state.servedModel = canonicalModel;
|
|
272
305
|
}
|
|
@@ -279,10 +312,13 @@ function updateRoutingFromMessage(
|
|
|
279
312
|
if (!state || !message) return;
|
|
280
313
|
const model = optionalString(message.model);
|
|
281
314
|
const canonicalModel = model ? canonicalEventModel(model) : undefined;
|
|
315
|
+
|
|
282
316
|
if (canonicalModel) state.servedModel = canonicalModel;
|
|
283
317
|
const stopReason = optionalString(message.stop_reason);
|
|
318
|
+
|
|
284
319
|
if (stopReason) {
|
|
285
320
|
state.stopReason = stopReason;
|
|
321
|
+
|
|
286
322
|
if (stopReason === "refusal") state.refusalWithoutFallback = true;
|
|
287
323
|
else if (state.modelFallbacks?.some((fallback) => fallback.toModel === canonicalModel)) {
|
|
288
324
|
state.refusalWithoutFallback = false;
|
|
@@ -290,12 +326,14 @@ function updateRoutingFromMessage(
|
|
|
290
326
|
}
|
|
291
327
|
|
|
292
328
|
const stopDetails = asObject(message.stop_details);
|
|
329
|
+
|
|
293
330
|
if (stopDetails?.type === "refusal" || stopReason === "refusal") {
|
|
294
331
|
state.refusal = {
|
|
295
332
|
category: optionalString(stopDetails?.category),
|
|
296
333
|
explanation: optionalString(stopDetails?.explanation),
|
|
297
334
|
};
|
|
298
335
|
}
|
|
336
|
+
|
|
299
337
|
updateRoutingFromUsage(asObject(message.usage), state);
|
|
300
338
|
}
|
|
301
339
|
|
|
@@ -308,49 +346,63 @@ export function handleStreamJsonLine(
|
|
|
308
346
|
const structuredOutput = opts?.structuredOutput ?? false;
|
|
309
347
|
const state = opts?.state;
|
|
310
348
|
const trimmed = line.trim();
|
|
349
|
+
|
|
311
350
|
if (!trimmed) return null;
|
|
312
351
|
|
|
313
|
-
let
|
|
352
|
+
let parsed: JsonValue;
|
|
353
|
+
|
|
314
354
|
try {
|
|
315
|
-
|
|
355
|
+
// JSON.parse without a reviver yields only JSON values.
|
|
356
|
+
parsed = JSON.parse(trimmed);
|
|
316
357
|
} catch {
|
|
317
358
|
return null;
|
|
318
359
|
}
|
|
319
360
|
|
|
361
|
+
// Every Claude stream-json line is an object; other JSON values carry no event.
|
|
362
|
+
const j = asObject(parsed) ?? {};
|
|
363
|
+
|
|
320
364
|
if (j.type === "stream_event") {
|
|
321
365
|
const event = asObject(j.event);
|
|
366
|
+
|
|
322
367
|
if (event?.type === "message_start") {
|
|
323
368
|
updateRoutingFromMessage(asObject(event.message), state);
|
|
324
369
|
} else if (event?.type === "message_delta") {
|
|
325
370
|
const delta = asObject(event.delta);
|
|
326
371
|
const stopReason = optionalString(delta?.stop_reason);
|
|
372
|
+
|
|
327
373
|
if (state && stopReason) {
|
|
328
374
|
state.stopReason = stopReason;
|
|
375
|
+
|
|
329
376
|
if (stopReason === "refusal") state.refusalWithoutFallback = true;
|
|
330
377
|
}
|
|
331
378
|
}
|
|
379
|
+
|
|
332
380
|
if (event && event.type === "content_block_delta") {
|
|
333
381
|
const delta = asObject(event.delta);
|
|
382
|
+
|
|
334
383
|
if (delta) {
|
|
335
384
|
if (structuredOutput) {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
385
|
+
const partialJson = jsonString(delta.partial_json);
|
|
386
|
+
|
|
387
|
+
if (delta.type === "input_json_delta" && partialJson !== undefined) onDelta(partialJson);
|
|
339
388
|
} else {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
389
|
+
const deltaText = jsonString(delta.text);
|
|
390
|
+
|
|
391
|
+
if (delta.type === "text_delta" && deltaText !== undefined) onDelta(deltaText);
|
|
343
392
|
}
|
|
344
393
|
}
|
|
345
394
|
}
|
|
395
|
+
|
|
346
396
|
return null;
|
|
347
397
|
}
|
|
348
398
|
|
|
349
399
|
if (j.type === "system") {
|
|
350
400
|
const subtype = optionalString(j.subtype);
|
|
401
|
+
|
|
351
402
|
if (subtype === "model_refusal_fallback") {
|
|
352
403
|
const fromModel = optionalString(j.originalModel) ?? optionalString(j.original_model);
|
|
353
404
|
const toModel = optionalString(j.fallbackModel) ?? optionalString(j.fallback_model);
|
|
405
|
+
|
|
354
406
|
if (fromModel && toModel) {
|
|
355
407
|
recordFallback(state, {
|
|
356
408
|
trigger: "refusal",
|
|
@@ -370,6 +422,7 @@ export function handleStreamJsonLine(
|
|
|
370
422
|
}
|
|
371
423
|
} else if (subtype === "model_refusal_no_fallback" && state) {
|
|
372
424
|
const originalModel = optionalString(j.originalModel) ?? optionalString(j.original_model);
|
|
425
|
+
|
|
373
426
|
if (originalModel) state.servedModel = canonicalEventModel(originalModel);
|
|
374
427
|
state.stopReason = "refusal";
|
|
375
428
|
state.refusalWithoutFallback = true;
|
|
@@ -386,27 +439,34 @@ export function handleStreamJsonLine(
|
|
|
386
439
|
optionalString(j.refusal_explanation),
|
|
387
440
|
};
|
|
388
441
|
}
|
|
442
|
+
|
|
389
443
|
return null;
|
|
390
444
|
}
|
|
391
445
|
|
|
392
446
|
if (j.type === "assistant") {
|
|
393
447
|
updateRoutingFromMessage(asObject(j.message), state);
|
|
448
|
+
|
|
394
449
|
if (structuredOutput && state && state.structuredOutputText === undefined) {
|
|
395
450
|
const text = structuredOutputToolUseText(j);
|
|
451
|
+
|
|
396
452
|
if (text !== undefined) state.structuredOutputText = text;
|
|
397
453
|
}
|
|
454
|
+
|
|
398
455
|
return null;
|
|
399
456
|
}
|
|
400
457
|
|
|
401
458
|
if (j.type === "result") {
|
|
402
|
-
const subtype =
|
|
403
|
-
const terminalReason =
|
|
459
|
+
const subtype = jsonString(j.subtype);
|
|
460
|
+
const terminalReason = jsonString(j.terminal_reason);
|
|
461
|
+
|
|
404
462
|
const resultSucceeded =
|
|
405
463
|
j.is_error !== true &&
|
|
406
464
|
terminalReason !== "model_error" &&
|
|
407
465
|
(subtype === undefined || subtype === "success");
|
|
466
|
+
|
|
408
467
|
let text: string;
|
|
409
468
|
const preservedStructuredOutput = structuredOutput ? state?.structuredOutputText : undefined;
|
|
469
|
+
|
|
410
470
|
// Claude Code는 StructuredOutput 스키마 검증 실패 후 내부 재시도를 할 수 있다. assistant
|
|
411
471
|
// 이벤트의 첫 tool input은 거절된 시도일 수 있으므로, 성공 result가 제공한 최종 검증값을
|
|
412
472
|
// 우선한다. 첫 입력 보존값은 max_turns/retry 초과처럼 성공 result가 없는 진단 경로용이다.
|
|
@@ -417,21 +477,26 @@ export function handleStreamJsonLine(
|
|
|
417
477
|
} else if (j.structured_output !== undefined) {
|
|
418
478
|
text = JSON.stringify(j.structured_output);
|
|
419
479
|
} else {
|
|
420
|
-
text = stripFences(
|
|
480
|
+
text = stripFences(jsonString(j.result) ?? "");
|
|
421
481
|
}
|
|
422
482
|
|
|
423
483
|
const rawUsage = asObject(j.usage) ?? {};
|
|
424
484
|
updateRoutingFromUsage(rawUsage, state);
|
|
425
485
|
const resultModel = optionalString(j.model);
|
|
486
|
+
|
|
426
487
|
if (state && resultModel && !state.servedModel) {
|
|
427
488
|
state.servedModel = canonicalEventModel(resultModel);
|
|
428
489
|
}
|
|
490
|
+
|
|
429
491
|
const resultStopReason = optionalString(j.stop_reason);
|
|
492
|
+
|
|
430
493
|
if (state && resultStopReason) {
|
|
431
494
|
state.stopReason = resultStopReason;
|
|
495
|
+
|
|
432
496
|
if (resultStopReason === "refusal") state.refusalWithoutFallback = true;
|
|
433
497
|
}
|
|
434
|
-
|
|
498
|
+
|
|
499
|
+
const usage = toUsageBreakdown(ClaudeUsage.parse(rawUsage));
|
|
435
500
|
const quotaExhausted = text.startsWith("You've hit");
|
|
436
501
|
|
|
437
502
|
// SON-495: 비정상 종료(error_max_structured_output_retries 등)는 정직하게 에러로 처리한다.
|
|
@@ -450,8 +515,8 @@ export function handleStreamJsonLine(
|
|
|
450
515
|
return {
|
|
451
516
|
text,
|
|
452
517
|
usage,
|
|
453
|
-
durationMs:
|
|
454
|
-
costUsd:
|
|
518
|
+
durationMs: jsonNumber(j.duration_ms) ?? 0,
|
|
519
|
+
costUsd: jsonNumber(j.total_cost_usd) ?? 0,
|
|
455
520
|
quotaExhausted,
|
|
456
521
|
isError,
|
|
457
522
|
subtype,
|
|
@@ -13,7 +13,15 @@ export function getRefreshToken(creds: TokenCredentials): string | undefined {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export function getExpiresAt(creds: TokenCredentials): number {
|
|
16
|
+
// Grok credentials (authMode "oauth") store RFC 3339; an unparseable value reads as expired.
|
|
17
|
+
if ("authMode" in creds) {
|
|
18
|
+
const parsed = Date.parse(creds.expiresAt);
|
|
19
|
+
|
|
20
|
+
return Number.isNaN(parsed) ? 0 : parsed;
|
|
21
|
+
}
|
|
22
|
+
|
|
16
23
|
if ("expiresAt" in creds) return creds.expiresAt;
|
|
24
|
+
|
|
17
25
|
return creds.accessTokenExpiresAt;
|
|
18
26
|
}
|
|
19
27
|
|
|
@@ -16,11 +16,13 @@ const logger = getLogger(["qgrid", "effort"]);
|
|
|
16
16
|
// Codex 구독 백엔드 모델 카탈로그(~/.codex/models_cache.json) 의 supported_reasoning_levels 합집합.
|
|
17
17
|
// Public effort options exclude none/minimal. thinking:false maps to wire-level none separately.
|
|
18
18
|
export const OPENAI_EFFORTS = ["low", "medium", "high", "xhigh", "max", "ultra"] as const;
|
|
19
|
+
|
|
19
20
|
export type OpenAIEffort = (typeof OPENAI_EFFORTS)[number];
|
|
20
21
|
|
|
21
22
|
// Claude Code `--effort` 허용값. 모델별 상한(xhigh_effort / max_effort capability)은 Claude Code 가
|
|
22
23
|
// 스스로 처리하므로 qgrid 는 provider 집합만 검사한다.
|
|
23
24
|
export const ANTHROPIC_EFFORTS = ["low", "medium", "high", "xhigh", "max"] as const;
|
|
25
|
+
|
|
24
26
|
export type AnthropicEffort = (typeof ANTHROPIC_EFFORTS)[number];
|
|
25
27
|
|
|
26
28
|
// 어휘 안에 있고 상한(있다면) 이하인 값만 통과시킨다. 나머지는 debug 로그 후 미지정.
|
|
@@ -31,16 +33,21 @@ function resolveWithin<T extends string>(
|
|
|
31
33
|
target: string,
|
|
32
34
|
): T | undefined {
|
|
33
35
|
if (effort === undefined) return undefined;
|
|
34
|
-
const rank = levels.
|
|
36
|
+
const rank = levels.findIndex((level) => level === effort);
|
|
37
|
+
|
|
35
38
|
if (rank < 0) {
|
|
36
39
|
logger.debug(`ignoring effort "${effort}" for ${target}: not in ${levels.join("/")}`);
|
|
40
|
+
|
|
37
41
|
return undefined;
|
|
38
42
|
}
|
|
43
|
+
|
|
39
44
|
if (max !== undefined && rank > levels.indexOf(max)) {
|
|
40
45
|
logger.debug(`ignoring effort "${effort}" for ${target}: model supports up to "${max}"`);
|
|
46
|
+
|
|
41
47
|
return undefined;
|
|
42
48
|
}
|
|
43
|
-
|
|
49
|
+
|
|
50
|
+
return levels[rank];
|
|
44
51
|
}
|
|
45
52
|
|
|
46
53
|
/** canonical OpenAI model(`openai/` prefix 제거 후) 기준으로 effort 를 판정한다. */
|
|
@@ -1,6 +1,53 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
calculateCostUsd,
|
|
5
|
+
getModelCosts,
|
|
6
|
+
grokImageCost,
|
|
7
|
+
grokReportedCost,
|
|
8
|
+
usdFromGrokTicks,
|
|
9
|
+
} from "./model-cost";
|
|
10
|
+
|
|
11
|
+
describe("Grok cost", () => {
|
|
12
|
+
it("converts provider ticks at 1e-10 USD", () => {
|
|
13
|
+
expect(usdFromGrokTicks(500_000_000)).toBe(0.05);
|
|
14
|
+
expect(usdFromGrokTicks(33_760_000)).toBeCloseTo(0.003376, 12);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it.each(["grok-4.7", "grok-4.6", "grok-4.5", "grok/grok-4.7"])(
|
|
18
|
+
"prices %s from the catalog ticks when the provider omitted the cost",
|
|
19
|
+
(model) => {
|
|
20
|
+
expect(getModelCosts(model)).toEqual({ inputTokens: 2, cachedInputTokens: 0.5, outputTokens: 6 });
|
|
21
|
+
// 1M input of which 400k cached, 100k output: 0.6*2 + 0.4*0.5 + 0.1*6.
|
|
22
|
+
expect(
|
|
23
|
+
calculateCostUsd(model, {
|
|
24
|
+
inputTokens: 1_000_000,
|
|
25
|
+
cachedInputTokens: 400_000,
|
|
26
|
+
outputTokens: 100_000,
|
|
27
|
+
}),
|
|
28
|
+
).toBeCloseTo(2.0, 10);
|
|
29
|
+
},
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
it("prefers reported image ticks and falls back to the catalog per-image price", () => {
|
|
33
|
+
expect(grokImageCost("grok/grok-imagine-image-quality", 2, 700_000_000)).toEqual({
|
|
34
|
+
costUsd: 0.07,
|
|
35
|
+
costSource: "provider",
|
|
36
|
+
ticks: 700_000_000,
|
|
37
|
+
});
|
|
38
|
+
expect(grokImageCost("grok-imagine-image-quality", 2)).toEqual({
|
|
39
|
+
costUsd: 0.1,
|
|
40
|
+
costSource: "pricing_table",
|
|
41
|
+
ticks: 1_000_000_000,
|
|
42
|
+
});
|
|
43
|
+
expect(grokImageCost("grok-imagine-image-unknown", 1)).toBeUndefined();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("reports video/voice cost only when xAI reported it", () => {
|
|
47
|
+
expect(grokReportedCost(undefined)).toBeUndefined();
|
|
48
|
+
expect(grokReportedCost(0)).toEqual({ costUsd: 0, costSource: "provider", ticks: 0 });
|
|
49
|
+
});
|
|
50
|
+
});
|
|
4
51
|
|
|
5
52
|
describe("calculateCostUsd", () => {
|
|
6
53
|
it.each([
|