Metadata-Version: 2.4
Name: nonebot-plugin-wyrestorm
Version: 0.1.1
Summary: Evidence-grounded WyreStorm presales AI bridge for NoneBot2
License-Expression: MIT
License-File: LICENSE
Keywords: nonebot,nonebot2,onebot,wyrestorm,rag,deepseek,qwen
Author: WyreStorm Product Intelligence Team
Requires-Python: >=3.10,<4.0
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Communications :: Chat
Requires-Dist: httpx (>=0.27.0,<1.0.0)
Requires-Dist: nonebot-adapter-onebot (>=2.4.0,<3.0.0)
Requires-Dist: nonebot2 (>=2.3.0,<3.0.0)
Requires-Dist: pydantic (>=2.5.0,<3.0.0)
Project-URL: Homepage, https://github.com/TonyLiangP2010405/nonebot-plugin-wyrestorm
Project-URL: Issues, https://github.com/TonyLiangP2010405/nonebot-plugin-wyrestorm/issues
Project-URL: Repository, https://github.com/TonyLiangP2010405/nonebot-plugin-wyrestorm
Description-Content-Type: text/markdown

# nonebot-plugin-wyrestorm

将 WyreStorm Product Intelligence 的 DeepSeek 售前 AI 对话和 Qwen 多模态工具接入
NoneBot2。插件负责 OneBot V11 命令、群聊/私聊会话、上下文、单轮附件与 Poster 草稿；
产品目录、Support 资料、培训文件、向量和模型调用仍由私有 WyreStorm 后端处理。

## 功能

- `/wys` 售前问答；兼容 `/ws`、`/wyrestorm`、`/威视问答` 旧命令。
- 群聊与私聊均可使用；每个会话独立保存最多 12 条上下文。
- 保留原系统的 RAG、完整系列查询、产品详情、比较和 Poster 工具调用。
- 支持随命令发送图片、PDF、Office、文本、音频或视频，由 Qwen 工具分析或转写。
- 显示可溯源的知识依据、工具名称和建议追问。
- 会话与 Poster 草稿写入包外 SQLite；同一会话的并发问题串行处理。
- 附件单轮最多 3 个、默认每个 32 MiB，使用后端随机 ID，处理后立即删除。
- 默认拒绝私网/本机附件 URL，降低恶意消息诱导机器人访问内网的风险。
- 后端未启动、超时、限流、配置缺失和数据目录不可写时返回安全提示。

## 架构与私有数据边界

```text
OneBot V11
    ↓
nonebot-plugin-wyrestorm       可发布：仅 Python 代码、README、测试
    ↓ HTTP
WyreStorm Product Intelligence 私有部署：DeepSeek、RAG、工具 Harness
    ↓
外置知识目录                  不发布：SQLite、PPT、Excel、PDF、图片、向量
```

插件包不包含知识库。`.gitignore` 和 Poetry `exclude` 同时排除：

- `data/`、`knowledge/`、`sources/`、`product-images/`
- `*.sqlite*`、`*.db`
- `*.ppt[x]`、`*.docx`、`*.xlsx`、`*.pdf`

不要把知识文件放入 `nonebot_plugin_wyrestorm/`。后续知识库迁移约定见
[`KNOWLEDGE_MIGRATION.md`](KNOWLEDGE_MIGRATION.md)。

## 环境要求

- Python 3.10+
- NoneBot2 2.3+
- OneBot V11 适配器
- 可访问的 WyreStorm Product Intelligence 后端

## 安装

从 PyPI 安装：

```bash
nb plugin install nonebot-plugin-wyrestorm
# 或
pip install nonebot-plugin-wyrestorm
# 或
poetry add nonebot-plugin-wyrestorm
```

然后在 NoneBot 项目的 `pyproject.toml` 中加载插件：

```toml
[tool.nonebot]
plugins = ["nonebot_plugin_wyrestorm"]
```

参与插件开发时也可以从本地目录安装：

```bash
pip install -e /path/to/nonebot-plugin-wyrestorm
```

## 配置

在 NoneBot 项目的 `.env` 中配置：

```env
WYRESTORM_API_BASE=http://127.0.0.1:4173
WYRESTORM_API_TOKEN=
WYRESTORM_REQUEST_TIMEOUT=300
WYRESTORM_HISTORY_LIMIT=12
WYRESTORM_DATA_DIR=data/nonebot_plugin_wyrestorm
WYRESTORM_PUBLIC_BASE_URL=
WYRESTORM_MAX_REPLY_CHARS=2800
WYRESTORM_ATTACHMENT_MAX_BYTES=33554432
WYRESTORM_ATTACHMENT_TIMEOUT=60
WYRESTORM_ATTACHMENT_ALLOW_PRIVATE_URLS=false
```

