84 lines
2.6 KiB
Python
84 lines
2.6 KiB
Python
"""声明式 Skill 激活:匹配、提示注入、Run 级工具别名和事件。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
from app.application.agent.prompt_composer import compose_system_messages
|
|
from app.application.agent.skill_loader import load_skill_manifests
|
|
from app.modules.runtime.events import Event
|
|
|
|
if TYPE_CHECKING:
|
|
from app.application.tool_runtime.view import RunScopedToolView
|
|
from app.modules.runtime.events import EventStore
|
|
|
|
|
|
class SkillExecutor:
|
|
"""把数据库 Skill 激活到当前 Run 的工具视图。"""
|
|
|
|
def __init__(
|
|
self,
|
|
tool_view: RunScopedToolView | None = None,
|
|
event_store: EventStore | None = None,
|
|
) -> None:
|
|
self._tool_view = tool_view
|
|
self._event_store = event_store
|
|
|
|
async def match_and_activate(
|
|
self,
|
|
context_text: str,
|
|
system_messages: list[str],
|
|
*,
|
|
run_id: str | None = None,
|
|
character_id: str | None = None,
|
|
skill_refs: tuple[str, ...] = (),
|
|
) -> list[str]:
|
|
"""匹配技能并把提示与别名写入当前 Run。"""
|
|
if not context_text:
|
|
return system_messages
|
|
|
|
manifests = await load_skill_manifests(context_text, skill_refs=skill_refs)
|
|
system_messages.extend(compose_system_messages([], None, manifests))
|
|
activated_names: list[str] = []
|
|
for manifest in manifests:
|
|
if self._tool_view is not None:
|
|
for tool_name in manifest.allowed_tools:
|
|
self._tool_view.bind_alias(
|
|
f"skill:{manifest.name}/{tool_name}",
|
|
tool_name,
|
|
description_prefix=f"[{manifest.name}] ",
|
|
)
|
|
activated_names.append(manifest.name)
|
|
|
|
if activated_names and self._event_store:
|
|
await self._emit_activation_event(
|
|
activated_names,
|
|
run_id=run_id,
|
|
character_id=character_id,
|
|
)
|
|
return system_messages
|
|
|
|
async def _emit_activation_event(
|
|
self,
|
|
skill_names: list[str],
|
|
*,
|
|
run_id: str | None = None,
|
|
character_id: str | None = None,
|
|
) -> None:
|
|
event_store = self._event_store
|
|
if event_store is None:
|
|
return
|
|
await event_store.append(
|
|
Event(
|
|
type="skill.activated",
|
|
source="skill_executor",
|
|
visibility="public",
|
|
run_id=run_id,
|
|
character_id=character_id,
|
|
payload={"skills": skill_names},
|
|
)
|
|
)
|
|
|
|
|
|
__all__ = ["SkillExecutor"]
|