13e87fb0832ce16879d98aa8fa223e61381b694f
19 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
13e87fb083 |
feat(oauth): ARIA kann Provider selbst registrieren + Custom-Provider in Diagnostic & App
ARIA hat jetzt das META-Tool oauth_register_provider. Wenn Stefan einen Service nutzen will, der nicht in den (auf Spotify reduzierten) Defaults ist, kann sie auth_url/token_url/scopes/client_auth selbst eintragen — ARIA kennt typische OAuth-Endpunkte (Dropbox, Discord, Notion, Slack, Zoom, Trello, LinkedIn, Reddit, Twitch) aus ihrem Training. Sie traegt NUR die URLs ein, client_id/secret bleiben Stefans Job (Diagnostic / App-UI) — bewusste Trennung damit Credentials nicht im Chat-Verlauf landen. DEFAULT_PROVIDERS auf Spotify reduziert — Rest war aktuell ungenutzt und macht den Code unnoetig "groß". ARIA registriert on-demand. Diagnostic-UI: - Custom-Provider zeigen auth_url/token_url/scopes als sichtbare Felder - Defaults verstecken die Felder hinter "Default-URLs ueberschreiben (advanced)" damit man die Spotify-URLs nicht versehentlich loescht - "+ Custom OAuth-Provider hinzufuegen" Button mit Prompts fuer Name/URLs/Scopes - 🗑-Icon bei Custom-Services (Service komplett entfernen) App-UI (neu fuer unterwegs): - Settings → Sektion 🔑 "OAuth-Apps" zwischen Skills und Protokoll - OAuthBrowser-Komponente analog zu Trigger/Skill-Browser: Liste mit Status, Tap → Edit-Modal mit client_id/secret + Advanced-Toggle fuer URLs. "Autorisieren ↗" oeffnet System-Browser via Linking.openURL, redirected zur RVS-Callback-Page, Status-Refresh nach 8s. - "+ Custom"-Button → Full-Screen-Modal fuer Service-Anlage. - brainApi um listOAuthServices/getOAuthApps/saveOAuthApp/ deleteOAuthApp/authorizeOAuth/revokeOAuth erweitert. Workflow ist jetzt: "verbinde mich mit Dropbox" → ARIA registriert Provider → "trag client_id/secret in Settings ein" → Stefan macht das in App oder Diagnostic → "Autorisieren ↗" → fertig. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
30c1dd7473 |
feat(app+brain): App-Bugfixes + Skill-Mgmt-Tools + Voice-Speed persistent + Skill-Browser
App-Bugs:
- Trigger-Liste war leer: brainApi.listTriggers() cast'te {triggers: [...]}
direkt als Array, t.sort() warf — TriggerBrowser blieb leer. Fix: unwrap.
- GPS-Tracking startete erst bei SettingsScreen-Mount, nicht beim App-Boot.
Wenn Stefan direkt in den Chat ging, blieb GPS aus. Fix: restoreFromStorage()
in App.tsx useEffect.
- Text in Chat-Bubbles nicht markierbar / kein Copy-Mechanismus: Bubble jetzt
Pressable mit onLongPress + neues ⎘-Icon in Status-Row → openBubbleActions().
Alert-Menu mit "Ganzen Text teilen" + pro extrahierte URL/Mail/Tel eine
eigene Option. Share.share() — keine neuen Native-Deps noetig.
Brain — Skill-Mgmt:
- ARIA legte beim Skill-Umbau neue Versionen mit Suffix an (Skill-Friedhof),
weil sie kein Update/Delete-Tool kannte. Zwei neue META_TOOLS in agent.py:
skill_update (kann entry_code, readme, pip_packages, args, description,
active patchen — venv wird bei pip_packages-Aenderung rebuilt) + skill_delete.
- skills.py update_skill um entry_code/readme/pip_packages erweitert,
venv-Rebuild bei pip-Aenderung.
Bridge — Voice-Speed persistent:
- _next_speed_override war pro-Request-Override ohne Persistenz. Bei
Diagnostic-Chats / Trigger-Replies ohne vorherigen App-Chat fiel der Speed
auf 1.0 zurueck, ebenso nach Bridge-Restart. Jetzt: _persistent_xtts_speed
aus voice_config.json (xttsSpeed), wird nach jedem App-chat mit speed
autopersistiert. TTS-Generation faellt zurueck: per-Request > persistent > 1.0.
App — Feature 6:
- SkillBrowser.tsx: Liste aller Skills, Toggle aktiv/inaktiv, Detail-Modal
mit Args-Inputs, Ausfuehren mit Live-stdout/stderr, Logs der letzten 20
Runs, Loeschen. Settings-Sektion "Skills" (🛠️) zwischen Trigger und
Protokoll. brainApi.listSkills/getSkill/runSkill/updateSkill/deleteSkill/
getSkillLogs ergaenzt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
acaa9fc3f2 |
feat(oauth): generische OAuth2-Pipeline ueber RVS-Callback (Spotify/Google/GitHub/Strava/MS)
Bisher musste Stefan bei OAuth-Flows manuell den Auth-Code aus der Browser-URL kopieren (redirect_uri war localhost). Jetzt: RVS hat einen HTTP-Listener auf demselben Port wie der WebSocket, Provider redirecten nach Auth zu https://{RVS_HOST}/oauth/callback/{service}, RVS broadcastet, aria-bridge forwarded, Brain matched state + tauscht code gegen Token. Token-Refresh laeuft automatisch. - rvs/server.js: hybrid http.createServer + WebSocketServer{noServer}. Route GET /oauth/callback/{service}, broadcast oauth_callback an alle Raeume, schoene Dark-Mode-HTML-Antwort an den Browser (Auto-Close 4s). - bridge/aria_bridge.py: empfaengt oauth_callback, POSTet an Brain /internal/oauth-callback. - aria-brain/oauth.py: neuer Manager. Pending-Store mit state+TTL, Token-Exchange (Basic-Auth oder Body je nach Provider), persistente Speicherung in /shared/config/oauth_tokens.json (mode 0600), Token-Refresh wenn <60s Restzeit. Vordefinierte Configs fuer Spotify, Google, GitHub, Strava, Microsoft. - aria-brain/agent.py: META-Tools oauth_authorize / oauth_get_token / oauth_revoke. - aria-brain/prompts.py: System-Prompt-Block zeigt ARIA die feste Callback-URL als Quelle der Wahrheit + aktuelle Service-States. - aria-brain/main.py: HTTP-Endpoints /oauth/services, /oauth/apps, /oauth/authorize, /oauth/{service}/revoke, /internal/oauth-callback. - diagnostic: neue Section "OAuth-Apps". Pro Service Karte mit Status, client_id + client_secret (Passwort-Toggle), Speichern + Autorisieren- Buttons. Authorize oeffnet Provider-Auth in neuem Tab. - docker-compose.yml: brain-env um RVS_HOST + RVS_PORT_PUBLIC + RVS_TLS ergaenzt (Brain braucht die Werte zum Bau der Callback-URL). - .env.example: RVS_PORT_PUBLIC + Brain-Timeout-Vars (PROXY_TIMEOUT_SEC + Connect/Write/Pool) dokumentiert. - README.md: OAuth-Pipeline + ARIA-Live-Mirror in Diagnostic-Section, OAuth-Apps in Einstellungen-Tab erwaehnt. - issue.md: OAuth-Pipeline + Brain-Timeout-Fix als erledigt dokumentiert. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
0887674497 |
fix(brain): Proxy-Timeout 20min -> 24h Read, split httpx-Timeouts, Cleanup-Pfade
Brain timed bei langen Pentests nach exakt 20:00 min raus, obwohl ARIAs
Subprozess fleissig weiterarbeitete und der Live-View alles zeigte.
Root-Cause: proxy_client.py hatte einen 1200s httpx.Client-Timeout —
genau der Wert, den wir vor 5 Tagen am Proxy auf 24h hochgezogen hatten.
Schicht uebersehen.
- docker-compose.yml: PROXY_TIMEOUT_SEC=86400 als brain-env.
- proxy_client.py: httpx.Timeout split (connect=10, read=86400, write=30,
pool=10). Toter Proxy wird in 10s erkannt, lange ARIA-Sessions duerfen
24h laufen.
- routes.js handleNonStreamingResponse: res.on("close") + isComplete-Flag.
Brain-Disconnect killt jetzt den Subprozess statt ihn verwaisen zu lassen.
- agent.py chat(): try/except — bei Exception nach dem User-Turn wird ein
Assistant-Error-Marker geschrieben, damit Conversation user->assistant
konsistent bleibt (kein Tool-Call-Loop-Fail in Folge-Calls).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
2d348aeec7 |
feat(flux): Modell-Wahl per Diagnostic + raw/switch-Keywords + Download-Hinweis
Diagnostic-Einstellungen fuer FLUX: - Default-Modell (dev | schnell) — wird via RVS gepusht, flux-bridge hot-swappt die Pipeline aus dem HF-Cache (~15-30s) - Raw-Keyword (Default 'flux') — Pipe-Modus, Brain leitet Stefans Text 1:1 als prompt durch, kein Rewriting/Beautify - Switch-Keyword (Default 'fix') — zwingt das ANDERE Modell als Default Brain-Tool flux_generate um model + raw erweitert, System-Prompt-Block mit den aktuellen Diagnostic-Settings + Whisper-Toleranz-Hinweis. Kein eager Bootstrap-Load: flux-bridge wartet auf config oder ersten Request. Bei erstem HF-Download zeigt Banner "laedt erstmalig runter" mit Pfeil-Icon, Toast in der App wenn fertig. FLUX_MODEL aus der .env entfernt (Steuerung jetzt komplett ueber Diagnostic). HF_TOKEN-Kommentar erklaert warum trotz lokaler Inference noetig (HF Gate-Mechanismus fuer FLUX.1-dev). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
7e53dcfed3 |
feat(flux): Bildgenerierung via FLUX.1-dev — flux-bridge auf Gamebox
Eigener Compose-Stack im /flux Verzeichnis (kann auf separater Maschine laufen). aria-bridge routet flux_request via RVS, ARIA referenziert das fertige PNG im Reply mit [FILE: ...]-Marker. Brain-Tool flux_generate mit Caps fuer steps/dimension. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
435b77e1df |
feat(trigger): entered_near + left_near — drei Modi fuer near()-Watcher
Stefan: bei aktuellen near()-Watcher gibt's nur "solange drin". Reale Szenarien wollen aber differenzieren: - VORWARNUNG vor Ziel (Blitzer-Warner 2 km vorher) → entered_near mit grossem r - ANKUNFT exakt am Ziel → entered_near mit kleinem r - VERLASSEN (Parkplatz, hast du was vergessen) → left_near - KONTINUIERLICH-DRIN (bin noch in der Naehe?) → near (Default, throttled) Zwei neue Funktionen in der Condition-Whitelist: - entered_near(lat, lon, r): True NUR im Moment des Uebergangs draussen → innen. Fires einmal pro Eintritt. - left_near(lat, lon, r): True NUR im Moment des Uebergangs innen → draussen. Fires einmal pro Austritt. State-Tracking: - pro Trigger pro near-Aufruf wird der letzte Auswertungs-Wert (true/ false) im Watcher-Manifest gespeichert (Field "near_states", Key "lat.6,lon.6,radius"). Background-Loop liest's vor dem Eval, gibt's per collect_variables(prev_near_states=...) in die Closure, schreibt nach dem Eval die neuen Werte zurueck — UNABHAENGIG ob gefeuert wurde, sonst greift die Uebergangs-Erkennung nicht. Background _tick: - Aufteilung in Watcher-Pass (mit prev_near_states pro Trigger) und Timer-Pass (ohne State, gemeinsame vars). Bisher war collect_variables einmal pro Tick — jetzt einmal pro Watcher. Disk-Stats sind teuer aber unter 30 Watchern unkritisch; bei mehr koennen wir cachen. ARIA-Tool-Description erweitert (trigger_watcher): erklaert die drei Modi mit Use-Cases und empfohlenen Throttle-Werten (kurz fuer entered/ left, lang fuer near). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
6239037fa7 |
feat(memory): Bubble-Header zeigt jetzt Aktion (angelegt/geaendert/geloescht)
Etappe 1 von Stefans App-Memory-UX-Wunsch:
Brain agent.py: memory_save Dispatcher pushed jetzt action="created",
memory_update Dispatcher pushed action="updated" mit demselben
memory_saved-Event-Typ. Bridge reicht das action-Feld im Payload mit
durch (in beiden Side-Channel-Pfaden — send_to_core + trigger-fired).
App ChatScreen: ChatMessage.memorySaved.action ('created' | 'updated'
| 'deleted'). Bubble-Header je nach Aktion:
- created → "🧠 ARIA hat etwas gemerkt" (gelb)
- updated → "🧠 ARIA hat eine Notiz geändert" (gelb)
- deleted → "🧠 ARIA hat eine Notiz gelöscht" (rot)
Naechste Etappen folgen (Detail-Modal beim Tap, Edit + Anhang-Upload,
Notizen-Inbox neben Lupe, Memory-Editor in Settings).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
16ebaa652f |
feat(brain): memory_search + memory_update Tools — ARIA findet Updates aktiv
Bug-Report von Stefan: er hat im Diagnostic den Baujahr-Memory von
1972 auf 1974 geaendert, ARIA wusste das nicht und beharrte auf 1972
(weil ihr letzter Conversation-Turn noch '1972' enthielt). Sie konnte
auch nicht nachpruefen, sagte selbst: "Qdrant kann ich nicht aktiv
durchsuchen".
Fix: zwei neue Meta-Tools im agent.py.
memory_search(query, mode='text'|'semantic', k=5):
- Volltext oder semantic via store.search_text / store.search
- Liefert Liste mit Titel, ID, Content, Anhaengen
- Tool-Description sagt explizit: "Memory ist Truth ueber dem
Conversation-Window" — wenn beide unterschiedlich sind, gilt
Memory. Plus Anker-Anwendungsfaelle: 'schau in deinem Gedaechtnis',
'ich hab das aktualisiert', 'pruef ob's schon was zum Thema gibt'
memory_update(id, title?, content?, category?, tags?, pinned?):
- Patch existierender Memory per ID (aus memory_search oder Cold-Memory)
- Content-Change triggert Re-Embedding fuer Search, sonst nur
Payload-Update
- Pushed memory_saved-Event analog zu memory_save (App/Diagnostic
refreshen)
- Tool-Description empfiehlt explizit Update statt neuem Save bei
Korrekturen/Ergaenzungen — vermeidet Fragmentierung
Damit kann Stefan jetzt sagen "schau in deinem Gedaechtnis" und ARIA
findet den aktualisierten Eintrag. Plus bei spaeteren Korrekturen
("ach nee, 1974") nutzt ARIA memory_update statt memory_save +
hinterlaesst einen sauberen Eintrag.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
31a1370050 |
feat(brain): memory_save mit attach_paths — ARIA haengt Bilder selbst an
Letzter Baustein vor Stefan's End-to-End-Test:
memory_attachments.attach_from_path(memory_id, src_path):
- Kopiert eine bestehende Datei aus /shared/uploads/ oder
/shared/memory-attachments/ in das Anhang-Verzeichnis der Memory
- Pfadschutz: nur ALLOWED_SOURCE_PREFIXES (/shared/uploads/,
/shared/memory-attachments/) — kein Zugriff auf Root-FS oder
SSH-Keys
- Groessen-Limit wie save_attachment (20 MB Default)
agent.py memory_save:
- Neuer optionaler Parameter `attach_paths: List[str]`
- Nach dem upsert: pro Pfad attach_from_path → Payload update mit
neuen Anhang-Metadaten
- Fehler beim Anhang sind nicht fatal (Memory bleibt gespeichert,
Hinweis in der Tool-Response)
- Tool-Description deutlich erweitert: expliziter Workflow-Hinweis
bei Bildern → erst `Read <pfad>` aufrufen (Claude Code Read ist
multi-modal), Texte/Kennungen/Marken in den content extrahieren,
dann erst memory_save mit attach_paths. Beispiel-Workflow als
Pseudocode mit Cessna 172 / Kennung D-EAAA.
End-to-End-Workflow ist jetzt einarmig moeglich:
User: "Ich hab eine Cessna 172" + Bild im Attachment
ARIA: Read /shared/uploads/aria_xy.jpg → sieht "Kennung D-EAAA"
ARIA: memory_save(content="Stefan besitzt eine Cessna 172,
Kennung D-EAAA, weiss/rot lackiert.",
attach_paths=["/shared/uploads/aria_xy.jpg"])
→ 🧠-Bubble mit Anhang in der App
→ Spaetere Frage "welche Kennung hat mein Flieger?" liefert via
Cold-Memory den Eintrag inkl. Kennung aus dem content
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
d5531521fa |
feat(memory): Anhaenge in App-Bubble + System-Prompt (Stufe C + D)
Stufe C — App:
- ChatMessage.memorySaved.attachments [{name, mime, size, path, localUri}]
- memory_saved-Listener uebernimmt payload.attachments
- renderMessage memorySaved-Bubble zeigt Anhaenge als Tap-Reihen
(Icon 🖼/📄 + Filename + Hint). Tap → file_request via Bridge,
beim ersten Mal "(tippen zum Laden)" → nach file_response cached
+ bei Bildern setFullscreenImage, bei anderen openFileWithIntent
- file_response-Handler updated zusaetzlich memorySaved.attachments
per serverPath-Match
- Styles fuer memoryAttachmentRow/Icon/Name/Meta
Stufe D — System-Prompt:
- prompts._attachments_line: pro Memory eine Zeile
"📎 Anhaenge: foo.jpg (image/jpeg, 109 KB) — Pfad: /shared/memory-attachments/<id>/"
- Wird in build_hot_memory_section + build_cold_memory_section
nach dem Content angehangen
- ARIA "weiss" damit dass Anhaenge da sind und kann via Bash darauf
zugreifen (file, head, base64 …). Echt sehen kann sie sie erst mit
Multi-Modal-Pipeline (Stufe E)
- memory_save Dispatcher: attachments-Liste auch im memory_saved-Event
(vermutlich [] beim Save, aber konsistent fuer spaeteres
Speichern-mit-Anhaengen-Pattern)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
1e754910ee |
fix(brain): Cold Memory mit Score-Threshold — kein Crosstalk mehr
Bug: Agent.chat() rief store.search() OHNE score_threshold — die
Top-5 wurden ungefiltert in den 'Moeglicherweise relevant'-Block
des System-Prompts gepackt. Bei kleiner DB hatte das absurde Folgen:
Stefan fragte 'hab ich ein flugzeug?', Cold-Search lieferte Top-1
'Watcher-Latenzproblem' mit Score 0.138 + 'Firmenadresse' mit 0.094,
ARIA wob die Firmenadresse in die Antwort ein ('Die Adresse habe ich
aus meinem Gedaechtnis...') — obwohl der User gar nicht danach gefragt
hat.
Fix: Konstante COLD_SCORE_THRESHOLD=0.30 in Agent eingefuehrt und an
store.search() durchgereicht. Treffer unter 0.30 werden als Rauschen
verworfen, ARIA bekommt nur substantielle Memories ins Cold-Set.
Konsistent mit dem Threshold im /memory/search HTTP-Endpoint und dem
Diagnostic UI.
MiniLM-multilingual gibt fuer unverwandte deutsche Texte gerne 0.10-
0.25 Score — alles darunter ist Embedder-Noise, kein echter Bezug.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
df60bb6d74 |
fix(brain): Cessna-Beispiel aus System-Prompt raus — keine Phantom-Wissens-Hinweise
ARIA hatte beim 'weisst du ob ich ein Flugzeug habe?'-Test richtig
geantwortet ('nein'), aber transparent erklaert dass sie das Wort
'Cessna' aus dem memory_save Tool-Description kennt — wo es als
Beispiel fuer den fact-Type stand. Ein Beispiel-Text der jedes
Chat-Turn im System-Prompt landet ist suboptimal, auch wenn ARIA
ihn korrekt einordnet.
Fix: das konkrete Beispiel durch eine generische Aufzaehlung
ersetzt (Vorlieben/Besitz/Orte/Termine/Personen). Ohne Stefan-
spezifisches Phantom-Wissen. Selber Spirit in der search-text
Docstring im main.py (geht zwar nicht in den Prompt, aber lieber
konsistent).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
5f96ace469 |
feat(brain): memory_save Tool — ARIA schreibt selber in die Qdrant-DB
ARIA hatte bisher KEIN Tool um eigene Notizen sauber zu persistieren — sie ist deshalb aufs Claude-Code-File-Memory ausgewichen (das wir mit dem letzten Commit per tmpfs abgeklemmt haben). Jetzt schliesst sich der Loop: ein echtes memory_save-Tool gegen die Qdrant-DB. Brain: - agent.py: memory_save als Meta-Tool mit Schema (title, content, type, optional category/tags/pinned). Tool-Description erklaert die Type-Wahl (identity/rule/preference/tool/skill = pinned, fact/conversation/reminder = cold) und sagt explizit: "Du hast KEIN File-Memory mehr, schreibe nicht in ~/.claude/projects/..." - Dispatcher: validiert type-enum, ruft self.embedder.embed + self.store.upsert, pushed memory_saved als _pending_events damit Bridge eine Bubble broadcasten kann. Side-Channel-Pipeline (gleich wie skill_created/trigger_created): - Bridge send_to_core + _handle_trigger_fired: forwarden memory_saved als RVS-Event - rvs/server.js: ALLOWED_TYPES += memory_saved - diagnostic/server.js: relayed memory_saved von RVS an Browser - diagnostic UI: addMemorySavedBubble (gelber Border) + Auto-Refresh des Gehirn-Tabs wenn aktiv - android: ChatMessage.memorySaved-Feld, Listener fuer memory_saved, renderMessage-Spezialbubble, History-Replace-Schutz (lokal-only) Damit ist die Architektur konsistent: "merk dir X" → ARIA ruft memory_save → Eintrag in Qdrant → Diagnostic-Gehirn-Tab zeigt's sofort → bei naechstem Turn liefert Cold Memory (Semantic Search) das Wissen wieder rein. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
8c74b3fed8 |
fix(brain): Timer in 2min funktioniert wieder — Zeit im Prompt + in_seconds-Param
ARIA wusste nicht wieviel Uhr es ist (kein Bash, kein Time-Tool, kein
Timestamp im System-Prompt) und konnte fires_at als ISO-UTC schlicht
nicht ausrechnen. Zwei Fixes:
1. prompts.py: build_time_section() injiziert UTC + lokale Zeit
(Europa/Berlin Sommer/Winter-Heuristik) als '## Aktuelle Zeit'-Block
oben in den System-Prompt. Hilft auch beim Einordnen von
Watcher-Conditions wie hour_of_day == 8.
2. agent.py trigger_timer-Tool: neuer Parameter `in_seconds` als
Alternative zu fires_at. Bei relativen Angaben ('in 2 Minuten')
rechnet jetzt der Server den absoluten Timestamp aus — keine
Rechnerei in der LLM noetig. fires_at bleibt fuer feste Termine.
required nur noch name + message.
Diagnostic-API (/triggers/timer) bleibt absolute-only, da der Browser
selbst datetime hat.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
fa47068d6d |
feat(gps): kontinuierliches GPS-Tracking — Blitzer-Warner-Pipeline komplett
ARIA kann jetzt GPS-Watcher mit near() effektiv nutzen: die App liefert
kontinuierliche Position, Brain wertet sie in den Background-Triggers aus.
rvs/server.js
ALLOWED_TYPES: location_update (App→Bridge) + location_tracking (Brain→App).
bridge/aria_bridge.py
location_update Handler: persistiert {lat, lon} via _persist_location in
/shared/state/location.json — selber Pfad wie chat/audio-events, aber als
eigenes Event ohne Chat-Overhead.
aria-brain/agent.py
Neues Meta-Tool request_location_tracking(on, reason). Dispatcher fuegt
{type: "location_tracking", on, reason} zu _pending_events hinzu →
Bridge forwarded als RVS-Message zur App.
aria-brain/prompts.py
Trigger-Section bekam neuen Block "GPS-Watcher mit near()": ARIA wird
angewiesen request_location_tracking(on=true) zu rufen wenn sie einen
near()-Watcher anlegt, und wieder false beim Loeschen des letzten.
android/src/services/gpsTracking.ts (NEU)
Singleton-Service. start(reason) → Geolocation.watchPosition mit
distanceFilter 30m + interval 15s, sendet location_update an RVS.
stop(reason) → clearWatch. Persistiert Status in 'aria_gps_tracking',
restoreFromStorage() beim Settings-Mount. Permission-Request fuer
ACCESS_FINE_LOCATION + Toast-Benachrichtigung bei An/Aus.
android/src/screens/SettingsScreen.tsx
Neuer Switch im "Standort"-Block: "GPS-Tracking (kontinuierlich)" mit
Hinweis-Text. Subscribe auf gpsTrackingService.onChange damit Toggle
reflektiert wenn ARIA das per Tool umschaltet.
RVS-Handler: location_tracking → gpsTrackingService.start/stop mit
Reason aus Brain-Tool.
Ablauf Stefan→ARIA→Blitzer:
1. Stefan: "Warn mich vor Blitzern auf Route nach Rhauderfehn"
2. ARIA: skill_create("blitzer-warner") falls noch nicht da
3. ARIA: run_blitzer-warner → Liste {lat,lon,name}
4. ARIA: pro Eintrag trigger_watcher mit near(lat,lon,500)
5. ARIA: request_location_tracking(on=true, reason="Blitzer-Warner aktiv")
6. App: GPS-Tracking startet, sendet alle 15s location_update
7. Bridge: /shared/state/location.json wird aktuell gehalten
8. Brain-Background-Loop: alle 30s near()-Check pro Trigger
9. Bei Erfolg: ARIA spricht "Blitzer A31 km 12 in 500m"
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
07c761fc72 |
feat(brain): GPS-Variablen + near()-Helper + erweiterte Condition-Vars
ARIA kann jetzt GPS-basierte Watcher-Trigger anlegen (Blitzer-Warner-Use-Case),
plus erweiterte Time-, System- und Activity-Variablen.
bridge/aria_bridge.py
_persist_state() schreibt atomar nach /shared/state/<key>.json.
Bei jedem chat- und audio-Event:
- location → /shared/state/location.json {lat, lon, ts_unix}
- last_user_ts → /shared/state/activity.json
Brain-Watcher lesen das fuer die GPS- und Activity-Variablen.
aria-brain/watcher.py — komplett ueberarbeitet
Neue Variablen-Sets:
GPS: current_lat, current_lon, location_age_sec (-1 = nie gesehen)
Zeit (+): minute_of_hour, day_of_month, month, year, is_weekend, unix_timestamp
System: ram_free_mb (MemAvailable), cpu_load_1min (loadavg)
Activity: last_user_message_ago_sec
Memory: pinned_count (zusaetzlich zu memory_count)
Neue Funktion fuer Conditions:
near(lat, lon, radius_m) Haversine-Distanz von current_lat/lon
zum Punkt. False wenn keine Position bekannt.
Parser-Erweiterung:
ast.Call jetzt erlaubt, ABER nur fuer direkte Funktionsnamen aus der
Whitelist (_ALLOWED_FUNCTIONS = {"near"}). Keine Attribute-Access,
keine Keywords, Args nur Constants/Names/UnaryOp.
Selbsttest blockt korrekt:
__import__("os")... → "Funktionsaufruf nur ueber direkten Namen"
memory_count.__class__ → "Verbotener Ausdruck: Attribute"
(lambda: 1)() → "Funktionsaufruf nur ueber direkten Namen"
aria-brain/main.py
/triggers/conditions liefert jetzt zusaetzlich {functions:[...]} mit
Signaturen + Beschreibungen. current-Snapshot filtert callable() raus
damit JSON serialisierbar bleibt.
aria-brain/prompts.py + agent.py
build_triggers_section bekommt condition_funcs als 4tes Argument und
listet die im System-Prompt unter "Verfuegbare Funktionen". Operatoren-
Hinweis ergaenzt mit Beispielen + Regeln (keine Variablen in Funktions-
Args, keine Schachtelung).
diagnostic/index.html
Trigger-Create-Modal: Variablen-Info-Block zeigt jetzt sowohl Variablen
(mit aktuellen Werten) als auch Funktionen (Signatur + Beschreibung).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
31aa86a2a9 |
feat(brain+ui+app): Triggers — passive Aufweck-Quellen fuer ARIA
ARIA hatte bisher nur ein "User fragt → Brain antwortet"-Modell. Neu:
Trigger laufen passiv im Hintergrund (kein LLM-Call) und wecken ARIA
nur dann auf wenn ein Event tatsaechlich passiert.
Drei Typen, zwei aktuell implementiert:
timer — einmalig zu festem ISO-Timestamp ("erinner mich in 10min")
watcher — Polling alle N Sek einer Condition, feuert bei True mit Throttle
(z.B. "disk_free_gb < 5", max 1x/h)
cron — Platzhalter fuer spaeter
aria-brain/triggers.py
CRUD auf /data/triggers/<name>.json + /data/triggers/logs/<name>.jsonl.
create_timer, create_watcher, mark_fired, list_logs, etc.
aria-brain/watcher.py
Built-in Condition-Variablen: disk_free_gb, disk_free_pct, uptime_sec,
hour_of_day, day_of_week, rvs_connected, memory_count.
Sicherer Condition-Parser via ast — Whitelist auf Vergleich + BoolOp +
Name + Const. Kein eval, kein exec, keine Builtins.
aria-brain/background.py
Async Loop laeuft alle 30s, sammelt einmalig Variables, geht durch
Trigger-Liste, _should_fire-Check (Timer: fires_at vergangen / Watcher:
check_interval + throttle respektiert + condition true). Fire ruft
agent.chat(prompt, source="trigger") — ARIA bekommt das wie eine
Push-Nachricht und antwortet via Bridge → RVS → App.
aria-brain/main.py
/triggers/list, /{name}, /{name}/logs, /timer, /watcher, PATCH, DELETE,
/triggers/conditions (Variablen + aktuelle Werte). Lifespan-Handler
startet den Background-Loop beim Container-Start, stoppt beim Shutdown.
aria-brain/agent.py
Meta-Tools fuer ARIA: trigger_timer, trigger_watcher, trigger_cancel,
trigger_list. ARIA legt Trigger via Tool-Call selbst an wenn Stefan das
wuenscht. Side-Channel-Event 'trigger_created' wird in chat-Response
mitgeschickt damit App + Diagnostic eine Bubble zeigen.
aria-brain/prompts.py
Neue System-Prompt-Section: Liste aktiver Triggers + verfuegbare
Condition-Variablen mit aktuellen Werten + Operatoren-Erklaerung.
ARIA weiss damit immer was es schon gibt und welche Vars sie nutzen kann.
bridge/aria_bridge.py + rvs/server.js
trigger_created als neuer RVS-Message-Type, Bridge forwarded das aus
data.events analog zu skill_created.
diagnostic/index.html
Neuer Top-Tab "Trigger". Liste mit Type-Badges (⏱ TIMER / 👁 WATCHER),
Status, Fire-Count, last_fired. Aktivieren/Deaktivieren + Löschen pro
Trigger. "+ Neu"-Modal mit Type-Dropdown, Timer-Minuten oder
Watcher-Condition + Vars-Anzeige + Throttle. Info-Modal-Eintrag mit
Erklaerung. Live-Bubble im Chat wenn ARIA selbst einen anlegt.
android/src/screens/ChatScreen.tsx
trigger_created RVS-Handler → eigene Bubble (gelber Border, "⏰ ARIA
hat einen Trigger angelegt", Type/Detail/Message/Zeit). ChatMessage
bekam triggerCreated-Feld. Lokal-only-Schutz beim Server-Sync analog
zu skill_created.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
70d1500096 |
feat(brain): Phase B — Vector-DB-Memory, Conversation-Loop, Skills, Tool-Use
OpenClaw (aria-core) ist raus, ARIA laeuft jetzt mit eigenem Agent-Framework
im aria-brain Container. Vector-DB-basiertes Gedaechtnis statt Sessions,
eigener Conversation-Loop mit Hot+Cold-Memory + Rolling Window, Tool-Use
fuer Skills, Memory-Destillat-Pipeline.
aria-brain/ (neuer Container)
- main.py FastAPI auf 8080, alle Endpoints
- agent.py Conversation-Loop mit Tool-Use (skill_create + run_<skill>)
- conversation.py Rolling Window, JSONL-Persistenz, Distill-Marker
- proxy_client.py httpx-Wrapper zum Claude-Proxy, OpenAI-Format
- prompts.py System-Prompt aus Hot+Cold+Skills
- migration.py Markdown-Parser fuer brain-import/ → atomare Memories
- skills.py Filesystem-Layer fuer /data/skills/<name>/ (Python-only,
venv pro Skill, tar.gz Export/Import, Run-Logs)
- memory/ Embedder (sentence-transformers, multilingual MiniLM)
+ VectorStore (Qdrant-Wrapper)
docker-compose.yml
- aria-core (OpenClaw) raus, openclaw-config Volume raus
- aria-brain Service (FastAPI + Memory)
- aria-qdrant Service (Vector-DB) mit Bind-Mount aria-data/brain/qdrant/
- Diagnostic teilt jetzt Netzwerk mit Bridge (vorher: aria-core)
- Brain bekommt SSH-Mount fuer aria-wohnung + /import fuer brain-import/
bridge/aria_bridge.py
- send_to_core → HTTP-Call an aria-brain:8080/chat (statt OpenClaw-WS)
- aria-core-spezifische Handler raus: doctor_fix, aria_restart,
aria_session_reset, Auto-Compact-Logik, OpenClaw-Handshake
- Generischer container_restart-Handler (Whitelist Bridge/Brain/Qdrant)
- Side-Channel-Events aus /chat-Response (z.B. skill_created) werden
als RVS-Events forwarded
- file_list_request / file_delete_request → an Diagnostic forwarded
- Tote OpenClaw-Connection-Logik bleibt im Code als Referenz (nicht aktiv)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|