用户系统

This commit is contained in:
2026-04-15 00:21:43 +08:00
parent 97bbb3f306
commit 47c0863bab
23 changed files with 1640 additions and 56 deletions

View File

@@ -4,6 +4,110 @@
## 记录
### [CL-20260414-2340] 2026-04-14 23:40 — 用 pwdlib (Argon2id) 替换 passlib (bcrypt),彻底解决兼容性问题
- **tags**: 重构, 安全, 密码哈希, Argon2, pwdlib, passlib, 依赖升级
- **affected_files**:
- art-agent/backend/app/auth.py
- art-agent/backend/requirements.txt
- docs/art-agent/USER-SYSTEM.md
- **what**: 将密码哈希从 passlib+bcrypt 替换为 pwdlib+Argon2id
- **why**: passlib 已停止维护Python 3.13+ 不可用,且与 bcrypt 5.x 有兼容性问题。pwdlib 是 passlib 的现代替代,原生支持 bcrypt 5.x
- **decisions**: 选择 pwdlib[argon2,bcrypt] 而非纯 argon2-cffipwdlib 提供与 passlib 类似的统一接口,同时内置 BcryptHasher 兼容已有旧哈希。新密码一律 Argon2id旧 bcrypt 哈希仍可验证(过渡期)
- **notes**: 已有 admin 用户的 bcrypt 哈希无需迁移,下次改密时自动升级为 Argon2id 格式。不再需要锁定 bcrypt 版本
- **source_chat**: [替换 passlib 为 pwdlib](a33b7af6-a8c0-4e88-8372-ec4b5b9dd703)
### [CL-20260414-2330] 2026-04-14 23:30 — 修复 passlib + bcrypt 5.x 兼容性问题,锁定 bcrypt<4.1
- **tags**: bug修复, 依赖, bcrypt, passlib, 用户系统
- **affected_files**:
- art-agent/backend/requirements.txt
- docs/art-agent/USER-SYSTEM.md
- **what**: 修复 passlib 1.7.4 与 bcrypt 5.0.0 不兼容导致后端启动失败
- **why**: passlib 已停止维护bcrypt 4.1+ 移除了 `__about__` 属性且改变了密码长度校验行为,导致 passlib 加载后端报 `AttributeError` + `ValueError`
- **decisions**: 降级 bcrypt 到 4.0.1 并锁定 `>=4.0.1,<4.1`,而非替换 passlib改动最小
- **notes**: 如果未来需要升级 bcrypt需替换 passlib 为 bcrypt 直接调用或改用 argon2-cffi 等不依赖 passlib 的方案
- **source_chat**: [修复 bcrypt 兼容性](a33b7af6-a8c0-4e88-8372-ec4b5b9dd703)
### [CL-20260414-2300] 2026-04-14 23:00 — 用户系统:管理员邀请制 + JWT 认证 + 数据按用户隔离
- **tags**: 用户系统, 认证, JWT, SQLite, 数据隔离, 多用户, 安全
- **affected_files**:
- art-agent/backend/requirements.txt
- art-agent/backend/app/db.py新建
- art-agent/backend/app/auth.py新建
- art-agent/backend/app/api/auth.py新建
- art-agent/backend/app/api/admin.py新建
- art-agent/backend/app/api/chat.py
- art-agent/backend/app/main.py
- art-agent/backend/app/agent/loop.py
- art-agent/backend/.env.example
- art-agent/frontend/src/lib/auth-context.tsx新建
- art-agent/frontend/src/lib/auth-guard.tsx新建
- art-agent/frontend/src/lib/api.ts
- art-agent/frontend/src/lib/store.ts
- art-agent/frontend/src/lib/app-context.tsx
- art-agent/frontend/src/app/layout.tsx
- art-agent/frontend/src/app/login/page.tsx新建
- art-agent/frontend/src/components/layout/top-nav.tsx
- art-agent/frontend/src/components/chat/model-selector.tsx
- **what**: 为 EPEEKit 添加完整用户系统管理员创建账号、JWT 登录、所有 API 鉴权、Mem0 记忆按用户隔离、前端 localStorage 按用户隔离
- **why**: 之前无认证,所有访问者共享 `default_user` 的记忆,多人通过穿透使用时数据互相混杂
- **decisions**:
- SQLitedata/epeekit.db存用户表零部署成本与 Qdrant 数据目录在同一 data/ 下
- JWT access token (30min) + refresh token (7d)passlib bcrypt 密码哈希
- 不开放注册,管理员通过 /api/admin/users 创建账号
- 首次启动自动创建 admin 账号(密码从 ADMIN_DEFAULT_PASSWORD 读取或随机生成打印到控制台)
- 前端 localStorage 键名加 user_id 前缀(如 `epeekit-{userId}-sessions`)实现数据隔离
- Mem0 的 user_id 从 JWT 中解析的真实用户 ID 传入,替代硬编码 `default_user`
- AppProvider 未登录时返回 `<>{children}</>` 而非 null确保 /login 页面可渲染
- **notes**:
- 旧 Mem0 数据仍在 `default_user` 下,不自动迁移,新用户从零积累
- 前端 401 响应自动跳转 /loginXHR上传和 fetch 均处理
- TopNav 右侧新增用户菜单(显示名称 + 退出登录)
- 需在 .env 中配置 JWT_SECRET否则启动时 RuntimeError
### [CL-20260414-2230] 2026-04-14 22:30 — 对话区域新增"回到底部"浮动按钮
- **tags**: 前端, UX, 滚动, 浮动按钮
- **affected_files**:
- art-agent/frontend/src/app/page.tsx
- **what**: 当用户在对话中间位置时,显示一个浮动的向下箭头按钮,点击平滑滚到最新消息
- **why**: 长对话中浏览历史消息后,缺少快速回到最新内容的入口
- **decisions**: 复用已有的 scroll 事件监听器检测距底部距离(阈值 200px按钮定位在输入框上方右侧。切换会话恢复位置后也主动检查按钮显示状态。使用已有的 `fadeIn` keyframes 动画
- **notes**: 按钮使用 `absolute` 定位在 `main` 容器内,`bottom-16` 避开输入框
### [CL-20260414-2220] 2026-04-14 22:20 — 修复长对话切换回来滚动位置上移scroll 事件实时保存取代 effect 延迟保存
- **tags**: 前端, bug修复, 滚动, 多会话, UX, scroll 事件
- **affected_files**:
- art-agent/frontend/src/app/page.tsx
- **what**: 修复长对话切换回来后滚动位置上移的 bug
- **why**: 之前在 useEffect 中保存旧会话的 scrollTop但 effect 执行时 DOM 已经渲染了新会话短对话的内容scrollHeight 变小,浏览器自动将 scrollTop 钳位clamp`scrollHeight - clientHeight`,导致保存的值远小于真实位置。最长的对话受影响最大,因为它的 scrollTop 差值最大
- **decisions**: 改用 scroll 事件监听器实时保存当前会话的 scrollTop 到 Map 中。这样在任何 state 变更或 DOM 重渲染之前,最新的滚动位置已经被记录。切换期间(`isSwitching=true`)跳过 scroll handler 写入,避免恢复过程中的中间值覆盖正确值
- **notes**: 这是 CL-20260414-2210 的后续修复。scroll 事件加了 `{ passive: true }` 避免影响滚动性能。cleanup 函数在 `activeSessionId` 变化时正确移除旧 listener
### [CL-20260414-2210] 2026-04-14 22:10 — 修复会话切换时滚动位置跳动:解决时序竞争 + 抑制切换期间 smooth scroll
- **tags**: 前端, bug修复, 滚动, 多会话, UX, 时序
- **affected_files**:
- art-agent/frontend/src/app/page.tsx
- **what**: 修复会话切换时滚动条频繁跳动的问题
- **why**: 上一版修复CL-20260414-2200存在时序竞争`useEffect``requestAnimationFrame` 执行时 React 可能还没将新会话的 messages 渲染到 DOM 中,导致 `scrollHeight` 是旧值。另外切换期间 `scrollToBottom(smooth)` 没有被抑制smooth 动画与位置恢复互相干扰
- **decisions**:
- 拆为两个 effect第一个依赖 `activeSessionId`)只做保存旧位置 + 设 `isSwitching` 标记;第二个(依赖 `activeSessionId` + `messages.length`)在 messages 内容更新后才恢复位置
- 新增 `isSwitching` ref切换期间抑制非 instant 的 `scrollToBottom` 调用,避免 smooth 动画干扰
- instant 模式改为直接赋值 `el.scrollTop = ...`,不再走 setTimeout消除额外异步
- `messages` 声明提前到 effect 之前,确保 `messages.length` 可在 effect 依赖中使用
- **notes**: 图片异步加载仍可能导致 scrollHeight 变化使恢复位置偏移,但这是更深层问题,当前改动先解决核心的切换跳动
### [CL-20260414-2200] 2026-04-14 22:00 — 修复多会话滚动位置共享 bugper-session 独立记录 + 切换恢复
- **tags**: 前端, bug修复, 滚动, 多会话, UX
- **affected_files**:
- art-agent/frontend/src/app/page.tsx
- **what**: 修复多会话切换时滚动条位置共享的 bug实现 per-session 滚动位置独立记录与恢复
- **why**: 所有会话共用同一个 scrollRef DOM 元素,切换会话时既不保存旧会话的 scrollTop也不恢复目标会话的位置。导致从长会话切到短会话可能看到空白底部从短会话切到长会话不会停在最新消息处
- **decisions**: 用 `useRef<Map<string, number>>` 在内存中记录每个会话的 scrollTop而非 localStorage因为滚动位置是临时状态刷新页面后重新滚到底部是合理的默认行为
- **notes**:
- 切换会话时,先保存离开会话的 scrollTop再用 `requestAnimationFrame` 等 DOM 渲染完新消息后恢复目标位置
- 无记录的会话(首次进入或新建)使用 `scrollToBottom(true)` 即时滚到底部
- `scrollToBottom` 改为 `useCallback` 并新增 `instant` 参数,恢复位置时用 instant 避免视觉跳动,正常对话流用 smooth
-`scrollToBottom` 加入 `handleSend` 的依赖数组,修复潜在的陈旧闭包问题
### [CL-20260413-2320] 2026-04-13 23:20 — 集成 Mem0 记忆系统:滑动窗口 + 跨会话长期记忆
- **tags**: Mem0, 记忆系统, 上下文管理, 长期记忆, Ollama, embedding, 滑动窗口
- **affected_files**:

