Skip to content

feat: add support for multiple types in Gemini structured outputs properties#1243

Merged
akshaydeo merged 1 commit intomainfrom
01-05-fix_added_support_for_multiple_types_in_gemini_structure_outputs_properties
Jan 5, 2026
Merged

feat: add support for multiple types in Gemini structured outputs properties#1243
akshaydeo merged 1 commit intomainfrom
01-05-fix_added_support_for_multiple_types_in_gemini_structure_outputs_properties

Conversation

@Pratham-Mishra04
Copy link
Collaborator

Summary

Added support for multiple types in JSON schema properties for Gemini and Anthropic structured outputs, allowing for proper handling of union types like ["string", "integer"] in schema definitions.

Changes

  • Added schema normalization for Gemini to handle properties with multiple types
  • Implemented conversion of union types to anyOf constructs for Gemini when needed
  • Maintained array type notation for nullable types (["string", "null"]) which Gemini supports natively
  • Added comprehensive test cases for structured output conversion with various schema patterns
  • Updated documentation to reflect the changes in schema handling

Type of change

  • Feature
  • Bug fix

Affected areas

  • Core (Go)
  • Providers/Integrations
  • Docs

How to test

# Run the new tests for structured output conversion
go test ./core/providers/gemini -run TestStructuredOutputConversion
go test ./core/providers/gemini -run TestResponsesStructuredOutputConversion

# Run all Gemini tests
go test ./core/providers/gemini/...

Breaking changes

  • No

Related issues

Extends the schema normalization support previously added for Anthropic to Gemini provider.

Security considerations

No security implications as this only affects schema transformation logic.

Checklist

  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)

Copy link
Collaborator Author

Pratham-Mishra04 commented Jan 5, 2026

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 5, 2026

📝 Walkthrough

Summary by CodeRabbit

Release Notes

  • New Features

    • Added support for multiple types in Gemini and Anthropic structured outputs properties, enabling more flexible schema definitions.
  • Documentation

    • Updated Gemini provider parameter documentation; response_format now maps to responseJsonSchema instead of responseSchema in both Chat Completions and Responses API.

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

The PR refactors Gemini provider's schema handling to support multiple types in structured outputs by migrating from typed Schema objects to map-based JSON schemas with added normalization logic. Tests, documentation, and changelogs are updated accordingly to reflect the new approach for handling union types and complex nested structures.

Changes

Cohort / File(s) Summary
Test Additions
core/providers/gemini/gemini_test.go
Added comprehensive test cases for structured output conversion (TestStructuredOutputConversion, TestResponsesStructuredOutputConversion) and Responses API tool conversion (TestBifrostResponsesToGeminiToolConversion), covering union types, nullable types, complex nested structures, and enums. Bumped test ChatModel from gemini-2.0-flash to gemini-2.5-flash.
Schema Handling Implementation
core/providers/gemini/responses.go, core/providers/gemini/utils.go
Refactored schema conversion logic from typed Schema objects to map-based JSON schemas. In responses.go, added conditional handling for pre-existing schemas and normalization step. In utils.go, replaced OpenAI response formatting path to use response_json_schema; added normalizeSchemaForGemini for recursive schema normalization (arrays of types, anyOf, oneOf, properties, items, enums); updated schema extraction and generation config flow to use normalized map-based schemas instead of typed objects.
Documentation & Configuration
docs/providers/supported-providers/gemini.mdx
Updated parameter mappings in Chat Completions and Responses API sections to map response_format and text fields to responseJsonSchema instead of responseSchema.
Changelog Updates
core/changelog.md, transports/changelog.md
Rewrote feature description from schema normalization for Anthropic enum fields to "added support for multiple types in gemini and anthropic structured outputs properties".

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 Schemas dance with types so grand,
Multiple ones, we understand!
Normalize and map with care,
Gemini's structured outputs fair.
Nested, nested, deep we go—
Schema magic in the flow!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main change—adding support for multiple types in Gemini structured outputs properties—which aligns with the primary objective across modified files.
Description check ✅ Passed The description follows the template structure with all key sections completed: summary, changes, type of change, affected areas, testing instructions, breaking changes, and a populated checklist.
Docstring Coverage ✅ Passed Docstring coverage is 91.67% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 01-05-fix_added_support_for_multiple_types_in_gemini_structure_outputs_properties

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4ea3f33 and c56dde9.

