diff --git a/AGENTS.md b/AGENTS.md index 79f0c49..fdf60a0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,4 +1,4 @@ -# AutoAgent 开发规则 +# AgentAdmin 开发规则 本仓库采用需求驱动的轻量开发流程。当前项目是内部系统,不设置额外的敏感数据规则、安全审批门禁、工单门禁、原型门禁或 Wiki 同步门禁。 @@ -26,13 +26,14 @@ ## 3. 项目标识 -- Gradle 项目名:`AutoAgent` +- 仓库 / 项目名:`AgentAdmin` +- 当前 Android 子项目 Gradle 名:`AutoAgent` - Android 包名 / Application ID:`cn.auto.agent` - Kotlin namespace:`cn.auto.agent` - 应用显示名:`Auto Agent` - 无障碍服务显示名:`autoagent` -未经用户明确要求,不修改上述标识。 +`AgentAdmin` 是仓库级项目名;其余为当前 Android 子项目的既有标识。未经用户明确要求,不修改 Android 标识。 ## 4. 系统、Java 与依赖版本 @@ -161,8 +162,8 @@ 默认从仓库根目录执行: ```powershell -.\gradlew.bat test -.\gradlew.bat assembleDebug +.\android\gradlew.bat -p android test +.\android\gradlew.bat -p android assembleDebug ``` 根据改动范围选择验证: @@ -175,7 +176,7 @@ APK 默认输出: ```text -app/build/outputs/apk/debug/app-debug.apk +android/app/build/outputs/apk/debug/app-debug.apk ``` ## 11. 完成条件 diff --git a/README.md b/README.md index 4659bd8..5d84422 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,16 @@ -# AutoAgent +# AgentAdmin -独立的原生 Kotlin Android 任务 Agent。项目标识: +AgentAdmin 内部系统仓库。当前已实现的交付单元是 `android/` 下的原生 Kotlin Android 任务 Agent;`admin/` 尚无已确认实现。 -- 项目名:`AutoAgent` +项目标识: + +- 仓库 / 项目名:`AgentAdmin` +- Android Gradle 项目名:`AutoAgent` - 包名:`cn.auto.agent` - 应用名:`Auto Agent` - 无障碍服务名:`autoagent` -## 当前提取范围 +## 当前实现范围 - 类型化任务协议:`WAIT`、`CLICK`、`INPUT`、`BACK`、`EXTRACT_TEXT` - 基于 `AccessibilityService` 的包名、Activity 和唯一节点操作驱动 @@ -23,11 +26,18 @@ 当前版本不会自动开始任务,也未实现后台轮询、结果 Outbox、任意脚本、Shell、坐标盲点、订单或支付动作。 +## 文档 + +- [项目文档入口](docs/README.md) +- [开发工作流](docs/01-workflow.md) +- [Agent 协议与动作](docs/agent/README.md) +- [开发规则](AGENTS.md) + ## 验证 ```powershell -.\gradlew.bat test -.\gradlew.bat assembleDebug +.\android\gradlew.bat -p android test +.\android\gradlew.bat -p android assembleDebug ``` -APK:`app/build/outputs/apk/debug/app-debug.apk` +APK:`android/app/build/outputs/apk/debug/app-debug.apk` diff --git a/docs/00-project-profile.md b/docs/00-project-profile.md new file mode 100644 index 0000000..9df3888 --- /dev/null +++ b/docs/00-project-profile.md @@ -0,0 +1,80 @@ +# AgentAdmin 项目概况 + +## 项目定位 + +AgentAdmin 是内部 Agent 管理系统仓库。当前已实现的交付单元是原生 Kotlin Android 任务 Agent:它接收类型化任务,筛选属于本机设备的任务,将任务持久化到 SQLite,并通过 Android 无障碍能力执行已支持的 UI 动作。 + +当前代码主要是通用 Android Agent 内核,不包含管理端实现,也不包含特定目标 App 的采购、订单、采集或支付业务。 + +## 固定标识 + +| 项目 | 当前值 | +|---|---| +| 仓库 / 项目名 | `AgentAdmin` | +| 当前 Android 子项目 Gradle 名 | `AutoAgent` | +| Android 包名 / Application ID | `cn.auto.agent` | +| Kotlin namespace | `cn.auto.agent` | +| 应用显示名 | `Auto Agent` | +| 无障碍服务显示名 | `autoagent` | + +`AgentAdmin` 是仓库级项目名;其余为当前 Android 子项目的既有标识。除非需求明确要求,不修改 Android 标识。 + +## 开发方式 + +本项目采用需求驱动的轻量流程:理解需求、检查现状、分析方案、实施、验证、交付。它是内部系统,不设置额外的安全审批、工单、原型、Wiki 同步或发布门禁。 + +文档结构参考 `D:\OPC\dev_harness`,参考基线为提交 `ecab8995026e57f2c28f307a6aa32b871cb3163f`。本项目只采用其中适合现有仓库的做法: + +- 先盘点现有代码和规则,再增量补充文档; +- 将项目概况、工作流、架构、开发验证和排障分开维护; +- 让文档链接到真实代码、命令和测试; +- 保留项目自己的历史、目录和开发规则。 + +未引入 DevHarness 的 Gitea、Wiki 镜像、任务归档、模板同步和门禁流程,也不复制其项目专用事实或脚本。 + +## 技术基线 + +| 项目 | 当前值 | +|---|---| +| 语言 | Kotlin | +| UI 平台 | 原生 Android Views / AppCompat | +| JDK | 17 | +| Gradle Wrapper | 8.2 | +| Android Gradle Plugin | 8.2.0 | +| Kotlin Android Plugin | 1.9.22 | +| `compileSdk` / `targetSdk` | 34 / 34 | +| `minSdk` | 23 | +| 应用版本 | `0.1.0`(`versionCode` 1) | +| 本地存储 | Android SQLite | +| UI 自动化能力 | `AccessibilityService` | + +可执行版本事实以 `android/gradle/wrapper/gradle-wrapper.properties`、`android/build.gradle.kts` 和 `android/app/build.gradle.kts` 为准。 + +## 仓库结构 + +```text +agent_admin/ AgentAdmin 仓库 +├─ android/ Android Gradle 工程 +│ └─ app/src/ 应用代码、资源和测试 +├─ admin/ 管理端预留目录,当前无实现 +├─ docs/ 项目文档 +│ └─ agent/ 任务协议和动作规范 +├─ AGENTS.md 仓库开发规则 +└─ README.md 项目入口 +``` + +当前只有 `android/` 是可构建交付单元。`admin/` 没有已确认需求时不预建框架,也不据此把整个项目称为 AutoAgent。 + +## 常用入口 + +- 开始开发:[开发工作流](01-workflow.md) +- 查找代码:[架构与代码地图](02-architecture-and-code-map.md) +- 运行项目:[本地开发与验证](04-local-development-and-verification.md) +- 修改任务动作:[常见改动指南](05-common-changes.md#新增或修改任务动作) +- 查看协议:[Agent 文档](agent/README.md) + +## 当前能力边界 + +已实现动作:`WAIT`、`CLICK`、`INPUT`、`BACK`、`EXTRACT_TEXT`。 + +外部服务接口尚未确定,因此当前只有 `TaskGateway` 抽象,没有服务地址、认证、轮询、领取、租约或结果提交实现。任务入库与任务开始执行仍是两个独立阶段。 diff --git a/docs/01-workflow.md b/docs/01-workflow.md new file mode 100644 index 0000000..747a1f6 --- /dev/null +++ b/docs/01-workflow.md @@ -0,0 +1,91 @@ +# 开发工作流 + +## 目标 + +用最少但完整的步骤完成需求,同时确保实现、测试和文档一致。流程服务于开发,不增加与风险无关的门禁。 + +## 标准流程 + +### 1. 理解需求 + +明确以下内容: + +- 目标结果和使用场景; +- 输入、输出和验收方式; +- 修改范围与明确不做的内容; +- 是否会改变现有协议、数据库或运行行为。 + +范围清楚、实现方式唯一且容易回退的小改动,可以检查现状后直接实施。存在关键事实缺失、多个重要方案或兼容性取舍时,先和用户确认。 + +### 2. 检查现状 + +先读与需求直接相关的代码、配置、测试和文档,不根据文件名或旧说明猜测实现。检查工作区状态,保留无关改动。 + +建议入口: + +- 项目规则:`AGENTS.md` +- 代码定位:[架构与代码地图](02-architecture-and-code-map.md) +- 协议与动作:`docs/agent/` +- 构建版本:`android/*.gradle.kts` 和 Gradle Wrapper 配置 + +### 3. 分析方案 + +根据改动范围说明必要的设计事实: + +- 模块边界和数据流; +- 协议、接口或持久化变化; +- 异常和超时行为; +- 兼容性影响; +- 自动测试与真机验证范围。 + +简单改动不要求编写单独方案文档;在任务沟通中说明即可。 + +### 4. 实施改动 + +- 按已确认方案做最小且完整的实现; +- 优先扩展已有抽象,不复制相同逻辑; +- 不混入与当前需求无关的重构; +- 变更协议、数据库或长期规则时,同步更新相关文档和测试; +- 当前没有 Android 实现需求时,只改文档,不以占位代码宣称能力可用。 + +### 5. 执行验证 + +验证应覆盖受影响范围: + +- 文档改动:检查链接、路径、命令和实现状态; +- 模型、协议、同步或执行器:运行相关单元测试,交付前运行完整 `test`; +- Manifest、资源、依赖或 Android 应用代码:运行 `assembleDebug`; +- SQLite 结构:补充读写或升级测试; +- 无障碍行为:除自动测试和构建外,列出需要真机验证的页面与动作。 + +测试必须真实执行。未运行、无法运行或需要外部环境的项目要明确说明。 + +### 6. 交付 + +向用户简要说明: + +- 实现结果和主要改动文件; +- 实际执行的验证及结果; +- 未完成、未验证或仍待确认的事项。 + +只有用户要求时才创建 Git 提交。提交前检查差异,确保不包含无关文件;不自动推送、发布 APK 或创建标签。 + +## 改动与文档的对应关系 + +| 改动 | 同步检查 | +|---|---| +| 项目标识、版本或依赖 | `README.md`、`AGENTS.md`、项目概况、构建文件 | +| 任务 JSON 或校验规则 | `docs/agent/protocol.md`、解析测试 | +| 选择器 | `docs/agent/selector.md`、解析和执行测试 | +| 动作 | 模型、解析器、执行器、动作页、动作索引和测试 | +| 任务同步规则 | 业务规则、调度代码、同步测试 | +| SQLite 表结构 | 业务规则、持久化代码、升级或读写测试 | +| 构建或运行方式 | README、本地开发文档、AGENTS(若为长期规则) | + +## 需求变化 + +需求或已确认方案发生变化时,先重新确认受影响范围,再继续实现。已经完成且仍有效的工作保留,不为追求形式完整而重做。 + +## 发现范围外问题 + +记录并在交付时提示,但不自动混入本次修改。只有它会阻止当前需求、破坏数据或使验证失真时,才需要立即处理或请求用户决策。 diff --git a/docs/02-architecture-and-code-map.md b/docs/02-architecture-and-code-map.md new file mode 100644 index 0000000..f787248 --- /dev/null +++ b/docs/02-architecture-and-code-map.md @@ -0,0 +1,83 @@ +# 架构与代码地图 + +## 分层原则 + +AgentAdmin 当前的 Android Agent 子项目将通用任务能力与 Android 实现分开: + +```text +外部任务源 + │ + ▼ +TaskGateway → TaskSynchronizer → TaskParser → TaskInbox / SQLite + │ + ▼ + AgentTask + │ + ▼ + TaskExecutor → ActionDriver + │ + ▼ + AutoAccessibilityService +``` + +- 核心模型不依赖外部服务或目标 App。 +- 执行器只依赖 `ActionDriver`,不直接调用 Android 无障碍 API。 +- 服务端差异由 `TaskGateway` 或等价适配器隔离。 +- 目标 App 的页面识别和业务步骤应进入独立适配层,不写入通用协议与执行内核。 + +## 代码地图 + +所有 Kotlin 源码位于 `android/app/src/`。 + +| 路径 | 职责 | 主要类型 | +|---|---|---| +| `main/java/cn/auto/agent/core/model/` | 通用任务、步骤、选择器和结果模型 | `AgentTask`、`TaskStep`、`NodeSelector`、`ActionType`、`ResultCode` | +| `main/java/cn/auto/agent/core/protocol/` | JSON 协议解析与校验 | `TaskParser`、`TaskProtocolException` | +| `main/java/cn/auto/agent/core/scheduler/` | 获取、筛选并同步任务 | `TaskGateway`、`TaskSynchronizer`、`TaskSyncSummary` | +| `main/java/cn/auto/agent/core/persistence/` | 任务收件箱抽象与 SQLite 实现 | `TaskInbox`、`SqliteTaskInbox` | +| `main/java/cn/auto/agent/core/executor/` | 步骤执行、超时和进程内互斥 | `TaskExecutor`、`ActionDriver`、`TaskExecutionMutex` | +| `main/java/cn/auto/agent/core/accessibility/` | Android 无障碍驱动与 Activity 跟踪 | `AutoAccessibilityService`、`ActivityTracker` | +| `main/java/cn/auto/agent/app/` | UI、生命周期和依赖装配入口 | `MainActivity` | +| `main/res/` | 字符串、主题和无障碍服务配置 | `strings.xml`、`accessibility_service_config.xml` | +| `test/java/cn/auto/agent/` | JVM 单元测试 | 解析、同步、执行和超时测试 | + +## 任务同步流程 + +1. `TaskGateway.fetchTaskPayloads()` 返回外部任务的原始 JSON 列表。 +2. `TaskSynchronizer` 逐条调用 `TaskParser`。 +3. 格式无效的任务计入无效数量,不写入数据库。 +4. `assignedAgentName` 与本机设备名做区分大小写的精确比较。 +5. 不属于本机的任务被忽略,不算本机执行失败。 +6. 属于本机的有效任务交给 `TaskInbox.save()`。 +7. `SqliteTaskInbox` 以 `task_id + revision` 作为幂等键保存。 + +同步只负责获取、校验、归属判断和入库,不代表任务已经领取或开始执行。 + +## 任务执行流程 + +1. 调用方将一个已解析的 `AgentTask` 交给 `TaskExecutor`。 +2. 执行器依次处理步骤,并在每步操作前检查包名和已声明 Activity。 +3. 需要控件的动作通过 `ActionDriver.find()` 查找节点。 +4. 默认要求唯一匹配:零个匹配为未找到,多个匹配为歧义失败。 +5. 执行器调用驱动完成点击、输入、返回或文本读取。 +6. 每个步骤都有有限超时,最终返回类型化 `TaskExecutionResult`。 + +`AutoAccessibilityService` 是当前 Android 驱动实现。它负责把通用驱动调用转换为无障碍节点查询和操作,不应承担服务端协议或目标 App 业务编排。 + +## 应用入口 + +`MainActivity` 当前只展示无障碍服务状态并提供打开系统无障碍设置的入口。后台轮询、任务自动启动、结果 Outbox 和服务端提交尚未实现。 + +## 修改影响 + +| 需要修改的行为 | 首要代码位置 | 通常还需检查 | +|---|---|---| +| 新增动作 | `TaskModels.kt`、`TaskParser.kt`、`TaskExecutor.kt` | `ActionDriver`、无障碍实现、动作文档和测试 | +| 修改 JSON 字段或校验 | `TaskParser.kt`、模型 | 协议文档、解析测试、兼容性 | +| 修改设备任务筛选 | `TaskSynchronizer.kt` | 业务规则、同步测试 | +| 修改幂等或表结构 | `SqliteTaskInbox.kt` | 数据库版本、升级路径、持久化测试 | +| 接入外部服务 | 新的 `TaskGateway` 实现 | 配置、错误处理、调度测试;不污染核心模型 | +| 修改节点操作 | `AutoAccessibilityService.kt` | 执行器契约、真机验证 | +| 增加目标 App 流程 | 独立适配层 | 包名/Activity、页面状态、恢复策略和真机用例 | + +更具体的操作步骤见 [常见改动指南](05-common-changes.md)。 diff --git a/docs/03-business-rules-and-glossary.md b/docs/03-business-rules-and-glossary.md new file mode 100644 index 0000000..f949091 --- /dev/null +++ b/docs/03-business-rules-and-glossary.md @@ -0,0 +1,74 @@ +# 业务规则与术语 + +本文记录当前代码和已确认需求中的稳定规则。目标 App 的具体业务流程尚未接入,不在这里预设。 + +## 核心术语 + +| 术语 | 含义 | +|---|---| +| Agent | AgentAdmin 管理的 Android Agent 端实例;当前应用显示名为 `Auto Agent` | +| Agent 设备名 | 本机配置的名称,用于与任务的 `assignedAgentName` 精确匹配 | +| 任务(`AgentTask`) | 一组有序步骤及其版本、目标包和 Activity 约束 | +| 步骤(`TaskStep`) | 一个类型化动作及其参数、选择器和超时配置 | +| revision | 同一 `taskId` 的任务版本号 | +| 选择器(`NodeSelector`) | 用于查找目标无障碍节点的通用条件 | +| `TaskGateway` | 外部任务源的抽象接口 | +| `TaskInbox` | 本地任务收件箱的持久化抽象 | +| `ActionDriver` | 执行器访问 UI 能力的抽象接口 | +| 执行结果 | 任务是否成功及类型化结果码、消息和输出 | + +## 任务归属与入库 + +- 外部任务通过 `assignedAgentName` 指定设备名。 +- 只有它与本机 Agent 设备名完全相同,任务才允许写入 SQLite。 +- 比较区分大小写,不进行包含、前缀、后缀或模糊匹配。 +- 不属于本机的任务直接忽略,不写入 SQLite,也不算本机执行失败。 +- 格式无效的任务不写入 SQLite,并在同步摘要中计入无效任务。 +- SQLite 以 `task_id + revision` 作为任务版本的幂等键。 +- 任务入库与开始执行是两个阶段。当前入库不代表领取、租约或执行已发生。 + +## 执行规则 + +- 步骤使用 `ActionType` 类型化表达,不用分散的任意字符串分支。 +- 当前已实现动作是 `WAIT`、`CLICK`、`INPUT`、`BACK`、`EXTRACT_TEXT`。 +- 控件选择器和执行结果使用通用模型。 +- 默认要求控件唯一;多个匹配明确返回歧义,不随意选第一个。 +- 每一步必须有有限超时,任务不得无限等待或循环。 +- 操作前核对目标包名和任务声明的 Activity。 +- 业务特定的页面判断、重试和恢复策略属于对应目标 App 的适配层。 +- 文档中标记为规划中或尚未实现的动作,不能只通过任务 JSON 启用。 + +## 当前状态与结果 + +任务模型定义以下状态: + +- `RECEIVED`:已接收; +- `RUNNING`:执行中; +- `SUCCEEDED`:执行成功; +- `FAILED`:执行失败。 + +当前执行结果码: + +| 结果码 | 含义 | +|---|---| +| `OK` | 执行成功 | +| `PACKAGE_MISMATCH` | 当前前台包与任务约束不一致 | +| `ACTIVITY_MISMATCH` | 当前 Activity 与任务声明不一致 | +| `TARGET_NOT_FOUND` | 超时前未找到目标控件 | +| `TARGET_AMBIGUOUS` | 选择器匹配到多个控件 | +| `ACTION_FAILED` | 驱动执行具体动作失败 | + +协议字段、选择器和动作参数的详细约定见 [Agent 文档](agent/README.md)。 + +## 未确定能力 + +以下事项等待后续需求和外部接口,不作为当前系统行为: + +- 外部服务 URL、认证和轮询策略; +- 稳定不可变的 `agentId`; +- 服务端原子领取、任务租约和续租; +- 自动调度和进程恢复; +- 结果 Outbox 与幂等提交; +- 目标 App 的业务适配规则。 + +这些事项发生变化时,应同步修改代码、测试、本文和相关 Agent 规范。 diff --git a/docs/04-local-development-and-verification.md b/docs/04-local-development-and-verification.md new file mode 100644 index 0000000..aeaafc0 --- /dev/null +++ b/docs/04-local-development-and-verification.md @@ -0,0 +1,94 @@ +# 本地开发与验证 + +## 环境要求 + +- Windows 10 或兼容开发环境; +- JDK 17; +- Android SDK,包含 API 34 对应平台和构建工具; +- Git; +- PowerShell 7 优先,Windows PowerShell 也可使用。 + +本机 Android SDK 路径可以由 Android Studio、环境变量或未提交的 `local.properties` 配置,不要把个人绝对路径提交到业务代码或版本库。 + +## 首次检查 + +从仓库根目录执行: + +```powershell +java -version +.\android\gradlew.bat -p android --version +.\android\gradlew.bat -p android test +``` + +确认 Gradle 使用 Java 17。如果依赖下载或 SDK 检查失败,先按错误信息补齐环境,再修改代码。 + +## 常用命令 + +运行 JVM 单元测试: + +```powershell +.\android\gradlew.bat -p android test +``` + +构建 Debug APK: + +```powershell +.\android\gradlew.bat -p android assembleDebug +``` + +同时验证测试和构建: + +```powershell +.\android\gradlew.bat -p android test assembleDebug +``` + +Debug APK 输出到: + +```text +android/app/build/outputs/apk/debug/app-debug.apk +``` + +也可以先进入 `android/`,再使用 `./gradlew.bat test` 等标准命令。 + +## 测试范围 + +当前 JVM 测试位于 `android/app/src/test/java/cn/auto/agent/`: + +| 测试 | 覆盖重点 | +|---|---| +| `TaskParserTest` | JSON 解析、字段校验和协议约束 | +| `TaskSynchronizerTest` | 设备名筛选、无效任务统计和入库 | +| `TaskExecutorTest` | 步骤执行、包/Activity、唯一节点和结果 | +| `TaskExecutorTimeoutTest` | 有限超时及相关失败行为 | + +只运行某个测试类时,可使用: + +```powershell +.\android\gradlew.bat -p android testDebugUnitTest --tests "cn.auto.agent.TaskParserTest" +``` + +交付涉及核心逻辑的改动前,仍应运行完整 `test`。 + +## 真机验证 + +无障碍节点树、输入法、不同系统版本和目标 App 页面无法完全由 JVM 测试覆盖。涉及 `AutoAccessibilityService`、Manifest、无障碍配置或目标 App 适配时,至少记录并验证: + +1. 应用可安装和启动; +2. 系统设置中可启用 `autoagent` 无障碍服务; +3. 前台包名和 Activity 能被正确识别; +4. 目标页面的选择器匹配数量符合预期; +5. 点击、输入、返回或提取动作返回正确结果; +6. 超时和失败不会无限等待。 + +交付时明确写出真机型号、Android 版本、目标 App/页面和实际验证步骤;没有真机验证时也要明确说明。 + +## 文档验证 + +文档改动至少检查: + +- 相对链接指向存在的文件; +- 命令从所写目录可以执行; +- 版本和能力状态与代码一致; +- 示例 JSON 符合协议,并且不会把规划中动作写成已实现。 + +不需要为了文档改动重复发布 APK,但涉及路径或构建说明时应实际运行对应命令。 diff --git a/docs/05-common-changes.md b/docs/05-common-changes.md new file mode 100644 index 0000000..2163c75 --- /dev/null +++ b/docs/05-common-changes.md @@ -0,0 +1,94 @@ +# 常见改动指南 + +本页用于快速确定修改范围。开始前仍应阅读相关实现,不把表格当作代码事实的替代品。 + +## 新增或修改任务动作 + +1. 在 `core/model/TaskModels.kt` 更新 `ActionType` 和必要模型。 +2. 在 `core/protocol/TaskParser.kt` 解析并校验动作参数。 +3. 在 `core/executor/TaskExecutor.kt` 定义执行语义、超时和失败结果。 +4. 如果需要新的 UI 能力,先扩展 `ActionDriver`,再实现到 `AutoAccessibilityService`。 +5. 更新 `docs/agent/actions/` 中对应动作页及动作索引。 +6. 补充解析、执行、异常和超时测试。 +7. 运行完整单元测试;涉及无障碍实现时再构建 APK 并列出真机验证。 + +不要只向枚举或 JSON 示例加入动作,也不要把目标 App 业务步骤硬编码到通用执行器。 + +## 修改任务协议或选择器 + +主要检查: + +- `core/model/TaskModels.kt`; +- `core/protocol/TaskParser.kt`; +- `docs/agent/protocol.md`、`selector.md` 和相关动作页; +- `TaskParserTest` 与受影响的执行器测试。 + +先明确字段是否必填、默认值、非法值、旧任务兼容和错误表现。协议变更应保持模型、解析器、文档和示例一致。 + +## 接入外部任务服务 + +新增 `TaskGateway` 实现,将 URL、认证、序列化和网络错误限制在适配层。保留 `TaskSynchronizer` 的通用职责,不在模型或执行器中直接调用服务端。 + +在接口明确前不要猜测: + +- 请求地址和认证; +- 拉取频率和分页; +- 领取、租约或确认语义; +- 重试、退避和错误码; +- 结果提交及幂等键。 + +接入后需要补充适配器测试、配置说明和失败场景;若引入后台运行,还要分析 Android 生命周期与系统限制。 + +## 修改任务筛选或同步 + +主要位置是 `core/scheduler/TaskSynchronizer.kt`。同步检查: + +- `assignedAgentName` 的匹配规则; +- 无效、忽略和保存数量的定义; +- `TaskSynchronizerTest`; +- [业务规则与术语](03-business-rules-and-glossary.md)。 + +除非需求明确改变,不把未分配给本机的任务写入 SQLite,也不将其记为执行失败。 + +## 修改 SQLite + +主要位置是 `core/persistence/SqliteTaskInbox.kt`。修改前明确表结构、唯一键、数据库版本和升级策略。 + +- 新安装场景需要验证建表和读写; +- 已有发布版本时必须验证旧版本升级路径; +- 幂等规则变化时同步更新业务规则和同步测试; +- 不通过清空用户数据来代替升级实现,除非需求明确允许。 + +## 修改执行器或超时 + +主要位置是 `core/executor/TaskExecutor.kt` 和 `TaskExecutionMutex.kt`。检查: + +- 包名与 Activity 校验顺序; +- 零个、一个和多个节点的结果; +- 可选步骤与失败传播; +- 超时边界及是否存在无限循环; +- `TaskExecutorTest` 和 `TaskExecutorTimeoutTest`。 + +通用重试应有明确上限;业务页面的恢复策略留给目标 App 适配层。 + +## 修改 Android UI、资源或无障碍服务 + +根据范围检查: + +- `app/MainActivity.kt`; +- `AndroidManifest.xml`; +- `res/values/`; +- `res/xml/accessibility_service_config.xml`; +- `core/accessibility/`。 + +运行 `assembleDebug`。涉及真实节点操作时,补充真机验证,不能只以构建成功作为行为验证。 + +## 升级 Gradle、SDK 或依赖 + +先分析 JDK、Gradle、AGP、Kotlin 和 Android SDK 之间的兼容关系,再统一修改对应构建文件。同步更新 `AGENTS.md` 和 [项目概况](00-project-profile.md),运行完整测试与 Debug 构建。 + +不要只改文档中的版本号来宣称升级完成。 + +## 仅修改文档 + +确认链接、路径、命令、示例和能力状态。文档若描述构建或测试命令,至少实际执行一次;纯措辞调整无需无意义地重跑 Android 构建。 diff --git a/docs/06-troubleshooting.md b/docs/06-troubleshooting.md new file mode 100644 index 0000000..7226d57 --- /dev/null +++ b/docs/06-troubleshooting.md @@ -0,0 +1,81 @@ +# 排障指南 + +## 推荐顺序 + +1. 复现并记录输入、当前页面、结果码和日志。 +2. 判断问题位于获取、解析、设备筛选、入库、调度还是执行阶段。 +3. 检查对应模块的直接输入和输出,不先改无关层。 +4. 用最小任务或最小测试复现。 +5. 修复后运行受影响测试,再执行交付所需的完整验证。 + +## 构建与环境 + +| 现象 | 优先检查 | +|---|---| +| 根目录找不到 `gradlew.bat` | 使用 `.\android\gradlew.bat -p android ...` | +| Java 版本错误 | `java -version` 与 Gradle `--version` 是否均为 JDK 17 | +| Android SDK 未找到 | Android Studio SDK 配置、环境变量或本机 `local.properties` | +| 依赖无法解析 | 网络、代理和 `google()` / `mavenCentral()` 可用性 | +| APK 路径找不到 | 是否执行 `assembleDebug`,检查 `android/app/build/outputs/apk/debug/` | + +不要提交包含个人 SDK 绝对路径的 `local.properties`。 + +## 任务没有写入 SQLite + +依次检查: + +1. 外部列表中是否确实包含该任务; +2. JSON 是否能被 `TaskParser` 解析; +3. `assignedAgentName` 是否与本机设备名完全一致,包括大小写和空格; +4. 同步摘要中任务被计为无效、忽略还是保存; +5. 相同 `task_id + revision` 是否已经存在。 + +未分配给本机的任务本来就应被忽略,不属于故障。 + +## 无障碍服务不可用 + +- 确认系统设置中已启用 `autoagent` 服务; +- 重新进入应用检查服务状态; +- 确认 Manifest 和 `accessibility_service_config.xml` 声明完整; +- 服务被系统停止后重新启用,并记录设备系统版本; +- 若节点根为空,确认目标 App 在前台且页面已稳定显示。 + +## 包名或 Activity 不匹配 + +- 核对任务声明与设备当前前台页面; +- 确认 Activity 名称格式与 `ActivityTracker` 实际记录一致; +- 排查启动页、弹窗、WebView 或重定向造成的页面切换; +- 不要删除校验来掩盖错误,应修正任务或目标 App 适配逻辑。 + +## 找不到控件 + +- 在超时前页面是否已经加载完成; +- 选择器字段是否与当前节点树一致; +- 目标是否在滚动区域、弹窗或其他窗口; +- 节点是否由 WebView、自绘控件或虚拟节点提供; +- 包名和 Activity 是否先通过检查。 + +需要等待页面状态时使用有限超时,不引入无限轮询。 + +## 控件匹配歧义 + +`TARGET_AMBIGUOUS` 表示选择器命中了多个节点。应增加稳定的选择器条件或由目标 App 适配层先确认页面状态,不随意改成选择第一个节点。 + +## 点击、输入或返回失败 + +- 确认节点支持对应无障碍动作且处于可操作状态; +- 点击目标本身不可点击时,检查是否应由驱动定位可点击父节点; +- 输入失败时检查可编辑、焦点、输入法和节点文本能力; +- 返回失败时确认当前窗口和系统全局动作状态; +- 对照 `ACTION_FAILED` 前的步骤、页面和驱动日志定位。 + +## 何时停止并确认 + +遇到以下情况时,不继续猜测实现: + +- 外部 API 契约、认证或领取语义未提供; +- 需求会改变既有任务兼容性或数据库升级策略; +- 目标 App 页面和成功条件无法确定; +- 修复需要删除数据、覆盖用户改动或扩大到当前需求之外。 + +整理已经确认的事实、复现方式和可选方案后,再向用户确认。 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..c4b535d --- /dev/null +++ b/docs/README.md @@ -0,0 +1,44 @@ +# AgentAdmin 项目文档 + +这里是 AgentAdmin 的项目级文档入口。文档由 Git 管理,直接随代码更新;本项目不要求同步 Wiki、创建工单或经过额外审批。 + +## 建议阅读顺序 + +1. [项目概况](00-project-profile.md):项目定位、技术基线和边界。 +2. [开发工作流](01-workflow.md):从理解需求到验证交付的轻量流程。 +3. [架构与代码地图](02-architecture-and-code-map.md):模块职责、数据流和修改影响。 +4. [业务规则与术语](03-business-rules-and-glossary.md):当前稳定规则和统一名称。 +5. [本地开发与验证](04-local-development-and-verification.md):环境、构建和测试命令。 +6. [常见改动指南](05-common-changes.md):按改动类型定位代码和测试。 +7. [排障指南](06-troubleshooting.md):常见问题的最短检查路径。 + +## Agent 规范 + +任务协议和动作是独立的可执行规范,从 [Agent 文档](agent/README.md) 开始阅读: + +- [协议结构](agent/protocol.md) +- [选择器](agent/selector.md) +- [变量、输出与断言](agent/values-and-outputs.md) +- [执行语义](agent/execution.md) +- [动作索引](agent/actions/README.md) +- [后续能力](agent/roadmap.md) + +`agent/` 中部分文档描述了目标设计。是否已经可用,以动作索引中的实现状态和当前代码为准。 + +## 事实来源 + +发生冲突时,按以下方式处理: + +- 用户当前确认的需求决定本次交付范围。 +- [AGENTS.md](../AGENTS.md) 记录仓库长期开发规则。 +- Gradle 配置、Manifest 和代码决定当前实际行为与版本。 +- `docs/agent/` 记录任务协议和动作约定,但未实现能力不能仅靠文档或 JSON 启用。 + +发现不一致时,应在同一次相关改动中修正文档、实现或测试,不保留互相矛盾的说明。 + +## 文档维护 + +- 修改运行行为时,同步更新对应项目文档和 Agent 规范。 +- 新增动作时,同步更新模型、解析、执行器、动作页和测试。 +- 只记录已经确认的事实;未确定事项放入后续能力文档,并明确为待定。 +- 避免复制同一份详细规则;项目级文档负责导航和代码地图,动作细节留在 `docs/agent/`。