Merge pull request #5742 from heathermhuang/codex/fix-grok-response-model-audit
fix: normalize Grok response model audit aliases
This commit is contained in:
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user