feat: 重构 memory 系统,支持 user memory 和 work memory 分离
This commit is contained in:
@@ -0,0 +1,231 @@
|
||||
# Memories 界面实现计划
|
||||
|
||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||
|
||||
**Goal:** 实现前端memories界面,卡片列表展示user和work记忆,支持查看详情和更新
|
||||
|
||||
**Architecture:**
|
||||
- 使用现有ApiClient调用后端 `/api/v1/memories` 接口
|
||||
- 数据模型解析UserMemoryContent和WorkProfileContent
|
||||
- 遵循项目视觉设计语言(soft blue, layered card-based)
|
||||
- 通过GoRouter管理导航
|
||||
|
||||
**Tech Stack:** Flutter, Dio, GoRouter, GetIt依赖注入
|
||||
|
||||
---
|
||||
|
||||
### Task 1: 创建Memory数据模型
|
||||
|
||||
**Files:**
|
||||
- Create: `apps/lib/features/settings/data/models/memory_models.dart`
|
||||
|
||||
**Step 1: 创建数据模型文件**
|
||||
|
||||
```dart
|
||||
// UserMemoryContent - 用户记忆
|
||||
class UserMemoryContent {
|
||||
final String? occupation;
|
||||
final String? timezone;
|
||||
final String? primaryLanguage;
|
||||
final List<Person> people;
|
||||
final List<Place> places;
|
||||
final UserPreferences preferences;
|
||||
final SchedulingPreferences schedulingPreferences;
|
||||
final List<String> interests;
|
||||
final List<String> avoidTopics;
|
||||
final List<String> customRules;
|
||||
final List<RecurringRoutine> recurringRoutines;
|
||||
|
||||
// ... 工厂方法 fromJson
|
||||
}
|
||||
|
||||
class Person {
|
||||
final String name;
|
||||
final String? relationship;
|
||||
final String? role;
|
||||
final String? preferredContactChannel;
|
||||
final String? notes;
|
||||
final PersonMeta? meta;
|
||||
}
|
||||
|
||||
class Place {
|
||||
final String name;
|
||||
final String? category;
|
||||
final String? address;
|
||||
final String? timezone;
|
||||
final int? commuteMinutes;
|
||||
final String? preference;
|
||||
final String? notes;
|
||||
final PlaceMeta? meta;
|
||||
}
|
||||
|
||||
// WorkProfileContent - 工作记忆
|
||||
class WorkProfileContent {
|
||||
final String? occupation;
|
||||
final List<String> expertise;
|
||||
final List<String> preferredTools;
|
||||
final List<CurrentProject> currentProjects;
|
||||
final WorkHabits workHabits;
|
||||
final List<TeamMember> teamMembers;
|
||||
final String? teamContext;
|
||||
final List<String> workRules;
|
||||
}
|
||||
|
||||
// MemoryListResponse - API响应
|
||||
class MemoryListResponse {
|
||||
final UserMemoryContent? userMemory;
|
||||
final WorkProfileContent? workMemory;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 2: 更新MemoryService调用真实API
|
||||
|
||||
**Files:**
|
||||
- Modify: `apps/lib/features/settings/data/services/memory_service.dart`
|
||||
|
||||
**Step 1: 重写MemoryService**
|
||||
|
||||
```dart
|
||||
import 'package:social_app/core/api/i_api_client.dart';
|
||||
import '../models/memory_models.dart';
|
||||
|
||||
class MemoryService {
|
||||
final IApiClient _client;
|
||||
static const _prefix = '/api/v1/memories';
|
||||
|
||||
MemoryService(this._client);
|
||||
|
||||
Future<MemoryListResponse> getAllMemories() async { ... }
|
||||
Future<UserMemoryContent?> getUserMemory() async { ... }
|
||||
Future<WorkProfileContent?> getWorkMemory() async { ... }
|
||||
Future<UserMemoryContent> updateUserMemory(UserMemoryContent content) async { ... }
|
||||
Future<WorkProfileContent> updateWorkMemory(WorkProfileContent content) async { ... }
|
||||
Future<UserMemoryContent> patchUserMemory(Map<String, dynamic> content) async { ... }
|
||||
Future<WorkProfileContent> patchWorkMemory(Map<String, dynamic> content) async { ... }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 3: 在injection.dart中注册MemoryService
|
||||
|
||||
**Files:**
|
||||
- Modify: `apps/lib/core/di/injection.dart:26` - 添加import
|
||||
- Modify: `apps/lib/core/di/injection.dart` - 注册MemoryService
|
||||
|
||||
---
|
||||
|
||||
### Task 4: 重新设计MemoryScreen主页面
|
||||
|
||||
**Files:**
|
||||
- Modify: `apps/lib/features/settings/ui/screens/memory_screen.dart`
|
||||
|
||||
**设计要点:**
|
||||
- 顶部启用记忆开关卡片
|
||||
- 两个主要卡片: User Memory (用户记忆) 和 Work Memory (工作记忆)
|
||||
- 每个卡片显示关键摘要信息
|
||||
- 点击卡片进入对应详情页
|
||||
- 底部"管理记忆条目"按钮可点击展开更多信息
|
||||
- 遵循soft blue品牌、layered card-based界面
|
||||
|
||||
**卡片内容:**
|
||||
- User Memory: 显示 occupation, people数量, places数量, interests数量
|
||||
- Work Memory: 显示 occupation, expertise数量, currentProjects数量, teamMembers数量
|
||||
|
||||
---
|
||||
|
||||
### Task 5: 创建UserMemoryDetailScreen
|
||||
|
||||
**Files:**
|
||||
- Create: `apps/lib/features/settings/ui/screens/user_memory_detail_screen.dart`
|
||||
|
||||
**功能:**
|
||||
- 显示完整的UserMemoryContent信息
|
||||
- 支持编辑和更新
|
||||
- 分组展示: 基本信息、联系人、地点、偏好设置、日程偏好、兴趣、回避话题等
|
||||
- 使用可折叠的Section展示
|
||||
|
||||
---
|
||||
|
||||
### Task 6: 创建WorkMemoryDetailScreen
|
||||
|
||||
**Files:**
|
||||
- Create: `apps/lib/features/settings/ui/screens/work_memory_detail_screen.dart`
|
||||
|
||||
**功能:**
|
||||
- 显示完整的WorkProfileContent信息
|
||||
- 支持编辑和更新
|
||||
- 分组展示: 基本信息、项目、团队成员、工作习惯等
|
||||
- 使用可折叠的Section展示
|
||||
|
||||
---
|
||||
|
||||
### Task 7: 添加路由配置
|
||||
|
||||
**Files:**
|
||||
- Modify: `apps/lib/core/router/app_router.dart:26` - 添加import
|
||||
- Modify: `apps/lib/core/router/app_router.dart` - 添加路由
|
||||
- Modify: `apps/lib/core/router/app_routes.dart` - 添加路由常量
|
||||
|
||||
**新增路由:**
|
||||
- `/settings/memory/user` - UserMemoryDetailScreen
|
||||
- `/settings/memory/work` - WorkMemoryDetailScreen
|
||||
|
||||
---
|
||||
|
||||
### Task 8: 更新MemoryScreen导航
|
||||
|
||||
**Files:**
|
||||
- Modify: `apps/lib/features/settings/ui/screens/memory_screen.dart`
|
||||
|
||||
**Step 1: 添加导航跳转**
|
||||
|
||||
```dart
|
||||
// 点击User Memory卡片
|
||||
context.push('/settings/memory/user');
|
||||
|
||||
// 点击Work Memory卡片
|
||||
context.push('/settings/memory/work');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 9: 验证和测试
|
||||
|
||||
**Step 1: 运行flutter analyze检查代码质量**
|
||||
|
||||
```bash
|
||||
cd apps && flutter analyze
|
||||
```
|
||||
|
||||
**Step 2: 验证设计token使用正确**
|
||||
|
||||
检查所有颜色、间距、圆角都来自design_tokens.dart
|
||||
|
||||
**Step 3: 验证API调用正确**
|
||||
|
||||
确认使用正确的endpoint和HTTP方法
|
||||
|
||||
---
|
||||
|
||||
### 关键文件路径参考
|
||||
|
||||
- Design tokens: `apps/lib/core/theme/design_tokens.dart`
|
||||
- Visual design language: `apps/rules/visual_design_language.md`
|
||||
- Settings scaffold: `apps/lib/features/settings/ui/widgets/settings_page_scaffold.dart`
|
||||
- API client: `apps/lib/core/api/api_client.dart`
|
||||
- 后端router: `backend/src/v1/memories/router.py`
|
||||
- Protocol文档: `docs/protocols/models/memory.md`
|
||||
|
||||
---
|
||||
|
||||
### 视觉设计要点
|
||||
|
||||
1. **Surface层次**: Background → Primary cards → Secondary grouped surfaces
|
||||
2. **Color**: 使用AppColors.blue系列作为品牌色,避免过度使用
|
||||
3. **Spacing**: 使用AppSpacing (xs=4, sm=8, md=12, lg=16, xl=20, xxl=24)
|
||||
4. **Radius**: 使用AppRadius (sm=6, md=12, lg=16, xl=18, xxl=24)
|
||||
5. **Motion**: 150-300ms micro-interactions, soft press feedback
|
||||
6. **卡片阴影**: 使用soft shadow如 `blurRadius: 8, offset: (0, 2)`
|
||||
@@ -0,0 +1,78 @@
|
||||
# Memory System Design
|
||||
|
||||
## Overview
|
||||
|
||||
每用户有两条记忆记录(user_type 和 work_type),存储在 `memories` 表的 `content` JSONB 字段中。
|
||||
|
||||
## Data Model
|
||||
|
||||
### UserMemoryContent
|
||||
|
||||
```python
|
||||
class UserPreferences(BaseModel):
|
||||
time_preference: str | None = None # "上午效率高"
|
||||
communication_style: str | None = None # "简洁直接"
|
||||
location_preference: str | None = None # "喜欢远程工作"
|
||||
work_lifestyle: str | None = None # "早睡早起"
|
||||
|
||||
class UserMemoryContent(BaseModel):
|
||||
occupation: str | None = None # 职业
|
||||
timezone: str | None = None # 时区
|
||||
language: str | None = None # 语言偏好
|
||||
people: list[str] = [] # 重要人物
|
||||
places: list[str] = [] # 常去地点
|
||||
projects: list[str] = [] # 个人项目
|
||||
preferences: UserPreferences = UserPreferences()
|
||||
interests: list[str] = [] # 兴趣爱好
|
||||
avoid_topics: list[str] = [] # 不想讨论的话题
|
||||
custom_rules: list[str] = [] # 自定义规则
|
||||
recurring_contexts: list[str] = [] # 周期性场景
|
||||
```
|
||||
|
||||
### WorkMemoryContent
|
||||
|
||||
```python
|
||||
class WorkProject(BaseModel):
|
||||
name: str
|
||||
description: str | None = None
|
||||
status: str | None = None # "active", "paused"
|
||||
key_milestones: list[str] = [] # 关键里程碑
|
||||
|
||||
class WorkHabit(BaseModel):
|
||||
available_hours: dict[str, str] = {} # {"monday": "09:00-18:00"}
|
||||
deep_work_blocks: list[str] = [] # 深度工作时段
|
||||
meeting_preference: str | None = None # "short", "30min最佳"
|
||||
notification_channel: str | None = None # 首选沟通渠道
|
||||
|
||||
class WorkMemoryContent(BaseModel):
|
||||
expertise: list[str] = [] # 专业领域
|
||||
preferred_tools: list[str] = [] # 惯用工具
|
||||
current_projects: list[WorkProject] = []
|
||||
work_habits: WorkHabit = WorkHabit()
|
||||
team_members: list[str] = [] # 团队成员
|
||||
team_context: str | None = None # 团队概述
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
| Method | Endpoint | Description |
|
||||
|--------|----------|-------------|
|
||||
| GET | `/api/v1/memories` | 获取用户所有记忆 |
|
||||
| PUT | `/api/v1/memories/user` | 创建/更新用户记忆 |
|
||||
| PUT | `/api/v1/memories/work` | 创建/更新工作记忆 |
|
||||
| DELETE | `/api/v1/memories/{type}` | 删除指定类型记忆 |
|
||||
|
||||
## TaskType支撑关系
|
||||
|
||||
| TaskType | Router决策依赖 | Worker执行依赖 |
|
||||
|----------|---------------|---------------|
|
||||
| SCHEDULING | timezone, available_hours | current_projects, team_members |
|
||||
| PLANNING | preferences, work_lifestyle | expertise, work_habits |
|
||||
| COMMUNICATION_DRAFTING | communication_style, avoid_topics | team_context, preferred_tools |
|
||||
| RECOMMENDATION | interests, people | expertise, current_projects |
|
||||
|
||||
## Frontend UI
|
||||
|
||||
- MemoryScreen: 主列表页,展示user/work两条记忆卡片
|
||||
- MemoryDetailScreen: 详情/编辑页,分Tab展示各字段
|
||||
- 支持新建/编辑/删除操作
|
||||
@@ -0,0 +1,262 @@
|
||||
# Schedule Items 协议
|
||||
|
||||
本文档定义 `/api/v1/schedule-items` 的日历日程管理协议。
|
||||
|
||||
Base URL: `/api/v1/schedule-items`
|
||||
|
||||
---
|
||||
|
||||
## 端点
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|---|---|---|
|
||||
| POST | `` | 创建日程 |
|
||||
| GET | `` | 按日期范围查询日程 |
|
||||
| GET | `/{item_id}` | 获取指定日程详情 |
|
||||
| PATCH | `/{item_id}` | 更新日程 |
|
||||
| DELETE | `/{item_id}` | 删除日程 |
|
||||
| POST | `/{item_id}/share` | 分享日程给其他用户 |
|
||||
| POST | `/{item_id}/accept` | 接受日程订阅 |
|
||||
| POST | `/{item_id}/reject` | 拒绝日程订阅 |
|
||||
|
||||
---
|
||||
|
||||
## 枚举类型
|
||||
|
||||
### ScheduleItemStatus
|
||||
|
||||
| 值 | 说明 |
|
||||
|---|---|
|
||||
| `active` | 进行中 |
|
||||
| `completed` | 已完成 |
|
||||
| `canceled` | 已取消 |
|
||||
| `archived` | 已归档 |
|
||||
|
||||
### ScheduleItemSourceType
|
||||
|
||||
| 值 | 说明 |
|
||||
|---|---|
|
||||
| `manual` | 手动创建 |
|
||||
| `imported` | 导入 |
|
||||
| `agent_generated` | Agent 生成 |
|
||||
|
||||
### AttachmentType
|
||||
|
||||
| 值 | 说明 |
|
||||
|---|---|
|
||||
| `document` | 文档 |
|
||||
| `reminder` | 提醒 |
|
||||
|
||||
---
|
||||
|
||||
## 数据结构
|
||||
|
||||
### ScheduleItemMetadata
|
||||
|
||||
```json
|
||||
{
|
||||
"color": "#FF5733 | null",
|
||||
"location": "string | null",
|
||||
"notes": "string | null",
|
||||
"attachments": [
|
||||
{
|
||||
"name": "string",
|
||||
"type": "document | reminder",
|
||||
"visible_to": ["uuid"],
|
||||
"url": "string | null",
|
||||
"note": "string | null",
|
||||
"content": "string | null"
|
||||
}
|
||||
],
|
||||
"reminder_minutes": "int (0-10080) | null",
|
||||
"version": 1
|
||||
}
|
||||
```
|
||||
|
||||
### ScheduleItemCreateRequest
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "string (1-255)",
|
||||
"description": "string | null (max 2000)",
|
||||
"start_at": "datetime (必须包含时区)",
|
||||
"end_at": "datetime | null (必须包含时区)",
|
||||
"timezone": "string (IANA 时区)",
|
||||
"metadata": "ScheduleItemMetadata | null"
|
||||
}
|
||||
```
|
||||
|
||||
### ScheduleItemUpdateRequest
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "string | null (1-255)",
|
||||
"description": "string | null (max 2000)",
|
||||
"start_at": "datetime | null (必须包含时区)",
|
||||
"end_at": "datetime | null (必须包含时区)",
|
||||
"timezone": "string | null (IANA 时区)",
|
||||
"metadata": "ScheduleItemMetadata | null",
|
||||
"status": "ScheduleItemStatus | null"
|
||||
}
|
||||
```
|
||||
|
||||
### ScheduleItemResponse
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"owner_id": "uuid",
|
||||
"title": "string",
|
||||
"description": "string | null",
|
||||
"start_at": "datetime",
|
||||
"end_at": "datetime | null",
|
||||
"timezone": "string",
|
||||
"metadata": "ScheduleItemMetadata | null",
|
||||
"status": "ScheduleItemStatus",
|
||||
"source_type": "ScheduleItemSourceType",
|
||||
"created_at": "datetime",
|
||||
"updated_at": "datetime",
|
||||
"permission": "int",
|
||||
"is_owner": "boolean"
|
||||
}
|
||||
```
|
||||
|
||||
### ScheduleItemShareRequest
|
||||
|
||||
```json
|
||||
{
|
||||
"phone": "+8613812345678",
|
||||
"permission_view": "boolean (default: true)",
|
||||
"permission_edit": "boolean (default: false)",
|
||||
"permission_invite": "boolean (default: false)"
|
||||
}
|
||||
```
|
||||
|
||||
### ScheduleItemShareResponse
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "string"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1) POST `/`
|
||||
|
||||
创建日程。
|
||||
|
||||
### Request
|
||||
|
||||
`ScheduleItemCreateRequest` 对象。
|
||||
|
||||
### Response
|
||||
|
||||
`ScheduleItemResponse` 对象,状态码 201。
|
||||
|
||||
---
|
||||
|
||||
## 2) GET `/`
|
||||
|
||||
按日期范围查询日程。
|
||||
|
||||
### Query Parameters
|
||||
|
||||
- `start_at`: 开始时间(必须包含时区)
|
||||
- `end_at`: 结束时间(必须包含时区)
|
||||
|
||||
### Response
|
||||
|
||||
`ScheduleItemResponse` 对象数组。
|
||||
|
||||
---
|
||||
|
||||
## 3) GET `/{item_id}`
|
||||
|
||||
获取指定日程详情。
|
||||
|
||||
### Path Parameters
|
||||
|
||||
- `item_id`: 日程 UUID
|
||||
|
||||
### Response
|
||||
|
||||
`ScheduleItemResponse` 对象。
|
||||
|
||||
---
|
||||
|
||||
## 4) PATCH `/{item_id}`
|
||||
|
||||
更新日程(部分更新)。
|
||||
|
||||
### Path Parameters
|
||||
|
||||
- `item_id`: 日程 UUID
|
||||
|
||||
### Request
|
||||
|
||||
`ScheduleItemUpdateRequest` 对象。
|
||||
|
||||
### Response
|
||||
|
||||
`ScheduleItemResponse` 对象。
|
||||
|
||||
---
|
||||
|
||||
## 5) DELETE `/{item_id}`
|
||||
|
||||
删除日程。
|
||||
|
||||
### Path Parameters
|
||||
|
||||
- `item_id`: 日程 UUID
|
||||
|
||||
### Response
|
||||
|
||||
204 No Content。
|
||||
|
||||
---
|
||||
|
||||
## 6) POST `/{item_id}/share`
|
||||
|
||||
分享日程给其他用户。
|
||||
|
||||
### Path Parameters
|
||||
|
||||
- `item_id`: 日程 UUID
|
||||
|
||||
### Request
|
||||
|
||||
`ScheduleItemShareRequest` 对象。
|
||||
|
||||
### Response
|
||||
|
||||
`ScheduleItemShareResponse` 对象。
|
||||
|
||||
---
|
||||
|
||||
## 7) POST `/{item_id}/accept`
|
||||
|
||||
接受日程订阅邀请。
|
||||
|
||||
### Path Parameters
|
||||
|
||||
- `item_id`: 日程 UUID
|
||||
|
||||
### Response
|
||||
|
||||
字典对象。
|
||||
|
||||
---
|
||||
|
||||
## 8) POST `/{item_id}/reject`
|
||||
|
||||
拒绝日程订阅邀请。
|
||||
|
||||
### Path Parameters
|
||||
|
||||
- `item_id`: 日程 UUID
|
||||
|
||||
### Response
|
||||
|
||||
字典对象。
|
||||
@@ -0,0 +1,188 @@
|
||||
# Friendships 协议
|
||||
|
||||
本文档定义 `/api/v1/friends` 的好友申请与管理协议。
|
||||
|
||||
Base URL: `/api/v1/friends`
|
||||
|
||||
---
|
||||
|
||||
## 端点
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|---|---|---|
|
||||
| POST | `/requests` | 发送好友申请 |
|
||||
| GET | `/requests/inbox` | 获取收到的好友申请列表 |
|
||||
| GET | `/requests/outgoing` | 获取发出的好友申请列表 |
|
||||
| GET | `/requests/{friendship_id}` | 获取指定好友申请详情 |
|
||||
| POST | `/requests/{friendship_id}/accept` | 接受好友申请 |
|
||||
| POST | `/requests/{friendship_id}/decline` | 拒绝好友申请 |
|
||||
| DELETE | `/requests/{friendship_id}` | 取消发出的好友申请 |
|
||||
| GET | `` | 获取好友列表 |
|
||||
| DELETE | `/{friendship_id}` | 删除好友 |
|
||||
|
||||
---
|
||||
|
||||
## 数据结构
|
||||
|
||||
### FriendRequestCreate
|
||||
|
||||
```json
|
||||
{
|
||||
"target_user_id": "uuid",
|
||||
"content": "string | null"
|
||||
}
|
||||
```
|
||||
|
||||
- `target_user_id`: 目标用户 ID
|
||||
- `content`: 申请消息,最大 200 字符
|
||||
|
||||
### FriendRequestResponse
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"sender": { /* UserContext */ },
|
||||
"recipient": { /* UserContext */ },
|
||||
"content": { "type": "request", "message": "string | null" } | null,
|
||||
"status": "pending | accepted | rejected | canceled",
|
||||
"created_at": "datetime"
|
||||
}
|
||||
```
|
||||
|
||||
### FriendResponse
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"friend": { /* UserContext */ },
|
||||
"status": "active",
|
||||
"created_at": "datetime",
|
||||
"accepted_at": "datetime | null"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1) POST `/requests`
|
||||
|
||||
发送好友申请。
|
||||
|
||||
### Request
|
||||
|
||||
`FriendRequestCreate` 对象。
|
||||
|
||||
### Response
|
||||
|
||||
`FriendRequestResponse` 对象,状态码 201。
|
||||
|
||||
---
|
||||
|
||||
## 2) GET `/requests/inbox`
|
||||
|
||||
获取收到的待处理好友申请列表。
|
||||
|
||||
### Request
|
||||
|
||||
无请求体。
|
||||
|
||||
### Response
|
||||
|
||||
`FriendRequestResponse` 对象数组,状态为 `pending`。
|
||||
|
||||
---
|
||||
|
||||
## 3) GET `/requests/outgoing`
|
||||
|
||||
获取发出的好友申请列表。
|
||||
|
||||
### Request
|
||||
|
||||
无请求体。
|
||||
|
||||
### Response
|
||||
|
||||
`FriendRequestResponse` 对象数组。
|
||||
|
||||
---
|
||||
|
||||
## 4) GET `/requests/{friendship_id}`
|
||||
|
||||
获取指定好友申请详情。
|
||||
|
||||
### Path Parameters
|
||||
|
||||
- `friendship_id`: 好友申请 UUID
|
||||
|
||||
### Response
|
||||
|
||||
`FriendRequestResponse` 对象。
|
||||
|
||||
---
|
||||
|
||||
## 5) POST `/requests/{friendship_id}/accept`
|
||||
|
||||
接受好友申请。
|
||||
|
||||
### Path Parameters
|
||||
|
||||
- `friendship_id`: 好友申请 UUID
|
||||
|
||||
### Response
|
||||
|
||||
`FriendRequestResponse` 对象,状态更新为 `accepted`。
|
||||
|
||||
---
|
||||
|
||||
## 6) POST `/requests/{friendship_id}/decline`
|
||||
|
||||
拒绝好友申请。
|
||||
|
||||
### Path Parameters
|
||||
|
||||
- `friendship_id`: 好友申请 UUID
|
||||
|
||||
### Response
|
||||
|
||||
`FriendRequestResponse` 对象,状态更新为 `rejected`。
|
||||
|
||||
---
|
||||
|
||||
## 7) DELETE `/requests/{friendship_id}`
|
||||
|
||||
取消发出的好友申请。
|
||||
|
||||
### Path Parameters
|
||||
|
||||
- `friendship_id`: 好友申请 UUID
|
||||
|
||||
### Response
|
||||
|
||||
204 No Content。
|
||||
|
||||
---
|
||||
|
||||
## 8) GET `/`
|
||||
|
||||
获取好友列表。
|
||||
|
||||
### Request
|
||||
|
||||
无请求体。
|
||||
|
||||
### Response
|
||||
|
||||
`FriendResponse` 对象数组,状态为 `active`。
|
||||
|
||||
---
|
||||
|
||||
## 9) DELETE `/{friendship_id}`
|
||||
|
||||
删除好友。
|
||||
|
||||
### Path Parameters
|
||||
|
||||
- `friendship_id`: 好友关系 UUID
|
||||
|
||||
### Response
|
||||
|
||||
204 No Content。
|
||||
@@ -0,0 +1,128 @@
|
||||
# Inbox Messages 协议
|
||||
|
||||
本文档定义 `/api/v1/inbox/messages` 的收件箱消息协议。
|
||||
|
||||
Base URL: `/api/v1/inbox/messages`
|
||||
|
||||
---
|
||||
|
||||
## 端点
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|---|---|---|
|
||||
| GET | `` | 获取消息列表 |
|
||||
| PATCH | `/{message_id}/read` | 标记消息为已读 |
|
||||
|
||||
---
|
||||
|
||||
## 枚举类型
|
||||
|
||||
### InboxMessageType
|
||||
|
||||
| 值 | 说明 |
|
||||
|---|---|
|
||||
| `friend_request` | 好友申请 |
|
||||
| `calendar` | 日历消息 |
|
||||
| `system` | 系统消息 |
|
||||
| `group` | 群组消息 |
|
||||
|
||||
### InboxMessageStatus
|
||||
|
||||
| 值 | 说明 |
|
||||
|---|---|
|
||||
| `pending` | 待处理 |
|
||||
| `accepted` | 已接受 |
|
||||
| `rejected` | 已拒绝 |
|
||||
| `dismissed` | 已忽略 |
|
||||
|
||||
---
|
||||
|
||||
## 消息内容类型
|
||||
|
||||
### CalendarInviteContent
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "invite",
|
||||
"permission": "int (1=view, 4=edit, 8=invite)",
|
||||
"action": "pending"
|
||||
}
|
||||
```
|
||||
|
||||
### CalendarUpdateContent
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "update",
|
||||
"title": "string",
|
||||
"action": "updated"
|
||||
}
|
||||
```
|
||||
|
||||
### CalendarDeleteContent
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "delete",
|
||||
"title": "string",
|
||||
"action": "deleted"
|
||||
}
|
||||
```
|
||||
|
||||
### FriendshipContent
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "request",
|
||||
"message": "string | null"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 数据结构
|
||||
|
||||
### InboxMessageResponse
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"recipient_id": "uuid",
|
||||
"sender_id": "uuid | null",
|
||||
"message_type": "InboxMessageType",
|
||||
"schedule_item_id": "uuid | null",
|
||||
"friendship_id": "uuid | null",
|
||||
"content": "CalendarInviteContent | CalendarUpdateContent | CalendarDeleteContent | FriendshipContent | null",
|
||||
"is_read": "boolean",
|
||||
"status": "InboxMessageStatus",
|
||||
"created_at": "datetime"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1) GET `/`
|
||||
|
||||
获取消息列表。
|
||||
|
||||
### Query Parameters
|
||||
|
||||
- `is_read`: boolean | null(可选,筛选已读/未读状态)
|
||||
|
||||
### Response
|
||||
|
||||
`InboxMessageResponse` 对象数组。
|
||||
|
||||
---
|
||||
|
||||
## 2) PATCH `/{message_id}/read`
|
||||
|
||||
标记指定消息为已读。
|
||||
|
||||
### Path Parameters
|
||||
|
||||
- `message_id`: 消息 UUID
|
||||
|
||||
### Response
|
||||
|
||||
`InboxMessageResponse` 对象。
|
||||
@@ -0,0 +1,322 @@
|
||||
# Memory 协议
|
||||
|
||||
本文档定义记忆系统的数据模型、API 协议以及 Agent 中的使用方式。
|
||||
|
||||
---
|
||||
|
||||
## 概述
|
||||
|
||||
记忆系统为每个用户维护两类持久化记忆:
|
||||
|
||||
| 类型 | 用途 | 使用者 |
|
||||
|------|------|--------|
|
||||
| `user` | 个人偏好、习惯、人际关系、常去地点等 | Router Agent |
|
||||
| `work` | 工作项目、团队成员、工作习惯、里程碑等 | Worker Agent |
|
||||
|
||||
每个用户拥有**恰好两条**记忆记录(user_type 和 work_type),存储为 JSONB。
|
||||
|
||||
注册初始化约定:
|
||||
- 用户首次注册成功后,后台会自动保证 `user` 与 `work` 两条 memory 记录存在。
|
||||
- `content` 初始值分别使用 `UserMemoryContent()` 与 `WorkProfileContent()` 的默认结构。
|
||||
|
||||
---
|
||||
|
||||
## 数据模型
|
||||
|
||||
### MemoryType
|
||||
|
||||
```json
|
||||
{
|
||||
"USER": "user",
|
||||
"WORK": "work"
|
||||
}
|
||||
```
|
||||
|
||||
### MemoryStatus
|
||||
|
||||
```json
|
||||
{
|
||||
"ACTIVE": "active",
|
||||
"DISABLED": "disabled"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Content 数据结构
|
||||
|
||||
### UserMemoryContent
|
||||
|
||||
```json
|
||||
{
|
||||
"occupation": "string | null",
|
||||
"timezone": "string | null",
|
||||
"primary_language": "string | null",
|
||||
"people": [
|
||||
{
|
||||
"name": "string",
|
||||
"relationship": "string | null",
|
||||
"role": "string | null",
|
||||
"preferred_contact_channel": "string | null",
|
||||
"notes": "string | null",
|
||||
"meta": {
|
||||
"source": "memory_source | null",
|
||||
"confidence": 0.0-1.0,
|
||||
"last_updated_at": "datetime | null"
|
||||
}
|
||||
}
|
||||
],
|
||||
"places": [
|
||||
{
|
||||
"name": "string",
|
||||
"category": "string | null",
|
||||
"address": "string | null",
|
||||
"timezone": "string | null",
|
||||
"commute_minutes": "int | null",
|
||||
"preference": "like | neutral | avoid | null",
|
||||
"notes": "string | null",
|
||||
"meta": { ... }
|
||||
}
|
||||
],
|
||||
"preferences": {
|
||||
"communication_style": "string | null",
|
||||
"language_preference": ["string"],
|
||||
"location_preference": "string | null",
|
||||
"work_lifestyle": "string | null",
|
||||
"notification_preference": ["string"]
|
||||
},
|
||||
"scheduling_preferences": {
|
||||
"productive_windows": [{ "weekdays": [], "start": "HH:MM", "end": "HH:MM" }],
|
||||
"preferred_meeting_windows": [],
|
||||
"no_meeting_windows": [],
|
||||
"deep_work_windows": [],
|
||||
"preferred_meeting_duration_minutes": [30, 60],
|
||||
"meeting_buffer_minutes": "int | null",
|
||||
"max_meetings_per_day": "int | null",
|
||||
"notes": "string | null"
|
||||
},
|
||||
"interests": ["string"],
|
||||
"avoid_topics": ["string"],
|
||||
"custom_rules": ["string"],
|
||||
"recurring_routines": [
|
||||
{
|
||||
"name": "string",
|
||||
"description": "string | null",
|
||||
"cadence": "string | null",
|
||||
"time_windows": [],
|
||||
"importance": "string | null",
|
||||
"meta": { ... }
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### WorkProfileContent
|
||||
|
||||
```json
|
||||
{
|
||||
"occupation": "string | null",
|
||||
"expertise": ["string"],
|
||||
"preferred_tools": ["string"],
|
||||
"current_projects": [
|
||||
{
|
||||
"name": "string",
|
||||
"description": "string | null",
|
||||
"status": "planned | active | paused | completed | null",
|
||||
"priority": "string | null",
|
||||
"deadline": "date | null",
|
||||
"collaborators": ["string"],
|
||||
"key_milestones": [
|
||||
{
|
||||
"name": "string",
|
||||
"due_date": "date | null",
|
||||
"status": "string | null",
|
||||
"notes": "string | null"
|
||||
}
|
||||
],
|
||||
"notes": "string | null",
|
||||
"meta": { ... }
|
||||
}
|
||||
],
|
||||
"work_habits": {
|
||||
"available_hours": [{ "weekdays": [], "start": "HH:MM", "end": "HH:MM" }],
|
||||
"deep_work_blocks": [],
|
||||
"preferred_meeting_windows": [],
|
||||
"no_meeting_windows": [],
|
||||
"preferred_meeting_duration_minutes": [30, 60],
|
||||
"notification_channel": "string | null",
|
||||
"notes": "string | null"
|
||||
},
|
||||
"team_members": [
|
||||
{
|
||||
"name": "string",
|
||||
"role": "string | null",
|
||||
"relationship": "string | null",
|
||||
"preferred_contact_channel": "string | null",
|
||||
"notes": "string | null",
|
||||
"meta": { ... }
|
||||
}
|
||||
],
|
||||
"team_context": "string | null",
|
||||
"work_rules": ["string"]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 数据库存储
|
||||
|
||||
### memories 表
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `id` | UUID | 主键 |
|
||||
| `owner_id` | UUID | 所有者用户 ID |
|
||||
| `agent_id` | UUID | 关联 Agent ID(可选) |
|
||||
| `memory_type` | VARCHAR(20) | 记忆类型枚举(当前含 `user`、`work`,可扩展) |
|
||||
| `content` | JSONB | UserMemoryContent 或 WorkProfileContent |
|
||||
| `status` | VARCHAR(20) | ACTIVE / DISABLED |
|
||||
| `created_at` | TIMESTAMP | 创建时间 |
|
||||
| `updated_at` | TIMESTAMP | 更新时间 |
|
||||
|
||||
说明:
|
||||
- `source` 列已移除,不再作为行级来源标记。
|
||||
- 来源信息如果需要保留,使用 `content` 内各条目的 `meta.source`(字段级来源)。
|
||||
- 唯一性约束:同一 `owner_id` 下 `memory_type` 不能重复(`UNIQUE(owner_id, memory_type)`)。
|
||||
|
||||
---
|
||||
|
||||
## API 端点
|
||||
|
||||
Base URL: `/api/v1/memories`
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| GET | `/` | 获取用户所有记忆 |
|
||||
| GET | `/user` | 获取用户记忆 (UserMemoryContent) |
|
||||
| GET | `/work` | 获取工作记忆 (WorkProfileContent) |
|
||||
| PUT | `/user` | 全量更新用户记忆 |
|
||||
| PUT | `/work` | 全量更新工作记忆 |
|
||||
| PATCH | `/user` | 部分更新用户记忆 |
|
||||
| PATCH | `/work` | 部分更新工作记忆 |
|
||||
|
||||
### GET `/`
|
||||
|
||||
获取用户所有记忆。
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"user_memory": { ...UserMemoryContent },
|
||||
"work_memory": { ...WorkProfileContent }
|
||||
}
|
||||
```
|
||||
|
||||
### GET `/user`
|
||||
|
||||
**Response:** `UserMemoryContent | null`
|
||||
|
||||
### GET `/work`
|
||||
|
||||
**Response:** `WorkProfileContent | null`
|
||||
|
||||
### PUT `/user`
|
||||
|
||||
全量更新用户记忆。
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"content": { ...UserMemoryContent }
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `UserMemoryContent`
|
||||
|
||||
### PATCH `/user`
|
||||
|
||||
部分更新用户记忆。
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"content": { ...Partial UserMemoryContent }
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `UserMemoryContent`
|
||||
|
||||
---
|
||||
|
||||
## Agent 中的使用
|
||||
|
||||
### 职责分离
|
||||
|
||||
| Agent | Memory 类型 | Prompt 标记 |
|
||||
|-------|-------------|-------------|
|
||||
| Router | UserMemoryContent | `<!-- USER_MEMORY_START -->...<!-- USER_MEMORY_END -->` |
|
||||
| Worker | WorkProfileContent | `<!-- WORK_MEMORY_START -->...<!-- WORK_MEMORY_END -->` |
|
||||
|
||||
### Prompt 组装流程
|
||||
|
||||
```
|
||||
MemoriesService.get_all_memories()
|
||||
│
|
||||
├── user_memory: UserMemoryContent | null
|
||||
│ └── build_user_memory_prompt(user_memory)
|
||||
│ └── 注入 Router system prompt
|
||||
│
|
||||
└── work_memory: WorkProfileContent | null
|
||||
└── build_work_memory_prompt(work_memory)
|
||||
└── 注入 Worker system prompt
|
||||
```
|
||||
|
||||
### Router Agent
|
||||
|
||||
Router 负责用户意图识别和任务规划,需要根据用户偏好、习惯、人际关系来更精确地理解用户需求。
|
||||
|
||||
```python
|
||||
build_system_prompt(
|
||||
agent_type=AgentType.ROUTER,
|
||||
user_memory=user_memory, # 注入用户个人记忆
|
||||
...
|
||||
)
|
||||
```
|
||||
|
||||
### Worker Agent
|
||||
|
||||
Worker 负责执行具体任务,需要根据工作项目、团队成员、工作习惯来更好地完成任务。
|
||||
|
||||
```python
|
||||
build_system_prompt(
|
||||
agent_type=AgentType.WORKER,
|
||||
work_memory=work_memory, # 注入工作记忆
|
||||
...
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 实现文件
|
||||
|
||||
### Backend
|
||||
|
||||
| 文件 | 职责 |
|
||||
|------|------|
|
||||
| `src/schemas/memories/memory_content.py` | UserMemoryContent、WorkProfileContent 模型 |
|
||||
| `src/schemas/memories/__init__.py` | MemoryType、MemoryStatus 枚举 |
|
||||
| `src/models/memories.py` | SQLAlchemy ORM 模型 |
|
||||
| `src/v1/memories/router.py` | API 端点 |
|
||||
| `src/v1/memories/service.py` | 业务逻辑层 |
|
||||
| `src/v1/memories/repository.py` | 数据访问层 |
|
||||
| `src/core/agentscope/prompts/memory_prompt.py` | Agent prompt 构建 |
|
||||
|
||||
### Flutter
|
||||
|
||||
| 文件 | 职责 |
|
||||
|------|------|
|
||||
| `apps/lib/features/settings/data/services/memory_service.dart` | Memory API 服务 |
|
||||
| `apps/lib/features/settings/ui/screens/memory_screen.dart` | Memory 界面 |
|
||||
@@ -0,0 +1,119 @@
|
||||
# Users 协议
|
||||
|
||||
本文档定义 `/api/v1/users` 的用户管理协议。
|
||||
|
||||
Base URL: `/api/v1/users`
|
||||
|
||||
---
|
||||
|
||||
## 端点
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|---|---|---|
|
||||
| GET | `/me` | 获取当前用户信息 |
|
||||
| PATCH | `/me` | 更新当前用户信息 |
|
||||
| POST | `/search` | 搜索用户 |
|
||||
| GET | `/{user_id}` | 获取指定用户信息 |
|
||||
|
||||
---
|
||||
|
||||
## UserContext 数据结构
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"username": "string",
|
||||
"phone": "+14155552671 | null",
|
||||
"avatar_url": "https://... | null",
|
||||
"bio": "string | null",
|
||||
"settings": {
|
||||
"version": 1,
|
||||
"preferences": {
|
||||
"interface_language": "zh-CN",
|
||||
"ai_language": "zh-CN",
|
||||
"timezone": "Asia/Shanghai",
|
||||
"country": "CN"
|
||||
},
|
||||
"privacy": {},
|
||||
"notification": {}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
字段说明:
|
||||
- `id`: 用户唯一标识符 (UUID)
|
||||
- `username`: 用户名,3-30 字符
|
||||
- `phone`: E.164 格式手机号,可为 null
|
||||
- `avatar_url`: 头像 URL,可为 null
|
||||
- `bio`: 个人简介,最大 200 字符,可为 null
|
||||
- `settings`: 用户偏好设置
|
||||
|
||||
---
|
||||
|
||||
## 1) GET `/me`
|
||||
|
||||
获取当前登录用户信息。
|
||||
|
||||
### Request
|
||||
|
||||
无请求体。
|
||||
|
||||
### Response
|
||||
|
||||
`UserContext` 对象。
|
||||
|
||||
---
|
||||
|
||||
## 2) PATCH `/me`
|
||||
|
||||
更新当前用户信息(部分更新)。
|
||||
|
||||
### Request
|
||||
|
||||
```json
|
||||
{
|
||||
"username": "newname",
|
||||
"avatar_url": "https://example.com/avatar.jpg",
|
||||
"bio": "Hello world"
|
||||
}
|
||||
```
|
||||
|
||||
至少提供一个字段。
|
||||
|
||||
### Response
|
||||
|
||||
更新后的 `UserContext` 对象。
|
||||
|
||||
---
|
||||
|
||||
## 3) POST `/search`
|
||||
|
||||
按用户名或手机号搜索用户。
|
||||
|
||||
### Request
|
||||
|
||||
```json
|
||||
{
|
||||
"query": "john"
|
||||
}
|
||||
```
|
||||
|
||||
`query` 最小 1 字符,最大 100 字符。
|
||||
|
||||
### Response
|
||||
|
||||
`UserContext` 对象数组。
|
||||
|
||||
---
|
||||
|
||||
## 4) GET `/{user_id}`
|
||||
|
||||
获取指定用户信息。
|
||||
|
||||
### Path Parameters
|
||||
|
||||
- `user_id`: 用户 UUID
|
||||
|
||||
### Response
|
||||
|
||||
`UserContext` 对象。
|
||||
Reference in New Issue
Block a user