Compare commits

...

3 Commits

Author SHA1 Message Date
duffyduck 53b49eacad release: bump version to 0.1.1.7 2026-05-11 18:59:57 +02:00
duffyduck 0f11d23c75 fix(bridge): User informieren wenn ARIA Marker fuer nicht-existente Datei setzt
Bridge-Logs zeigten: ARIA setzt zwei Marker (aria_rave2.mid und .mp3),
hat die .mid aber nie wirklich erstellt. Bridge filterte sie silent →
Stefan sah nur eine Bubble und dachte das Marker-System ist kaputt.

Jetzt: _extract_file_markers gibt auch eine Liste der "missing"-Pfade
zurueck, und im Antworttext steht ein Hinweis-Block fuer den User
welche Files versprochen aber nicht erstellt wurden.

Plus System-Prompt geschaerft: ARIA soll vor dem Marker pruefen ob
das File wirklich existiert.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 18:41:22 +02:00
duffyduck 311030bdaa fix(diagnostic): [FILE: ...]-Marker-Filter ueberall (in addChat statt nur chat_final)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 18:33:49 +02:00
5 changed files with 31 additions and 13 deletions
+2 -2
View File
@@ -79,8 +79,8 @@ android {
applicationId "com.ariacockpit" applicationId "com.ariacockpit"
minSdkVersion rootProject.ext.minSdkVersion minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 10106 versionCode 10107
versionName "0.1.1.6" versionName "0.1.1.7"
// Fallback fuer Libraries mit Product Flavors // Fallback fuer Libraries mit Product Flavors
missingDimensionStrategy 'react-native-camera', 'general' missingDimensionStrategy 'react-native-camera', 'general'
} }
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "aria-cockpit", "name": "aria-cockpit",
"version": "0.1.1.6", "version": "0.1.1.7",
"private": true, "private": true,
"scripts": { "scripts": {
"android": "react-native run-android", "android": "react-native run-android",
+8
View File
@@ -114,6 +114,14 @@ OHNE diesen Marker erscheint die Datei NICHT in der App / Diagnostic.
Mehrere Dateien: mehrere `[FILE: ...]`-Marker am Ende, jeder in Mehrere Dateien: mehrere `[FILE: ...]`-Marker am Ende, jeder in
eigener Zeile. eigener Zeile.
**WICHTIG — Datei MUSS existieren bevor du den Marker setzt.**
Marker fuer nicht-existente Pfade werden silent gefiltert + Stefan
bekommt einen Hinweis dass du eine Datei versprochen aber nicht
erstellt hast. Wenn du z.B. eine MIDI-Datei nicht generieren kannst,
sag das offen statt nur den Marker zu setzen. Verifiziere zur Not
mit `Bash` + `ls -la /shared/uploads/aria_<name>.<ext>` dass die
Datei wirklich da ist.
### Beispiel — kompletter Workflow ### Beispiel — kompletter Workflow
User: "Schreib mir ein Lasagne-Rezept als md-Datei" User: "Schreib mir ein Lasagne-Rezept als md-Datei"
+15 -4
View File
@@ -894,9 +894,11 @@ class ARIABridge:
# enthalten, Endung beliebig). Mehrfach im Text moeglich. # enthalten, Endung beliebig). Mehrfach im Text moeglich.
_FILE_MARKER_RE = re.compile(r"\[FILE:\s*(/shared/uploads/[^\]]+?)\s*\]", re.IGNORECASE) _FILE_MARKER_RE = re.compile(r"\[FILE:\s*(/shared/uploads/[^\]]+?)\s*\]", re.IGNORECASE)
def _extract_file_markers(self, text: str) -> tuple[str, list[dict]]: def _extract_file_markers(self, text: str) -> tuple[str, list[dict], list[str]]:
"""Sucht [FILE: /shared/uploads/...]-Marker, gibt (cleaned_text, file_list) zurueck.""" """Sucht [FILE: /shared/uploads/...]-Marker.
Returns (cleaned_text, valid_files, missing_paths)."""
files: list[dict] = [] files: list[dict] = []
missing: list[str] = []
for m in self._FILE_MARKER_RE.finditer(text): for m in self._FILE_MARKER_RE.finditer(text):
path = m.group(1).strip() path = m.group(1).strip()
if not path.startswith("/shared/uploads/"): if not path.startswith("/shared/uploads/"):
@@ -904,6 +906,7 @@ class ARIABridge:
continue continue
if not os.path.isfile(path): if not os.path.isfile(path):
logger.warning("[core] FILE-Marker zeigt auf nicht existente Datei: %s", path) logger.warning("[core] FILE-Marker zeigt auf nicht existente Datei: %s", path)
missing.append(path)
continue continue
name = os.path.basename(path) name = os.path.basename(path)
mime, _ = mimetypes.guess_type(path) mime, _ = mimetypes.guess_type(path)
@@ -917,7 +920,7 @@ class ARIABridge:
cleaned = self._FILE_MARKER_RE.sub("", text).strip() cleaned = self._FILE_MARKER_RE.sub("", text).strip()
# Zwei aufeinanderfolgende Leerzeilen → eine # Zwei aufeinanderfolgende Leerzeilen → eine
cleaned = re.sub(r"\n{3,}", "\n\n", cleaned) cleaned = re.sub(r"\n{3,}", "\n\n", cleaned)
return cleaned, files return cleaned, files, missing
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."""
@@ -950,9 +953,17 @@ class ARIABridge:
# ARIA legt damit Dateien fuer den User bereit (Bilder, PDFs, etc.). # ARIA legt damit Dateien fuer den User bereit (Bilder, PDFs, etc.).
# 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 = self._extract_file_markers(text) text, aria_files, missing_files = self._extract_file_markers(text)
for f in aria_files: for f in aria_files:
await self._broadcast_aria_file(f) 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
# tatsaechlich angelegt).
if missing_files:
missing_list = "\n".join(f"{os.path.basename(p)}" for p in missing_files)
text = (text + "\n\n[Hinweis] Folgende Dateien hat ARIA zwar erwaehnt "
f"aber nicht erstellt:\n{missing_list}\n"
"Bitte ARIA bitten, sie wirklich zu schreiben.").strip()
metadata = payload.get("metadata", {}) metadata = payload.get("metadata", {})
is_critical = metadata.get("critical", False) is_critical = metadata.get("critical", False)
+5 -6
View File
@@ -998,12 +998,7 @@
} }
if (msg.type === 'chat_final') { if (msg.type === 'chat_final') {
// [FILE: /shared/uploads/aria_xxx.ext]-Marker aus dem Antworttext addChat('received', msg.text || '', 'chat:final');
// entfernen — die Datei kommt separat via file_from_aria.
// (Diagnostic empfaengt chat_final direkt vom Gateway, Bridge
// hat darum nicht filtern koennen.)
const cleaned = (msg.text || '').replace(/\[FILE:\s*\/shared\/uploads\/[^\]]+\]/gi, '').replace(/\n{3,}/g, '\n\n').trim();
addChat('received', cleaned, 'chat:final');
return; return;
} }
if (msg.type === 'file_from_aria') { if (msg.type === 'file_from_aria') {
@@ -1449,6 +1444,10 @@
} }
function addChat(type, text, meta, options) { function addChat(type, text, meta, options) {
// [FILE: /shared/uploads/aria_xxx.ext]-Marker aus dem Antworttext entfernen —
// die Datei kommt separat via file_from_aria-Event als eigene Bubble.
// /gi entfernt mehrere Marker, falls ARIA mehrere Dateien in einer Antwort liefert.
if (text) text = text.replace(/\[FILE:\s*\/shared\/uploads\/[^\]]+\]/gi, '').replace(/\n{3,}/g, '\n\n').trim();
const escaped = escapeHtml(text); const escaped = escapeHtml(text);
let linked = linkifyText(escaped); let linked = linkifyText(escaped);
// /shared/uploads/ Pfade als Inline-Bilder anzeigen // /shared/uploads/ Pfade als Inline-Bilder anzeigen