Merge pull request #5742 from heathermhuang/codex/fix-grok-response-model-audit

fix: normalize Grok response model audit aliases
This commit is contained in:
Wesley Liddick
2026-08-18 10:03:26 +08:00
committed by GitHub
2 changed files with 95 additions and 1 deletions
@@ -167,10 +167,33 @@ func upstreamModelMismatch(sentModel, responseModel string) *bool {
return nil
}
sentModel = strings.TrimSpace(sentModel)
mismatch := sentModel == "" || !strings.EqualFold(sentModel, responseModel)
mismatch := sentModel == "" || !upstreamModelsMatchForAudit(sentModel, responseModel)
return &mismatch
}
func upstreamModelsMatchForAudit(sentModel, responseModel string) bool {
if strings.EqualFold(sentModel, responseModel) {
return true
}
// xAI reports the runtime build ID for these supported public aliases.
// Canonicalize only for mismatch auditing; keep the raw response model for
// observability and for the separate response-model billing safeguards.
sentGrokModel := canonicalGrokBuildRuntimeModel(sentModel)
return sentGrokModel != "" && sentGrokModel == canonicalGrokBuildRuntimeModel(responseModel)
}
func canonicalGrokBuildRuntimeModel(model string) string {
switch strings.ToLower(strings.TrimSpace(model)) {
case "grok-4.5", "grok-4.5-latest", "grok-4.5-build":
return "grok-4.5-build"
case "grok-4.6", "grok-4.6-latest", "grok-4.6-build":
return "grok-4.6-build"
default:
return ""
}
}
func upstreamSentModel(requestedModel, upstreamModel string) string {
sentModel := strings.TrimSpace(upstreamModel)
if sentModel == "" {
@@ -59,6 +59,77 @@ func TestUpstreamModelMismatchThreeStateAndCaseInsensitiveComparison(t *testing.
require.True(t, *mismatched)
}
func TestUpstreamModelMismatchTreatsGrokBuildRuntimeIDsAsAliases(t *testing.T) {
tests := []struct {
name string
sentModel string
responseModel string
}{
{
name: "issue 5634 grok 4.6",
sentModel: "grok-4.6",
responseModel: "grok-4.6-build",
},
{
name: "grok 4.6 latest",
sentModel: "grok-4.6-latest",
responseModel: "grok-4.6-build",
},
{
name: "issue 5647 grok 4.5 latest",
sentModel: "grok-4.5-latest",
responseModel: "grok-4.5-build",
},
{
name: "grok 4.5 canonical",
sentModel: "grok-4.5",
responseModel: "GROK-4.5-BUILD",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mismatch := upstreamModelMismatch(tt.sentModel, tt.responseModel)
require.NotNil(t, mismatch)
require.False(t, *mismatch)
})
}
}
func TestUpstreamModelMismatchDoesNotCollapseDifferentModels(t *testing.T) {
tests := []struct {
name string
sentModel string
responseModel string
}{
{
name: "different grok versions",
sentModel: "grok-4.5",
responseModel: "grok-4.6-build",
},
{
name: "unrelated build suffix",
sentModel: "gpt-5.5",
responseModel: "gpt-5.5-build",
},
{
name: "different grok runtime",
sentModel: "grok-build-0.1",
responseModel: "grok-4.5-build",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mismatch := upstreamModelMismatch(tt.sentModel, tt.responseModel)
require.NotNil(t, mismatch)
require.True(t, *mismatch)
})
}
}
func TestObserveOpenAISSEBodyIgnoresMalformedPayload(t *testing.T) {
observer := &upstreamResponseModelObserver{}
observeOpenAISSEBody(observer, "data: not-json\n\ndata: {\"type\":\"response.completed\",\"response\":{\"model\":\"gpt-5.4\"}}\n\n")