threepointone/agent-recovery-viz
GitHub: threepointone/agent-recovery-viz
Cloudflare Agents 聊天恢复系统的交互式离散事件可视化模拟器,帮助开发者理解故障注入后恢复引擎的分类与修复决策过程。
Stars: 1 | Forks: 0
# 恢复实验室
Cloudflare Agents 聊天恢复系统的交互式可视化。这是一个离散事件模拟器,可让您观察聊天轮次在系统中的流转过程,注入故障(客户端断开连接、Durable Object 驱逐),并查看恢复引擎如何对中断的轮次进行分类和修复。
基于 React 19、Tailwind v4、[Kumo](https://www.npmjs.com/package/@cloudflare/kumo)(Cloudflare 的设计系统)和 Framer Motion 构建。纯静态前端——无服务器、无 Workers、无构建时代码生成。
## 功能介绍
- **观察聊天轮次的生命周期**:在多轨道时间轴(客户端 WebSocket、fiber、stream、工具、预算)上展开
- **在任意节点注入故障**:断开客户端连接、驱逐 Durable Object、在工具执行中途将其终止,或触发部署
- **查看分类器决策**:当 DO 被驱逐时,7 分支恢复分类器会按优先级顺序评估条件并选择恢复操作。动画覆盖层会显示每个条件检查和所选的路径。
- **检查内部状态**:持久化状态(SQLite 表、DO 存储)与易失性状态(内存中)分开显示。持久化状态在驱逐后依然存活;易失性状态会丢失。这是关键的视觉展示:您可以清楚地看到恢复系统保护了什么。
- **浏览时间轴**:将播放头拖动到任意位置,查看该时刻重构的状态
- **8 个预设场景**:涵盖每一条恢复路径,且支持在任何场景中手动注入故障
## 运行方式
```
npm install
npm run dev
```
打开输出的 URL。
构建生产环境版本:
```
npm run build # outputs to dist/
npm run preview # serve the production build locally
```
`dist/` 文件夹是完全静态的——将其部署到任何静态托管平台(Cloudflare Pages、Netlify、Vercel、GitHub Pages、S3 等)。
## 可视化的恢复路径
分类器严格按照优先级顺序评估条件(匹配即停止):
| # | 条件 | 恢复操作 | 后续处理 |
|---|---|---|---|
| 1 | 未产生输出 | **重试轮次** (Retry Turn) | 丢弃中断的 fiber,从用户消息处重新运行 |
| 2 | 等待人工批准 | **等待人工介入** (Park for Human) | 等待——不消耗预算,无进度损失 |
| 3 | 上一个工具已结算 | **保留工具结果** (Preserve Tool Result) | 复用持久化的结果,跳过重新执行 |
| 4 | 子 agent (facet) 正在运行 | **重新附加子节点** (Reattach Child) | 查找子节点的持久化 runId,重新附加到其结果上 |
| 5 | 工具调用进行中(未结算) | **修复记录** (Repair Transcript) | 移除悬空条目,从头重试该工具 |
| 6 | 部分文本已流式传输 | **继续部分传输** (Continue Partial) | 从持久化的分块中重构,恢复流式传输 |
| 7 | 无匹配条件 | **等待 Provider** (Wait on Provider) | Stream 停止响应——等待并监控是否有正向进展 |
## 项目结构
```
src/
client.tsx # Entry point — renders RecoveryLab + ModeToggle
styles.css # Tailwind v4 + Kumo + viz CSS variables
sim/
types.ts # All simulation types, enums, track configs
classifier.ts # 7-branch classifier + RECOVERY_INFO metadata
scenarios.ts # 8 preset scenarios + SCENARIO_MAP
useRecoverySim.ts # Simulation engine: computeSnapshot, playback hook
components/
RecoveryLab.tsx # Root layout: header, timeline, panels
Timeline.tsx # Multi-track timeline + budget bar + scrubbing
FailureControls.tsx # 4 chaos buttons (disconnect, evict, kill, deploy)
ClassifierOverlay.tsx # Animated decision tree modal
StateInspector.tsx # Durable (blue) vs volatile (orange) state panels
DESIGN.md # Design system spec (colors, typography, motion)
public/
favicon.ico
```
## 模拟工作原理
引擎是一个**离散事件模拟器**。事件带有时间戳并按时间轴排序。播放头以可配置的速度(0.5 倍–4 倍)在事件中推进。系统通过对当前时间之前的所有事件进行重放来计算快照(派生状态)——`computeSnapshot()` 是一个纯函数,它对事件列表进行折叠(fold)操作。
当注入故障时,引擎会执行以下操作:
1. 计算当前时间的新快照
2. 在该快照上运行真实的分类器逻辑 (`classify()`)
3. 生成恢复事件 (`computeRecoveryEvents()`),并使用稳定排序将它们合并到时间轴中
当播放头到达 `classify` 事件时,模拟会自动暂停,以便用户可以在继续之前阅读分类器覆盖层的内容。
### 双层恢复
可视化展示区分了两个恢复层:
- **Stream 恢复**(客户端断开连接,DO 存活)—— WebSocket 掉线,但 Durable Object 继续进行流式传输。重新连接时,会从 SQLite 重放缓冲的分块。无需 fiber 恢复。
- **Fiber 恢复**(DO 驱逐,isolate 终止)—— 所有内存中的状态都会丢失。恢复引擎会扫描处于“running”状态的 fiber,由分类器决定后续操作,并通过触发定时器来执行恢复动作。
### 持久化状态与易失性状态
| 持久化(在驱逐后存活) | 易失性(在驱逐后丢失) |
|---|---|
| `cf_ai_chat_agent_messages` (SQLite) | WebSocket 连接 |
| `cf_ai_chat_stream_chunks` (SQLite) | Stream 控制器 |
| `cf:chat:recovering` (DO 存储) | Fiber 执行状态 |
| `cf:chat:last-terminal` (DO 存储) | 内存中的工具 promise |
| `cf:chat-recovery:incident:*` (DO 存储) | 进度预算计数器 |
状态检查面板并排展示了这两种状态——持久化状态使用蓝色修饰,易失性状态使用橙色修饰。当 isolate 被替换时,易失性状态面板的透明度会降至 50%,并显示警告横幅。
## 技术栈
- **React 19** 与 TypeScript(严格模式,禁用 `as any` 或 `@ts-ignore`)
- **Tailwind v4** 通过 `@tailwindcss/vite` 集成
- **Kumo** (`@cloudflare/kumo`) —— Cloudflare 的设计系统
- **Framer Motion** 用于动画(GPU 合成:仅限 transform/opacity)
- **Phosphor Icons** 用于图标设计
- **Vite 8** 用于开发服务器和构建
## 设计系统
所有可视化特定的 token 都使用 `light-dark()` CSS 函数,并继承了 Kumo 的 `data-mode` 属性系统。默认采用暗黑模式。
有关完整的规范——颜色 token、排版、间距、组件模式和动画指南——请参阅 [DESIGN.md](./DESIGN.md)。
Cloudflare Agents 聊天恢复系统的交互式可视化。这是一个离散事件模拟器,可让您观察聊天轮次在系统中的流转过程,注入故障(客户端断开连接、Durable Object 驱逐),并查看恢复引擎如何对中断的轮次进行分类和修复。
基于 React 19、Tailwind v4、[Kumo](https://www.npmjs.com/package/@cloudflare/kumo)(Cloudflare 的设计系统)和 Framer Motion 构建。纯静态前端——无服务器、无 Workers、无构建时代码生成。
## 功能介绍
- **观察聊天轮次的生命周期**:在多轨道时间轴(客户端 WebSocket、fiber、stream、工具、预算)上展开
- **在任意节点注入故障**:断开客户端连接、驱逐 Durable Object、在工具执行中途将其终止,或触发部署
- **查看分类器决策**:当 DO 被驱逐时,7 分支恢复分类器会按优先级顺序评估条件并选择恢复操作。动画覆盖层会显示每个条件检查和所选的路径。
- **检查内部状态**:持久化状态(SQLite 表、DO 存储)与易失性状态(内存中)分开显示。持久化状态在驱逐后依然存活;易失性状态会丢失。这是关键的视觉展示:您可以清楚地看到恢复系统保护了什么。
- **浏览时间轴**:将播放头拖动到任意位置,查看该时刻重构的状态
- **8 个预设场景**:涵盖每一条恢复路径,且支持在任何场景中手动注入故障
## 运行方式
```
npm install
npm run dev
```
打开输出的 URL。
构建生产环境版本:
```
npm run build # outputs to dist/
npm run preview # serve the production build locally
```
`dist/` 文件夹是完全静态的——将其部署到任何静态托管平台(Cloudflare Pages、Netlify、Vercel、GitHub Pages、S3 等)。
## 可视化的恢复路径
分类器严格按照优先级顺序评估条件(匹配即停止):
| # | 条件 | 恢复操作 | 后续处理 |
|---|---|---|---|
| 1 | 未产生输出 | **重试轮次** (Retry Turn) | 丢弃中断的 fiber,从用户消息处重新运行 |
| 2 | 等待人工批准 | **等待人工介入** (Park for Human) | 等待——不消耗预算,无进度损失 |
| 3 | 上一个工具已结算 | **保留工具结果** (Preserve Tool Result) | 复用持久化的结果,跳过重新执行 |
| 4 | 子 agent (facet) 正在运行 | **重新附加子节点** (Reattach Child) | 查找子节点的持久化 runId,重新附加到其结果上 |
| 5 | 工具调用进行中(未结算) | **修复记录** (Repair Transcript) | 移除悬空条目,从头重试该工具 |
| 6 | 部分文本已流式传输 | **继续部分传输** (Continue Partial) | 从持久化的分块中重构,恢复流式传输 |
| 7 | 无匹配条件 | **等待 Provider** (Wait on Provider) | Stream 停止响应——等待并监控是否有正向进展 |
## 项目结构
```
src/
client.tsx # Entry point — renders RecoveryLab + ModeToggle
styles.css # Tailwind v4 + Kumo + viz CSS variables
sim/
types.ts # All simulation types, enums, track configs
classifier.ts # 7-branch classifier + RECOVERY_INFO metadata
scenarios.ts # 8 preset scenarios + SCENARIO_MAP
useRecoverySim.ts # Simulation engine: computeSnapshot, playback hook
components/
RecoveryLab.tsx # Root layout: header, timeline, panels
Timeline.tsx # Multi-track timeline + budget bar + scrubbing
FailureControls.tsx # 4 chaos buttons (disconnect, evict, kill, deploy)
ClassifierOverlay.tsx # Animated decision tree modal
StateInspector.tsx # Durable (blue) vs volatile (orange) state panels
DESIGN.md # Design system spec (colors, typography, motion)
public/
favicon.ico
```
## 模拟工作原理
引擎是一个**离散事件模拟器**。事件带有时间戳并按时间轴排序。播放头以可配置的速度(0.5 倍–4 倍)在事件中推进。系统通过对当前时间之前的所有事件进行重放来计算快照(派生状态)——`computeSnapshot()` 是一个纯函数,它对事件列表进行折叠(fold)操作。
当注入故障时,引擎会执行以下操作:
1. 计算当前时间的新快照
2. 在该快照上运行真实的分类器逻辑 (`classify()`)
3. 生成恢复事件 (`computeRecoveryEvents()`),并使用稳定排序将它们合并到时间轴中
当播放头到达 `classify` 事件时,模拟会自动暂停,以便用户可以在继续之前阅读分类器覆盖层的内容。
### 双层恢复
可视化展示区分了两个恢复层:
- **Stream 恢复**(客户端断开连接,DO 存活)—— WebSocket 掉线,但 Durable Object 继续进行流式传输。重新连接时,会从 SQLite 重放缓冲的分块。无需 fiber 恢复。
- **Fiber 恢复**(DO 驱逐,isolate 终止)—— 所有内存中的状态都会丢失。恢复引擎会扫描处于“running”状态的 fiber,由分类器决定后续操作,并通过触发定时器来执行恢复动作。
### 持久化状态与易失性状态
| 持久化(在驱逐后存活) | 易失性(在驱逐后丢失) |
|---|---|
| `cf_ai_chat_agent_messages` (SQLite) | WebSocket 连接 |
| `cf_ai_chat_stream_chunks` (SQLite) | Stream 控制器 |
| `cf:chat:recovering` (DO 存储) | Fiber 执行状态 |
| `cf:chat:last-terminal` (DO 存储) | 内存中的工具 promise |
| `cf:chat-recovery:incident:*` (DO 存储) | 进度预算计数器 |
状态检查面板并排展示了这两种状态——持久化状态使用蓝色修饰,易失性状态使用橙色修饰。当 isolate 被替换时,易失性状态面板的透明度会降至 50%,并显示警告横幅。
## 技术栈
- **React 19** 与 TypeScript(严格模式,禁用 `as any` 或 `@ts-ignore`)
- **Tailwind v4** 通过 `@tailwindcss/vite` 集成
- **Kumo** (`@cloudflare/kumo`) —— Cloudflare 的设计系统
- **Framer Motion** 用于动画(GPU 合成:仅限 transform/opacity)
- **Phosphor Icons** 用于图标设计
- **Vite 8** 用于开发服务器和构建
## 设计系统
所有可视化特定的 token 都使用 `light-dark()` CSS 函数,并继承了 Kumo 的 `data-mode` 属性系统。默认采用暗黑模式。
有关完整的规范——颜色 token、排版、间距、组件模式和动画指南——请参阅 [DESIGN.md](./DESIGN.md)。标签:Cloudflare, Framer Motion, MITRE ATT&CK, React, Syscalls, 前端可视化, 状态恢复, 离散事件模拟器, 自动化攻击