fix: Projekt-Fokus pro Geraet unabhaengig (Diagnostic/App/Multi-Instanz)
Zwei Kopplungs-Bugs behoben: - set_project_kind nutzte den globalen active_project statt des Request-Projekts → markierte das falsche Projekt (belegt: global aktiv war mac_os_update_fehler, das kind=code bekam, obwohl die App in basic_os war). _dispatch_tool bekommt jetzt die project_id des Requests durchgereicht; set_project_kind wirkt darauf. - Die App erzwang bei project_changed-Broadcasts (ARIA-Tool/Diagnostic/andere App-Instanz) einen Fokuswechsel → alle Geraete wurden mitgezogen. Fokus ist jetzt rein geraetelokal; Broadcasts aktualisieren nur Namen/Typ. Wechseln nur noch lokal ueber den Drawer. py-compile + tsc clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+15
-8
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user