Accept universal format#253
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 47198f94eb
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "Codex (@codex) review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "Codex (@codex) address that feedback".
| fn detect_request(&self, payload: &Value) -> bool { | ||
| serde_json::from_value::<UniversalRequest>(payload.clone()).is_ok() |
There was a problem hiding this comment.
Apply Responses upgrade after universal request conversion
With UniversalAdapter now matching requests first, universal payloads reach transform_request without top-level reasoning_effort/tools, so the existing ChatCompletions→Responses upgrade check never triggers. For requests that carry these fields in params (the universal shape), the router can send a Chat Completions payload containing reasoning + tools that certain OpenAI reasoning models reject, while the semantically equivalent OpenAI-format input would be upgraded. Re-run the upgrade decision on the transformed OpenAI payload (or inspect universal params) to keep behavior consistent.
Useful? React with 👍 / 👎.
| "mistral" => Ok(ProviderFormat::Mistral), | ||
| "converse" | "bedrock" => Ok(ProviderFormat::Converse), | ||
| "responses" => Ok(ProviderFormat::Responses), | ||
| "universal" => Ok(ProviderFormat::Universal), |
There was a problem hiding this comment.
Do not accept
universal as a public format string yet
ProviderFormat::from_str now accepts "universal", but the newly added adapter still returns UnsupportedTargetFormat(Universal) for response conversion, so requests that select universal as output format fail at runtime instead of being rejected at parse/validation time. Until universal response transforms are implemented, exposing this parse path makes the API advertise a format it cannot serve end-to-end.
Useful? React with 👍 / 👎.
| ProviderFormat::ChatCompletions | ||
| | ProviderFormat::Mistral | ||
| | ProviderFormat::Universal | ||
| | ProviderFormat::Unknown => "chatcmpl-", |
There was a problem hiding this comment.
should we make the universal format have streaming chunks or ids, etc. that look different than `chatcmpl-
| ProviderFormat::Mistral => "mistral", | ||
| ProviderFormat::Converse => "bedrock", | ||
| ProviderFormat::Responses => "openai", // Responses API uses OpenAI provider | ||
| ProviderFormat::Universal => "universal", |
There was a problem hiding this comment.
i wonder what this looks like in practice. i'd like to see more testing with transforms or full on gateway PR before we merge.
There was a problem hiding this comment.
SG I won't merge until I get it running end to end with a UI form.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a0e218f442
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "Codex (@codex) review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "Codex (@codex) address that feedback".
| transformed: true; | ||
| data: TData; | ||
| sourceFormat: ProviderFormat; | ||
| }; |
There was a problem hiding this comment.
Return actual target format from transformRequest
The new TypeScript transformRequest API returns only sourceFormat, so callers cannot tell when the Rust transform upgraded the request to a different wire format (for example Chat Completions → Responses for reasoning+tools requests). In that case, SDK consumers will typically keep using the originally requested endpoint and can send a Responses-shaped payload to /v1/chat/completions, causing request failures despite a “successful” transform result.
Useful? React with 👍 / 👎.
| fn detect_response(&self, _payload: &Value) -> bool { | ||
| false | ||
| } | ||
|
|
||
| fn response_to_universal(&self, _payload: Value) -> Result<UniversalResponse, TransformError> { | ||
| Err(TransformError::UnsupportedSourceFormat( | ||
| ProviderFormat::Universal, | ||
| )) |
There was a problem hiding this comment.
Detect universal responses as transform sources
Although this commit exposes universal as a first-class format, the universal adapter explicitly disables response detection and always rejects response_to_universal, so transformResponse cannot accept universal-response JSON as input. Any attempt to convert a universal response into another format will fail with format detection/unsupported-source errors, which breaks the expected peer-format behavior for response transforms.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 04ef0db0bf
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "Codex (@codex) review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "Codex (@codex) address that feedback".
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, TS)] | ||
| #[ts(export)] |
There was a problem hiding this comment.
Accept canonical lowercase universal enum values
Now that UniversalAdapter deserializes incoming universal requests (detect_request/request_to_universal), ToolChoiceMode and ResponseFormatType only deserialize Rust variant names ("Auto", "JsonSchema") because they use default Serde enum casing. Inputs using the canonical lowercase strings already implied by this module (from_str accepts "auto", "json_schema", etc.) will fail universal detection and return UnableToDetectFormat during transform_request. Add Serde renames/aliases (or custom deserialization) so wire values match the documented lowercase forms.
Useful? React with 👍 / 👎.
| ProviderFormat::Mistral => "mistral", | ||
| ProviderFormat::Converse => "bedrock", | ||
| ProviderFormat::Responses => "openai", // Responses API uses OpenAI provider | ||
| ProviderFormat::Universal => "universal", |
There was a problem hiding this comment.
Do not default universal models to a non-existent provider alias
Mapping ProviderFormat::Universal to the alias string "universal" makes resolver fallback route selection produce an alias that is not registered by default, so catalog entries with format: universal and no explicit available_providers will fail later with NoProvider(...) instead of resolving to an executable provider path. This effectively makes universal-format models unroutable unless callers add a custom provider alias named universal.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f172aad5ab
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "Codex (@codex) review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "Codex (@codex) address that feedback".
Universal format should be something lingua can accept as a peer to the other ones.