aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-09-18 20:29:36 +0200
committerDanilo M. <danix@danix.xyz>2026-09-18 20:29:36 +0200
commit4edb09f7b9737e0db89e227803c09017fe669599 (patch)
tree2f31625b004947497d79c0ffe603209aa1c9c478
parenta830263c8fa51922ecc44a5eab7ce21d29a1ba6a (diff)
downloadllamachat-4edb09f7b9737e0db89e227803c09017fe669599.tar.gz
llamachat-4edb09f7b9737e0db89e227803c09017fe669599.zip
feat: gate audio sends and add the default audio prompt
-rw-r--r--llamachat/ui.py56
1 files changed, 56 insertions, 0 deletions
diff --git a/llamachat/ui.py b/llamachat/ui.py
index 101f1a8..17e36b1 100644
--- a/llamachat/ui.py
+++ b/llamachat/ui.py
@@ -994,6 +994,53 @@ class ChatWindow(QMainWindow):
names.append(name)
return names
+ def audio_models(self) -> list[str]:
+ names = []
+ for i in range(self.model_box.count()):
+ name = self.model_box.itemData(i)
+ if self.model_info(name).audio is True:
+ names.append(name)
+ return names
+
+ def _ensure_audio_model(self) -> bool:
+ """Offer to switch to an audio-capable model. True when one is active.
+
+ Unlike vision, an unknown model is not given the benefit of the
+ doubt: audio input is rare and explicitly reported, so only a model
+ known to accept it is allowed to receive a recording.
+ """
+ if self.current_info().audio is True:
+ return True
+
+ candidates = self.audio_models()
+ if not candidates:
+ QMessageBox.warning(
+ self,
+ "No audio model",
+ "No model on the router reports audio input, so a recording "
+ "cannot be sent.",
+ )
+ return False
+
+ target = candidates[0]
+ answer = QMessageBox.question(
+ self,
+ "Switch model?",
+ f"Audio needs a model that accepts voice input.\n\n"
+ f"Switch to {target}?\n\n"
+ "The router unloads the current model to do this, so the next "
+ "reply will take several seconds to start.",
+ QMessageBox.Yes | QMessageBox.No,
+ QMessageBox.Yes,
+ )
+ if answer != QMessageBox.Yes:
+ return False
+
+ index = self.model_box.findData(target)
+ if index >= 0:
+ self.model_box.setCurrentIndex(index)
+ return True
+
def edit_model_settings(self, model_id: str | None = None) -> bool:
"""Open the dialog for one model. True when values were saved."""
model_id = model_id or self.current_model()
@@ -1296,6 +1343,15 @@ class ChatWindow(QMainWindow):
text = self.input.toPlainText().strip()
if not text and not self.attachments:
return
+
+ if any(a.kind == "audio" for a in self.attachments):
+ # A switch here changes the model, so this must run before the
+ # model is read below.
+ if not self._ensure_audio_model():
+ return
+ if not text:
+ text = backend.AUDIO_PROMPT
+
model = self.current_model()
if not model:
self.show_status("No model selected.", error=True)