models
This commit is contained in:
@@ -4,129 +4,67 @@ import importlib
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
from pathlib import PurePosixPath
|
||||
from typing import Any
|
||||
|
||||
import yaml
|
||||
|
||||
from personal_mcp.registry.ingest.document import MarkdownDocument
|
||||
from personal_mcp.registry.ingest.prompt import PromptFilesBundle
|
||||
from personal_mcp.registry.ingest.skill import SkillFilesBundle
|
||||
from personal_mcp.registry.models.common import ReferenceEntry
|
||||
from personal_mcp.registry.ingest.skill import build_stored_skill
|
||||
from personal_mcp.registry.models.common import _normalize_docs_path
|
||||
from personal_mcp.registry.models.prompt import StoredPrompt
|
||||
from personal_mcp.registry.models.registry import DocsRegistry
|
||||
from personal_mcp.registry.models.registry import PromptRecord
|
||||
from personal_mcp.registry.models.registry import PromptSummaryRecord
|
||||
from personal_mcp.registry.models.registry import ReferenceRecord
|
||||
from personal_mcp.registry.models.registry import SkillRecord
|
||||
from personal_mcp.registry.models.registry import SkillSummaryRecord
|
||||
from personal_mcp.skills.document_loader import _reference_id_from_filename
|
||||
from personal_mcp.skills.document_loader import _title_from_reference_filename
|
||||
from personal_mcp.skills.document_loader import _validate_prompt_frontmatter
|
||||
from personal_mcp.skills.document_loader import _validate_skill_frontmatter
|
||||
|
||||
|
||||
def _parse_frontmatter(raw_frontmatter: str | None, *, path: PurePosixPath) -> dict[str, Any]:
|
||||
if raw_frontmatter is None:
|
||||
raise ValueError(f"missing YAML frontmatter: {path.as_posix()}")
|
||||
parsed = yaml.safe_load(raw_frontmatter)
|
||||
if not isinstance(parsed, dict):
|
||||
raise TypeError(f"frontmatter must parse to an object: {path.as_posix()}")
|
||||
return parsed
|
||||
|
||||
|
||||
def _discover_reference_entries(bundle: SkillFilesBundle) -> dict[str, ReferenceEntry]:
|
||||
discovered: dict[str, ReferenceEntry] = {}
|
||||
for reference_doc in bundle.references:
|
||||
ref_id = _reference_id_from_filename(reference_doc.relpath.name)
|
||||
if ref_id is None:
|
||||
continue
|
||||
discovered[ref_id] = ReferenceEntry(
|
||||
path=PurePosixPath("references").joinpath(reference_doc.relpath.name).as_posix(),
|
||||
title=_title_from_reference_filename(reference_doc.relpath.name),
|
||||
)
|
||||
return discovered
|
||||
|
||||
|
||||
def _build_skill_record(
|
||||
*, bundle: SkillFilesBundle, docs_by_relpath: dict[PurePosixPath, MarkdownDocument]
|
||||
) -> SkillRecord:
|
||||
frontmatter_raw = _parse_frontmatter(bundle.skill.frontmatter, path=bundle.skill.relpath)
|
||||
frontmatter = _validate_skill_frontmatter(frontmatter_raw, skill_dir_name=bundle.slug)
|
||||
metadata = frontmatter.x_personal_mcp
|
||||
|
||||
merged_entries = _discover_reference_entries(bundle)
|
||||
merged_entries.update(dict(metadata.references))
|
||||
|
||||
stored = build_stored_skill(bundle=bundle, docs_by_relpath=docs_by_relpath)
|
||||
metadata = stored.frontmatter.x_personal_mcp
|
||||
references: dict[str, ReferenceRecord] = {}
|
||||
for ref_id, entry in sorted(merged_entries.items()):
|
||||
ref_relpath = PurePosixPath("skills").joinpath(bundle.slug).joinpath(entry.path)
|
||||
if ref_relpath not in docs_by_relpath:
|
||||
raise KeyError(f"reference document not found for '{metadata.id}:{ref_id}' at {ref_relpath.as_posix()}")
|
||||
ref_doc = docs_by_relpath[ref_relpath]
|
||||
for ref_id, ref in sorted(stored.references.items()):
|
||||
references[ref_id] = ReferenceRecord(
|
||||
ref_id=ref_id,
|
||||
uri=f"resource://skills/{metadata.id}/references/{ref_id}",
|
||||
relpath=ref_relpath.as_posix(),
|
||||
mime_type=entry.mime_type,
|
||||
title=entry.title,
|
||||
content=ref_doc.content,
|
||||
relpath=ref.relpath.as_posix(),
|
||||
mime_type=ref.entry.mime_type,
|
||||
title=ref.entry.title,
|
||||
content=ref.content,
|
||||
)
|
||||
|
||||
return SkillRecord(
|
||||
skill_id=metadata.id,
|
||||
name=frontmatter.name,
|
||||
description=frontmatter.description,
|
||||
name=stored.frontmatter.name,
|
||||
description=stored.frontmatter.description,
|
||||
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=bundle.skill.relpath.as_posix(),
|
||||
document_content=bundle.skill.content,
|
||||
document_relpath=stored.relpath.as_posix(),
|
||||
document_content=stored.content,
|
||||
references=references,
|
||||
)
|
||||
|
||||
|
||||
def _build_prompt_record(*, bundle: PromptFilesBundle) -> PromptRecord:
|
||||
frontmatter_raw = _parse_frontmatter(bundle.prompt.frontmatter, path=bundle.prompt.relpath)
|
||||
frontmatter = _validate_prompt_frontmatter(frontmatter_raw, prompt_dir_name=bundle.slug)
|
||||
metadata = frontmatter.x_personal_mcp
|
||||
stored = StoredPrompt.from_bundle(bundle)
|
||||
metadata = stored.frontmatter.x_personal_mcp
|
||||
|
||||
return PromptRecord(
|
||||
prompt_id=metadata.id,
|
||||
name=frontmatter.name,
|
||||
description=frontmatter.description,
|
||||
name=stored.frontmatter.name,
|
||||
description=stored.frontmatter.description,
|
||||
version=metadata.version,
|
||||
tags=tuple(metadata.tags),
|
||||
capabilities=tuple(metadata.capabilities),
|
||||
arguments=dict(metadata.arguments),
|
||||
document_uri=f"resource://prompts/{metadata.id}/document",
|
||||
document_relpath=bundle.prompt.relpath.as_posix(),
|
||||
document_content=bundle.prompt.content,
|
||||
)
|
||||
|
||||
|
||||
def _to_summary(skill: SkillRecord) -> SkillSummaryRecord:
|
||||
return SkillSummaryRecord(
|
||||
skill_id=skill.skill_id,
|
||||
name=skill.name,
|
||||
description=skill.description,
|
||||
tags=skill.tags,
|
||||
capabilities=skill.capabilities,
|
||||
document_uri=skill.document_uri,
|
||||
version=skill.version,
|
||||
)
|
||||
|
||||
|
||||
def _to_prompt_summary(prompt: PromptRecord) -> PromptSummaryRecord:
|
||||
return PromptSummaryRecord(
|
||||
prompt_id=prompt.prompt_id,
|
||||
name=prompt.name,
|
||||
description=prompt.description,
|
||||
tags=prompt.tags,
|
||||
capabilities=prompt.capabilities,
|
||||
document_uri=prompt.document_uri,
|
||||
version=prompt.version,
|
||||
document_relpath=stored.relpath.as_posix(),
|
||||
document_content=stored.content,
|
||||
)
|
||||
|
||||
|
||||
@@ -215,7 +153,9 @@ def load_docs_registry(*, package_anchor: str, docs_root: str = "docs") -> DocsR
|
||||
return DocsRegistry(
|
||||
skills_by_id=skills_by_id,
|
||||
skills_in_load_order=skills_in_order_tuple,
|
||||
skills_summary_in_load_order=tuple(_to_summary(skills_by_id[skill_id]) for skill_id in skills_in_order_tuple),
|
||||
skills_summary_in_load_order=tuple(
|
||||
SkillSummaryRecord.from_record(skills_by_id[skill_id]) for skill_id in skills_in_order_tuple
|
||||
),
|
||||
docs_markdown_by_path=docs_markdown_by_path,
|
||||
docs_markdown_path_index=tuple(sorted(docs_markdown_by_path)),
|
||||
tag_to_skill_ids=_build_tag_index_skills(skills_in_order_tuple, skills_by_id),
|
||||
@@ -223,7 +163,7 @@ def load_docs_registry(*, package_anchor: str, docs_root: str = "docs") -> DocsR
|
||||
prompts_by_id=prompts_by_id,
|
||||
prompts_in_load_order=prompts_in_order_tuple,
|
||||
prompts_summary_in_load_order=tuple(
|
||||
_to_prompt_summary(prompts_by_id[prompt_id]) for prompt_id in prompts_in_order_tuple
|
||||
PromptSummaryRecord.from_record(prompts_by_id[prompt_id]) for prompt_id in prompts_in_order_tuple
|
||||
),
|
||||
tag_to_prompt_ids=_build_tag_index_prompts(prompts_in_order_tuple, prompts_by_id),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user