📒 Files selected for processing (6)
  • core/changelog.md
  • core/providers/gemini/gemini_test.go
  • core/providers/gemini/responses.go
  • core/providers/gemini/utils.go
  • docs/providers/supported-providers/gemini.mdx
  • transports/changelog.md
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

always check the stack if there is one for the current PR. do not give localized reviews for the PR, always see all changes in the light of the whole stack of PRs (if there is a stack, if there is no stack you can continue to make localized suggestions/reviews)

Files:

  • core/changelog.md
  • docs/providers/supported-providers/gemini.mdx
  • transports/changelog.md
  • core/providers/gemini/responses.go
  • core/providers/gemini/utils.go
  • core/providers/gemini/gemini_test.go
🧠 Learnings (5)
📚 Learning: 2025-12-30T05:37:48.365Z
Learnt from: Pratham-Mishra04
Repo: maximhq/bifrost PR: 1180
File: docs/features/mcp/connecting-to-servers.mdx:452-458
Timestamp: 2025-12-30T05:37:48.365Z
Learning: When reviewing documentation PRs in a Graphite-managed stack, first check related or previous PRs in the stack for feature implementations before flagging documentation as incorrect or unsupported. Documentation MDX files often reference features implemented in earlier stack PRs; verify that the documented behavior exists in earlier changes and that the docs accurately reflect the implemented state before requesting edits.

Applied to files:

  • docs/providers/supported-providers/gemini.mdx
📚 Learning: 2025-12-09T17:07:42.007Z
Learnt from: qwerty-dvorak
Repo: maximhq/bifrost PR: 1006
File: core/schemas/account.go:9-18
Timestamp: 2025-12-09T17:07:42.007Z
Learning: In core/schemas/account.go, the HuggingFaceKeyConfig field within the Key struct is currently unused and reserved for future Hugging Face inference endpoint deployments. Do not flag this field as missing from OpenAPI documentation or require its presence in the API spec until the feature is actively implemented and used. When the feature is added, update the OpenAPI docs accordingly; otherwise, treat this field as non-breaking and not part of the current API surface.

Applied to files:

  • core/providers/gemini/responses.go
  • core/providers/gemini/utils.go
  • core/providers/gemini/gemini_test.go
📚 Learning: 2025-12-29T11:54:55.836Z
Learnt from: akshaydeo
Repo: maximhq/bifrost PR: 1153
File: framework/configstore/rdb.go:2221-2246
Timestamp: 2025-12-29T11:54:55.836Z
Learning: In Go reviews, do not flag range-over-int patterns like for i := range n as compile-time errors, assuming Go 1.22+ semantics. Only flag actual range-capable values (slices, arrays, maps, channels, strings) and other compile-time issues. This applies to all Go files across the repository.

Applied to files:

  • core/providers/gemini/responses.go
  • core/providers/gemini/utils.go
  • core/providers/gemini/gemini_test.go
📚 Learning: 2025-12-19T09:26:54.961Z
Learnt from: qwerty-dvorak
Repo: maximhq/bifrost PR: 1006
File: core/providers/utils/utils.go:1050-1051
Timestamp: 2025-12-19T09:26:54.961Z
Learning: Update streaming end-marker handling so HuggingFace is treated as a non-[DONE] provider for backends that do not emit a DONE marker (e.g., meta llama on novita). In core/providers/utils/utils.go, adjust ProviderSendsDoneMarker() (or related logic) to detect providers that may not emit DONE and avoid relying on DONE as the sole end signal. Add tests to cover both DONE-emitting and non-DONE backends, with clear documentation in code comments explaining the rationale and any fallback behavior.

Applied to files:

  • core/providers/gemini/responses.go
  • core/providers/gemini/utils.go
  • core/providers/gemini/gemini_test.go
