165 lines
5.3 KiB
Python
165 lines
5.3 KiB
Python
from typing import Any, Dict
|
|
|
|
|
|
def get_single_param_type_from_schema(param_schema: Dict[str, Any]) -> str:
|
|
"""
|
|
Get the type of a parameter from the schema.
|
|
If the schema is a union type, return the first type.
|
|
"""
|
|
if "anyOf" in param_schema:
|
|
types = {schema.get("type") for schema in param_schema["anyOf"] if schema.get("type")}
|
|
if "null" in types:
|
|
types.remove("null")
|
|
if types:
|
|
return next(iter(types))
|
|
return "string"
|
|
return param_schema.get("type", "string")
|
|
|
|
|
|
def resolve_schema_references(schema_part: Dict[str, Any], reference_schema: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""
|
|
Resolve schema references in OpenAPI schemas.
|
|
|
|
Args:
|
|
schema_part: The part of the schema being processed that may contain references
|
|
reference_schema: The complete schema used to resolve references from
|
|
|
|
Returns:
|
|
The schema with references resolved
|
|
"""
|
|
# Make a copy to avoid modifying the input schema
|
|
schema_part = schema_part.copy()
|
|
|
|
# Handle $ref directly in the schema
|
|
if "$ref" in schema_part:
|
|
ref_path = schema_part["$ref"]
|
|
# Standard OpenAPI references are in the format "#/components/schemas/ModelName"
|
|
if ref_path.startswith("#/components/schemas/"):
|
|
model_name = ref_path.split("/")[-1]
|
|
if "components" in reference_schema and "schemas" in reference_schema["components"]:
|
|
if model_name in reference_schema["components"]["schemas"]:
|
|
# Replace with the resolved schema
|
|
ref_schema = reference_schema["components"]["schemas"][model_name].copy()
|
|
# Remove the $ref key and merge with the original schema
|
|
schema_part.pop("$ref")
|
|
schema_part.update(ref_schema)
|
|
|
|
# Recursively resolve references in all dictionary values
|
|
for key, value in schema_part.items():
|
|
if isinstance(value, dict):
|
|
schema_part[key] = resolve_schema_references(value, reference_schema)
|
|
elif isinstance(value, list):
|
|
# Only process list items that are dictionaries since only they can contain refs
|
|
schema_part[key] = [
|
|
resolve_schema_references(item, reference_schema) if isinstance(item, dict) else item for item in value
|
|
]
|
|
|
|
return schema_part
|
|
|
|
|
|
def clean_schema_for_display(schema: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""
|
|
Clean up a schema for display by removing internal fields.
|
|
|
|
Args:
|
|
schema: The schema to clean
|
|
|
|
Returns:
|
|
The cleaned schema
|
|
"""
|
|
# Make a copy to avoid modifying the input schema
|
|
schema = schema.copy()
|
|
|
|
# Remove common internal fields that are not helpful for LLMs
|
|
fields_to_remove = [
|
|
"allOf",
|
|
"anyOf",
|
|
"oneOf",
|
|
"nullable",
|
|
"discriminator",
|
|
"readOnly",
|
|
"writeOnly",
|
|
"xml",
|
|
"externalDocs",
|
|
]
|
|
for field in fields_to_remove:
|
|
if field in schema:
|
|
schema.pop(field)
|
|
|
|
# Process nested properties
|
|
if "properties" in schema:
|
|
for prop_name, prop_schema in schema["properties"].items():
|
|
if isinstance(prop_schema, dict):
|
|
schema["properties"][prop_name] = clean_schema_for_display(prop_schema)
|
|
|
|
# Process array items
|
|
if "type" in schema and schema["type"] == "array" and "items" in schema:
|
|
if isinstance(schema["items"], dict):
|
|
schema["items"] = clean_schema_for_display(schema["items"])
|
|
|
|
return schema
|
|
|
|
|
|
def generate_example_from_schema(schema: Dict[str, Any]) -> Any:
|
|
"""
|
|
Generate a simple example response from a JSON schema.
|
|
|
|
Args:
|
|
schema: The JSON schema to generate an example from
|
|
|
|
Returns:
|
|
An example object based on the schema
|
|
"""
|
|
if not schema or not isinstance(schema, dict):
|
|
return None
|
|
|
|
# Handle different types
|
|
schema_type = schema.get("type")
|
|
|
|
if schema_type == "object":
|
|
result = {}
|
|
if "properties" in schema:
|
|
for prop_name, prop_schema in schema["properties"].items():
|
|
# Generate an example for each property
|
|
prop_example = generate_example_from_schema(prop_schema)
|
|
if prop_example is not None:
|
|
result[prop_name] = prop_example
|
|
return result
|
|
|
|
elif schema_type == "array":
|
|
if "items" in schema:
|
|
# Generate a single example item
|
|
item_example = generate_example_from_schema(schema["items"])
|
|
if item_example is not None:
|
|
return [item_example]
|
|
return []
|
|
|
|
elif schema_type == "string":
|
|
# Check if there's a format
|
|
format_type = schema.get("format")
|
|
if format_type == "date-time":
|
|
return "2023-01-01T00:00:00Z"
|
|
elif format_type == "date":
|
|
return "2023-01-01"
|
|
elif format_type == "email":
|
|
return "user@example.com"
|
|
elif format_type == "uri":
|
|
return "https://example.com"
|
|
# Use title or property name if available
|
|
return schema.get("title", "string")
|
|
|
|
elif schema_type == "integer":
|
|
return 1
|
|
|
|
elif schema_type == "number":
|
|
return 1.0
|
|
|
|
elif schema_type == "boolean":
|
|
return True
|
|
|
|
elif schema_type == "null":
|
|
return None
|
|
|
|
# Default case
|
|
return None
|