diff --git a/CHANGELOG.md b/CHANGELOG.md index 85f24bc..9d65242 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,19 @@ Alle Änderungen am Projekt. Format: [Keep a Changelog](https://keepachangelog.c --- +## [0.2.2.1] — 2026-07-17 — Projekt-Fokus wirklich pro Gerät unabhängig + +### Behoben + +- **`set_project_kind` markierte das falsche Projekt.** Es nutzte den **globalen** `active_project` (geräteübergreifend) statt des Projekts, in dem der aktuelle Request läuft. Folge: Obwohl auf der App „Basic os" aktiv war, bekam das global-aktive „Mac OS Update Fehler" `kind=code`. Jetzt wirkt das Tool auf die pro Request mitgesendete `project_id` (in `_dispatch_tool` durchgereicht) — jede App-/Diagnostic-Instanz markiert ihr eigenes Projekt. +- **App wurde von fremden `project_changed`-Broadcasts ins andere Projekt gezogen.** Ein Projektwechsel/‑anlegen durch ARIA, das Diagnostic oder eine andere App-Instanz erzwang auf **allen** Geräten einen Fokuswechsel. Der Projekt-Fokus ist jetzt **rein gerätelokal**: Broadcasts aktualisieren nur Namen + Typ, wechseln aber nicht mehr das Projekt. Umschalten geht ausschließlich lokal über den Projekt-Drawer. So arbeitet jedes Gerät unabhängig in seinem eigenen Projekt (auch mehrere App-Instanzen). +- Hinweis: „ARIA, geh in Projekt X" per Sprache wechselt das App-Projekt dadurch **nicht mehr** automatisch — bewusst, damit Geräte unabhängig bleiben. Wechseln über den Drawer. + +### Deploy +`git pull && docker compose up -d --build brain` + APK 0.2.2.1 neu bauen. + +--- + ## [0.2.2.0] — 2026-07-17 — Workbench: Taskleisten-Dock statt Zoom-Landkarte + bedienbare VNC-Konsole ### Geändert diff --git a/android/src/screens/ChatScreen.tsx b/android/src/screens/ChatScreen.tsx index 432fb79..2730a9e 100644 --- a/android/src/screens/ChatScreen.tsx +++ b/android/src/screens/ChatScreen.tsx @@ -992,11 +992,14 @@ const ChatScreen: React.FC = () => { if (p.id && (p.kind === 'code' || p.kind === 'chat')) { projectFocus.setKind(p.id, p.kind); } - if (action === 'entered' || action === 'created') { - if (p.id) setFocusedProjectId(p.id); - } else if (action === 'exited') { - setFocusedProjectId(''); - } + // KEIN erzwungener Fokuswechsel mehr: Projekt-Fokus ist rein GERAETE- + // LOKAL. project_changed-Broadcasts (von ARIA-Tools / Diagnostic / einer + // anderen App-Instanz) aktualisieren nur Namen + Typ, ziehen dieses + // Geraet aber NICHT in ein anderes Projekt. So arbeitet jede App-/ + // Diagnostic-Instanz unabhaengig in ihrem eigenen Projekt. Wechseln + // geht ausschliesslich lokal ueber den Projekt-Drawer. + // (action wird bewusst nicht mehr fuer setFocusedProjectId genutzt.) + void action; return; } diff --git a/aria-brain/agent.py b/aria-brain/agent.py index 3bf519a..44548e3 100644 --- a/aria-brain/agent.py +++ b/aria-brain/agent.py @@ -1515,7 +1515,7 @@ class Agent: targs = {} logger.info("[router] lokal Tool-Call: %s(%s)", tname, ", ".join(targs.keys())) - tresult = self._dispatch_tool(tname, targs) + tresult = self._dispatch_tool(tname, targs, active_project_id) # Echter Skill (run_*) erfolgreich? Dann uebernimmt dieser # Turn das speak-Flag des Skills (Steuerbefehl=stumm, # Antwort-Skill=vorlesen). Letzter Skill gewinnt. @@ -1807,7 +1807,7 @@ class Agent: )) # Tools ausfuehren + Ergebnis als role=tool zurueck for tc in result.tool_calls: - tool_result = self._dispatch_tool(tc["name"], tc["arguments"]) + tool_result = self._dispatch_tool(tc["name"], tc["arguments"], active_project_id) # Steuerbefehl-Skill (run_*, speak=false) erfolgreich # ausgefuehrt → Antwort nicht vorlesen (letzter Skill gewinnt). _tn = tc.get("name") or "" @@ -1895,10 +1895,12 @@ class Agent: # ── Tool-Dispatcher ─────────────────────────────────────── - def _dispatch_tool(self, name: str, arguments: dict) -> str: + def _dispatch_tool(self, name: str, arguments: dict, project_id: str = "") -> str: """Fuehrt einen Tool-Call aus und gibt ein kurzes Text-Resultat zurueck. Niemals werfen — Fehler werden als Text-Resultat reportet damit Claude - weitermachen kann.""" + weitermachen kann. project_id = Projekt DIESES Requests (fuer Tools die + aufs aktuelle Projekt wirken, z.B. set_project_kind) — NICHT der globale + active_project (geraeteuebergreifend).""" try: if name == "skill_create": # ARIA-Skills sind immer Python — execution ist nicht mehr im Schema @@ -2602,13 +2604,18 @@ class Agent: kind = (arguments.get("kind") or "").strip().lower() if kind not in ("code", "chat"): return "FEHLER: kind muss 'code' oder 'chat' sein." - active_id = projects_mod.get_active() + # WICHTIG: das Projekt des AKTUELLEN Requests markieren, NICHT den + # globalen active_project — der ist geraeteuebergreifend und wuerde + # (bei mehreren App-/Diagnostic-Instanzen) das falsche Projekt + # treffen. project_id kommt pro Request vom Client. + active_id = (project_id or "").strip() if not active_id: - return ("Kein aktives Projekt — Du bist im Hauptthread. Erst ein Projekt " - "anlegen/betreten (project_create/project_enter), dann set_project_kind.") + return ("Kein aktives Projekt — dieser Chat laeuft im Hauptthread. " + "set_project_kind wirkt nur, wenn der Request in einem Projekt " + "laeuft (der Client sendet die project_id mit).") updated = projects_mod.update_project(active_id, {"kind": kind}) if not updated: - return f"FEHLER: aktives Projekt '{active_id}' nicht gefunden." + return f"FEHLER: Projekt '{active_id}' nicht gefunden." self._pending_events.append({ "type": "project_changed", "project": updated,