How-to: Mod erstellen & extern verlinken¶
Typ: How-to Guide (Diátaxis) Lerne: Wie erstelle ich ein neues ToolBoxV2-Mod — im Terminal UND im Code.
1. Mod-Struktur¶
Jedes Mod lebt unter toolboxv2/mods/<ModName>/:
toolboxv2/mods/MyMod/
├── __init__.py # Mod-Entry-Point
├── main.py # Hauptlogik (optional)
├── helpers.py # Hilfsfunktionen (optional)
└── static/ # Statische Dateien (optional)
Externe Ordner verlinken¶
Wenn dein Mod-Code außerhalb von toolboxv2/mods/ liegt:
# Symlink erstellen (Linux/Mac)
ln -s /path/to/external/MyMod toolboxv2/mods/MyMod
# Junction (Windows)
mklink /J toolboxv2\mods\MyMod C:\path\to\external\MyMod
Oder via __init__.py Forwarding:
# toolboxv2/mods/MyMod/__init__.py
import sys
sys.path.insert(0, "/external/path/to/")
from my_external_mod import *
2. Mod schreiben — Minimalbeispiel¶
__init__.py (Pflicht)¶
from toolboxv2 import App, Result, ToolBoxInterfaces # Core Types
# ============ MOD METADATA ============
MOD_NAME = "MyMod"
MOD_VERSION = "1.0.0"
# Wird beim Laden ausgeführt
def on_start(app):
"""Called when mod is loaded."""
app.logger.info(f"{MOD_NAME} v{MOD_VERSION} loaded")
return App.on_start_result
# Wird beim Entladen ausgeführt
def on_exit(app):
"""Called when mod is unloaded."""
app.logger.info(f"{MOD_NAME} unloaded")
return App.on_exit_result
# ============ EXPORTED FUNCTIONS ============
# Methode 1: @app.tb Decorator (empfohlen)
@app.tb(name="greet", mod_name=MOD_NAME, api=True)
async def greet(name: str = "World"):
"""Greet someone. Available via CLI, API, and ISAA."""
return Result.ok(
data=f"Hello {name}!",
info="greeting generated",
interface=ToolBoxInterfaces.cli
)
# Methode 2: Manuelles Registration
@app.tb(name="calculate", mod_name=MOD_NAME, api=True, level=1)
async def calculate(operation: str, a: float, b: float):
"""Do math. Level 1 = requires login."""
operations = {
"add": lambda x, y: x + y,
"sub": lambda x, y: x - y,
"mul": lambda x, y: x * y,
}
if operation not in operations:
return Result.error(
data=f"Unknown operation: {operation}",
info="valid: add, sub, mul"
)
result = operations[operation](a, b)
return Result.ok(data=result)
# Methode 3: Sync-Funktion (wird auto-wrapped)
@app.tb(name="health_check", mod_name=MOD_NAME, api=True)
def health_check():
"""Sync function — automatically wrapped async."""
return Result.ok(data={"status": "healthy", "mod": MOD_NAME})
3. Mod verwenden — Terminal¶
Installieren & Laden¶
# Mod laden (automatisch bei tb Start wenn unter mods/)
tb -l # Liste alle geladenen Mods
tb -i MyMod # Mod explizit installieren/installieren
# Nach Code-Änderungen: Enums regenerieren!
tb -l -sfe # Scan-for-enums: aktualisiert all_functions_enums.py
CLI Aufrufe¶
# Funktion aufrufen
tb -c MyMod greet --name "Alice"
# → Hello Alice!
# Mit Parameter
tb -c MyMod calculate --operation add --a 5 --b 3
# → 8.0
# Health check
tb -c MyMod health_check
# → {"status": "healthy", "mod": "MyMod"}
# Debug-Modus (hot-reload bei Code-Änderung)
tb -c MyMod greet --name "Bob" --debug
API Aufrufe (HTTP)¶
# GET health
curl http://localhost:8500/api/MyMod/health_check
# POST mit JSON
curl -X POST http://localhost:8500/api/MyMod/calculate \
-H "Content-Type: application/json" \
-d '{"operation": "add", "a": 5, "b": 3}'
4. Mod in Code verwenden (Python)¶
from toolboxv2 import get_app
app = get_app(name="my-app")
# Mod-Funktion aufrufen
result = await app.a_run_any("MyMod.greet", name="Alice")
print(result.get()) # → "Hello Alice!"
# Oder direkt
result = await app.a_run_any("MyMod.calculate", operation="mul", a=4, b=7)
print(result.get()) # → 28.0
# ISAA Agent mit Mod-Tool ausstatten
builder = app.get_agent_builder()("my_agent")
agent = (
builder
.add_tool("MyMod.greet")
.add_tool("MyMod.calculate")
.build()
)
5. Fortgeschritten: RequestData & Session¶
@app.tb(name="user_data", mod_name=MOD_NAME, api=True, request_as_kwarg=True)
async def user_data(request, session=None):
"""Access user session data."""
if session is None or not session.is_authenticated:
return Result.error(data="Not authenticated", info="401")
user_id = session.user_id
# ... do user-specific work ...
return Result.ok(data={"user": user_id, "level": session.level})
6. Fortgeschritten: FileHandler für Configs¶
from toolboxv2.utils.system.file_handler import FileHandlerV2, StorageScope
@app.tb(name="get_config", mod_name=MOD_NAME)
async def get_config():
"""Load mod config (encrypted, auto-local)."""
fh = FileHandlerV2("mymod.config", name=MOD_NAME)
await fh.aload()
return Result.ok(data=fh.to_dict())
@app.tb(name="set_config", mod_name=MOD_NAME)
async def set_config(key: str, value: str):
"""Save mod config."""
fh = FileHandlerV2("mymod.config", name=MOD_NAME)
await fh.aload()
await fh.aset(key, value)
await fh.asave()
return Result.ok(data="saved")
7. Cheat Sheet¶
| Was | Terminal | Code |
|---|---|---|
| Mod laden | tb -l |
app.a_add_mod("MyMod") |
| Enums aktualisieren | tb -l -sfe |
— (auto-generated) |
| Funktion aufrufen | tb -c MyMod greet |
await app.a_run_any("MyMod.greet") |
| Alle Funktionen | tb -c MyMod --help |
app.mods_functions["MyMod"] |
| Debug/Hot-reload | --debug flag |
— |
| Config speichern | tb -c MyMod set_config |
FileHandlerV2("mymod.config") |
| API exponieren | @app.tb(api=True) |
auto-routed bei Worker-Start |
Related¶
- Core Types —
AppType,Result,@tbDecorator - FileHandlerV2 — Config/Data Storage
- All Functions Enums — Dispatch-Tabelle
- Toolbox Integration — AccessController, API Routing
- Onboarding — Installation