fix(models): return inferred type from v1 models - #668
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem / background\n\nFollow-up to #661.\n\nProduction verification showed that #661 correctly fixed GET /v1/available_models, but the OpenAI-compatible GET /v1/models endpoint continued omitting data[].type. Clients then defaulted video models such as MiniMax-H3 and seedance2.0-pro to text.\n\n## Evidence / reproduction\n\nAfter #661 was deployed to 100% of both newapi-console and newapi-router:\n\nGET /v1/available_models returned:\n\n {\n "id": "MiniMax-H3",\n "type": "video",\n "supported_endpoint_types": ["video"]\n }\n\nGET /v1/models returned:\n\n {\n "id": "MiniMax-H3",\n "supported_endpoint_types": ["video"]\n }\n\nThe same mismatch was observed for seedance2.0-pro.\n\n## Root cause\n\nThe endpoints use separate response builders:\n\n- /v1/available_models calls AvailableModels(), which already assigns Type with availableModelType().\n- /v1/models calls ListModels() -> buildOpenAIModel(), which populated SupportedEndpointTypes but never assigned Type.\n\nBecause OpenAIModels.Type has json:"type,omitempty", the empty string was omitted from the response.\n\n## Scope / design\n\nAfter buildOpenAIModel() loads SupportedEndpointTypes, assign Type using the existing availableModelType() helper. This keeps both model-list endpoints on the same classification rules without duplicating inference logic.\n\nThe OpenAI response-shape contract test now requires the type field. A new integration regression creates the production-equivalent MiniMax-H3 metadata with a custom video endpoint, executes ListModels(), and asserts:\n\n- type == "video"\n- supported_endpoint_types == ["video"]\n\nNo schema, routing, provider adapter, billing, quota, or dependency changes.\n\n## Impact and risks\n\nRisk is low. The OpenAI-compatible /v1/models response gains the previously omitted type field for every model. Existing clients should tolerate additive response fields; clients already reading type receive a meaningful value instead of a missing/null fallback.\n\nMulti-node behavior is stateless and deterministic. During a rolling deployment, old and new router instances may temporarily differ on whether type is present.\n\n## Validation\n\nPassed:\n\n- go test ./controller -run 'Test(ListModelsClassifiesCustomVideoEndpoint|ListModelsKeepsOpenAIResponseShape|AvailableModelTypeInference|BuildOpenAIModel)' -count=1\n- git diff --check\n- GitNexus compare against origin/main: LOW risk, 2 files, no affected execution flows\n\nFull controller suite:\n\n- The response-shape failure introduced by this contract change was updated and now passes.\n- One unrelated existing failure remains and reproduces alone: TestGetChannelRetryMaterializationFailureClearsStaleMapAndReturnsError in controller/relay_channel_concurrency_test.go:466.\n\n## Acceptance criteria\n\n- GET /v1/models returns type="video" for MiniMax-H3 configured with supported endpoint video.\n- GET /v1/models returns type="video" for Seedance video models.\n- Existing non-video models continue using the shared image/audio/text inference rules.\n- GET /v1/available_models behavior remains unchanged.\n\n## Production deployment recommendation\n\n- Router deploy: required.\n- Reason: controller/model.go changes the runtime response for GET /v1/models served by API router nodes.\n- Other deploy targets: newapi-console should also deploy because it shares the Go image and serves the same route; newapi-web, Terraform, and Cloudflare are not involved.\n- Risk / validation: validate on staging that both /v1/models and /v1/available_models return type="video" for MiniMax-H3 and Seedance, then roll out all production router and console instances.