Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 53b49eacad | |||
| 0f11d23c75 | |||
| 311030bdaa |
@@ -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,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",
|
||||||
|
|||||||
@@ -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
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user