mirror of
https://github.com/meta-llama/llama-stack.git
synced 2025-12-03 09:53:45 +00:00
chore: fix missing titles for unions
Added _add_titles_to_unions() to: Recursively scan all schemas for anyOf/oneOf unions Generate descriptive titles from the union members Add those titles to help code generators infer names Signed-off-by: Sébastien Han <seb@redhat.com>
This commit is contained in:
parent
500804f0eb
commit
221f28b685
6 changed files with 3404 additions and 1663 deletions
File diff suppressed because it is too large
Load diff
1124
docs/static/deprecated-llama-stack-spec.yaml
vendored
1124
docs/static/deprecated-llama-stack-spec.yaml
vendored
File diff suppressed because it is too large
Load diff
911
docs/static/experimental-llama-stack-spec.yaml
vendored
911
docs/static/experimental-llama-stack-spec.yaml
vendored
File diff suppressed because it is too large
Load diff
1032
docs/static/llama-stack-spec.yaml
vendored
1032
docs/static/llama-stack-spec.yaml
vendored
File diff suppressed because it is too large
Load diff
990
docs/static/stainless-llama-stack-spec.yaml
vendored
990
docs/static/stainless-llama-stack-spec.yaml
vendored
File diff suppressed because it is too large
Load diff
|
|
@ -1030,10 +1030,11 @@ def _fix_path_parameters(openapi_schema: dict[str, Any]) -> dict[str, Any]:
|
||||||
|
|
||||||
|
|
||||||
def _fix_schema_issues(openapi_schema: dict[str, Any]) -> dict[str, Any]:
|
def _fix_schema_issues(openapi_schema: dict[str, Any]) -> dict[str, Any]:
|
||||||
"""Fix common schema issues: exclusiveMinimum and null defaults."""
|
"""Fix common schema issues: exclusiveMinimum, null defaults, and add titles to unions."""
|
||||||
if "components" in openapi_schema and "schemas" in openapi_schema["components"]:
|
if "components" in openapi_schema and "schemas" in openapi_schema["components"]:
|
||||||
for schema_def in openapi_schema["components"]["schemas"].values():
|
for schema_name, schema_def in openapi_schema["components"]["schemas"].items():
|
||||||
_fix_schema_recursive(schema_def)
|
_fix_schema_recursive(schema_def)
|
||||||
|
_add_titles_to_unions(schema_def, schema_name)
|
||||||
return openapi_schema
|
return openapi_schema
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1064,6 +1065,130 @@ def validate_openapi_schema(schema: dict[str, Any], schema_name: str = "OpenAPI
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _get_schema_title(item: dict[str, Any]) -> str | None:
|
||||||
|
"""Extract a title for a schema item to use in union variant names."""
|
||||||
|
if "$ref" in item:
|
||||||
|
return item["$ref"].split("/")[-1]
|
||||||
|
elif "type" in item:
|
||||||
|
type_val = item["type"]
|
||||||
|
if type_val == "null":
|
||||||
|
return None
|
||||||
|
if type_val == "array" and "items" in item:
|
||||||
|
items = item["items"]
|
||||||
|
if isinstance(items, dict):
|
||||||
|
if "anyOf" in items or "oneOf" in items:
|
||||||
|
nested_union = items.get("anyOf") or items.get("oneOf")
|
||||||
|
if isinstance(nested_union, list) and len(nested_union) > 0:
|
||||||
|
nested_types = []
|
||||||
|
for nested_item in nested_union:
|
||||||
|
if isinstance(nested_item, dict):
|
||||||
|
if "$ref" in nested_item:
|
||||||
|
nested_types.append(nested_item["$ref"].split("/")[-1])
|
||||||
|
elif "oneOf" in nested_item:
|
||||||
|
one_of_items = nested_item.get("oneOf", [])
|
||||||
|
if one_of_items and isinstance(one_of_items[0], dict) and "$ref" in one_of_items[0]:
|
||||||
|
base_name = one_of_items[0]["$ref"].split("/")[-1].split("-")[0]
|
||||||
|
nested_types.append(f"{base_name}Union")
|
||||||
|
else:
|
||||||
|
nested_types.append("Union")
|
||||||
|
elif "type" in nested_item and nested_item["type"] != "null":
|
||||||
|
nested_types.append(nested_item["type"])
|
||||||
|
if nested_types:
|
||||||
|
unique_nested = list(dict.fromkeys(nested_types))
|
||||||
|
# Use more descriptive names for better code generation
|
||||||
|
if len(unique_nested) <= 3:
|
||||||
|
return f"list[{' | '.join(unique_nested)}]"
|
||||||
|
else:
|
||||||
|
# Include first few types for better naming
|
||||||
|
return f"list[{unique_nested[0]} | {unique_nested[1]} | ...]"
|
||||||
|
return "list[Union]"
|
||||||
|
elif "$ref" in items:
|
||||||
|
return f"list[{items['$ref'].split('/')[-1]}]"
|
||||||
|
elif "type" in items:
|
||||||
|
return f"list[{items['type']}]"
|
||||||
|
return "array"
|
||||||
|
return type_val
|
||||||
|
elif "title" in item:
|
||||||
|
return item["title"]
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _add_titles_to_unions(obj: Any, parent_key: str | None = None) -> None:
|
||||||
|
"""Recursively add titles to union schemas (anyOf/oneOf) to help code generators infer names."""
|
||||||
|
if isinstance(obj, dict):
|
||||||
|
# Check if this is a union schema (anyOf or oneOf)
|
||||||
|
if "anyOf" in obj or "oneOf" in obj:
|
||||||
|
union_type = "anyOf" if "anyOf" in obj else "oneOf"
|
||||||
|
union_items = obj[union_type]
|
||||||
|
|
||||||
|
if isinstance(union_items, list) and len(union_items) > 0:
|
||||||
|
# Skip simple nullable unions (type | null) - these don't need titles
|
||||||
|
is_simple_nullable = (
|
||||||
|
len(union_items) == 2
|
||||||
|
and any(isinstance(item, dict) and item.get("type") == "null" for item in union_items)
|
||||||
|
and any(
|
||||||
|
isinstance(item, dict) and "type" in item and item.get("type") != "null" for item in union_items
|
||||||
|
)
|
||||||
|
and not any(
|
||||||
|
isinstance(item, dict) and ("$ref" in item or "anyOf" in item or "oneOf" in item)
|
||||||
|
for item in union_items
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if is_simple_nullable:
|
||||||
|
# Remove title from simple nullable unions if it exists
|
||||||
|
if "title" in obj:
|
||||||
|
del obj["title"]
|
||||||
|
else:
|
||||||
|
# Add titles to individual union variants that need them
|
||||||
|
for item in union_items:
|
||||||
|
if isinstance(item, dict):
|
||||||
|
# Skip null types
|
||||||
|
if item.get("type") == "null":
|
||||||
|
continue
|
||||||
|
# Add title to complex variants (arrays with unions, nested unions, etc.)
|
||||||
|
# Also add to simple types if they're part of a complex union
|
||||||
|
needs_title = (
|
||||||
|
"items" in item
|
||||||
|
or "anyOf" in item
|
||||||
|
or "oneOf" in item
|
||||||
|
or ("$ref" in item and "title" not in item)
|
||||||
|
)
|
||||||
|
if needs_title and "title" not in item:
|
||||||
|
variant_title = _get_schema_title(item)
|
||||||
|
if variant_title:
|
||||||
|
item["title"] = variant_title
|
||||||
|
|
||||||
|
# Try to infer a meaningful title from the union items for the parent
|
||||||
|
titles = []
|
||||||
|
for item in union_items:
|
||||||
|
if isinstance(item, dict):
|
||||||
|
title = _get_schema_title(item)
|
||||||
|
if title:
|
||||||
|
titles.append(title)
|
||||||
|
|
||||||
|
if titles:
|
||||||
|
# Create a title from the union items
|
||||||
|
unique_titles = list(dict.fromkeys(titles)) # Preserve order, remove duplicates
|
||||||
|
if len(unique_titles) <= 3:
|
||||||
|
title = " | ".join(unique_titles)
|
||||||
|
else:
|
||||||
|
title = f"{unique_titles[0]} | ... ({len(unique_titles)} variants)"
|
||||||
|
# Always set the title for unions to help code generators
|
||||||
|
# This will replace generic property titles with union-specific ones
|
||||||
|
obj["title"] = title
|
||||||
|
elif "title" not in obj and parent_key:
|
||||||
|
# Use parent key as fallback only if no title exists
|
||||||
|
obj["title"] = f"{parent_key.title()}Union"
|
||||||
|
|
||||||
|
# Recursively process all values
|
||||||
|
for key, value in obj.items():
|
||||||
|
_add_titles_to_unions(value, key)
|
||||||
|
elif isinstance(obj, list):
|
||||||
|
for item in obj:
|
||||||
|
_add_titles_to_unions(item, parent_key)
|
||||||
|
|
||||||
|
|
||||||
def _fix_schema_recursive(obj: Any) -> None:
|
def _fix_schema_recursive(obj: Any) -> None:
|
||||||
"""Recursively fix schema issues: exclusiveMinimum and null defaults."""
|
"""Recursively fix schema issues: exclusiveMinimum and null defaults."""
|
||||||
if isinstance(obj, dict):
|
if isinstance(obj, dict):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue