"""Transport-neutral vector-store contract and canonical vector models.""" from dataclasses import dataclass from typing import Protocol, runtime_checkable from tht.vectorstore.records import VectorRecord from tht.vectorstore.store import VectorHit @dataclass(frozen=True) class VectorCapabilities: search: bool = True existing_hashes: bool = False upsert: bool = False metadata_filter: bool = False delete_generation: bool = False list_evidence_generations: bool = False @dataclass(frozen=True) class VectorHealth: ok: bool detail: str | None = None read_configured: bool = False read_reachable: bool | None = None read_detail: str | None = None write_configured: bool = False write_reachable: bool | None = None write_detail: str | None = None expected_dimension: int | None = None observed_dimensions: tuple[int, ...] = () dimension_compatible: bool | None = None @dataclass(frozen=True) class VectorWriteRecord: """A canonical record plus transport-neutral, precomputed vector data.""" record: VectorRecord embedding: list[float] content_hash: str class VectorStoreError(Exception): """Base error exposed by vector adapters.""" class VectorWriteUnavailable(VectorStoreError): """Raised when a deployment has no vector writer credential.""" class VectorReadUnavailable(VectorStoreError): """Raised when a deployment has no vector reader credential.""" def require_positive_limit(limit: int) -> None: """Reject coercible values: vector limits are exact positive integers.""" if type(limit) is not int or limit <= 0: raise ValueError("Vector search limit must be a positive integer") @runtime_checkable class VectorStore(Protocol): @property def capabilities(self) -> VectorCapabilities: ... def health(self) -> VectorHealth: ... def search( self, collections: list[str], embedding: list[float], *, limit: int, kinds: list[str] | None = None, metadata_filter: dict[str, object] | None = None, ) -> list[VectorHit]: ... def existing_hashes(self, collection: str, kinds: list[str]) -> dict[str, str]: ... def upsert(self, collection: str, records: list[VectorWriteRecord]) -> int: ... def delete_generation(self, collection: str, generation: str, workspace_id: str) -> int: ... def list_evidence_generations(self, collection: str, workspace_id: str) -> list[str]: ... __all__ = [ "VectorCapabilities", "VectorHealth", "VectorHit", "VectorRecord", "VectorReadUnavailable", "VectorStore", "VectorStoreError", "VectorWriteRecord", "VectorWriteUnavailable", ]