Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
## v3.6.3 合并转发快照、附件 UID 分析与 Release 下载说明

本版本聚焦合并转发在协议端不可二次读取时的可用性:收到消息时先把可访问的转发树按会话保存为本地快照,后续工具读取优先复用快照,避免内层转发过期或回源失败导致 AI 看不到内容。同时补齐文件分析 Agent 对内部附件 UID 的直接解析能力,并澄清 Release 产物的下载选择。

- 新增合并转发快照缓存。消息预处理阶段会递归保存当前可访问的合并转发树到 `data/cache/forward_snapshots/`,保留实时上下文中的 `<forward uid="..."/>` 语义;快照按会话隔离,并合并同一转发的并发抓取。
- 改进 `messages.get_forward_msg`。工具支持 `forward_` UID 与原始 ID 优先读取本地快照,缺失时再回源 OneBot 并补写快照;协议端无法二次读取内层转发时,会返回明确诊断和可见原始字段,而不是只报空内容。
- 修复合并转发当前轮上下文重复。Prompt 构建在剔除当前消息历史副本时优先匹配 `message_id`,避免历史中的递归展开文本与实时 `<forward uid="..."/>` 在同一轮重复注入。
- 增强文件分析附件链路。`file_analysis_agent` 的 `analyze_multimodal` 可直接接收 `pic_` / `file_` UID,按当前会话作用域解析并本地化后再分析;Agent 提示同步明确不要改写或猜测附件 UID。
- 澄清 Release 下载选择。README 与部署、构建、App 文档补充说明:部署 QQ Bot 通常不需要下载 Release 客户端安装包,Console / Chat 仅作为远程管理或原生聊天的可选组件。
- 同步 3.6.3 版本号与测试覆盖。Python 包、Console、Chat、Tauri 与 lock 文件版本统一更新;新增合并转发快照、转发读取回退、多模态附件 UID 和当前消息去重回归测试。

---

## v3.6.2 合并转发 UID、表情包跟进与协调器清理

本版本继续收敛消息附件链路和协调器结构:合并转发可作为会话内 `forward_` UID 被 AI 按层读取和复用,表情包跟进策略更稳定,同时移除旧版协调器兼容模块,并完成 3.6.2 版本号同步。
Expand Down
28 changes: 27 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,32 @@