View File

@@ -2,6 +2,13 @@
最近 ~50 次改动的一句话概要,按时间倒序排列。每次会话自动注入上下文。
- [CL-20260414-2340] 用 pwdlib (Argon2id) 替换 passlib (bcrypt):彻底解决兼容性问题,新密码 Argon2id旧 bcrypt 哈希兼容验证
- [CL-20260414-2330] 修复 passlib + bcrypt 5.x 兼容性:锁定 bcrypt>=4.0.1,<4.1,解决后端启动 AttributeError + ValueError
- [CL-20260414-2300] 用户系统:管理员邀请制 + JWT 认证 + SQLite 用户表 + Mem0/localStorage 按用户隔离,所有 API 鉴权,前端登录页 + AuthGuard
- [CL-20260414-2230] 对话区域新增"回到底部"浮动按钮:不在底部时显示向下箭头,点击平滑滚到最新消息
- [CL-20260414-2220] 修复长对话切换回来滚动位置上移scroll 事件实时保存替代 effect 延迟保存,避免 DOM 变更后 scrollTop 被浏览器 clamp
- [CL-20260414-2210] 修复会话切换时滚动位置跳动:拆 effect 解决时序竞争 + isSwitching 抑制 smooth scroll 干扰 + instant 同步赋值
- [CL-20260414-2200] 修复多会话滚动位置共享 bugper-session 独立记录滚动位置,切换会话时保存/恢复,无记录时滚到底部
- [CL-20260413-2320] 集成 Mem0 记忆系统Mem0 OSS + DeepSeek 事实提取 + Ollama 本地 embedding + 滑动窗口,一次性解决上下文管理和跨会话长期记忆
- [CL-20260413-1130] 修复 SDXL 模型 404 错误:与 Kolors 同因Replicate 非 Flux 官方模型需补全版本 hash
- [CL-20260413-1100] 修复切换模型后 LLM 仍声称使用旧模型名System Prompt 动态注入当前模型名,阻止 LLM 从对话历史幻觉旧模型

