-
Notifications
You must be signed in to change notification settings - Fork 28
Expand file tree
/
Copy pathfeature_list.json
More file actions
1 lines (1 loc) · 10.8 KB
/
Copy pathfeature_list.json
File metadata and controls
1 lines (1 loc) · 10.8 KB
1
{"project": "MobileClaw", "description": "带眼睛的龙虾对讲机 — iOS/Android 多模态语音+视觉 OpenClaw 移动端客户端。语音唤醒 → 相机+麦克风同时激活 → 实时画面+语音发给 openclaw → AI 回复 + TTS 播放", "features": [{"id": "feat-01", "category": "foundation", "priority": 1, "description": "修复 npm 缓存权限问题,确保 pnpm install 正常工作,项目可编译运行", "file": "package.json", "steps": ["确认 node_modules 存在且完整(17 个包)", "运行 npx expo prebuild --clean --platform ios 确认原生项目可生成", "运行 npx expo start --dev-client 确认 Metro bundler 启动无报错"], "passes": true, "verification": "pnpm install 无报错,node_modules/react-native-vision-camera 等核心依赖存在"}, {"id": "feat-02", "category": "gateway", "priority": 2, "description": "GatewayClient 对接本地 openclaw :18787,完成真实连接握手和 RPC 调用测试", "file": "src/services/gateway/GatewayClient.ts", "steps": ["修复 GatewayClient 中 crypto.randomUUID() 调用(应改用 uuid 库)", "在 WakeUpManager.sendUserMessage 中修复动态 import 为静态导入", "编写测试脚本:连接本地 openclaw gateway,发送 handshake,调用 health RPC", "验证 challenge → connect(token) → hello-ok 完整认证流程通过", "验证 rpc('send', {message: 'hello'}) 能收到 AI 回复", "验证断线后自动重连(指数退避+抖动)正常工作", "验证心跳/tick 检测机制不误判死连接"], "passes": true, "verification": "能连上本地 openclaw:18789,handshake 成功(Ed25519设备身份+v3签名),chat.send 收到AI回复('Hey! I am here and ready to go'),health RPC正常,断线重连成功"}, {"id": "feat-03", "category": "camera", "priority": 3, "description": "集成 react-native-vision-camera 实现真实相机预览和 Frame Processor 帧捕获", "file": "src/components/camera/CameraPreview.tsx", "steps": ["创建 CameraPreview.tsx 组件:使用 <Camera> + useFrameProcessor 挂载相机", "创建 frameProcessorWorklet.ts:实现离线线程 Worklet,JPEG 编码(quality=0.7),缩放到 640x480,节流到 15fps", "关键:每个 frame 必须调用 frame.close() 防止内存泄漏", "将 Worklet 输出通过 runOnJS 回调到 JS 层", "在 SessionScreen 中替换 cameraPlaceholder 为真实 CameraPreview 组件", "添加相机权限请求逻辑(首次启动时弹窗)", "真机测试:帧率稳定 15fps,内存不增长,10 分钟不崩溃"], "passes": true, "verification": "SessionScreen 显示真实相机画面,frameSender 收到 JPEG 数据,控制台显示帧率计数器递增"}, {"id": "feat-04", "category": "camera-send", "priority": 4, "description": "实现双策略视频帧发送:Strategy A(快照附在 send 消息)+ Strategy B(连续 video_frame 事件流)", "file": "src/services/camera/frameSender.ts", "steps": ["实现 Strategy A:cameraManager.onNewFrame 回调缓存最新 JPEG 到 latestFrame", "实现 Strategy B:startContinuousStream() 以 5fps 发送 event: video_frame(base64_jpeg payload)", "在 WakeUpManager.sendUserMessage 中集成 Strategy A:发送消息时附带 cameraManager.latestFrame", "确保 Strategy A 和 Strategy B 可独立开关(配置项 video.strategy)", "验证:用户说话时 send 消息携带图片字段", "验证:激活状态下持续收到 video_frame 事件(可在 gatewayClient.onEvent 监听)"], "passes": true, "verification": "openclaw 后端收到的 send 消息包含 image 字段(base64 JPEG),video_frame 事件持续推送"}, {"id": "feat-05", "category": "audio", "priority": 5, "description": "实现音频录制管线:AudioSession 配置 + PCM 采集 + 音频可视化波形", "file": "src/services/audio/AudioManager.ts", "steps": ["实现 AudioSession 原生模块(iOS: AVAudioSession playAndRecord + voiceChat mode)", "配置正确选项:allowBluetooth, allowBluetoothA2DP, defaultToSpeaker, preferredSampleRate=16000", "Android 端:MODE_IN_COMMUNICATION + bluetoothScoOn + speakerphoneOn", "实现音频采集:使用 expo-av 或原生模块获取 PCM 数据流", "创建 WaveformView 组件:实时显示麦克风音量电平", "在 SessionScreen 录制状态叠加层中嵌入 WaveformView", "验证:录音时波形动起来,TTS 播放时波形停止(半双工切换)"], "passes": true, "verification": "SessionScreen 录制状态显示动态波形图,音量变化时波形振幅响应"}, {"id": "feat-06", "category": "asr", "priority": 6, "description": "接入豆包流式 ASR:PCM 音频 → 豆包 WS API → 中间/最终转录文本 → UI 显示 + 自动发消息给 openclaw", "file": "src/services/audio/ASRService.ts", "steps": ["研究豆包流式 ASR API 文档(WebSocket 接口、鉴权、音频格式要求)", "实现 DoubaoASRProvider.initialize(): 连接豆包 ASR WebSocket endpoint", "实现 DoubaoASRProvider.startListening(): 流式发送 PCM 音频块", "处理 interim 结果:更新 UI 的 currentTranscript(蓝色打字光标)", "处理 final 结果:自动 commitTranscript + 调用 sendUserMessage 发给 openclaw", "ASR 错误时显示错误提示,支持重试", "Settings 页面可配置豆包 API Key 和 endpoint"], "passes": true, "verification": "说话时 TranscriptBubble 实时显示中间结果(带 ▊ 光标),说完后自动变为固定文本并触发 AI 回复"}, {"id": "feat-07", "category": "tts", "priority": 7, "description": "实现双路径 TTS:Path A(openclaw tts.convert RPC)+ Path B(Edge TTS 本地合成),半双工模式切换", "file": "src/services/audio/TTSService.ts", "steps": ["实现 EdgeTTSProvider:调用微软 Edge TTS REST API 合成音频", "实现音频播放:将合成的 PCM/MP3 数据通过 AVAudioPlayer 或 React Native Sound 播放", "TTSService.speak() 根据 config.tts.type 选择路径 A 或路径 B", "AI 回复到达时自动触发 TTS 播放(观察 aiResponseText 变化或监听 store)", "半双工:TTS 播放时暂停 ASR(isTTSSpeaking=true → stopListening),播完恢复", "ResponseBubble 中 TTS 播放时显示波形动画(▰▰▰▱▱▱ 效果)", "Settings 页面可选择 TTS 提供者(openclaw / edge / doubao)和语速"], "passes": true, "verification": "AI 回复后自动听到语音播放,播放时 ASR 暂停,播放完 ASR 恢复,波形动画可见"}, {"id": "feat-08", "category": "wake", "priority": 8, "description": "实现 iOS Siri Shortcut 语音唤醒:URL scheme mobileclaw://activate + 完整激活链路", "file": "src/services/wake/WakeUpManager.ts", "steps": ["在 ios/MobileClaw/AppDelegate.swift 中注册 URL scheme handler(mobileclaw://activate)", "唤醒时解析 URL 参数,post NotificationName('MobileClawActivateFromURL')", "RN 端通过 NativeEventEmitter 监听激活通知,触发 wakeUpManager.activate()", "实现 idle timeout:30 秒无语音活动自动 deactivate(省电)", "idle warning 在 25s 时显示倒计时(23s to idle)", "点击 SessionScreen 关闭按钮或 ⏸ 停止按钮时 graceful deactivate", "备用:HomeScreen 大按钮 Tap to Talk 也走同一 activate() 链路"], "passes": true, "verification": "Siri 说 'Hey Siri, 打开爪子' → App 前台激活 → 相机+麦克风+WS 全部启动 → SessionScreen 显示 → 30s 无操作自动回待机"}, {"id": "feat-09", "category": "storage", "priority": 9, "description": "实现 SecureStorage 原生模块:iOS Keychain / Android Keystore 安全存储 Gateway Token 和 API Key", "file": "src/services/storage/SecureStorage.ts", "steps": ["创建 iOS TurboModule:封装 Security/SecItemAdd + SecItemCopyMatching(kSecClassGenericPassword)", "创建 Android TurboModule:封装 EncryptedSharedPreferences(MasterKey AES256_GCM)", "service name 设为 com.mobileclaw.keystore", "替换当前 XOR 混淆占位实现为真正的原生安全存储", "迁移 ConfigStore 和 SettingsScreen 使用新的 SecureStorage", "验证:Token 写入后 App 重启仍可读出,不会明文存储在文件系统中"], "passes": true, "verification": "Settings 页面保存 Token 后重启 App Token 仍在,keychain 中可见 com.mobileclaw.keystore 条目"}, {"id": "feat-10", "category": "ui-polish", "priority": 10, "description": "UI 打磨:暗色主题完善、动画效果、错误处理、Gateway CRUD 交互优化", "file": "src/screens/SettingsScreen.tsx", "steps": ["SessionScreen:相机预览区添加红色脉冲边框(isCameraActive 时)", "SessionScreen:添加下滑手势快速 deactivate", "HomeScreen:未配置 Gateway 时显示引导动画(非空白态)", "SettingsScreen:添加 Gateway 编辑功能(不只是删除)", "SettingsScreen:Token 输入框改为 secureTextEntry 样式(显示为 ••••)", "全局错误处理:网络断开/认证失败/权限拒绝 时显示 ErrorBanner", "添加 Loading 状态:连接中/唤醒中的骨架屏或 spinner", "适配 iPhone SE 到 iPhone 15 Pro Max 不同屏幕尺寸"], "passes": true, "verification": "暗色主题一致,所有屏幕在不同 iPhone 尺寸上布局正常,错误提示友好"}, {"id": "feat-11", "category": "feishu", "priority": 11, "description": "飞书历史记录推送:每轮对话完成后推送到飞书 webhook,含离线重试队列", "file": "src/services/history/FeishuPushService.ts", "steps": ["修复 FeishuPushService 中循环依赖问题(useAppStore 动态 require 改为顶层 import)", "实现 Feishu 卡片 JSON schema:header(蓝底白字)+ 元信息行 + 用户/AI 消息体", "在 WakeUpManager.deactivate() 之前调用 FeishuPushService.pushTurn() 推送本轮对话", "离线时入队 MessageQueue(AsyncStorage 持久化),指数退避重试(5s→15s→45s→5min)", "Settings 页面添加 Test 按钮:手动发送测试卡片到飞书", "验证:对话完成后飞书收到卡片,包含时间戳/用户原文/AI 回复/是否有画面/时长"], "passes": true, "verification": "跟龙虾说句话并得到回复后,飞书频道收到一张卡片,内容完整准确"}, {"id": "feat-12", "category": "integration", "priority": 12, "description": "端到端集成测试:完整唤醒→流媒体→对话→自动待机流程跑通,真机 10 分钟稳定性验证", "file": "src/App.tsx", "steps": ["完整流程测试:Siri 唤醒 → 连接 openclaw → 相机预览 + ASR 监听 → 说话 → AI 回复 → TTS 播放 → 自动待机", "边界测试:WiFi 断开后重连、App 切后台后恢复、来电中断后恢复、权限中途拒绝", "电量测试:10 分钟连续运行消耗 < 15% 电量", "内存泄漏测试:Instruments/Profiler 观察 frame.close() 是否每次都调用", "多轮对话测试:连续 5 轮 speak→reply→speak 不崩溃、状态正确重置", "修复集成测试中发现的所有 bug"], "passes": true, "verification": "真机上完整流程一次通过,10 分钟无崩溃,电量 < 15%,断网自动重连"}]}