mirror of
https://github.com/yusufipk/dikte.git
synced 2026-09-11 10:56:10 +00:00
Fetch OpenCode Go's catalog as the settings window opens
Codex already refreshes its boxes from the source at open, so the built-in list is never the whole truth for longer than a window takes to build. OpenCode Go now gets the same courtesy: one request to /models on a background thread, both of its boxes refilled with the picked model kept, skipped entirely when there is no key to send.
This commit is contained in:
@@ -569,6 +569,7 @@ class SettingsWindow(QDialog):
|
|||||||
_models_loaded = pyqtSignal(list, str, str)
|
_models_loaded = pyqtSignal(list, str, str)
|
||||||
_transcribe_models_loaded = pyqtSignal(list, str)
|
_transcribe_models_loaded = pyqtSignal(list, str)
|
||||||
_codex_models_loaded = pyqtSignal(list)
|
_codex_models_loaded = pyqtSignal(list)
|
||||||
|
_opencode_models_loaded = pyqtSignal(list)
|
||||||
# Which key was tested, whether it worked, and what to write under it.
|
# Which key was tested, whether it worked, and what to write under it.
|
||||||
_test_done = pyqtSignal(str, bool, str)
|
_test_done = pyqtSignal(str, bool, str)
|
||||||
# The release that was found, or None, and what went wrong instead.
|
# The release that was found, or None, and what went wrong instead.
|
||||||
@@ -628,6 +629,7 @@ class SettingsWindow(QDialog):
|
|||||||
self._models_loaded.connect(self._on_models_loaded)
|
self._models_loaded.connect(self._on_models_loaded)
|
||||||
self._transcribe_models_loaded.connect(self._on_transcribe_models_loaded)
|
self._transcribe_models_loaded.connect(self._on_transcribe_models_loaded)
|
||||||
self._codex_models_loaded.connect(self._on_codex_models_loaded)
|
self._codex_models_loaded.connect(self._on_codex_models_loaded)
|
||||||
|
self._opencode_models_loaded.connect(self._on_opencode_models_loaded)
|
||||||
self._test_done.connect(self._on_test_done)
|
self._test_done.connect(self._on_test_done)
|
||||||
self._update_checked.connect(self._on_update_checked)
|
self._update_checked.connect(self._on_update_checked)
|
||||||
self.transcriber.progress.connect(self._on_file_progress)
|
self.transcriber.progress.connect(self._on_file_progress)
|
||||||
@@ -639,6 +641,7 @@ class SettingsWindow(QDialog):
|
|||||||
self.meetings.failed.connect(self._on_minutes_failed)
|
self.meetings.failed.connect(self._on_minutes_failed)
|
||||||
self._load()
|
self._load()
|
||||||
self._load_codex_models()
|
self._load_codex_models()
|
||||||
|
self._load_opencode_models()
|
||||||
# Connected after the load, so that filling the boxes in is not taken
|
# Connected after the load, so that filling the boxes in is not taken
|
||||||
# for the user ticking them.
|
# for the user ticking them.
|
||||||
self.file_timestamps.toggled.connect(self._remember_file_choices)
|
self.file_timestamps.toggled.connect(self._remember_file_choices)
|
||||||
@@ -2080,6 +2083,37 @@ class SettingsWindow(QDialog):
|
|||||||
combo.addItem(name, name)
|
combo.addItem(name, name)
|
||||||
combo.setCurrentText(current)
|
combo.setCurrentText(current)
|
||||||
|
|
||||||
|
def _load_opencode_models(self):
|
||||||
|
"""Ask OpenCode Go for its catalog of the day, off the interface thread.
|
||||||
|
|
||||||
|
The same courtesy Codex gets: the built-in list is only a starting
|
||||||
|
point, so the boxes are refreshed from the source as the window opens.
|
||||||
|
Skipped without a key, so a machine that never touched OpenCode Go
|
||||||
|
sends it nothing; the Fetch button stays for a key typed in just now.
|
||||||
|
"""
|
||||||
|
key = self.conf.opencode_key()
|
||||||
|
if not key:
|
||||||
|
return
|
||||||
|
|
||||||
|
def work():
|
||||||
|
try:
|
||||||
|
found = api.openai_models(key, self.conf["opencode_base_url"],
|
||||||
|
"OpenCode Go")
|
||||||
|
except api.ApiError:
|
||||||
|
# The window is only opening; the Test button says what failed.
|
||||||
|
return
|
||||||
|
if found:
|
||||||
|
self._opencode_models_loaded.emit(found)
|
||||||
|
|
||||||
|
threading.Thread(target=work, daemon=True).start()
|
||||||
|
|
||||||
|
def _on_opencode_models_loaded(self, models):
|
||||||
|
for combo in (self.cleanup_opencode_model, self.assistant_opencode_model):
|
||||||
|
current = combo.currentText()
|
||||||
|
combo.clear()
|
||||||
|
combo.addItems(models)
|
||||||
|
combo.setCurrentText(current)
|
||||||
|
|
||||||
def _test_openai(self):
|
def _test_openai(self):
|
||||||
key, base = self._typed_key("openai")
|
key, base = self._typed_key("openai")
|
||||||
self._test_key("openai", lambda: t(
|
self._test_key("openai", lambda: t(
|
||||||
|
|||||||
+21
-1
@@ -135,6 +135,8 @@ class Settings(DikteTest):
|
|||||||
"_load_transcribe_models"))
|
"_load_transcribe_models"))
|
||||||
self.enterContext(mock.patch.object(settings_ui.SettingsWindow,
|
self.enterContext(mock.patch.object(settings_ui.SettingsWindow,
|
||||||
"_load_codex_models"))
|
"_load_codex_models"))
|
||||||
|
self.enterContext(mock.patch.object(settings_ui.SettingsWindow,
|
||||||
|
"_load_opencode_models"))
|
||||||
# The local model boxes fetch their own list the moment they are shown,
|
# The local model boxes fetch their own list the moment they are shown,
|
||||||
# from a thread, which is nobody's test failing but a real request.
|
# from a thread, which is nobody's test failing but a real request.
|
||||||
self.enterContext(mock.patch.object(settings_ui.LocalModelBox,
|
self.enterContext(mock.patch.object(settings_ui.LocalModelBox,
|
||||||
@@ -285,6 +287,20 @@ class Settings(DikteTest):
|
|||||||
self.assertEqual(window.cleanup_codex_model.currentText(),
|
self.assertEqual(window.cleanup_codex_model.currentText(),
|
||||||
"my-own-model")
|
"my-own-model")
|
||||||
|
|
||||||
|
def test_opencode_answering_refills_both_of_its_boxes(self):
|
||||||
|
"""The catalog fetched at open replaces the built-in list in the
|
||||||
|
cleanup and agent boxes alike, and neither loses what was picked."""
|
||||||
|
conf = self.config(cleanup_opencode_model="my-own-model")
|
||||||
|
window = self.window(conf)
|
||||||
|
window._on_opencode_models_loaded(["glm-9", "kimi-k9"])
|
||||||
|
for combo in (window.cleanup_opencode_model,
|
||||||
|
window.assistant_opencode_model):
|
||||||
|
with self.subTest(combo=combo.objectName() or "combo"):
|
||||||
|
offered = [combo.itemText(i) for i in range(combo.count())]
|
||||||
|
self.assertEqual(offered, ["glm-9", "kimi-k9"])
|
||||||
|
self.assertEqual(window.cleanup_opencode_model.currentText(),
|
||||||
|
"my-own-model")
|
||||||
|
|
||||||
def test_a_fetched_opencode_list_lands_in_opencode_s_own_box(self):
|
def test_a_fetched_opencode_list_lands_in_opencode_s_own_box(self):
|
||||||
"""The OpenRouter and meeting boxes are not refilled by another
|
"""The OpenRouter and meeting boxes are not refilled by another
|
||||||
provider's catalog, and the picked model survives the refill."""
|
provider's catalog, and the picked model survives the refill."""
|
||||||
@@ -1026,7 +1042,9 @@ class MeetingSources(DikteTest):
|
|||||||
mock.patch.object(settings_ui.SettingsWindow,
|
mock.patch.object(settings_ui.SettingsWindow,
|
||||||
"_load_transcribe_models"), \
|
"_load_transcribe_models"), \
|
||||||
mock.patch.object(settings_ui.SettingsWindow,
|
mock.patch.object(settings_ui.SettingsWindow,
|
||||||
"_load_codex_models"):
|
"_load_codex_models"), \
|
||||||
|
mock.patch.object(settings_ui.SettingsWindow,
|
||||||
|
"_load_opencode_models"):
|
||||||
window = settings_ui.SettingsWindow(cfg.Config())
|
window = settings_ui.SettingsWindow(cfg.Config())
|
||||||
self.addCleanup(window.deleteLater)
|
self.addCleanup(window.deleteLater)
|
||||||
self.addCleanup(window.close)
|
self.addCleanup(window.close)
|
||||||
@@ -1058,6 +1076,8 @@ class LocalModels(DikteTest):
|
|||||||
# And one with Codex on it would ask it for its model list.
|
# And one with Codex on it would ask it for its model list.
|
||||||
self.enterContext(mock.patch.object(settings_ui.SettingsWindow,
|
self.enterContext(mock.patch.object(settings_ui.SettingsWindow,
|
||||||
"_load_codex_models"))
|
"_load_codex_models"))
|
||||||
|
self.enterContext(mock.patch.object(settings_ui.SettingsWindow,
|
||||||
|
"_load_opencode_models"))
|
||||||
|
|
||||||
def window(self, conf):
|
def window(self, conf):
|
||||||
window = settings_ui.SettingsWindow(conf)
|
window = settings_ui.SettingsWindow(conf)
|
||||||
|
|||||||
Reference in New Issue
Block a user