feat(plugins): Stage 2.1 — plugin framework and AI tool-use

Introduces a standalone plugin system where every integration lives as
an independent Python script in ~/.pyra/plugins/, not hardcoded in core.

Plugin framework (src/pyra/plugins/):
- base.py: Tool dataclass, PyraPlugin Protocol, BasePlugin helper
- loader.py: importlib-based discovery; one bad plugin never crashes pyra
- registry.py: singleton aggregating tools, slash commands, system prompts
- executor.py: approval gate — scans args, prompts y/N, scans result, logs
- install.py: copies bundled_plugins/ to ~/.pyra/plugins/ on install

Chat integration:
- AI tool-use loop (litellm function calling, up to 10 iterations)
- Plugin system prompt additions injected per session
- Plugin slash commands merged with static commands

CLI additions:
- pyra plugin list/install/enable/disable/setup
- pyra daemon start/stop/status/restart/install/uninstall (stubs for 2.4)

Config: PluginConfig + DaemonConfig added to PyraConfig (backwards-compatible)
Bootstrap: ~/.pyra/plugins/ and ~/.pyra/logs/ created on startup
Security: tool args and results always injection-scanned; plugin dirs
validated with assert_safe_path() before loading (symlink protection)

Tests: 37 new tests (loader, registry, executor, plugin isolation security)
161 total, all passing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
curo1305
2026-05-17 15:35:20 +02:00
parent 30cda28ec8
commit c0c0156468
21 changed files with 1569 additions and 59 deletions
+19
View File
@@ -25,6 +25,25 @@ dev = [
"pytest-asyncio>=0.23.0",
"ruff>=0.4.0",
]
nextcloud = ["caldav>=1.3.0", "webdav4>=0.9.0", "vobject>=0.9.6"]
matrix = ["matrix-nio>=0.24.0", "aiofiles>=23.0.0"]
telegram = ["python-telegram-bot>=21.0"]
ssh = ["paramiko>=3.4.0"]
docker = ["docker>=7.0.0"]
gdrive = ["google-api-python-client>=2.120.0", "google-auth-oauthlib>=1.2.0"]
onedrive = ["msal>=1.28.0"]
dropbox = ["dropbox>=12.0.0"]
daemon = ["aiofiles>=23.0.0"]
all-plugins = [
"caldav>=1.3.0", "webdav4>=0.9.0", "vobject>=0.9.6",
"matrix-nio>=0.24.0", "aiofiles>=23.0.0",
"python-telegram-bot>=21.0",
"paramiko>=3.4.0",
"docker>=7.0.0",
"google-api-python-client>=2.120.0", "google-auth-oauthlib>=1.2.0",
"msal>=1.28.0",
"dropbox>=12.0.0",
]
[project.scripts]
pyra = "pyra.cli:main"