Files
agent-frontend-web/docs/superpowers/specs/2026-08-04-list-chat-sessions-agent-id-design.md
T
2026-08-07 13:56:29 +08:00

119 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 智能体广场跳转后 listChatSessions 传参 agentId
- **日期**: 2026-08-04
- **状态**: 已批准,待实施
## 背景
从智能体广场(`marketplace.vue`)点击智能体进入前端聊天页面(`Frontend/index.vue`)时,路由携带 `query.agentId`。当前页面已读取该值并在 WebSocket 发送消息时回传,但会话侧边栏调用 `listChatSessions()` 获取会话列表时未携带 `agentId`,导致列表不能按智能体过滤。
## 目标
从智能体广场跳转进入前端页面后,会话侧边栏调用 `listChatSessions()` 时附带 `agentId` 作为查询参数,后端据此只返回该智能体下的会话。其他入口(无 `agentId`)行为不变。
## 非目标
- 不修改 `marketplace.vue` 现有跳转逻辑
- 不修改 WebSocket 消息体(`agentId` 已附带,不在范围内)
- 不修改其他 list API`listLlmModels``listAgentProjects` 等)
- 不引入状态管理库(Pinia 等)
## 设计
### 1. API 层 `src/api/frontend/index.js`
`listChatSessions` 改为接收可选 `agentId`,作为 GET 查询参数:
```js
export function listChatSessions(agentId) {
return chatRequest({
url: '/llm/chatSession/list',
method: 'get',
params: agentId ? { agentId: Number(agentId) } : {}
})
}
```
- 不传或传 `null`/`undefined`/空字符串时,`params` 为空对象,行为与现状完全一致
- `agentId` 通过 `Number()` 转为数字,与 WebSocket 发送处的转换(`messageData.agentId = Number(agentId.value)`)保持一致
### 2. 父组件 `src/views/frontend/index.vue`
模板中已存在 `<ConversationSidebar ref="conversationSidebarRef" ... />`,新增 `:agent-id` 绑定:
```vue
<ConversationSidebar
ref="conversationSidebarRef"
:agent-id="agentId"
@select="handleConversationSelect"
@new-session="handleNewSession"
@ready="switchingConversation = false"
/>
```
`agentId` ref(第 162 行)已存在,由 `route.query.agentId` 赋值,无需新增状态。
### 3. 子组件 `src/views/frontend/components/ConversationSidebar.vue`
- 新增 prop 定义:
```js
const props = defineProps({
agentId: { type: [String, Number], default: null }
})
```
- 第 131 行 `fetchSessions`
```js
const res = await listChatSessions(props.agentId)
```
- 第 207 行 `refreshQuiet`
```js
const res = await listChatSessions(props.agentId)
```
由于 `props.agentId` 是响应式的,直接读取即可拿到最新值,无需 `watch`。
## 数据流
```
marketplace.vue (handleAgentClick)
└─ router.push({ name: 'Frontend', query: { agentId, name } })
└─ index.vue (onMounted: agentId.value = route.query.agentId)
└─ <ConversationSidebar :agent-id="agentId" />
└─ fetchSessions() / refreshQuiet()
└─ listChatSessions(props.agentId)
└─ GET /llm/chatSession/list?agentId=<id>
```
## 边界与错误处理
| 输入 | 行为 |
|---|---|
| `agentId` 未提供 | 不带 `agentId` 参数,返回全部会话 |
| `agentId = ''` 或 `null` | 同上 |
| `agentId = '123'`(字符串) | `Number('123') = 123`,作为查询参数 |
| `agentId = 0` 或无效数字 | 后端按 `0` 处理,与现状一致 |
不引入额外的错误处理;网络错误沿用现有的 `console.error` 与 UI 行为。
## 验证
1. **从智能体广场跳转**
- 进入智能体 A → 侧边栏只显示智能体 A 的会话
- 返回广场,进入智能体 B → 侧边栏只显示智能体 B 的会话
2. **直接进入 `/frontend`**(无 query):侧边栏显示全部会话,行为与现状一致
3. **新建会话后**:通过 `refreshQuiet` 刷新时仍按当前 `agentId` 过滤
4. **删除/重命名会话**:调用 `deleteChatSession`/`renameChatSession`,刷新后列表仍正确过滤
## 涉及文件
| 文件 | 变更类型 |
|---|---|
| `src/api/frontend/index.js` | 修改 `listChatSessions` 签名 |
| `src/views/frontend/index.vue` | 模板新增 `:agent-id` 绑定 |
| `src/views/frontend/components/ConversationSidebar.vue` | 新增 prop;两处 `listChatSessions` 调用透传参数 |
## 实施依赖
无新增依赖。沿用现有 axios、`vue-router`、`@element-plus`。