Merge pull request #3751 from heathermhuang/codex/grok-image-pricing-latest

fix: expose Grok image pricing controls
This commit is contained in:
Wesley Liddick
2026-07-07 08:29:01 +08:00
committed by GitHub
5 changed files with 76 additions and 10 deletions
+1
View File
@@ -483,6 +483,7 @@ func grokMediaUsageFromResponse(endpoint GrokMediaEndpoint, requestInfo GrokMedi
meta.ImageOutputSizes = collectOpenAIResponseImageOutputSizesFromJSONBytes(responseBody)
case GrokMediaEndpointVideosGenerations:
meta.ResponseID = extractGrokMediaVideoRequestID(responseBody)
// Video generation is one billable media unit; the legacy usage schema stores it in ImageCount.
meta.ImageCount = 1
meta.ImageSize = requestInfo.SizeTier
meta.ImageInputSize = requestInfo.Size
@@ -1803,6 +1803,52 @@ func TestOpenAIGatewayServiceRecordUsage_ImageIndependentMultiplierUsesImageRate
require.Equal(t, string(BillingModeImage), *usageRepo.lastLog.BillingMode)
}
func TestGrokVideoMediaBillingUsesImageRateMultiplier(t *testing.T) {
mediaPrice2K := 0.4
groupID := int64(126)
usageRepo := &openAIRecordUsageLogRepoStub{inserted: true}
svc := newOpenAIRecordUsageServiceForTest(usageRepo, &openAIRecordUsageUserRepoStub{}, &openAIRecordUsageSubRepoStub{}, nil)
err := svc.RecordUsage(context.Background(), &OpenAIRecordUsageInput{
Result: &OpenAIForwardResult{
RequestID: "video-request-123",
ResponseID: "video-request-123",
Model: "grok-imagine-video-1.5",
BillingModel: "grok-imagine-video-1.5",
// The usage schema has no separate video count; video generation is billed as one media unit.
ImageCount: 1,
ImageSize: ImageBillingSize2K,
Duration: time.Second,
},
APIKey: &APIKey{
ID: 10126,
GroupID: i64p(groupID),
Group: &Group{
ID: groupID,
Platform: PlatformGrok,
RateMultiplier: 0.15,
ImageRateIndependent: true,
ImageRateMultiplier: 0.5,
ImagePrice2K: &mediaPrice2K,
},
},
User: &User{ID: 20126},
Account: &Account{ID: 30126, Platform: PlatformGrok},
})
require.NoError(t, err)
require.NotNil(t, usageRepo.lastLog)
require.Equal(t, "grok-imagine-video-1.5", usageRepo.lastLog.Model)
require.Equal(t, 1, usageRepo.lastLog.ImageCount)
require.Equal(t, ImageBillingSize2K, *usageRepo.lastLog.ImageSize)
require.InDelta(t, 0.4, usageRepo.lastLog.TotalCost, 1e-12)
require.InDelta(t, 0.2, usageRepo.lastLog.ActualCost, 1e-12)
require.InDelta(t, 0.5, usageRepo.lastLog.RateMultiplier, 1e-12)
require.NotNil(t, usageRepo.lastLog.BillingMode)
require.Equal(t, string(BillingModeImage), *usageRepo.lastLog.BillingMode)
}
func TestOpenAIGatewayServiceRecordUsage_ChannelImageBillingUsesImageCountAndSharedMultiplier(t *testing.T) {
groupID := int64(123)
usageRepo := &openAIRecordUsageLogRepoStub{inserted: true}
+3 -10
View File
@@ -789,11 +789,7 @@
<!-- 图片生成计费配置 -->
<div
v-if="
createForm.platform === 'antigravity' ||
createForm.platform === 'gemini' ||
createForm.platform === 'openai'
"
v-if="supportsImagePricingPlatform(createForm.platform)"
class="border-t pt-4"
>
<label
@@ -2128,11 +2124,7 @@
<!-- 图片生成计费配置 -->
<div
v-if="
editForm.platform === 'antigravity' ||
editForm.platform === 'gemini' ||
editForm.platform === 'openai'
"
v-if="supportsImagePricingPlatform(editForm.platform)"
class="border-t pt-4"
>
<label
@@ -3216,6 +3208,7 @@ import {
} from "./groupsModelsList";
import { createModelsListCandidatesTracker } from "./groupsModelsListCandidates";
import { normalizeSupportedModelScopesForPlatform } from "./groupsSupportedModelScopes";
import { supportsImagePricingPlatform } from "./groupsImagePricing";
const { t } = useI18n();
const appStore = useAppStore();
@@ -0,0 +1,17 @@
import { describe, expect, it } from "vitest";
import {
imagePricingPlatforms,
supportsImagePricingPlatform,
} from "../groupsImagePricing";
describe("groups image pricing platform support", () => {
it("includes Grok media groups", () => {
expect(supportsImagePricingPlatform("grok")).toBe(true);
expect(imagePricingPlatforms.has("grok")).toBe(true);
});
it("keeps non-media group platforms out of the image pricing controls", () => {
expect(supportsImagePricingPlatform("anthropic")).toBe(false);
});
});
@@ -0,0 +1,9 @@
export const imagePricingPlatforms = new Set([
"antigravity",
"gemini",
"grok",
"openai",
]);
export const supportsImagePricingPlatform = (platform: string): boolean =>
imagePricingPlatforms.has(platform);