feat(brain): skill_scaffold — Templates statt Skill aus dem Nichts
Variante C: niedrigere Huerde zum Skill-Bau. Statt einen kompletten
Python-Skill via skill_create zu generieren (~100 Zeilen Code, teuer in
Tokens und fehleranfaellig), waehlt ARIA ein Template + minimale params,
Brain expandiert das Skelett in ~1s zu fertigem Skill.
Beobachtung: ARIA driftet bei Spotify, PDF etc. zu Bash-curl statt
einen Skill zu bauen, weil die Skill-Bau-Huerde zu hoch ist (Code,
README, args, pip_packages, config_schema). Mit Templates ist die
Huerde minimal.
Neue Module:
- aria-brain/skill_templates.py: drei mitgelieferte Templates
- oauth-api: OAuth2-API (Spotify, GitHub, Reddit, Google, Discord, ...).
Token via BRAIN_INTERNAL_URL/oauth/<s>/token mit Auto-Refresh.
Args: method/path/body/base_url
- apikey-api: API mit statischem Key (OpenWeather, OpenAI, Twilio).
Key liegt im config_schema -> CFG_<NAME> ENV, KEIN hardcoden.
Konfigurierbar: auth_header (Authorization|X-Api-Key), auth_prefix.
- file-process: Skelett fuer File-In/File-Out (PDF, Bild, JSON).
process()-Funktion ist Stub, ARIA fuellt sie via skill_update.
Templates nutzen Token-Replacement statt f-Strings (sonst Konflikt
mit dem skill-internen Python-Code).
- aria-brain/skills.py: scaffold_skill(name, template, params, author)
wrappt create_skill mit den expandierten Feldern.
- aria-brain/agent.py: neues Brain-Tool skill_scaffold mit detaillierter
Description (Template-Liste + params-Schema). Dispatcher-Handler
schickt skill_created Side-Channel-Event analog zu skill_create.
- aria-brain/main.py: POST /skills/scaffold + GET /skills/templates
(letzteres listet alle Templates fuer UI/Diagnostic).
- 11. seed_rule scaffold-reflex: bei 2x derselben API per Bash-curl
SOFORT skill_scaffold rufen. Belohnung explizit benannt
("welches lied" von 20s auf 3s).
README mit Skills-Scaffold-Tabelle ergaenzt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -186,6 +186,47 @@ META_TOOLS = [
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "skill_scaffold",
|
||||
"description": (
|
||||
"ERSTE WAHL fuer Skill-Bau wenn das Muster zu einem Template passt — "
|
||||
"Brain expandiert das Skelett, Du sparst Dir das vollstaendige "
|
||||
"Python-Programm zu generieren. Wenn Stefan eine externe API "
|
||||
"mehrmals nutzt: SOFORT `skill_scaffold` statt jedes Mal "
|
||||
"ad-hoc Bash-curl.\n\n"
|
||||
"Verfuegbare Templates:\n"
|
||||
" - **oauth-api**: OAuth2-API (Spotify, GitHub, Reddit, Google, Discord, …). "
|
||||
"Token kommt vom Brain mit Auto-Refresh. params: "
|
||||
"`{service:'spotify', base_url?:'https://...'}`\n"
|
||||
" - **apikey-api**: API mit statischem Key (OpenWeather, OpenAI, Twilio). "
|
||||
"Key liegt im skill.json config_schema → CFG_<NAME> ENV. params: "
|
||||
"`{api_name:'OpenWeather', key_env:'OWM_API_KEY', auth_header?:'Authorization', auth_prefix?:'Bearer ', base_url:'https://...'}`\n"
|
||||
" - **file-process**: Skelett fuer Datei-In/Datei-Out (PDF, Bild, JSON umformen). "
|
||||
"process()-Funktion ist Stub — danach `skill_update` mit echtem Code. params: "
|
||||
"`{output_ext:'txt'}`\n\n"
|
||||
"Nach Scaffold kannst Du das Skelett via `skill_update` weiter "
|
||||
"anpassen falls noetig (mehr pip_packages, andere args, …). "
|
||||
"Aber meistens reicht das Template direkt.\n\n"
|
||||
"Wenn kein Template passt: erst pruefen ob Du wirklich ein "
|
||||
"kustomes brauchst, sonst lieber Template + Update."
|
||||
),
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string",
|
||||
"description": "Skill-Name (kebab-case, ohne Versionssuffix)"},
|
||||
"template": {"type": "string",
|
||||
"enum": ["oauth-api", "apikey-api", "file-process"],
|
||||
"description": "Eines der drei Templates"},
|
||||
"params": {"type": "object",
|
||||
"description": "Template-spezifische Parameter (siehe description)"},
|
||||
},
|
||||
"required": ["name", "template"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
@@ -945,6 +986,35 @@ class Agent:
|
||||
},
|
||||
})
|
||||
return f"OK — Skill '{manifest['name']}' erstellt (active={manifest['active']})."
|
||||
if name == "skill_scaffold":
|
||||
skill_name = (arguments.get("name") or "").strip()
|
||||
template = (arguments.get("template") or "").strip()
|
||||
params = arguments.get("params") or {}
|
||||
if not skill_name or not template:
|
||||
return "FEHLER: name + template erforderlich."
|
||||
try:
|
||||
manifest = skills_mod.scaffold_skill(
|
||||
name=skill_name, template=template, params=params, author="aria",
|
||||
)
|
||||
except ValueError as exc:
|
||||
return f"FEHLER: {exc}"
|
||||
# Side-Channel-Event analog zu skill_create
|
||||
self._pending_events.append({
|
||||
"type": "skill_created",
|
||||
"skill": {
|
||||
"name": manifest["name"],
|
||||
"description": manifest.get("description", ""),
|
||||
"execution": manifest.get("execution", ""),
|
||||
"active": manifest.get("active", True),
|
||||
"setup_error": manifest.get("setup_error"),
|
||||
"scaffolded_from": template,
|
||||
},
|
||||
})
|
||||
return (
|
||||
f"OK — Skill '{manifest['name']}' aus Template '{template}' angelegt. "
|
||||
f"active={manifest['active']}. "
|
||||
f"Falls noetig: skill_update fuer custom Code, skill_set_config fuer secrets."
|
||||
)
|
||||
if name == "skill_list":
|
||||
items = skills_mod.list_skills(active_only=False)
|
||||
if not items:
|
||||
|
||||
Reference in New Issue
Block a user