Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions client/pyside6/components/provider_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def __init__(self, api, parent=None):
self.preset = QComboBox()
self.preset.addItem("智谱 AI(GLM-4.5-Flash)", "zhipu")
self.preset.addItem("OpenAI", "openai")
self.preset.addItem("OrcaRouter", "orcarouter")
self.preset.addItem("自定义 OpenAI 兼容服务", "custom")
self.preset.currentIndexChanged.connect(self._preset_changed)
self.name = QLineEdit()
Expand Down Expand Up @@ -115,6 +116,11 @@ def _preset_changed(self, _index: int) -> None:
self.base_url.setText("https://api.openai.com/v1")
self.model.setText("gpt-4.1-mini")
self.protocol.setCurrentIndex(0)
elif preset == "orcarouter":
self.name.setText("OrcaRouter")
self.base_url.setText("https://api.orcarouter.ai/v1")
self.model.setText("orcarouter/auto")
self.protocol.setCurrentIndex(0)

def refresh(self) -> None:
self.state.setText("正在加载模型服务…")
Expand Down
59 changes: 59 additions & 0 deletions tests/test_provider_presets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"""Offscreen preset coverage for the remote provider dialog.

The dialog is the desktop surface where users configure OpenAI-compatible
remote providers; named presets fill name/base_url/model so a provider is
used as a first-class service instead of an anonymous custom base URL.
"""

from __future__ import annotations

import os
import sys
from unittest.mock import MagicMock

os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
ROOT = os.path.dirname(os.path.dirname(__file__))
sys.path.insert(0, os.path.join(ROOT, "client", "pyside6"))

from components.provider_dialog import RemoteProviderDialog
from PySide6.QtWidgets import QApplication

_app = QApplication.instance() or QApplication([])


def _dialog() -> RemoteProviderDialog:
api = MagicMock()
api.list_remote_providers.return_value = []
return RemoteProviderDialog(api)


def test_orcarouter_preset_is_listed():
dialog = _dialog()
try:
presets = [dialog.preset.itemData(index) for index in range(dialog.preset.count())]
assert "orcarouter" in presets
finally:
dialog.shutdown_async_api()


def test_orcarouter_preset_fills_named_provider_fields():
dialog = _dialog()
try:
dialog.preset.setCurrentIndex(dialog.preset.findData("orcarouter"))
assert dialog.name.text() == "OrcaRouter"
assert dialog.base_url.text() == "https://api.orcarouter.ai/v1"
assert dialog.model.text() == "orcarouter/auto"
assert dialog.protocol.currentData() == "responses"
finally:
dialog.shutdown_async_api()


def test_openai_preset_is_preserved():
dialog = _dialog()
try:
dialog.preset.setCurrentIndex(dialog.preset.findData("openai"))
assert dialog.name.text() == "OpenAI"
assert dialog.base_url.text() == "https://api.openai.com/v1"
assert dialog.model.text() == "gpt-4.1-mini"
finally:
dialog.shutdown_async_api()