feat(local-llm): Skill-Ausführung via local = kein TTS (speak=False)
Wenn das lokale LLM einen echten Skill (run_*, z.B. Spotify) ausführt, ist es
ein Steuerbefehl — genau wie Fast-Path. Jetzt speak=False: kein Vorlesen, und
die App beendet direkt (STOP) statt ins 30s-Gespräch zu gehen. Deckt den Fall
ab, wo Whisper sich verhört ("Nächster Slick") und local statt Fast-Path
den Skill auffängt.
Info-Tools (web_search/memory_search/trigger_timer) zählen NICHT — deren
Antwort/Bestätigung bleibt gesprochen. Reiner Brain-Fix: die App liest speak
bereits (2b48e5c), kein neuer APK nötig.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+14
-1
@@ -1226,6 +1226,11 @@ class Agent:
|
||||
cfg = router_mod.load_config()
|
||||
if not router_mod.should_try_local(user_message, cfg):
|
||||
return None
|
||||
# Merker: hat dieser lokale Turn einen echten Skill (run_*) ausgefuehrt?
|
||||
# Dann ist es ein Steuerbefehl (z.B. Spotify) → NICHT vorlesen (speak=
|
||||
# False), wie beim Fast-Path. Info-Tools (web_search/memory_search/
|
||||
# trigger_timer) zaehlen NICHT — deren Antwort/Bestaetigung wird gesprochen.
|
||||
self._local_turn_executed_skill = False
|
||||
local_only = bool(cfg.get("localOnly"))
|
||||
local_model = cfg.get("localLlmModel") or "qwen3-8b" # B0.5: llama-swap-Key
|
||||
tools = self._build_local_tools() # B1b: kuratierte Tools
|
||||
@@ -1273,6 +1278,10 @@ class Agent:
|
||||
logger.info("[router] lokal Tool-Call: %s(%s)", tname,
|
||||
", ".join(targs.keys()))
|
||||
tresult = self._dispatch_tool(tname, targs)
|
||||
# Echter Skill (run_*) ausgefuehrt = Steuerbefehl → nachher
|
||||
# nicht vorlesen. Nur bei Erfolg (Fehler → eskaliert eh).
|
||||
if tname.startswith("run_") and not self._local_tool_failed(tname, tresult):
|
||||
self._local_turn_executed_skill = True
|
||||
if self._local_tool_failed(tname, tresult):
|
||||
had_error = True
|
||||
messages.append({"role": "tool",
|
||||
@@ -1383,7 +1392,11 @@ class Agent:
|
||||
# teure Claude-Aufbau + Tool-Loop wird uebersprungen. Sonst None → Claude.
|
||||
local_reply = self._try_local_fast_lane(user_message, active_project_id)
|
||||
if local_reply is not None:
|
||||
return local_reply, "local", True # ARIA-Antwort → vorlesen ok
|
||||
# Hat local einen echten Skill (run_*) ausgefuehrt → Steuerbefehl,
|
||||
# NICHT vorlesen (kein TTS, App beendet direkt statt 30s-Gespraech) —
|
||||
# genau wie Fast-Path. Sonst normale gesprochene Antwort.
|
||||
speak = not getattr(self, "_local_turn_executed_skill", False)
|
||||
return local_reply, "local", speak
|
||||
|
||||
# 2. Hot Memory (alle pinned Punkte)
|
||||
hot = self.store.list_pinned()
|
||||
|
||||
Reference in New Issue
Block a user