5df99ced7b
feat(M2.1): Web 端语音录放闭环
...
1. 新增 GET /api/chat/audio/file?path=<tmp_dir内路径> 路由
- 路径白名单:canonicalize 后必须位于 config.ai.tmp_dir 内
- 返回 audio/wav 二进制流(浏览器可直接 <audio> 播放)
- 60s 后自动清理临时文件
- 修复:原 /download/:filename 只能读 downloads_dir,TTS 输出在 tmp_dir 无法访问
2. POST /api/chat/audio 支持 X-Audio-Format 头
- 浏览器 MediaRecorder 产 webm/ogg/m4a,whisper-cli 靠扩展名判断格式
- 服务端按头指示决定文件扩展名(webm/ogg/m4a/mp3/wav)
3. chat.html 录音 UI + 客户端 WAV 转码
- 按住🎙按钮录音(MediaRecorder),松开发送
- 客户端用 Web Audio API 解码 + 重采样到 16k 单声道 PCM16
- 手写 WAV header,输出标准 16k mono wav(whisper-cli 直接可处理)
- 非安全上下文(HTTP)下禁用录音并显示 Chrome flag 启用指引
- 回复音频改用 /api/chat/audio/file 路径播放
- 显示 ASR 转写文本(🎤 你说: xxx)
2026-07-06 14:18:17 +08:00
8617a0e708
feat(M2.1): Web UI 统一入口+角色类型策略+Live2D 渲染支持+Gemma4 清单
...
- chat.html: 统一入口, 当前角色信息条, 四种角色类型策略 (pet/human/singer/live2d)
- 对话时根据 render_type 触发不同策略: video 切 talk/idle, live2d 显示动效
- config.rs: 新增 CharacterType::Live2d + RenderType 枚举 + live2d_model/live2d_config 字段
- model_manager.rs: 默认清单加 Gemma 4 E2B Q4_K_M (下载链接, 不含文件)
2026-07-06 12:49:46 +08:00
0c625a0c9a
fix: 模型文件不进 git (加 .gitignore, 从索引移除 3.2GB gguf)
...
模型文件通过 model_manager.rs 清单里的 URL 在线下载,
不随 git 仓库分发。.gitignore 新增 model_download/ model_store/。
2026-07-06 12:41:36 +08:00
0ac4aa31c8
feat(M2.1): Web 对话控制端 (/chat 页面 - 文字对话+角色切换+模型管理)
2026-07-06 10:24:34 +08:00
2f202b82b7
fix: dog 配置 flip_vertical 改为 false (画面上下反了)
2026-07-06 09:51:39 +08:00
b0e201a16f
fix: 清理真正的退格符 \u{8} (llama-cli 进度动画)
2026-07-04 17:39:42 +08:00
15ab383603
fix: 编译错误 (\b 转义 + 临时变量生命周期)
2026-07-04 17:35:45 +08:00
9069145de6
fix: 解析 llama-cli 进度动画和回复在同一行的情况 (清理 \b 转义)
2026-07-04 17:28:06 +08:00
1c037db0c2
fix: 解析 llama-cli 输出,只提取生成回复 (去除 banner/进度动画/统计)
2026-07-04 17:18:58 +08:00
a3052ad6db
fix: piper 加 ESPEAK_DATA_PATH 环境变量 (espeak-ng-data 目录)
2026-07-04 17:10:23 +08:00
dc20fd3502
fix: piper_lib_dir 修正为 piper/piper 子目录 (库文件实际位置)
2026-07-04 17:04:21 +08:00
4fd7e7997e
fix: piper 二进制+依赖库+config 修正 (符号链接指向正确二进制,加 LD_LIBRARY_PATH 和 -c 参数)
2026-07-04 16:58:41 +08:00
706b1375ce
fix: llama-cli 加 --single-turn --no-warmup -sys,对齐 spike 调用方式 (修复卡死)
2026-07-04 16:39:33 +08:00
8fc82813d3
fix: ensure_default_models 每次启动重新检查模型文件存在性
2026-07-04 16:02:42 +08:00
6810d1ca13
feat(M2.1): 设备端部署脚本 + whisper LD_LIBRARY_PATH + dog/cat 角色人设配置
2026-07-04 15:44:48 +08:00
4877d54a1c
fix: 修复 main.rs config move 后借用错误 (提前提取 ai 配置)
2026-07-04 15:12:16 +08:00
1bb044a3d7
fix: 修复 M2.1 骨架编译错误 (import/match/AppConfig 字段)
2026-07-04 15:09:11 +08:00
a0c4ca2307
feat(M2.1): AI 语音对话插件骨架 + 模型管理 + HTTP API + config schema 扩展
...
这是 M2.1(语音数字生命 V1)的后端骨架实现,不含 Web UI / Flutter / 设备部署。
新增文件:
- src/plugins/ai/mod.rs: AiPlugin 薄层(持有 ChatPipeline Arc,处理消息系统联动)
- src/plugins/ai/backend.rs: AiBackend trait + LocalCliBackend (whisper-cli/llama-cli/piper 子进程)
+ CloudBackend 占位(V1 返回"暂未支持")
- src/plugins/ai/chat.rs: ChatPipeline 对话管线执行器(HTTP 层 spawn_blocking 直接调用)
- src/plugins/ai/model_manager.rs: ModelManager 模型资产管理
(清单/下载/切换/删除/配额/档位守门,参照 plugin_repo + version_manager 模式)
修改文件:
- src/core/message.rs: 新增 ChatRequest/ChatResponse/AiModelEvent 消息类型
- src/core/config.rs: AppConfig 新增 character 块(角色元信息+人设)+ ai 块(后端配置)
均为 #[serde(default)] 向后兼容旧配置
- src/plugins/mod.rs: 注册 ai 模块
- src/plugins/http/mod.rs: HttpState 新增 ai_pipeline + ai_models 字段及注册方法;
HttpPlugin 新增 set_ai_pipeline/set_ai_models 方法
- src/plugins/http/routes.rs: 新增 6 个 AI 相关路由
- POST /api/chat/text (文字对话,Web 端主路径)
- POST /api/chat/audio (语音对话,App 主路径)
- GET /api/models (模型清单+水位+配额)
- POST /api/models/download (下载模型,后台线程执行)
- POST /api/models/switch (切换激活模型)
- POST /api/models/delete (删除模型,保护当前激活)
- src/main.rs: 注册 AiPlugin,连接 pipeline 到 HttpPlugin
技术决策:
- 对话管线用 spawn_blocking 而非消息系统,满足 HTTP 同步响应需求
- ChatPipeline 用 Arc<Mutex> 共享,HTTP 和 AiPlugin 共用同一实例
- 互斥用 try_lock,忙时返回 409 而非阻塞
- Spike 结论固化: LLM t=2 锁大核、ctx=1024 限死、Qwen2.5-0.5B 默认档
待完成 (后续提交):
- Web 控制端 UI (文字对话 + 角色切换 + 模型管理界面)
- Flutter App (角色页/语音页/模型管理页)
- 设备端部署 llama.cpp/whisper.cpp/piper 二进制 + 模型下载
- 画面联动 (talk/idle 状态切换)
- 测试
注: Windows 开发环境缺 dbus,无法本地 cargo check;待目标机验证。
2026-07-04 15:01:00 +08:00
b066dd187b
docs: CLAUDE.md 标记 P1/P2 修复目标机复验通过 (147/147 零 warning, SIGINT 234ms 退出)
2026-07-04 14:29:16 +08:00
a64d9907c3
docs: 更新 CLAUDE.md 待处理清单 - P1 Shutdown 修复标记完成, P2 部分完成, 新增待复验项
2026-07-04 12:35:27 +08:00
38dcd21352
refactor: P2 清理 - 闭环 check_updates 结果回传 + SDK 文档修正 + DeviceResponse 错误留痕
...
1. service_manager.rs check_plugin_updates: 返回 Vec<(id, cur, new)>,
调用处通过 Custom { kind: "plugin_updates" } 广播结果,闭环 HTTP
调用方获取检查结果的链路 (CLAUDE.md:163 第3项, 王浩然风险3 建议)
2. plugin-sdk/src/lib.rs broadcast 文档: 替换误导性的 WifiProvisioned
示例为 StateChanged (当前真正闭环的消息),并新增 Phase 2 占位消息
说明,列出 WifiProvisioned/DeviceEvent/CursorVisibility 三个当前无
生产者的变体,提醒开发者不要为其编写业务逻辑 (CLAUDE.md:163 第1项)
3. src/plugins/device/mod.rs handle_message: DeviceResponse::Error
转换时补 eprintln 留痕,避免设备层故障完全静默 (CLAUDE.md:163 第4项,
王浩然风险3 建议: 至少在一处记录 Error 响应)
未处理项:
- 单实例保护 (锁文件/socket 互斥): 需目标机实测锁行为,留给设备端工程师
- unclutter 僵尸 reap: 核查发现 shutdown() 已做 kill+wait+pkill 兜底,
仅 SIGKILL 极端场景残留,不值得加 SIGCHLD handler (过度工程)
- CursorVisibility 变体: 删除会破坏示例插件和测试,倾向 Phase 2 统一清理
注: Windows 开发环境缺 dbus/pkg-config, 无法本地 cargo check;
改动经 rust-analyzer 类型检查零诊断, 待目标机验证.
2026-07-04 12:27:35 +08:00
ab1dd9160c
fix: 修复 Ctrl+C 无法及时退出主循环的 P1 bug
...
问题: main.rs Ctrl+C handler 只置 AtomicBool, 但 manager.run() 阻塞在
rx.recv() 永久等待下一条消息, 导致 Ctrl+C 后需等任意消息到达才能退出.
CLAUDE.md:162 记录的已知 P1 隐患 (王浩然发现).
修复 (3 处):
1. service_manager.rs run(): recv() -> recv_timeout(200ms), 超时则
continue 重新检查 self.running, 确保信号能被及时响应
2. service_manager.rs handle_manager_message(): Shutdown 分支广播后
置 self.running=false, 让主循环正常退出 (原本只广播不停机)
3. main.rs Ctrl+C handler: 除置 AtomicBool 外, 向 channel 注入
Message::Shutdown envelope, 唤醒 recv_timeout 并触发优雅停机
效果: Ctrl+C 后最多 200ms 退出, 而非等待下一条任意消息.
注: Windows 开发环境缺 pkg-config/libdbus, 无法本地 cargo check;
改动经 rust-analyzer 类型检查零诊断, 待目标机 (Linux ARM64) 验证.
2026-07-04 12:22:51 +08:00
4d830c0e56
docs: 修正 README 与代码不一致 (edition 2021 + 补 device 插件)
2026-07-04 12:17:57 +08:00
9c290e19ab
docs: M2.1 PRD 立项 + 团队沟通记录与状态同步
...
- 新增 docs/M2.1_PRD.md:语音数字生命 V1 产品需求文档(角色切换 + 语音回合 + 模型管理 + 双端交付)
- 更新 CLAUDE.md:M2.1 立项状态、spike 结论、待处理项
- 更新 .showen/TEAM_CHAT.md:团队最新沟通记录
- 更新 souls/zhang-mingyuan.md、souls/zhang-wanlin.md:成员状态
2026-07-04 12:04:01 +08:00
417dabb127
refactor: 更新团队成员状态和设备清理经验,优化文档内容
2026-07-03 15:17:59 +08:00
2a6e14b976
feat: Update project documentation and workflow to reflect changes in task dispatching and testing processes
...
- Changed references from "kilo" to "Agent 子代理" in various documentation files to align with the new task dispatching method.
- Updated CLAUDE.md to reflect the new agent-based execution model and modified task dispatch template.
- Revised PROGRESS.md to indicate successful testing and acceptance of M1.2 with detailed results.
- Enhanced communication and workflow documentation to clarify the use of Agent 子代理 for real-time collaboration and task management.
- Updated team member soul files with lessons learned from recent testing and integration experiences.
- Refactored test files to remove unused code and improve clarity, ensuring compliance with zero warning standards.
- Documented specific experiences and lessons learned during M1.2 testing, including handling of edge cases and configuration validation.
2026-07-03 14:14:50 +08:00
5770b7007c
chore: remove unused Config type alias, add deny_unknown_fields to remaining config structs
2026-03-31 23:45:00 +08:00
1ded747a0c
refactor: deduplicate HSV validation with loop over channel ranges
2026-03-31 23:43:44 +08:00
0cdea53f8d
refactor: derive PartialEq + Eq for core message types (Destination, PlayerCommand, WifiCommand, etc.)
2026-03-31 23:43:06 +08:00
c52dd6b336
refactor: derive PartialEq + Eq for PluginStateInfo, PluginInfo, CapabilityTestResult, ErrorPolicy
2026-03-31 23:42:06 +08:00
8d1ebf02e3
refactor: use OnceLock for log dedup statics in processor.rs
2026-03-31 23:41:10 +08:00
98d827f5c3
refactor: introduce plugin_ids constants, replace hardcoded plugin ID strings
2026-03-31 23:40:23 +08:00
c8dece351c
fix(security): sanitize filename in Content-Disposition header to prevent injection
2026-03-31 23:39:20 +08:00
fbe064253c
perf: inline WiFi connect/hotspot args to eliminate Vec<String> allocation
2026-03-31 23:38:57 +08:00
2507629b4c
refactor: derive PartialEq for PlayerStatusData, simplify status_changed()
2026-03-31 23:38:13 +08:00
96a170f719
fix: remove double semicolon in wifi ap_stop()
2026-03-31 23:37:48 +08:00
8952bb14d2
chore: update .gitignore and remove .claude/ from tracking
...
- Add .claude/ to .gitignore (Claude worktree artifacts)
- Add editor swap/backup file patterns (*.swp, *.swo, *~)
- Remove accidentally tracked .claude/worktrees/ from git index
2026-03-31 23:29:49 +08:00
566cfd0cbc
fix(security): fix percent_decode to handle multi-byte UTF-8 properly
...
The previous implementation decoded percent-encoded bytes one at a time
and cast each to char, which produces invalid characters for multi-byte
UTF-8 sequences (e.g. Chinese filenames). Fixed to accumulate raw bytes
first and convert to String at the end with proper UTF-8 validation.
2026-03-31 23:29:00 +08:00
a8108cea9d
fix: add random_loop_range validation in VideoItem
...
- Validate that random_loop_range values are positive
- Validate that min <= max in random_loop_range
- Prevents invalid config from causing runtime panics in rand::gen_range
2026-03-31 23:28:03 +08:00
758dead601
refactor: clean up unused binding and simplify Mutex patterns
...
- plugin_loader.rs: remove unused _plugin_id binding in discover_plugins
- http/mod.rs: simplify config() and player_status() Mutex access patterns
2026-03-31 23:27:26 +08:00
e112b2e8b7
chore: add Cargo.toml metadata (description, license, rust-version)
...
- All crates: rust-version = 1.70, license = MIT
- Root + example-plugin: publish = false (not intended for crates.io)
- plugin-sdk: proper description for potential future publication
2026-03-31 23:26:17 +08:00
d040f51cb2
fix: improve error handling and code robustness
...
- state_machine.rs: if-let replaces is_some()+take().unwrap()
- state_machine.rs: expect() replaces unwrap() with invariant docs
- wifi/mod.rs: send_result uses self.id() instead of hardcoded string
2026-03-31 23:25:47 +08:00
b570362546
perf: 减少 WiFi 模块不必要的 String 分配
...
- run_nmcli: 改为泛型 &[impl AsRef<OsStr>],直接接受 &[&str]
- 移除 nmcli_args() 中间函数,消除每次 nmcli 调用的 Vec<String> 分配
- build_connect_args/build_hotspot_args: 使用 array.into_iter() (Rust 2021)
2026-03-31 23:24:50 +08:00
1bf9e055e0
refactor: 补全 Default trait + 简化 Rust 2021 惯用写法
...
- LinuxArm64Backend: 添加 Default impl(与其他插件保持一致)
- version_manager.rs: [active, stable].into_iter() 替换 IntoIterator::into_iter()
(Rust 2021 edition 原生支持数组 IntoIterator)
2026-03-31 23:23:30 +08:00
d48a1cf88b
fix: 使用 CARGO_PKG_VERSION 替换硬编码版本号
...
- routes.rs: AppInfoResponse.version 使用 env!(CARGO_PKG_VERSION)
- device/mod.rs: DevicePlugin PluginInfo.version 使用 env!(CARGO_PKG_VERSION)
消除版本不一致问题:之前 Cargo.toml 版本为 0.2.0,但代码中硬编码为 0.1.0。
2026-03-31 23:22:32 +08:00
47d6b06ced
chore: upgrade Rust edition 2018 2021
...
- Cargo.toml: edition 2021
- plugin-sdk/Cargo.toml: edition 2021
- plugins/example-plugin/Cargo.toml: edition 2021
Rust 2021 edition 带来更好的闭包捕获规则、IntoIterator for arrays 等改进。
2026-03-31 23:21:57 +08:00
showen
d30c111c71
feat: M1.1 完成 + M1.2 启动 — 全量更新
...
M1.1 收尾:
- 24项 P0/P1/P2 bug 修复 (Rust 107 tests + Flutter 15 tests)
- Flutter App v0.3: cupertino_icons 修复, 单元测试, 调试面板, APK 52.6MB
- 示例插件完善: manifest.json + 请求/响应示范 + 7个测试
- API 文档重写 (以 routes.rs 为唯一权威)
- MILESTONES.md 更新至 100%
M1.2 启动:
- P0: 插件管理 API 闭环 (handle_manager_message Custom 分支 + broadcast_plugin_states)
- ServiceManager 集成测试 8/8 (tests/m1_2_service_manager.rs)
- M1.2 测试计划 (docs/M1.2_TEST_PLAN.md, 18个E2E场景)
- 动态插件系统: auto_rollback + version_manager GC + 路径穿越防护
总计: Rust 115/115 测试, Flutter 15/15 测试, 零 warning
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-14 18:12:42 +08:00
showen
8ed9cb2d9d
feat: Flutter APK 编译成功 + Gradle 配置修复 + APK 下载部署 + 待优化清单
...
- 通过 qemu-user-static 实现 ARM64 主机编译 Android APK (51MB)
- 修复 Gradle: Aliyun 镜像 + PREFER_SETTINGS + JVM 内存 1536M
- 部署 APK 到 configs/downloads/, Web 下载接口已验证 (HTTP 200)
- 新增 Flutter TODO.md: 10项待优化 (P0/P1/P2 分级)
- 新增 pm_soul.md, 更新 routes.rs APK 下载路由
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-14 06:43:55 +08:00
showen
bff9ec535d
feat: Flutter 客户端 App + Web UI APK 下载入口
...
- 新增 Flutter 跨平台客户端项目 (clients/flutter/)
- 29 个 Dart 文件: 服务层/状态管理/5个页面/BLE配网
- BLE 蓝牙配网: 扫描设备、写入WiFi凭据、配网状态监听
- HTTP API 客户端: 覆盖全部端点 (播放/场景/WiFi/视频/配置/文件/插件)
- WebSocket 实时通信: 事件流 + 自动重连
- 暗色主题 Material 3 UI, 中文界面
- Android 配置: minSdkVersion 21, BLE/网络权限
- PRD 产品需求文档 + 开发任务看板
- Web UI 添加 APK 下载入口 (routes.rs)
- 下载弹窗 + 二维码 + /download/{filename} 静态文件路由
- BLE 插件增加自动重连循环 (ble/mod.rs)
- BLE 默认设备名修正为 'Showen' (config.rs)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-14 02:09:52 +08:00
showen
d4f0eb7eca
fix: 触发器响应优化 — pending trigger 在当前step结束后立即触发
...
修复网页触发器点击后无响应的问题。原因是 defer_triggers 模式下,
pending trigger 必须等待整个 sequence 播完才触发,当 step 有
random_loop_range [2,15] 时用户可能要等几分钟。
现在改为当前 step 循环结束后立即检查并执行 pending trigger。
同时添加 systemd service 脚本。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-03-13 13:08:10 +08:00