* fix: entities list only show 100 entities * fix: update Rust CLI for entities pagination API changes
600 lines
16 KiB
Python
600 lines
16 KiB
Python
"""Abstract interface for MemoryEngine public methods.
|
|
|
|
This module defines the public API that HTTP endpoints and extensions should use
|
|
to interact with the memory system. All methods require a RequestContext for
|
|
authentication when a TenantExtension is configured.
|
|
"""
|
|
|
|
from abc import ABC, abstractmethod
|
|
from datetime import datetime
|
|
from typing import TYPE_CHECKING, Any
|
|
|
|
if TYPE_CHECKING:
|
|
from hindsight_api.engine.memory_engine import Budget
|
|
from hindsight_api.engine.response_models import RecallResult, ReflectResult
|
|
from hindsight_api.models import RequestContext
|
|
|
|
|
|
class MemoryEngineInterface(ABC):
|
|
"""
|
|
Abstract interface for the Memory Engine.
|
|
|
|
This defines the public API that should be used by HTTP endpoints and extensions.
|
|
All methods require a RequestContext for authentication.
|
|
"""
|
|
|
|
# =========================================================================
|
|
# Health & Status
|
|
# =========================================================================
|
|
|
|
@abstractmethod
|
|
async def health_check(self) -> dict:
|
|
"""
|
|
Check the health of the memory system.
|
|
|
|
Returns:
|
|
Dict with 'status' key ('healthy' or 'unhealthy') and additional info.
|
|
"""
|
|
...
|
|
|
|
# =========================================================================
|
|
# Core Memory Operations
|
|
# =========================================================================
|
|
|
|
@abstractmethod
|
|
async def retain_batch_async(
|
|
self,
|
|
bank_id: str,
|
|
contents: list[dict[str, Any]],
|
|
*,
|
|
request_context: "RequestContext",
|
|
) -> dict[str, Any]:
|
|
"""
|
|
Retain a batch of memory items.
|
|
|
|
Args:
|
|
bank_id: The memory bank ID.
|
|
contents: List of content dicts with 'content', optional 'event_date',
|
|
'context', 'metadata', 'document_id'.
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
Dict with processing results.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def recall_async(
|
|
self,
|
|
bank_id: str,
|
|
query: str,
|
|
*,
|
|
budget: "Budget | None" = None,
|
|
max_tokens: int = 4096,
|
|
enable_trace: bool = False,
|
|
fact_type: list[str] | None = None,
|
|
question_date: datetime | None = None,
|
|
include_entities: bool = False,
|
|
max_entity_tokens: int = 500,
|
|
include_chunks: bool = False,
|
|
max_chunk_tokens: int = 8192,
|
|
request_context: "RequestContext",
|
|
) -> "RecallResult":
|
|
"""
|
|
Recall memories relevant to a query.
|
|
|
|
Args:
|
|
bank_id: The memory bank ID.
|
|
query: The search query.
|
|
budget: Search budget (LOW, MID, HIGH).
|
|
max_tokens: Maximum tokens in response.
|
|
enable_trace: Include trace information.
|
|
fact_type: Filter by fact types.
|
|
question_date: Context date for temporal relevance.
|
|
include_entities: Include entity observations.
|
|
max_entity_tokens: Max tokens for entity observations.
|
|
include_chunks: Include raw chunks.
|
|
max_chunk_tokens: Max tokens for chunks.
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
RecallResult with matching memories.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def reflect_async(
|
|
self,
|
|
bank_id: str,
|
|
query: str,
|
|
*,
|
|
budget: "Budget | None" = None,
|
|
context: str | None = None,
|
|
max_tokens: int = 4096,
|
|
response_schema: dict | None = None,
|
|
request_context: "RequestContext",
|
|
) -> "ReflectResult":
|
|
"""
|
|
Reflect on a query and generate a thoughtful response.
|
|
|
|
Args:
|
|
bank_id: The memory bank ID.
|
|
query: The question to reflect on.
|
|
budget: Search budget for retrieving context.
|
|
context: Additional context for the reflection.
|
|
max_tokens: Maximum tokens for the response.
|
|
response_schema: Optional JSON Schema for structured output.
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
ReflectResult with generated response and supporting facts.
|
|
"""
|
|
...
|
|
|
|
# =========================================================================
|
|
# Bank Management
|
|
# =========================================================================
|
|
|
|
@abstractmethod
|
|
async def list_banks(
|
|
self,
|
|
*,
|
|
request_context: "RequestContext",
|
|
) -> list[dict[str, Any]]:
|
|
"""
|
|
List all memory banks.
|
|
|
|
Args:
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
List of bank info dicts.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def get_bank_profile(
|
|
self,
|
|
bank_id: str,
|
|
*,
|
|
request_context: "RequestContext",
|
|
) -> dict[str, Any]:
|
|
"""
|
|
Get bank profile including disposition and background.
|
|
|
|
Args:
|
|
bank_id: The memory bank ID.
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
Bank profile dict.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def update_bank_disposition(
|
|
self,
|
|
bank_id: str,
|
|
disposition: dict[str, int],
|
|
*,
|
|
request_context: "RequestContext",
|
|
) -> None:
|
|
"""
|
|
Update bank disposition traits.
|
|
|
|
Args:
|
|
bank_id: The memory bank ID.
|
|
disposition: Dict with trait values.
|
|
request_context: Request context for authentication.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def merge_bank_background(
|
|
self,
|
|
bank_id: str,
|
|
new_info: str,
|
|
*,
|
|
update_disposition: bool = True,
|
|
request_context: "RequestContext",
|
|
) -> dict[str, Any]:
|
|
"""
|
|
Merge new background information into bank profile.
|
|
|
|
Args:
|
|
bank_id: The memory bank ID.
|
|
new_info: New background information to merge.
|
|
update_disposition: Whether to infer disposition from background.
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
Updated background info.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def delete_bank(
|
|
self,
|
|
bank_id: str,
|
|
*,
|
|
fact_type: str | None = None,
|
|
request_context: "RequestContext",
|
|
) -> dict[str, int]:
|
|
"""
|
|
Delete a bank or its memories.
|
|
|
|
Args:
|
|
bank_id: The memory bank ID.
|
|
fact_type: If specified, only delete memories of this type.
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
Dict with deletion counts.
|
|
"""
|
|
...
|
|
|
|
# =========================================================================
|
|
# Memory Units
|
|
# =========================================================================
|
|
|
|
@abstractmethod
|
|
async def list_memory_units(
|
|
self,
|
|
bank_id: str,
|
|
*,
|
|
fact_type: str | None = None,
|
|
search_query: str | None = None,
|
|
limit: int = 100,
|
|
offset: int = 0,
|
|
request_context: "RequestContext",
|
|
) -> dict[str, Any]:
|
|
"""
|
|
List memory units with pagination.
|
|
|
|
Args:
|
|
bank_id: The memory bank ID.
|
|
fact_type: Filter by fact type.
|
|
search_query: Full-text search query.
|
|
limit: Maximum results.
|
|
offset: Pagination offset.
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
Dict with 'items', 'total', 'limit', 'offset'.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def delete_memory_unit(
|
|
self,
|
|
unit_id: str,
|
|
*,
|
|
request_context: "RequestContext",
|
|
) -> dict[str, Any]:
|
|
"""
|
|
Delete a specific memory unit.
|
|
|
|
Args:
|
|
unit_id: The memory unit ID.
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
Deletion result.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def get_graph_data(
|
|
self,
|
|
bank_id: str,
|
|
*,
|
|
fact_type: str | None = None,
|
|
limit: int = 1000,
|
|
request_context: "RequestContext",
|
|
) -> dict[str, Any]:
|
|
"""
|
|
Get graph data for visualization.
|
|
|
|
Args:
|
|
bank_id: The memory bank ID.
|
|
fact_type: Filter by fact type.
|
|
limit: Maximum number of items to return (default: 1000).
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
Dict with nodes, edges, table_rows, total_units, limit.
|
|
"""
|
|
...
|
|
|
|
# =========================================================================
|
|
# Documents
|
|
# =========================================================================
|
|
|
|
@abstractmethod
|
|
async def list_documents(
|
|
self,
|
|
bank_id: str,
|
|
*,
|
|
search_query: str | None = None,
|
|
limit: int = 100,
|
|
offset: int = 0,
|
|
request_context: "RequestContext",
|
|
) -> dict[str, Any]:
|
|
"""
|
|
List documents with pagination.
|
|
|
|
Args:
|
|
bank_id: The memory bank ID.
|
|
search_query: Search query.
|
|
limit: Maximum results.
|
|
offset: Pagination offset.
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
Dict with 'items', 'total', 'limit', 'offset'.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def get_document(
|
|
self,
|
|
document_id: str,
|
|
bank_id: str,
|
|
*,
|
|
request_context: "RequestContext",
|
|
) -> dict[str, Any] | None:
|
|
"""
|
|
Get a specific document.
|
|
|
|
Args:
|
|
document_id: The document ID.
|
|
bank_id: The memory bank ID.
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
Document dict or None if not found.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def delete_document(
|
|
self,
|
|
document_id: str,
|
|
bank_id: str,
|
|
*,
|
|
request_context: "RequestContext",
|
|
) -> dict[str, int]:
|
|
"""
|
|
Delete a document and its memory units.
|
|
|
|
Args:
|
|
document_id: The document ID.
|
|
bank_id: The memory bank ID.
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
Dict with deletion counts.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def get_chunk(
|
|
self,
|
|
chunk_id: str,
|
|
*,
|
|
request_context: "RequestContext",
|
|
) -> dict[str, Any] | None:
|
|
"""
|
|
Get a specific chunk.
|
|
|
|
Args:
|
|
chunk_id: The chunk ID.
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
Chunk dict or None if not found.
|
|
"""
|
|
...
|
|
|
|
# =========================================================================
|
|
# Entities
|
|
# =========================================================================
|
|
|
|
@abstractmethod
|
|
async def list_entities(
|
|
self,
|
|
bank_id: str,
|
|
*,
|
|
limit: int = 100,
|
|
offset: int = 0,
|
|
request_context: "RequestContext",
|
|
) -> dict[str, Any]:
|
|
"""
|
|
List entities for a bank with pagination.
|
|
|
|
Args:
|
|
bank_id: The memory bank ID.
|
|
limit: Maximum results.
|
|
offset: Offset for pagination.
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
Dict with items, total, limit, offset.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def get_entity_observations(
|
|
self,
|
|
bank_id: str,
|
|
entity_id: str,
|
|
*,
|
|
limit: int = 10,
|
|
request_context: "RequestContext",
|
|
) -> list[Any]:
|
|
"""
|
|
Get observations for an entity.
|
|
|
|
Args:
|
|
bank_id: The memory bank ID.
|
|
entity_id: The entity ID.
|
|
limit: Maximum observations.
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
List of EntityObservation objects.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def regenerate_entity_observations(
|
|
self,
|
|
bank_id: str,
|
|
entity_id: str,
|
|
entity_name: str,
|
|
*,
|
|
request_context: "RequestContext",
|
|
) -> None:
|
|
"""
|
|
Regenerate observations for an entity.
|
|
|
|
Args:
|
|
bank_id: The memory bank ID.
|
|
entity_id: The entity ID.
|
|
entity_name: The entity's canonical name.
|
|
request_context: Request context for authentication.
|
|
"""
|
|
...
|
|
|
|
# =========================================================================
|
|
# Statistics & Operations
|
|
# =========================================================================
|
|
|
|
@abstractmethod
|
|
async def get_bank_stats(
|
|
self,
|
|
bank_id: str,
|
|
*,
|
|
request_context: "RequestContext",
|
|
) -> dict[str, Any]:
|
|
"""
|
|
Get statistics about memory nodes and links for a bank.
|
|
|
|
Args:
|
|
bank_id: The memory bank ID.
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
Dict with node_counts, link_counts, link_counts_by_fact_type,
|
|
link_breakdown, and operations stats.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def get_entity(
|
|
self,
|
|
bank_id: str,
|
|
entity_id: str,
|
|
*,
|
|
request_context: "RequestContext",
|
|
) -> dict[str, Any] | None:
|
|
"""
|
|
Get entity details including metadata and observations.
|
|
|
|
Args:
|
|
bank_id: The memory bank ID.
|
|
entity_id: The entity ID.
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
Entity dict with id, canonical_name, mention_count, first_seen,
|
|
last_seen, metadata, and observations. None if not found.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def list_operations(
|
|
self,
|
|
bank_id: str,
|
|
*,
|
|
request_context: "RequestContext",
|
|
) -> list[dict[str, Any]]:
|
|
"""
|
|
List async operations for a bank.
|
|
|
|
Args:
|
|
bank_id: The memory bank ID.
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
List of operation dicts with id, task_type, status, etc.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def cancel_operation(
|
|
self,
|
|
bank_id: str,
|
|
operation_id: str,
|
|
*,
|
|
request_context: "RequestContext",
|
|
) -> dict[str, Any]:
|
|
"""
|
|
Cancel a pending async operation.
|
|
|
|
Args:
|
|
bank_id: The memory bank ID.
|
|
operation_id: The operation ID to cancel.
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
Dict with success status and message.
|
|
|
|
Raises:
|
|
ValueError: If operation not found.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def update_bank(
|
|
self,
|
|
bank_id: str,
|
|
*,
|
|
name: str | None = None,
|
|
background: str | None = None,
|
|
request_context: "RequestContext",
|
|
) -> dict[str, Any]:
|
|
"""
|
|
Update bank name and/or background.
|
|
|
|
Args:
|
|
bank_id: The memory bank ID.
|
|
name: New bank name (optional).
|
|
background: New background text (optional, replaces existing).
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
Updated bank profile dict.
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def submit_async_retain(
|
|
self,
|
|
bank_id: str,
|
|
contents: list[dict[str, Any]],
|
|
*,
|
|
request_context: "RequestContext",
|
|
) -> dict[str, Any]:
|
|
"""
|
|
Submit a batch retain operation to run asynchronously.
|
|
|
|
Args:
|
|
bank_id: The memory bank ID.
|
|
contents: List of content dicts to retain.
|
|
request_context: Request context for authentication.
|
|
|
|
Returns:
|
|
Dict with operation_id and items_count.
|
|
"""
|
|
...
|