fix(brain): run_<skill> Tool-Namen safe escapen — Bindestriche kippten Tools-Liste
Beobachtung beim zweiten Live-Test (01:13:41): ARIA versuchte echten
Tool-Call `run_spotify` — bekam aber Error: 'No such tool available'.
Ursache: _skill_to_tool baute Tool-Namen via `run_{s['name']}`. Bei
Skills wie 'yt-dlp-download' wurde daraus 'run_yt-dlp-download' mit
Bindestrich. Anthropic-Tool-Name-Schema ist eigentlich [a-zA-Z0-9_-],
ABER der claude-max-api-proxy konvertiert intern auf OpenAI-Format
und faellt bei Bindestrichen um — wenn EIN Tool ungueltig ist, kippt
die GANZE Tool-Liste, ARIA sieht nichts von 'run_*' inklusive
'run_spotify' obwohl der ja Bindestrich-frei war.
Fix:
- _skill_to_tool: name = "run_" + re.sub(r"[^a-zA-Z0-9_]", "_", s["name"])
→ run_yt_dlp_download statt run_yt-dlp-download.
- Dispatcher: bei tool_name='run_X' wird zuerst X als skill_name probiert,
bei Miss wird ueber die Liste der existierenden Skills gemappt — der
Skill mit safe_name(name)==X wird dann genommen.
- Bypass-Lesson + Bypass-Section: gleiche safe-Logik fuer den
empfohlenen run_<tool>-String im Memory/Prompt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+22
-3
@@ -787,10 +787,18 @@ def _skill_to_tool(s: dict) -> dict:
|
||||
}
|
||||
if a.get("required"):
|
||||
required.append(name)
|
||||
# Tool-Namen duerfen in der Anthropic/Claude tool_use-API nur
|
||||
# [a-zA-Z0-9_-]{1,64} sein, aber der claude-max-api-proxy (OpenAI-
|
||||
# Format-Adapter) ist restriktiver und faellt bei Bindestrichen auf
|
||||
# die Nase — die GANZE Tool-Liste wird dann verworfen und ARIA
|
||||
# bekommt "No such tool available". Skill-Namen wie 'yt-dlp-download'
|
||||
# oder 'pdf-umfrage-generator' muessen daher zu run_yt_dlp_download
|
||||
# bzw. run_pdf_umfrage_generator gemappt werden.
|
||||
safe_name = "run_" + re.sub(r"[^a-zA-Z0-9_]", "_", s["name"])
|
||||
return {
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": f"run_{s['name']}",
|
||||
"name": safe_name,
|
||||
"description": s.get("description", "(ohne Beschreibung)"),
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
@@ -844,7 +852,7 @@ class Agent:
|
||||
count = ev["count"]
|
||||
migration_key = f"auto/skill-bypass/{skill_name}"
|
||||
title = f"Skill '{skill_name}' nutzen, nicht curl"
|
||||
run_tool = f"run_{skill_name.replace('-', '_')}"
|
||||
run_tool = "run_" + re.sub(r"[^a-zA-Z0-9_]", "_", skill_name)
|
||||
content = (
|
||||
f"WICHTIG fuer Performance + Stefans Wartezeit: "
|
||||
f"Skill '{skill_name}' existiert und deckt {host} ab. "
|
||||
@@ -1262,7 +1270,18 @@ class Agent:
|
||||
f"Sicherheits-Snapshot des vorherigen Stands: {res.get('safety_snapshot')}"
|
||||
)
|
||||
if name.startswith("run_"):
|
||||
skill_name = name[len("run_"):]
|
||||
# Tool-Namen sind 'safe' (nur _), Skill-Namen koennen aber
|
||||
# Bindestriche enthalten (z.B. yt-dlp-download). Wir suchen
|
||||
# zuerst exakt, dann ueber Underscore-zu-Bindestrich-Mapping.
|
||||
tool_suffix = name[len("run_"):]
|
||||
skill_name = tool_suffix
|
||||
if skills_mod.read_manifest(skill_name) is None:
|
||||
# ggf. Bindestriche zurueckmappen
|
||||
for cand in skills_mod.list_skills(active_only=False):
|
||||
cand_name = cand.get("name") or ""
|
||||
if re.sub(r"[^a-zA-Z0-9_]", "_", cand_name) == tool_suffix:
|
||||
skill_name = cand_name
|
||||
break
|
||||
res = skills_mod.run_skill(skill_name, args=arguments)
|
||||
snippet = (res.get("stdout") or "")[:2000] or "(kein stdout)"
|
||||
err = (res.get("stderr") or "")[:500]
|
||||
|
||||
@@ -164,8 +164,9 @@ def build_bypass_section(bypass_events: list[dict]) -> str:
|
||||
sname = ev["skill_name"]
|
||||
host = ev["host"]
|
||||
count = ev["count"]
|
||||
safe = re.sub(r"[^a-zA-Z0-9_]", "_", sname)
|
||||
lines.append(f"- gegen **{host}** ({count}x kuerzlich) → nutze "
|
||||
f"`run_{sname.replace('-', '_')}(...)` statt curl. "
|
||||
f"`run_{safe}(...)` statt curl. "
|
||||
f"Der Skill ist da. Nutze ihn.")
|
||||
lines.append("")
|
||||
return "\n".join(lines)
|
||||
|
||||
Reference in New Issue
Block a user