feat: support registry collections and docker publishing
This commit is contained in:
@@ -56,3 +56,52 @@ def external_skill_path(name: str, entry: dict[str, Any] | None = None) -> Path:
|
||||
f"registry 条目 {name!r} 的 path 超出外部仓库: {subpath!r}"
|
||||
) from exc
|
||||
return skill_path
|
||||
|
||||
|
||||
def discover_external_skills(
|
||||
name: str,
|
||||
entry: dict[str, Any] | None = None,
|
||||
) -> dict[str, Path]:
|
||||
"""Discover a single registry skill or a collection of sibling skills."""
|
||||
entry = entry or load_registry().get(name, {})
|
||||
root = external_skill_path(name, entry)
|
||||
if (root / "SKILL.md").is_file():
|
||||
return {name: root}
|
||||
if not root.is_dir():
|
||||
return {}
|
||||
resolved_root = root.resolve()
|
||||
skills: dict[str, Path] = {}
|
||||
for item in sorted(root.iterdir()):
|
||||
skill_md = item / "SKILL.md"
|
||||
if (
|
||||
item.name.startswith("_")
|
||||
or item.is_symlink()
|
||||
or not item.is_dir()
|
||||
or skill_md.is_symlink()
|
||||
or not skill_md.is_file()
|
||||
):
|
||||
continue
|
||||
resolved_item = item.resolve()
|
||||
resolved_skill_md = skill_md.resolve()
|
||||
try:
|
||||
resolved_item.relative_to(resolved_root)
|
||||
resolved_skill_md.relative_to(resolved_item)
|
||||
except ValueError:
|
||||
continue
|
||||
skills[item.name] = item
|
||||
return skills
|
||||
|
||||
|
||||
def external_collection_skill_path(
|
||||
collection: str,
|
||||
skill_name: str,
|
||||
entry: dict[str, Any] | None = None,
|
||||
) -> Path:
|
||||
skills = discover_external_skills(collection, entry)
|
||||
if skill_name not in skills:
|
||||
available = ", ".join(skills) or "(无)"
|
||||
raise SystemExit(
|
||||
f"registry collection {collection!r} 中找不到 skill {skill_name!r}。"
|
||||
f"可用: {available}"
|
||||
)
|
||||
return skills[skill_name]
|
||||
|
||||
Reference in New Issue
Block a user