📚 Learning: 2025-12-15T10:16:21.909Z
Learnt from: qwerty-dvorak
Repo: maximhq/bifrost PR: 1006
File: core/providers/huggingface/huggingface_test.go:12-63
Timestamp: 2025-12-15T10:16:21.909Z
Learning: In provider tests under core/providers/<provider>/*_test.go, do not require or flag the use of defer for Shutdown(); instead call client.Shutdown() at the end of each test function. This pattern appears consistent across all provider tests. Apply this rule only within this path; for other tests or resources, defer may still be appropriate.

Applied to files:

  • core/providers/gemini/gemini_test.go
🧬 Code graph analysis (2)
core/providers/gemini/utils.go (2)
core/schemas/responses.go (2)
  • ResponsesTextConfig (120-123)
  • ResponsesTextConfigFormat (125-130)
core/providers/gemini/types.go (1)
  • Type (783-783)
core/providers/gemini/gemini_test.go (6)
core/schemas/chatcompletions.go (1)
  • BifrostChatRequest (12-19)
core/providers/gemini/types.go (3)
  • GeminiGenerationRequest (59-78)
  • Content (982-990)
  • GenerationConfig (636-702)
core/schemas/utils.go (1)
  • Ptr (16-18)
core/providers/gemini/chat.go (1)
  • ToGeminiChatCompletionRequest (12-63)
core/schemas/responses.go (2)
  • BifrostResponsesRequest (32-39)
  • ResponsesMessage (321-334)
core/providers/gemini/responses.go (1)
  • ToGeminiResponsesRequest (70-120)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (51)
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
🔇 Additional comments (13)
core/changelog.md (1)

1-1: Changelog entry is clear and comprehensive.

Accurately captures the feature scope covering both Gemini and Anthropic structured outputs support for multiple types.

transports/changelog.md (1)

1-1: Changelog entry consistent with core module.

Maintains synchronization between transport and core changelogs for the multi-type support feature.

docs/providers/supported-providers/gemini.mdx (1)

43-43: Parameter mappings consistently updated from responseSchema to responseJsonSchema.

Both Chat Completions (line 43) and Responses API (line 197) sections correctly reflect the shift to map-based JSON schema handling. The naming aligns with the PR objective of supporting multiple types through schema normalization. No orphaned references to the old parameter name remain in the documentation.

core/providers/gemini/responses.go (1)

1964-2009: LGTM - Clean schema reconstruction with normalization.

The function correctly handles both paths:

  1. Direct schema from jsonSchema.Schema field
  2. Building schema from individual fields (Type, Properties, etc.)

The mapping of Name to title is correct per JSON Schema conventions. The nil check at line 2003-2005 prevents returning empty schemas.

core/providers/gemini/gemini_test.go (4)

30-30: Verify the model version update is intentional.

The test configuration updated ChatModel from gemini-2.0-flash to gemini-2.5-flash. Ensure this aligns with the intended test targets and that gemini-2.5-flash is stable for the test scenarios.


291-514: Good test coverage for structured output conversion.

The tests comprehensively cover the key scenarios:

  • Union types (["string", "integer"]) correctly converted to anyOf structure
  • Nullable types (["string", "null"]) preserved as arrays (Gemini-native support)
  • Complex nested structures with arrays of objects
  • json_object format correctly sets only ResponseMIMEType without schema

The assertions correctly validate the transformed schema structure.


516-647: Good coverage for Responses API structured output conversion.

These tests ensure the same normalization logic works correctly through the ToGeminiResponsesRequest path, providing consistency between the Chat and Responses APIs.


649-851: Comprehensive tool conversion tests.

These tests validate critical scenarios for tool parameter conversion:

  • Array properties with items field properly preserved
  • Nested object structures within array items
  • Empty items objects handled gracefully

This addresses the array items bug mentioned in the test comments.

core/providers/gemini/utils.go (5)

1001-1063: Consider preserving description when converting to anyOf.

When converting union types to anyOf, the current implementation removes the enum field but preserves description at the top level. However, per JSON Schema semantics, if the original property had a description, it should remain alongside anyOf. The current code does preserve it (doesn't delete it), which is correct.

One edge case: if the original property has both a union type AND an enum (e.g., {"type": ["string", "integer"], "enum": ["active", 123]}), deleting the enum makes sense since enums with mixed types are unusual and anyOf provides the type branching.


1066-1111: Complete recursive normalization coverage.

The function correctly handles all nested schema locations: properties, items, anyOf, and oneOf. This ensures union types are normalized throughout the entire schema tree, including deeply nested structures.


1113-1143: Correct schema extraction with normalization.

The function properly navigates the OpenAI response_format structure and applies Gemini-specific normalization. The early returns for invalid structures prevent nil pointer issues.


940-979: Clean refactoring for flexible schema handling.

The function now handles the schema as a flexible map structure, with appropriate fallbacks to json_object mode when the schema is nil or not in the expected format. This aligns with the PR's goal of supporting more complex schema patterns.


441-444: Add override handling for response_schema in ExtraParams or clarify if intentional deprecation.

The code asymmetrically handles response_schema vs response_json_schema: both are populated into ExtraParams (lines 86-91), but only response_json_schema is checked during override processing (lines 441-444). If external code relies on response_schema in ExtraParams for configuration overrides, it will now be silently ignored. Either add override handling for response_schema to maintain parity, or update the populate logic to reflect that response_schema is deprecated in favor of response_json_schema.


Comment @coderabbitai help to get the list of available commands and usage tips.

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 01-05-fix_added_support_for_multiple_types_in_gemini_structure_outputs_properties branch from 02bbc2f to c56dde9 Compare January 5, 2026 08:21
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 01-05-feat_added_structured_output_schema_normalisation_for_anthropic branch from e8d777d to 4ea3f33 Compare January 5, 2026 08:21
@Pratham-Mishra04 Pratham-Mishra04 changed the title feat: add support for multiple types in Gemini structured outputs feat: add support for multiple types in Gemini structured outputs properties Jan 5, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
core/providers/gemini/utils.go (2)

1001-1111: Consider adding recursion depth protection.

The normalizeSchemaForGemini function correctly implements the schema normalization logic:

  • Keeps ["string", "null"] as-is (Gemini native support)
  • Converts ["string", "integer"] to anyOf constructs
  • Handles various edge cases properly

However, the recursive calls (lines 1071, 1081, 1089, 1102) lack depth protection, which could cause stack overflow with malicious or deeply nested schemas.

🔎 Suggested approach for recursion protection

Add a depth parameter to track recursion depth and return early if exceeded:

-func normalizeSchemaForGemini(schema map[string]interface{}) map[string]interface{} {
+func normalizeSchemaForGemini(schema map[string]interface{}) map[string]interface{} {
+	return normalizeSchemaForGeminiWithDepth(schema, 0, 100) // max depth 100
+}
+
+func normalizeSchemaForGeminiWithDepth(schema map[string]interface{}, depth, maxDepth int) map[string]interface{} {
 	if schema == nil {
 		return nil
 	}
+	if depth > maxDepth {
+		// Return schema as-is if max depth exceeded
+		return schema
+	}

 	normalized := make(map[string]interface{})
 	// ... rest of logic, replacing recursive calls with:
-	newProps[key] = normalizeSchemaForGemini(propMap)
+	newProps[key] = normalizeSchemaForGeminiWithDepth(propMap, depth+1, maxDepth)

1051-1052: Add test coverage for enum removal when converting union types to anyOf.

The code at lines 1051-1052 removes the enum field when converting multiple-type union schemas to anyOf format. While a comment explains the rationale, this significant schema transformation lacks test coverage. The Anthropic provider has explicit tests for this scenario (e.g., "type array with multiple types and enum"), whereas Gemini's tests only validate anyOf conversion for union types without enums. Add a test case covering enum removal with union types to document and validate this behavior.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4ea3f33 and c56dde9.

📒 Files selected for processing (6)
  • core/changelog.md
  • core/providers/gemini/gemini_test.go
  • core/providers/gemini/responses.go
  • core/providers/gemini/utils.go
  • docs/providers/supported-providers/gemini.mdx
  • transports/changelog.md
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

always check the stack if there is one for the current PR. do not give localized reviews for the PR, always see all changes in the light of the whole stack of PRs (if there is a stack, if there is no stack you can continue to make localized suggestions/reviews)

Files:

  • transports/changelog.md
  • core/changelog.md
  • docs/providers/supported-providers/gemini.mdx
  • core/providers/gemini/gemini_test.go
  • core/providers/gemini/utils.go
  • core/providers/gemini/responses.go
🧠 Learnings (5)
📚 Learning: 2025-12-30T05:37:48.365Z
Learnt from: Pratham-Mishra04
Repo: maximhq/bifrost PR: 1180
File: docs/features/mcp/connecting-to-servers.mdx:452-458
Timestamp: 2025-12-30T05:37:48.365Z
Learning: When reviewing documentation PRs in a Graphite-managed stack, first check related or previous PRs in the stack for feature implementations before flagging documentation as incorrect or unsupported. Documentation MDX files often reference features implemented in earlier stack PRs; verify that the documented behavior exists in earlier changes and that the docs accurately reflect the implemented state before requesting edits.

Applied to files:

  • docs/providers/supported-providers/gemini.mdx
📚 Learning: 2025-12-09T17:07:42.007Z
Learnt from: qwerty-dvorak
Repo: maximhq/bifrost PR: 1006
File: core/schemas/account.go:9-18
Timestamp: 2025-12-09T17:07:42.007Z
Learning: In core/schemas/account.go, the HuggingFaceKeyConfig field within the Key struct is currently unused and reserved for future Hugging Face inference endpoint deployments. Do not flag this field as missing from OpenAPI documentation or require its presence in the API spec until the feature is actively implemented and used. When the feature is added, update the OpenAPI docs accordingly; otherwise, treat this field as non-breaking and not part of the current API surface.

Applied to files:

  • core/providers/gemini/gemini_test.go
  • core/providers/gemini/utils.go
  • core/providers/gemini/responses.go
📚 Learning: 2025-12-29T11:54:55.836Z
Learnt from: akshaydeo
Repo: maximhq/bifrost PR: 1153
File: framework/configstore/rdb.go:2221-2246
Timestamp: 2025-12-29T11:54:55.836Z
Learning: In Go reviews, do not flag range-over-int patterns like for i := range n as compile-time errors, assuming Go 1.22+ semantics. Only flag actual range-capable values (slices, arrays, maps, channels, strings) and other compile-time issues. This applies to all Go files across the repository.

Applied to files:

  • core/providers/gemini/gemini_test.go
  • core/providers/gemini/utils.go
  • core/providers/gemini/responses.go
📚 Learning: 2025-12-15T10:16:21.909Z
Learnt from: qwerty-dvorak
Repo: maximhq/bifrost PR: 1006
File: core/providers/huggingface/huggingface_test.go:12-63
Timestamp: 2025-12-15T10:16:21.909Z
Learning: In provider tests under core/providers/<provider>/*_test.go, do not require or flag the use of defer for Shutdown(); instead call client.Shutdown() at the end of each test function. This pattern appears consistent across all provider tests. Apply this rule only within this path; for other tests or resources, defer may still be appropriate.

Applied to files:

  • core/providers/gemini/gemini_test.go
📚 Learning: 2025-12-19T09:26:54.961Z
Learnt from: qwerty-dvorak
Repo: maximhq/bifrost PR: 1006
File: core/providers/utils/utils.go:1050-1051
Timestamp: 2025-12-19T09:26:54.961Z
Learning: Update streaming end-marker handling so HuggingFace is treated as a non-[DONE] provider for backends that do not emit a DONE marker (e.g., meta llama on novita). In core/providers/utils/utils.go, adjust ProviderSendsDoneMarker() (or related logic) to detect providers that may not emit DONE and avoid relying on DONE as the sole end signal. Add tests to cover both DONE-emitting and non-DONE backends, with clear documentation in code comments explaining the rationale and any fallback behavior.

Applied to files:

  • core/providers/gemini/gemini_test.go
  • core/providers/gemini/utils.go
  • core/providers/gemini/responses.go
🧬 Code graph analysis (2)
core/providers/gemini/utils.go (1)
core/schemas/responses.go (2)
  • ResponsesTextConfig (120-123)
  • ResponsesTextConfigFormat (125-130)
core/providers/gemini/responses.go (1)
core/providers/gemini/types.go (2)
  • Schema (729-780)
  • Type (783-783)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (50)
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
🔇 Additional comments (16)
core/providers/gemini/gemini_test.go (4)

30-30: Model version updated to target newer Gemini capabilities.

The upgrade from gemini-2.0-flash to gemini-2.5-flash aligns with testing the new structured output features introduced in this PR.


291-514: Comprehensive test coverage for structured output conversion.

The test cases thoroughly validate:

  • Union type conversion to anyOf constructs (e.g., ["string", "integer"]anyOf: [{type: "string"}, {type: "integer"}])
  • Nullable types preserved as arrays (e.g., ["string", "null"] remains as-is)
  • Complex nested schemas with proper structure
  • json_object format behavior (MIME type set, no schema attached)

The test structure is clear, with explicit validation functions that check both the presence and correctness of transformed fields.


516-647: Responses API structured output conversion tests are well-implemented.

The tests mirror the Chat Completions tests but target the Responses API conversion path (ToGeminiResponsesRequest). This ensures consistent behavior across both API surfaces for:

  • Union type normalization to anyOf
  • Nullable type preservation as arrays

The parallel test structure helps maintain feature parity between the two APIs.


291-647: Excellent test coverage for the new structured output functionality.

The new tests comprehensively validate the schema normalization logic for both Chat Completions and Responses APIs. The test structure is clear, assertions are thorough, and edge cases are covered (union types, nullable types, complex nested schemas, and json_object format).

transports/changelog.md (1)

1-1: Changelog appropriately reflects the broader feature scope.

The updated entry correctly describes the feature as supporting multiple types in both Gemini and Anthropic structured outputs, rather than limiting the description to Anthropic-specific schema normalization.

core/changelog.md (1)

1-1: Changelog correctly reflects the feature expansion.

The entry appropriately describes the broader support for multiple types in both Gemini and Anthropic structured outputs.

docs/providers/supported-providers/gemini.mdx (3)

43-43: Documentation accurately reflects the parameter mapping changes.

The update from responseSchema to responseJsonSchema aligns with the code changes and ensures users have the correct mapping information.


47-47: Gemini-specific parameter properly documented.

The top_k parameter is correctly documented as requiring extra_params for Gemini-specific usage.


197-197: Responses API documentation updated consistently.

The Responses API text mapping now correctly references responseJsonSchema instead of responseSchema, maintaining consistency with the Chat Completions API documentation.

core/providers/gemini/responses.go (1)

1964-2009: Schema reconstruction enhanced with normalization and safer handling.

The updated logic improves robustness:

  1. Type-safe casting: The Schema field is safely cast to map[string]interface{} with fallback to the original value on failure (lines 1969-1972)
  2. Field-by-field construction: When Schema is nil, individual fields are assembled into a schema map (lines 1975-2005)
  3. Empty schema handling: Returns nil if no fields are populated, preventing empty schema objects (lines 2002-2005)
  4. Normalization: Calls normalizeSchemaForGemini to handle union types and ensure Gemini compatibility (line 2009)

The normalization step is crucial for converting union types (e.g., ["string", "integer"]) to anyOf constructs, as validated by the test suite.

core/providers/gemini/utils.go (6)

77-77: LGTM: Function call updated to match new signature.

The call to buildOpenAIResponseFormat correctly uses only the ResponseJSONSchema parameter, matching the refactored function signature at line 940.


420-423: LGTM: Schema extraction updated to use normalization.

The updated logic correctly extracts and normalizes the schema using extractSchemaMapFromResponseFormat, which now includes Gemini-specific normalization (handling union types). The assignment to config.ResponseJSONSchema properly reflects this normalized schema.


441-444: LGTM: ExtraParams handling updated consistently.

The comment and parameter key are correctly updated to use response_json_schema, maintaining consistency with the broader refactoring from ResponseSchema to ResponseJSONSchema.


940-979: LGTM: Function refactored to handle schema-based response formatting.

The refactored buildOpenAIResponseFormat correctly:

  • Returns json_object mode when no schema is provided
  • Returns json_schema mode with proper structure when a schema exists
  • Extracts the title/name from the schema or defaults to "json_response"
  • Includes appropriate fallback logic for invalid inputs

981-999: LGTM: Type extraction helper is well-implemented.

The extractTypesFromValue function correctly handles the different type representations (string, []string, []interface{}) that can appear in JSON schemas. The logic is straightforward and robust with proper type checking.


1113-1143: LGTM: Schema extraction now includes Gemini normalization.

The addition of normalizeSchemaForGemini at line 1142 ensures that all schemas extracted from OpenAI's response_format structure are properly normalized for Gemini's requirements, handling union types and nullable types correctly.

Copy link
Contributor

akshaydeo commented Jan 5, 2026

Merge activity

  • Jan 5, 8:59 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jan 5, 9:01 AM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo akshaydeo changed the base branch from 01-05-feat_added_structured_output_schema_normalisation_for_anthropic to graphite-base/1243 January 5, 2026 09:00
@akshaydeo akshaydeo changed the base branch from graphite-base/1243 to main January 5, 2026 09:00
@akshaydeo akshaydeo merged commit bf23f5b into main Jan 5, 2026
5 checks passed
@akshaydeo akshaydeo deleted the 01-05-fix_added_support_for_multiple_types_in_gemini_structure_outputs_properties branch January 5, 2026 09:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants