@cartanova/qgrid-cli 2.10.10 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/dist/_virtual/_rolldown/runtime.js +1 -10
- package/bundle/dist/application/monit/log-buffer.js +12 -6
- package/bundle/dist/application/monit/monit.frame.js +11 -3
- package/bundle/dist/application/monit/monit.types.js +1 -1
- package/bundle/dist/application/qgrid/conv-routing.js +9 -6
- package/bundle/dist/application/qgrid/expired-token-reminder.js +2 -2
- package/bundle/dist/application/qgrid/oauth.js +31 -4
- package/bundle/dist/application/qgrid/qgrid-image-generation.js +1 -1
- package/bundle/dist/application/qgrid/qgrid-response-format.js +21 -19
- package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +40 -33
- package/bundle/dist/application/qgrid/qgrid.dispatcher.js +128 -93
- package/bundle/dist/application/qgrid/qgrid.frame.js +930 -49
- package/bundle/dist/application/qgrid/qgrid.types.js +212 -5
- package/bundle/dist/application/qgrid/schema-prompt.js +75 -48
- package/bundle/dist/application/qgrid/slack-user-map.js +1 -1
- package/bundle/dist/application/qgrid/token-death.js +1 -1
- package/bundle/dist/application/qgrid/token-subscriber.js +83 -30
- package/bundle/dist/application/qgrid/token-trigger-setup.js +1 -1
- package/bundle/dist/application/qgrid/token-window-keepalive.js +8 -6
- package/bundle/dist/application/qgrid/tool-emulation-schema.js +13 -13
- package/bundle/dist/application/qgrid/tool-emulation.js +19 -15
- package/bundle/dist/application/request-log/json-schema-type-text.js +29 -12
- package/bundle/dist/application/request-log/request-log.model.js +83 -70
- package/bundle/dist/application/request-log/request-log.types.js +1 -1
- package/bundle/dist/application/request-log/zod-code-format.js +1 -1
- package/bundle/dist/application/request-log-step/request-log-step.model.js +1 -1
- package/bundle/dist/application/request-log-step/request-log-step.types.js +1 -1
- package/bundle/dist/application/setting/setting.constant.js +1 -1
- package/bundle/dist/application/setting/setting.model.js +2 -2
- package/bundle/dist/application/setting/setting.store.js +2 -2
- package/bundle/dist/application/setting/setting.types.js +1 -1
- package/bundle/dist/application/sonamu.generated.js +32 -16
- package/bundle/dist/application/sonamu.generated.sso.js +1 -1
- package/bundle/dist/application/token/token.model.js +26 -9
- package/bundle/dist/application/token/token.types.js +20 -3
- package/bundle/dist/i18n/en.js +15 -1
- package/bundle/dist/i18n/ko.js +15 -1
- package/bundle/dist/i18n/sd.generated.js +1 -1
- package/bundle/dist/migrations/20260807133553_manual__backfill_request_log_cost.js +8 -6
- package/bundle/dist/server-bootstrap.js +4 -2
- package/bundle/dist/server-error-handler.js +1 -1
- package/bundle/dist/sonamu.config.js +37 -8
- package/bundle/dist/startup-migrations.js +17 -7
- package/bundle/dist/testing/global.js +1 -1
- package/bundle/dist/testing/schema-bench.js +0 -0
- package/bundle/dist/testing/test-database-name.js +1 -1
- package/bundle/dist/utils/providers/anthropic/anthropic-constants.js +1 -1
- package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +11 -5
- package/bundle/dist/utils/providers/anthropic/anthropic-quota.js +4 -4
- package/bundle/dist/utils/providers/anthropic/anthropic-thinking.js +1 -1
- package/bundle/dist/utils/providers/anthropic/claude-session.js +20 -19
- package/bundle/dist/utils/providers/anthropic/fence-strip.js +1 -1
- package/bundle/dist/utils/providers/anthropic/stream-json-adapter.js +49 -23
- package/bundle/dist/utils/providers/common/credentials.js +5 -1
- package/bundle/dist/utils/providers/common/effort.js +3 -3
- package/bundle/dist/utils/providers/common/model-cost.js +69 -14
- package/bundle/dist/utils/providers/common/provider-types.js +29 -1
- package/bundle/dist/utils/providers/common/schema-validation.js +78 -40
- package/bundle/dist/utils/providers/common/smooth-weighted-round-robin.js +1 -1
- package/bundle/dist/utils/providers/common/strictifier.js +62 -43
- package/bundle/dist/utils/providers/common/thinking.js +3 -2
- package/bundle/dist/utils/providers/common/ttft.js +1 -1
- package/bundle/dist/utils/providers/grok/grok-backend-protocol.js +427 -0
- package/bundle/dist/utils/providers/grok/grok-constants.js +55 -0
- package/bundle/dist/utils/providers/grok/grok-direct-client.js +196 -0
- package/bundle/dist/utils/providers/grok/grok-dispatcher.js +1313 -0
- package/bundle/dist/utils/providers/grok/grok-headers.js +118 -0
- package/bundle/dist/utils/providers/grok/grok-media-client.js +420 -0
- package/bundle/dist/utils/providers/grok/grok-models.js +114 -0
- package/bundle/dist/utils/providers/grok/grok-oauth.js +455 -0
- package/bundle/dist/utils/providers/grok/grok-quota.js +119 -0
- package/bundle/dist/utils/providers/grok/grok-refresh.js +192 -0
- package/bundle/dist/utils/providers/grok/grok-types.js +186 -0
- package/bundle/dist/utils/providers/grok/grok-voice-client.js +199 -0
- package/bundle/dist/utils/providers/grok/index.js +11 -0
- package/bundle/dist/utils/providers/openai/openai-backend-protocol.js +111 -83
- package/bundle/dist/utils/providers/openai/openai-callback-relay.js +3 -2
- package/bundle/dist/utils/providers/openai/openai-constants.js +1 -1
- package/bundle/dist/utils/providers/openai/openai-direct-client.js +23 -7
- package/bundle/dist/utils/providers/openai/openai-dispatcher.js +143 -106
- package/bundle/dist/utils/providers/openai/openai-image-generation.js +48 -33
- package/bundle/dist/utils/providers/openai/openai-oauth.js +28 -13
- package/bundle/dist/utils/providers/openai/openai-quota.js +38 -27
- package/bundle/dist/utils/providers/openai/openai-refresh.js +17 -9
- package/bundle/dist/utils/providers/openai/openai-sse.js +1 -1
- package/bundle/dist/utils/providers/openai/openai-transport-config.js +1 -1
- package/bundle/dist/utils/quiet-hours.js +1 -1
- package/bundle/dist/utils/slack-notify.js +14 -8
- package/bundle/dist/utils/subset-loaders.js +4 -5
- package/bundle/src/application/monit/log-buffer.ts +23 -9
- package/bundle/src/application/monit/monit.frame.ts +22 -5
- package/bundle/src/application/monit/monit.types.ts +6 -0
- package/bundle/src/application/qgrid/conv-routing.test.ts +76 -4
- package/bundle/src/application/qgrid/conv-routing.ts +35 -9
- package/bundle/src/application/qgrid/expired-token-reminder.ts +9 -1
- package/bundle/src/application/qgrid/oauth.ts +51 -15
- package/bundle/src/application/qgrid/qgrid-image-generation.ts +9 -0
- package/bundle/src/application/qgrid/qgrid-response-format.ts +50 -25
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +19 -0
- package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +84 -40
- package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +97 -0
- package/bundle/src/application/qgrid/qgrid.dispatcher.ts +274 -126
- package/bundle/src/application/qgrid/qgrid.frame.test.ts +1013 -3
- package/bundle/src/application/qgrid/qgrid.frame.ts +1415 -60
- package/bundle/src/application/qgrid/qgrid.types.ts +335 -0
- package/bundle/src/application/qgrid/schema-prompt.ts +105 -41
- package/bundle/src/application/qgrid/slack-user-map.ts +5 -0
- package/bundle/src/application/qgrid/token-death.ts +4 -0
- package/bundle/src/application/qgrid/token-subscriber.test.ts +21 -19
- package/bundle/src/application/qgrid/token-subscriber.ts +186 -53
- package/bundle/src/application/qgrid/token-trigger-setup.ts +2 -0
- package/bundle/src/application/qgrid/token-window-keepalive.ts +49 -6
- package/bundle/src/application/qgrid/tool-emulation-schema.ts +33 -29
- package/bundle/src/application/qgrid/tool-emulation.ts +52 -27
- package/bundle/src/application/request-log/json-schema-type-text.test.ts +5 -5
- package/bundle/src/application/request-log/json-schema-type-text.ts +81 -26
- package/bundle/src/application/request-log/request-log.model.test.ts +111 -4
- package/bundle/src/application/request-log/request-log.model.ts +277 -146
- package/bundle/src/application/request-log/request-log.types.ts +6 -0
- package/bundle/src/application/request-log/zod-code-format.ts +11 -0
- package/bundle/src/application/request-log-step/request-log-step.model.ts +1 -0
- package/bundle/src/application/request-log-step/request-log-step.types.ts +2 -0
- package/bundle/src/application/setting/setting.constant.ts +9 -0
- package/bundle/src/application/setting/setting.model.ts +12 -2
- package/bundle/src/application/setting/setting.store.ts +5 -1
- package/bundle/src/application/setting/setting.types.ts +8 -0
- package/bundle/src/application/sonamu.generated.http +133 -0
- package/bundle/src/application/sonamu.generated.sso.ts +2 -0
- package/bundle/src/application/sonamu.generated.ts +15 -0
- package/bundle/src/application/token/token.identity.test.ts +20 -0
- package/bundle/src/application/token/token.model.ts +66 -7
- package/bundle/src/application/token/token.types.ts +24 -1
- package/bundle/src/i18n/en.ts +19 -0
- package/bundle/src/i18n/ko.ts +21 -0
- package/bundle/src/i18n/sd.generated.ts +23 -2
- package/bundle/src/migrations/20260807133553_manual__backfill_request_log_cost.ts +16 -8
- package/bundle/src/server-bootstrap.ts +4 -2
- package/bundle/src/server-error-handler.ts +1 -0
- package/bundle/src/sonamu.config.ts +69 -7
- package/bundle/src/startup-migrations.ts +27 -9
- package/bundle/src/testing/global.ts +20 -0
- package/bundle/src/testing/schema-bench.ts +105 -30
- package/bundle/src/testing/test-database-name.ts +2 -0
- package/bundle/src/utils/providers/anthropic/anthropic-constants.ts +8 -0
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +41 -6
- package/bundle/src/utils/providers/anthropic/anthropic-quota.ts +7 -3
- package/bundle/src/utils/providers/anthropic/anthropic-thinking.ts +6 -0
- package/bundle/src/utils/providers/anthropic/claude-session.ts +58 -24
- package/bundle/src/utils/providers/anthropic/fence-strip.ts +11 -0
- package/bundle/src/utils/providers/anthropic/stream-json-adapter.ts +110 -45
- package/bundle/src/utils/providers/common/credentials.ts +8 -0
- package/bundle/src/utils/providers/common/effort.ts +9 -2
- package/bundle/src/utils/providers/common/model-cost.test.ts +48 -1
- package/bundle/src/utils/providers/common/model-cost.ts +259 -158
- package/bundle/src/utils/providers/common/provider-dispatcher.ts +98 -2
- package/bundle/src/utils/providers/common/provider-types.ts +46 -3
- package/bundle/src/utils/providers/common/schema-validation.test.ts +5 -1
- package/bundle/src/utils/providers/common/schema-validation.ts +124 -56
- package/bundle/src/utils/providers/common/smooth-weighted-round-robin.ts +4 -0
- package/bundle/src/utils/providers/common/strictifier.ts +185 -59
- package/bundle/src/utils/providers/common/thinking.ts +2 -2
- package/bundle/src/utils/providers/common/ttft.ts +4 -2
- package/bundle/src/utils/providers/grok/__fixtures__/golden-responses-1.0.60.json +164 -0
- package/bundle/src/utils/providers/grok/grok-backend-protocol.test.ts +325 -0
- package/bundle/src/utils/providers/grok/grok-backend-protocol.ts +721 -0
- package/bundle/src/utils/providers/grok/grok-constants.ts +105 -0
- package/bundle/src/utils/providers/grok/grok-direct-client.test.ts +179 -0
- package/bundle/src/utils/providers/grok/grok-direct-client.ts +313 -0
- package/bundle/src/utils/providers/grok/grok-dispatcher.test.ts +1395 -0
- package/bundle/src/utils/providers/grok/grok-dispatcher.ts +2105 -0
- package/bundle/src/utils/providers/grok/grok-headers.test.ts +149 -0
- package/bundle/src/utils/providers/grok/grok-headers.ts +199 -0
- package/bundle/src/utils/providers/grok/grok-media-client.test.ts +446 -0
- package/bundle/src/utils/providers/grok/grok-media-client.ts +703 -0
- package/bundle/src/utils/providers/grok/grok-models.test.ts +96 -0
- package/bundle/src/utils/providers/grok/grok-models.ts +161 -0
- package/bundle/src/utils/providers/grok/grok-oauth.test.ts +406 -0
- package/bundle/src/utils/providers/grok/grok-oauth.ts +771 -0
- package/bundle/src/utils/providers/grok/grok-quota.test.ts +142 -0
- package/bundle/src/utils/providers/grok/grok-quota.ts +198 -0
- package/bundle/src/utils/providers/grok/grok-refresh.test.ts +239 -0
- package/bundle/src/utils/providers/grok/grok-refresh.ts +325 -0
- package/bundle/src/utils/providers/grok/grok-types.test.ts +252 -0
- package/bundle/src/utils/providers/grok/grok-types.ts +374 -0
- package/bundle/src/utils/providers/grok/grok-voice-client.test.ts +321 -0
- package/bundle/src/utils/providers/grok/grok-voice-client.ts +284 -0
- package/bundle/src/utils/providers/grok/index.ts +20 -0
- package/bundle/src/utils/providers/openai/openai-backend-protocol.ts +221 -137
- package/bundle/src/utils/providers/openai/openai-callback-relay.ts +12 -1
- package/bundle/src/utils/providers/openai/openai-constants.ts +2 -0
- package/bundle/src/utils/providers/openai/openai-direct-client.ts +111 -21
- package/bundle/src/utils/providers/openai/openai-dispatcher.ts +322 -169
- package/bundle/src/utils/providers/openai/openai-image-generation.ts +116 -36
- package/bundle/src/utils/providers/openai/openai-oauth.ts +48 -20
- package/bundle/src/utils/providers/openai/openai-quota.ts +77 -46
- package/bundle/src/utils/providers/openai/openai-refresh.ts +42 -18
- package/bundle/src/utils/providers/openai/openai-sse.ts +27 -3
- package/bundle/src/utils/providers/openai/openai-transport-config.ts +2 -0
- package/bundle/src/utils/quiet-hours.ts +12 -1
- package/bundle/src/utils/slack-notify.ts +44 -13
- package/bundle/src/utils/subset-loaders.ts +7 -7
- package/bundle/web-dist/client/assets/clsx-5XM_pHvN.js +1 -0
- package/bundle/web-dist/client/assets/index-BA7uQ-6c.js +31 -0
- package/bundle/web-dist/client/assets/index-Be2qCZmI.css +1 -0
- package/bundle/web-dist/client/assets/logs-C47OJGEI.js +1 -0
- package/bundle/web-dist/client/assets/monit-BS9no0dU.js +4 -0
- package/bundle/web-dist/client/assets/plus-sdACTfH0.js +1 -0
- package/bundle/web-dist/client/assets/refresh-cw-CY8o_1cT.js +1 -0
- package/bundle/web-dist/client/assets/request-model-BRtFuZvj.js +1 -0
- package/bundle/web-dist/client/assets/routes-kqgkUxE8.js +5 -0
- package/bundle/web-dist/client/assets/{services.generated-NP-ValHd.js → services.generated-CefiDXEv.js} +5 -5
- package/bundle/web-dist/client/assets/settings-DNDvFGSw.js +1 -0
- package/bundle/web-dist/client/assets/show-u8Np69q3.js +2 -0
- package/bundle/web-dist/client/assets/tokens-QvP410NW.js +1 -0
- package/bundle/web-dist/client/assets/total-cost-MnfKU8IN.js +1 -0
- package/bundle/web-dist/client/assets/use-oauth-login-flow-Bzdh28Ws.js +1 -0
- package/bundle/web-dist/client/assets/use-update-token-mutation-CfJKaxmR.js +1 -0
- package/bundle/web-dist/client/assets/vendor-react-CUFFrVN9.js +244 -0
- package/bundle/web-dist/client/assets/vendor-tanstack-Bf_jag9G.js +1 -0
- package/bundle/web-dist/client/index.html +6 -6
- package/bundle/web-dist/server/assets/clsx-D_N5PN_2.js +16 -0
- package/bundle/web-dist/server/assets/{lazyRouteComponent-CgBdabgd.js → lazyRouteComponent-D8iTIHyn.js} +129 -2
- package/bundle/web-dist/server/assets/logs-B3OTd9hy.js +825 -0
- package/bundle/web-dist/server/assets/{monit-ZPt66W5M.js → monit-B2hqorPe.js} +385 -126
- package/bundle/web-dist/server/assets/plus-DwG7h9kq.js +28 -0
- package/bundle/web-dist/server/assets/{react-dom-Ds75e4Jl.js → react-dom-BIYQzBqG.js} +2 -129
- package/bundle/web-dist/server/assets/refresh-cw-mMBkwOq0.js +44 -0
- package/bundle/web-dist/server/assets/{request-model-DjGldb-h.js → request-model-I6OdODSH.js} +15 -6
- package/bundle/web-dist/server/assets/{routes-Ct-k7nBA.js → routes-B95YlUv2.js} +760 -213
- package/bundle/web-dist/server/assets/{services.generated-BA4AcAf5.js → services.generated-DQATJ6qf.js} +12820 -12194
- package/bundle/web-dist/server/assets/settings-C3gbGk0m.js +830 -0
- package/bundle/web-dist/server/assets/{show-LSFIzvO2.js → show-Bxaj3rhH.js} +1350 -418
- package/bundle/web-dist/server/assets/tokens-CZjH3cB7.js +1038 -0
- package/bundle/web-dist/server/assets/total-cost-fTE9Xy82.js +18 -0
- package/bundle/web-dist/server/assets/use-oauth-login-flow-CKDHgc3U.js +2379 -0
- package/bundle/web-dist/server/assets/{use-update-token-mutation-pkArIzCP.js → use-update-token-mutation-BEbgOzaa.js} +1 -1
- package/bundle/web-dist/server/entry-server.generated.js +4295 -22810
- package/dist/cli.js +9 -9
- package/package.json +4 -11
- package/postinstall.mjs +12 -0
- package/skills/qgrid/SKILL.md +1 -0
- package/skills/qgrid/references/cli-env-and-server-boot.md +4 -1
- package/skills/qgrid/references/decision-rationale.md +23 -0
- package/skills/qgrid/references/grok-runtime.md +89 -0
- package/skills/qgrid/references/provider-runtime-differences.md +30 -29
- package/skills/qgrid/references/repo-map.md +10 -0
- package/skills/qgrid/references/token-auth-quota-lifecycle.md +56 -3
- package/bundle/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +0 -406
- package/bundle/dist/node_modules/.pnpm/@vitest_expect@4.1.10/node_modules/@vitest/expect/dist/index.js +0 -1507
- package/bundle/dist/node_modules/.pnpm/@vitest_pretty-format@4.1.10/node_modules/@vitest/pretty-format/dist/index.js +0 -887
- package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/chunk-artifact.js +0 -2756
- package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/index.js +0 -8
- package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/utils.js +0 -8
- package/bundle/dist/node_modules/.pnpm/@vitest_snapshot@4.1.10/node_modules/@vitest/snapshot/dist/index.js +0 -922
- package/bundle/dist/node_modules/.pnpm/@vitest_spy@4.1.10/node_modules/@vitest/spy/dist/index.js +0 -386
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +0 -121
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/constants.js +0 -51
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/diff.js +0 -1317
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/display.js +0 -561
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/error.js +0 -40
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/helpers.js +0 -272
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/offset.js +0 -27
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/serialize.js +0 -77
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/source-map.js +0 -381
- package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/timers.js +0 -51
- package/bundle/dist/node_modules/.pnpm/chai@6.2.2/node_modules/chai/index.js +0 -2986
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.js +0 -10
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.js +0 -109
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.js +0 -10
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.js +0 -10
- package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.js +0 -10
- package/bundle/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +0 -1126
- package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.js +0 -21
- package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +0 -432
- package/bundle/dist/node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.js +0 -517
- package/bundle/dist/node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js +0 -101
- package/bundle/dist/node_modules/.pnpm/vite@8.0.3_@emnapi_core@1.11.2_@emnapi_runtime@1.11.2_@types_node@25.0.7_esbuild@0.27.4_5b35fc1fb85d2af4d105e0d74f940f50/node_modules/vite/dist/node/module-runner.js +0 -1265
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js +0 -9
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/benchmark.CX_oY03V.js +0 -41
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/evaluatedModules.Dg1zASAC.js +0 -19
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/index.Chj8NDwU.js +0 -202
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/index.DdgEv5B1.js +0 -46
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/rpc.MzXet3jl.js +0 -119
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/test.DNmyFkvJ.js +0 -3044
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.js +0 -59
- package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_vi_a1977b93af7bb69308bcb1dbab39b618/node_modules/vitest/dist/index.js +0 -28
- package/bundle/dist/testing/setup-mocks.js +0 -16
- package/bundle/src/testing/setup-mocks.ts +0 -44
- package/bundle/web-dist/client/assets/index-Bw2s88Ot.css +0 -1
- package/bundle/web-dist/client/assets/index-DZwzUfI-.js +0 -106
- package/bundle/web-dist/client/assets/logs-Cog79DU5.js +0 -1
- package/bundle/web-dist/client/assets/monit-2auznBys.js +0 -1
- package/bundle/web-dist/client/assets/plus-B62CuqT8.js +0 -1
- package/bundle/web-dist/client/assets/refresh-cw-NNcU0Cmq.js +0 -1
- package/bundle/web-dist/client/assets/request-model-CojtinqK.js +0 -1
- package/bundle/web-dist/client/assets/routes-B0lTeLK-.js +0 -5
- package/bundle/web-dist/client/assets/settings-D8ZxZGSJ.js +0 -1
- package/bundle/web-dist/client/assets/show-CFSERlnM.js +0 -2
- package/bundle/web-dist/client/assets/tokens-CZXUyI7O.js +0 -1
- package/bundle/web-dist/client/assets/use-oauth-login-flow-hboOs3wG.js +0 -1
- package/bundle/web-dist/client/assets/use-update-token-mutation-BQHS0byG.js +0 -1
- package/bundle/web-dist/client/assets/vendor-react-DH4kUfK2.js +0 -9
- package/bundle/web-dist/client/assets/vendor-tanstack-DJRQAbrY.js +0 -1
- package/bundle/web-dist/server/assets/logs-BMyR98rU.js +0 -509
- package/bundle/web-dist/server/assets/plus-BZ9I0VgC.js +0 -19
- package/bundle/web-dist/server/assets/refresh-cw-CztCFis-.js +0 -23
- package/bundle/web-dist/server/assets/settings-CBUZ47Xx.js +0 -461
- package/bundle/web-dist/server/assets/tokens-DxrBW512.js +0 -448
- package/bundle/web-dist/server/assets/use-oauth-login-flow-Gn8flMK5.js +0 -178
- package/dist/cli.d.ts +0 -10
- /package/bundle/web-dist/client/assets/{cost-DH2jZbrw.js → cost-DB3HbU7T.js} +0 -0
- /package/bundle/web-dist/client/assets/{preload-helper-ca-nBW7U.js → preload-helper-DWTEM3RW.js} +0 -0
- /package/bundle/web-dist/server/assets/{cost-eEHeTRT5.js → cost-BC9yzyA9.js} +0 -0
package/dist/cli.js
CHANGED
|
@@ -39,7 +39,7 @@ function runSelfUpdate(params, dependencies) {
|
|
|
39
39
|
try {
|
|
40
40
|
latest = latestVersion(packageName);
|
|
41
41
|
} catch (cause) {
|
|
42
|
-
warn(`Warning: failed to check for qgrid-cli updates: ${cause.message}`);
|
|
42
|
+
warn(`Warning: failed to check for qgrid-cli updates: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
43
43
|
warn(`Continuing with qgrid-cli ${currentVersion}.`);
|
|
44
44
|
return { kind: "continue" };
|
|
45
45
|
}
|
|
@@ -60,7 +60,8 @@ function runSelfUpdate(params, dependencies) {
|
|
|
60
60
|
return { kind: "continue" };
|
|
61
61
|
}
|
|
62
62
|
} catch (cause) {
|
|
63
|
-
|
|
63
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
64
|
+
warn(`Warning: failed to update qgrid-cli to ${latest}: ${message}`);
|
|
64
65
|
warn(`Continuing with qgrid-cli ${currentVersion}; fix the global ${packageManager} install.`);
|
|
65
66
|
return { kind: "continue" };
|
|
66
67
|
}
|
|
@@ -213,13 +214,12 @@ function ensureLatestRuntimeCliDependencies() {
|
|
|
213
214
|
installedOutput = commandVersion(dep.command);
|
|
214
215
|
}
|
|
215
216
|
} catch (e) {
|
|
216
|
-
console.warn(`Warning: failed to update ${dep.label}: ${e.message}`);
|
|
217
|
+
console.warn(`Warning: failed to update ${dep.label}: ${e instanceof Error ? e.message : String(e)}`);
|
|
217
218
|
}
|
|
218
219
|
if (!installedOutput) warnMissingRuntimeCliDependency(dep);
|
|
219
220
|
}
|
|
220
221
|
}
|
|
221
|
-
function normalizePort(
|
|
222
|
-
const value = String(port);
|
|
222
|
+
function normalizePort(value) {
|
|
223
223
|
const numeric = Number(value);
|
|
224
224
|
if (!/^\d+$/.test(value) || numeric < 1 || numeric > 65535) {
|
|
225
225
|
console.error(`Invalid port: ${value}`);
|
|
@@ -303,10 +303,10 @@ program.name("qgrid").version(pkg.version).description("Qgrid — LLM subscripti
|
|
|
303
303
|
await client.connect();
|
|
304
304
|
await client.end();
|
|
305
305
|
} catch (e) {
|
|
306
|
-
const
|
|
306
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
307
307
|
console.error(`Error: Cannot connect to PostgreSQL at ${dbHost}:${dbPort}/${dbName}`);
|
|
308
|
-
console.error(`error: ${
|
|
309
|
-
if (
|
|
308
|
+
console.error(`error: ${message}`);
|
|
309
|
+
if (message.includes("timeout expired")) console.error(`cannot connect to the database server. Please check if the database is running and accessible.`);
|
|
310
310
|
console.error(`\nProvide DB connection via --db flag or QGRID_DB_* env vars:`);
|
|
311
311
|
console.error(` qgrid --db postgres://user:password@host:port/dbname`);
|
|
312
312
|
process.exit(1);
|
|
@@ -314,7 +314,7 @@ program.name("qgrid").version(pkg.version).description("Qgrid — LLM subscripti
|
|
|
314
314
|
try {
|
|
315
315
|
await import(serverEntry);
|
|
316
316
|
} catch (e) {
|
|
317
|
-
console.error("Failed to start server:", e.stack ?? e.message);
|
|
317
|
+
console.error("Failed to start server:", e instanceof Error ? e.stack ?? e.message : e);
|
|
318
318
|
process.exit(1);
|
|
319
319
|
}
|
|
320
320
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cartanova/qgrid-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/cartanova-ai/qgrid"
|
|
@@ -20,20 +20,15 @@
|
|
|
20
20
|
"@ai-sdk/anthropic": "^3.0.0",
|
|
21
21
|
"@ai-sdk/provider": "^3.0.0",
|
|
22
22
|
"@ai-sdk/provider-utils": "^4.0.0",
|
|
23
|
-
"@anthropic-ai/sdk": "^0.81.0",
|
|
24
23
|
"@better-auth/core": "~1.6.0",
|
|
25
24
|
"@better-auth/passkey": "~1.6.0",
|
|
26
25
|
"@better-auth/sso": "~1.6.0",
|
|
27
26
|
"@logtape/logtape": "2.0.0",
|
|
28
27
|
"@logtape/pretty": "2.0.0",
|
|
29
|
-
"@
|
|
30
|
-
"@oxc-project/runtime": "^0.79.0",
|
|
28
|
+
"@oxc-project/runtime": "^0.79.1",
|
|
31
29
|
"ai": "^6.0.1",
|
|
32
|
-
"bcrypt": "^6.0.0",
|
|
33
30
|
"better-auth": "~1.6.0",
|
|
34
|
-
"chalk": "^4.1.2",
|
|
35
31
|
"commander": "^13.0.0",
|
|
36
|
-
"date-fns": "^4.1.0",
|
|
37
32
|
"dotenv": "^16",
|
|
38
33
|
"fastify": "^4",
|
|
39
34
|
"ioredis": "^5.8.2",
|
|
@@ -41,16 +36,14 @@
|
|
|
41
36
|
"knex": "^3.2.9",
|
|
42
37
|
"pg": "^8.16.3",
|
|
43
38
|
"pngjs": "^7.0.0",
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"typescript": "6.0.3",
|
|
39
|
+
"sonamu": "0.11.16",
|
|
40
|
+
"typescript": "7.1.0-dev.20260831.1",
|
|
47
41
|
"ws": "8.20.0",
|
|
48
42
|
"zod": "^4.3.6"
|
|
49
43
|
},
|
|
50
44
|
"devDependencies": {
|
|
51
45
|
"@types/node": "25.0.7",
|
|
52
46
|
"@types/pg": "^8.20.0",
|
|
53
|
-
"@types/ws": "8.18.1",
|
|
54
47
|
"semver": "^7.7.4",
|
|
55
48
|
"tsdown": "^0.22.3",
|
|
56
49
|
"yaml": "^2.8.2"
|
package/postinstall.mjs
CHANGED
|
@@ -28,6 +28,7 @@ function findProjectRoot(startDir) {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
const parent = path.dirname(current);
|
|
31
|
+
|
|
31
32
|
if (parent === current) return packageJsonRoot ?? path.resolve(startDir);
|
|
32
33
|
current = parent;
|
|
33
34
|
}
|
|
@@ -35,15 +36,19 @@ function findProjectRoot(startDir) {
|
|
|
35
36
|
|
|
36
37
|
function defaultProjectRoot() {
|
|
37
38
|
if (process.env.QGRID_SKILLS_CWD) return findProjectRoot(process.env.QGRID_SKILLS_CWD);
|
|
39
|
+
|
|
38
40
|
if (process.env.INIT_CWD) return findProjectRoot(process.env.INIT_CWD);
|
|
39
41
|
|
|
40
42
|
const cwd = process.cwd();
|
|
43
|
+
|
|
41
44
|
if (cwd.includes(`${path.sep}node_modules${path.sep}`)) return null;
|
|
45
|
+
|
|
42
46
|
return findProjectRoot(cwd);
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
function isInside(parentDir, childDir) {
|
|
46
50
|
const relative = path.relative(path.resolve(parentDir), path.resolve(childDir));
|
|
51
|
+
|
|
47
52
|
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
|
|
48
53
|
}
|
|
49
54
|
|
|
@@ -55,9 +60,11 @@ function defaultTargets() {
|
|
|
55
60
|
const codexHome = process.env.CODEX_HOME
|
|
56
61
|
? path.resolve(process.env.CODEX_HOME)
|
|
57
62
|
: path.join(os.homedir(), ".codex");
|
|
63
|
+
|
|
58
64
|
const claudeHome = process.env.CLAUDE_HOME
|
|
59
65
|
? path.resolve(process.env.CLAUDE_HOME)
|
|
60
66
|
: path.join(os.homedir(), ".claude");
|
|
67
|
+
|
|
61
68
|
return [
|
|
62
69
|
{ label: "Codex", target: path.join(codexHome, "skills", "qgrid"), useSymlink: false },
|
|
63
70
|
{ label: "Claude Code", target: path.join(claudeHome, "skills", "qgrid"), useSymlink: false },
|
|
@@ -65,10 +72,13 @@ function defaultTargets() {
|
|
|
65
72
|
}
|
|
66
73
|
|
|
67
74
|
const projectRoot = defaultProjectRoot();
|
|
75
|
+
|
|
68
76
|
if (!projectRoot) return null;
|
|
69
77
|
const isInstalledPackage = packageDir.split(path.sep).includes("node_modules");
|
|
78
|
+
|
|
70
79
|
if (!isInstalledPackage && isInside(projectRoot, sourceSkillsDir)) {
|
|
71
80
|
console.log("qgrid skill sync skipped: running inside qgrid repository.");
|
|
81
|
+
|
|
72
82
|
return [];
|
|
73
83
|
}
|
|
74
84
|
|
|
@@ -89,6 +99,7 @@ function defaultTargets() {
|
|
|
89
99
|
async function syncSkill({ label, target, useSymlink }) {
|
|
90
100
|
if (!existsSync(path.join(sourceSkillsDir, "SKILL.md"))) {
|
|
91
101
|
console.log("qgrid skill source not found in qgrid CLI package.");
|
|
102
|
+
|
|
92
103
|
return;
|
|
93
104
|
}
|
|
94
105
|
|
|
@@ -99,6 +110,7 @@ async function syncSkill({ label, target, useSymlink }) {
|
|
|
99
110
|
try {
|
|
100
111
|
await symlink(sourceSkillsDir, target, "dir");
|
|
101
112
|
console.log(`qgrid skill linked for ${label}: ${target}`);
|
|
113
|
+
|
|
102
114
|
return;
|
|
103
115
|
} catch (error) {
|
|
104
116
|
console.log(
|
package/skills/qgrid/SKILL.md
CHANGED
|
@@ -21,6 +21,7 @@ Before changing code, identify the affected path:
|
|
|
21
21
|
- OpenAI direct transport, permits, routing, cache affinity, OAuth, or quota behavior: read `references/openai-codex-runtime.md`.
|
|
22
22
|
- Adding an OpenAI model, its pricing, or reasoning levels: follow the model-addition checklist in `references/openai-codex-runtime.md`.
|
|
23
23
|
- Anthropic models or Claude Code spawn/stream-json behavior: read `references/anthropic-claude-code-runtime.md`.
|
|
24
|
+
- Grok fingerprinting, OAuth, quota routing, media, voice, or retry behavior: read `references/grok-runtime.md`.
|
|
24
25
|
- Token registration, OAuth, token sync, active/inactive behavior, quota thresholds, or weighted token routing: read `references/token-auth-quota-lifecycle.md`.
|
|
25
26
|
- Provider comparisons, routing, or cross-provider bugs: read `references/provider-runtime-differences.md`.
|
|
26
27
|
- Tool calling, AI SDK multi-step loops, or tool-call request logs: read `references/tool-calling-and-multiturn.md`.
|
|
@@ -66,6 +66,8 @@ When helping a user set up qgrid locally, check for `QGRID_PROJECT_NAME` or conf
|
|
|
66
66
|
|---|---:|---|
|
|
67
67
|
| `QGRID_OPENAI_TRANSPORT` | `websocket` | OpenAI transport selector (`https` or `websocket`). Invalid values fail at dispatcher configuration time. This is the only OpenAI runtime knob; there is no concurrency cap. |
|
|
68
68
|
| `QGRID_OPENAI_AUTOSCALE` / `QGRID_OPENAI_MIN_WORKERS_PER_TOKEN` / `QGRID_OPENAI_MAX_WORKERS_PER_TOKEN` / `QGRID_OPENAI_PERMITS_PER_TOKEN` | ignored | Removed. OpenAI requests run uncapped like Anthropic (stateless per-request execution); setting these has no effect. |
|
|
69
|
+
| `QGRID_GROK_MAX_INFLIGHT_PER_TOKEN` | unset (uncapped) | Optional positive-integer per-account Grok cap. Accounts at the cap are excluded from selection rather than queued. Invalid values are ignored with a warning (`packages/api/src/utils/providers/grok/grok-dispatcher.ts`). |
|
|
70
|
+
| `QGRID_GROK_LIVE_TOKEN_ID` | unset | Reserved token-row selector for opt-in Grok live tests. Keep it unset in CI and ordinary server runs. The live-test gate is specified in `docs/plans/2026-10-16-grok-provider-integration-plan.md` §7; no current server runtime behavior reads it. |
|
|
69
71
|
| `QGRID_TOKEN_WINDOW_KEEPALIVE_ENABLED` | off | Marks this instance as the Anthropic 5-hour window keepalive runner (2.8.0, `ea7feb3`). Only the literal `true` enables it; set it on exactly one instance per shared DB so developer instances do not fire duplicates. Two more gates apply: the global setting `qgrid.tokenWindowKeepaliveEnabled` (`false` turns everything off; changing it reschedules immediately) and the per-token `tokens.keepalive_enabled` flag (default `false`, dashboard settings-panel toggle). In 2.7.6 this env was a default-on global switch with no per-token opt-in. |
|
|
70
72
|
| `MAX_STRUCTURED_OUTPUT_RETRIES` | `1` for structured Anthropic streaming calls | Claude Code structured-output retry count for streaming only, clamped to at least 1 by qgrid. Non-streaming `generate` leaves the variable unset and uses Claude Code's default retry budget. |
|
|
71
73
|
|
|
@@ -81,7 +83,8 @@ When helping a user set up qgrid locally, check for `QGRID_PROJECT_NAME` or conf
|
|
|
81
83
|
1. Ensures PostgreSQL `tokens_changed` triggers.
|
|
82
84
|
2. Starts `TokenSubscriber` for LISTEN/NOTIFY plus periodic reconcile.
|
|
83
85
|
3. Starts `OpenAIDispatcher` and `AnthropicDispatcher`.
|
|
84
|
-
4.
|
|
86
|
+
4. Constructs `GrokRefreshCoordinator`, `GrokMediaClient`, and `GrokVoiceClient`, injects them into `GrokDispatcher`, starts it, then reconciles Grok tokens (`packages/api/src/sonamu.config.ts`).
|
|
87
|
+
5. Logs server URL and provider readiness counts.
|
|
85
88
|
|
|
86
89
|
On shutdown, it stops provider dispatchers and the token subscriber.
|
|
87
90
|
|
|
@@ -10,6 +10,7 @@ Do not copy these notes blindly into implementation. Use them to find the releva
|
|
|
10
10
|
- Tool calling and request-log lifecycle
|
|
11
11
|
- OpenAI/Codex runtime
|
|
12
12
|
- Anthropic/Claude Code runtime
|
|
13
|
+
- Grok (xAI subscription) runtime
|
|
13
14
|
- Token sync and quota thresholds
|
|
14
15
|
- Weighted token routing
|
|
15
16
|
- Request logs, metrics, and dashboard
|
|
@@ -133,6 +134,28 @@ Key decisions:
|
|
|
133
134
|
- `--setting-sources project` is required for shared-service isolation. User/local Claude settings can load hooks or memory and leak context across requests.
|
|
134
135
|
- Claude Code OAuth prompt cache sharing across tokens in the same workspace is an observed cost behavior, not a product contract. Monitor it; do not promise it.
|
|
135
136
|
|
|
137
|
+
## Grok (xAI Subscription) Runtime
|
|
138
|
+
|
|
139
|
+
Sources:
|
|
140
|
+
|
|
141
|
+
- `docs/plans/2026-10-16-grok-provider-integration-plan.md`
|
|
142
|
+
- `docs/diagnosis/2026-10-16-grok-live-probe.md`
|
|
143
|
+
- `packages/api/src/utils/providers/grok/*`
|
|
144
|
+
- `packages/api/src/application/qgrid/qgrid.dispatcher.ts`
|
|
145
|
+
|
|
146
|
+
Key decisions:
|
|
147
|
+
|
|
148
|
+
- **D1 — accepted terms risk:** The user accepted the risk of using an xAI subscription token from a non-official client and authorized the bounded live probe. This is recorded acceptance, not a claim that xAI permits every deployment.
|
|
149
|
+
- **D2 — reproduce grok-build:** Qgrid sends the full installed grok-build fingerprint. `GROK_BUILD_VERSION` is a source pin, not an environment override; changing it requires a new installed-binary capture, golden fixture, build id, and fingerprint test.
|
|
150
|
+
- **D3 — subscription OAuth only:** Grok tokens must be `at+jwt` OAuth credentials issued by `auth.x.ai`. Raw xAI API keys are outside qgrid's subscription-pooling purpose.
|
|
151
|
+
- **D4 — URL video delivery:** Return the upstream `api.x.ai` video URL in the AI SDK URL result. Qgrid does not download, proxy, or persist video bytes.
|
|
152
|
+
- **D5 — no new workspace package:** Grok runtime code lives under `packages/api/src/utils/providers/grok/`; SDK adapters stay in `packages/ai-sdk/src/`.
|
|
153
|
+
- **D6 — exclude on-demand billing:** An account with `/settings.on_demand_enabled = true` is ineligible. There is no per-token override because the exclusion closes accidental paid usage.
|
|
154
|
+
- **D7 — shared weighted routing:** Grok uses the common `SmoothWeightedRoundRobin` with `tokens.weight`, after quota, on-demand, cooldown, entitlement, and optional in-flight gates.
|
|
155
|
+
- **D8 — preserve tool emulation:** Grok remains on qgrid's shared strict action-envelope tool contract. The provider can emit native function calls, but qgrid callers continue to receive the same emulated AI SDK multi-step lifecycle as the other routes.
|
|
156
|
+
|
|
157
|
+
Current implementation evidence is in `grok-constants.ts`, `grok-dispatcher.ts`, `grok-oauth.ts`, `grok-media-client.ts`, `packages/api/src/application/qgrid/qgrid.frame.ts`, and `qgrid.dispatcher.ts`. See `references/grok-runtime.md` for operational details and unverified gaps.
|
|
158
|
+
|
|
136
159
|
## Token Sync And Quota Thresholds
|
|
137
160
|
|
|
138
161
|
Sources:
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Grok Direct Runtime
|
|
2
|
+
|
|
3
|
+
Use this reference before changing Grok chat transport, fingerprinting, OAuth, quota routing, media, voice, cost accounting, or retry behavior.
|
|
4
|
+
|
|
5
|
+
## Source files
|
|
6
|
+
|
|
7
|
+
- Fingerprint constants and headers: `packages/api/src/utils/providers/grok/grok-constants.ts`, `grok-headers.ts`.
|
|
8
|
+
- Chat protocol, transport, models, and dispatch: `grok-backend-protocol.ts`, `grok-direct-client.ts`, `grok-models.ts`, `grok-dispatcher.ts`.
|
|
9
|
+
- OAuth, refresh, billing, and settings: `grok-oauth.ts`, `grok-refresh.ts`, `grok-quota.ts`.
|
|
10
|
+
- Image/video and voice clients: `grok-media-client.ts`, `grok-voice-client.ts`.
|
|
11
|
+
- API limits and endpoints: `packages/api/src/application/qgrid/qgrid.types.ts`, `qgrid.frame.ts`.
|
|
12
|
+
- Probe evidence and design decisions: `docs/diagnosis/2026-10-16-grok-live-probe.md`, `docs/plans/2026-10-16-grok-provider-integration-plan.md`.
|
|
13
|
+
|
|
14
|
+
## Hosts and fingerprint
|
|
15
|
+
|
|
16
|
+
Grok uses the same xAI subscription OAuth bearer on two hosts, but the header families are not interchangeable (`grok-constants.ts`, `grok-headers.ts`):
|
|
17
|
+
|
|
18
|
+
| Host | Operations | Identity headers |
|
|
19
|
+
| --- | --- | --- |
|
|
20
|
+
| `https://cli-chat-proxy.grok.com/v1` | `/responses`, `/settings`, `/models`, `/billing`, `/user` | `grok-shell/1.0.60 (<os>; <arch>)`, client version and identifier, client mode, and the proxy auth headers. `/responses` also sends the captured `x-grok-*` conversation headers, trace context, loop guards, and zstd encoding. |
|
|
21
|
+
| `https://api.x.ai/v1` | image generation/editing, video start/status, STT, TTS | Media uses `xai-grok-build/1.0.60`; voice uses the shell user agent. Both send the client version and identifier, but never the proxy auth trio. |
|
|
22
|
+
|
|
23
|
+
D2 requires the installed grok-build fingerprint. `GROK_BUILD_VERSION` is pinned to `1.0.60` and `GROK_BUILD_COMMIT` to build `01a8e1c591c0`; the golden request came from the installed binary, not the older public source (`grok-constants.ts`, `grok-headers.test.ts`, `docs/diagnosis/2026-10-16-grok-live-probe.md`).
|
|
24
|
+
|
|
25
|
+
Handle the pin like OpenAI's `CODEX_CLI_VERSION`: keep it as a source constant with no runtime override. To bump it:
|
|
26
|
+
|
|
27
|
+
1. Edit `GROK_BUILD_VERSION` in `grok-constants.ts`.
|
|
28
|
+
2. Run the newly installed grok-build binary through an intercepting proxy and re-capture the redacted golden request fixture.
|
|
29
|
+
3. Update `GROK_BUILD_COMMIT` with that binary's build id.
|
|
30
|
+
4. Run `grok-headers.test.ts` and the golden fingerprint test before release.
|
|
31
|
+
|
|
32
|
+
The proxy treats the client version as a floor. The 2026-10-16 probe saw `/settings.min_client_version = 1.0.13`; a lower client received HTTP 426. The dispatcher trips a chat-only fast gate for 10 minutes and reports the bump routine (`docs/diagnosis/2026-10-16-grok-live-probe.md`, `grok-dispatcher.ts`).
|
|
33
|
+
|
|
34
|
+
## OAuth, credentials, and refresh
|
|
35
|
+
|
|
36
|
+
Grok login uses OIDC discovery under `https://auth.x.ai`, public client id `b1a00492-073a-47ea-816f-4c329264a828`, S256 PKCE, `referrer=grok-build`, and these frozen scopes: `openid profile email offline_access grok-cli:access api:access conversations:read conversations:write workspaces:read workspaces:write` (`grok-constants.ts`, `grok-oauth.ts`).
|
|
37
|
+
|
|
38
|
+
Browser login uses a random `127.0.0.1` callback and accepts either the full callback URL or a pasted bare code. Qgrid exposes this as code-paste completion because it does not serve the random callback. Device login uses `/oauth2/device/code`, polls `/oauth2/token` at the returned interval, and adds five seconds after `slow_down` (`grok-oauth.ts`, `packages/api/src/application/qgrid/qgrid.frame.ts`).
|
|
39
|
+
|
|
40
|
+
Stored credentials contain OAuth access/refresh tokens, RFC 3339 expiry, issuer, client id, scopes, `userId`, stable session/agent ids, and an optional tier. Registration accepts only an `at+jwt` issued by `auth.x.ai`; the post-login `/user` lookup resolves the account (`grok-types.ts`, `grok-oauth.ts`). `userId` is the token identity key, so signing in again replaces the prior row for the same account while preserving token settings (`packages/api/src/application/token/token.model.ts`).
|
|
41
|
+
|
|
42
|
+
Refresh starts 300 seconds plus stable 0–60 second per-account jitter before expiry, coalesces concurrent refreshes, persists before publishing credentials, and retains the old refresh token when xAI does not rotate it. Only `invalid_grant` and `invalid_client` require a new login; network errors, 429, 5xx, and unknown OAuth errors remain transient. An upstream 401 permits one forced refresh and one same-token retry (`grok-refresh.ts`, `grok-dispatcher.ts`).
|
|
43
|
+
|
|
44
|
+
## Quota, billing, and token selection
|
|
45
|
+
|
|
46
|
+
`/billing?format=credits` is camelCase: qgrid reads `config.creditUsagePercent`, `config.currentPeriod`, and `config.prepaidBalance.val`. The observed period was seven days anchored at subscription start. Results are cached for 60 seconds; lookup failure fails open (`grok-quota.ts`, `grok-dispatcher.ts`, `docs/diagnosis/2026-10-16-grok-live-probe.md`).
|
|
47
|
+
|
|
48
|
+
D6 excludes accounts when `/settings.on_demand_enabled` is `true`; `null`, `false`, or absence allows routing. Billing does not carry this field. D7 selects eligible accounts through the shared `SmoothWeightedRoundRobin`, using `tokens.weight`; a valid cache-affinity token remains preferred. `QGRID_GROK_MAX_INFLIGHT_PER_TOKEN` optionally excludes accounts at the cap, while omission leaves Grok uncapped (`grok-quota.ts`, `grok-dispatcher.ts`, `packages/api/src/utils/providers/common/smooth-weighted-round-robin.ts`).
|
|
49
|
+
|
|
50
|
+
## Failure and failover rules
|
|
51
|
+
|
|
52
|
+
The dispatcher implements the plan §5.4 state machine (`grok-backend-protocol.ts`, `grok-direct-client.ts`, `grok-dispatcher.ts`, `grok-media-client.ts`):
|
|
53
|
+
|
|
54
|
+
| Condition | State and retry behavior |
|
|
55
|
+
| --- | --- |
|
|
56
|
+
| 429 with `Retry-After` | Set a request-class cooldown, capped at 120 seconds; fail over within the hop budget. If every candidate is cooling down, wait once for at most 30 seconds, then return a rate-limit error. |
|
|
57
|
+
| 429 exhaustion | Block the request class until the billing period ends, or one hour when the end is unavailable; invalidate billing and fail over. |
|
|
58
|
+
| 403 | Chat fails permanently without refresh or failover. Public API sets a one-hour entitlement block for that request class and may fail over once. |
|
|
59
|
+
| HTTP 426 | Trip the chat-only version gate. Media and voice remain available. |
|
|
60
|
+
| 401 | Refresh once and retry the same account; a second 401 marks it for re-authentication and may fail over. |
|
|
61
|
+
| `x-should-retry: false` | Return the error without retry or failover. |
|
|
62
|
+
| Chat 5xx/connect/idle failure | Fail over only before any event was forwarded and before upstream execution was observed. |
|
|
63
|
+
| Media/voice transport failure | Fail over only for a classified pre-send connection failure. Never replay a sent POST or a timeout that may have executed upstream. |
|
|
64
|
+
|
|
65
|
+
## Chat, tools, usage, and cost
|
|
66
|
+
|
|
67
|
+
Chat sends complete Responses-format history over HTTPS/SSE. It preserves image data/HTTPS inputs, strict structured output, prompt-cache affinity, reasoning effort, and the fixed include/store fields captured from grok-build. A stream succeeds only after `response.completed` (`grok-backend-protocol.ts`, `grok-direct-client.ts`, `grok-dispatcher.ts`, `docs/diagnosis/2026-10-16-grok-live-probe.md`).
|
|
68
|
+
|
|
69
|
+
D8 keeps qgrid's shared structured-output tool emulation: caller tools become the strict action envelope, the AI SDK executes returned tool calls, and a follow-up turn replays results. Do not replace this with Grok-native function execution without reopening the cross-provider contract (`packages/api/src/application/qgrid/qgrid.dispatcher.ts`, `tool-emulation.ts`, `tool-emulation-schema.ts`).
|
|
70
|
+
|
|
71
|
+
Provider `cost_in_usd_ticks` is authoritative, including zero; one tick is `1e-10` USD. If ticks are absent, qgrid uses catalog-seeded language/image prices and marks `costSource: "pricing_table"`; reported ticks use `costSource: "provider"` (`grok-dispatcher.ts`, `packages/api/src/utils/providers/common/model-cost.ts`, `docs/diagnosis/2026-10-16-grok-live-probe.md`).
|
|
72
|
+
|
|
73
|
+
## Media and voice
|
|
74
|
+
|
|
75
|
+
Qgrid exposes image generation/editing, asynchronous video start/status, transcription, and speech through `api.x.ai`. Reference images select `/images/edits`; video uses `/videos/generations` and `/videos/{request_id}`; voice uses multipart `/stt` and JSON `/tts` (`grok-media-client.ts`, `grok-voice-client.ts`, `packages/api/src/application/qgrid/qgrid.frame.ts`).
|
|
76
|
+
|
|
77
|
+
Inline audio, each inline image, and the aggregate inline images in one request are capped at 7 MiB decoded. The server maps Fastify's oversized-body error to HTTP 413 (`packages/api/src/application/qgrid/qgrid.types.ts`, `qgrid.frame.ts`).
|
|
78
|
+
|
|
79
|
+
Video starts return a random 128-bit in-memory job handle. Handles expire after 24 hours, polling stays pinned to the starting token, and `projectName` must match the owner supplied at start. D4 returns the upstream `api.x.ai` video URL unchanged; qgrid does not fetch, proxy, or store the bytes (`qgrid.frame.ts`, `grok-media-client.ts`, `packages/ai-sdk/README.md`).
|
|
80
|
+
|
|
81
|
+
**ZDR and video.** xAI refuses `POST /v1/videos/generations` for Zero Data Retention accounts with HTTP 400 `invalid_request`: "Zero Data Retention teams must provide output.upload_url for video generation." The dispatcher therefore keeps a per-token `zdr` state and excludes `zdr === true` tokens from video only; chat, image, STT, and TTS still route. The primary signal is `codingDataRetentionOptOut` on `GET /user?include=subscription`, re-read on the 60 s prefetch with settings; `x-zero-data-retention: true` on a chat-proxy response confirms it, but its absence never clears it. Unknown state, or a failed `/user` read with no prior value, routes (fail open). If a video start still gets the ZDR 400, the token is marked ZDR, video is entitlement-blocked for an hour, and the start fails over under the media rules. With no eligible video token the caller gets `GrokZdrVideoUnavailableError` (HTTP 503) naming the tokens; usage exposes `zdrVideoExcluded`. Both signals were inferred from one account (plan §11). grok-build's remedy, a user-owned S3 presigned `output.upload_url`, is not implemented (`grok-dispatcher.ts`, `grok-quota.ts`).
|
|
82
|
+
|
|
83
|
+
## Known gaps and residual risks
|
|
84
|
+
|
|
85
|
+
- **Verified 2026-10-16:** video generation succeeded through the SDK once the account's data-retention opt-out was off (8 s H.264 mp4 on vidgen.x.ai, $0.64; plan section 11). ZDR accounts are refused upstream and are excluded from the video class (see ZDR and video).
|
|
86
|
+
- Node/undici adds headers such as `accept-language` and `sec-fetch-mode` that the captured reqwest client did not send. Transport fingerprinting remains residual risk 10; D1/D2 do not authorize anti-detection work (`docs/plans/2026-10-16-grok-provider-integration-plan.md`, risk 10).
|
|
87
|
+
- **Unverified:** The capture pins chat header order. Media header order has not been verified through an installed-binary capture (`grok-headers.ts`, `docs/diagnosis/2026-10-16-grok-live-probe.md`).
|
|
88
|
+
- **Observed 2026-10-16, not represented in the catalog fixture:** `grok-composer` ids silently remapped to `grok-4.5-build`. Treat the returned serving model as authoritative; the captured catalog itself lists only the four documented model ids (`docs/diagnosis/2026-10-16-grok-live-probe.md`, `grok-models.ts`).
|
|
89
|
+
- `QGRID_GROK_LIVE_TOKEN_ID` is reserved by the plan for opt-in live tests and must stay unset in ordinary/CI runs; no current server runtime behavior depends on it (`docs/plans/2026-10-16-grok-provider-integration-plan.md`, §7).
|
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
# Provider Runtime Differences
|
|
2
2
|
|
|
3
|
-
Use this reference when comparing OpenAI and
|
|
4
|
-
|
|
5
|
-
| Topic | OpenAI via Codex | Anthropic via Claude Code |
|
|
6
|
-
|
|
7
|
-
| Process lifetime | No child process; direct HTTPS/SSE request | Fresh `claude` process per request |
|
|
8
|
-
| Worker pool | None; in-memory token pool only | None; in-memory token pool only |
|
|
9
|
-
| Worker id | Legacy coordinate field carries token id | `tokenId` |
|
|
10
|
-
| Epoch | Legacy compatibility value; not a process generation | Always `0` |
|
|
11
|
-
| Request concurrency | Uncapped; stateless
|
|
12
|
-
| Token selection | Smooth weighted RR over quota-eligible tokens; valid affinity may prefer its token | Smooth weighted RR over quota-eligible tokens per request |
|
|
13
|
-
| Model routing | `openai/*`; qgrid strips provider prefix before provider call | `anthropic/*`; provider canonicalizes model and strips prefix/`[1m]` |
|
|
14
|
-
| Prefix-less models | Fallback not implemented | Fallback not implemented |
|
|
15
|
-
| Effort vocabulary | Codex catalog levels `low`..`ultra`
|
|
16
|
-
| Unsupported effort | Server drops it
|
|
17
|
-
| Thread/session | No provider thread retained | Fresh Claude `--session-id` per request |
|
|
18
|
-
| `sessionKey` | AI SDK derives and replays opaque `prompt_cache_key` affinity | AI SDK intentionally disables storage/replay |
|
|
19
|
-
| Multi-turn | Full Responses-format history is sent on every request | Fresh spawn receives flattened full history through stream-json |
|
|
20
|
-
| Cache key | Opaque model-scoped affinity key plus stable serialized prefix | Anthropic prefix cache via Claude Code
|
|
21
|
-
| Built-in tools | Direct
|
|
22
|
-
| AI SDK tools | Emulated via qgrid structured output schema
|
|
23
|
-
| Structured output | Strict JSON schema is sent in the direct Responses request
|
|
24
|
-
| Usage accounting |
|
|
25
|
-
| Cost source | qgrid model price fallback | Prefer Claude Code `total_cost_usd`, else qgrid
|
|
26
|
-
| Settings isolation | Per-token credentials in memory | Shared project cwd plus per-token `CLAUDE_CONFIG_DIR` |
|
|
27
|
-
| Streaming close | `AbortSignal` cancels
|
|
28
|
-
|
|
|
3
|
+
Use this reference when comparing OpenAI, Anthropic, and Grok behavior, debugging provider-specific bugs, or reviewing cross-provider changes. Sources: `packages/api/src/utils/providers/{openai,anthropic,grok}/*`, `packages/api/src/application/qgrid/qgrid.dispatcher.ts`, and `references/grok-runtime.md`.
|
|
4
|
+
|
|
5
|
+
| Topic | OpenAI via Codex | Anthropic via Claude Code | Grok via grok-build fingerprint |
|
|
6
|
+
|---|---|---|---|
|
|
7
|
+
| Process lifetime | No child process; direct HTTPS/SSE or WebSocket request | Fresh `claude` process per request | No child process; direct HTTPS/SSE request |
|
|
8
|
+
| Worker pool | None; in-memory token pool only | None; in-memory token pool only | None; in-memory token/account pool only |
|
|
9
|
+
| Worker id | Legacy coordinate field carries token id | `tokenId` | Legacy coordinate field carries token id |
|
|
10
|
+
| Epoch | Legacy compatibility value; not a process generation | Always `0` | `-1`; not a process generation |
|
|
11
|
+
| Request concurrency | Uncapped; stateless request per call | Uncapped; fresh process per request | Uncapped by default; optional `QGRID_GROK_MAX_INFLIGHT_PER_TOKEN` excludes accounts at the cap |
|
|
12
|
+
| Token selection | Smooth weighted RR over quota-eligible tokens; valid affinity may prefer its token | Smooth weighted RR over quota-eligible tokens per request | Smooth weighted RR after quota, on-demand, cooldown, entitlement, and capacity gates; valid affinity may prefer its token |
|
|
13
|
+
| Model routing | `openai/*`; qgrid strips provider prefix before provider call | `anthropic/*`; provider canonicalizes model and strips prefix/`[1m]` | `grok/*`; qgrid strips the provider prefix and validates against the seeded/live catalog |
|
|
14
|
+
| Prefix-less models | Fallback not implemented | Fallback not implemented | Fallback not implemented |
|
|
15
|
+
| Effort vocabulary | Codex catalog levels `low`..`ultra` | Claude Code `--effort` levels `low`..`max` | Catalog levels `low`, `medium`, `high`, `xhigh`; thinking-off is unverified and rejected |
|
|
16
|
+
| Unsupported effort | Server drops it before the request; backend default applies | Server drops it; qgrid default `low` applies | Server drops it; catalog default applies |
|
|
17
|
+
| Thread/session | No provider thread retained | Fresh Claude `--session-id` per request | No provider thread retained; stable account session/agent ids are fingerprint headers |
|
|
18
|
+
| `sessionKey` | AI SDK derives and replays opaque `prompt_cache_key` affinity | AI SDK intentionally disables storage/replay | AI SDK derives and replays account-affine `prompt_cache_key` coordinates |
|
|
19
|
+
| Multi-turn | Full Responses-format history is sent on every request | Fresh spawn receives flattened full history through stream-json | Full Responses-format history is sent on every request |
|
|
20
|
+
| Cache key | Opaque model-scoped affinity key plus stable serialized prefix | Anthropic prefix cache via Claude Code | Opaque model-scoped affinity key, also used to derive Grok conversation ids |
|
|
21
|
+
| Built-in tools | Direct request includes only requested qgrid tools/options | Claude tools disabled via `--tools ""` | Captured proxy supports `web_search`/`x_search`, but qgrid's public tool path remains the shared emulation contract |
|
|
22
|
+
| AI SDK tools | Emulated via qgrid structured output schema | Emulated via prompt envelope; not native Claude Code tools | Emulated via the strict qgrid action envelope (D8), not provider-executed function tools |
|
|
23
|
+
| Structured output | Strict JSON schema is sent in the direct Responses request | Schema is prompt text; consumer validation owns correctness | Strict JSON schema is sent in the direct Responses request |
|
|
24
|
+
| Usage accounting | Input includes cached input | Native categories are summed into total input | Responses reports cached/reasoning/context tokens and `cost_in_usd_ticks` |
|
|
25
|
+
| Cost source | qgrid model price fallback | Prefer Claude Code `total_cost_usd`, else qgrid fallback | Provider ticks are authoritative; catalog-seeded fallback when ticks are absent |
|
|
26
|
+
| Settings isolation | Per-token credentials in memory | Shared project cwd plus per-token `CLAUDE_CONFIG_DIR` | Per-token OAuth credentials and stable ids in memory |
|
|
27
|
+
| Streaming close | `AbortSignal` cancels selection or active transport | Abort kills the fresh child process | `AbortSignal` cancels selection or active SSE; success requires `response.completed` |
|
|
28
|
+
| Media/voice | OpenAI image routes only | Explicitly unsupported | Image generation/editing, async video URL jobs, STT, and TTS on `api.x.ai` |
|
|
29
29
|
|
|
30
30
|
## Routing contract
|
|
31
31
|
|
|
@@ -33,13 +33,14 @@ Provider routing happens in `packages/api/src/application/qgrid/qgrid.dispatcher
|
|
|
33
33
|
|
|
34
34
|
- `openai/<model>` routes to `OpenAIDispatcher`.
|
|
35
35
|
- `anthropic/<model>` routes to `AnthropicDispatcher`.
|
|
36
|
+
- `grok/<model>` routes to `GrokDispatcher`.
|
|
36
37
|
- models without provider prefix produce "Direct LLM API fallback not implemented".
|
|
37
38
|
|
|
38
39
|
Do not silently route prefix-less Claude model names such as `claude-sonnet-4-6` to Anthropic. Tests intentionally guard against this.
|
|
39
40
|
|
|
40
41
|
## Shared contracts
|
|
41
42
|
|
|
42
|
-
|
|
43
|
+
All three providers return `GenerateResult` with:
|
|
43
44
|
|
|
44
45
|
- `text`
|
|
45
46
|
- `tokenName`
|
|
@@ -52,6 +53,6 @@ Both providers return `GenerateResult` with:
|
|
|
52
53
|
|
|
53
54
|
`qgrid.dispatcher.ts` maps this into `QueryOutput`, applies tool-call emulation, calculates fallback cost, and keeps the legacy `QgridThreadCoord` response shape for opaque OpenAI cache affinity.
|
|
54
55
|
|
|
55
|
-
|
|
56
|
+
OpenAI and Grok receive strictified output schemas from `buildStrictOutputSchema`; Anthropic receives the original schema as prompt text.
|
|
56
57
|
|
|
57
|
-
Tool calling uses
|
|
58
|
+
Tool calling uses qgrid's shared action-envelope path. It is not native provider tool execution on any public route (`packages/api/src/application/qgrid/qgrid.dispatcher.ts`, `tool-emulation.ts`).
|
|
@@ -25,6 +25,7 @@ Use this map to orient qgrid work quickly.
|
|
|
25
25
|
- Token trigger setup: `packages/api/src/application/qgrid/token-trigger-setup.ts`.
|
|
26
26
|
- OpenAI direct backend transport, OAuth, quota, and dispatcher: `packages/api/src/utils/providers/openai/*`.
|
|
27
27
|
- Anthropic Claude Code runtime: `packages/api/src/utils/providers/anthropic/*`.
|
|
28
|
+
- Grok chat fingerprint/transport, OAuth/refresh, quota/models, dispatcher, media, and voice: `packages/api/src/utils/providers/grok/{grok-constants.ts,grok-headers.ts,grok-backend-protocol.ts,grok-direct-client.ts,grok-oauth.ts,grok-refresh.ts,grok-quota.ts,grok-models.ts,grok-dispatcher.ts,grok-media-client.ts,grok-voice-client.ts,grok-types.ts}`. See `packages/cli/skills/qgrid/references/grok-runtime.md`.
|
|
28
29
|
- Cost/usage accounting: `packages/api/src/utils/providers/common/model-cost.ts`.
|
|
29
30
|
- Weighted token selection: `packages/api/src/utils/providers/common/smooth-weighted-round-robin.ts`.
|
|
30
31
|
- Boot order and startup migrations: `packages/api/src/server-bootstrap.ts`, `packages/api/src/startup-migrations.ts`.
|
|
@@ -38,3 +39,12 @@ Use this map to orient qgrid work quickly.
|
|
|
38
39
|
- Generated API files: `packages/api/src/application/sonamu.generated*`, `packages/web/src/services` when present, generated route/client files.
|
|
39
40
|
- Dashboard components: `packages/web/src/components/qgrid/*`.
|
|
40
41
|
- Dashboard routes: `packages/web/src/routes/*`.
|
|
42
|
+
|
|
43
|
+
## Grok SDK and API surfaces
|
|
44
|
+
|
|
45
|
+
- Public AI SDK language/options integration: `packages/ai-sdk/src/index.ts`, `index.types.ts`, `grok-options.ts`.
|
|
46
|
+
- Grok image/video/transcription/speech adapters: `packages/ai-sdk/src/image-model.ts`, `video-model.ts`, `transcription-model.ts`, `speech-model.ts`.
|
|
47
|
+
- Grok OAuth, media, voice, limits, and video job handles: `packages/api/src/application/qgrid/qgrid.frame.ts`, `qgrid.types.ts`.
|
|
48
|
+
- Grok dispatcher construction and lifecycle: `packages/api/src/sonamu.config.ts`.
|
|
49
|
+
|
|
50
|
+
These paths are documented by `packages/ai-sdk/README.md` and `packages/cli/skills/qgrid/references/grok-runtime.md`.
|
|
@@ -9,6 +9,7 @@ Use this reference before changing token storage, OAuth flows, token activation,
|
|
|
9
9
|
- Token APIs
|
|
10
10
|
- Anthropic OAuth flow
|
|
11
11
|
- OpenAI OAuth and refresh flow
|
|
12
|
+
- Grok OAuth, refresh, and quota flow
|
|
12
13
|
- Token sync and reconcile
|
|
13
14
|
- Provider runtime consequences
|
|
14
15
|
- Quota threshold semantics
|
|
@@ -24,7 +25,8 @@ Use this reference before changing token storage, OAuth flows, token activation,
|
|
|
24
25
|
- Token subscriber: `packages/api/src/application/qgrid/token-subscriber.ts`.
|
|
25
26
|
- OpenAI direct OAuth/refresh/quota: `packages/api/src/utils/providers/openai/openai-oauth.ts`, `openai-refresh.ts`, `openai-quota.ts`.
|
|
26
27
|
- Anthropic quota: `packages/api/src/utils/providers/anthropic/anthropic-quota.ts`.
|
|
27
|
-
-
|
|
28
|
+
- Grok OAuth/refresh/quota: `packages/api/src/utils/providers/grok/grok-oauth.ts`, `grok-refresh.ts`, `grok-quota.ts`.
|
|
29
|
+
- Provider token event handlers: `openai-dispatcher.ts`, `anthropic-dispatcher.ts`, `grok-dispatcher.ts`.
|
|
28
30
|
|
|
29
31
|
## Token Table Contract
|
|
30
32
|
|
|
@@ -71,10 +73,29 @@ Anthropic credentials:
|
|
|
71
73
|
}
|
|
72
74
|
```
|
|
73
75
|
|
|
74
|
-
|
|
76
|
+
Grok credentials (`packages/api/src/utils/providers/grok/grok-types.ts`):
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
{
|
|
80
|
+
authMode: "oauth";
|
|
81
|
+
accessToken: string;
|
|
82
|
+
refreshToken: string;
|
|
83
|
+
expiresAt: string;
|
|
84
|
+
issuer: "https://auth.x.ai";
|
|
85
|
+
clientId: string;
|
|
86
|
+
scopes: string[];
|
|
87
|
+
userId: string;
|
|
88
|
+
sessionId: string;
|
|
89
|
+
agentId: string;
|
|
90
|
+
subscriptionTier?: string;
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Duplicate account replacement is account-identifier based (`packages/api/src/application/token/token.model.ts`):
|
|
75
95
|
|
|
76
96
|
- OpenAI: `credentials.accountId`.
|
|
77
97
|
- Anthropic: `credentials.accountUuid`.
|
|
98
|
+
- Grok: `credentials.userId`.
|
|
78
99
|
|
|
79
100
|
## Token APIs
|
|
80
101
|
|
|
@@ -152,6 +173,26 @@ Usage/quota:
|
|
|
152
173
|
- Threshold uses primary `usedPercent`.
|
|
153
174
|
- Usage lookup failure is fail-open for routing.
|
|
154
175
|
|
|
176
|
+
## Grok OAuth, Refresh, And Quota Flow
|
|
177
|
+
|
|
178
|
+
Grok supports two OAuth entry paths (`grok-oauth.ts`, `packages/api/src/application/qgrid/qgrid.frame.ts`):
|
|
179
|
+
|
|
180
|
+
1. Browser PKCE uses xAI OIDC discovery, a random `127.0.0.1` callback, the grok-build client id/scopes/referrer, and code-paste completion from either a full callback URL or bare code.
|
|
181
|
+
2. Device code starts at `auth.x.ai/oauth2/device/code` and polls the token endpoint at the returned interval; `slow_down` adds five seconds.
|
|
182
|
+
|
|
183
|
+
The resulting access token must be an `at+jwt` issued by `auth.x.ai`. Qgrid confirms identity through `/user?include=subscription` and stores `userId` as the account identity key (`grok-oauth.ts`, `grok-types.ts`, `token.model.ts`).
|
|
184
|
+
|
|
185
|
+
Refresh starts 300 seconds plus stable 0–60 second jitter before expiry, is single-flight per token, keeps the previous refresh token when xAI does not rotate it, and persists rotated credentials before exposing them. `invalid_grant` and `invalid_client` require re-login; other failures remain transient. A generation 401 permits one forced refresh and same-token retry (`grok-refresh.ts`, `grok-dispatcher.ts`).
|
|
186
|
+
|
|
187
|
+
Quota and spending controls use two proxy reads (`grok-quota.ts`, `grok-dispatcher.ts`):
|
|
188
|
+
|
|
189
|
+
| Read | Routing fields | Cache/failure policy |
|
|
190
|
+
|---|---|---|
|
|
191
|
+
| `/billing?format=credits` | camelCase `config.creditUsagePercent`, weekly `currentPeriod`, prepaid balance | 60-second cache; lookup failure fails open |
|
|
192
|
+
| `/settings` | `on_demand_enabled`, minimum client version, feature/tier flags | 60-second cache; `true` excludes the account under D6; lookup failure fails open |
|
|
193
|
+
|
|
194
|
+
The observed weekly billing window begins at subscription start, not a calendar boundary (`docs/diagnosis/2026-10-16-grok-live-probe.md`). Quota exhaustion blocks only the affected request class until period end (one-hour fallback); a fresh below-threshold billing read clears blocks (`grok-dispatcher.ts`).
|
|
195
|
+
|
|
155
196
|
## Token Sync And Reconcile
|
|
156
197
|
|
|
157
198
|
On server start, qgrid creates PostgreSQL triggers for `tokens_changed`.
|
|
@@ -176,7 +217,8 @@ On DELETE or missing row:
|
|
|
176
217
|
|
|
177
218
|
- remove from `QgridDispatcher.tokens`;
|
|
178
219
|
- call OpenAI `onTokenRemoved`;
|
|
179
|
-
- call Anthropic `onTokenRemoved
|
|
220
|
+
- call Anthropic `onTokenRemoved`;
|
|
221
|
+
- call Grok `onTokenRemoved`.
|
|
180
222
|
|
|
181
223
|
OpenAI row changes:
|
|
182
224
|
|
|
@@ -192,6 +234,12 @@ Anthropic row changes:
|
|
|
192
234
|
- inactive row: remove from pool.
|
|
193
235
|
- reconcile uses active Anthropic rows to replace the in-memory pool.
|
|
194
236
|
|
|
237
|
+
Grok row changes (`packages/api/src/application/qgrid/token-subscriber.ts`, `grok-dispatcher.ts`):
|
|
238
|
+
|
|
239
|
+
- active INSERT/UPDATE: validate credentials and upsert account metadata plus selector weight.
|
|
240
|
+
- inactive or deleted row: remove it from the in-memory pool and weighted selector.
|
|
241
|
+
- reconcile uses active Grok rows to replace the in-memory pool.
|
|
242
|
+
|
|
195
243
|
## Provider Runtime Consequences
|
|
196
244
|
|
|
197
245
|
OpenAI token changes create, update, deactivate, or remove in-memory credential metadata.
|
|
@@ -202,6 +250,8 @@ OpenAI token changes create, update, deactivate, or remove in-memory credential
|
|
|
202
250
|
|
|
203
251
|
Anthropic token changes only affect the in-memory token pool because every request fresh-spawns Claude Code.
|
|
204
252
|
|
|
253
|
+
Grok token changes update the in-memory OAuth credentials, quota/settings cache generation, and weighted selector. Grok has no child process; media and chat reserve the selected account for the request (`grok-dispatcher.ts`).
|
|
254
|
+
|
|
205
255
|
## Auth-Dead Detection And Token Registration
|
|
206
256
|
|
|
207
257
|
When a refresh fails in a way that only re-login can fix, qgrid removes the token from routing instead of letting every subsequent request 401.
|
|
@@ -232,6 +282,9 @@ When a refresh fails in a way that only re-login can fix, qgrid removes the toke
|
|
|
232
282
|
`recovered` once a later quota check falls below the threshold. Metadata generations prevent an
|
|
233
283
|
in-flight lookup from restoring a block after a threshold or lifecycle change. The state is not
|
|
234
284
|
persisted across server restarts.
|
|
285
|
+
- Grok also keeps threshold and exhaustion blocks in memory. Its exhaustion block is request-class
|
|
286
|
+
scoped, and `/settings.on_demand_enabled = true` independently excludes the entire account
|
|
287
|
+
(`packages/api/src/utils/providers/grok/grok-dispatcher.ts`).
|
|
235
288
|
- If all ready/eligible tokens are over threshold, qgrid throws `QuotaThresholdExceededError`.
|
|
236
289
|
- Log messages use `quota_threshold gate` with reasons such as `over_threshold`, `lookup_fail_open`, and `all_exceeded`.
|
|
237
290
|
|