116 lines
3.8 KiB
Python
116 lines
3.8 KiB
Python
"""Namespace construction and access checks for Memory Gateway."""
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime, timezone
|
|
|
|
from .schemas import AccessContext, MemoryRecord, NamespaceInfo, Visibility
|
|
|
|
|
|
def user_profile_namespace(user_id: str) -> str:
|
|
return f"user/{user_id}/profile"
|
|
|
|
|
|
def user_preferences_namespace(user_id: str) -> str:
|
|
return f"user/{user_id}/preferences"
|
|
|
|
|
|
def user_long_term_namespace(user_id: str) -> str:
|
|
return f"user/{user_id}/long_term"
|
|
|
|
|
|
def agent_memory_namespace(agent_id: str) -> str:
|
|
return f"agent/{agent_id}/memory"
|
|
|
|
|
|
def workspace_shared_namespace(workspace_id: str) -> str:
|
|
return f"workspace/{workspace_id}/shared"
|
|
|
|
|
|
def session_episodic_namespace(session_id: str) -> str:
|
|
return f"session/{session_id}/episodic"
|
|
|
|
|
|
def global_public_namespace() -> str:
|
|
return "global/public"
|
|
|
|
|
|
def default_namespace_for_context(ctx: AccessContext, visibility: Visibility) -> str:
|
|
if visibility == Visibility.AGENT_ONLY and ctx.agent_id:
|
|
return agent_memory_namespace(ctx.agent_id)
|
|
if visibility == Visibility.WORKSPACE_SHARED and ctx.workspace_id:
|
|
return workspace_shared_namespace(ctx.workspace_id)
|
|
if ctx.session_id:
|
|
return session_episodic_namespace(ctx.session_id)
|
|
return user_long_term_namespace(ctx.user_id)
|
|
|
|
|
|
def can_access_memory(ctx: AccessContext, memory: MemoryRecord) -> bool:
|
|
if memory.expires_at and memory.expires_at <= datetime.now(timezone.utc):
|
|
return False
|
|
if memory.visibility == Visibility.GLOBAL:
|
|
return True
|
|
if memory.visibility == Visibility.PRIVATE:
|
|
return memory.user_id == ctx.user_id
|
|
if memory.visibility == Visibility.AGENT_ONLY:
|
|
return memory.user_id == ctx.user_id and memory.agent_id == ctx.agent_id
|
|
if memory.visibility == Visibility.WORKSPACE_SHARED:
|
|
return memory.workspace_id is not None and memory.workspace_id == ctx.workspace_id
|
|
return False
|
|
|
|
|
|
def visible_namespaces(ctx: AccessContext) -> list[NamespaceInfo]:
|
|
namespaces = [
|
|
NamespaceInfo(
|
|
namespace=user_profile_namespace(ctx.user_id),
|
|
owner_user_id=ctx.user_id,
|
|
visibility=Visibility.PRIVATE,
|
|
description="用户 profile 与稳定偏好",
|
|
),
|
|
NamespaceInfo(
|
|
namespace=user_preferences_namespace(ctx.user_id),
|
|
owner_user_id=ctx.user_id,
|
|
visibility=Visibility.PRIVATE,
|
|
description="用户显式偏好",
|
|
),
|
|
NamespaceInfo(
|
|
namespace=user_long_term_namespace(ctx.user_id),
|
|
owner_user_id=ctx.user_id,
|
|
visibility=Visibility.PRIVATE,
|
|
description="用户长期记忆",
|
|
),
|
|
NamespaceInfo(
|
|
namespace=global_public_namespace(),
|
|
visibility=Visibility.GLOBAL,
|
|
description="全局公开知识",
|
|
),
|
|
]
|
|
if ctx.agent_id:
|
|
namespaces.append(
|
|
NamespaceInfo(
|
|
namespace=agent_memory_namespace(ctx.agent_id),
|
|
owner_user_id=ctx.user_id,
|
|
visibility=Visibility.AGENT_ONLY,
|
|
description="指定 agent 私有经验",
|
|
)
|
|
)
|
|
if ctx.workspace_id:
|
|
namespaces.append(
|
|
NamespaceInfo(
|
|
namespace=workspace_shared_namespace(ctx.workspace_id),
|
|
owner_user_id=ctx.user_id,
|
|
visibility=Visibility.WORKSPACE_SHARED,
|
|
description="workspace / project 共享记忆",
|
|
)
|
|
)
|
|
if ctx.session_id:
|
|
namespaces.append(
|
|
NamespaceInfo(
|
|
namespace=session_episodic_namespace(ctx.session_id),
|
|
owner_user_id=ctx.user_id,
|
|
visibility=Visibility.PRIVATE,
|
|
description="session 临时 episodic memory",
|
|
)
|
|
)
|
|
return namespaces
|
|
|