Apply a legacy order so we can easily see diff against what was generated

This commit is contained in:
Ashwin Bharambe 2025-11-14 10:39:00 -08:00
parent 9381673405
commit 69e1176ff8
8 changed files with 29509 additions and 29034 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,410 @@
#!/usr/bin/env python3
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the terms described in the LICENSE file in
# the root directory of this source tree.
"""
Temporary ordering helpers extracted from origin/main client-sdks/stainless/openapi.yml.
These lists help the new generator match the previous ordering so that diffs
remain readable while we debug schema content regressions. Remove once stable.
"""
# TODO: remove once generator output stabilizes
LEGACY_PATH_ORDER = ['/v1/batches',
'/v1/batches/{batch_id}',
'/v1/batches/{batch_id}/cancel',
'/v1/chat/completions',
'/v1/chat/completions/{completion_id}',
'/v1/completions',
'/v1/conversations',
'/v1/conversations/{conversation_id}',
'/v1/conversations/{conversation_id}/items',
'/v1/conversations/{conversation_id}/items/{item_id}',
'/v1/embeddings',
'/v1/files',
'/v1/files/{file_id}',
'/v1/files/{file_id}/content',
'/v1/health',
'/v1/inspect/routes',
'/v1/models',
'/v1/models/{model_id}',
'/v1/moderations',
'/v1/prompts',
'/v1/prompts/{prompt_id}',
'/v1/prompts/{prompt_id}/set-default-version',
'/v1/prompts/{prompt_id}/versions',
'/v1/providers',
'/v1/providers/{provider_id}',
'/v1/responses',
'/v1/responses/{response_id}',
'/v1/responses/{response_id}/input_items',
'/v1/safety/run-shield',
'/v1/scoring-functions',
'/v1/scoring-functions/{scoring_fn_id}',
'/v1/scoring/score',
'/v1/scoring/score-batch',
'/v1/shields',
'/v1/shields/{identifier}',
'/v1/tool-runtime/invoke',
'/v1/tool-runtime/list-tools',
'/v1/toolgroups',
'/v1/toolgroups/{toolgroup_id}',
'/v1/tools',
'/v1/tools/{tool_name}',
'/v1/vector-io/insert',
'/v1/vector-io/query',
'/v1/vector_stores',
'/v1/vector_stores/{vector_store_id}',
'/v1/vector_stores/{vector_store_id}/file_batches',
'/v1/vector_stores/{vector_store_id}/file_batches/{batch_id}',
'/v1/vector_stores/{vector_store_id}/file_batches/{batch_id}/cancel',
'/v1/vector_stores/{vector_store_id}/file_batches/{batch_id}/files',
'/v1/vector_stores/{vector_store_id}/files',
'/v1/vector_stores/{vector_store_id}/files/{file_id}',
'/v1/vector_stores/{vector_store_id}/files/{file_id}/content',
'/v1/vector_stores/{vector_store_id}/search',
'/v1/version',
'/v1beta/datasetio/append-rows/{dataset_id}',
'/v1beta/datasetio/iterrows/{dataset_id}',
'/v1beta/datasets',
'/v1beta/datasets/{dataset_id}',
'/v1alpha/eval/benchmarks',
'/v1alpha/eval/benchmarks/{benchmark_id}',
'/v1alpha/eval/benchmarks/{benchmark_id}/evaluations',
'/v1alpha/eval/benchmarks/{benchmark_id}/jobs',
'/v1alpha/eval/benchmarks/{benchmark_id}/jobs/{job_id}',
'/v1alpha/eval/benchmarks/{benchmark_id}/jobs/{job_id}/result',
'/v1alpha/inference/rerank',
'/v1alpha/post-training/job/artifacts',
'/v1alpha/post-training/job/cancel',
'/v1alpha/post-training/job/status',
'/v1alpha/post-training/jobs',
'/v1alpha/post-training/preference-optimize',
'/v1alpha/post-training/supervised-fine-tune']
LEGACY_SCHEMA_ORDER = ['Error',
'ListBatchesResponse',
'CreateBatchRequest',
'Batch',
'Order',
'ListOpenAIChatCompletionResponse',
'OpenAIAssistantMessageParam',
'OpenAIChatCompletionContentPartImageParam',
'OpenAIChatCompletionContentPartParam',
'OpenAIChatCompletionContentPartTextParam',
'OpenAIChatCompletionToolCall',
'OpenAIChatCompletionToolCallFunction',
'OpenAIChatCompletionUsage',
'OpenAIChoice',
'OpenAIChoiceLogprobs',
'OpenAIDeveloperMessageParam',
'OpenAIFile',
'OpenAIFileFile',
'OpenAIImageURL',
'OpenAIMessageParam',
'OpenAISystemMessageParam',
'OpenAITokenLogProb',
'OpenAIToolMessageParam',
'OpenAITopLogProb',
'OpenAIUserMessageParam',
'OpenAIJSONSchema',
'OpenAIResponseFormatJSONObject',
'OpenAIResponseFormatJSONSchema',
'OpenAIResponseFormatParam',
'OpenAIResponseFormatText',
'OpenAIChatCompletionRequestWithExtraBody',
'OpenAIChatCompletion',
'OpenAIChatCompletionChunk',
'OpenAIChoiceDelta',
'OpenAIChunkChoice',
'OpenAICompletionWithInputMessages',
'OpenAICompletionRequestWithExtraBody',
'OpenAICompletion',
'OpenAICompletionChoice',
'ConversationItem',
'OpenAIResponseAnnotationCitation',
'OpenAIResponseAnnotationContainerFileCitation',
'OpenAIResponseAnnotationFileCitation',
'OpenAIResponseAnnotationFilePath',
'OpenAIResponseAnnotations',
'OpenAIResponseContentPartRefusal',
'OpenAIResponseInputFunctionToolCallOutput',
'OpenAIResponseInputMessageContent',
'OpenAIResponseInputMessageContentFile',
'OpenAIResponseInputMessageContentImage',
'OpenAIResponseInputMessageContentText',
'OpenAIResponseMCPApprovalRequest',
'OpenAIResponseMCPApprovalResponse',
'OpenAIResponseMessage',
'OpenAIResponseOutputMessageContent',
'OpenAIResponseOutputMessageContentOutputText',
'OpenAIResponseOutputMessageFileSearchToolCall',
'OpenAIResponseOutputMessageFunctionToolCall',
'OpenAIResponseOutputMessageMCPCall',
'OpenAIResponseOutputMessageMCPListTools',
'OpenAIResponseOutputMessageWebSearchToolCall',
'CreateConversationRequest',
'Conversation',
'UpdateConversationRequest',
'ConversationDeletedResource',
'ConversationItemList',
'AddItemsRequest',
'ConversationItemDeletedResource',
'OpenAIEmbeddingsRequestWithExtraBody',
'OpenAIEmbeddingData',
'OpenAIEmbeddingUsage',
'OpenAIEmbeddingsResponse',
'OpenAIFilePurpose',
'ListOpenAIFileResponse',
'OpenAIFileObject',
'ExpiresAfter',
'OpenAIFileDeleteResponse',
'Response',
'HealthInfo',
'RouteInfo',
'ListRoutesResponse',
'OpenAIModel',
'OpenAIListModelsResponse',
'Model',
'ModelType',
'RunModerationRequest',
'ModerationObject',
'ModerationObjectResults',
'Prompt',
'ListPromptsResponse',
'CreatePromptRequest',
'UpdatePromptRequest',
'SetDefaultVersionRequest',
'ProviderInfo',
'ListProvidersResponse',
'ListOpenAIResponseObject',
'OpenAIResponseError',
'OpenAIResponseInput',
'OpenAIResponseInputToolFileSearch',
'OpenAIResponseInputToolFunction',
'OpenAIResponseInputToolWebSearch',
'OpenAIResponseObjectWithInput',
'OpenAIResponseOutput',
'OpenAIResponsePrompt',
'OpenAIResponseText',
'OpenAIResponseTool',
'OpenAIResponseToolMCP',
'OpenAIResponseUsage',
'ResponseGuardrailSpec',
'OpenAIResponseInputTool',
'OpenAIResponseInputToolMCP',
'CreateOpenaiResponseRequest',
'OpenAIResponseObject',
'OpenAIResponseContentPartOutputText',
'OpenAIResponseContentPartReasoningSummary',
'OpenAIResponseContentPartReasoningText',
'OpenAIResponseObjectStream',
'OpenAIResponseObjectStreamResponseCompleted',
'OpenAIResponseObjectStreamResponseContentPartAdded',
'OpenAIResponseObjectStreamResponseContentPartDone',
'OpenAIResponseObjectStreamResponseCreated',
'OpenAIResponseObjectStreamResponseFailed',
'OpenAIResponseObjectStreamResponseFileSearchCallCompleted',
'OpenAIResponseObjectStreamResponseFileSearchCallInProgress',
'OpenAIResponseObjectStreamResponseFileSearchCallSearching',
'OpenAIResponseObjectStreamResponseFunctionCallArgumentsDelta',
'OpenAIResponseObjectStreamResponseFunctionCallArgumentsDone',
'OpenAIResponseObjectStreamResponseInProgress',
'OpenAIResponseObjectStreamResponseIncomplete',
'OpenAIResponseObjectStreamResponseMcpCallArgumentsDelta',
'OpenAIResponseObjectStreamResponseMcpCallArgumentsDone',
'OpenAIResponseObjectStreamResponseMcpCallCompleted',
'OpenAIResponseObjectStreamResponseMcpCallFailed',
'OpenAIResponseObjectStreamResponseMcpCallInProgress',
'OpenAIResponseObjectStreamResponseMcpListToolsCompleted',
'OpenAIResponseObjectStreamResponseMcpListToolsFailed',
'OpenAIResponseObjectStreamResponseMcpListToolsInProgress',
'OpenAIResponseObjectStreamResponseOutputItemAdded',
'OpenAIResponseObjectStreamResponseOutputItemDone',
'OpenAIResponseObjectStreamResponseOutputTextAnnotationAdded',
'OpenAIResponseObjectStreamResponseOutputTextDelta',
'OpenAIResponseObjectStreamResponseOutputTextDone',
'OpenAIResponseObjectStreamResponseReasoningSummaryPartAdded',
'OpenAIResponseObjectStreamResponseReasoningSummaryPartDone',
'OpenAIResponseObjectStreamResponseReasoningSummaryTextDelta',
'OpenAIResponseObjectStreamResponseReasoningSummaryTextDone',
'OpenAIResponseObjectStreamResponseReasoningTextDelta',
'OpenAIResponseObjectStreamResponseReasoningTextDone',
'OpenAIResponseObjectStreamResponseRefusalDelta',
'OpenAIResponseObjectStreamResponseRefusalDone',
'OpenAIResponseObjectStreamResponseWebSearchCallCompleted',
'OpenAIResponseObjectStreamResponseWebSearchCallInProgress',
'OpenAIResponseObjectStreamResponseWebSearchCallSearching',
'OpenAIDeleteResponseObject',
'ListOpenAIResponseInputItem',
'RunShieldRequest',
'RunShieldResponse',
'SafetyViolation',
'ViolationLevel',
'AggregationFunctionType',
'ArrayType',
'BasicScoringFnParams',
'BooleanType',
'ChatCompletionInputType',
'CompletionInputType',
'JsonType',
'LLMAsJudgeScoringFnParams',
'NumberType',
'ObjectType',
'RegexParserScoringFnParams',
'ScoringFn',
'ScoringFnParams',
'ScoringFnParamsType',
'StringType',
'UnionType',
'ListScoringFunctionsResponse',
'ScoreRequest',
'ScoreResponse',
'ScoringResult',
'ScoreBatchRequest',
'ScoreBatchResponse',
'Shield',
'ListShieldsResponse',
'InvokeToolRequest',
'ImageContentItem',
'InterleavedContent',
'InterleavedContentItem',
'TextContentItem',
'ToolInvocationResult',
'URL',
'ToolDef',
'ListToolDefsResponse',
'ToolGroup',
'ListToolGroupsResponse',
'Chunk',
'ChunkMetadata',
'InsertChunksRequest',
'QueryChunksRequest',
'QueryChunksResponse',
'VectorStoreFileCounts',
'VectorStoreListResponse',
'VectorStoreObject',
'VectorStoreChunkingStrategy',
'VectorStoreChunkingStrategyAuto',
'VectorStoreChunkingStrategyStatic',
'VectorStoreChunkingStrategyStaticConfig',
'OpenAICreateVectorStoreRequestWithExtraBody',
'OpenaiUpdateVectorStoreRequest',
'VectorStoreDeleteResponse',
'OpenAICreateVectorStoreFileBatchRequestWithExtraBody',
'VectorStoreFileBatchObject',
'VectorStoreFileStatus',
'VectorStoreFileLastError',
'VectorStoreFileObject',
'VectorStoreFilesListInBatchResponse',
'VectorStoreListFilesResponse',
'OpenaiAttachFileToVectorStoreRequest',
'OpenaiUpdateVectorStoreFileRequest',
'VectorStoreFileDeleteResponse',
'bool',
'VectorStoreContent',
'VectorStoreFileContentResponse',
'OpenaiSearchVectorStoreRequest',
'VectorStoreSearchResponse',
'VectorStoreSearchResponsePage',
'VersionInfo',
'AppendRowsRequest',
'PaginatedResponse',
'Dataset',
'RowsDataSource',
'URIDataSource',
'ListDatasetsResponse',
'Benchmark',
'ListBenchmarksResponse',
'BenchmarkConfig',
'GreedySamplingStrategy',
'ModelCandidate',
'SamplingParams',
'SystemMessage',
'TopKSamplingStrategy',
'TopPSamplingStrategy',
'EvaluateRowsRequest',
'EvaluateResponse',
'RunEvalRequest',
'Job',
'RerankRequest',
'RerankData',
'RerankResponse',
'Checkpoint',
'PostTrainingJobArtifactsResponse',
'PostTrainingMetric',
'CancelTrainingJobRequest',
'PostTrainingJobStatusResponse',
'ListPostTrainingJobsResponse',
'DPOAlignmentConfig',
'DPOLossType',
'DataConfig',
'DatasetFormat',
'EfficiencyConfig',
'OptimizerConfig',
'OptimizerType',
'TrainingConfig',
'PreferenceOptimizeRequest',
'PostTrainingJob',
'AlgorithmConfig',
'LoraFinetuningConfig',
'QATFinetuningConfig',
'SupervisedFineTuneRequest',
'RegisterModelRequest',
'ParamType',
'RegisterScoringFunctionRequest',
'RegisterShieldRequest',
'RegisterToolGroupRequest',
'DataSource',
'RegisterDatasetRequest',
'RegisterBenchmarkRequest']
LEGACY_RESPONSE_ORDER = ['BadRequest400', 'TooManyRequests429', 'InternalServerError500', 'DefaultError']
LEGACY_TAG_ORDER = ['Agents',
'Batches',
'Benchmarks',
'Conversations',
'DatasetIO',
'Datasets',
'Eval',
'Files',
'Inference',
'Inspect',
'Models',
'PostTraining (Coming Soon)',
'Prompts',
'Providers',
'Safety',
'Scoring',
'ScoringFunctions',
'Shields',
'ToolGroups',
'ToolRuntime',
'VectorIO']
LEGACY_TAG_GROUPS = [{'name': 'Operations',
'tags': ['Agents',
'Batches',
'Benchmarks',
'Conversations',
'DatasetIO',
'Datasets',
'Eval',
'Files',
'Inference',
'Inspect',
'Models',
'PostTraining (Coming Soon)',
'Prompts',
'Providers',
'Safety',
'Scoring',
'ScoringFunctions',
'Shields',
'ToolGroups',
'ToolRuntime',
'VectorIO']}]

