typing
This commit is contained in:
@@ -2,21 +2,19 @@ import re
|
||||
from collections.abc import Mapping
|
||||
from pathlib import PurePosixPath
|
||||
from types import MappingProxyType
|
||||
from typing import TypeVar
|
||||
from typing import ClassVar
|
||||
from typing import Final
|
||||
|
||||
from pydantic import BaseModel
|
||||
from pydantic import ConfigDict
|
||||
from pydantic import field_validator
|
||||
|
||||
SKILL_ID_RE = re.compile(r"^[a-z][a-z0-9-]*$")
|
||||
SEMVER_RE = re.compile(r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:[-+][0-9A-Za-z.-]+)?$")
|
||||
|
||||
K = TypeVar("K")
|
||||
V = TypeVar("V")
|
||||
SKILL_ID_RE: Final[re.Pattern[str]] = re.compile(r"^[a-z][a-z0-9-]*$")
|
||||
SEMVER_RE: Final[re.Pattern[str]] = re.compile(r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:[-+][0-9A-Za-z.-]+)?$")
|
||||
|
||||
|
||||
class StrictFrozenModel(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
model_config: ClassVar[ConfigDict] = ConfigDict(
|
||||
extra="forbid",
|
||||
frozen=True,
|
||||
validate_by_alias=True,
|
||||
@@ -25,8 +23,8 @@ class StrictFrozenModel(BaseModel):
|
||||
)
|
||||
|
||||
|
||||
def frozen_mapping(value: Mapping[K, V] | None = None) -> Mapping[K, V]:
|
||||
return MappingProxyType(dict(value or {}))
|
||||
def frozen_mapping[K, V](value: Mapping[K, V] | None = None) -> Mapping[K, V]:
|
||||
return MappingProxyType(dict(value) if value is not None else {})
|
||||
|
||||
|
||||
class ReferenceEntry(StrictFrozenModel):
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from pathlib import PurePosixPath
|
||||
from typing import Self
|
||||
|
||||
from .common import StrictFrozenModel
|
||||
|
||||
@@ -24,7 +25,7 @@ class SkillFilesBundleModel(StrictFrozenModel):
|
||||
skill: MarkdownDocumentModel,
|
||||
references: tuple[MarkdownDocumentModel, ...] = (),
|
||||
other: tuple[MarkdownDocumentModel, ...] = (),
|
||||
) -> "SkillFilesBundleModel":
|
||||
) -> Self:
|
||||
# Ensure deterministic ordering even when the source collection is unordered.
|
||||
references_sorted = tuple(sorted(references, key=lambda doc: doc.relpath))
|
||||
other_sorted = tuple(sorted(other, key=lambda doc: doc.relpath))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import re
|
||||
from collections.abc import Mapping
|
||||
from typing import Any
|
||||
from typing import Literal
|
||||
|
||||
from pydantic import Field
|
||||
from pydantic import field_validator
|
||||
@@ -10,28 +11,22 @@ from .common import SKILL_ID_RE
|
||||
from .common import StrictFrozenModel
|
||||
from .common import frozen_mapping
|
||||
|
||||
|
||||
class PromptArgumentEntry(StrictFrozenModel):
|
||||
type: str = Field(min_length=1)
|
||||
description: str | None = None
|
||||
required: bool = False
|
||||
default: Any | None = None
|
||||
enum: tuple[str, ...] | None = None
|
||||
|
||||
@field_validator("type")
|
||||
@classmethod
|
||||
def validate_type(cls, value: str) -> str:
|
||||
allowed_types = {
|
||||
type PromptArgumentType = Literal[
|
||||
"string",
|
||||
"number",
|
||||
"integer",
|
||||
"boolean",
|
||||
"array",
|
||||
"object",
|
||||
}
|
||||
if value not in allowed_types:
|
||||
raise ValueError(f"unsupported prompt argument type: {value}")
|
||||
return value
|
||||
]
|
||||
|
||||
|
||||
class PromptArgumentEntry(StrictFrozenModel):
|
||||
type: PromptArgumentType
|
||||
description: str | None = None
|
||||
required: bool = False
|
||||
default: Any | None = None
|
||||
enum: tuple[str, ...] | None = None
|
||||
|
||||
@field_validator("enum")
|
||||
@classmethod
|
||||
|
||||
@@ -9,6 +9,8 @@ from .common import ReferenceEntry
|
||||
from .common import StrictFrozenModel
|
||||
from .common import frozen_mapping
|
||||
|
||||
type ToolSelector = str | tuple[str, ...]
|
||||
|
||||
|
||||
class SkillMetadata(StrictFrozenModel):
|
||||
id: str
|
||||
@@ -66,8 +68,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: str | tuple[str, ...] | None = Field(default=None, alias="allowed-tools")
|
||||
disallowed_tools: str | tuple[str, ...] | None = Field(
|
||||
allowed_tools: ToolSelector | None = Field(default=None, alias="allowed-tools")
|
||||
disallowed_tools: ToolSelector | None = Field(
|
||||
default=None,
|
||||
alias="disallowed-tools",
|
||||
)
|
||||
@@ -77,7 +79,7 @@ class SkillFrontmatter(StrictFrozenModel):
|
||||
)
|
||||
user_invocable: bool | None = Field(default=None, alias="user-invocable")
|
||||
argument_hint: str | None = Field(default=None, alias="argument-hint")
|
||||
arguments: str | tuple[str, ...] | None = None
|
||||
arguments: ToolSelector | None = None
|
||||
license: str | None = None
|
||||
compatibility: str | None = None
|
||||
metadata: Mapping[str, str] | None = None
|
||||
|
||||
Reference in New Issue
Block a user