Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,86 @@ public void FromPromptAndExecutionSettingsWithThinkingConfigReturnsInGenerationC
Assert.Equal(executionSettings.ThinkingConfig.ThinkingBudget, request.Configuration?.ThinkingConfig?.ThinkingBudget);
}

[Fact]
public void ResponseSchemaStripsUnsupportedFormatFields()
{
// Arrange
var prompt = "prompt-example";
var schemaWithUnsupportedFormats = """
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "unique identifier"
},
"email": {
"type": "string",
"format": "email",
"description": "user email"
},
"status": {
"type": "string",
"format": "enum",
"enum": ["active", "inactive"],
"description": "user status"
},
"createdAt": {
"type": "string",
"format": "date-time",
"description": "creation timestamp"
},
"phoneNumber": {
"type": "string",
"format": "phone",
"description": "phone number"
}
}
}
""";

var executionSettings = new GeminiPromptExecutionSettings
{
ResponseMimeType = "application/json",
ResponseSchema = JsonSerializer.Deserialize<JsonElement>(schemaWithUnsupportedFormats)
};

// Act
var request = GeminiRequest.FromPromptAndExecutionSettings(prompt, executionSettings);

// Assert
Assert.NotNull(request.Configuration?.ResponseSchema);
var properties = request.Configuration.ResponseSchema.Value.GetProperty("properties");

// UUID format should be stripped
var idProperty = properties.GetProperty("id");
Assert.Equal("string", idProperty.GetProperty("type").GetString());
Assert.False(idProperty.TryGetProperty("format", out _));

// Email format should be stripped
var emailProperty = properties.GetProperty("email");
Assert.Equal("string", emailProperty.GetProperty("type").GetString());
Assert.False(emailProperty.TryGetProperty("format", out _));

// Enum format should be preserved
var statusProperty = properties.GetProperty("status");
Assert.Equal("string", statusProperty.GetProperty("type").GetString());
Assert.True(statusProperty.TryGetProperty("format", out var statusFormat));
Assert.Equal("enum", statusFormat.GetString());

// Date-time format should be preserved
var createdAtProperty = properties.GetProperty("createdAt");
Assert.Equal("string", createdAtProperty.GetProperty("type").GetString());
Assert.True(createdAtProperty.TryGetProperty("format", out var createdAtFormat));
Assert.Equal("date-time", createdAtFormat.GetString());

// Phone format should be stripped
var phoneProperty = properties.GetProperty("phoneNumber");
Assert.Equal("string", phoneProperty.GetProperty("type").GetString());
Assert.False(phoneProperty.TryGetProperty("format", out _));
}

private sealed class DummyContent(object? innerContent, string? modelId = null, IReadOnlyDictionary<string, object?>? metadata = null) :
KernelContent(innerContent, modelId, metadata);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,23 @@ static void TransformOpenApi3Object(JsonObject obj)
{
propertyObj["type"] = JsonValue.Create("string");
}
else if (propertyObj.TryGetPropertyValue("type", out JsonNode? typeNode))

// Strip unsupported format fields for string types
// Google API only supports "enum" and "date-time" formats for string types
if (propertyObj.TryGetPropertyValue("type", out JsonNode? typeNode) &&
typeNode is JsonValue typeValue &&
typeValue.GetValue<string>() == "string" &&
propertyObj.TryGetPropertyValue("format", out JsonNode? formatNode) &&
formatNode is JsonValue formatValue)
{
var format = formatValue.GetValue<string>();
if (format != "enum" && format != "date-time")
{
propertyObj.Remove("format");
}
}

if (propertyObj.TryGetPropertyValue("type", out typeNode))
{
if (typeNode is JsonArray typeArray)
{
Expand All @@ -387,7 +403,7 @@ static void TransformOpenApi3Object(JsonObject obj)
propertyObj["nullable"] = JsonValue.Create(true);
}
}
else if (typeNode is JsonValue typeValue && typeValue.GetValue<string>() == "array")
else if (typeNode is JsonValue typeVal && typeVal.GetValue<string>() == "array")
{
if (propertyObj.TryGetPropertyValue("items", out JsonNode? itemsNode) && itemsNode is JsonObject itemsObj)
{
Expand Down
Loading