"""Installation binding for Memory; vector dependencies are opened only when needed.""" import os from tht.session.models import PrincipalContext from .migrate import installation_url from .models import MemoryForbidden, MemoryUnavailable from .repository import MemoryRepository from .service import MemoryService def _principal(): issuer = os.environ.get("THT_PRINCIPAL_ISSUER", "").strip() subject = os.environ.get("THT_PRINCIPAL_SUBJECT", "").strip() if not issuer or not subject: raise MemoryForbidden("A trusted runtime principal is required for Memory") return PrincipalContext( issuer=issuer, subject=subject, is_admin=os.environ.get("THT_PRINCIPAL_IS_ADMIN", "").lower() in {"1", "true"}, ) def _repository(workspace_id): try: url = installation_url() except ValueError: raise MemoryUnavailable("Memory PostgreSQL installation configuration is unavailable") \ from None return MemoryRepository(url, workspace_id) def memory_service(cfg): from tht.adapters.factory import build_vector_store from tht.cli.vector_cmd import make_embedder principal = _principal() return MemoryService(_repository(cfg._workspace_id), principal, language=cfg.language, store_factory=lambda: build_vector_store(cfg, require_write=True), embedder_factory=lambda: make_embedder(cfg.embeddings)) def admin_service(workspace_id, runtime): """Admin access needs no DWH binding, active session or Evidence materialization.""" from tht.adapters.vector.qdrant import QdrantVectorStore from tht.config import EmbeddingsConfig from tht.vectorstore.embeddings import OllamaEmbeddings principal = _principal() if not principal.is_admin: raise MemoryForbidden("Memory administration requires an administrator") return MemoryService(_repository(workspace_id), principal, language=runtime.get("memoryLanguage", "en"), store_factory=lambda: QdrantVectorStore( base_url=runtime["internalQdrantUrl"], workspace_id=workspace_id, collections={"reference": workspace_id+"-reference", "memory": workspace_id+"-memory"}, expected_dimension=runtime["internalEmbeddingDimensions"], ), embedder_factory=lambda: OllamaEmbeddings(EmbeddingsConfig( base_url=runtime["internalEmbeddingUrl"], model=runtime["internalEmbeddingModel"], dimensions=runtime["internalEmbeddingDimensions"], timeout=30, )))