Repository navigation
fix(anthropic): deterministic tool schema serialization for prompt caching #2082
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -116,7 +116,7 @@ func getRequestBodyForResponses(ctx *schemas.BifrostContext, request *schemas.Bi | |
| delete(requestBody, field) | ||
| } | ||
| } | ||
| jsonBody, err = sonic.Marshal(requestBody) | ||
| jsonBody, err = providerUtils.MarshalSorted(requestBody) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apply deterministic re-marshal in the exclude-fields branch too. Line 119 fixes raw-body determinism, but Line 174 still re-marshals a Suggested patch@@
- // Re-marshal the map
- jsonBody, err = sonic.Marshal(jsonMap)
+ // Re-marshal deterministically to preserve stable cache keys
+ jsonBody, err = providerUtils.MarshalSorted(jsonMap)
if err != nil {
return nil, providerUtils.NewBifrostOperationError(schemas.ErrProviderRequestMarshal, err, providerName)
}🤖 Prompt for AI Agents |
||
| if err != nil { | ||
| return nil, providerUtils.NewBifrostOperationError(schemas.ErrProviderRequestMarshal, err, providerName) | ||
| } | ||
|
|
@@ -160,21 +160,13 @@ func getRequestBodyForResponses(ctx *schemas.BifrostContext, request *schemas.Bi | |
| return nil, providerUtils.NewBifrostOperationError(schemas.ErrProviderRequestMarshal, err, providerName) | ||
| } | ||
| } | ||
| } else { | ||
| // Remove excluded fields | ||
| if len(excludeFields) > 0 { | ||
| var jsonMap map[string]interface{} | ||
| if err := sonic.Unmarshal(jsonBody, &jsonMap); err != nil { | ||
| return nil, providerUtils.NewBifrostOperationError(schemas.ErrProviderRequestMarshal, err, providerName) | ||
| } | ||
| for _, field := range excludeFields { | ||
| delete(jsonMap, field) | ||
| } | ||
| // Re-marshal the map | ||
| jsonBody, err = sonic.Marshal(jsonMap) | ||
| if err != nil { | ||
| return nil, providerUtils.NewBifrostOperationError(schemas.ErrProviderRequestMarshal, err, providerName) | ||
| } | ||
| } else if len(excludeFields) > 0 { | ||
| // Remove top-level keys while preserving nested JSON byte ordering | ||
| // (avoids roundtrip through map[string]interface{} which loses key order | ||
| // in nested objects like tool input_schema). | ||
| jsonBody, err = excludeTopLevelJSONKeys(jsonBody, excludeFields) | ||
| if err != nil { | ||
| return nil, providerUtils.NewBifrostOperationError(schemas.ErrProviderRequestMarshal, err, providerName) | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -1646,3 +1638,18 @@ func IsClaudeCodeRequest(ctx *schemas.BifrostContext) bool { | |
| } | ||
| return false | ||
| } | ||
|
|
||
| // excludeTopLevelJSONKeys removes the specified top-level keys from a JSON | ||
| // object without parsing nested values. Nested bytes are preserved as-is, | ||
| // which keeps the original key ordering within tool schemas and other | ||
| // deeply nested structures. | ||
| func excludeTopLevelJSONKeys(data []byte, keys []string) ([]byte, error) { | ||
| var raw map[string]json.RawMessage | ||
| if err := sonic.Unmarshal(data, &raw); err != nil { | ||
| return nil, fmt.Errorf("anthropic: unmarshalling for field exclusion: %w", err) | ||
| } | ||
| for _, k := range keys { | ||
| delete(raw, k) | ||
| } | ||
| return sonic.Marshal(raw) | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -409,6 +409,59 @@ func (t *ToolFunctionParameters) UnmarshalJSON(data []byte) error { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Normalized returns a shallow copy of the ToolFunctionParameters with all | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // OrderedMap keys sorted using JSON Schema priority ordering (type, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // description, properties, required first, then alphabetically). The copy | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // shares primitive values with the original but has independent key slices, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // so sorting does not mutate the caller's data. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // The captured keyOrder is cleared so the struct field declaration order is | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // used for the top-level keys. This produces deterministic JSON serialization | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // regardless of the client's original key ordering, which is critical for | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Anthropic's prefix-based prompt caching. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (t *ToolFunctionParameters) Normalized() *ToolFunctionParameters { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if t == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| out := *t | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| out.keyOrder = JSONKeyOrder{} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| out.Properties = t.Properties.SortedCopy() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| out.Defs = t.Defs.SortedCopy() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| out.Definitions = t.Definitions.SortedCopy() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| out.Items = t.Items.SortedCopy() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if len(t.AnyOf) > 0 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| out.AnyOf = make([]OrderedMap, len(t.AnyOf)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for i := range t.AnyOf { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if cp := t.AnyOf[i].SortedCopy(); cp != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| out.AnyOf[i] = *cp | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if len(t.OneOf) > 0 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| out.OneOf = make([]OrderedMap, len(t.OneOf)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for i := range t.OneOf { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if cp := t.OneOf[i].SortedCopy(); cp != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| out.OneOf[i] = *cp | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if len(t.AllOf) > 0 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| out.AllOf = make([]OrderedMap, len(t.AllOf)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for i := range t.AllOf { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if cp := t.AllOf[i].SortedCopy(); cp != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| out.AllOf[i] = *cp | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if t.AdditionalProperties != nil && t.AdditionalProperties.AdditionalPropertiesMap != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| out.AdditionalProperties = &AdditionalPropertiesStruct{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AdditionalPropertiesBool: t.AdditionalProperties.AdditionalPropertiesBool, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AdditionalPropertiesMap: t.AdditionalProperties.AdditionalPropertiesMap.SortedCopy(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return &out | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+422
to
+463
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Verify `Normalized()` does not currently normalize `Default`.
rg -n 'type ToolFunctionParameters struct|Default interface|func \(t \*ToolFunctionParameters\) Normalized|out\.Default' core/schemas/chatcompletions.go -A80 -B20Repository: maximhq/bifrost Length of output: 9719 🏁 Script executed: #!/bin/bash
# Find where Normalized() is called
rg -n '\.Normalized\(\)' core/ --type goRepository: maximhq/bifrost Length of output: 279 🏁 Script executed: #!/bin/bash
# Check if there are any examples or tests that use Default with map/array values
rg -n 'Default.*:=' core/schemas/ -A2 -B2 --type go | head -50Repository: maximhq/bifrost Length of output: 302 🏁 Script executed: #!/bin/bash
# Look at OrderedMap and understand how SortedCopy works
rg -n 'func.*SortedCopy|type OrderedMap' core/schemas/ --type go -A5 | head -80Repository: maximhq/bifrost Length of output: 1155 🏁 Script executed: #!/bin/bash
# Look at the full SortedCopy implementation
rg -n 'func.*SortedCopy' core/schemas/orderedmap.go -A30Repository: maximhq/bifrost Length of output: 912 🏁 Script executed: #!/bin/bash
# Check if Default field is ever populated with maps in tests or examples
rg -n '"default"' core/schemas/chatcompletions.go -B2 -A2Repository: maximhq/bifrost Length of output: 211 🏁 Script executed: #!/bin/bash
# Look at how OrderedMapFromMap works
rg -n 'func OrderedMapFromMap' core/schemas/ --type go -A20Repository: maximhq/bifrost Length of output: 1181 🏁 Script executed: #!/bin/bash
# Check the Anthropic provider usage to understand the context
rg -n 'InputSchema.*Normalized' core/providers/anthropic/ -B5 -A5 --type goRepository: maximhq/bifrost Length of output: 1699 🏁 Script executed: #!/bin/bash
# Get the complete SortedCopy implementation
sed -n '376,430p' core/schemas/orderedmap.goRepository: maximhq/bifrost Length of output: 1358 🏁 Script executed: #!/bin/bash
# Look for actual usage of Default field with structured values in tests
rg -n 'Default.*map\[|Default.*\[\]|Default.*{' core/ --type go | head -20Repository: maximhq/bifrost Length of output: 200 🏁 Script executed: #!/bin/bash
# Check JSON Schema specs - Default field can be any JSON value
# Let's see if there are any existing helpers for normalizing arbitrary values
rg -n 'func normalize' core/schemas/ --type goRepository: maximhq/bifrost Length of output: 405 🏁 Script executed: #!/bin/bash
# Check the normalizeForSortedMarshal function - it may already handle this
rg -n 'func normalizeForSortedMarshal' core/schemas/ -A20 --type goRepository: maximhq/bifrost Length of output: 2385 🏁 Script executed: #!/bin/bash
# Look for actual test cases that use Default with complex values
rg -n '"default"' core/schemas/chatcompletions_test.go -B3 -A3Repository: maximhq/bifrost Length of output: 135 🏁 Script executed: #!/bin/bash
# Check if there's a stack of related PRs or if this is localized
git log --oneline -20Repository: maximhq/bifrost Length of output: 142 🏁 Script executed: #!/bin/bash
# Check what the recent commit actually changed
git show --stat 92aa3ab2 | head -50Repository: maximhq/bifrost Length of output: 2875 🏁 Script executed: #!/bin/bash
# Check if there are any tests that populate Default with map or array values
find core -name "*.go" -type f -exec grep -l "Default" {} \; | xargs grep -l "map\|OrderedMap" | head -5Repository: maximhq/bifrost Length of output: 211 🏁 Script executed: #!/bin/bash
# Look at the actual diff of the recent commit to understand what was normalized
git show 92aa3ab2 core/schemas/chatcompletions.go 2>/dev/null | head -100Repository: maximhq/bifrost Length of output: 4471 🏁 Script executed: #!/bin/bash
# Check if Default is actually used with complex values anywhere
rg -n 'Default:' core/ --type go -B2 -A2 | head -40Repository: maximhq/bifrost Length of output: 2478 🏁 Script executed: #!/bin/bash
# Confirm the patch would compile and check if similar patterns are already tested
rg -n 'sortedCopySlice\|normalizeForSortedMarshal' core/schemas/ --type go -B2 -A10 | head -60Repository: maximhq/bifrost Length of output: 41 🏁 Script executed: #!/bin/bash
# Check if there's any test that verifies Normalized() determinism
rg -n 'Normalized.*deterministic\|deterministic.*Normalized' core/ --type go -B3 -A3Repository: maximhq/bifrost Length of output: 41 🏁 Script executed: #!/bin/bash
# Verify that OrderedMapFromMap + SortedCopy pattern is sound
rg -n 'OrderedMapFromMap.*SortedCopy' core/ --type goRepository: maximhq/bifrost Length of output: 223 Normalize
Suggested patch func (t *ToolFunctionParameters) Normalized() *ToolFunctionParameters {
if t == nil {
return nil
}
out := *t
out.keyOrder = JSONKeyOrder{}
out.Properties = t.Properties.SortedCopy()
out.Defs = t.Defs.SortedCopy()
out.Definitions = t.Definitions.SortedCopy()
out.Items = t.Items.SortedCopy()
@@
if t.AdditionalProperties != nil && t.AdditionalProperties.AdditionalPropertiesMap != nil {
out.AdditionalProperties = &AdditionalPropertiesStruct{
AdditionalPropertiesBool: t.AdditionalProperties.AdditionalPropertiesBool,
AdditionalPropertiesMap: t.AdditionalProperties.AdditionalPropertiesMap.SortedCopy(),
}
}
+ out.Default = normalizeDeterministicSchemaValue(t.Default)
return &out
}
+
+func normalizeDeterministicSchemaValue(v interface{}) interface{} {
+ switch x := v.(type) {
+ case *OrderedMap:
+ return x.SortedCopy()
+ case map[string]interface{}:
+ return OrderedMapFromMap(x).SortedCopy()
+ case []interface{}:
+ out := make([]interface{}, len(x))
+ for i := range x {
+ out[i] = normalizeDeterministicSchemaValue(x[i])
+ }
+ return out
+ default:
+ return v
+ }
+}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type AdditionalPropertiesStruct struct { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AdditionalPropertiesBool *bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AdditionalPropertiesMap *OrderedMap | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.