@buaa_smat/hometrans 0.1.15 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +108 -99
  2. package/agents/build-fixer.md +15 -14
  3. package/agents/code-reviewer.md +3 -3
  4. package/agents/logic-coder.md +1 -1
  5. package/agents/logic-context-builder.md +1 -1
  6. package/agents/self-tester.md +16 -13
  7. package/dist/cli/config-store.js +127 -29
  8. package/dist/cli/config.js +9 -2
  9. package/dist/cli/init.js +431 -248
  10. package/dist/cli/uninstall.js +103 -8
  11. package/dist/context/index.js +19 -2
  12. package/env-requirements.json +19 -23
  13. package/package.json +1 -1
  14. package/resource/choose_editor.png +0 -0
  15. package/resource/set_environment.png +0 -0
  16. package/resource/set_multimodel.png +0 -0
  17. package/resource/set_sdk.png +0 -0
  18. package/skills/hmos-batch-ui-align/SKILL.md +8 -6
  19. package/skills/hmos-convert-pipeline/SKILL.md +7 -7
  20. package/skills/hmos-fix-build-errors/SKILL.md +4 -3
  21. package/skills/hmos-incremental-ui-align/README.md +9 -12
  22. package/skills/hmos-incremental-ui-align/SKILL.md +9 -9
  23. package/skills/hmos-incremental-ui-align/scripts/__pycache__/app_feature_verify.cpython-314.pyc +0 -0
  24. package/skills/hmos-incremental-ui-align/scripts/app_feature_verify.py +128 -29
  25. package/skills/hmos-incremental-ui-align/scripts/navigation-capure.md +37 -37
  26. package/skills/hmos-incremental-ui-align/scripts/page_capture.py +7 -2
  27. package/skills/hmos-integration-test/README.md +3 -3
  28. package/skills/hmos-integration-test/SKILL.md +7 -7
  29. package/skills/hmos-spec-generate/SKILL.md +45 -52
  30. package/tools/test-tools/autotest/README.md +10 -11
  31. package/tools/test-tools/autotest/self_test_runner.py +40 -12
  32. package/resource/common_config.png +0 -0
  33. package/resource/integration_test_config.png +0 -0
  34. package/resource/set_env.png +0 -0
  35. package/resource/ui_align_config.png +0 -0
  36. package/skills/hmos-resources-convert/tools/apktool.bat +0 -85
package/README.md CHANGED
@@ -1,33 +1,33 @@
1
1
  # 安卓应用迁移鸿蒙指导
2
2
 
3
+ **HomeTrans工具用于辅助鸿蒙开发者完成原生安卓应用迁移到鸿蒙应用,为应用迁移的各个环节提供能力支持。**
4
+
5
+ **本文档为使用HomeTrans工具进行应用迁移的流程指导。**
3
6
 
