From 2c1de6705b4817764f3c64c976a08477d794898e Mon Sep 17 00:00:00 2001 From: duffyduck Date: Sat, 11 Jul 2026 21:45:27 +0200 Subject: [PATCH] feat(skills): speak-Flag gilt jetzt auch im Claude-Pfad MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vorher gab Claude immer speak=true zurück — führte Claude einen speak=false- Steuerbefehl aus (z.B. "spiele auf duffy desktop weiter"), wurde die Antwort trotzdem vorgelesen + 30s. Jetzt konsistent zu Fast-Path/local: führt Claude einen run_*-Skill mit speak=false erfolgreich aus → speak=false (kein TTS, App STOP). Der Text landet aber normal in der Bubble (Stefans Wunsch: Text ok, nur nicht vorlesen). Antwort-Skills (speak=true) + reine Konversation bleiben gesprochen; bei Skill-Fehler bleibt's gesprochen (Erklaerung soll man hoeren). Reiner Brain-Fix — App liest speak bereits. Co-Authored-By: Claude Opus 4.8 --- aria-brain/agent.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/aria-brain/agent.py b/aria-brain/agent.py index 7ec2140..8c584e9 100644 --- a/aria-brain/agent.py +++ b/aria-brain/agent.py @@ -1555,6 +1555,12 @@ class Agent: # zwei Turns, was OpenAI/Anthropic verwirrt und bei strict tools-Aufrufen # zu 400-Errors fuehren kann. final_reply = "" + # Vorlesen ja/nein fuer diesen Claude-Turn. Default True (Gespraech). + # Fuehrt Claude einen Steuerbefehl-Skill (run_*, speak=false) erfolgreich + # aus, wird die Antwort NICHT vorgelesen — der Text landet aber normal in + # der Bubble (Stefans Wunsch). Antwort-Skills (speak=true) + reine + # Konversation bleiben gesprochen. + self._claude_turn_speak = True try: for iteration in range(self.MAX_TOOL_ITERATIONS): result = self.proxy.chat_full(messages, tools=tools, @@ -1572,6 +1578,11 @@ class Agent: # Tools ausfuehren + Ergebnis als role=tool zurueck for tc in result.tool_calls: tool_result = self._dispatch_tool(tc["name"], tc["arguments"]) + # Steuerbefehl-Skill (run_*, speak=false) erfolgreich + # ausgefuehrt → Antwort nicht vorlesen (letzter Skill gewinnt). + _tn = tc.get("name") or "" + if _tn.startswith("run_") and not self._local_tool_failed(_tn, tool_result): + self._claude_turn_speak = self._skill_speak_flag(_tn) # Cap auf 50 KB — passt zur Cap in _dispatch_tool fuer # Skill-Outputs (siehe agent.py weiter unten). 8 KB war # viel zu wenig: Spotify _all=true mit 90 Playlists @@ -1640,7 +1651,8 @@ class Agent: # 7. Assistant-Turn (final reply) in die Conversation self.conversation.add("assistant", final_reply, project_id=active_project_id) - return final_reply, "claude", True # ARIA-Antwort → vorlesen ok + # speak folgt dem ausgefuehrten Skill (Steuerbefehl=stumm), sonst True. + return final_reply, "claude", bool(getattr(self, "_claude_turn_speak", True)) # ── Tool-Dispatcher ───────────────────────────────────────