MCPcopy Create free account
hub / github.com/anomalyco/opencode / sanitizeGemini

Function sanitizeGemini

packages/opencode/src/provider/transform.ts:1488–1553  ·  view source on GitHub ↗
(obj: any)

Source from the content-addressed store, hash-verified

1486 }
1487
1488 const sanitizeGemini = (obj: any): any => {
1489 if (obj === null || typeof obj !== "object") {
1490 return obj
1491 }
1492
1493 if (Array.isArray(obj)) {
1494 return obj.map(sanitizeGemini)
1495 }
1496
1497 const result: any = {}
1498 for (const [key, value] of Object.entries(obj)) {
1499 if (key === "enum" && Array.isArray(value)) {
1500 // Convert all enum values to strings
1501 result[key] = value.map((v) => String(v))
1502 // If we have integer type with enum, change type to string
1503 if (result.type === "integer" || result.type === "number") {
1504 result.type = "string"
1505 }
1506 } else if (typeof value === "object" && value !== null) {
1507 result[key] = sanitizeGemini(value)
1508 } else {
1509 result[key] = value
1510 }
1511 }
1512
1513 // Gemini requires a single `type`, not a JSON Schema type array such as
1514 // `["number","string"]` (emitted by some MCP servers). Plain `@ai-sdk/google`
1515 // rewrites these into an `anyOf` of single-type schemas, but OpenAI-compatible
1516 // transports (e.g. GitHub Copilot proxying to Gemini) forward them verbatim
1517 // and the backend rejects the array form. Mirror the SDK: split non-null
1518 // types into `anyOf`, and lift `null` into `nullable`.
1519 if (Array.isArray(result.type)) {
1520 const hasNull = result.type.includes("null")
1521 const nonNull = result.type.filter((entry: unknown) => entry !== "null")
1522 if (nonNull.length === 0) {
1523 result.type = "null"
1524 } else {
1525 delete result.type
1526 result.anyOf = nonNull.map((entry: unknown) => ({ type: entry }))
1527 if (hasNull) result.nullable = true
1528 }
1529 }
1530
1531 // Filter required array to only include fields that exist in properties
1532 if (result.type === "object" && result.properties && Array.isArray(result.required)) {
1533 result.required = result.required.filter((field: any) => field in result.properties)
1534 }
1535
1536 if (result.type === "array" && !hasCombiner(result)) {
1537 if (result.items == null) {
1538 result.items = {}
1539 }
1540 // Ensure items has a type only when it's still schema-empty.
1541 if (isPlainObject(result.items) && !hasSchemaIntent(result.items)) {
1542 result.items.type = "string"
1543 }
1544 }
1545

Callers 1

schemaFunction · 0.85

Calls 3

hasCombinerFunction · 0.70
isPlainObjectFunction · 0.70
hasSchemaIntentFunction · 0.70

Tested by

no test coverage detected