Optional JSONPath query/extract support, FTS5 section/block search, mkt cache query and search. Local SQLite backend now supports parsed snapshot persistence, incremental refresh, cached querying, and ranked full-text search

This commit is contained in:
2026-05-04 10:32:06 +02:00
parent 36ff4cedab
commit 0015c8a385
11 changed files with 540 additions and 22 deletions

View File

@@ -17,6 +17,10 @@ class Heading:
def to_dict(self) -> dict[str, Any]:
return asdict(self)
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "Heading":
return cls(level=int(data["level"]), text=str(data["text"]), line=int(data["line"]))
@dataclass(frozen=True)
class ContentBlock:
@@ -32,6 +36,16 @@ class ContentBlock:
data = asdict(self)
return {key: value for key, value in data.items() if value is not None}
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "ContentBlock":
return cls(
type=str(data["type"]),
text=str(data.get("text", "")),
line_start=int(data["line_start"]) if data.get("line_start") is not None else None,
line_end=int(data["line_end"]) if data.get("line_end") is not None else None,
heading_level=int(data["heading_level"]) if data.get("heading_level") is not None else None,
)
@dataclass(frozen=True)
class Section:
@@ -46,6 +60,13 @@ class Section:
"blocks": [block.to_dict() for block in self.blocks],
}
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "Section":
return cls(
heading=Heading.from_dict(data["heading"]),
blocks=[ContentBlock.from_dict(block) for block in data.get("blocks", [])],
)
@dataclass(frozen=True)
class Document:
@@ -70,3 +91,15 @@ class Document:
"tokens": self.tokens,
}
return {key: value for key, value in data.items() if value is not None}
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "Document":
return cls(
source_path=str(data["source_path"]) if data.get("source_path") is not None else None,
frontmatter=dict(data.get("frontmatter", {})),
body=str(data.get("body", "")),
blocks=[ContentBlock.from_dict(block) for block in data.get("blocks", [])],
headings=[Heading.from_dict(heading) for heading in data.get("headings", [])],
sections=[Section.from_dict(section) for section in data.get("sections", [])],
tokens=list(data.get("tokens", [])),
)