Skip to content

Commit ecfa78a

Browse files
Add OpenAPI request examples for Foundry UI (#19)
Populate requestBody media-type examples from schema examples so the compute module function UI shows realistic sample payloads instead of generic string placeholders.
1 parent f48db67 commit ecfa78a

File tree

2 files changed

+32
-3
lines changed

2 files changed

+32
-3
lines changed

openapi.foundry.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
"application/json": {
3737
"schema": {
3838
"$ref": "#/components/schemas/AEPCRequest"
39+
},
40+
"example": {
41+
"complaint": "I experienced severe nausea and vomiting after taking Ozempic."
3942
}
4043
}
4144
},
@@ -68,6 +71,9 @@
6871
"application/json": {
6972
"schema": {
7073
"$ref": "#/components/schemas/AECategoryRequest"
74+
},
75+
"example": {
76+
"complaint": "I developed pancreatitis after using Ozempic for 3 months."
7177
}
7278
}
7379
},
@@ -100,6 +106,9 @@
100106
"application/json": {
101107
"schema": {
102108
"$ref": "#/components/schemas/PCCategoryRequest"
109+
},
110+
"example": {
111+
"complaint": "The medication arrived warm, temperature control was not maintained during shipping."
103112
}
104113
}
105114
},

scripts/deploy/foundry_openapi.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,11 @@ def _collect_combiners(node: Any, path: str = "$", issues: list[str] | None = No
7474
return issues
7575

7676

77-
def _normalize_operation(operation: dict[str, Any], operation_id: str) -> dict[str, Any]:
77+
def _normalize_operation(
78+
operation: dict[str, Any],
79+
operation_id: str,
80+
schemas: dict[str, Any] | None = None,
81+
) -> dict[str, Any]:
7882
normalized: dict[str, Any] = {
7983
"operationId": operation_id,
8084
"responses": {},
@@ -91,6 +95,22 @@ def _normalize_operation(operation: dict[str, Any], operation_id: str) -> dict[s
9195
if not json_content:
9296
raise ValueError(f"Operation {operation_id} has no request content")
9397
request_copy["content"] = json_content
98+
99+
# Help Foundry generate better example payloads.
100+
# Foundry's function UI appears to prefer a media-type `example` over a
101+
# schema-level `example` behind a $ref.
102+
if schemas is not None:
103+
media = request_copy.get("content", {}).get("application/json")
104+
if isinstance(media, dict) and "example" not in media:
105+
schema = media.get("schema")
106+
if isinstance(schema, dict):
107+
ref = schema.get("$ref")
108+
if isinstance(ref, str) and ref.startswith("#/components/schemas/"):
109+
schema_name = ref.rsplit("/", maxsplit=1)[-1]
110+
schema_obj = schemas.get(schema_name)
111+
if isinstance(schema_obj, dict) and "example" in schema_obj:
112+
media["example"] = deepcopy(schema_obj["example"])
113+
94114
normalized["requestBody"] = request_copy
95115

96116
responses = operation.get("responses")
@@ -113,17 +133,17 @@ def build_foundry_openapi_spec(server_url: str = DEFAULT_FOUNDRY_SERVER_URL) ->
113133

114134
raw_spec = app.openapi()
115135
raw_paths = raw_spec.get("paths", {})
136+
raw_schemas = raw_spec.get("components", {}).get("schemas", {})
116137

117138
filtered_paths: dict[str, Any] = {}
118139
for path, operation_id in EXPECTED_OPERATIONS.items():
119140
path_item = raw_paths.get(path)
120141
if not isinstance(path_item, dict) or "post" not in path_item:
121142
raise ValueError(f"Missing POST operation for required path: {path}")
122143
filtered_paths[path] = {
123-
"post": _normalize_operation(path_item["post"], operation_id),
144+
"post": _normalize_operation(path_item["post"], operation_id, schemas=raw_schemas),
124145
}
125146

126-
raw_schemas = raw_spec.get("components", {}).get("schemas", {})
127147
referenced_schemas: set[str] = set()
128148
_collect_schema_refs(filtered_paths, referenced_schemas)
129149

0 commit comments

Comments
 (0)