Skip to content

fix(models): let the request format own endpoint presets - #3651

Merged
bobleer merged 3 commits into
GCWing:mainfrom
bobleer:bob/model-config-endpoint-dedup
Oct 31, 2026
Merged

bobleer merged 3 commits into
GCWing:mainfrom
bobleer:bob/model-config-endpoint-dedup

Conversation

@bobleer

@bobleer bobleer commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

The model provider editor showed two dropdowns that both chose the API format. For the OpenAI preset, the endpoint picker offered "Chat Completions API" and "Responses API (default)" right next to the request format select (OpenAI (chat/completions) / OpenAI (responses)). The picker matched presets by base URL only, so it could show "Chat Completions" while the request format and the resolved URL were Responses.

The request format select is now the only control for the API format. The endpoint picker only chooses a host, region, or plan within that format.

Type and Areas

Type: bug fix / UI/UX

Areas: web UI (Settings → Models provider editor)

Motivation / Impact

  • Presets filtered by format: the endpoint picker lists only the presets for the selected request format. It is hidden when the only preset left is already selected. OpenAI shows no picker now. Zhipu, Moonshot, Qwen, MiniMax and similar providers still show it when several regions or plans share a format.
  • Selection by effective URL: the selected preset is matched by its resolved request URL. So https://api.openai.com/v1 + Responses now selects the Responses preset instead of the Chat Completions one.
  • Endpoint follows the format: before, switching the OpenAI preset from Responses to Chat Completions built https://api.openai.com/v1/responses/chat/completions. Now, when the base URL is still a preset, a format change moves it to the preset for the new format on the same host. Examples: /v1/responses → /v1, api.z.ai/api/paas/v4 → api.z.ai/api/anthropic. Custom URLs, forced # URLs, and moves that would change host, region, or plan are left alone. This also applies when editing a saved provider whose URL is still a preset.
  • Preset labels name region/plan only (en-US, zh-CN, zh-TW): labels such as "China - Anthropic Format" / "国内-Anthropic格式" repeated the format select once the list became format-scoped. They are now "China" / "国内", "Global (Z.AI)", "China - Coding Plan", and so on. The preset test now requires labels to be distinct within each request format, which is what the picker shows together. The Installer keeps its own catalog (it has no separate format select) and is unchanged.
  • Request URL helpers (resolveRequestUrl, previewRequestUrl, geminiBaseUrl) moved unchanged from ModelSettingsPage.tsx into modelRequestUrl.ts, next to the new preset helpers.

Remote scenarios: front-end form logic only. Nothing changes in commands, the wire format, or the persisted shape. Saved provider / base_url / request_url fields keep their meaning, so peer, remote-control, and dispatch paths are unaffected. Not run in a remote scenario.

Verification

  • pnpm --dir src/web-ui run test:run src/infrastructure/config/services/providerPresets.test.ts src/app/scenes/settings/pages/ai/: 19 files, 130 tests passed. New tests:
    • modelRequestUrl.test.ts covers format filtering, preset matching by effective URL, same-host remap, and that custom, #, cross-host, and cross-plan URLs are kept.
    • ModelSettingsPage.loading.test.tsx → request format and endpoint presets renders the real editor and checks three cases: OpenAI has no picker and its URL follows the format; Zhipu keeps a region picker after switching to Anthropic; a saved OpenAI provider moves /v1/responses → /v1 instead of appending a second path.
  • pnpm run type-check:web
  • pnpm run check:repo-hygiene
  • pnpm run i18n:audit: passed, 0 warnings

Not checked visually in the desktop app. The component tests run in jsdom.

Reviewer Notes

Checked refreshed upstream main and open PRs (including #3422 and #3230, which touch ModelSettingsPage.tsx) before implementation. None changes the endpoint or format pickers.

Checklist

  • This PR is focused and does not include secrets, temporary prompts, generated scratch files, or unrelated artifacts.
  • Relevant verification is recorded above, or skipped checks are explained.
  • User-facing strings, docs, and locales are updated where applicable.

The provider endpoint picker listed every preset, so OpenAI showed a
"Chat Completions / Responses" picker next to the request format select.
It matched presets by base URL only, which made the two disagree (Chat
Completions shown while Responses was requested), and switching the
format on the /v1/responses preset produced /v1/responses/chat/completions.

- Filter endpoint presets by the selected request format and hide the
  picker when only the current preset remains; region and plan presets
  that share a format keep the picker.
- Match the selected preset by its effective request URL.
- When the format changes, move a base URL that is still a preset to the
  same-host preset of the new format; custom, forced (#), cross-host and
  cross-plan URLs are left unchanged. Applies to saved providers too.
- Extract request URL helpers to modelRequestUrl.ts with unit tests.
The endpoint picker now lists one request format at a time, so preset
labels such as "China - Anthropic Format" repeated the request format
select. Labels now name only the region or plan; the preset test checks
that labels stay distinct within each request format.
@bobleer
bobleer merged commit 7d3c7c7 into GCWing:main Oct 31, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant