You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* feat: upstream providers[] + convert_from_map
- Replace upstream.provider with providers[]
- Add per-upstream convert_from_map for cross-format fallback
- Add config migration + UI editor updates
* test(frontend): add Vitest to prevent config/dashboard regressions
So config normalization, upstream defaults, and dashboard helpers stay reliable
as the UI evolves and CI runs.
* perf: cut overhead when tracking or capture is disabled
Avoid blocking Tokio threads on temp-file cleanup and reduce
allocations/background tasks for noop token tracking; also skip
redundant log capture-state loads.
|`enable_api_format_conversion`|`true`| Allow OpenAI/Anthropic/Gemini fallback via request/response body and SSE stream conversion. |
83
102
|`upstream_strategy`|`priority_fill_first`|`priority_fill_first` (default) keeps trying the highest-priority group in list order; `priority_round_robin` rotates within each priority group. |
84
103
85
104
### Upstream entries (`upstreams[]`)
86
105
| Field | Default | Notes |
87
106
| --- | --- | --- |
88
107
|`id`| required | Unique per upstream. |
89
-
|`provider`| required | One of `openai`, `openai-response`, `anthropic`, `gemini`, `kiro`. |
90
-
|`base_url`| required | Full base; overlapping path parts are de-duplicated. (`kiro` can be empty.) |
108
+
|`providers`| required | One upstream can serve multiple providers. Special providers `kiro/codex/antigravity` cannot be mixed with others. |
109
+
|`base_url`| required | Full base; overlapping path parts are de-duplicated. (`providers=["kiro"]` / `["codex"]` / `["antigravity"]` can be empty.) |
- Other paths: choose the provider with the highest configured priority; tie-break is `openai` > `openai-response` > `anthropic`.
105
-
-If the preferred provider is missing but `enable_api_format_conversion=true`, the proxy auto-converts request/response bodies and streams between supported formats (including SSE).
125
+
-Cross-format fallback/conversion is controlled by `upstreams[].convert_from_map` (no global switch). If a provider has no eligible upstream for the inbound format, it won't be selected.
106
126
- If `openai` is missing for `/v1/chat/completions`: fallback can be `openai-response`, `anthropic`, or `gemini` (priority-based; tie-break prefers `openai-response`).
107
127
- For `/v1/messages`: choose between `anthropic` and `kiro` by priority; tie-break uses upstream id. If the chosen provider returns a retryable error, the proxy will fall back to the other native provider (Anthropic ↔ Kiro) when configured.
108
-
- If neither `anthropic` nor `kiro` exists for `/v1/messages` and `enable_api_format_conversion=true`: fallback can be `openai-response`, `openai`, or `gemini`(priority-based; tie-break prefers `openai-response`).
128
+
- If neither `anthropic` nor `kiro` exists for `/v1/messages`: fallback can be `openai-response`, `openai`, or `gemini`when the target provider is allowed for `anthropic_messages` via `convert_from_map`.
109
129
- If `openai-response` is missing for `/v1/responses`: fallback can be `openai`, `anthropic`, or `gemini` (priority-based; tie-break prefers `openai`).
110
130
- If `gemini` is missing for `/v1beta/models/*:generateContent`: fallback can be `openai-response`, `openai`, or `anthropic` (priority-based; tie-break prefers `openai-response`).
0 commit comments