89 lines
3.4 KiB
Python
89 lines
3.4 KiB
Python
import os
|
||
from pathlib import Path
|
||
|
||
from pydantic import BaseModel, Field
|
||
|
||
from deerflow.config.runtime_paths import project_root, resolve_path
|
||
|
||
DEFAULT_ES_QUERY_ROUTING_PROMPT = """当用户的问题需要基于 Elasticsearch 查询语句(Query DSL)灵活构造、调整或执行查询时,必须优先使用 `es_query` 技能。
|
||
典型场景包括:根据用户条件动态组合 bool/must/filter/should、范围、聚合、排序或分页等 ES 查询;或者用户直接提供、要求修改 ES 语句并据此查询数据。
|
||
执行前先读取 `es_query` 技能的 SKILL.md,严格按照技能中的流程和参数调用;不要用通用搜索替代,也不要凭记忆臆测查询结果。
|
||
仅当问题确实需要 ES 数据查询时使用;纯概念解释、普通代码说明或与 ES 无关的问题不要调用。"""
|
||
|
||
|
||
class EsQueryRoutingConfig(BaseModel):
|
||
"""Prompt steering that routes flexible Elasticsearch queries to ``es_query``."""
|
||
|
||
enabled: bool = Field(
|
||
default=False,
|
||
description="Inject the es_query routing prompt into the agent system prompt.",
|
||
)
|
||
prompt: str = Field(
|
||
default=DEFAULT_ES_QUERY_ROUTING_PROMPT,
|
||
description="Editable system-prompt instructions for deciding when and how to use es_query.",
|
||
)
|
||
|
||
|
||
class SecurityScanConfig(BaseModel):
|
||
"""Toggle for the LLM-based skill security scanner."""
|
||
|
||
enabled: bool = Field(
|
||
default=True,
|
||
description=(
|
||
"When false, skip the LLM security scan applied to skill installs, "
|
||
"custom-skill edits, and rollbacks. The scan is then treated as 'allow'."
|
||
),
|
||
)
|
||
|
||
|
||
class SkillsConfig(BaseModel):
|
||
"""Configuration for skills system"""
|
||
|
||
use: str = Field(
|
||
default="deerflow.skills.storage.local_skill_storage:LocalSkillStorage",
|
||
description="Class path of the SkillStorage implementation.",
|
||
)
|
||
path: str | None = Field(
|
||
default=None,
|
||
description="Path to skills directory. If not specified, defaults to skills under the caller project root.",
|
||
)
|
||
container_path: str = Field(
|
||
default="/mnt/skills",
|
||
description="Path where skills are mounted in the sandbox container",
|
||
)
|
||
security_scan: SecurityScanConfig = Field(
|
||
default_factory=SecurityScanConfig,
|
||
description="LLM security-scan toggle for skill content.",
|
||
)
|
||
es_query_routing: EsQueryRoutingConfig = Field(
|
||
default_factory=EsQueryRoutingConfig,
|
||
description="Optional configurable routing prompt for the es_query skill.",
|
||
)
|
||
|
||
def get_skills_path(self) -> Path:
|
||
"""
|
||
Get the resolved skills directory path.
|
||
|
||
Returns:
|
||
Path to the skills directory
|
||
"""
|
||
if self.path:
|
||
# Use configured path (can be absolute or relative to project root)
|
||
return resolve_path(self.path)
|
||
if env_path := os.getenv("DEER_FLOW_SKILLS_PATH"):
|
||
return resolve_path(env_path)
|
||
return project_root() / "skills"
|
||
|
||
def get_skill_container_path(self, skill_name: str, category: str = "public") -> str:
|
||
"""
|
||
Get the full container path for a specific skill.
|
||
|
||
Args:
|
||
skill_name: Name of the skill (directory name)
|
||
category: Category of the skill (public or custom)
|
||
|
||
Returns:
|
||
Full path to the skill in the container
|
||
"""
|
||
return f"{self.container_path}/{category}/{skill_name}"
|