feat(config,policy): skill sets per kind, master without vault skills, attachments in the vault, crons in local tz
This commit is contained in:
@@ -27,6 +27,7 @@ __all__ = [
|
||||
"TRIAGE_DISALLOWED",
|
||||
"Zones",
|
||||
"bash_zones",
|
||||
"forbid_skills",
|
||||
"requires_skill",
|
||||
"skill_tracker",
|
||||
"vault_zones",
|
||||
@@ -220,15 +221,39 @@ def _pathlike(word: str) -> bool:
|
||||
)
|
||||
|
||||
|
||||
def _skill_name(call: ToolCall) -> str:
|
||||
"""Имя скилла из `Skill({"skill": "vault:firefly", ...})`, без плагина."""
|
||||
name = str(call.input.get("skill") or call.input.get("name") or "")
|
||||
return name.rsplit(":", 1)[-1]
|
||||
|
||||
|
||||
def skill_tracker() -> PolicyRule:
|
||||
"""Запоминает открытые скиллы в состоянии сессии (для `requires_skill`)."""
|
||||
|
||||
def rule(call: ToolCall) -> None:
|
||||
if call.tool != "Skill":
|
||||
return
|
||||
name = str(call.input.get("skill") or call.input.get("name") or "")
|
||||
opened: set[str] = call.state.setdefault("skills", set())
|
||||
opened.add(name.rsplit(":", 1)[-1])
|
||||
opened.add(_skill_name(call))
|
||||
|
||||
return rule
|
||||
|
||||
|
||||
def forbid_skills(names: tuple[str, ...], kinds: tuple[str, ...]) -> PolicyRule:
|
||||
"""§4.3: скиллы из ``names`` (fnmatch, без учёта регистра) в ``kinds`` закрыты.
|
||||
|
||||
Мастер их не открывает - для этого есть ветка; правило отвечает так,
|
||||
чтобы модель сама её открыла.
|
||||
"""
|
||||
patterns = tuple(p.lower() for p in names)
|
||||
|
||||
def rule(call: ToolCall) -> Deny | None:
|
||||
if call.tool != "Skill" or call.kind not in kinds:
|
||||
return None
|
||||
name = _skill_name(call)
|
||||
if not any(fnmatch.fnmatchcase(name.lower(), p) for p in patterns):
|
||||
return None
|
||||
return Deny(reason=f"скилл {name} недоступен в {call.kind}: открой ветку")
|
||||
|
||||
return rule
|
||||
|
||||
|
||||
Reference in New Issue
Block a user