feat: 微信 AI 助手插件(wechat-ai)基线

- 移除旧 aitest 与 mobile-ui-auto 插件及其资源、测试
- 新增纯 Java 微信 AI 助手插件(ADB 驱动 + AI 回复)
- 同步更新主界面图标映射、主题样式与插件配置
This commit is contained in:
2026-08-16 11:52:52 +08:00
commit 2c23679ebb
123 changed files with 17393 additions and 0 deletions
@@ -0,0 +1,218 @@
---
name: wechat-ai-helper-plugin
overview: 删除现有 mobile-ui-auto 手机 UI 自动化插件(含 Python/Airtest 依赖),全新编写纯 Java 的"微信 AI 助手"插件:通过 ADB 读取安卓微信聊天记录、监测指定联系人的新消息,并按用户配置的话术由大模型 AI 自动/半自动回复。
design:
styleKeywords:
- 深色科技
- 卡片化面板
- 状态徽标
- 分栏布局
- 克制动效
- 高对比可读性
fontSystem:
fontFamily: Microsoft YaHei UI
heading:
size: 20px
weight: 600
subheading:
size: 15px
weight: 600
body:
size: 13px
weight: 400
colorSystem:
primary:
- "#4F8CFF"
- "#00C9A7"
background:
- "#181D26"
- "#1E2430"
- "#262D3B"
text:
- "#E8ECF4"
- "#9AA5B8"
- "#FFFFFF"
functional:
- "#27AE60"
- "#EB5757"
- "#F2994A"
- "#56CCF2"
todos:
- id: remove-old-plugin
content: 用 [mcp:Windows CLI MCP Server] 删除旧 mobile-ui-auto 代码/资源/data 目录,并用 [subagent:code-explorer] 复核引用点后同步更新 plugins.config、MainWindow 图标映射与插件测试
status: completed
- id: adb-wechat-reader
content: 实现 AdbClient 与 WechatSessionReader,完成设备连接、微信启动、dump 解析与聊天记录读取
status: completed
dependencies:
- remove-old-plugin
- id: monitor-ai-engine
content: 实现 MessageMonitor 快照比对监测与 AiResponder 模板命中+AI 生成,含 config.json 持久化
status: completed
dependencies:
- adb-wechat-reader
- id: wechat-ai-ui
content: 实现 WechatAiWindow 四页签界面与 WechatAiPlugin 注册,整合联系人/话术/AI 配置与监控日志
status: completed
dependencies:
- monitor-ai-engine
- id: compile-verify
content: 用 [mcp:Windows CLI MCP Server] 执行 mvnw compile 并启动应用,验证插件加载、配置生效与旧插件消失
status: completed
dependencies:
- wechat-ai-ui
---
## 产品概述
将现有"手机UI自动化"插件(基于 Python/Airtest 的测试工具)整体删除重写,全新打造"微信AI助手"插件(方案C)。插件通过 ADB 连接安卓手机微信,实现聊天记录读取、指定联系人消息监测、AI 按用户话术自动回复三大能力,纯 Java 实现、无 Python 依赖。
## 核心功能
- **设备连接与微信启动**:USB/无线 ADB 设备枚举与连接,一键启动手机微信,前台状态检测。
- **聊天记录读取**:`uiautomator dump` 提取消息文本节点(精确免费),支持滚动加载历史记录;截图保存作为视觉兜底,可识别图片消息。
- **指定联系人监测**:维护"指定人"名单,定时轮询会话最新消息与快照比对,检测新消息并推送事件。
- **AI 话术回复**:人设描述驱动 AI 自由发挥 + 固定模板兜底(关键词命中优先),调用 OpenAI 兼容接口(base-url/api-key/model 可配)。
- **回复模式**:默认半自动(PC 端预览 AI 回复,点击"发送"才在手机输入发送),提供全自动开关。
- **监控与日志**:消息事件、AI 生成内容、发送结果完整记录,支持手动重发。
## 交互界面
JavaFX 桌面窗口,深色科技风,顶部工具栏 + 中央分栏布局:左侧聊天记录预览,右侧配置面板(联系人/话术与AI/监控日志三个页签),设备、微信、监控、AI 四色状态徽标实时反馈。
## 技术栈
- Java 17 + Spring Boot 2.7.18 + JavaFX 17(沿用现有桌面架构)
- ADB:直接调用 `adb` 命令行(`devices` / `shell am start` / `shell uiautomator dump` / `shell screencap` / `shell input tap|text|swipe` / `shell dumpsys window`)
- AI 调用:JDK17 自带 `java.net.http.HttpClient` 调 OpenAI 兼容 `chat/completions`,**不新增 Maven 依赖**(pom 不动)
- 配置持久化:`data/wechat-ai/config.json`(fastjson 读写,沿用项目现有 JSON 序列化方式)
- 日志:SLF4J + logback(项目现有),UI 日志区双写
## 实现方式
**策略**:删除旧插件后,以"纯 Java ADB 直连 + 文本 dump 优先 + 视觉兜底"的方式重建。微信聊天界面是原生控件,`uiautomator dump` 可直接拿到消息文本与发送者,比截图识图更精确、零成本;截图仅在新消息检测/图片消息/解析失败兜底时触发,配合多模态模型识别。
**关键决策**:
- dump 优先而非全量识图:uiautomator XML 直接含 text/content-desc 属性,解析效率高、无 OCR 误差;视觉模型仅在兜底路径启用。
- 轮询快照比对:Monitor 记录每个指定会话的最新消息 hash,仅在新 hash 出现时才触发 AI,避免重复回复。
- 半自动默认 + 全自动开关:AI 生成结果先回传 UI 预览,防止误发;开关一键切换。
- 话术两级:固定模板(关键词→固定回复,命中直接采用)优先于 AI 生成,保证确定性场景可控。
- 所有 AI/ADB 参数在 UI 可配并持久化,模型/密钥不硬编码。
**性能与可靠性**:
- 轮询默认间隔 3~5 秒(可配),单次 dump 约 1~2 秒,解析仅取文本节点 O(n),无性能瓶颈;截图仅在必要时触发。
- AI 请求设置 30s 超时 + 单次重试,失败不阻塞监控线程,事件落入日志。
- 边界处理:设备断开、未授权、微信未安装/未登录、dump 失败(回退截图+视觉)、消息为空/超长(截断)。
**日志**:AI 请求记录到 UI 日志区(截断至 200 字,不打印 api-key);错误可操作性强、不 dump 大对象。
**爆炸半径控制**:删除前全仓复核 `mobile-ui-auto`/`mobileuiauto` 引用(已定位 MainWindow 图标映射、plugins.config 模板、插件配置测试);新插件 ID 独立,不影响其他插件;data 目录占用删除失败时提示手动清理、不阻塞编译。
## 架构设计
```mermaid
graph LR
UI[WechatAiWindow JavaFX] --> SVC[WechatAiService]
SVC --> ADB[AdbClient]
SVC --> MON[MessageMonitor]
SVC --> AI[AiResponder]
ADB --> PHONE[安卓手机微信]
MON --> READER[WechatSessionReader]
READER --> ADB
AI --> HTTP[OpenAI兼容API]
SVC --> CFG[config.json 持久化]
UI --> EVT[事件回调: 设备状态/新消息/AI结果/日志]
EVT --> UI
```
**模块划分**:
- `adb` 层:AdbClient(命令封装)、AdbDevice(设备模型)——独立于微信逻辑,可复用。
- `wechat` 层:WechatSessionReader(dump 解析/滚动/截图)、WechatMessage/WechatSession(模型)、MessageMonitor(轮询监测,事件回调)。
- `ai` 层:AiResponder(消息组装/模板命中/HTTP 调用/超时重试)、AiConfig(模型参数)。
- `ui` 层:WechatAiWindow(四页签)、WechatAiPlugin(插件注册与生命周期)。
**数据流**:Monitor 轮询 → Reader dump 会话页 → 解析文本节点 → 快照比对发现新消息 → 回调 UI(消息+截图)→ AiResponder 组装(system 人设 + 历史 + 模板)→ 生成回复 → 半自动预览/全自动直发 → AdbClient input 输入发送 → 日志记录。
## 目录结构
### 删除(方案C)
```
src/main/java/com/example/homeutils/biz/mobileuiauto/ # [DELETE] 整个包(Plugin/Window/Service/7个model,共10个文件)
src/main/resources/mobile-ui-auto/ # [DELETE] 整个目录(python/runner.py、requirements.txt、install_tools.py、templates)
data/mobile-ui-auto/ # [DELETE] 运行数据(含 .venv,占用时提示手动清理)
```
### 修改
```
src/main/resources/templates/plugins.config # [MODIFY] plugins.order=mobile-ui-auto → wechat-ai
src/main/java/com/example/homeutils/system/ui/MainWindow.java # [MODIFY] 第325行 AppIcon switch 的 "mobile-ui-auto" case 替换为新ID(先复核该switch)
src/test/java/com/example/homeutils/system/plugin/DefaultPluginConfigurationTest.java # [MODIFY] 测试配置模板中 mobile-ui-auto 引用更新为新ID
```
### 新建
```
src/main/java/com/example/homeutils/biz/wechatai/
├── WechatAiPlugin.java # [NEW] 插件注册:id=wechat-ai,name=微信AI助手,commandName=wechat-ai,实现 Plugin 生命周期与 VisualPluginFactory
├── WechatAiWindow.java # [NEW] JavaFX 主窗口:顶部工具栏(设备/启动微信/监控主开关+模式切换)、中央分栏(左侧聊天记录预览+截图,右侧 TabPane: 联系人/话术与AI/监控日志);沿用 Theme/StyledButton
├── WechatAiService.java # [NEW] 编排服务:组装 AdbClient/Reader/Monitor/AiResponder,提供 start/stop/发送/配置读写,事件分发到 UI
├── adb/
│ ├── AdbClient.java # [NEW] adb 命令封装:listDevices/connect/tap/input/screenshot/dumpUiXml/foregroundPackage/startApp;解析 dump XML 文本节点
│ └── AdbDevice.java # [NEW] 设备模型(serial/state/model),含无线连接地址解析
├── wechat/
│ ├── WechatSessionReader.java # [NEW] 打开微信(com.tencent.mm)→dump会话列表/聊天页→解析消息(发送者/内容/时间)→滚动加载→截图
│ ├── WechatMessage.java # [NEW] 消息模型(sender/content/time/type)
│ ├── WechatSession.java # [NEW] 会话模型(title/messages/lastHash)
│ └── MessageMonitor.java # [NEW] 定时轮询线程:快照比对检测指定联系人的新消息,回调事件;支持启动/停止/间隔配置
├── ai/
│ ├── AiResponder.java # [NEW] HttpClient 调 chat/completions;system=人设+话术;固定模板命中优先;超时30s+重试1次;可选 base64 视觉消息
│ └── AiConfig.java # [NEW] 模型配置模型(baseUrl/apiKey/model/温度/超时)
└── config/
└── WechatAiProperties.java # [NEW] data/wechat-ai/config.json 读写:联系人名单/话术模板/AI配置/监控间隔/模式开关
```
## 关键代码结构
```java
// AdbClient 核心接口(adb 命令封装,全部通过 ProcessBuilder 执行)
public class AdbClient {
List<AdbDevice> listDevices() throws IOException;
String foregroundPackage(String serial) throws IOException;
void startApp(String serial, String packageName) throws IOException;
Path screenshot(String serial, Path outPng) throws IOException;
List<UiNode> dumpUiXml(String serial) throws IOException; // uiautomator dump + XML 解析
void tap(String serial, int x, int y) throws IOException;
void inputText(String serial, String text) throws IOException; // 中文经 ADBKeyboard 或剪贴板方式处理
void swipe(String serial, int x1, int y1, int x2, int y2, int ms) throws IOException;
}
// MessageMonitor 事件回调(解耦监测与 UI/AI)
public interface MessageMonitorListener {
void onNewMessage(WechatSession session, WechatMessage msg, Path screenshot);
void onMonitorError(String message);
void onStatusChanged(boolean running);
}
```
## 设计风格
深色现代科技风桌面应用,与 homeutils 现有 Theme(BG_BODY 深色系、StyledButton、AtlantaFX)体系保持一致。顶部工具栏承载核心操作(设备连接、启动微信、监控主开关、自动/手动模式切换),配四色状态徽标(设备/微信/监控/AI)。中央采用分栏布局:左侧聊天记录列表 + 消息详情/手机截图预览,右侧设置面板以 TabPane 组织(指定联系人、话术与 AI、监控日志)。卡片化面板、圆角、克制的悬停反馈与状态色点缀,信息层级清晰,长时间监控不刺眼。
## Agent Extensions
### MCP
- **Windows CLI MCP Server**
- Purpose: 执行删除操作(`cmd /c rmdir /s /q` 删除旧插件代码/资源/data 目录,规避 Windows 文件占用拦截)、编译验证(`mvnw.cmd compile -q`)、启动应用并检查 data/plugins.config 与侧边栏插件加载结果
- Expected outcome: 旧插件相关文件与 Python 环境被彻底清理,新插件编译通过、应用启动后"微信AI助手"出现在侧边栏且原"手机UI自动化"消失
### SubAgent
- **code-explorer**
- Purpose: 在删除前全仓复核 `mobile-ui-auto`/`mobileuiauto`/`MobileUiAutomation` 的所有引用点(MainWindow 图标 switch、配置、测试、文档),确认无遗漏后才执行删除
- Expected outcome: 输出完整引用清单,确保删除后编译无残留错误、无死引用
@@ -0,0 +1,228 @@
---
name: 系统设置重构-直接打开配置文件
overview: 重构系统设置窗口,去掉繁琐的表单填写,改为每个 Tab 直接打开 data 目录下对应配置文件,用系统默认编辑器快速配置,每个 Tab 只管理自己栏目的配置。
design:
styleKeywords:
- Clean
- Minimalist
fontSystem:
fontFamily: Microsoft YaHei
heading:
size: 16px
weight: 700
subheading:
size: 14px
weight: 600
body:
size: 13px
weight: 400
colorSystem:
primary:
- "#4CAF50"
background:
- "#F5F5F5"
- "#FFFFFF"
text:
- "#333333"
- "#666666"
functional:
- "#FF9800"
- "#F44336"
todos:
- id: refactor-external-config
content: 移除 ExternalConfigManager 中 MyBatis 相关配置节,只保留系统路径、数据文件路径和字体大小
status: completed
- id: refactor-path-tab
content: 重构系统路径 Tab,移除表单,改为显示 workutils.config 路径 + 打开按钮 + 重新加载按钮
status: completed
dependencies:
- refactor-external-config
- id: refactor-mybatis-tab
content: 重构 MyBatis 数据库 Tab,移除表单,改为显示 mybatis-generator.properties 路径 + 打开按钮 + 重新加载按钮
status: completed
dependencies:
- refactor-external-config
- id: refactor-project-tab
content: 重构项目路径 Tab,移除 TextArea,改为显示 project_paths.txt 路径 + 打开按钮,保留批量替换工具
status: completed
- id: add-datasource-tab
content: 新增多数据源 Tab,显示 datasources.json 路径 + 打开按钮 + 重新加载按钮
status: completed
- id: refactor-damaged-cache-tab
content: 重构损坏缓存 Tab,移除 TextArea,改为显示 damaged_repos.cache 路径 + 打开按钮 + 清理缓存按钮
status: completed
- id: add-open-file-util
content: 新增 openFileInEditor 工具方法,支持 Desktop.edit 和 notepad fallback
status: completed
- id: compile-test
content: 编译验证并测试所有 Tab 功能
status: completed
dependencies:
- refactor-path-tab
- refactor-mybatis-tab
- refactor-project-tab
- add-datasource-tab
- refactor-damaged-cache-tab
- add-open-file-util
---
## 产品概述
重构系统设置窗口,去掉繁琐的 JavaFX 表单填写体验,改为每个 Tab 直接打开 data 目录下对应的配置文件,用系统默认编辑器(记事本/IDE)快速配置。每个 Tab 只管理自己栏目的配置,各配置文件独立管理。
## 核心功能
- **系统路径 Tab**:显示 `data/workutils.config` 文件路径,提供「用记事本打开」按钮直接编辑系统路径和字体设置
- **MyBatis 数据库 Tab**:显示 `data/mybatis-generator.properties` 文件路径,提供「用记事本打开」按钮直接编辑数据库连接和包路径配置
- **项目路径 Tab**:显示 `data/project_paths.txt` 文件路径,提供「用记事本打开」按钮直接编辑项目路径列表
- **多数据源 Tab**:显示 `data/datasources.json` 文件路径,提供「用记事本打开」按钮直接编辑多数据源配置
- **损坏缓存 Tab**:显示 `data/damaged_repos.cache` 文件路径,标记为只读,提供「用记事本打开」按钮查看,保留「清理缓存」按钮
- **重新加载**:每个 Tab 提供「重新加载」按钮,让程序重新读取文件使配置生效
- **ExternalConfigManager 精简**:移除 `SECTIONS` 中的 MyBatis 相关配置节,只保留系统路径、数据文件路径和字体大小
## 技术栈
- JavaFX(原有技术栈,保持一致的 UI 风格)
- Desktop.getDesktop().edit() 打开配置文件(Windows 下用默认编辑器打开)
## 实施方案
### 架构设计
重构后的设置窗口每个 Tab 统一结构:
```
┌─────────────────────────────────────────────────────────┐
│ Tab 标题(如:系统路径) │
│ │
│ 配置文件: C:\xxx\data\workutils.config │
│ │
│ [用记事本打开] [重新加载] │
│ │
│ 说明文字:编辑后点击「重新加载」生效,无需重启。 │
└─────────────────────────────────────────────────────────┘
```
### 关键修改点
#### 1. SettingsWindow.java — 重构各 Tab
**createPathTab()**(系统路径 Tab):
- 移除所有 GridPane 表单行(tfBaseDir、tfExportDir 等 TextField)
- 显示 `properties.getWorkutilsConfigFilePath()` 绝对路径
- 保留「用记事本打开」按钮(调用 `Desktop.getDesktop().edit(file)`)
- 保留「重新加载」按钮(调用 `properties.mergeExternal(configManager.load())`)
- 保留字体大小设置说明(字体设置仍在 workutils.config 中)
**createMyBatisTab()**(MyBatis 数据库 Tab):
- 完全移除 GridPane 表单(tfDbDriver、tfDbUrl 等)
- 显示 `properties.getMybatisGeneratorFilePath()` 绝对路径
- 「用记事本打开」按钮打开 `data/mybatis-generator.properties`
- 「重新加载」按钮调用已有逻辑重新加载 MyBatis 配置
- 移除「从内置配置加载」按钮(用户直接编辑文件即可)
**createProjectTab()**(项目路径 Tab):
- 移除 TextArea + 加载/保存按钮的复杂结构
- 显示 `properties.getProjectPathsFilePath()` 绝对路径
- 「用记事本打开」按钮打开 `data/project_paths.txt`
- 保留「重新加载」按钮刷新项目路径列表
- **保留批量替换工具**(这是用户之前明确需求的功能,在 memory ID 70362697 中有记录)
**createDatasourceTab()**(新增 Tab — 多数据源):
- 显示 `properties.getDatasourcesFilePath()` 绝对路径
- 「用记事本打开」按钮打开 `data/datasources.json`
- 「重新加载」按钮调用 `datasourceConfigManager.reload()`
**createDamagedCacheTab()**(损坏缓存 Tab,替代原项目管理 Tab 中的子 Tab):
- 显示 `properties.getDamagedReposFilePath()` 绝对路径
- 标记为只读(加提示文字)
- 「用记事本打开」按钮打开 `data/damaged_repos.cache`
- 保留「清理缓存」按钮
**createDisplayTab()**(显示设置 Tab):
- 字体设置仍在 `workutils.config` 中,所以此 Tab 内容与系统路径 Tab 操作的是同一个文件
- 可以简化为一个提示:「字体设置请在 workutils.config 中修改 font.size.* 属性」+ 「重新加载」按钮
- 或者保留现有的滑块预览(用户可能喜欢实时预览字体效果),但保存时改为提示用户去文件编辑
**建议**:显示设置 Tab 保留现有滑块预览功能(用户体验好),但「保存」按钮改为提示用户手动编辑 workutils.config,或仍通过 `ExternalConfigManager.saveSectioned()` 保存字体设置(因为字体设置是系统级的,适合集中管理)。
#### 2. ExternalConfigManager.java — 移除 MyBatis 配置节
修改 `SECTIONS` 静态初始化块,移除:
- `"===== MyBatis 数据库连接(覆盖内置 mybatis-generator.properties)====="`
- `"===== MyBatis 代码生成包路径 ====="`
只保留:
- `"===== 系统路径 ====="`
- `"===== 数据文件路径 ====="`
- `"===== 字体大小(显示设置) ====="`
同步移除对应的 KEY 常量(或修改注释说明这些 KEY 仅用于 workutils.config)。
#### 3. 打开文件工具方法
在 SettingsWindow 中新增工具方法:
```java
private void openFileInEditor(Path file) {
try {
if (!Files.exists(file)) {
Files.createDirectories(file.getParent());
Files.createFile(file);
}
// Windows: Desktop.edit 用关联程序打开并允许编辑
// 如果 Desktop 不可用,fallback 到 Runtime.exec("notepad")
if (Desktop.isDesktopSupported()) {
Desktop.getDesktop().edit(file.toFile());
} else {
// Windows fallback
Runtime.getRuntime().exec(new String[]{"notepad", file.toAbsolutePath().toString()});
}
} catch (Exception e) {
showAlert(AlertType.ERROR, "打开文件失败: " + e.getMessage());
}
}
```
### 实施注意事项
1. **Desktop.getDesktop().edit()** 在 Windows 上需要文件有关联的编辑器,且文件必须存在
2. **批量替换工具保留**:用户的 memory 中明确提到需要保留项目路径批量替换功能,不能删除
3. **向后兼容**:workutils.config 中如果仍有旧的 MyBatis 配置项,程序应能忽略(不报错)
4. **文件不存在处理**:打开前检查文件是否存在,不存在则创建空文件或从模板复制
### 目录结构变更
```
src/main/java/com/example/workutils/system/config/
├── SettingsWindow.java [MODIFY] 重构所有 Tab 内容
├── ExternalConfigManager.java [MODIFY] 移除 MyBatis 配置节
├── WorkUtilsProperties.java [NO CHANGE] 无需修改
├── DatasourceConfigManager.java [NO CHANGE] 无需修改
└── ConfigInitializer.java [NO CHANGE] 无需修改
```
无需新增文件,只需修改现有两个文件。
## 设计风格
保持现有 JavaFX 窗口的简洁风格,每个 Tab 内容统一为:
- 顶部:标题(加粗,字号稍大)
- 中部:配置文件路径(等宽字体,可选择性可复制)
- 按钮区:[]用记事本打开] []重新加载](对齐,间距合理)
- 底部:说明文字(灰色,小字号)
## 布局说明
每个 Tab 使用 VBox 垂直布局,内容居中偏左对齐,整体留白适中(Insets 12px)。
按钮使用 HBox 水平排列,间距 10px。
路径 Label 使用等宽字体(Consolas),背景浅灰,增加可读性。