View file

@ -141,6 +141,7 @@ def generate_openapi_spec(output_dir: str) -> dict[str, Any]:
for schema, _ in schemas_to_validate:
schema_transforms._fix_schema_issues(schema)
schema_transforms._apply_legacy_sorting(schema)
print("\n🔍 Validating generated schemas...")
failed_schemas = [

View file

@ -9,6 +9,7 @@ Schema transformations and fixes for OpenAPI generation.
"""
import copy
from collections import OrderedDict
from pathlib import Path
from typing import Any
@ -17,6 +18,13 @@ from openapi_spec_validator import validate_spec
from openapi_spec_validator.exceptions import OpenAPISpecValidatorError
from . import endpoints, schema_collection
from ._legacy_order import (
LEGACY_PATH_ORDER,
LEGACY_RESPONSE_ORDER,
LEGACY_SCHEMA_ORDER,
LEGACY_TAG_GROUPS,
LEGACY_TAG_ORDER,
)
from .state import _extra_body_fields
@ -821,6 +829,62 @@ def _write_yaml_file(file_path: Path, schema: dict[str, Any]) -> None:
f.writelines(cleaned_lines)
def _apply_legacy_sorting(openapi_schema: dict[str, Any]) -> dict[str, Any]:
"""
Temporarily match the legacy ordering from origin/main so diffs are easier to read.
Remove this once the generator output stabilizes and we no longer need legacy diffs.
"""
def order_mapping(data: dict[str, Any], priority: list[str]) -> OrderedDict[str, Any]:
ordered: OrderedDict[str, Any] = OrderedDict()
for key in priority:
if key in data:
ordered[key] = data[key]
for key, value in data.items():
if key not in ordered:
ordered[key] = value
return ordered
paths = openapi_schema.get("paths")
if isinstance(paths, dict):
openapi_schema["paths"] = order_mapping(paths, LEGACY_PATH_ORDER)
components = openapi_schema.setdefault("components", {})
schemas = components.get("schemas")
if isinstance(schemas, dict):
components["schemas"] = order_mapping(schemas, LEGACY_SCHEMA_ORDER)
responses = components.get("responses")
if isinstance(responses, dict):
components["responses"] = order_mapping(responses, LEGACY_RESPONSE_ORDER)
tags = openapi_schema.get("tags")
if isinstance(tags, list):
tag_priority = {name: idx for idx, name in enumerate(LEGACY_TAG_ORDER)}
def tag_sort(tag_obj: dict[str, Any]) -> tuple[int, int | str]:
name = tag_obj.get("name", "")
if name in tag_priority:
return (0, tag_priority[name])
return (1, name)
openapi_schema["tags"] = sorted(tags, key=tag_sort)
tag_groups = openapi_schema.get("x-tagGroups")
if isinstance(tag_groups, list) and LEGACY_TAG_GROUPS:
legacy_tags = LEGACY_TAG_GROUPS[0].get("tags", [])
tag_priority = {name: idx for idx, name in enumerate(legacy_tags)}
for group in tag_groups:
group_tags = group.get("tags")
if isinstance(group_tags, list):
group["tags"] = sorted(
group_tags,
key=lambda name: (0, tag_priority[name]) if name in tag_priority else (1, name),
)
openapi_schema["x-tagGroups"] = tag_groups
return openapi_schema
def _fix_schema_issues(openapi_schema: dict[str, Any]) -> dict[str, Any]:
"""Fix common schema issues: exclusiveMinimum, null defaults, and add titles to unions."""
# Convert anyOf with const values to enums across the entire schema