228 lines
7.0 KiB
Python
228 lines
7.0 KiB
Python
"""Core schemas for the generic Memory Gateway v1 API."""
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime, timezone
|
|
from enum import Enum
|
|
from typing import Any, Literal, Optional
|
|
from uuid import uuid4
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
def utc_now() -> datetime:
|
|
return datetime.now(timezone.utc)
|
|
|
|
|
|
class Visibility(str, Enum):
|
|
PRIVATE = "private"
|
|
AGENT_ONLY = "agent-only"
|
|
WORKSPACE_SHARED = "workspace-shared"
|
|
GLOBAL = "global"
|
|
|
|
|
|
class MemoryType(str, Enum):
|
|
PROFILE = "profile"
|
|
PREFERENCE = "preference"
|
|
FACT = "fact"
|
|
DECISION = "decision"
|
|
SUMMARY = "summary"
|
|
EPISODIC = "episodic"
|
|
PROCEDURE = "procedure"
|
|
EXPERIENCE = "experience"
|
|
KNOWLEDGE = "knowledge"
|
|
|
|
|
|
class SourceType(str, Enum):
|
|
CONVERSATION = "conversation"
|
|
TASK = "task"
|
|
AGENT = "agent"
|
|
OBSIDIAN = "obsidian"
|
|
OPENVIKING = "openviking"
|
|
EVERMEMOS = "evermemos"
|
|
MANUAL = "manual"
|
|
|
|
|
|
class UserRecord(BaseModel):
|
|
id: str = Field(default_factory=lambda: f"user_{uuid4().hex[:12]}")
|
|
display_name: str
|
|
status: Literal["active", "disabled"] = "active"
|
|
profile_namespace: Optional[str] = None
|
|
preferences: dict[str, Any] = Field(default_factory=dict)
|
|
created_at: datetime = Field(default_factory=utc_now)
|
|
updated_at: datetime = Field(default_factory=utc_now)
|
|
|
|
|
|
class AgentRecord(BaseModel):
|
|
id: str
|
|
name: str
|
|
framework: str
|
|
owner_user_id: Optional[str] = None
|
|
created_at: datetime = Field(default_factory=utc_now)
|
|
|
|
|
|
class WorkspaceRecord(BaseModel):
|
|
id: str
|
|
name: str
|
|
owner_user_id: str
|
|
member_user_ids: list[str] = Field(default_factory=list)
|
|
allowed_agent_ids: list[str] = Field(default_factory=list)
|
|
created_at: datetime = Field(default_factory=utc_now)
|
|
|
|
|
|
class SessionRecord(BaseModel):
|
|
id: str = Field(default_factory=lambda: f"sess_{uuid4().hex[:12]}")
|
|
user_id: str
|
|
agent_id: Optional[str] = None
|
|
workspace_id: Optional[str] = None
|
|
status: Literal["open", "committed", "expired"] = "open"
|
|
expires_at: Optional[datetime] = None
|
|
created_at: datetime = Field(default_factory=utc_now)
|
|
updated_at: datetime = Field(default_factory=utc_now)
|
|
|
|
|
|
class ACLRule(BaseModel):
|
|
visibility: Visibility = Visibility.PRIVATE
|
|
allowed_user_ids: list[str] = Field(default_factory=list)
|
|
allowed_agent_ids: list[str] = Field(default_factory=list)
|
|
allowed_workspace_ids: list[str] = Field(default_factory=list)
|
|
|
|
|
|
class MemoryRecord(BaseModel):
|
|
id: str = Field(default_factory=lambda: f"mem_{uuid4().hex[:16]}")
|
|
user_id: str
|
|
agent_id: Optional[str] = None
|
|
workspace_id: Optional[str] = None
|
|
session_id: Optional[str] = None
|
|
namespace: str
|
|
memory_type: MemoryType = MemoryType.FACT
|
|
content: str
|
|
summary: Optional[str] = None
|
|
tags: list[str] = Field(default_factory=list)
|
|
importance: float = Field(default=0.5, ge=0, le=1)
|
|
confidence: float = Field(default=0.8, ge=0, le=1)
|
|
visibility: Visibility = Visibility.PRIVATE
|
|
acl: ACLRule = Field(default_factory=ACLRule)
|
|
source: SourceType = SourceType.MANUAL
|
|
source_ref: Optional[str] = None
|
|
embedding_ref: Optional[str] = None
|
|
created_at: datetime = Field(default_factory=utc_now)
|
|
updated_at: datetime = Field(default_factory=utc_now)
|
|
expires_at: Optional[datetime] = None
|
|
archived_at: Optional[datetime] = None
|
|
version: int = 1
|
|
|
|
|
|
class EpisodeRecord(BaseModel):
|
|
id: str = Field(default_factory=lambda: f"epi_{uuid4().hex[:16]}")
|
|
user_id: str
|
|
agent_id: Optional[str] = None
|
|
workspace_id: Optional[str] = None
|
|
session_id: str
|
|
namespace: str
|
|
content: str
|
|
summary: Optional[str] = None
|
|
events: list[dict[str, Any]] = Field(default_factory=list)
|
|
tags: list[str] = Field(default_factory=list)
|
|
source: SourceType = SourceType.CONVERSATION
|
|
created_at: datetime = Field(default_factory=utc_now)
|
|
expires_at: Optional[datetime] = None
|
|
|
|
|
|
class ProfileRecord(BaseModel):
|
|
id: str = Field(default_factory=lambda: f"profile_{uuid4().hex[:12]}")
|
|
user_id: str
|
|
namespace: str
|
|
display_name: Optional[str] = None
|
|
stable_facts: list[str] = Field(default_factory=list)
|
|
preferences: dict[str, Any] = Field(default_factory=dict)
|
|
working_style: list[str] = Field(default_factory=list)
|
|
updated_from_memory_ids: list[str] = Field(default_factory=list)
|
|
version: int = 1
|
|
updated_at: datetime = Field(default_factory=utc_now)
|
|
|
|
|
|
class AuditLog(BaseModel):
|
|
id: str = Field(default_factory=lambda: f"audit_{uuid4().hex[:16]}")
|
|
actor_user_id: Optional[str] = None
|
|
actor_agent_id: Optional[str] = None
|
|
action: str
|
|
target_type: str
|
|
target_id: Optional[str] = None
|
|
namespace: Optional[str] = None
|
|
decision: Literal["allow", "deny"] = "allow"
|
|
reason: Optional[str] = None
|
|
metadata: dict[str, Any] = Field(default_factory=dict)
|
|
created_at: datetime = Field(default_factory=utc_now)
|
|
|
|
|
|
class AccessContext(BaseModel):
|
|
user_id: str
|
|
agent_id: Optional[str] = None
|
|
workspace_id: Optional[str] = None
|
|
session_id: Optional[str] = None
|
|
|
|
|
|
class CreateUserRequest(BaseModel):
|
|
display_name: str
|
|
user_id: Optional[str] = None
|
|
preferences: dict[str, Any] = Field(default_factory=dict)
|
|
|
|
|
|
class MemorySearchRequest(AccessContext):
|
|
query: str
|
|
namespaces: list[str] = Field(default_factory=list)
|
|
memory_types: list[MemoryType] = Field(default_factory=list)
|
|
tags: list[str] = Field(default_factory=list)
|
|
limit: int = Field(default=10, ge=1, le=100)
|
|
|
|
|
|
class MemoryUpsertRequest(AccessContext):
|
|
namespace: Optional[str] = None
|
|
memory_type: MemoryType = MemoryType.FACT
|
|
content: str
|
|
summary: Optional[str] = None
|
|
tags: list[str] = Field(default_factory=list)
|
|
importance: float = Field(default=0.5, ge=0, le=1)
|
|
confidence: float = Field(default=0.8, ge=0, le=1)
|
|
visibility: Visibility = Visibility.PRIVATE
|
|
source: SourceType = SourceType.MANUAL
|
|
expires_at: Optional[datetime] = None
|
|
|
|
|
|
class MemoryPatchRequest(BaseModel):
|
|
content: Optional[str] = None
|
|
summary: Optional[str] = None
|
|
tags: Optional[list[str]] = None
|
|
importance: Optional[float] = Field(default=None, ge=0, le=1)
|
|
confidence: Optional[float] = Field(default=None, ge=0, le=1)
|
|
visibility: Optional[Visibility] = None
|
|
expires_at: Optional[datetime] = None
|
|
|
|
|
|
class EpisodeAppendRequest(AccessContext):
|
|
content: str
|
|
namespace: Optional[str] = None
|
|
events: list[dict[str, Any]] = Field(default_factory=list)
|
|
tags: list[str] = Field(default_factory=list)
|
|
source: SourceType = SourceType.CONVERSATION
|
|
expires_at: Optional[datetime] = None
|
|
|
|
|
|
class CommitSessionRequest(AccessContext):
|
|
promote: bool = True
|
|
min_importance: float = Field(default=0.6, ge=0, le=1)
|
|
target_namespace: Optional[str] = None
|
|
|
|
|
|
class MemoryFeedbackRequest(AccessContext):
|
|
feedback: Literal["useful", "not_useful", "incorrect", "duplicate", "outdated"]
|
|
comment: Optional[str] = None
|
|
|
|
|
|
class NamespaceInfo(BaseModel):
|
|
namespace: str
|
|
owner_user_id: Optional[str] = None
|
|
visibility: Visibility
|
|
description: str
|
|
|