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>
This commit is contained in:
@@ -194,14 +194,59 @@ def _setup_venv(skill_dir: Path, pip_packages: list[str]) -> None:
|
||||
|
||||
|
||||
def update_skill(name: str, patch: dict) -> dict:
|
||||
"""Aktualisiert einen bestehenden Skill. Manifest-Felder ueber den
|
||||
`allowed`-Filter, Code-Aenderungen ueber dedizierte Keys:
|
||||
|
||||
- `entry_code` (str) → ueberschreibt run.py / run.sh
|
||||
- `readme` (str) → ueberschreibt README.md
|
||||
- `pip_packages` (list) → ueberschreibt requirements.txt + venv-Rebuild
|
||||
(nur bei local-venv)
|
||||
"""
|
||||
manifest = read_manifest(name)
|
||||
if manifest is None:
|
||||
raise ValueError(f"Skill '{name}' nicht gefunden")
|
||||
d = _skill_dir(name)
|
||||
allowed = {"description", "args", "requires", "active", "version", "entry"}
|
||||
for k, v in patch.items():
|
||||
if k in allowed:
|
||||
manifest[k] = v
|
||||
|
||||
# Code austauschen
|
||||
if "entry_code" in patch and patch["entry_code"]:
|
||||
execution = manifest.get("execution", "local-venv")
|
||||
if execution == "local-venv":
|
||||
entry_path = d / "run.py"
|
||||
entry_path.write_text(patch["entry_code"], encoding="utf-8")
|
||||
else:
|
||||
entry_path = d / "run.sh"
|
||||
content = patch["entry_code"] if patch["entry_code"].startswith("#!") else "#!/usr/bin/env bash\nset -euo pipefail\n" + patch["entry_code"]
|
||||
entry_path.write_text(content, encoding="utf-8")
|
||||
entry_path.chmod(0o755)
|
||||
|
||||
# README austauschen
|
||||
if "readme" in patch and patch["readme"] is not None:
|
||||
(d / "README.md").write_text(patch["readme"], encoding="utf-8")
|
||||
|
||||
# pip_packages geaendert → requirements.txt + venv neu aufbauen
|
||||
if "pip_packages" in patch and manifest.get("execution") == "local-venv":
|
||||
pip_packages = patch["pip_packages"] or []
|
||||
(d / "requirements.txt").write_text("\n".join(pip_packages) + "\n", encoding="utf-8")
|
||||
# venv loeschen + neu aufbauen, damit alte Pakete weg sind
|
||||
venv = d / "venv"
|
||||
if venv.exists():
|
||||
shutil.rmtree(venv, ignore_errors=True)
|
||||
try:
|
||||
_setup_venv(d, pip_packages)
|
||||
# Falls vorher wegen Setup-Error deaktiviert war: jetzt frei
|
||||
manifest.pop("setup_error", None)
|
||||
manifest["active"] = patch.get("active", True)
|
||||
except Exception as exc:
|
||||
manifest["active"] = False
|
||||
manifest["setup_error"] = str(exc)[:500]
|
||||
logger.warning("Skill %s: venv-Rebuild fehlgeschlagen: %s", name, exc)
|
||||
|
||||
write_manifest(name, manifest)
|
||||
logger.info("Skill aktualisiert: %s (keys=%s)", name, sorted(patch.keys()))
|
||||
return manifest
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user