|
25 | 25 |
|
26 | 26 | from __future__ import annotations |
27 | 27 |
|
| 28 | +import copy |
28 | 29 | import os |
29 | 30 | import re |
30 | 31 | import subprocess |
@@ -886,29 +887,37 @@ def _singularize(word: str) -> str: |
886 | 887 | health_get["tags"] = ["health"] |
887 | 888 | fixes.append("/health: added 'health' tag") |
888 | 889 |
|
889 | | - # 15. /files responses: YAML anchor overlay hides actual response schemas |
890 | | - # Remove the overlaid empty content block so $ref responses are used |
891 | | - for files_ep in ("/files",): |
892 | | - fpath = paths.get(files_ep, {}) |
893 | | - for method in ("get", "post"): |
894 | | - op = fpath.get(method) |
895 | | - if not op: |
| 890 | + # 15. /files responses: inline $ref responses so Mintlify renders them correctly |
| 891 | + # The upstream spec uses YAML anchors that cause issues, and some renderers |
| 892 | + # don't resolve response-level $refs properly. |
| 893 | + comp_responses = spec.get("components", {}).get("responses", {}) |
| 894 | + files_path = paths.get("/files", {}) |
| 895 | + for method in ("get", "post"): |
| 896 | + op = files_path.get(method) |
| 897 | + if not op: |
| 898 | + continue |
| 899 | + responses = op.get("responses", {}) |
| 900 | + for status_code, resp in list(responses.items()): |
| 901 | + if not isinstance(resp, dict): |
896 | 902 | continue |
897 | | - responses = op.get("responses", {}) |
898 | | - for status_code, resp in responses.items(): |
899 | | - if not isinstance(resp, dict): |
900 | | - continue |
901 | | - # If the response has both $ref and content with an empty schema, |
902 | | - # the empty content overlay was from the YAML anchor bug — remove it |
903 | | - if "$ref" in resp and "content" in resp: |
904 | | - content = resp["content"] |
905 | | - for ct, media in list(content.items()): |
906 | | - s = media.get("schema", {}) |
907 | | - if s.get("description") == "Empty response": |
908 | | - del content[ct] |
909 | | - if not content: |
910 | | - del resp["content"] |
911 | | - fixes.append(f"{files_ep} {method.upper()}: removed anchor-overlaid empty content") |
| 903 | + # Inline any $ref to components/responses |
| 904 | + ref = resp.get("$ref", "") |
| 905 | + if ref.startswith("#/components/responses/"): |
| 906 | + ref_name = ref.split("/")[-1] |
| 907 | + resolved = comp_responses.get(ref_name) |
| 908 | + if resolved: |
| 909 | + # Replace with a copy so we don't mutate the shared component |
| 910 | + responses[status_code] = copy.deepcopy(resolved) |
| 911 | + # Also clean up any anchor-overlaid empty content |
| 912 | + elif "$ref" not in resp and "content" in resp: |
| 913 | + content = resp["content"] |
| 914 | + for ct, media in list(content.items()): |
| 915 | + s = media.get("schema", {}) |
| 916 | + if s.get("description") == "Empty response": |
| 917 | + del content[ct] |
| 918 | + if not content: |
| 919 | + del resp["content"] |
| 920 | + fixes.append("/files: inlined response definitions for GET and POST") |
912 | 921 |
|
913 | 922 | # 16. Missing type: object on schemas that have properties |
914 | 923 | obj_fixed = 0 |
|
0 commit comments