View File

@@ -3,6 +3,41 @@
最近 ~10 次改动的摘要记录,按时间倒序排列。
当 Agent 检测到当前任务与近期改动相关时自动读取。
### [CL-20260414-2340] 2026-04-14 — 用 pwdlib (Argon2id) 替换 passlib (bcrypt),彻底解决兼容性问题
- **tags**: 重构, 安全, 密码哈希, Argon2, pwdlib, passlib, 依赖升级
- **affected_files**: auth.py, requirements.txt, docs/art-agent/USER-SYSTEM.md
- **summary**: passlib 已停止维护且与 bcrypt 5.x 不兼容。替换为 pwdlib[argon2,bcrypt],新密码用 Argon2id旧 bcrypt 哈希仍可验证。不再需要锁定 bcrypt 版本。
### [CL-20260414-2330] 2026-04-14 — 修复 passlib + bcrypt 5.x 兼容性问题,锁定 bcrypt<4.1
- **tags**: bug修复, 依赖, bcrypt, passlib, 用户系统
- **affected_files**: requirements.txt, docs/art-agent/USER-SYSTEM.md
- **summary**: passlib 1.7.4 与 bcrypt 5.0.0 不兼容(`__about__` 移除 + 密码长度 ValueError后端启动报错。降级 bcrypt 到 4.0.1 并在 requirements.txt 中锁定 `>=4.0.1,<4.1`。同时在用户系统文档故障排除中补充此问题。
### [CL-20260414-2300] 2026-04-14 — 用户系统:管理员邀请制 + JWT 认证 + 数据按用户隔离
- **tags**: 用户系统, 认证, JWT, SQLite, 数据隔离, 多用户, 安全
- **affected_files**: db.py, auth.py, api/auth.py, api/admin.py, chat.py, main.py, loop.py, auth-context.tsx, auth-guard.tsx, api.ts, store.ts, app-context.tsx, layout.tsx, login/page.tsx, top-nav.tsx, model-selector.tsx, requirements.txt, .env.example
- **summary**: 后端新增 SQLite 用户表 + JWT 认证access+refresh+ 管理员/普通用户路由,所有 API 加鉴权Mem0 user_id 改为真实用户 ID。前端新增登录页 + AuthProvider/AuthGuard + 401 自动跳转 + localStorage 按用户 ID 隔离。TopNav 新增用户菜单。首次启动自动创建 admin。
### [CL-20260414-2230] 2026-04-14 — 对话区域新增"回到底部"浮动按钮
- **tags**: 前端, UX, 滚动, 浮动按钮
- **affected_files**: art-agent/frontend/src/app/page.tsx
- **summary**: 长对话中不在底部时,右下角显示向下箭头按钮,点击平滑滚到最新消息。复用 scroll 监听器检测距底部距离(>200px 显示),切换会话后也同步按钮状态。
### [CL-20260414-2220] 2026-04-14 — 修复长对话切换回来滚动位置上移scroll 事件实时保存取代 effect 延迟保存
- **tags**: 前端, bug修复, 滚动, 多会话, UX, scroll 事件
- **affected_files**: art-agent/frontend/src/app/page.tsx
- **summary**: effect 中保存 scrollTop 时 DOM 已变为短对话内容,浏览器 clamp scrollTop 导致保存值偏小。改用 scroll 事件实时记录位置,确保在任何 DOM 变更之前数据已正确保存。
### [CL-20260414-2210] 2026-04-14 — 修复会话切换时滚动位置跳动:时序竞争 + 抑制切换期间 smooth scroll
- **tags**: 前端, bug修复, 滚动, 多会话, UX, 时序
- **affected_files**: art-agent/frontend/src/app/page.tsx
- **summary**: CL-20260414-2200 的 rAF 恢复时序不可靠——React 可能还没渲染新会话内容scrollHeight 是旧值。拆为两个 effect保存+标记 / 等 messages 更新后恢复),新增 `isSwitching` 抑制切换期间的 smooth scroll 干扰instant 模式改为同步赋值 `scrollTop`
### [CL-20260414-2200] 2026-04-14 — 修复多会话滚动位置共享 bugper-session 独立记录 + 切换恢复
- **tags**: 前端, bug修复, 滚动, 多会话, UX
- **affected_files**: art-agent/frontend/src/app/page.tsx
- **summary**: 所有会话共用同一 scrollRef切换时不保存/恢复 scrollTop。修复新增 `scrollPositions` Map 按 sessionId 记录滚动位置,`useEffect` 监听 `activeSessionId` 变化时保存旧位置、恢复新位置(有记录则恢复,无记录则 scrollToBottom`scrollToBottom` 改为 useCallback + 支持 instant 模式。
### [CL-20260413-2320] 2026-04-13 — 集成 Mem0 记忆系统:滑动窗口 + 跨会话长期记忆
- **tags**: Mem0, 记忆系统, 上下文管理, 长期记忆, Ollama, embedding, 滑动窗口
- **affected_files**: app/memory.py, app/agent/loop.py, app/config.py, app/api/chat.py, requirements.txt, .env, frontend/src/lib/api.ts, frontend/src/app/page.tsx