# 异步上下文压缩插件：当前问题与处理状态总结

这份文档详细梳理了我们在处理 `async_context_compression`（异步上下文压缩插件）时，遭遇的“幽灵截断”问题的根本原因，以及我们目前的解决进度。

## 1. 根本原因：两种截然不同的“世界观”（数据序列化差异）

在我们之前的排查中，我曾错误地认为：`outlet`（后置处理阶段）拿到的 `body["messages"]` 是由于截断导致的残缺数据。
但根据您提供的本地运行日志，**您是对的，`body['messages']` 确实包含了完整的对话历史**。

那么为什么长度会产生 `inlet 看到 27 条`，而 `outlet 只看到 8 条` 这种巨大的差异？

原因在于，OpenWebUI 的管道在进入大模型前和从大模型返回后，使用了**两种完全不同的消息格式**：

### 视图 A：Inlet 阶段（原生 API 展开视图）
- **特点**：严格遵循 OpenAI 函数调用规范。
- **状态**：每一次工具调用、工具返回，都被视为一条独立的 message。
- **例子**：一个包含了复杂搜索的对话。
  - User: 帮我查一下天气（1条）
  - Assistant: 发起 tool_call（1条）
  - Tool: 返回 JSON 结果（1条）
  - ...多次往复...
  - **最终总计：27 条。**我们的压缩算法（trim）是基于这个 27 条的坐标系来计算保留多少条的。

### 视图 B：Outlet 阶段（UI HTML 折叠视图）
- **特点**：专为前端渲染优化的紧凑视图。
- **状态**：OpenWebUI 在调用完模型后，为了让前端显示出那个好看的、可折叠的工具调用卡片，强行把中间所有的 Tool 交互过程，用 `<details type="tool_calls">...</details>` 的 HTML 代码包裹起来，塞进了一个 `role: assistant` 的 `content` 字符串里！
- **例子**：同样的对话。
  - User: 帮我查一下天气（1条）
  - Assistant: `<details>包含了好多次工具调用和结果的代码</details> 今天天气很好...`（1条）
  - **最终总计：8 条。**

**💥 灾难发生点：**
原本的插件逻辑假定 `inlet` 和 `outlet` 共享同一个坐标系。
1. 在 `inlet` 时，系统计算出：“我需要把前 10 条消息生成摘要，保留后 17 条”。
2. 系统把“生成前10条摘要”的任务转入后台异步执行。
3. 后台任务在 `outlet` 阶段被触发，此时它拿到的消息数组变成了**视图 B（总共只有 8 条）。**
4. 算法试图在只有 8 条消息的数组里，把“前 10 条消息”砍掉并替换为 1 条摘要。
5. **结果就是：数组索引越界/坐标彻底错乱，触发报错，并且可能将最新的有效消息当成旧消息删掉（过度压缩）。**

---

## 2. 目前已解决的问题 (✅ Done)

为了立刻制止这种因为“坐标系错位”导致的数据破坏，我们已经落实了热修复（Local v1.4.0）：

**✅ 添加了“折叠视图”的探针防御：**
- 我写了一个函数 `_is_compact_tool_details_view`。
- 现在，当后台触发生成摘要时，系统会自动扫描 `outlet` 传来的 `messages`。只要发现里面包含 `<details type="tool_calls">` 这种带有 HTML 折叠标签的痕迹，就会**立刻终止并跳过**当前的摘要生成任务。
- **收益**：彻底杜绝了因数组错位而引发的任务报错和强制裁切。UI 崩溃与历史丢失问题得到遏制。

---

## 3. 当前已解决的遗留问题 (✅ Done: 逆向展开修复)

之前因为跳过生成而引入的新限制：**包含工具调用的长轮次对话，无法自动生成“历史摘要”** 的问题，现已彻底解决。

### 最终实施的技术方案：
我们通过源码分析发现，OpenWebUI 在进入 `inlet` 时会执行 `convert_output_to_messages` 还原工具调用链。因此，我们在插件的 `outlet` 阶段引入了相同的 **逆向展开 (Deflation/Unfolding)** 机制 `_unfold_messages`。

现在，当后台任务拿到 `outlet` 传来的折叠视图时，不会再选择“跳过”。而是自动提取出潜藏在消息对象体内部的原生 `output` 字段，并**将其重新展开为展开视图**（比如将 8 条假象重新还原为真实的 27 条底层数据），使得它的坐标系与 `inlet` 完全对齐。

至此，带有复杂工具调用的长轮次对话也能安全地进行背景自动压缩，不再有任何截断和强制删减的风险！