fix(projects): ARIA-generierte Dateien dem aktiven Projekt zuordnen
Bisher haben nur App-Uploads (msg_type == "file") ein Projekt-Tag bekommen. Dateien die ARIA waehrend des Turns selbst schreibt (via [FILE: /shared/ uploads/aria_xyz.pdf]-Marker) sind dem Hauptchat zugefallen, auch wenn Stefan in einem Projekt war. Fix: Beim Verarbeiten der ARIA-Antwort in _process_core_response wird die turn_project_id aus payload.projectId (ChatOut.project_id vom Brain) ge- nutzt um jede gefundene ARIA-Datei sofort zu taggen, bevor sie als file_from_aria broadcast wird. Helper-Split: - _tag_file_to_project(path, pid): pure Write, pid schon bekannt - _tag_file_to_active_project(path): Convenience-Wrapper, fragt Brain nach active project (genutzt vom App-Upload-Handler, der noch nichts vom Projekt-Kontext weiss) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+33
-12
@@ -1005,17 +1005,10 @@ class ARIABridge:
|
|||||||
cleaned = re.sub(r"\n{3,}", "\n\n", cleaned)
|
cleaned = re.sub(r"\n{3,}", "\n\n", cleaned)
|
||||||
return cleaned, files, missing
|
return cleaned, files, missing
|
||||||
|
|
||||||
def _tag_file_to_active_project(self, file_path: str) -> None:
|
def _tag_file_to_project(self, file_path: str, project_id: str) -> None:
|
||||||
"""Holt vom Brain das aktive Projekt + schreibt file_path → project_id
|
"""Schreibt file_path → project_id in /shared/config/file_projects.json.
|
||||||
in /shared/config/file_projects.json. Best-effort, fail-silent.
|
Best-effort, fail-silent. project_id leer = Eintrag entfernen (Hauptchat)."""
|
||||||
Wird vom File-Save-Handler nach erfolgreichem Schreiben aufgerufen."""
|
|
||||||
try:
|
try:
|
||||||
brain_url = os.environ.get("BRAIN_URL", "http://aria-brain:8080")
|
|
||||||
with urllib.request.urlopen(f"{brain_url}/projects/status", timeout=5) as r:
|
|
||||||
data = json.loads(r.read())
|
|
||||||
active_id = (data.get("active_id") or "").strip()
|
|
||||||
if not active_id:
|
|
||||||
return
|
|
||||||
manifest_path = "/shared/config/file_projects.json"
|
manifest_path = "/shared/config/file_projects.json"
|
||||||
os.makedirs("/shared/config", exist_ok=True)
|
os.makedirs("/shared/config", exist_ok=True)
|
||||||
try:
|
try:
|
||||||
@@ -1027,15 +1020,35 @@ class ARIABridge:
|
|||||||
manifest = {}
|
manifest = {}
|
||||||
except Exception:
|
except Exception:
|
||||||
manifest = {}
|
manifest = {}
|
||||||
manifest[file_path] = active_id
|
if project_id:
|
||||||
|
manifest[file_path] = project_id
|
||||||
|
else:
|
||||||
|
manifest.pop(file_path, None)
|
||||||
tmp = manifest_path + ".tmp"
|
tmp = manifest_path + ".tmp"
|
||||||
with open(tmp, "w") as f:
|
with open(tmp, "w") as f:
|
||||||
json.dump(manifest, f, indent=2, ensure_ascii=False)
|
json.dump(manifest, f, indent=2, ensure_ascii=False)
|
||||||
os.replace(tmp, manifest_path)
|
os.replace(tmp, manifest_path)
|
||||||
logger.info("[file-project] %s → %s", file_path, active_id)
|
logger.info("[file-project] %s → %s", file_path, project_id or "(main)")
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.warning("[file-project] tag failed (%s): %s", file_path, exc)
|
logger.warning("[file-project] tag failed (%s): %s", file_path, exc)
|
||||||
|
|
||||||
|
def _tag_file_to_active_project(self, file_path: str) -> None:
|
||||||
|
"""Convenience: Brain nach aktivem Projekt fragen + taggen.
|
||||||
|
Wird vom App-Upload-Handler genutzt (dort wissen wir die Projekt-ID
|
||||||
|
noch nicht aus dem Payload — Stefan kann ja zwischen App-Upload und
|
||||||
|
Chat-Send das Projekt gewechselt haben). ARIA-eigene Dateien gehen
|
||||||
|
ueber _tag_file_to_project mit turn_project_id direkt."""
|
||||||
|
try:
|
||||||
|
brain_url = os.environ.get("BRAIN_URL", "http://aria-brain:8080")
|
||||||
|
with urllib.request.urlopen(f"{brain_url}/projects/status", timeout=5) as r:
|
||||||
|
data = json.loads(r.read())
|
||||||
|
active_id = (data.get("active_id") or "").strip()
|
||||||
|
if not active_id:
|
||||||
|
return
|
||||||
|
self._tag_file_to_project(file_path, active_id)
|
||||||
|
except Exception as exc:
|
||||||
|
logger.warning("[file-project] active-query failed (%s): %s", file_path, exc)
|
||||||
|
|
||||||
async def _broadcast_aria_file(self, file_info: dict) -> None:
|
async def _broadcast_aria_file(self, file_info: dict) -> None:
|
||||||
"""ARIA hat eine Datei fuer den User erstellt — App+Diagnostic informieren."""
|
"""ARIA hat eine Datei fuer den User erstellt — App+Diagnostic informieren."""
|
||||||
logger.info("[rvs] ARIA-Datei rausgeben: %s (%s, %dKB)",
|
logger.info("[rvs] ARIA-Datei rausgeben: %s (%s, %dKB)",
|
||||||
@@ -1194,7 +1207,15 @@ class ARIABridge:
|
|||||||
# Der Marker wird aus dem Antworttext entfernt (TTS soll ihn nicht
|
# Der Marker wird aus dem Antworttext entfernt (TTS soll ihn nicht
|
||||||
# vorlesen) und parallel als file_from_aria-Event geschickt.
|
# vorlesen) und parallel als file_from_aria-Event geschickt.
|
||||||
text, aria_files, missing_files = self._extract_file_markers(text)
|
text, aria_files, missing_files = self._extract_file_markers(text)
|
||||||
|
# ARIA-Dateien dem aktiven Projekt zuordnen (falls eines aktiv war).
|
||||||
|
# turn_project_id kommt vom Brain mit dem /chat-Response und reflektiert
|
||||||
|
# den Stand NACH dem Turn — passt fuer Dateien die ARIA waehrend des
|
||||||
|
# Turns geschrieben hat (sie sind „im selben Projekt entstanden").
|
||||||
|
turn_pid = (payload.get("projectId") or "").strip() if isinstance(payload, dict) else ""
|
||||||
for f in aria_files:
|
for f in aria_files:
|
||||||
|
server_path = f.get("serverPath")
|
||||||
|
if turn_pid and server_path:
|
||||||
|
self._tag_file_to_project(server_path, turn_pid)
|
||||||
await self._broadcast_aria_file(f)
|
await self._broadcast_aria_file(f)
|
||||||
# Bei fehlenden Files: User informieren (sonst sieht er nur stille
|
# Bei fehlenden Files: User informieren (sonst sieht er nur stille
|
||||||
# Verluste — ARIA hat den Marker hingeschrieben aber das File nicht
|
# Verluste — ARIA hat den Marker hingeschrieben aber das File nicht
|
||||||
|
|||||||
Reference in New Issue
Block a user