| 配置项 | 默认值 | 说明 |
|---|---:|---|
| `WYRESTORM_API_BASE` | `http://127.0.0.1:4173` | 私有 AI/RAG 后端地址 |
| `WYRESTORM_API_TOKEN` | 空 | 后端绑定非回环地址时使用的本地管理令牌；不会写入日志 |
| `WYRESTORM_REQUEST_TIMEOUT` | `300` | Agent/Qwen 请求超时秒数，范围 5–320 |
| `WYRESTORM_HISTORY_LIMIT` | `12` | 每个群或私聊保留的消息数，最大 12 |
| `WYRESTORM_DATA_DIR` | `data/nonebot_plugin_wyrestorm` | 包外会话数据库目录 |
| `WYRESTORM_PUBLIC_BASE_URL` | 空 | 可由聊天客户端访问的后端公网/内网地址，用于 Poster 下载链接 |
| `WYRESTORM_MAX_REPLY_CHARS` | `2800` | 单条机器人消息的最大字符数 |
| `WYRESTORM_ATTACHMENT_MAX_BYTES` | `33554432` | 单个 OneBot 附件最大字节数，默认 32 MiB |
| `WYRESTORM_ATTACHMENT_TIMEOUT` | `60` | 从 OneBot URL 下载附件的超时秒数 |
| `WYRESTORM_ATTACHMENT_ALLOW_PRIVATE_URLS` | `false` | 是否允许附件 URL 指向私网；仅可信内网 OneBot 才应开启 |

DeepSeek API Key 仍在 WyreStorm 后端配置，不写入 NoneBot 插件。

## 使用方法

| 指令 | 权限 | 范围 | 说明 |
|---|---|---|---|
| `/wys <问题>` | 群员 | 群聊/私聊 | 向售前 AI 提问 |
| `/wys <问题>` + 附件 | 群员 | 群聊/私聊 | 使用 Qwen 分析图片、文档、音视频 |
| `/wys 状态` | 群员 | 群聊/私聊 | 检查后端、数据库和当前会话 |
| `/wys 清空` | 群员 | 群聊/私聊 | 清空当前会话和 Poster 草稿 |
| `/wys 帮助` | 群员 | 群聊/私聊 | 显示帮助 |

示例：

```text
用户：/wys NHD-500-TX v2 的关键参数和限制是什么？
机器人：返回知识库约束的回答、依据与建议追问。

用户：/wys 把这个产品加入 Poster
机器人：调用后端 Poster 草稿工具并保存到当前会话。

用户：/wys 输出当前 Poster
机器人：生成 Poster；配置公开后端地址后同时返回 Word/PDF 链接。

用户：/wys 请读取图中的型号和接口（同时发送图片）
机器人：临时上传图片，调用 Qwen 分析，并结合 RAG 返回结果。
```

若 OneBot 只返回本地文件标识而没有 `url` 或 `base64://`，插件无法跨进程安全读取，
会提示调整适配器配置。可信的同机/内网 OneBot 若只提供私网 URL，可以显式启用
`WYRESTORM_ATTACHMENT_ALLOW_PRIVATE_URLS=true`；公网机器人不建议开启。

群聊以 OneBot 的群会话 ID 为单位，因此同一群成员共享上下文；不同群与不同私聊互不影响。

## 启动私有后端

在原项目中运行：

```bash
npm start
curl http://127.0.0.1:4173/ready
```

不要把 4173 端口直接暴露到公网。跨机器部署时应使用内网、反向代理、TLS 与访问控制。

## 原功能迁移对照

| 原项目功能 | NoneBot 插件实现位置 | 是否完成 | 备注 |
|---|---|---|---|
| 发送 AI 消息 | `matcher.py` + `client.py` | 是 | 调用原 `/api/v1/presales-agent/messages` |
| 最多 12 条上下文 | `models.py` + `session_store.py` | 是 | 改为服务端会话持久化 |
| 群聊/私聊隔离 | `event.get_session_id()` | 是 | 群内共享、私聊独立 |
| RAG 与真实性守门 | 私有 Node 后端 | 是 | 不复制知识数据或 Agent 规则 |
| 产品工具调用 | 私有 Node 后端 | 是 | 保持现有 Harness |
| Poster 草稿 | `session_store.py` | 是 | 随会话持久化 |
| Poster Word/PDF | `formatter.py` | 部分 | 已生成链接；不直接上传群文件 |
| 浏览器结构化卡片 | `formatter.py` | 已适配 | 转为 OneBot 纯文本与分段消息 |
| 图片/文档/音视频附件 | `attachments.py` + `client.py` | 是 | 单轮临时上传、SSRF 防护、完成后删除 |
| Qwen 多模态状态 | `/wys 状态` | 是 | 显示附件工具是否可用 |
| 浏览器对话导出 | — | 否 | Bot 聊天记录由平台/会话数据库保存 |
| 知识库本体迁移 | `KNOWLEDGE_MIGRATION.md` | 待后续 | 本阶段明确不进入 Git/PyPI |

## 开发与测试

```bash
poetry install
poetry run python -m compileall nonebot_plugin_wyrestorm
poetry run pytest
poetry run ruff check .
poetry build
```

构建后应检查 wheel/sdist 内容，确认不存在 SQLite、Office/PDF、图片或知识目录。

## 许可证

MIT。产品知识、产品图片和原始资料不属于插件发布物，也不随本许可证分发。

