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)
|
||||
return cleaned, files, missing
|
||||
|
||||
def _tag_file_to_active_project(self, file_path: str) -> None:
|
||||
"""Holt vom Brain das aktive Projekt + schreibt file_path → project_id
|
||||
in /shared/config/file_projects.json. Best-effort, fail-silent.
|
||||
Wird vom File-Save-Handler nach erfolgreichem Schreiben aufgerufen."""
|
||||
def _tag_file_to_project(self, file_path: str, project_id: str) -> None:
|
||||
"""Schreibt file_path → project_id in /shared/config/file_projects.json.
|
||||
Best-effort, fail-silent. project_id leer = Eintrag entfernen (Hauptchat)."""
|
||||
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"
|
||||
os.makedirs("/shared/config", exist_ok=True)
|
||||
try:
|
||||
@@ -1027,15 +1020,35 @@ class ARIABridge:
|
||||
manifest = {}
|
||||
except Exception:
|
||||
manifest = {}
|
||||
manifest[file_path] = active_id
|
||||
if project_id:
|
||||
manifest[file_path] = project_id
|
||||
else:
|
||||
manifest.pop(file_path, None)
|
||||
tmp = manifest_path + ".tmp"
|
||||
with open(tmp, "w") as f:
|
||||
json.dump(manifest, f, indent=2, ensure_ascii=False)
|
||||
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:
|
||||
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:
|
||||
"""ARIA hat eine Datei fuer den User erstellt — App+Diagnostic informieren."""
|
||||
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
|
||||
# vorlesen) und parallel als file_from_aria-Event geschickt.
|
||||
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:
|
||||
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)
|
||||
# Bei fehlenden Files: User informieren (sonst sieht er nur stille
|
||||
# Verluste — ARIA hat den Marker hingeschrieben aber das File nicht
|
||||
|
||||
Reference in New Issue
Block a user