feat(ai): enforce direct image edit contract
This commit is contained in:
@@ -36,6 +36,7 @@ class SettingsTab(QWidget):
|
||||
BACKEND_ITEMS = [("默认网关", "cmhub"), ("自定义网关", "direct")]
|
||||
CATEGORY_ITEMS = [("文本", "text"), ("图像", "image")]
|
||||
API_TYPE_ITEMS = [("chat", "chat"), ("images_edits", "images_edits"), ("auto", "auto")]
|
||||
IMAGE_API_TYPE_ITEMS = [("OpenAI 图片编辑接口", "images_edits")]
|
||||
RESOLUTION_ITEMS = ["512", "1k", "2k", "4k"]
|
||||
|
||||
def __init__(
|
||||
@@ -431,6 +432,7 @@ class SettingsTab(QWidget):
|
||||
self.delete_model_button.clicked.connect(self.delete_model)
|
||||
self.save_model_button.clicked.connect(self.save_model)
|
||||
self.test_connection_button.clicked.connect(self.test_connection)
|
||||
self.category_combo.currentIndexChanged.connect(self._on_model_category_changed)
|
||||
self.gateway_default_button.toggled.connect(self._on_gateway_source_toggled)
|
||||
self.gateway_custom_button.toggled.connect(self._on_gateway_source_toggled)
|
||||
self.cmhub_refresh_button.clicked.connect(self.refresh_cmhub_models)
|
||||
@@ -667,6 +669,8 @@ class SettingsTab(QWidget):
|
||||
label = f"{model['name']} · {self._category_label(model['category'])}"
|
||||
if not model.get("enabled", True):
|
||||
label += " · 已停用"
|
||||
if model.get("category") == "image" and not appconfig.is_image_edit_model(model):
|
||||
label += " · 当前图片模型不支持 OpenAI 图片编辑接口"
|
||||
self.model_combo.addItem(label, model["name"])
|
||||
index = self.model_combo.findData(current)
|
||||
self.model_combo.setCurrentIndex(index if index >= 0 else (0 if self.models else -1))
|
||||
@@ -765,6 +769,7 @@ class SettingsTab(QWidget):
|
||||
ai_models_path=self.ai_models_path,
|
||||
db_path=_database_path(config=self.config),
|
||||
diagnostic_log_dir=diagnostics.DEFAULT_LOG_DIR,
|
||||
check_image_config=model.get("category") == "image",
|
||||
)
|
||||
worker.finished.connect(self._on_test_finished)
|
||||
worker.failed.connect(self._on_test_failed)
|
||||
@@ -773,8 +778,12 @@ class SettingsTab(QWidget):
|
||||
self.test_worker = worker
|
||||
self.test_thread = thread
|
||||
self._set_test_running(True)
|
||||
self.test_result_label.setText("正在测试连接...")
|
||||
self._set_status(f"正在测试 AI 模型连接:{model['name']}")
|
||||
if model.get("category") == "image":
|
||||
self.test_result_label.setText("正在检查图片配置...")
|
||||
self._set_status(f"正在检查图片模型配置:{model['name']}")
|
||||
else:
|
||||
self.test_result_label.setText("正在测试连接...")
|
||||
self._set_status(f"正在测试 AI 模型连接:{model['name']}")
|
||||
thread.start()
|
||||
|
||||
def save_app_settings(self, checked=False):
|
||||
@@ -1010,7 +1019,10 @@ class SettingsTab(QWidget):
|
||||
combo.clear()
|
||||
for model in self.models:
|
||||
if model.get("category") == category and model.get("enabled", True):
|
||||
combo.addItem(model.get("name", ""), model.get("name", ""))
|
||||
label = model.get("name", "")
|
||||
if category == "image" and not appconfig.is_image_edit_model(model):
|
||||
label += " · 当前图片模型不支持 OpenAI 图片编辑接口"
|
||||
combo.addItem(label, model.get("name", ""))
|
||||
if combo.count() == 0:
|
||||
combo.addItem("无可用模型", None)
|
||||
index = combo.findData(selected)
|
||||
@@ -1058,6 +1070,32 @@ class SettingsTab(QWidget):
|
||||
"extra_body": dict(extra_body),
|
||||
}
|
||||
|
||||
def _on_model_category_changed(self, index=None):
|
||||
category = self.category_combo.currentData() or "text"
|
||||
current_type = self.api_type_combo.currentData()
|
||||
if category == "image":
|
||||
self._set_api_type_options(category, selected="images_edits")
|
||||
else:
|
||||
self._set_api_type_options(category, selected=current_type or "chat")
|
||||
self._update_button_state()
|
||||
|
||||
def _set_api_type_options(self, category, selected=None):
|
||||
"""Render category-specific API choices without mutating legacy models."""
|
||||
|
||||
self.api_type_combo.blockSignals(True)
|
||||
self.api_type_combo.clear()
|
||||
if category == "image":
|
||||
# Keep a stored legacy choice visible so users can correct it explicitly.
|
||||
if selected and selected != "images_edits":
|
||||
self.api_type_combo.addItem("当前不支持(%s)" % selected, selected)
|
||||
items = self.IMAGE_API_TYPE_ITEMS
|
||||
else:
|
||||
items = self.API_TYPE_ITEMS
|
||||
for label, value in items:
|
||||
self.api_type_combo.addItem(label, value)
|
||||
self._set_combo_by_data(self.api_type_combo, selected)
|
||||
self.api_type_combo.blockSignals(False)
|
||||
|
||||
def _populate_form(self, model):
|
||||
widgets = [
|
||||
self.enabled_checkbox,
|
||||
@@ -1075,7 +1113,7 @@ class SettingsTab(QWidget):
|
||||
self.enabled_checkbox.setChecked(False)
|
||||
self.name_edit.clear()
|
||||
self.category_combo.setCurrentIndex(0)
|
||||
self.api_type_combo.setCurrentIndex(0)
|
||||
self._set_api_type_options("text", selected="chat")
|
||||
self.model_id_edit.clear()
|
||||
self.url_edit.clear()
|
||||
self.api_key_edit.clear()
|
||||
@@ -1084,7 +1122,10 @@ class SettingsTab(QWidget):
|
||||
self.enabled_checkbox.setChecked(bool(model.get("enabled", True)))
|
||||
self.name_edit.setText(model.get("name", ""))
|
||||
self._set_combo_by_data(self.category_combo, model.get("category", "text"))
|
||||
self._set_combo_by_data(self.api_type_combo, model.get("api_type", "auto"))
|
||||
self._set_api_type_options(
|
||||
model.get("category", "text"),
|
||||
selected=model.get("api_type", "auto"),
|
||||
)
|
||||
self.model_id_edit.setText(model.get("model", ""))
|
||||
self.url_edit.setText(model.get("url", ""))
|
||||
self.api_key_edit.setText(model.get("api_key", ""))
|
||||
@@ -1118,6 +1159,13 @@ class SettingsTab(QWidget):
|
||||
has_model and not testing and self._can_delete_model(self._current_model())
|
||||
)
|
||||
self.test_connection_button.setEnabled(has_model and not testing)
|
||||
if not testing:
|
||||
model = self._current_model()
|
||||
self.test_connection_button.setText(
|
||||
"检查图片配置"
|
||||
if model is not None and model.get("category") == "image"
|
||||
else "测试连接"
|
||||
)
|
||||
|
||||
def _set_test_running(self, running):
|
||||
self._update_button_state()
|
||||
@@ -1132,7 +1180,11 @@ class SettingsTab(QWidget):
|
||||
self._set_test_running(False)
|
||||
|
||||
def _on_test_finished(self, payload):
|
||||
if payload.get("ok"):
|
||||
if payload.get("check_only") and payload.get("ok"):
|
||||
message = f"图片配置检查通过:{payload.get('name')}"
|
||||
elif payload.get("check_only"):
|
||||
message = "图片配置检查失败:%s" % (payload.get("error") or "配置不完整")
|
||||
elif payload.get("ok"):
|
||||
status = payload.get("status")
|
||||
suffix = f"(HTTP {status})" if status else ""
|
||||
message = f"测试连接成功:{payload.get('name')}{suffix}"
|
||||
|
||||
Reference in New Issue
Block a user