feat: 统一 Admin 用户中心 + 修复默认对话记忆存储路径

## 前端
- 新增 AdminUserHub 页面,合并用户管理/审计/记忆三个页面为统一中心(左侧用户列表 + 右侧 Tab)
- 旧三条 admin 路由重定向到新 /admin 路由
- 侧边栏导航菜单合并为单一入口"用户中心"
- memory-settings-page: 默认助手下拉选项传 agent=default(后端识别为全局哨兵)

## 后端
- memory.py: 将 "default" 加入全局哨兵 _GLOBAL_AGENT_VALUES,?agent=default 读全局记忆文件
- memory_middleware.py: _resolve_agent_id() 无 agent 上下文时返回 None,默认对话写入 users/{id}/memory.json
- manager.py: 移除 agent_id or "default" 回退,让 None 透传给 V1 provider
- admin_users.py: Admin 记忆 API 将"默认助手"桶改为读全局文件(agent_id=None)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
xuhdandClaude Sonnet 4.6 committed 2026-05-22 16:04:49 +08:00
1 parent ad8f74c964
commit 2c0bb2041b
10 files changed
+558 -137

No files matched your search

@@ -181,9 +181,10 @@ async def get_user_memory(user_id: str, request: Request) -> AdminMemoryResponse
# V1 模式:每个桶读 memory.json,内容为 {facts, user, history}
buckets: list[AdminMemoryBucket] = []
try:
buckets.append(AdminMemoryBucket(name="global", display_name="用户记忆", data=_read_v1_memory_bucket(user_id, None)))
buckets.append(AdminMemoryBucket(name="default", display_name="默认助手", data=_read_v1_memory_bucket(user_id, None)))
except Exception:
buckets.append(AdminMemoryBucket(name="global", display_name="用户记忆", data={}))
logger.exception("Failed to read V1 global memory for user %s", user_id)
buckets.append(AdminMemoryBucket(name="default", display_name="默认助手", data={}))
for agent in owned_agents:
agent_id: str = agent["id"]
@@ -198,7 +199,7 @@ async def get_user_memory(user_id: str, request: Request) -> AdminMemoryResponse
# V2 模式:读 USER.md / MEMORY.md,内容为 {entries: [...]}
buckets = [
AdminMemoryBucket(name="global", display_name="用户画像", data=_read_memory_bucket(user_id, None))
AdminMemoryBucket(name="default", display_name="默认助手", data=_read_memory_bucket(user_id, None))
]
for agent in owned_agents:
agent_id = agent["id"]
@@ -39,7 +39,7 @@ router = APIRouter(prefix="/api", tags=["memory"])
# 表示"全局桶 (无 agent)"的 agent 取值。
_GLOBAL_AGENT_VALUES: frozenset[str] = frozenset({"", "global", "__global__"})
_GLOBAL_AGENT_VALUES: frozenset[str] = frozenset({"", "global", "__global__", "default"})
def _resolve_agent_name(agent: str | None) -> str | None:
@@ -288,7 +288,7 @@ def build_memory_manager(
manager.initialize_all(
user_id=user_id,
agent_id=agent_id or "default",
agent_id=agent_id,
thread_id=thread_id,
base_dir=base_dir,
)
@@ -117,15 +117,18 @@ class MemoryMiddleware(AgentMiddleware[MemoryMiddlewareState]):
except RuntimeError:
return None
def _resolve_agent_id(self, runtime: Runtime | None) -> str:
"""解析 agent_id;优先 middleware 构造时的 agent_name,再 runtime context。"""
def _resolve_agent_id(self, runtime: Runtime | None) -> str | None:
"""解析 agent_id;优先 middleware 构造时的 agent_name,再 runtime context。
无 agent 上下文时返回 None,使 V1 记忆存入全局文件(users/{id}/memory.json)。
"""
if self._agent_name:
return self._agent_name
if runtime is not None and getattr(runtime, "context", None):
agent_id = runtime.context.get("agent_id")
if agent_id:
return str(agent_id)
return "default"
return None
# ---- wrap_model_call:Hindsight 动态召回注入 -------------------------