ClawCraft

OpenClaw 的 RTS(即时战略)风格图形配置管理界面,通过城堡/领主/探险者/建筑等隐喻可视化 Agent 生态系统。

概述

ClawCraft 是一个基于 PixiJS 2D Canvas 的 OpenClaw 图形管理界面,采用 RTS 游戏风格将 Agent、Gateway、Channel、Model 等概念映射为城堡建筑系统。用户可以通过拖拽建筑、点击面板来管理 OpenClaw 的配置。项目由 craftbot 开发维护。

技术栈

  • 前端:React 18 + TypeScript + PixiJS + Zustand + Tailwind CSS + Vite
  • 后端:OpenClaw Gateway 插件(Node.js/TypeScript)
  • 认证:Logto OAuth(@logto/react)
  • 部署:Caddy + SCP + pm2

项目规模

  • 前端 67 文件 / ~16,800 行
  • 后端插件 ~2,675 行
  • 总计 ~19,500+ 行
  • 54 个配置域 100% 覆盖
  • 版本:v0.9.5-dev

核心架构

数据对接

前端通过 3 个通道对接后端(Gateway 插件):

通道端点用途
SSE 长连接/clawcraft/events实时推送状态变更
全量快照/clawcraft/state连接后拉取完整状态
配置读取/clawcraft/config管理面板读取配置(密钥脱敏)

数据流程

  1. 页面加载 → useSSE('/clawcraft/events') 建立 SSE 连接
  2. SSE 收到 connected 事件 → fetch('/clawcraft/state') 拉全量快照写入 Zustand store
  3. 后续 SSE 推送 state-update 增量 delta → applyDelta() 局部更新
  4. 面板操作 → 各自 fetch /clawcraft/config/clawcraft/action

插件注册

ClawCraft 作为 OpenClaw 插件运行,注册了 11 个 HTTP 路由和 9 个 hooks。插件位于 ~/.openclaw/extensions/clawcraft/(非 workspace/plugins/)。

RTS 隐喻体系

概念RTS 隐喻说明
Gateway城堡/主城核心入口,显示领主数/探险者数/频道数
Agent领主每个 Agent 对应一个建筑
Channel频道建筑Mattermost/WhatsApp 等
Model Provider模型熔炉显示提供商和模型列表
Binding绑定Agent 与 Channel 的关联
Session探险者活跃会话

交互系统

  • 建筑拖拽:PixiJS Canvas 内拖拽调整布局,pointerup 时保存位置
  • 面板系统:15 个 lazy-loaded 面板(Gateway/Channel/Model/Agent/Activity/Chat 等)
  • 对话功能:可直接与 Agent 聊天,支持多轮对话、Session 切换、消息持久化
  • 事件日志:实时显示系统事件,默认折叠
  • 音效系统soundManager 提供 hover/select/event/error/complete 音效
  • 城墙工具:围墙绘制/清除功能
  • 快捷栏:底部功能快捷入口

代码质量审查结果

审查后的质量评分:81/100

已修复问题(21+7 项):

类别修复内容
XSSdangerouslySetInnerHTML → react-markdown
ARIA16 处 aria/role 属性
移动端min-width:1280px → sm:hidden 全屏提示
性能authFetch token 缓存 55s TTL
代码结构WorldCanvas 拆分 (1912→1153+775)
Markdownreact-markdown 替换手写 regex
安全focus trap + StrictMode 条件化
样式ErrorBoundary + Skeleton 统一 + StyledSelect + theme.ts

正面发现

  • RTS 隐喻一致性优秀,贯穿始终
  • PixiJS Canvas 性能优秀(ticker 内用 getState(),不触发 React re-render)
  • 代码分割好(15 个 lazy-loaded 面板,manualChunks)
  • Zustand store 设计合理(89 处精确 selector)

重大 Bug 历史

SSE 无限重连死循环(2026-03-20)

症状:页面加载或拖拽建筑时界面卡死,SSE 连接疯狂创建(250+ 个)

根因链

  1. authFetch 调用 Logto getAccessToken()
  2. Logto 内部 proxy() 每次调用 setIsLoading(true/false) 修改 React Context
  3. Context 变化触发整个组件树 re-render
  4. ProtectedRoute 在 isLoading 时 unmount App → 所有 Effect cleanup
  5. App remount → 新 SSE 连接 → 又调 getAccessToken → 死循环

修复:SSE 和 fetchSnapshot 移除 getAccessToken 调用;useSSE effect 依赖改为 [];module-level 防重入锁。

对话消息消失(2026-03-17)

根因loadChatHistory 在流式响应过程中被触发,用空数组覆盖已有消息。

修复:5 处代码修改,包括 loadChatHistory 防重入、空结果不覆盖、session key 匹配修正。

部署环境

生产环境

组件位置
服务器owl (4.193.115.141:18822, user restry)
前端~/clawcraft/frontend/ → Caddy 静态文件
插件~/.openclaw/extensions/clawcraft/
Gatewaysystemd service,端口 18789
Caddycraft.clawlines.net → 静态文件 + API 反代
HTTPSLet’s Encrypt 自动管理

开发环境

组件位置
架构clawedbot Caddy → owl:18852 全量反代
域名craft.dev.dora.restry.cn
前端源码poc/frontend/src/
插件源码poc/plugin/
pm2dev-craft (:3010 静态 dist)
vite dev:4010(按需启动)

停用域名

  • clawcraft.octopus-ops.net — 已停用(2026-03-18)

安全注意事项

🔴 开发环境安全债务

  • Gateway auth 设为 none(仅 loopback 绑定)
  • 插件 CLAWCRAFT_AUTH_SKIP=true 跳过 Logto 认证
  • 功能开发完成后需恢复:Logto JWT + Gateway auth 统一方案

时间线

  • 2026-03-11~15: 概念到全覆盖(5 天),54 配置域 100%
  • 2026-03-17: 8 轮 UX 迭代 + 核心 Bug 修复
  • 2026-03-18: 测试服迁移至 owl + Monorepo 重构 + 部署
  • 2026-03-19: Logto JWT 认证集成
  • 2026-03-20: SSE 死循环修复 + 25 项审查优化
  • 2026-03-24: 项目稳定,v0.9.5-dev

相关主题