"""Compatibility adapter for the existing direct PostgreSQL vector reader.""" from sqlalchemy import Engine from tht.ports.vector import ( VectorCapabilities, VectorHealth, VectorStoreError, VectorWriteRecord, VectorWriteUnavailable, require_positive_limit, ) from tht.vectorstore.store import VectorHit, VectorStore as TableVectorStore class LegacyDirectVectorStore: """Read-only port wrapper around the legacy table-scoped pgvector store.""" capabilities = VectorCapabilities(search=True, existing_hashes=False, upsert=False) def __init__(self, engine: Engine, schema: str = "vectors", dim: int = 768): self._engine = engine self._schema = schema self._dim = dim def health(self) -> VectorHealth: try: with self._engine.connect() as connection: connection.exec_driver_sql("SELECT 1") except Exception as exc: return VectorHealth( ok=False, detail=str(exc), read_configured=True, read_reachable=False, read_detail=str(exc), expected_dimension=self._dim, ) return VectorHealth( ok=True, read_configured=True, read_reachable=True, expected_dimension=self._dim, ) 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]: require_positive_limit(limit) if metadata_filter is not None: raise VectorStoreError("Legacy vector store cannot enforce metadata filtering") hits: list[VectorHit] = [] for collection in collections: table = TableVectorStore( self._engine, schema=self._schema, table=collection, dim=self._dim ) hits.extend(table.search(embedding, top_n=limit, kinds=kinds)) return sorted(hits, key=lambda hit: hit.similarity, reverse=True)[:limit] def existing_hashes(self, collection: str, kinds: list[str]) -> dict[str, str]: raise VectorWriteUnavailable("Legacy direct reader has no writer interface") def upsert(self, collection: str, records: list[VectorWriteRecord]) -> int: raise VectorWriteUnavailable("Legacy direct reader has no writer interface")