Skip to content

Commit c2d54b5

Browse files
authored
Merge pull request #374 from kushaldotdev/fix/gemini-schema-ref-validation
fix: resolve Gemini 400 error caused by co-existing fields in Schema.ref
2 parents 751aeec + 57d9526 commit c2d54b5

1 file changed

Lines changed: 24 additions & 13 deletions

File tree

src/converter/openai2gemini.py

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -140,16 +140,23 @@ def _normalize_function_name(name: str) -> str:
140140

141141
def _resolve_ref(ref: str, root_schema: Dict[str, Any]) -> Optional[Dict[str, Any]]:
142142
"""
143-
解析 $ref 引用
143+
解析 $ref 或 ref 引用
144144
145145
Args:
146-
ref: 引用路径,如 "#/definitions/MyType"
146+
ref: 引用路径,如 "#/definitions/MyType" 或 "#/$defs/MyType"
147147
root_schema: 根 schema 对象
148148
149149
Returns:
150150
解析后的 schema,如果失败返回 None
151151
"""
152+
if not isinstance(ref, str):
153+
return None
154+
152155
if not ref.startswith('#/'):
156+
# 尝试在 definitions 或 $defs 中查找
157+
for key in ["definitions", "$defs"]:
158+
if key in root_schema and ref in root_schema[key]:
159+
return root_schema[key][ref]
153160
return None
154161

155162
path = ref[2:].split('/')
@@ -356,22 +363,26 @@ def _clean_schema_for_gemini(schema: Any, root_schema: Optional[Dict[str, Any]]
356363
# 创建副本避免修改原对象
357364
result = {}
358365

359-
# 1. 处理 $ref
360-
if "$ref" in schema:
361-
resolved = _resolve_ref(schema["$ref"], root_schema)
366+
# 1. 处理 $ref 或 ref
367+
ref_key = "$ref" if "$ref" in schema else ("ref" if "ref" in schema else None)
368+
if ref_key:
369+
resolved = _resolve_ref(schema[ref_key], root_schema)
362370
if resolved:
363-
# 检测循环引用:若 resolved 已在 visited 中,直接返回占位符
371+
# 检测循环引用
364372
resolved_id = id(resolved)
365373
if resolved_id in visited:
366374
return {"type": "OBJECT", "description": "(circular reference)"}
367-
# 将 resolved 的 id 加入 visited,防止后续递归时重复处理
375+
368376
visited.add(resolved_id)
369-
# 合并解析后的 schema 和当前 schema(浅拷贝,避免 deepcopy 爆栈)
377+
# 合并解析后的 schema
370378
merged = dict(resolved)
371-
# 当前 schema 的其他字段会覆盖解析后的字段
372-
for key, value in schema.items():
373-
if key != "$ref":
374-
merged[key] = value
379+
380+
# 重要:根据 Gemini API 限制,当存在引用时,只能并列存在 description 和 default
381+
# 其他字段(如 type, properties 等)必须丢弃,否则会触发 400 错误
382+
for key in ["description", "default"]:
383+
if key in schema:
384+
merged[key] = schema[key]
385+
375386
schema = merged
376387
result = {}
377388

@@ -500,7 +511,7 @@ def _clean_schema_for_gemini(schema: Any, root_schema: Optional[Dict[str, Any]]
500511

501512
# 7. 清理不支持的字段
502513
unsupported_keys = {
503-
"title", "$schema", "$ref", "strict", "exclusiveMaximum",
514+
"title", "$schema", "$ref", "ref", "strict", "exclusiveMaximum",
504515
"exclusiveMinimum", "additionalProperties", "oneOf", "allOf",
505516
"$defs", "definitions", "example", "examples", "readOnly",
506517
"writeOnly", "const", "additionalItems", "contains",

0 commit comments

Comments
 (0)