tightening

This commit is contained in:
John Lancaster
2026-06-21 22:12:02 -05:00
parent 3c7f7e61b7
commit 123c491413
29 changed files with 150 additions and 357 deletions
-1
View File
@@ -107,7 +107,6 @@ def build_skill_detail_payload(registry: DocsRegistry, skill_id: str) -> dict[st
"description": skill.description,
"version": skill.version,
"tags": list(skill.tags),
"depends_on": list(skill.depends_on),
"capabilities": list(skill.capabilities),
"resources": {
"document": skill.document_uri,
+3 -20
View File
@@ -88,22 +88,6 @@ def _render_prompt_markdown(content: str, arguments: dict[str, Any]) -> str:
return rendered
def _python_type(prompt_arg_type: str) -> type[Any]:
if prompt_arg_type == "string":
return str
if prompt_arg_type == "number":
return float
if prompt_arg_type == "integer":
return int
if prompt_arg_type == "boolean":
return bool
if prompt_arg_type == "array":
return list
if prompt_arg_type == "object":
return dict
return str
def _make_prompt_handler(content: str):
def prompt_handler(**kwargs: Any) -> str:
return _render_prompt_markdown(content, kwargs)
@@ -118,15 +102,14 @@ def _register_prompt_objects() -> None:
params: list[Parameter] = []
for arg_name, arg in sorted(prompt.arguments.items()):
arg_type = _python_type(arg.type)
annotations[arg_name] = arg_type
default = Parameter.empty if arg.required else arg.default
annotations[arg_name] = str
default = Parameter.empty if arg.required else None
params.append(
Parameter(
arg_name,
kind=Parameter.KEYWORD_ONLY,
default=default,
annotation=arg_type,
annotation=str,
)
)
-6
View File
@@ -60,7 +60,6 @@ def _build_skill_record(
version=metadata.version,
tags=tuple(metadata.tags),
capabilities=tuple(metadata.capabilities),
depends_on=tuple(metadata.depends_on),
document_uri=f"resource://skills/{metadata.id}/document",
document_relpath=stored.relpath.as_posix(),
document_content=stored.content,
@@ -160,11 +159,6 @@ def load_docs_registry(*, package_anchor: str, docs_root: str = "docs") -> DocsR
prompts_by_id[record.prompt_id] = record
prompts_in_load_order.append(record.prompt_id)
for skill_id, skill in skills_by_id.items():
for dependency in skill.depends_on:
if dependency not in skills_by_id:
raise ValueError(f"skill '{skill_id}' depends_on unknown skill '{dependency}'")
skills_in_order_tuple = tuple(skills_in_load_order)
prompts_in_order_tuple = tuple(prompts_in_load_order)
+1 -21
View File
@@ -2,8 +2,6 @@ import re
from collections.abc import Mapping
from pathlib import PurePosixPath
from typing import TYPE_CHECKING
from typing import Any
from typing import Literal
import yaml
from pydantic import Field
@@ -18,31 +16,13 @@ from .common import frozen_mapping
if TYPE_CHECKING:
from personal_mcp.registry.ingest.prompt import PromptFilesBundle
type PromptArgumentType = Literal[
"string",
"number",
"integer",
"boolean",
"array",
"object",
]
class PromptArgumentEntry(StrictFrozenModel):
"""Schema for a single prompt argument definition."""
type: PromptArgumentType
title: str | None = None
description: str | None = None
required: bool = False
default: Any | None = None
enum: tuple[str, ...] | None = None
@field_validator("enum")
@classmethod
def validate_enum(cls, value: tuple[str, ...] | None) -> tuple[str, ...] | None:
if value is not None and not value:
raise ValueError("enum must contain at least one value when provided")
return value
class PromptMetadata(StrictFrozenModel):
@@ -28,7 +28,6 @@ class SkillRecord(StrictFrozenModel):
version: str
tags: tuple[str, ...]
capabilities: tuple[str, ...]
depends_on: tuple[str, ...]
document_uri: str
document_relpath: str
document_content: str
@@ -116,7 +115,6 @@ class SkillPatternPayload(StrictFrozenModel):
version: str
description: str
tags: list[str]
depends_on: list[str]
capabilities: list[str]
resources: list[str]
@@ -128,7 +126,6 @@ class SkillPatternPayload(StrictFrozenModel):
version=record.version,
description=record.description,
tags=list(record.tags),
depends_on=list(record.depends_on),
capabilities=list(record.capabilities),
resources=list(record.capabilities),
)
+1 -35
View File
@@ -12,17 +12,14 @@ from .common import ReferenceEntry
from .common import StrictFrozenModel
from .common import frozen_mapping
type ToolSelector = str | tuple[str, ...]
class SkillMetadata(StrictFrozenModel):
"""Canonical metadata describing a skill and its dependencies."""
"""Canonical metadata describing a skill."""
id: str
version: str
tags: tuple[str, ...] = ()
capabilities: tuple[str, ...] = Field(min_length=1)
depends_on: tuple[str, ...] = ()
references: Mapping[str, ReferenceEntry] = Field(default_factory=frozen_mapping)
@field_validator("id")
@@ -47,14 +44,6 @@ class SkillMetadata(StrictFrozenModel):
raise ValueError(f"invalid tag: {tag}")
return value
@field_validator("depends_on")
@classmethod
def validate_depends_on(cls, value: tuple[str, ...]) -> tuple[str, ...]:
for dep in value:
if not SKILL_ID_RE.fullmatch(dep):
raise ValueError(f"invalid depends_on skill id: {dep}")
return value
@field_validator("references", mode="before")
@classmethod
def freeze_references(cls, value: Mapping[str, ReferenceEntry] | None) -> Mapping[str, ReferenceEntry]:
@@ -74,31 +63,8 @@ class SkillFrontmatter(StrictFrozenModel):
name: str = Field(min_length=1, max_length=64)
description: str = Field(min_length=1, max_length=1024)
when_to_use: str | None = None
allowed_tools: ToolSelector | None = Field(default=None, alias="allowed-tools")
disallowed_tools: ToolSelector | None = Field(
default=None,
alias="disallowed-tools",
)
disable_model_invocation: bool | None = Field(
default=None,
alias="disable-model-invocation",
)
user_invocable: bool | None = Field(default=None, alias="user-invocable")
argument_hint: str | None = Field(default=None, alias="argument-hint")
arguments: ToolSelector | None = None
license: str | None = None
compatibility: str | None = None
metadata: Mapping[str, str] | None = None
x_personal_mcp: SkillMetadata = Field(alias="x-personal-mcp")
@field_validator("metadata", mode="before")
@classmethod
def freeze_metadata(cls, value: Mapping[str, str] | None) -> Mapping[str, str] | None:
if value is None:
return None
return frozen_mapping(value)
@field_validator("name")
@classmethod
def validate_name(cls, value: str) -> str: