changed to skill provider

This commit is contained in:
John Lancaster
2026-08-07 19:09:54 -05:00
parent c6817a074e
commit 44edffb8b7
48 changed files with 552 additions and 2946 deletions
-125
View File
@@ -5,42 +5,11 @@ from typing import Any
from personal_mcp.registry.models.registry import DocsRegistry
from personal_mcp.registry.models.registry import PromptRecord
from personal_mcp.registry.models.registry import PromptSummaryPayload
from personal_mcp.registry.models.registry import SkillPatternPayload
from personal_mcp.registry.models.registry import SkillRecord
from personal_mcp.registry.models.registry import SkillSummaryPayload
DEFAULT_LIMIT = 20
MAX_LIMIT = 100
def _skill_matches(
skill: SkillRecord,
*,
query: str | None,
tag: str | None,
capability: str | None,
) -> bool:
if query:
lowered = query.strip().lower()
if lowered:
haystack = " ".join(
[
skill.skill_id,
skill.name,
skill.description,
" ".join(skill.tags),
]
).lower()
terms = [term for term in lowered.replace("-", " ").split() if term]
if any(term not in haystack for term in terms):
return False
if tag and tag not in skill.tags:
return False
return not (capability and capability not in skill.capabilities)
def _prompt_matches(
prompt: PromptRecord,
*,
@@ -66,63 +35,6 @@ def _prompt_matches(
return not (tag and tag not in prompt.tags)
def build_skills_index_payload(
registry: DocsRegistry,
*,
query: str | None = None,
tag: str | None = None,
capability: str | None = None,
cursor: str | None = None,
limit: int | None = None,
) -> dict[str, Any]:
normalized_limit = DEFAULT_LIMIT if limit is None else max(1, min(limit, MAX_LIMIT))
try:
start = 0 if cursor is None else max(0, int(cursor))
except ValueError as exc:
raise ValueError("cursor must be an integer string") from exc
ordered = [registry.skills_by_id[skill_id] for skill_id in registry.skills_in_load_order]
matches = [skill for skill in ordered if _skill_matches(skill, query=query, tag=tag, capability=capability)]
page = matches[start : start + normalized_limit]
next_cursor = start + normalized_limit
return {
"skills": [SkillSummaryPayload.from_record(skill).model_dump() for skill in page],
"total": len(matches),
"cursor": str(start),
"limit": normalized_limit,
"next_cursor": str(next_cursor) if next_cursor < len(matches) else None,
}
def build_skill_detail_payload(registry: DocsRegistry, skill_id: str) -> dict[str, Any]:
if skill_id not in registry.skills_by_id:
raise KeyError(skill_id)
skill = registry.skills_by_id[skill_id]
return {
"id": skill.skill_id,
"name": skill.name,
"description": skill.description,
"version": skill.version,
"tags": list(skill.tags),
"capabilities": list(skill.capabilities),
"resources": {
"document": skill.document_uri,
"references": {
ref_id: {
"uri": ref.uri,
"mime_type": ref.mime_type,
"title": ref.title,
"path": ref.relpath.as_posix(),
}
for ref_id, ref in sorted(skill.references.items())
},
},
}
def build_prompts_index_payload(
registry: DocsRegistry,
*,
@@ -173,43 +85,6 @@ def build_prompt_detail_payload(registry: DocsRegistry, prompt_id: str) -> dict[
}
def search_patterns_payload(
registry: DocsRegistry,
*,
query: str = "",
tags: list[str] | None = None,
skip: int = 0,
limit: int = DEFAULT_LIMIT,
) -> dict[str, Any]:
normalized_skip = max(skip, 0)
normalized_limit = max(1, min(limit, MAX_LIMIT))
requested_tags = [tag.strip() for tag in (tags or []) if tag and tag.strip()]
matches: list[SkillRecord] = []
for skill_id in registry.skills_in_load_order:
skill = registry.skills_by_id[skill_id]
if not _skill_matches(skill, query=query, tag=None, capability=None):
continue
if requested_tags and any(tag not in skill.tags for tag in requested_tags):
continue
matches.append(skill)
page = matches[normalized_skip : normalized_skip + normalized_limit]
return {
"patterns": [SkillPatternPayload.from_record(skill).model_dump() for skill in page],
"total": len(matches),
"skip": normalized_skip,
"limit": normalized_limit,
}
def get_pattern_by_id_payload(registry: DocsRegistry, skill_id: str) -> dict[str, Any]:
if skill_id not in registry.skills_by_id:
return {"found": False, "id": skill_id}
return {"found": True, "pattern": SkillPatternPayload.from_record(registry.skills_by_id[skill_id]).model_dump()}
def search_prompts_payload(
registry: DocsRegistry,
*,