feat(agent): Bild mit Text einblenden — host_notify kann jetzt image_path
Der Android-Agent konnte schon immer ein Bild MIT Text einblenden (OverlayView.show nimmt ein imageB64), aber ARIA kam nicht dran: in der Parameter-Liste von host_notify fehlte das Feld einfach. Die Faehigkeit war gebaut und unerreichbar. ARIA gibt jetzt image_path an (ein Pfad unter /shared/uploads/, damit arbeitet sie sowieso) und das Brain wandelt die Datei nach base64 — statt ARIA megabyteweise base64 durch den Tool-Call schieben zu lassen. Pfad-Praefix wird geprueft, und ueber 4 MB wird abgelehnt: fuer eine Einblendung auf einem Fernseher ist mehr sinnlos und blaeht die WS-Nachricht auf. Nur Android-Agenten koennen das; die Beschreibung sagt das ausdruecklich. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+29
-1
@@ -1599,7 +1599,9 @@ META_TOOLS = [
|
|||||||
"das NICHT ueber host_exec/adb (dort gibt es kein passendes Kommando). "
|
"das NICHT ueber host_exec/adb (dort gibt es kein passendes Kommando). "
|
||||||
"mode: 'overlay' (einblenden), 'speech' (vorlesen) oder 'both'; ohne "
|
"mode: 'overlay' (einblenden), 'speech' (vorlesen) oder 'both'; ohne "
|
||||||
"Angabe gilt die Einstellung am Geraet. Braucht dort einmalig die "
|
"Angabe gilt die Einstellung am Geraet. Braucht dort einmalig die "
|
||||||
"Berechtigung 'Ueber anderen Apps anzeigen'."
|
"Berechtigung 'Ueber anderen Apps anzeigen'. Mit image_path kann "
|
||||||
|
"ein BILD mit Text darueber eingeblendet werden (z.B. ein "
|
||||||
|
"generiertes Bild oder ein Screenshot) — nur bei Android-Agenten."
|
||||||
),
|
),
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -1610,6 +1612,14 @@ META_TOOLS = [
|
|||||||
"seconds": {"type": "integer", "description": "Anzeigedauer (Default 12)."},
|
"seconds": {"type": "integer", "description": "Anzeigedauer (Default 12)."},
|
||||||
"mode": {"type": "string", "description": "overlay | speech | both"},
|
"mode": {"type": "string", "description": "overlay | speech | both"},
|
||||||
"focus": {"type": "string", "description": "Bei Sprachausgabe: 'duck' (laufende Medien werden leiser, Standard) | 'pause' (Film/Musik anhalten) | 'none'."},
|
"focus": {"type": "string", "description": "Bei Sprachausgabe: 'duck' (laufende Medien werden leiser, Standard) | 'pause' (Film/Musik anhalten) | 'none'."},
|
||||||
|
"image_path": {
|
||||||
|
"type": "string",
|
||||||
|
"description": (
|
||||||
|
"Optional: Pfad zu einem Bild (PNG/JPEG) unter "
|
||||||
|
"/shared/uploads/, das MIT dem Text eingeblendet wird. "
|
||||||
|
"Nur Android-Agenten koennen das."
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"required": ["host", "text"],
|
"required": ["host", "text"],
|
||||||
},
|
},
|
||||||
@@ -3246,6 +3256,24 @@ class Agent:
|
|||||||
if name in _UI_ACTIONS:
|
if name in _UI_ACTIONS:
|
||||||
action, keys = _UI_ACTIONS[name]
|
action, keys = _UI_ACTIONS[name]
|
||||||
params = {k: arguments[k] for k in keys if arguments.get(k) is not None}
|
params = {k: arguments[k] for k in keys if arguments.get(k) is not None}
|
||||||
|
# Bild-Einblendung: ARIA gibt einen Pfad an (damit arbeitet sie
|
||||||
|
# sowieso), der Agent will base64. Hier umwandeln, statt ARIA
|
||||||
|
# megabyteweise base64 durch den Tool-Call schieben zu lassen.
|
||||||
|
img_path = (arguments.get("image_path") or "").strip()
|
||||||
|
if action == "notify" and img_path:
|
||||||
|
if not img_path.startswith("/shared/uploads/"):
|
||||||
|
return "FEHLER: image_path muss unter /shared/uploads/ liegen."
|
||||||
|
if not os.path.isfile(img_path):
|
||||||
|
return f"FEHLER: Bild nicht gefunden: {img_path}"
|
||||||
|
# Overlay-Bilder ueber ~4 MB sind sinnlos gross fuer einen
|
||||||
|
# Fernseher und blaehen die WS-Nachricht unnoetig auf.
|
||||||
|
_img_size = os.path.getsize(img_path)
|
||||||
|
if _img_size > 4 * 1024 * 1024:
|
||||||
|
return (f"FEHLER: Bild zu gross fuer eine Einblendung "
|
||||||
|
f"({_img_size // (1024 * 1024)} MB > 4 MB). "
|
||||||
|
f"Vorher verkleinern.")
|
||||||
|
with open(img_path, "rb") as _f:
|
||||||
|
params["image_base64"] = _b64.b64encode(_f.read()).decode("ascii")
|
||||||
# Sprachausgabe braucht laenger: der Agent meldet erst Erfolg,
|
# Sprachausgabe braucht laenger: der Agent meldet erst Erfolg,
|
||||||
# wenn wirklich Ton laeuft (TTS-Render + Uebertragung). Mit den
|
# wenn wirklich Ton laeuft (TTS-Render + Uebertragung). Mit den
|
||||||
# 20s der UI-Aktionen lief die ehrliche Antwort in den Timeout.
|
# 20s der UI-Aktionen lief die ehrliche Antwort in den Timeout.
|
||||||
|
|||||||
Reference in New Issue
Block a user