代码提交
This commit is contained in:
1 parent
b101ee7fc9
commit
1938c80061
42 files changed
+5552
-278
No files matched your search
@@ -0,0 +1,47 @@
|
||||
# 并行多智能体面板 · 测试用例总览
|
||||
|
||||
本目录是 `parallel-agents-vue` 的**手工测试用例**(Markdown)。覆盖:并行调用与流式、文件写入禁用、
|
||||
保存与回显、重新分析、免密登录与鉴权、嵌入与深色样式。
|
||||
|
||||
## 用例清单
|
||||
|
||||
| 文件 | 主题 |
|
||||
| -------------------------------------------- | ------------------------------------- |
|
||||
| [01-并行调用与流式.md](./01-并行调用与流式.md) | 并行扇出、流式输出、步骤条、席位状态条、禁写文件 |
|
||||
| [02-保存与回显.md](./02-保存与回显.md) | 保存聊天记录、历史列表、加载回显、更新保存 |
|
||||
| [03-重新分析.md](./03-重新分析.md) | 重新分析(覆盖重跑)、停止、空输入校验 |
|
||||
| [04-免密登录与鉴权.md](./04-免密登录与鉴权.md) | username 免密登录、token 优先级、401 重登、口令门 |
|
||||
| [05-嵌入与深色样式.md](./05-嵌入与深色样式.md) | 配置文件接口地址、抽屉/弹窗嵌入、深色自适应、不污染宿主 |
|
||||
| [06-可用智能体清单.md](./06-可用智能体清单.md) | **测试用真实 agent_id 清单(可直接复制粘贴)** + 示例任务 |
|
||||
| [07-使用说明.md](./07-使用说明.md) | **在其它 Vue 项目中引入哪些组件、如何使用**(props/事件/嵌入) |
|
||||
|
||||
## 测试环境
|
||||
|
||||
| 组件 | 地址 / 命令 |
|
||||
| --------------- | ------------------------------------------------------ |
|
||||
| DeerFlow 后端 | `http://localhost:8001`(`make dev`,需含本功能的新路由)|
|
||||
| Vue dev demo | `http://localhost:5183`(`pnpm dev`) |
|
||||
| 接口地址配置 | `src/config.ts` 的 `DEFAULT_BASE_URL` |
|
||||
|
||||
## 前置准备(所有用例通用)
|
||||
|
||||
1. 后端已启动,且包含本功能:
|
||||
- `POST /api/parallel-agents/run/stream`(并行扇出,合并 SSE)
|
||||
- `GET/POST/PUT/DELETE /api/parallel-agent-tasks`(任务保存/回显)
|
||||
- `POST /api/v1/auth/login/username`(免密登录,公共)
|
||||
- 数据表 `parallel_agent_tasks` 已建(`alembic upgrade head` 或 `create_all`)。
|
||||
2. 至少准备 **2 个真实存在的 agent_id**(必须是后端注册过的真实 id,不能只写名字)。
|
||||
本环境可直接用:`roundtable-solution-design`(方案设计)、`roundtable-risk-review`(风险审查)等
|
||||
—— 完整可复制清单见 [06-可用智能体清单.md](./06-可用智能体清单.md)。
|
||||
3. 打开 dev demo `http://localhost:5183`,填:
|
||||
- 后端 baseUrl:`http://localhost:8001`
|
||||
- 用户名:`demo`(免密自动登录)
|
||||
- 智能体:每行 `agent_id, 显示名`
|
||||
点「打开面板(弹窗内)」。
|
||||
|
||||
## 用例字段约定
|
||||
|
||||
- **用例ID**:`PA-<模块>-<序号>`
|
||||
- **优先级**:P0(核心,必过)/ P1(重要)/ P2(边界)
|
||||
- **前置条件 → 操作步骤 → 预期结果**:逐条核对,全部命中才算通过。
|
||||
- **结果记录**:建议在「实际结果 / 通过?」列里回填。
|
||||
@@ -0,0 +1,105 @@
|
||||
# 测试用例 · 并行调用与流式
|
||||
|
||||
覆盖:并行扇出多个智能体、流式逐字输出、步骤条(工具调用)、点头像切换显示(单选)、席位状态条、
|
||||
运行期间**禁止写文件**。
|
||||
|
||||
---
|
||||
|
||||
## PA-RUN-01 · 并行调用多个智能体(P0)
|
||||
|
||||
**前置条件**
|
||||
- 面板已打开,填入任务名「竞品调研」、简介「对比 A、B 两款产品的核心功能与定价」。
|
||||
- 传入 2 个智能体(情报收集、风险审查)。
|
||||
|
||||
**操作步骤**
|
||||
1. 点击「开始分析」。
|
||||
|
||||
**预期结果**
|
||||
- 顶部出现**席位状态条**,显示「并行 2 席」,两个席位头像角标先后转为「进行中」(转圈)。
|
||||
- 两个智能体**同时**开始执行(并行,而非一个跑完再跑下一个)——可在状态条上看到都在「进行中」。
|
||||
- 会话区每次显示**一个**席位的消息列表(默认第 1 个),点头像可切换查看另一个(见 PA-RUN-06)。
|
||||
- 气泡头部显示:头像、智能体名、状态徽标「并行执行中」、时间。
|
||||
|
||||
---
|
||||
|
||||
## PA-RUN-02 · 流式逐字输出 + 光标(P0)
|
||||
|
||||
**前置条件**:PA-RUN-01 正在运行中。
|
||||
|
||||
**操作步骤**
|
||||
1. 观察当前显示席位的气泡正文(点头像可切换看其它席位)。
|
||||
|
||||
**预期结果**
|
||||
- 正文**逐步增量**出现(流式),不是一次性整段刷出。
|
||||
- 正在输出的气泡末尾有**闪烁光标**(`.pa-cursor`)。
|
||||
- 内容还没来时,显示 loading 占位(转圈 + 跳动圆点 + 「并行执行中」文案)。
|
||||
- Markdown 能正确渲染(标题/列表/代码块/表格按 `.pa-md` 样式)。
|
||||
|
||||
---
|
||||
|
||||
## PA-RUN-03 · 步骤条(思维链 / 工具调用)(P1)
|
||||
|
||||
**前置条件**:智能体会调用工具(如检索类技能)。
|
||||
|
||||
**操作步骤**
|
||||
1. 运行一轮,观察气泡顶部的「执行步骤」折叠卡。
|
||||
|
||||
**预期结果**
|
||||
- 出现「执行步骤(N)」折叠卡(`MessageStepsCard`),点击可展开/收起。
|
||||
- 每条步骤显示:工具标签(如「调用工具 xxx」)、参数摘要(如有 `path` 优先显示)、时间。
|
||||
- 同一工具调用**不重复**出条目(按 key 去重)。
|
||||
- 若智能体本轮不调工具,则不出现步骤卡(属正常)。
|
||||
|
||||
---
|
||||
|
||||
## PA-RUN-04 · 席位状态流转(P1)
|
||||
|
||||
**操作步骤**
|
||||
1. 运行一轮,全程观察席位状态条各头像角标。
|
||||
|
||||
**预期结果**
|
||||
- 角标状态依次:灰(pending)→ 蓝色转圈(running)→ 绿色对勾(done)。
|
||||
- 某智能体失败时其角标变**红色叉**(error),且对应气泡显示「该智能体执行出错:…」、状态徽标「出错」。
|
||||
- 单个智能体失败**不影响**其它智能体继续完成(互不拖累)。
|
||||
- 全部结束后,运行按钮从「停止」恢复为「重新分析」。
|
||||
|
||||
---
|
||||
|
||||
## PA-RUN-05 · 运行期间禁止写文件(P0)
|
||||
|
||||
**目的**:核对后端 `seat_parallel` 策略生效——并行席位被禁用 `write_file` / `str_replace` / `bash` 等。
|
||||
|
||||
**操作步骤**
|
||||
1. 简介里**故意要求写文件**,例如:「请把结果保存成一个 .md 文件」。
|
||||
2. 点击「开始分析」,等待完成。
|
||||
|
||||
**预期结果**
|
||||
- 智能体**不会**真正落地文件,产出**直接呈现在气泡正文**里。
|
||||
- 步骤条里**不出现** `write_file` / `bash` / `str_replace` 工具调用(被策略排除)。
|
||||
- 可旁证:后端日志中该席位 `role=seat_parallel`。
|
||||
|
||||
---
|
||||
|
||||
## PA-RUN-06 · 点头像切换显示(单选)(P1)
|
||||
|
||||
**前置条件**:传入 ≥2 个智能体并运行。
|
||||
|
||||
**操作步骤**
|
||||
1. 点击席位状态条上的某个头像。
|
||||
|
||||
**预期结果**
|
||||
- 主区**切换为只显示**该智能体的消息列表(**单选**,每次显示一个)。
|
||||
- 被选中的头像高亮(外发光描边);再点别的头像即切到那个。
|
||||
- 切换不影响后台并行执行:未显示的智能体仍在跑/已完成,其增量在切回时能看到。
|
||||
- 默认显示第 1 个席位。
|
||||
|
||||
---
|
||||
|
||||
## PA-RUN-07 · 后端不可达 / 智能体 id 非法(P2)
|
||||
|
||||
**操作步骤**
|
||||
1. 把 baseUrl 改成一个打不通的地址,或传入不存在的 agent_id,点「开始分析」。
|
||||
|
||||
**预期结果**
|
||||
- 顶部出现红色错误提示(请求失败信息),不白屏、不卡死。
|
||||
- 非法 agent_id 时,对应席位以 error 角标 + 出错气泡呈现,其它正常席位不受影响。
|
||||
@@ -0,0 +1,94 @@
|
||||
# 测试用例 · 保存与回显
|
||||
|
||||
覆盖:保存聊天记录(新建/更新)、历史列表、加载已存任务并回显、`taskId` 自动加载、跨刷新持久化。
|
||||
|
||||
---
|
||||
|
||||
## PA-SAVE-01 · 首次保存(新建)(P0)
|
||||
|
||||
**前置条件**:已跑完一轮、会话区有结果。任务名「竞品调研」。
|
||||
|
||||
**操作步骤**
|
||||
1. 点击「保存」。
|
||||
|
||||
**预期结果**
|
||||
- 按钮短暂显示「保存中…」,成功后变为「更新保存」(说明已绑定 taskId)。
|
||||
- 触发 `@saved` 事件,回传 `SavedTask`(含 id、title、agents、messages)。
|
||||
- 「历史」下拉里出现这条记录(标题 + 更新时间)。
|
||||
- 后端 `parallel_agent_tasks` 表新增一行(owner = 当前登录用户)。
|
||||
|
||||
---
|
||||
|
||||
## PA-SAVE-02 · 再次保存(更新覆盖)(P0)
|
||||
|
||||
**前置条件**:PA-SAVE-01 已保存、当前仍是同一任务。
|
||||
|
||||
**操作步骤**
|
||||
1. 修改任务名 / 简介,或重新分析得到新结果。
|
||||
2. 点击「更新保存」。
|
||||
|
||||
**预期结果**
|
||||
- **不新增**记录,而是更新原 taskId 那条(title / brief / agents / messages 被覆盖为最新)。
|
||||
- 历史列表里该条的更新时间刷新、排到最前。
|
||||
|
||||
---
|
||||
|
||||
## PA-SAVE-03 · 历史加载并回显(P0)
|
||||
|
||||
**前置条件**:历史里至少有 1 条已保存任务。
|
||||
|
||||
**操作步骤**
|
||||
1. 点击「历史 ▾」展开列表。
|
||||
2. 选择一条历史任务。
|
||||
|
||||
**预期结果**
|
||||
- 任务名、简介**回填**为该任务保存时的值。
|
||||
- 会话区**完整回显**保存时的消息列表(各智能体气泡、正文、步骤条),且**均为非流式终态**(无光标、无 loading)。
|
||||
- 席位状态条据消息重建:正常席位显示 done(绿勾),出错的显示 error(红叉)。
|
||||
- 当前 taskId 切换为该任务(再点「保存」是「更新保存」该条)。
|
||||
|
||||
---
|
||||
|
||||
## PA-SAVE-04 · taskId 进入即自动回显(P1)
|
||||
|
||||
**操作步骤**
|
||||
1. 以 `:task-id="<已存在任务id>"` 方式挂载面板(嵌入场景)。
|
||||
|
||||
**预期结果**
|
||||
- 面板挂载后**自动加载**该任务并回显(等同于 PA-SAVE-03 的结果),无需手动点历史。
|
||||
- `@update:taskId` 随之触发。
|
||||
|
||||
---
|
||||
|
||||
## PA-SAVE-05 · 跨刷新持久化(P1)
|
||||
|
||||
**操作步骤**
|
||||
1. 保存一条任务后,刷新浏览器(或重开宿主页面)。
|
||||
2. 用相同用户名进入,打开历史。
|
||||
|
||||
**预期结果**
|
||||
- 历史里仍能看到之前保存的任务(数据存在后端、按用户隔离,非浏览器 localStorage)。
|
||||
- 加载后能正常回显。
|
||||
|
||||
---
|
||||
|
||||
## PA-SAVE-06 · 无结果时禁止保存(P2)
|
||||
|
||||
**操作步骤**
|
||||
1. 新开面板、尚未运行任何分析。
|
||||
|
||||
**预期结果**
|
||||
- 「保存」按钮**禁用**(无可保存内容)。
|
||||
- 运行中也不应因保存导致状态错乱(保存按钮在有结果后才可用)。
|
||||
|
||||
---
|
||||
|
||||
## PA-SAVE-07 · 用户隔离(P1)
|
||||
|
||||
**操作步骤**
|
||||
1. 用户名 A 保存一条任务。
|
||||
2. 切换用户名为 B(重新进入面板),打开历史。
|
||||
|
||||
**预期结果**
|
||||
- B 的历史里**看不到** A 的任务。
|
||||
- B 直接用 A 的 taskId 加载应失败(404 / 无内容),不报错崩溃。
|
||||
@@ -0,0 +1,77 @@
|
||||
# 测试用例 · 重新分析与运行控制
|
||||
|
||||
覆盖:重新分析(覆盖重跑)、运行中停止、空输入校验、运行态按钮切换。
|
||||
|
||||
---
|
||||
|
||||
## PA-RE-01 · 重新分析(覆盖重跑)(P0)
|
||||
|
||||
**前置条件**:已跑完一轮、会话区有结果(按钮显示「重新分析」)。
|
||||
|
||||
**操作步骤**
|
||||
1. (可选)修改任务名 / 简介。
|
||||
2. 点击「重新分析」。
|
||||
|
||||
**预期结果**
|
||||
- **清空**上一轮的所有气泡与席位状态,按当前输入**重新并行**调用各智能体。
|
||||
- 不会和上一轮结果混在一起(旧消息被替换,不是追加)。
|
||||
- 重跑过程与首跑一致(流式、单列消息 + 点头像切换、步骤条、席位状态流转)。
|
||||
|
||||
---
|
||||
|
||||
## PA-RE-02 · 运行中按钮为「停止」(P1)
|
||||
|
||||
**操作步骤**
|
||||
1. 开始分析,运行未结束时观察操作区。
|
||||
|
||||
**预期结果**
|
||||
- 运行期间,主按钮显示「停止」(不再是「开始/重新分析」)。
|
||||
- 「保存」按钮在运行中可点(保存当前已产出的内容)或按实现禁用——以不报错为准。
|
||||
|
||||
---
|
||||
|
||||
## PA-RE-03 · 停止当前运行(P0)
|
||||
|
||||
**前置条件**:正在运行中。
|
||||
|
||||
**操作步骤**
|
||||
1. 点击「停止」。
|
||||
|
||||
**预期结果**
|
||||
- 进行中的请求被取消(AbortController),不再有新增量进来。
|
||||
- 仍在 streaming 的气泡被收尾为终态(去掉光标,徽标置「已完成」)。
|
||||
- 按钮恢复为「重新分析」,可立即再次发起。
|
||||
- 控制台不应出现未捕获的 AbortError 报错(已被吞掉)。
|
||||
|
||||
---
|
||||
|
||||
## PA-RE-04 · 空输入校验(P1)
|
||||
|
||||
**操作步骤**
|
||||
1. 任务名与简介**都留空**,点击「开始分析」。
|
||||
|
||||
**预期结果**
|
||||
- 按钮处于**禁用**态,点击无效(`canStart` 为假需任务名或简介至少其一 + 至少一个智能体)。
|
||||
- 只填任务名或只填简介,按钮可用。
|
||||
|
||||
---
|
||||
|
||||
## PA-RE-05 · 未传智能体(P2)
|
||||
|
||||
**操作步骤**
|
||||
1. `:agents="[]"`(空数组)挂载面板。
|
||||
|
||||
**预期结果**
|
||||
- 操作区显示提示「⚠️ 未传入任何智能体(agents 为空)」。
|
||||
- 「开始分析」禁用,不会发起空请求。
|
||||
|
||||
---
|
||||
|
||||
## PA-RE-06 · 连续多次重新分析(P2)
|
||||
|
||||
**操作步骤**
|
||||
1. 连续点击「重新分析」若干次(每次等上一轮结束或中途停止再点)。
|
||||
|
||||
**预期结果**
|
||||
- 每次都干净重置 + 重跑,无残留旧气泡、无席位状态错乱。
|
||||
- 不出现多份 SSE 叠加导致的内容串列 / 重复。
|
||||
@@ -0,0 +1,106 @@
|
||||
# 测试用例 · 免密登录与鉴权
|
||||
|
||||
覆盖:username 免密自动登录、token 优先级、token 缓存与 401 重登、口令门、CSRF 绕过。
|
||||
|
||||
> 背景:面板优先用宿主传入的 token;没有 token 时,用宿主传入的 **username** 走 DeerFlow 公共免密端点
|
||||
> `POST /api/v1/auth/login/username` 换取 `access_token`,以 `Authorization: Bearer` 发起后续请求
|
||||
> (带 Bearer 会绕过 CSRF)。token 解析优先级:`token` > `getToken` > 缓存 > `username` 登录。
|
||||
|
||||
---
|
||||
|
||||
## PA-AUTH-01 · username 免密自动登录(P0)
|
||||
|
||||
**前置条件**:后端 `auth_login.username_login.require_password = false`(默认)。
|
||||
|
||||
**操作步骤**
|
||||
1. 只传 `:username="demo"`(不传 token),打开面板。
|
||||
2. 开始分析 / 打开历史。
|
||||
|
||||
**预期结果**
|
||||
- 面板能正常拉历史、能发起并行流式——说明已用 username 换到 token 并附带在请求头。
|
||||
- 旁证(手工 curl):
|
||||
```bash
|
||||
curl -s -X POST -H "Content-Type: application/json" \
|
||||
-d '{"username":"demo"}' http://localhost:8001/api/v1/auth/login/username
|
||||
# → 返回 {"access_token":"...","token_type":"bearer",...}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## PA-AUTH-02 · token 优先级高于 username(P1)
|
||||
|
||||
**操作步骤**
|
||||
1. 同时传 `:token="<有效token>"` 和 `:username="demo"`。
|
||||
2. 触发请求(开始分析 / 历史)。
|
||||
|
||||
**预期结果**
|
||||
- 直接用传入的 `token`(不会再去调登录端点)。
|
||||
- `:get-token` 同理优先于 username(动态取 token)。
|
||||
|
||||
---
|
||||
|
||||
## PA-AUTH-03 · token 缓存(不重复登录)(P1)
|
||||
|
||||
**操作步骤**
|
||||
1. 只传 username,先后触发多次请求(拉历史 → 开始分析 → 保存)。
|
||||
|
||||
**预期结果**
|
||||
- 登录端点**只调用一次**(首个请求),后续请求复用缓存 token(按 `baseUrl::username` 缓存)。
|
||||
- 可在浏览器 Network 面板核对 `login/username` 只出现一次。
|
||||
|
||||
---
|
||||
|
||||
## PA-AUTH-04 · 401 自动重登重试(P1)
|
||||
|
||||
**前置条件**:能制造 token 失效(例如等待过期,或后端清理)。
|
||||
|
||||
**操作步骤**
|
||||
1. 用 username 登录并缓存 token 后,使其失效,再触发一次 CRUD 请求。
|
||||
|
||||
**预期结果**
|
||||
- 首次请求收到 401 → 面板**清缓存并用 username 重登一次**,再自动重试该请求。
|
||||
- 用户无感知(不需手动重新登录),请求最终成功。
|
||||
|
||||
---
|
||||
|
||||
## PA-AUTH-05 · 口令门(require_password=true)(P2)
|
||||
|
||||
**前置条件**:后端把 `auth_login.username_login.require_password` 设为 `true`、配置 `password`。
|
||||
|
||||
**操作步骤**
|
||||
1. 只传 username、不传 `loginPassword` → 触发请求。
|
||||
2. 再传上正确的 `:login-password="<口令>"` → 触发请求。
|
||||
|
||||
**预期结果**
|
||||
- 不传口令时:登录返回 401「口令错误」,面板顶部红色错误提示,不崩溃。
|
||||
- 传对口令时:登录成功,后续请求正常。
|
||||
|
||||
---
|
||||
|
||||
## PA-AUTH-06 · Bearer 绕过 CSRF(P1)
|
||||
|
||||
**目的**:核对带 Bearer 的 POST 不被 CSRF 拦截。
|
||||
|
||||
**操作步骤(手工 curl 旁证)**
|
||||
```bash
|
||||
TOKEN=... # 上面登录拿到的 access_token
|
||||
# 带 Bearer 的 POST:参数非法应为 400/422,而非 403(403=CSRF 拦截)
|
||||
curl -s -o /dev/null -w "%{http_code}\n" -X POST \
|
||||
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
|
||||
-d '{}' http://localhost:8001/api/parallel-agents/run/stream
|
||||
```
|
||||
|
||||
**预期结果**
|
||||
- 返回 **400/422**(业务参数校验),**不是 403**——证明 Bearer 已绕过 CSRF。
|
||||
- 不带任何鉴权时该 POST 返回 401/403(被拦截),属正常。
|
||||
|
||||
---
|
||||
|
||||
## PA-AUTH-07 · 未传 token 且未传 username(P2)
|
||||
|
||||
**操作步骤**
|
||||
1. 既不传 token / getToken,也不传 username,触发需要鉴权的请求。
|
||||
|
||||
**预期结果**
|
||||
- 请求因缺少鉴权失败(401/403),面板给出可读的错误提示(不白屏)。
|
||||
- 控制台/提示能反映「缺少 token 且未提供 username,无法登录」之类信息。
|
||||
@@ -0,0 +1,105 @@
|
||||
# 测试用例 · 嵌入与深色样式
|
||||
|
||||
覆盖:接口地址走配置文件、组件库构建产物、嵌入其它 Vue 项目、放进抽屉/弹窗自适应、深色成色、
|
||||
不污染宿主全局样式。
|
||||
|
||||
---
|
||||
|
||||
## PA-EMBED-01 · 接口地址走配置文件(P0)
|
||||
|
||||
**操作步骤**
|
||||
1. 不传 `:base-url`,只改 `src/config.ts` 的 `DEFAULT_BASE_URL` 为目标后端地址。
|
||||
2. 运行面板触发请求。
|
||||
|
||||
**预期结果**
|
||||
- 请求打到配置文件里的地址。
|
||||
- 传 `:base-url` prop 时**优先**用 prop(覆盖配置默认)。
|
||||
- dev 下设 `VITE_PA_BASE_URL` 环境变量也能覆盖默认。
|
||||
|
||||
---
|
||||
|
||||
## PA-EMBED-02 · 组件库构建产物(P0)
|
||||
|
||||
**操作步骤**
|
||||
```bash
|
||||
pnpm build:lib
|
||||
```
|
||||
|
||||
**预期结果**
|
||||
- `dist/` 产出:`parallel-agents-vue.js`(ESM)、`parallel-agents-vue.umd.cjs`(UMD)、`parallel-agents-vue.css`。
|
||||
- `vue` 被 external(不打进库,由宿主提供)。
|
||||
- 构建无报错、无「named + default exports」警告。
|
||||
|
||||
---
|
||||
|
||||
## PA-EMBED-03 · 嵌入其它 Vue 项目(P0)
|
||||
|
||||
**操作步骤**
|
||||
1. 在另一个 Vue3 项目里:
|
||||
```ts
|
||||
import { ParallelAgentsPanel } from "parallel-agents-vue";
|
||||
import "parallel-agents-vue/style.css";
|
||||
```
|
||||
2. 模板中放置:
|
||||
```vue
|
||||
<ParallelAgentsPanel :username="user" :agents="agents" />
|
||||
```
|
||||
|
||||
**预期结果**
|
||||
- 组件正常渲染、可交互(深色面板,与 demo 一致)。
|
||||
- 只需 `:username` + `:agents` 两个 prop 即可跑起来(接口地址走配置)。
|
||||
- 也支持 `app.use(ParallelAgentsVue)` 全局注册后用 `<ParallelAgentsPanel/>`。
|
||||
|
||||
---
|
||||
|
||||
## PA-EMBED-04 · 放进抽屉 / 弹窗自适应(P0)
|
||||
|
||||
**操作步骤**
|
||||
1. 把面板放进宿主的抽屉 / 对话框,外层给一个固定高度容器:
|
||||
```vue
|
||||
<YourDrawer v-model="open">
|
||||
<div style="height: 80vh"><ParallelAgentsPanel :username="user" :agents="agents" /></div>
|
||||
</YourDrawer>
|
||||
```
|
||||
2. 改变容器尺寸 / 视口大小。
|
||||
|
||||
**预期结果**
|
||||
- 面板**充满容器**(根元素 `h-full w-full flex flex-col min-h-0`),不溢出、不塌缩。
|
||||
- 会话区内部独立滚动,输入区与席位条固定不被挤掉。
|
||||
- 窄容器下消息列表正常显示、内部滚动,不溢出。
|
||||
|
||||
---
|
||||
|
||||
## PA-EMBED-05 · 深色成色自带、与宿主主题无关(P1)
|
||||
|
||||
**操作步骤**
|
||||
1. 分别在**浅色**宿主页和**深色**宿主页里嵌入面板。
|
||||
|
||||
**预期结果**
|
||||
- 面板始终是深蓝深色(自带 `--pa-*` token,作用域在 `.parallel-agents`),不随宿主明暗变化。
|
||||
- 文案、徽标、步骤卡、并行列底、滚动条等观感与圆桌 Step2 深色一致。
|
||||
- 传 `:dark="false"` 时按实现切换(如未实现浅色则保持深色,至少不报错)。
|
||||
|
||||
---
|
||||
|
||||
## PA-EMBED-06 · 不污染宿主全局样式(P0)
|
||||
|
||||
**目的**:核对**未引入 Tailwind preflight**(不重置宿主全局标签样式)。
|
||||
|
||||
**操作步骤**
|
||||
1. 在一个有自己样式的宿主页里嵌入面板(页面有 `h1/p/button/ul` 等默认样式)。
|
||||
|
||||
**预期结果**
|
||||
- 嵌入后,宿主页面**自身**的 `h1/p/button/列表/边距` 等样式**不被改变**(没有被 Tailwind 的 reset 抹平)。
|
||||
- 面板内部样式正常(不依赖宿主提供 Tailwind)。
|
||||
- 类名都在 `.parallel-agents` 作用域下,不与宿主类名冲突。
|
||||
|
||||
---
|
||||
|
||||
## PA-EMBED-07 · 多实例并存(P2)
|
||||
|
||||
**操作步骤**
|
||||
1. 同一页面放置 2 个面板实例(不同 agents / 不同 username)。
|
||||
|
||||
**预期结果**
|
||||
- 两个实例各自独立运行、各自保存/回显,互不串流、互不串 token 缓存(缓存按 `baseUrl::username` 区分)。
|
||||
@@ -0,0 +1,73 @@
|
||||
# 测试用 · 可用智能体清单(可直接复制粘贴)
|
||||
|
||||
测试时面板需要传入**真实存在的 `agent_id`**(后端真正拿去跑的标识,不能只写名字)。
|
||||
下面是当前后端里**可直接用于测试**的内置智能体(已排除 intent / recommender / coordinator 这些系统角色)。
|
||||
|
||||
> 注:`name` 只是显示用、可省略;`agent_id` 必须照抄。下列为本环境实测可用的内置智能体;
|
||||
> 你部署里的智能体可能不同,用文末方法自查。
|
||||
|
||||
## 可用智能体
|
||||
|
||||
| agent_id | 显示名 |
|
||||
| --------------------------- | -------- |
|
||||
| `roundtable-solution-design`| 方案设计 |
|
||||
| `roundtable-risk-review` | 风险审查 |
|
||||
| `roundtable-execution-plan` | 执行规划 |
|
||||
| `roundtable-report` | 方案总结 |
|
||||
| `demo-expert` | 演示专家 |
|
||||
|
||||
## A. 粘贴进 dev demo 页「智能体」输入框(每行 `agent_id, 显示名`)
|
||||
|
||||
推荐至少 2 个以便点头像切换查看不同智能体:
|
||||
|
||||
```
|
||||
roundtable-solution-design, 方案设计
|
||||
roundtable-risk-review, 风险审查
|
||||
```
|
||||
|
||||
想多看几列就多贴几行:
|
||||
|
||||
```
|
||||
roundtable-solution-design, 方案设计
|
||||
roundtable-risk-review, 风险审查
|
||||
roundtable-execution-plan, 执行规划
|
||||
```
|
||||
|
||||
## B. 粘贴进组件 `:agents` prop(嵌入场景)
|
||||
|
||||
```ts
|
||||
const agents = [
|
||||
{ agent_id: "roundtable-solution-design", name: "方案设计" },
|
||||
{ agent_id: "roundtable-risk-review", name: "风险审查" },
|
||||
{ agent_id: "roundtable-execution-plan", name: "执行规划" },
|
||||
];
|
||||
```
|
||||
|
||||
```vue
|
||||
<ParallelAgentsPanel :username="'demo'" :agents="agents" />
|
||||
```
|
||||
|
||||
## C. 配一个示例任务(直接粘贴到面板)
|
||||
|
||||
- **任务名称**:`新功能上线方案评估`
|
||||
- **任务简介**:
|
||||
```
|
||||
我们要给 App 上线「扫码点餐」功能。请从你的专业角度,评估方案可行性、列出关键风险、
|
||||
并给出落地步骤与里程碑。
|
||||
```
|
||||
|
||||
## 自查:列出你部署里所有可用的 agent_id
|
||||
|
||||
```bash
|
||||
# 1) 免密登录拿 token(用户名换成你的)
|
||||
TOKEN=$(curl -s -X POST -H "Content-Type: application/json" \
|
||||
-d '{"username":"demo"}' http://localhost:8001/api/v1/auth/login/username \
|
||||
| python -c "import sys,json;print(json.load(sys.stdin)['access_token'])")
|
||||
|
||||
# 2) 列出 agent_id <TAB> name
|
||||
curl -s -H "Authorization: Bearer $TOKEN" http://localhost:8001/api/agents -o agents.json
|
||||
python -c "import json,io;[print(a['id'],'\t',a['name']) for a in json.load(io.open('agents.json',encoding='utf-8')).get('agents',[])]"
|
||||
```
|
||||
|
||||
第一列 `id` 才是要填的 `agent_id`。挑你需要的智能体即可(避开 `roundtable-intent` /
|
||||
`roundtable-recommender` / `roundtable-coordinator*` 这些系统角色——它们不是用来当并行席位的)。
|
||||
@@ -0,0 +1,163 @@
|
||||
# 使用说明 · 在其它 Vue 项目中引入
|
||||
|
||||
本组件库只对外暴露**一个**组件 `ParallelAgentsPanel`(其余 `MessageBubble` / `MessageStepsCard` /
|
||||
`ParallelSeatStrip` / `Avatar` / `MarkdownContent` 都是它的内部子组件,**无需也不要单独引入**)。
|
||||
宿主只管把它放进自己的页面 / 抽屉 / 弹窗,并传几个 prop。
|
||||
|
||||
---
|
||||
|
||||
## 一、要引入的东西(就这两样)
|
||||
|
||||
1. **组件**:`ParallelAgentsPanel`
|
||||
2. **样式**:`parallel-agents-vue/style.css`(一次性引入即可,样式作用域全在 `.parallel-agents` 下)
|
||||
|
||||
> 依赖说明:`vue ^3.4`(宿主提供,库不打包 vue);`markdown-it` 已打进库内,无需宿主安装。
|
||||
|
||||
---
|
||||
|
||||
## 二、两种引入方式
|
||||
|
||||
### 方式 A:构建成库后按包引入(推荐)
|
||||
|
||||
1. 在本项目构建:
|
||||
```bash
|
||||
pnpm install
|
||||
pnpm build:lib # 产出 dist/parallel-agents-vue.{js,umd.cjs,css}
|
||||
```
|
||||
2. 宿主项目里安装(任选其一):
|
||||
- 把本目录作为本地依赖:`"parallel-agents-vue": "file:../parallel-agents-vue"`;
|
||||
- 或发到你们的私有 npm 后正常 `pnpm add parallel-agents-vue`。
|
||||
3. 代码里引入:
|
||||
```ts
|
||||
import { ParallelAgentsPanel } from "parallel-agents-vue";
|
||||
import "parallel-agents-vue/style.css";
|
||||
```
|
||||
|
||||
### 方式 B:直接拷贝源码(无需发包)
|
||||
|
||||
把本项目 `src/` 下这些拷进宿主项目(保持相对结构),按相对路径引入 `ParallelAgentsPanel.vue` +
|
||||
`styles/parallel-agents.css` 即可:
|
||||
|
||||
```
|
||||
src/
|
||||
components/ ParallelAgentsPanel.vue · MessageBubble.vue · MessageStepsCard.vue
|
||||
ParallelSeatStrip.vue · Avatar.vue · MarkdownContent.vue
|
||||
composables/ useParallelRun.ts
|
||||
lib/ avatar-constants.ts
|
||||
styles/ parallel-agents.css
|
||||
api.ts · config.ts · types.ts
|
||||
```
|
||||
宿主需有 `markdown-it` 依赖(`pnpm add markdown-it`),并保证构建支持 `.vue`(Vite/@vitejs/plugin-vue)。
|
||||
|
||||
---
|
||||
|
||||
## 三、注册与使用
|
||||
|
||||
### 局部引入(推荐)
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { ParallelAgentsPanel } from "parallel-agents-vue";
|
||||
import "parallel-agents-vue/style.css";
|
||||
|
||||
const agents = [
|
||||
{ agent_id: "roundtable-solution-design", name: "方案设计" },
|
||||
{ agent_id: "roundtable-risk-review", name: "风险审查" },
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div style="height: 80vh">
|
||||
<ParallelAgentsPanel :username="'demo'" :agents="agents" />
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
### 全局注册(可选)
|
||||
|
||||
```ts
|
||||
import ParallelAgentsVue from "parallel-agents-vue";
|
||||
import "parallel-agents-vue/style.css";
|
||||
app.use(ParallelAgentsVue); // 之后任意模板可直接用 <ParallelAgentsPanel/>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、放进抽屉 / 弹窗
|
||||
|
||||
组件根元素是 `h-full w-full flex flex-col min-h-0`,会**充满父容器**。所以**父容器要给一个高度**
|
||||
(弹窗/抽屉本身有高度即可):
|
||||
|
||||
```vue
|
||||
<YourDrawer v-model="open" size="large">
|
||||
<div style="height: 86vh">
|
||||
<ParallelAgentsPanel :username="currentUsername" :agents="agents" @saved="onSaved" />
|
||||
</div>
|
||||
</YourDrawer>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、接口地址与登录
|
||||
|
||||
- **接口地址**:默认读 `src/config.ts` 的 `DEFAULT_BASE_URL`(可改源码,或 dev 设 `VITE_PA_BASE_URL`);
|
||||
也可用 `:base-url` prop 临时覆盖。
|
||||
- **登录**:把宿主的**用户名**用 `:username` 传进来即可——组件自动走 DeerFlow 免密登录端点换 token、
|
||||
缓存、401 自动重登。**宿主不用管 token**。若已有 token,可改传 `:token` / `:get-token`(优先级更高)。
|
||||
- token 缓存按 `baseUrl::username` 维度,多个实例/多用户互不串。
|
||||
|
||||
---
|
||||
|
||||
## 六、Props
|
||||
|
||||
| prop | 类型 | 必填 | 说明 |
|
||||
| --------------- | --------------------------------------- | :--: | ----------------------------------------------- |
|
||||
| `agents` | `{ agent_id, name, avatarType? }[]` | ✔ | 要并行调用的智能体(`agent_id` 必须是真实 id) |
|
||||
| `username` | `string` | | 免密自动登录用户名(推荐方式) |
|
||||
| `baseUrl` | `string` | | 后端地址;不传用 `config.ts` 默认 |
|
||||
| `token` | `string` | | 已有 Bearer token(优先于 username) |
|
||||
| `getToken` | `() => string \| Promise<string>` | | 动态取 token |
|
||||
| `loginPassword` | `string` | | 仅当后端开启口令门时需要 |
|
||||
| `taskId` | `string` | | 传入则挂载时自动加载并回显该任务 |
|
||||
| `model` | `string` | | 可选模型名(不传走默认 / 后端回退) |
|
||||
| `dark` | `boolean`(默认 `true`) | | 深色面板(自带成色,不依赖宿主主题) |
|
||||
|
||||
`AgentInput`/`SavedTask` 等类型也从包里导出:`import type { AgentInput, SavedTask } from "parallel-agents-vue"`。
|
||||
|
||||
## 七、事件
|
||||
|
||||
| 事件 | 载荷 | 触发时机 |
|
||||
| ----------------- | ------------ | --------------------------------------- |
|
||||
| `saved` | `SavedTask` | 保存成功(新建或更新)后 |
|
||||
| `update:taskId` | `string` | 当前任务 id 变化(保存 / 加载历史时) |
|
||||
|
||||
```vue
|
||||
<ParallelAgentsPanel
|
||||
:username="user"
|
||||
:agents="agents"
|
||||
:task-id="taskId"
|
||||
@saved="(t) => console.log('saved', t.id)"
|
||||
@update:taskId="(id) => (taskId = id)"
|
||||
/>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、交互要点(与圆桌 Step2 一致)
|
||||
|
||||
- 输入「任务名称 + 简介」→「开始分析」→ 各智能体**并行**输出,运行期间**禁止写文件**(产出走正文)。
|
||||
- 主区每次只显示**一个**席位的消息列表;**点席位头像切换**要看哪个(单选)。
|
||||
- 顶部席位状态条显示每个智能体的进行中 / 完成 / 出错。
|
||||
- 操作区右侧有**模型切换**下拉(拉取后端 `/api/models`);选「默认」则用 `model` prop / 配置 / 后端回退。
|
||||
切换作用于**下一次**「开始分析 / 重新分析」,运行中禁用。
|
||||
- 「保存」存档;「历史」里选回**回显**;「重新分析」清空重跑。
|
||||
|
||||
---
|
||||
|
||||
## 九、注意事项
|
||||
|
||||
- **不会污染宿主全局样式**:库未引入 Tailwind preflight,类名都在 `.parallel-agents` 作用域内。
|
||||
- **深色自带成色**:面板始终深蓝深色,不随宿主明暗切换(与圆桌 Step2 观感一致)。
|
||||
- **跨域**:若宿主与后端不同源,后端需允许该来源的 CORS + 带 `credentials`;登录端点公共且 CSRF 豁免,
|
||||
业务请求用 Bearer 头已绕过 CSRF。
|
||||
- **agent_id 必须真实**:见 [06-可用智能体清单.md](./06-可用智能体清单.md) 获取可用 id 与自查方法。
|
||||
Reference in new issue
Block a user