Clawline — 03-21 移动端优先与协议修复¶
移动端 Agent 列表增强¶
网格/列表视图支持¶
Dad 决策:移动端 bot/agent 列表支持 grid 与 list 两种视图。
Bot 实现方案:
- 增加 viewMode state 管理
- Header 中加入切换按钮
- 统一 grouped/single-server/search result 三种渲染路径都支持 effectiveView
后续增强功能: - 默认 4 列网格布局 - 显示消息气泡预览 - 支持 typing 状态显示 - 自定义 agent 头像功能
移动端拖拽排序的技术突破¶
第一版方案(失败)¶
Bot 初始方案:移动端用"编辑模式 + 上下箭头"替代 HTML5 drag
Dad 反馈:真正需求是"每个 agent 都可拖拽排序",手机也要支持原生拖拽体验。
第二版方案(成功)¶
Bot 最终选型:使用 motion/react 的 Reorder.Group + Reorder.Item
选型理由: - 原生支持 touch drag,比 HTML5 drag 更适合移动端 - 提供流畅的动画效果 - API 简洁,易于集成
关键问题解决¶
死循环问题
- 根因:handleReorder 依赖 customOrder 导致无限重渲染
- 解决方案:改为 functional setState
状态持久化
- 问题:展开状态未持久化,页面切换后丢失
- 解决方案:expandedIds 持久化到 localStorage
测试局限性发现 - Playwright 模拟 drag 更像 mouse event,无法完全验证 touch drag - 需要真机测试验证移动端拖拽体验
里程碑成果¶
移动端支持真实触摸拖拽排序,展开状态可记忆,为后续的移动端优先策略提供了核心交互组件。
协议层重大问题修复¶
WebSocket 重连死循环¶
问题现象:在 Chats/ChatRoom 页面不断重复请求 agent.list.get,WS 连接反复重建。
根因分析:
1. useEffect 依赖 expandedIds,展开/折叠会触发重新请求
2. connection.open 事件再次调用 requestAgentList,与 ensureAgentsLoaded 叠加
3. ChatRoom 中多处无条件 channel.connect(),已连接状态下仍重复建连
解决方案:
- 去掉 useEffect 中 expandedIds 依赖
- 展开新 group 时只在 handleToggleGroup 中触发加载
- 移除按钮点击中的重复 ensureAgentsLoaded
- ChatRoom/history drawer 中增加连接状态判断
结果:循环请求与重连问题彻底消失。
消息发送失败问题解决¶
Dad 反馈:有 model 名字的 agent 能聊,没有 model 的不行。
根因分析:
- Token auth 场景下,前端错误生成了 fake chatId
- 过度激进的 guard:if (!currentChatId) throw 导致 failed to send
- sendRaw guard 还误伤了 agent.list.get 等无需 chatId 的包
最终修复策略:
- Token auth 时不再强制生成 fake chatId
- buildSocketUrl 在 chatId 为空时不追加该参数
- 从 serverUrl 中提取 channelId 作为兜底 chatId
- 仅对真正需要 chatId 的消息类型做 guard
Bot 自测验证:
- 使用 Dad 提供的 Eagle/Ottor 地址实测
- main 等无 model 字段的 agent 聊天功能恢复正常
- 确认历史中的长串 openclaw-web-agent-... 假 chatId 是旧 bug 遗留
自定义头像功能¶
Dad 决策:支持自定义 agent 头像。
Bot 实现细节:
- 头像 URL 存储在 localStorage
- 桌面端右键触发设置
- 移动端长按触发设置
- 列表卡片与网格卡片统一支持
这个功能为用户个性化 Agent 交互体验提供了基础。
技术架构要点¶
状态管理模式确立¶
// 多连接状态管理核心
agentMap[connectionId]
statusMap[connectionId]
loadingMap[connectionId]
expandedIds → localStorage 持久化
移动端优先的设计原则¶
- Touch drag 优于 mouse drag
- 44px 最小触控目标
- 状态持久化避免页面切换丢失
- 原生动画体验
协议层健壮性¶
- 连接状态判断避免重复建连
- 消息类型区分,避免过度 guard
- 兜底机制保证基础功能可用
为什么这一天是关键转折点?¶
1. 移动端体验质的提升 从"能用"到"好用",真正实现了移动端原生应用般的交互体验。
2. 协议层稳定性确立 解决了两个核心的连接和消息发送问题,为后续功能扩展提供了可靠基础。
3. 架构模式成型 多连接状态管理、移动端优先设计、协议层健壮性处理的模式在这一天基本确立,为后续开发提供了可遵循的范式。
4. 用户体验哲学确认 Dad 对"每个 agent 都可拖拽排序,手机也要支持"的坚持,体现了产品对移动端体验的高标准要求,这种用户体验哲学贯穿了后续所有开发工作。