[点击添加官方实例QQ](https://qm.qq.com/q/cvjJoNysGA)

## Release 下载速查

如果只是部署和运行 QQ Bot,通常**不需要**在 GitHub Release 的 Assets 里下载任何文件。推荐按下方[快速开始](#-快速开始-源码模式)使用源码部署;只想快速体验命令行入口时,可使用 `pip install -U Undefined-bot` 或 `uv tool install Undefined-bot`。

Release 里的安装包是可选组件,不是 Bot 服务本体:

| 目标 | 是否需要下载 Release | 选择 |
| --- | --- | --- |
| 部署 / 运行 QQ Bot | 不需要 | 源码部署,启动 `uv run Undefined-webui`;或使用 `pip` / `uv tool` 安装 Python 包 |
| 远程管理已有实例 | 可选 | `Undefined-Console-*`,用于连接 Management API 并打开远程 WebUI |
| 使用原生聊天客户端 | 可选 | `Undefined-Chat-*`,用于连接 Runtime API 聊天 |
| 离线安装 / 镜像缓存 Python 包 | 可选 | `undefined_bot-*.whl` 或 `undefined_bot-*.tar.gz` |

平台文件选择:

| 平台 | 推荐下载 |
| --- | --- |
| Windows x64 | `*-windows-x64-setup.exe`;批量部署或系统管理场景可选 `.msi` |
| macOS Apple Silicon | `*-macos-arm64.dmg` |
| macOS Intel | `*-macos-x64.dmg` |
| Debian / Ubuntu | `*.deb` |
| 其他 Linux x64 | `*.AppImage` |
| Android 常见手机 / 平板 | `*-android-arm64-v8a-release.apk`;旧 32 位设备选 `armeabi-v7a`,模拟器按需选 `x86_64` / `x86` |

Console 和 Chat 都需要连接到已经运行的 Undefined 服务。首次部署请先启动 `Undefined-webui`,完成配置和 Bot 启动后,再按需使用这些客户端连接。

## ⚡ 核心特性

- **Skills 架构**:全新设计的技能系统,将基础工具(Tools)与智能代理(Agents)分层管理,支持自动发现与注册。
Expand Down Expand Up @@ -126,7 +152,7 @@ uv run Undefined-webui
# cp config.toml.example config.toml
```

> 浏览器是默认入口;如果你下载了 Release 中的桌面端或 Android 安装包,也可以在完成首轮密码设置后,连接到同一个 Management API 地址进行远程管理。
> 浏览器是默认入口;如果你按上方 [Release 下载速查](#release-下载速查)下载了桌面端或 Android 安装包,也可以在完成首轮密码设置后,连接到同一个 Management API 地址进行远程管理。

---

Expand Down
4 changes: 2 additions & 2 deletions apps/undefined-chat/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/undefined-chat/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "undefined-chat",
"private": true,
"version": "3.6.2",
"version": "3.6.3",
"type": "module",
"scripts": {
"tauri": "tauri",
Expand Down
2 changes: 1 addition & 1 deletion apps/undefined-chat/src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/undefined-chat/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "undefined_chat"
version = "3.6.2"
version = "3.6.3"
description = "Undefined native chat client"
authors = ["Undefined contributors"]
license = "MIT"
Expand Down
2 changes: 1 addition & 1 deletion apps/undefined-chat/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Undefined Chat",
"version": "3.6.2",
"version": "3.6.3",
"identifier": "com.undefined.chat",
"build": {
"beforeDevCommand": "npm run dev",
Expand Down
4 changes: 2 additions & 2 deletions apps/undefined-console/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/undefined-console/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "undefined-console",
"private": true,
"version": "3.6.2",
"version": "3.6.3",
"type": "module",
"scripts": {
"tauri": "tauri",
Expand Down
2 changes: 1 addition & 1 deletion apps/undefined-console/src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/undefined-console/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "undefined_console"
version = "3.6.2"
version = "3.6.3"
description = "Undefined cross-platform management console"
authors = ["Undefined contributors"]
license = "MIT"
Expand Down
2 changes: 1 addition & 1 deletion apps/undefined-console/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Undefined Console",
"version": "3.6.2",
"version": "3.6.3",
"identifier": "com.undefined.console",
"build": {
"beforeDevCommand": "npm run dev",
Expand Down
2 changes: 2 additions & 0 deletions docs/app.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ Android 端仍然走同一套连接模型,但 UI 目标是:

## 8. Release 产物

普通用户如果只是部署 Bot,不需要下载这些 App 产物;先运行 `Undefined-webui` 即可。需要远程管理或原生聊天客户端时,再按 [README — Release 下载速查](../README.md#release-下载速查) 选择对应平台文件。

每次 `v*` tag 发布时,Release workflow 计划同步上传:

- Python:`wheel` + `sdist`
Expand Down
2 changes: 2 additions & 0 deletions docs/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,8 @@ npm install

## 9. Release 产物矩阵

面向普通用户的下载选择见 [README — Release 下载速查](../README.md#release-下载速查);本节只记录构建和发布矩阵。部署 Bot 本身不需要下载 Console / Chat 客户端安装包。

每次正式 Release 计划上传:

- Python
Expand Down
2 changes: 1 addition & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ Prompt caching 补充:

外部接收的远程图片或文件默认会先下载到附件缓存再生成 UID,避免后续 URL 失效;大文件超过阈值时,UID 仍会生成,但绑定的是 URL 引用而不是缓存文件,AI 可在上下文中看到原始 `source_ref`。如果本地缓存因总容量或时间清理被删除,但记录仍保留 URL,后续需要文件内容时会优先按 URL 回源下载。

合并转发会复用同一注册表登记为 `forward_...` UID,并在实时 AI 输入中显示为 `<forward uid="..."/>`。历史记录仍保留递归展开后的文本;需要查看实时上下文里的转发内容时,AI 会调用 `messages.get_forward_msg` 按层读取,内层合并转发会继续分配新的 `forward_...` UID。
合并转发会复用同一注册表登记为 `forward_...` UID,并在实时 AI 输入中显示为 `<forward uid="..."/>`。收到合并转发时会在预处理阶段递归保存当前可访问的转发树到 `data/cache/forward_snapshots/`,后续 `messages.get_forward_msg` 读取时优先使用本地快照;缺失时才回源 OneBot 并补写快照。历史记录仍保留递归展开后的文本,但同一轮 prompt 会按 `message_id` 剔除当前消息的历史副本,因此实时上下文只保留 UID;需要查看第一层或内层内容时,AI 会调用工具按层读取,内层合并转发会继续分配新的 `forward_...` UID。如果协议端无法二次读取内层转发,会返回明确诊断和可见原始字段

### 4.10.2 `[message_batcher]` 同 sender 短时消息合并

Expand Down
4 changes: 3 additions & 1 deletion docs/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

提供源码部署与 pip/uv tool 安装两种方式:**源码部署是推荐的首选方式**,功能完整且经过充分测试;pip/uv tool 安装适合快速体验,但部分功能支持尚不完善。

> **Release 下载提示**:如果目的是部署 QQ Bot,不需要在 GitHub Release 的 Assets 中挑客户端安装包;按本文源码部署或 pip/uv tool 安装即可。Release 中的 `Undefined-Console-*` 和 `Undefined-Chat-*` 是可选客户端,选择说明见 [README — Release 下载速查](../README.md#release-下载速查)。
>
> **作为 Python 库嵌入**:若你不需要启动 QQ Bot CLI,而是要在自己的应用或测试中复用 Undefined 组件(配置、`AIClient`、Skills、认知记忆等),请参阅 [Python 库 API 参考](python-api.md) 与 [配置详解 — 库嵌入配置](configuration.md#2-库嵌入配置)。CLI 入口(`Undefined` / `Undefined-webui`)行为不受库嵌入 API 影响。

>
> Python 版本要求:`3.11`~`3.13`(包含)。
>
> 若使用 `uv`,通常不需要你手动限制系统 Python 版本;`uv` 会根据项目约束自动选择/下载兼容解释器。
Expand Down
4 changes: 2 additions & 2 deletions docs/pipelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

## 运行顺序

1. `MessageHandler` 先并行执行消息预处理:附件收集、历史文本解析、昵称或群信息读取等。图片、文件等媒体会登记为附件 UID,并在 AI 可见正文中统一写作 `<attachment uid="..."/>`;合并转发会登记为 `<forward uid="forward_xxx"/>`,不在实时 AI 输入中自动展开。
2. 用户消息先写入历史。历史记录仍会递归展开合并转发文本,保持历史检索和旧行为兼容;实时 AI 输入只保留 forward UID,AI 需要查看时调用 `messages.get_forward_msg` 按层读取。
1. `MessageHandler` 先并行执行消息预处理:附件收集、历史文本解析、昵称或群信息读取等。图片、文件等媒体会登记为附件 UID,并在 AI 可见正文中统一写作 `<attachment uid="..."/>`;合并转发会登记为 `<forward uid="forward_xxx"/>`,同时递归保存当前可访问的转发树快照,不在实时 AI 输入中自动展开。
2. 用户消息先写入历史。历史记录仍会递归展开合并转发文本,保持历史检索和旧行为兼容;同一轮 prompt 会剔除当前消息的历史副本,实时 AI 输入只保留 forward UID,AI 需要查看第一层或内层内容时调用 `messages.get_forward_msg` 按层读取。
3. 若消息命中斜杠命令,立即分发命令并结束本轮后续流程;命令输入和命令输出会写入历史,供后续 AI 轮次读取。
4. 未命中命令时,`PipelineRegistry` 并行调用所有已注册管线的 `detect(context)`。
5. 对所有命中的管线,并行调用对应的 `process(detection, context)`。
Expand Down
2 changes: 1 addition & 1 deletion docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ Undefined 搭载了基于 ChromaDB 向量数据库的后台认知系统,无需
| `messages.send_text_file` | 将文本内容生成文件后发送 |
| `messages.send_url_file` | 下载指定 URL 的文件后发送 |
| `messages.send_group_sign` | 执行群签到操作 |
| `messages.get_forward_msg` | 按层读取合并转发内容;支持 `<forward uid="forward_xxx"/>` 和旧合并转发 ID,可用 `offset`/`limit` 分页查看更多 |
| `messages.get_forward_msg` | 按层读取合并转发内容;支持 `<forward uid="forward_xxx"/>` 和旧合并转发 ID,优先使用收到消息时递归保存的本地快照,缺失时回源 OneBot,可用 `offset`/`limit` 分页查看更多 |

---

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "Undefined-bot"
version = "3.6.2"
version = "3.6.3"
description = "QQ bot platform with cognitive memory architecture and multi-agent Skills, via OneBot V11."
readme = "README.md"
authors = [
Expand Down
2 changes: 1 addition & 1 deletion src/Undefined/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from .skills.registry import BaseRegistry as BaseRegistry
from .skills.tools import ToolRegistry as ToolRegistry

__version__ = "3.6.2"
__version__ = "3.6.3"

# symbol -> (module_path, attribute_name);首次访问时才 importlib 加载
_LAZY_IMPORTS: dict[str, tuple[str, str]] = {
Expand Down
8 changes: 4 additions & 4 deletions src/Undefined/ai/prompts/current_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,15 @@ def build_current_input_per_message_query_texts(
def _history_msg_matches_signature(
msg: dict[str, Any], signature: CurrentMessageSignature
) -> bool:
history_message_id = str(msg.get("message_id", "") or "").strip()
if signature.message_id and history_message_id:
return history_message_id == signature.message_id

sig_sender_id = signature.sender_id.strip()
sig_content = signature.content.strip()
if not sig_sender_id or not sig_content:
return False

history_message_id = str(msg.get("message_id", "") or "").strip()
if signature.message_id and history_message_id:
return history_message_id == signature.message_id

last_sender_id = str(msg.get("user_id", "") or "").strip()
last_content = str(msg.get("message", "") or "").strip()
if last_sender_id != sig_sender_id or last_content != sig_content:
Expand Down
8 changes: 8 additions & 0 deletions src/Undefined/attachments/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
RegisteredMessageAttachments,
RenderedRichMessage,
)
from Undefined.attachments.forward_snapshot import (
load_forward_snapshot,
save_forward_snapshot,
snapshot_forward_tree,
)
from Undefined.attachments.registry import AttachmentRegistry
from Undefined.attachments.render import (
dispatch_pending_file_sends,
Expand Down Expand Up @@ -40,8 +45,11 @@
"attachment_refs_to_xml",
"build_attachment_scope",
"dispatch_pending_file_sends",
"load_forward_snapshot",
"register_message_attachments",
"render_message_with_attachments",
"render_message_with_pic_placeholders",
"save_forward_snapshot",
"scope_from_context",
"snapshot_forward_tree",
]
Loading
Loading