4
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
8
+ [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D%2022-339933.svg?logo=node.js&logoColor=white)](https://nodejs.org/en/download)
5
9
 
6
- 本文档为完整的Android到HarmonyOS迁移流程指导。
10
+ [![Claude Code](https://img.shields.io/badge/Claude_Code-supported-blueviolet.svg)](#选择本地editor)
11
+ [![Cursor](https://img.shields.io/badge/Cursor-supported-blueviolet.svg)](#选择本地editor)
12
+ [![OpenCode](https://img.shields.io/badge/OpenCode-supported-blueviolet.svg)](#选择本地editor)
13
+ [![DevEco Code](https://img.shields.io/badge/DevEco_Code-supported-blueviolet.svg)](#选择本地editor)
14
+ [![Codex](https://img.shields.io/badge/Codex-supported-blueviolet.svg)](#选择本地editor)
15
+ [![CodeBuddy](https://img.shields.io/badge/CodeBuddy-supported-blueviolet.svg)](#选择本地editor)
7
16
 
8
17
  ---
9
18
 
10
- ## 步骤0:安装依赖
11
-
12
- ### 0.1安装依赖并连接设备
13
-
14
- 按以下顺序安装(`ht init` 会逐项检测,并提示缺失项对各skill的影响)。各依赖下方均列出了「被依赖」的步骤:如果你不需要执行某依赖所对应的步骤,则可以不安装该依赖(相应skill会显示为受限或不可用,但不影响其它步骤)。
19
+ ## 安装DevEco Studio以及Android Studio
15
20
 
16
- 1. **安装DevEco Studio** — 下载地址:<https://developer.huawei.com/consumer/cn/download/>。安装完成后,配置以下 **PATH环境变量**(`<DevEco安装目录>` 指DevEco Studio的安装根目录):
21
+ 1. **安装DevEco Studio** — 下载地址:<https://developer.huawei.com/consumer/cn/download/>。安装完成后,配置以下 **PATH环境变量**:
17
22
 
18
23
  | 工具 | PATH中加入的目录 |
19
24
  |------|------------------|
20
- | node / npm / npx | `<DevEco安装目录>\tools\node` |
21
25
  | java | `<DevEco安装目录>\jbr\bin` |
22
26
  | hdc | `<DevEco安装目录>\sdk\default\openharmony\toolchains` |
23
27
 
24
- 验证方式:执行 `node -v`、`java -version`、`hdc -v` 均返回正常
28
+ 验证方式:执行 `java -version`、`hdc -v` 均返回正常
29
+
25
30
 
26
- 被依赖:
27
- - 资源转换skill(java可选,缺失时回退读取源码 `res/`)
28
- - 步骤1.2UI对齐(必需)
29
- - 步骤3逻辑代码转换流水线(必需,构建/评审修复)
30
- - 集成测试skill(必需,真机调试)
31
31
  2. **安装Android Studio** — 下载地址:<https://developer.android.com/studio>,并在 **SDK Manager** 中安装SDK。
32
32
 
33
33
  验证方式:执行 `adb version` 返回正常
@@ -35,107 +35,80 @@
35
35
  被依赖:
36
36
  - 步骤1.1UI迁移(可选,仅自动抓取页面快照时需要)
37
37
  - 步骤1.2UI对齐(必需)
38
- 3. **安装uv** — 安装指引:<https://docs.astral.sh/uv/getting-started/installation/>。
39
38
 
40
- 验证方式:执行 `uv --version` 返回正常
39
+ ## 安装Node.js
41
40
 
42
- 被依赖:
43
- - 步骤3逻辑代码转换流水线的自测阶段(可经 `skip_test` 跳过)
44
- - 集成测试skill(必需,AutoTest在uv下运行)
45
- 4. **安装python** — 安装指引:<https://www.python.org/downloads/>,要求 ≥ 3.10。
41
+ 安装 **Node.js(版本需 >= 22)** — 下载地址:<https://nodejs.org/en/download>。
46
42
 
47
- 验证方式:执行 `python --version` 返回正常
43
+ 验证方式:执行 `node -v`、`npm -v`、`npx -v` 均返回正常,且 `node -v` 显示版本不低于 22
48
44
 
49
- 被依赖:
50
- - 步骤1.1UI迁移(必需,页面快照解析脚本)
51
- - 步骤1.2UI对齐(必需,双端页面采集脚本)
52
- 5. **安装 [GitNexus](https://github.com/abhigyanpatwari/GitNexus)** — 执行 `npm install -g gitnexus && gitnexus setup`
45
+ ## 安装HomeTrans
53
46
 
54
- 验证方式:执行 `gitnexus --version` 返回正常
47
+ 执行 `npm install -g @buaa_smat/hometrans`。
55
48
 
56
- 被依赖:
57
- - 步骤2生成需求规格(必需)
58
- 6. **连接设备** — 连接安卓和鸿蒙真机,或启动模拟器
49
+ 验证方式:执行 `hometrans --version` 或 `ht --version` 返回正常
59
50
 
60
- 被依赖:
61
- - 安卓真机/模拟器 — 步骤1 UI迁移
62
- - 鸿蒙真机/模拟器 — 步骤1.2UI对齐
63
- - 鸿蒙**真机** — 步骤3流水线自测阶段、集成测试skill
51
+ ## 环境初始化
64
52
 
65
- ### 0.2安装hometrans
53
+ 执行 `hometrans init` 或 `ht init`。
66
54
 
67
- 执行 `npm install -g @buaa_smat/hometrans`。
55
+ > 如果在PowerShell下运行,命令需要加上 `.cmd` 后缀,如 `hometrans.cmd --version`、`ht.cmd init`。
68
56
 
69
- 验证方式:执行 `hometrans --version` 或 `ht --version` 返回正常
57
+ ### 选择本地editor:
58
+ ![choose_editor.png](https://raw.gitcode.com/SMAT/HomeTrans/raw/main/resource/choose_editor.png)
70
59
 
71
- 然后执行 `hometrans init` 或 `ht init`。
60
+ ### 参数配置:
72
61
 
62
+ #### 配置鸿蒙SDK:
63
+ ![set_sdk.png](https://raw.gitcode.com/SMAT/HomeTrans/raw/main/resource/set_sdk.png)
73
64
 
74
- > 如果在PowerShell下运行,命令需要加上 `.cmd` 后缀,如 `hometrans.cmd --version`、`ht.cmd init`。
65
+ #### 配置多模态模型(不执行UI对齐以及集成测试可以跳过该配置):
66
+ ![set_multimodel.png](https://raw.gitcode.com/SMAT/HomeTrans/raw/main/resource/set_multimodel.png)
67
+
68
+ | 参数 | 含义 |
69
+ |-----------------|---------|
70
+ | `model_api_key` | 用于模型API请求认证的令牌 |
71
+ | `model_name` | 多模态(视觉)模型的名字 |
72
+ | `model_base_url` | 模型API服务的基础地址 |
73
+
74
+ ##### 配置参考
75
+
76
+ 前往[阿里云百炼平台](https://bailian.console.aliyun.com/)开通服务并申请 API Key,选用 Qwen 系列多模态(视觉)模型(如 `qwen3.5-plus`)。
77
+
78
+ | 参数 | 取值 |
79
+ |---|-----------------------------------------------------|
80
+ | `model_api_key` | 百炼控制台申请的 API Key(形如 `sk-xxxxxxxx`) |
81
+ | `model_name` | `qwen3.5-plus` |
82
+ | `model_base_url` | `https://dashscope.aliyuncs.com/compatible-mode/v1` |
75
83
 
76
- ### 0.2.1选择本地editor:
77
- ![choose_editor.png](resource/choose_editor.png)
78
-
79
- ### 0.2.2通用配置:
80
- ![common_config.png](resource/common_config.png)
81
- - `DEVECO_SDK_HOME` — DevEco Studio的sdk目录,其余路径由它派生并校验存在。示例:
82
-
83
- ```text
84
- + DEVECO_SDK_HOME : <DevEco安装目录>\sdk
85
- + DEVECO_HOME : <DevEco安装目录>
86
- + OHOS_SDK_PATH : <DevEco安装目录>\sdk\default\openharmony\ets
87
- + HMS_SDK_PATH : <DevEco安装目录>\sdk\default\hms\ets
88
- ```
89
- ### 0.2.3 UI对齐配置(如果不执行步骤1.2UI对齐,则可以不配置):
90
- ![ui_align_config.png](resource/ui_align_config.png)
91
- - `GLM_API_KEY` — UI对齐中过程中GLM phone agent所用的LLM API key。
92
-
93
- 申请方式:在[智谱官方网站](https://bigmodel.cn/apikey/platform)注册用户后,申请一个API KEY即可,调用的是免费的auto-glm模型,无需充值。
94
-
95
- ### 0.2.4集成测试配置(如果不执行步骤3的自测阶段与集成测试skill,则可以不配置):
96
- ![integration_test_config.png](resource/integration_test_config.png)
97
- - `autotest api_key` — 集成测试agent执行测试用例(真机自测)所用的多模态大模型API key。各配置项含义如下,`init` 环节只配置前4项,其余参数在`config.json`中配置。
98
-
99
- | 参数 | 示例 / 默认值 | 含义 |
100
- |-------------------|--------------|------|
101
- | `name` | `""` | 多模态(视觉)模型的名字 |
102
- | `base_url` | `""` | 模型API服务的基础地址 |
103
- | `api_key` | (需填写) | 用于模型API请求认证的令牌 |
104
- | `provider` | `openai` | 模型API服务的提供方标识,如openai;Azure服务填azure |
105
- | `temperature` | `0.1` | 采样温度 |
106
- | `top_p` | `0.9` | 核采样阈值 |
107
- | `frequency_penalty` | `0.5` | 重复惩罚 |
108
- | `device_sn` | `null` | 设备序列号;`null` 表示自动选用当前连接的设备 |
109
- | `ip` | `127.0.0.1` | 设备连接IP(hdc) |
110
- | `port` | `8710` | 设备连接端口(hdc) |
111
- | `device_log_level` | `debug` | 设备日志级别:debug/info/... |
112
- | `max_steps` | `50` | 单条用例最大执行步数 |
113
- | `verbose` | `true` | 是否输出详细日志 |
114
- | `lang` | `zh` | 输出语言:zh/en |
115
- | `enable_preprocess` | `false` | 执行前是否先用unified_model把用例拆成步骤序列(多一次LLM调用,默认关) |
116
- | `debug_mode` | `null` | 调试会话:`null` 关闭 / `memory` 内存 / `file` 存盘并跑完后起调试服务(:5000) |
117
-
118
- ### 0.2.5将配置信息添加到环境变量:
119
- ![set_env.png](resource/set_env.png)
120
-
121
- ### 0.3准备项目
84
+ #### 将配置信息添加到环境变量:
85
+ ![set_environment.png](https://raw.gitcode.com/SMAT/HomeTrans/raw/main/resource/set_environment.png)
86
+
87
+ ### 准备项目
122
88
 
123
89
  准备 **Android源项目** 与 **HarmonyOS目标项目目录**。
124
90
 
125
91
  ---
126
92
  ## 迁移流程
127
- ![migration_process.svg](resource/migration_process.svg)
93
+ ![migration_process.svg](https://raw.gitcode.com/SMAT/HomeTrans/raw/main/resource/migration_process.svg)
128
94
 
129
95
  ---
130
96
 
131
97
  ## 步骤1:UI迁移
132
98
 
133
- ### 1.1UI迁移(`hmos-batch-ui-align`)
99
+ ### 1.1 UI迁移
100
+
101
+ > 📦 依赖:uv(必需,页面快照解析脚本经 `uv run` 运行,uv 自带 Python);Android Studio + 安卓真机/模拟器(可选,仅自动抓取页面快照时需要)。
134
102
 
135
- > 📦 依赖:python(必需,页面快照解析脚本);Android Studio + 安卓真机/模拟器(可选,仅自动抓取页面快照时需要)
103
+ 打开本地editor(claude code,open code等),在会话中通过 `斜杠/ `或者 `自然语言 `的方式调用skill--hmos-batch-ui-align,并且传递相关参数)
136
104
 
105
+ 斜杠调用方式举例
106
+ ```
107
+ /hmos-batch-ui-align android_project_dir=<安卓项目路径> harmony_project_dir=<鸿蒙项目路径> ui_info_root=<页面快照目录> apk_path=<安卓apk路径>
137
108
  ```
138
- /hmos-batch-ui-align android_project_dir=<安卓项目路径> harmony_project_dir=<鸿蒙项目路径> ui_info_root=<页面快照目录>
109
+ 自然语言调用方式举例
110
+ ```
111
+ 帮我使用skill:hmos-batch-ui-align完成安卓应用页面到鸿蒙应用的迁移,传递的参数是 android_project_dir=<安卓项目路径> harmony_project_dir=<鸿蒙项目路径> ui_info_root=<页面快照目录> apk_path=<安卓apk路径>
139
112
  ```
140
113
 
141
114
  **输入参数**
@@ -146,6 +119,7 @@
146
119
  | `harmony_project_dir` | **必选** | HarmonyOS项目输出路径 |
147
120
  | `ui_info_root` | 可选 | 包含 `page_NNNN_ActivityName` 格式子目录的父目录(每子目录含 `meta.json` + `view.xml` + 可选 `screenshot.png`);不提供时自动通过adb抓取 |
148
121
  | `pages` | 可选 | 显式列出的页面子集(不提供则处理所有页面) |
122
+ | `apk_path` | 可选 | Android APK文件路径;透传给内部的 `hmos-resources-convert`,提供后跳过Gradle构建,直接用apktool解包该APK提取资源 |
149
123
 
150
124
  **输出产物**
151
125
 
@@ -155,13 +129,20 @@
155
129
  | 资源文件 | HarmonyOS项目下 | 页面所需资源(含UI迁移内部触发的资源转换产物) |
156
130
  | 批量转换报告 | HarmonyOS项目下 | 各页面转换结果、缺陷与统计 |
157
131
 
158
- ### 1.2UI对齐(`hmos-incremental-ui-align`,按需)
132
+ ### 1.2 UI对齐(按需)
133
+
134
+ > 📦 依赖:DevEco Studio、Android Studio、uv(必需,双端页面采集脚本经 `uv run` 运行,uv 自带 Python);安卓真机/模拟器 + 鸿蒙真机/模拟器(必需)。
159
135
 
160
- > 📦 依赖:DevEco Studio、Android Studio、python(必需,双端页面采集脚本);安卓真机/模拟器 + 鸿蒙真机/模拟器(必需)
136
+ 打开本地editor(claude code,open code等),在会话中通过 `斜杠/ `或者 `自然语言 `的方式调用skill--hmos-incremental-ui-align,并且传递相关参数)
161
137
 
138
+ 斜杠调用方式举例
162
139
  ```
163
140
  /hmos-incremental-ui-align android_project_dir=<安卓工程路径> harmony_project_dir=<鸿蒙工程路径>
164
141
  ```
142
+ 自然语言调用方式举例
143
+ ```
144
+ 帮我使用skill:hmos-incremental-ui-align完成安卓和鸿蒙应用的页面对齐,传递的参数是 android_project_dir=<安卓工程路径> harmony_project_dir=<鸿蒙工程路径>
145
+ ```
165
146
 
166
147
  **输入参数**
167
148
 
@@ -181,9 +162,9 @@
181
162
 
182
163
  ---
183
164
 
184
- ## 步骤2:生成需求规格(`hmos-spec-generate`)
165
+ ## 步骤2:生成需求规格
185
166
 
186
- > 📦 依赖:GitNexus(必需)。
167
+ > 📦 依赖:homegraph(必需)。
187
168
 
188
169
  > 👤 前置:用户编写 `REQ.txt` 文件 — 以自然语言描述原始需求,如有多个需求则在文件中使用空行进行分隔,需求中建议包含页面跳转路径的说明以及业务逻辑的描述。
189
170
 
@@ -214,9 +195,16 @@
214
195
  8,在播放界面隐藏:开关 默认关闭 打开后如果切换到播放页,则不在悬浮窗区域显示歌词
215
196
  ```
216
197
 
198
+ 打开本地editor(claude code,open code等),在会话中通过 `斜杠/ `或者 `自然语言 `的方式调用skill--hmos-spec-generate,并且传递相关参数)
199
+
200
+ 斜杠调用方式举例
217
201
  ```
218
202
  /hmos-spec-generate requirement_description_file=<需求描述文件路径> android_project_dir=<安卓项目路径> spec_output_dir=<规格输出目录>
219
203
  ```
204
+ 自然语言调用方式举例
205
+ ```
206
+ 帮我使用skill:hmos-spec-generate生成需求spec文档,传递的参数是 requirement_description_file=<需求描述文件路径> android_project_dir=<安卓项目路径> spec_output_dir=<规格输出目录>
207
+ ```
220
208
 
221
209
  **输入参数**
222
210
 
@@ -231,21 +219,28 @@
231
219
  | 产物 | 位置 | 说明 |
232
220
  |------|------|------|
233
221
  | `<feature>-SPEC.md` | `spec_output_dir` | 每个REQ对应一份原子场景规格文档 |
234
- | `.trace/<feature>.md` | `spec_output_dir/.trace/` | 每个REQ对应的代码trace(GitNexus探索结果) |
222
+ | `.trace/<feature>.md` | `spec_output_dir/.trace/` | 每个REQ对应的代码trace(homegraph探索结果) |
235
223
 
236
224
  ---
237
225
 
238
- ## 步骤3:逻辑代码转换流水线(`hmos-convert-pipeline`)
226
+ ## 步骤3:逻辑代码转换流水线
239
227
 
240
- > 📦 依赖:DevEco Studio(必需,构建/评审修复);uv + 鸿蒙真机(集成测试阶段需要,可经 `skip_test` 跳过)。
228
+ > 📦 依赖:DevEco Studio(必需,构建/评审修复);uv + 鸿蒙真机(集成测试阶段需要,可经 `skip_test` 跳过;uv 经 `uv run` 运行 `self_test_runner.py` 并自带 Python)。
241
229
 
242
230
  > 👤 前置:
243
231
  > 1. 如果执行集成测试,需要**编写测试用例文档**输出前置测试用例(非必须,用于测试用例的环境准备等)通过pre_test_case_path参数传递,测试用例通过test_case_path参数传递。
244
232
  > 2. 如果执行集成测试,需要**连接HarmonyOS真机**并且在DevEco Studio中[**配置签名**](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/networkboost-preparations#%E9%85%8D%E7%BD%AE%E7%AD%BE%E5%90%8D)。
245
233
 
234
+ 打开本地editor(claude code,open code等),在会话中通过 `斜杠/ `或者 `自然语言 `的方式调用skill--hmos-convert-pipeline,并且传递相关参数)
235
+
236
+ 斜杠调用方式举例
246
237
  ```
247
238
  /hmos-convert-pipeline android_project_dir=<安卓项目路径> harmony_project_dir=<鸿蒙项目路径> spec_file_path=<需求规格文档路径>
248
239
  ```
240
+ 自然语言调用方式举例
241
+ ```
242
+ 帮我使用skill:hmos-convert-pipeline完成逻辑代码开发,代码检视,集成测试,传递的参数是 android_project_dir=<安卓项目路径> harmony_project_dir=<鸿蒙项目路径> spec_file_path=<需求规格文档路径>
243
+ ```
249
244
 
250
245
  **输入参数**
251
246
 
@@ -275,7 +270,7 @@
275
270
 
276
271
  ---
277
272
 
278
- ## 步骤4:人工验收(👤 用户介入)
273
+ ## 步骤4:人工验收
279
274
 
280
275
  **输入**
281
276
 
@@ -299,15 +294,22 @@
299
294
 
300
295
  以下能力包含在迁移流程中也可按需独立调用。
301
296
 
302
- ### 资源转换(`hmos-resources-convert`)
297
+ ### 资源转换
303
298
 
304
299
  > 📦 依赖:DevEco Studio中的java(可选,缺失时回退读取源码 `res/`)。
305
300
 
306
301
  > ⚠️ 提示:如果步骤1采用 **UI迁移**(`hmos-batch-ui-align`),则跳过当前能力(UI迁移内部已包含资源转换)。
307
302
 
303
+ 打开本地editor(claude code,open code等),在会话中通过 `斜杠/ `或者 `自然语言 `的方式调用skill--hmos-resources-convert,并且传递相关参数)
304
+
305
+ 斜杠调用方式举例
308
306
  ```
309
307
  /hmos-resources-convert android_project_dir=<安卓项目路径> harmony_project_dir=<鸿蒙项目路径> resource_mapping_path=<资源映射文档路径>
310
308
  ```
309
+ 自然语言调用方式举例
310
+ ```
311
+ 帮我使用skill:hmos-resources-convert完成安卓应用到鸿蒙应用的资源转换,传递的参数是 android_project_dir=<安卓项目路径> harmony_project_dir=<鸿蒙项目路径> resource_mapping_path=<资源映射文档路径>
312
+ ```
311
313
 
312
314
  **输入参数**
313
315
 
@@ -316,7 +318,7 @@
316
318
  | `android_project_dir` | **必选** | Android项目根目录路径(含 `build.gradle` 或 `build.gradle.kts`) |
317
319
  | `harmony_project_dir` | **必选** | HarmonyOS项目输出路径 |
318
320
  | `resource_mapping_path` | **必选** | Android ↔ HarmonyOS资源映射文档的完整输出路径(`.md`) |
319
- | `apk_path` | 可选 | Android APK文件路径;提供后跳过Gradle构建和apktool解包,直接从APK提取资源 |
321
+ | `apk_path` | 可选 | Android APK文件路径;提供后跳过Gradle构建,直接用apktool解包该APK提取资源 |
320
322
 
321
323
  **输出产物**
322
324
 
@@ -326,13 +328,20 @@
326
328
  | 资源映射文档 | `resource_mapping_path` | Android ↔ HarmonyOS资源条目映射(`.md`) |
327
329
  | 转换报告 | HarmonyOS项目下 | 资源转换过程与统计 |
328
330
 
329
- ### 集成测试(`hmos-integration-test`,已包含在步骤3的流水线,也可以单独运行)
331
+ ### 集成测试(已包含在步骤3的流水线,也可以单独运行)
330
332
 
331
333
  > 📦 依赖:DevEco Studio(必需,真机调试);uv(必需,AutoTest在uv下运行);鸿蒙真机(必需)。
332
334
 
335
+ 打开本地editor(claude code,open code等),在会话中通过 `斜杠/ `或者 `自然语言 `的方式调用skill--hmos-integration-test,并且传递相关参数)
336
+
337
+ 斜杠调用方式举例
333
338
  ```
334
339
  /hmos-integration-test test_case_path=<测试用例路径> hap_path=<签名HAP路径>
335
340
  ```
341
+ 自然语言调用方式举例
342
+ ```
343
+ 帮我使用skill:hmos-integration-test基于测试用例完成鸿蒙应用的集成测试,传递的参数是 test_case_path=<测试用例路径> hap_path=<签名HAP路径>
344
+ ```
336
345
 
337
346
  **输入参数**
338
347
 
@@ -29,24 +29,25 @@ Execute a build-fix loop: resolve environment → validate project → build →
29
29
 
30
30
  The build requires the **DevEco Studio installation path**, from which Node.js, hvigor, and ohpm are derived.
31
31
 
32
- ### 0a. Read the DevEco environment variables
32
+ ### 0a. Read the DevEco config values
33
33
 
34
- Read these **directly from the OS environment** `ht init` persists them as machine environment variables (`echo "$VAR"` on macOS/Linux; `$env:VAR` in PowerShell on Windows):
34
+ Resolve each value along the standard chain — **OS environment variable first, then `~/.hometrans/config.json` (its `env.*` block), then ask the user**. `ht init` persists these both as machine environment variables and in config.json (read env vars with `echo "$VAR"` on macOS/Linux; `$env:VAR` in PowerShell on Windows):
35
35
 
36
- | Variable | Meaning |
37
- |---|---|
38
- | `DEVECO_SDK_HOME` | DevEco sdk dir, e.g. `D:/DevEco Studio/sdk` — single source of truth |
39
- | `DEVECO_HOME` | DevEco install root, e.g. `D:/DevEco Studio` |
40
- | `OHOS_SDK_PATH` | `<DEVECO_SDK_HOME>/default/openharmony/ets` |
41
- | `HMS_SDK_PATH` | `<DEVECO_SDK_HOME>/default/hms/ets` |
36
+ | Variable | config.json fallback | Meaning |
37
+ |---|---|---|
38
+ | `DEVECO_SDK_HOME` | `env.DEVECO_SDK_HOME` | DevEco sdk dir, e.g. `D:/DevEco Studio/sdk` — single source of truth |
39
+ | `DEVECO_HOME` | `env.DEVECO_HOME` | DevEco install root, e.g. `D:/DevEco Studio` |
40
+ | `OHOS_SDK_PATH` | `env.OHOS_SDK_PATH` | `<DEVECO_SDK_HOME>/default/openharmony/ets` |
41
+ | `HMS_SDK_PATH` | `env.HMS_SDK_PATH` | `<DEVECO_SDK_HOME>/default/hms/ets` |
42
42
 
43
- ### 0b. Resolve the DevEco root `<deveco>` — env vars first, then auto-detect, then ask
43
+ ### 0b. Resolve the DevEco root `<deveco>` — env vars config.json auto-detect ask
44
44
 
45
45
  Stop at the **first** source that yields a path:
46
46
 
47
- 1. **Environment variables**: `DEVECO_HOME` if non-empty → that is `<deveco>`; else `DEVECO_SDK_HOME` → `<deveco>` is its **parent directory**; else (legacy) strip the trailing `/sdk/default/openharmony/ets` from `OHOS_SDK_PATH` (or `/sdk/default/hms/ets` from `HMS_SDK_PATH`) to get `<deveco>`.
48
- 2. **Auto-detect** (0c below).
49
- 3. If both fail, **ask the user** for the DevEco Studio install path (suggest running `ht init` to persist it as an environment variable).
47
+ 1. **OS environment variables**: `DEVECO_HOME` if non-empty → that is `<deveco>`; else `DEVECO_SDK_HOME` → `<deveco>` is its **parent directory**; else (legacy) strip the trailing `/sdk/default/openharmony/ets` from `OHOS_SDK_PATH` (or `/sdk/default/hms/ets` from `HMS_SDK_PATH`) to get `<deveco>`.
48
+ 2. **`~/.hometrans/config.json`**: apply the same derivation to `env.DEVECO_HOME` / `env.DEVECO_SDK_HOME` (read with `uv run --no-project python -c "import json;from pathlib import Path;p=Path.home()/'.hometrans'/'config.json';print((json.loads(p.read_text(encoding='utf-8')).get('env') or {}).get('DEVECO_HOME','') if p.exists() else '')"`).
49
+ 3. **Auto-detect** (0c below).
50
+ 4. If all fail, **ask the user** for the DevEco Studio install path (suggest running `ht init` to persist it as an environment variable).
50
51
 
51
52
  > Example: `DEVECO_SDK_HOME = D:/DevEco Studio/sdk` → `<deveco> = D:/DevEco Studio`.
52
53
 
@@ -58,9 +59,9 @@ From `<deveco>`, derive:
58
59
 
59
60
  Verify these files exist. If they do, use them and skip auto-detection. If an env-sourced path does **not** exist on disk, treat that source as invalid and continue down the resolution order.
60
61
 
61
- ### 0c. Auto-detect if env vars are missing or invalid
62
+ ### 0c. Auto-detect if env vars and config.json are missing or invalid
62
63
 
63
- If the environment variables do not yield a valid install, auto-detect:
64
+ If neither the environment variables nor `~/.hometrans/config.json` yield a valid install, auto-detect:
64
65
 
65
66
  1. **Find DevEco Studio installation**:
66
67
  - Search common locations: `D:\DevEco Studio`, `C:\DevEco Studio`, `C:\Program Files\DevEco Studio`
@@ -33,10 +33,10 @@ Before starting the review, extract the code context for the commit via the `ext
33
33
  - `projectPath`: `<harmony_project_dir>` (absolute path to the HarmonyOS project root containing the `.git` directory)
34
34
  - `commitId`: `<commit_id>` (the git commit to analyze — diffs against its first parent)
35
35
  - `mode`: `"default"` (builds full call graph for call-chain context)
36
- - `ohosSdkPath` / `hmsSdkPath`: the OpenHarmony / HMS SDK ETS directory paths. Resolve each **from the OS environment**, stopping at the first hit:
36
+ - `ohosSdkPath` / `hmsSdkPath`: the OpenHarmony / HMS SDK ETS directory paths. Resolve each along the standard chain — **OS environment variable → `~/.hometrans/config.json` → ask the user** — stopping at the first hit:
37
37
  1. `OHOS_SDK_PATH` / `HMS_SDK_PATH` environment variables; if those are empty but `DEVECO_SDK_HOME` is set, derive them as `<DEVECO_SDK_HOME>/default/openharmony/ets` and `<DEVECO_SDK_HOME>/default/hms/ets`.
38
- 2. Omit the parameter to let the tool read `OHOS_SDK_PATH` / `HMS_SDK_PATH` from the environment itself.
39
- 3. If the environment provides no path that exists on disk, **ask the user** for the DevEco `sdk` directory (and suggest running `ht init` to persist it as an environment variable).
38
+ 2. Omit the parameter to let the `extract_commit_context` tool resolve them itself — it reads `OHOS_SDK_PATH` / `HMS_SDK_PATH` from the OS environment, then falls back to `env.OHOS_SDK_PATH` / `env.HMS_SDK_PATH` in `~/.hometrans/config.json`.
39
+ 3. If neither the environment nor `~/.hometrans/config.json` provides a path that exists on disk, **ask the user** for the DevEco `sdk` directory (and suggest running `ht init` to persist it as an environment variable).
40
40
 
41
41
  2. **On success** — the tool returns the affected code context (diffs, call graphs, impacted files). Treat this response as the **code context** for the review.
42
42
 
@@ -16,7 +16,7 @@ min-model: sonnet
16
16
 
17
17
  Platform context query:
18
18
 
19
- python3 {scripts}/platform_context_query.py \
19
+ uv run --no-project python {scripts}/platform_context_query.py \
20
20
  --request {output_path}/platform-context-request.json \
21
21
  --out-dir {output_path}/platform-context-{N}
22
22
 
@@ -16,7 +16,7 @@ min-model: sonnet
16
16
 
17
17
  Platform context query:
18
18
 
19
- python3 {scripts}/platform_context_query.py \
19
+ uv run --no-project python {scripts}/platform_context_query.py \
20
20
  --request {output_path}/platform-context-request.json \
21
21
  --out-dir {output_path}/platform-context-{N}
22
22
 
@@ -38,16 +38,19 @@ You are a self-tester for HarmonyOS applications. You run a single pipeline: par
38
38
 
39
39
  ### AutoTest Directory Locator
40
40
 
41
- Used independently by S5 and T4. The AutoTest tools are installed by `ht init` under the HomeTrans tools dir; resolve their location from config rather than searching the filesystem.
41
+ Used independently by S5 and T4. The AutoTest tools are installed by `ht init` under the HomeTrans tools dir; resolve their location along the standard config chain — **OS environment variable → `~/.hometrans/config.json` → filesystem walk-up** — rather than searching the filesystem first.
42
42
 
43
- **Primaryread `HOMETRANS_TOOL_PATH` directly from the OS environment.** The autotest dir is `<HOMETRANS_TOOL_PATH>/test-tools/autotest`:
43
+ **Tier 1 OS environment variable `HOMETRANS_TOOL_PATH`; Tier 2 `env.HOMETRANS_TOOL_PATH` in `~/.hometrans/config.json`.** The autotest dir is `<tool_path>/test-tools/autotest`:
44
44
 
45
45
  ```bash
46
46
  tool_path="$HOMETRANS_TOOL_PATH"
47
+ if [ -z "$tool_path" ]; then \
48
+ tool_path="$(uv run --no-project python -c "import json,os; from pathlib import Path; cfg=Path.home()/'.hometrans'/'config.json'; print((json.loads(cfg.read_text(encoding='utf-8')).get('env') or {}).get('HOMETRANS_TOOL_PATH','') if cfg.exists() else '')" 2>/dev/null)"; \
49
+ fi
47
50
  if [ -n "$tool_path" ] && [ -d "$tool_path/test-tools/autotest" ]; then echo "$tool_path/test-tools/autotest"; fi
48
51
  ```
49
52
 
50
- If the `HOMETRANS_TOOL_PATH` environment variable is unset or invalid, **fall back** to walking up from `<output_path>` for a sibling `test-tools/autotest` (then `agents/test-tools/autotest` for legacy layouts) — **anchor the search at `<output_path>`, the sub-agent cwd is not guaranteed**:
53
+ If neither the env var nor `~/.hometrans/config.json` yields a valid tool path, **fall back** (Tier 3) to walking up from `<output_path>` for a sibling `test-tools/autotest` (then `agents/test-tools/autotest` for legacy layouts) — **anchor the search at `<output_path>`, the sub-agent cwd is not guaranteed**:
51
54
 
52
55
  ```bash
53
56
  d="<output_path>"; while [ "$d" != "/" ] && [ "$d" != "" ]; do \
@@ -195,7 +198,7 @@ cd "<autotest_dir>" && uv run python testcases_tool.py generate "<output_path>/_
195
198
  **Sanity-check `[PRE]` ordering** — run this command **if and only if** a `pre_test_case.md` was found and extracted in S4.1. If no pre-cases were extracted, skip this step entirely (the assertion would spuriously fail on an empty `pre` list):
196
199
 
197
200
  ```bash
198
- python -c "import json,sys; d=json.load(open(sys.argv[1],encoding='utf-8')); pre=[i for i,c in enumerate(d) if c['case_name'].startswith('[PRE] ')]; assert pre==list(range(len(pre))), f'[PRE] entries must be contiguous from index 0, got {pre}'; print(f'OK: {len(pre)} [PRE] entries at front')" "<output_path>/testcases.json"
201
+ uv run --no-project python -c "import json,sys; d=json.load(open(sys.argv[1],encoding='utf-8')); pre=[i for i,c in enumerate(d) if c['case_name'].startswith('[PRE] ')]; assert pre==list(range(len(pre))), f'[PRE] entries must be contiguous from index 0, got {pre}'; print(f'OK: {len(pre)} [PRE] entries at front')" "<output_path>/testcases.json"
199
202
  ```
200
203
 
201
204
  If assertion fails, edit `_extracted.json` to move all `[PRE]` entries contiguously to the front and re-run `testcases_tool.py`.
@@ -219,7 +222,7 @@ test -f "<hap_path>" && mkdir -p "<output_path>" && test -f "<output_path>/testc
219
222
  If `setup=false`, additionally verify each JSON parses and `testcases.json` is non-empty:
220
223
 
221
224
  ```bash
222
- python -c "import json,sys; t=json.load(open(sys.argv[1],encoding='utf-8')); m=json.load(open(sys.argv[2],encoding='utf-8')); assert isinstance(t,list) and len(t)>0, 'testcases.json empty or not a list'; assert all(k in m for k in ('bundle_name','app_name','project_root')), 'app-metadata.json missing required fields'; print('OK')" "<output_path>/testcases.json" "<output_path>/app-metadata.json"
225
+ uv run --no-project python -c "import json,sys; t=json.load(open(sys.argv[1],encoding='utf-8')); m=json.load(open(sys.argv[2],encoding='utf-8')); assert isinstance(t,list) and len(t)>0, 'testcases.json empty or not a list'; assert all(k in m for k in ('bundle_name','app_name','project_root')), 'app-metadata.json missing required fields'; print('OK')" "<output_path>/testcases.json" "<output_path>/app-metadata.json"
223
226
  ```
224
227
 
225
228
  If any check fails, write a `self-test-report.md` using the sentinel format from Shared Utilities. The `reason:` line names the specific failure, e.g.:
@@ -246,17 +249,17 @@ Record the device serial number.
246
249
 
247
250
  ### T4 — Locate AutoTest Directory & Verify autotest config
248
251
 
249
- Find the `test-tools/autotest` directory using the **AutoTest Directory Locator** in Shared Utilities (OS env var `HOMETRANS_TOOL_PATH` → walk up from `<output_path>`). If not found, write a `self-test-report.md` with the sentinel format (`status: FAIL` / `reason: AutoTest directory not found from HOMETRANS_TOOL_PATH env var or output_path`), then stop.
252
+ Find the `test-tools/autotest` directory using the **AutoTest Directory Locator** in Shared Utilities (OS env var `HOMETRANS_TOOL_PATH` → `env.HOMETRANS_TOOL_PATH` in `~/.hometrans/config.json` → walk up from `<output_path>`). If not found, write a `self-test-report.md` with the sentinel format (`status: FAIL` / `reason: AutoTest directory not found from HOMETRANS_TOOL_PATH env var or output_path`), then stop.
250
253
 
251
254
  Set `<autotest_dir>` to the found path.
252
255
 
253
- The AutoTest configuration now lives in the `autotest` block of `~/.hometrans/config.json` (it replaced the old `config.yaml`). `self_test_runner.py` reads it at run time and materializes a transient YAML for `AutoTest.batch` — you do **not** create or edit any YAML. Just verify the config is usable: the `autotest` block exists with a real `api_key`, **or** the `TEST_API_KEY` OS environment variable is set (the runner uses it to fill a placeholder/empty key).
256
+ The model config is shared with UI alignment and resolved along the standard chain **env var → `~/.hometrans/config.json` ask**. `self_test_runner.py` reads it at run time (env `HOMETRANS_MODEL_API_KEY` overrides `autotest.unified_model.api_key`; legacy `TEST_API_KEY` still honored as a fallback) and materializes a transient YAML for `AutoTest.batch` — you do **not** create or edit any YAML. Just verify the api_key is usable: the `HOMETRANS_MODEL_API_KEY` (or legacy `TEST_API_KEY`) OS environment variable is set, **or** the `autotest` block in `~/.hometrans/config.json` has a real (non-placeholder) `api_key`.
254
257
 
255
258
  ```bash
256
- python -c "import json,os,sys; from pathlib import Path; cfg=Path.home()/'.hometrans'/'config.json'; tp=os.environ.get('HOMETRANS_TOOL_PATH'); cand=(Path(tp).parent/'config.json') if tp else None; cfg=cand if (cand and cand.exists()) else cfg; at=(json.loads(cfg.read_text(encoding='utf-8')).get('autotest') or {}) if cfg.exists() else {}; real=any(isinstance(at.get(k),dict) and str(at[k].get('api_key','')).strip() not in ('','YOUR_API_KEY_HERE') for k in ('unified_model','execute_model','decision_model')); print('OK' if (real or os.environ.get('TEST_API_KEY','').strip()) else 'MISSING')"
259
+ uv run --no-project python -c "import json,os,sys; from pathlib import Path; cfg=Path.home()/'.hometrans'/'config.json'; tp=os.environ.get('HOMETRANS_TOOL_PATH'); cand=(Path(tp).parent/'config.json') if tp else None; cfg=cand if (cand and cand.exists()) else cfg; at=(json.loads(cfg.read_text(encoding='utf-8')).get('autotest') or {}) if cfg.exists() else {}; real=any(isinstance(at.get(k),dict) and str(at[k].get('api_key','')).strip() not in ('','YOUR_API_KEY_HERE') for k in ('unified_model','execute_model','decision_model')); env=os.environ.get('HOMETRANS_MODEL_API_KEY','').strip() or os.environ.get('TEST_API_KEY','').strip(); print('OK' if (env or real) else 'MISSING')"
257
260
  ```
258
261
 
259
- If this does not print `OK` (no `autotest` block with a real `api_key`, and no `TEST_API_KEY` in the OS environment), write `self-test-report.md` with the sentinel format (`status: FAIL` / `reason: autotest api_key not configured — set TEST_API_KEY env var or run ht init`), then stop.
262
+ If this does not print `OK` (no `HOMETRANS_MODEL_API_KEY` in the OS environment, and no `autotest` block with a real `api_key`), write `self-test-report.md` with the sentinel format (`status: FAIL` / `reason: model api_key not configured — set HOMETRANS_MODEL_API_KEY env var or run ht init`), then stop.
260
263
 
261
264
  ### T5 — Clean Task Directory
262
265
 
@@ -267,7 +270,7 @@ rm -rf "<output_path>/task" && echo "Task directory cleaned" || echo "Task direc
267
270
  ### T6 — Run self_test_runner.py
268
271
 
269
272
  > 🚨 **MANDATORY**: Environment setup, HAP installation, and test execution are all handled by a **single invocation** of `self_test_runner.py run`. The script synchronously executes:
270
- > 1. Read & validate the `autotest` config from `~/.hometrans/config.json` (filling the api_key from `TEST_API_KEY` if needed) and materialize a transient YAML for AutoTest.batch
273
+ > 1. Read & validate the `autotest` config from `~/.hometrans/config.json` (env `HOMETRANS_MODEL_API_KEY` overrides the api_key; legacy `TEST_API_KEY` honored as a fallback) and materialize a transient YAML for AutoTest.batch
271
274
  > 2. `uv sync` — installs `harmony-autotest` + `hypium_mcp`
272
275
  > 3. `hdc uninstall` + `hdc install -r`
273
276
  >
@@ -281,7 +284,7 @@ rm -rf "<output_path>/task" && echo "Task directory cleaned" || echo "Task direc
281
284
  > - ❌ Writing a shell loop or Python loop to iterate over cases yourself
282
285
 
283
286
  ```bash
284
- cd "<autotest_dir>" && python self_test_runner.py run --testcases "<output_path>/testcases.json" --hap "<hap_path>" --bundle-name "<bundle_name>" --category "<app_name>" --task-dir "<output_path>/task" --output-dir "<output_path>"
287
+ cd "<autotest_dir>" && uv run --no-project python self_test_runner.py run --testcases "<output_path>/testcases.json" --hap "<hap_path>" --bundle-name "<bundle_name>" --category "<app_name>" --task-dir "<output_path>/task" --output-dir "<output_path>"
285
288
  ```
286
289
 
287
290
  Record the `pid` and `task_subdir` from the output.
@@ -291,7 +294,7 @@ Record the `pid` and `task_subdir` from the output.
291
294
  Each poll MUST include `sleep 60`. **Use `timeout: 120000` on each Bash call** so the 60-second sleep plus the status command have headroom and the status check itself isn't truncated:
292
295
 
293
296
  ```bash
294
- sleep 60 && cd "<autotest_dir>" && python self_test_runner.py status --task-dir "<output_path>/task" --output-dir "<output_path>"
297
+ sleep 60 && cd "<autotest_dir>" && uv run --no-project python self_test_runner.py status --task-dir "<output_path>/task" --output-dir "<output_path>"
295
298
  ```
296
299
 
297
300
  | `status` | Meaning | Exit code | Action |
@@ -310,7 +313,7 @@ sleep 60 && cd "<autotest_dir>" && python self_test_runner.py status --task-dir
310
313
 
311
314
  **Polling rules:**
312
315
  - Max iterations: **N_cases × 6** (each case takes ~6 minutes). For 8 cases → max 48 polls. If still `RUNNING` after that, kill and write TIMEOUT report.
313
- - **Timeout kill**: `cd "<autotest_dir>" && python self_test_runner.py kill --task-dir "<output_path>/task"`. This verifies the PID belongs to an `AutoTest.batch` process before terminating it.
316
+ - **Timeout kill**: `cd "<autotest_dir>" && uv run --no-project python self_test_runner.py kill --task-dir "<output_path>/task"`. This verifies the PID belongs to an `AutoTest.batch` process before terminating it.
314
317
  - **CRASHED**: Write CRASHED report with sentinel (`status: FAIL` / `reason: AutoTest batch crashed`). Include the `log_tail` from the status response. `task_results.jsonl` is unavailable.
315
318
  - **TIMEOUT**: After killing, write TIMEOUT report with sentinel (`status: FAIL` / `reason: AutoTest batch timed out after N polls`) and include partial results from `task_results.jsonl` if any cases finished.
316
319