"""Backend adapter contracts for Memory Gateway v2.""" from __future__ import annotations from datetime import datetime from enum import Enum from typing import Any, Optional from uuid import uuid4 from pydantic import BaseModel, Field from .schemas import utc_now from .schemas_v2 import BackendType, MemoryRefType, OperationStatus class BackendOperation(str, Enum): INGEST_TURN = "ingest_turn" COMMIT_SESSION = "commit_session" RETRIEVE_CONTEXT = "retrieve_context" CREATE_REVIEW_DRAFT = "create_review_draft" class BackendResultStatus(str, Enum): SUCCESS = "success" FAILED = "failed" SKIPPED = "skipped" PENDING = "pending" class OutboxEventStatus(str, Enum): PENDING = "pending" PROCESSING = "processing" SUCCESS = "success" SKIPPED = "skipped" FAILED = "failed" DEAD_LETTER = "dead_letter" class BackendWriteResult(BaseModel): backend_type: BackendType operation: BackendOperation status: BackendResultStatus native_id: Optional[str] = None native_uri: Optional[str] = None retryable: bool = False error_code: Optional[str] = None error_message: Optional[str] = None latency_ms: Optional[float] = None metadata: dict[str, Any] = Field(default_factory=dict) class BackendProducedRef(BaseModel): ref_type: MemoryRefType native_id: Optional[str] = None native_uri: Optional[str] = None metadata: dict[str, Any] = Field(default_factory=dict) class BackendCommitResult(BaseModel): backend_type: BackendType operation: BackendOperation = BackendOperation.COMMIT_SESSION status: BackendResultStatus native_id: Optional[str] = None native_uri: Optional[str] = None retryable: bool = False error_code: Optional[str] = None error_message: Optional[str] = None latency_ms: Optional[float] = None created_refs: list[str] = Field(default_factory=list) refs: list[BackendProducedRef] = Field(default_factory=list) metadata: dict[str, Any] = Field(default_factory=dict) class BackendRetrieveItem(BaseModel): text: Optional[str] = None source_backend: BackendType ref_id: Optional[str] = None score: float = 0.0 memory_type: Optional[str] = None metadata: dict[str, Any] = Field(default_factory=dict) class BackendRetrieveResult(BaseModel): backend_type: BackendType operation: BackendOperation = BackendOperation.RETRIEVE_CONTEXT status: BackendResultStatus native_id: Optional[str] = None native_uri: Optional[str] = None retryable: bool = False error_code: Optional[str] = None error_message: Optional[str] = None latency_ms: Optional[float] = None items: list[BackendRetrieveItem] = Field(default_factory=list) metadata: dict[str, Any] = Field(default_factory=dict) class OutboxEvent(BaseModel): id: str = Field(default_factory=lambda: f"outbox_{uuid4().hex[:16]}") event_type: str gateway_id: str workspace_id: str user_id: str agent_id: Optional[str] = None session_id: Optional[str] = None backend_type: BackendType operation: BackendOperation payload_ref: Optional[str] = None status: OutboxEventStatus = OutboxEventStatus.PENDING attempt_count: int = 0 max_attempts: int = 3 next_retry_at: Optional[datetime] = None last_error: Optional[str] = None locked_by: Optional[str] = None locked_at: Optional[datetime] = None lease_expires_at: Optional[datetime] = None metadata: dict[str, Any] = Field(default_factory=dict) created_at: datetime = Field(default_factory=utc_now) updated_at: datetime = Field(default_factory=utc_now) class CommitJob(BaseModel): job_id: str = Field(default_factory=lambda: f"job_{uuid4().hex[:16]}") workspace_id: str user_id: str agent_id: Optional[str] = None session_id: str namespace: Optional[str] = None status: OperationStatus = OperationStatus.ACCEPTED requested_by: Optional[str] = None created_refs_count: int = 0 error_message: Optional[str] = None created_at: datetime = Field(default_factory=utc_now) updated_at: datetime = Field(default_factory=utc_now) started_at: Optional[datetime] = None finished_at: Optional[datetime] = None