agentscope-ai / agentscope-ai/QwenPaw
[Feature]: 新增2个需求,chat聊天对话界面可以不带侧边栏和头部栏单独打开。url带上apikey避免权限验证。其次是session列表查询支持日期和sessionId等条件及精确筛选。
- 主要言語
- Python
- スター
- 34.9k
- フォーク
- 3.1k
- 平均マージ
- 1日 15時間
- マージ済み PR(30日)
- 225
説明
## Summary
当前版本 V2.0.1.
# QwenPaw Feature Requests
**Submitter:** 星光灏然 (test & tooling, HundSun)
**Context:** QwenPaw v2.0.1, console frontend @ http://127.0.0.1:8088/chat
**Submitted:** 2026-08-13
**Tags:** `enhancement` `frontend` `api` `embed` `chat`
---
## FR-1 — Embeddable Chat Sub-Page (no sidebar, no header)
### 现状 / Current behaviour
- 所有路径(`/`、`/chat`、`/chat/{sessionId}`、`/agents`...)都返回**同一个 HTML**,由前端 React Router 处理
- 后端**没有** `embed`、`standalone`、`minimal` 之类的路由
- 页面布局被固定写死在根布局组件里(三段式):
- 顶部:`[class*="index-module__header__"]` — logo、版本号、文档、GitHub
- 左侧:`[class*="index-module__sider__"]` — agent 选择 + 全部菜单
- 主区:`qwenpaw-layout-content` — `/chat` 内容
**已实测证据:**
```bash
$ curl -s -I http://127.0.0.1:8088/chat
HTTP/1.1 405 Method Not Allowed
allow: GET
$ curl -s http://127.0.0.1:8088/api/chats # 后端只有 /api,没有 /embed /chat/embed 等
{"detail":"Not Found"}
```
DOM 实测(生产 console):
```js
bannerClass: "qwenpaw-layout-header index-module__header__qmg3x css-var-r0"
siderClass: "qwenpaw-layout-sider qwenpaw-layout-sider-dark index-module__sider__s7Q1a css-var-r0"
mainClass: "qwenpaw-layout-content page-container css-var-r0"
```
### 痛点 / Why this matters
测试场景下,我们经常希望:
1. **集成到内部工具面板里做内嵌** — 比如把 QwenPaw chat 直接放进我们自研的测试执行台 / 缺陷分析台
2. **录屏/截图做自动化测试** — 侧边栏 icon 在不同 agent 切换时变化,会让 diff 截图不可比
3. **把 chat 当独立子页面挂载到 iFrame** — 现在因为带 header 和 sider,引入方要塞一堆不相关视觉
写油猴/Stylus 临时隐藏只是 workaround,每次升级 CSS Module 类名变了就会失效(`index-module__header__qmg3x` 后缀是 hash)。
### 建议实现 / Proposed implementation
**P1 — 最小改动(推荐先做)**
增加 **URL query** 控制,例如:
```
GET /chat/{sessionId}?embed=1
GET /chat/{sessionId}?chrome=hidden # 备选命名
```
embed 模式下:
- 不渲染 `` 与 `` 组件(root layout 不带 chrome)
- 主区域铺满 `100vh × 100vw`,去除默认 padding(保留 chat 内部 padding)
- `window.parent.postMessage({type:'qwenpaw:ready', sessionId})` 给宿主页面一个握手信号
- 标题里 `qwenPaw` logo/title 替换成 `chatId` 或保留窗体 title 用空字符串
**P2 — 完整 embed API**
提供 `postMessage` 协议让宿主控制 chat:
```js
// parent → iframe
{ type: 'qwenpaw:send', content: '...' }
{ type: 'qwenpaw:createSession' }
{ type: 'qwenpaw:abort' }
// iframe → parent
{ type: 'qwenpaw:ready', sessionId }
{ type: 'qwenpaw:message', role: 'assistant', content: '...' }
{ type: 'qwenpaw:state', status: 'running' | 'idle' }
```
**P3 — 样式 token 暴露**
embed 模式下,通过 query 参数接受设计 token:
```
?embed=1&theme=dark&accent=3370FF&fontSize=14
```
让父页面可以品牌化嵌入的 chat。
### 验收标准 / Acceptance criteria
- [ ] 单 URL 即可打开纯 chat 页(无 header、无 sider、无 menu 按钮)
- [ ] `?embed=1` 在 `/chat` 和 `/chat/{sessionId}` 都生效
- [ ] embed 模式下 `body` 高度为 viewport 的 `100vh`,无滚动条溢出
- [ ] embed 页面在 iFrame 中跨域不报错(postMessage 协议)
- [ ] 默认(原 `?embed=0` 或无参数)行为不变,回归通过
### 变通方案 / Workarounds currently in use
我们暂时只能写 CSS 隐藏:
```css
[class*="index-module__header__"] { display: none !important; }
[class*="index-module__sider__"] { display: none !important; }
[class*="qwenpaw-layout-content"] { margin: 0; padding: 12px; height: 100vh; }
```
但 CSS Module 类名每次构建都变 hash,hack 脚本得跟着升级更新,不可维护。
---
## FR-2 — `/api/chats` 增加日期范围与精确 session_id 查询
### 现状 / Current behaviour
`GET /api/chats` 当前支持的查询参数(基于实测,已在 v2.0.1 验证):
| 参数 | 类型 | 生效 |
|---|---|---|
| `user_id` | string | ✅ 已支持 |
| `channel` | string | ✅ 已支持 |
| `archived` | bool | ✅ 已支持 |
| `session_id` | string | ❌ **缺失** |
| `date` / `date_from` / `date_to` | ISO date/range | ❌ **缺失** |
| `q` (name 模糊搜索) | string | ❌ 缺失 |
| `limit` / `offset` (分页) | int | ❌ 缺失 |
实测(v2.0.1):传 `?user_id=python-user` 拿到 1 条,✅ 生效;传 `?session_id=...` 和 `?date=...` 都被静默忽略,返回全量。
### 痛点 / Why this matters
- **CI 回归**:拿测试数据时只能拉全量再 Python 端 filter,几百条还算 OK,几千条响应慢且 JSON 巨大
- **日志审计**:现场测试回归需要"今天对 python-user 发起的所有 chat",当前只能全量下载客户端过滤
- **批量校验**:要批量核对某些关键 session 的落库情况,全量拉取非常低效
### 建议实现 / Proposed implementation
保持现有 `user_id / channel / archived` 参数兼容性,**追加**新参数:
```http
GET /api/chats
?user_id=default # 现有:仍工作
&archived=false # 现有:仍工作
# —— 新增 ——
&session_id=1786595667235-1sx1erm # 精确匹配,返回 0 或 1 条
&date=2026-08-13 # 当天 (created_at 落在 [00:00, 24:00) 本地时区)
&date_from=2026-08-01&date_to=2026-08-13 # 区间(含端点,created_at 过滤)
&created_after=2026-08-01T00:00:00Z # ISO-8601,绝对时间
&created_before=2026-08-13T23:59:59Z # ISO-8601,绝对时间
&updated_after=2026-08-10T00:00:00Z # 按 updated_at 过滤
&q=反洗钱 # name LIKE 模糊匹配
&limit=50&offset=0 # 分页,默认 limit=100, max=500
&order=updated_at:desc # 排序,可选 updated_at:asc / created_at:desc 等
```
**关键约定:**
1. `session_id` 与 `date`/`date_from`-`date_to` 互斥(同时传返回 400)
2. 时间字段都用 **ISO-8601**,UTC 优先,本地时区参数 `tz=Asia/Shanghai`
3. `date_from / date_to` 默认含两端;想 exclusive 用 `date_from_exclusive=true`
4. 分页 `limit ≤ 500`,超过返 400 + 建议值
5. 排序默认 `updated_at desc`,可显式覆盖
### 响应示例 / Example
```bash
# 精确查某个 session
$ curl 'http://127.0.0.1:8088/api/chats?session_id=1786595667235-1sx1erm'
[
{
"id": "c2214ed4-0e4e-40df-b736-015148b99d2c",
"session_id": "1786595667235-1sx1erm",
"name": "QwenPaw 后台聊天独立页面",
"user_id": "default",
"channel": "console",
"created_at": "2026-08-13T04:36:12.007748Z",
"updated_at": "2026-08-13T04:40:27.761014Z",
...
}
]
# 区间
$ curl 'http://127.0.0.1:8088/api/chats?date_from=2026-08-01&date_to=2026-08-13&limit=10&order=updated_at:desc'
[ ... ] # 200 OK, 最多 10 条
# 互斥冲突
$ curl -i 'http://127.0.0.1:8088/api/chats?session_id=foo&date_from=2026-08-01'
HTTP/1.1 400 Bad Request
{
"detail": "session_id is mutually exclusive with date/date_from/date_to"
}
```
### 验收标准 / Acceptance criteria
- [ ] `session_id=foo` 返回 0 或 1 条
- [ ] `date=2026-08-13` 返回当天创建的所有 chat(按业务时区)
- [ ] `date_from=A&date_to=B`(A ≤ B)返回区间内
- [ ] 与 `user_id / channel / archived` 叠加生效(AND 语义)
- [ ] `limit > 500` 返回 400
- [ ] 现有 `user_id / channel / archived` 调用方零回归
### 用法示例 / How we'd use it
测试自动化里:
```python
# 拉今天对 python-user 发起的所有 chat
today = datetime.now().date().isoformat()
resp = httpx.get(
"http://127.0.0.1:8088/api/chats",
params={"user_id": "python-user", "date": today, "limit": 500},
headers={"Authorization": f"Bearer {token}"},
).json()
assert len(resp) >= 1
```
CI 回归日志采集:
```bash
# 抓 7 天内的 console 数据汇总
curl -s 'http://127.0.0.1:8088/api/chats?channel=console&date_from=2026-08-06&date_to=2026-08-13&limit=500' \
-H "Authorization: Bearer $TOKEN" \
| jq '[.[].session_id] | length'
```
---
## 共性建议 / Cross-cutting suggestions
1. **OpenAPI schema 文档化** — 把 `/api/chats` 现有参数写进 `openapi.json`,前端调用方少踩坑
2. **变更日志** — 每次加参数,CHANGELOG 里留一行;外部调用方(自动化脚本)能 trust 升级
3. **向后兼容约定** — 文档里写明 "新增参数,永不删"
## 元数据 / Metadata
- **Reporter env:** QwenPaw v2.0.1, macOS Darwin 25.6.0 arm64, Python 3.13
- **Reproduction repo:** `~/.copaw/workspaces/default/`
- **Severity for FR-1:** Medium (UI integration blockers)
- **Severity for FR-2:** Low-Medium (workable via client-side filter, inefficient at scale)
- **Willing to PR:** Yes — 可以贡献 PoC patch (frontend embed route + API param parser),需要 maintainer 在哪个 repo 上提
## Component(s) Affected
- [ ] Core / Backend (app, agents, config, providers, utils, local_models)
- [ ] Console (frontend web UI)
- [ ] Channels (DingTalk, Feishu, QQ, Discord, iMessage, etc.)
- [ ] Skills
- [ ] CLI
- [ ] Documentation (website)
- [ ] Tests
- [ ] CI/CD
- [ ] Scripts / Deploy
## Problem / Motivation
[What problem does this solve? Who benefits?]
## Proposed Solution
[Describe the feature or change you have in mind. Be as specific as possible.]
## Alternatives Considered
[Any other approaches or workarounds you thought about.]
## Additional Context
[Screenshots, examples, links to docs or similar features elsewhere.]
## Willing to Contribute
- [ ] I am willing to open a PR for this feature (after discussion).
コントリビューションガイド
評価
この issue はまだ評価されていません。