鸿蒙 AI 自动化开发:让 AI 学会自己编译、自己调试

鸿蒙 AI 自动化开发:让 AI 学会自己编译、自己调试
鸿蒙 AI 自动化开发让 AI 学会自己编译、自己调试参考文档当前 AI 开发流程的真正瓶颈用 AI 辅助编码半年后大多数开发者都有一个感受AI 写代码已经够用了但围绕 AI 的人工配合太累了。一个典型的场景你让 AI 在首页加个下拉刷新它几秒钟就写出了代码。然后——你来编译报错了。你把错误信息复制给 AI等它改。改完再编译又报错。你再复制再等。终于编译通过了。你手动启动应用导航到首页操作一遍——发现 UI 不对。你截图描述给 AI再等它改。改完再编译、再部署、再手动验证……整个过程里AI 只负责一件事生成代码。而编译、部署、运行、看界面、判断对不对——全是你在做。你本质上在给 AI 当编译器、调试器和 QA。你的日常工作流 你 → 告诉 AI 需求 AI → 生成代码 你 → 编译 ← 人工 你 → 看报错 ← 人工 你 → 把报错复制给 AI ← 人工 AI → 修复代码 你 → 再编译 ← 人工 你 → 部署到设备 ← 人工 你 → 打开应用看界面 ← 人工 你 → 看日志排查问题 ← 人工 你 → 截图 复制日志给 AI ← 人工 AI → 再修复 ...重复直到你满意问题很明显AI 能写代码但它看不见自己写的代码跑起来是什么样。它不知道编译有没有过不知道界面长什么样不知道日志里有没有报错不知道功能对不对。每一次反馈都需要你手动介入——你就是 AI 的眼睛、耳朵和手。换个思路让 AI 自己编译、自己看界面如果 AI 能自己编译呢编译报错了它自己读错误信息、自己改、自己重新编译——不需要你复制粘贴。如果 AI 能自己部署运行呢改完代码它自己把应用装到设备上、自己启动。如果 AI 能自己看界面呢它能看到当前页面上有哪些元素、文字对不对、按钮在不在、布局是否符合预期——不需要你截图描述。如果 AI 能自己读日志呢它能自己抓取运行日志看到崩溃堆栈、网络请求结果、业务流程走到了哪个分支——不需要你复制粘贴日志。换句话说不是让流水线替人做事而是教会 AI 使用开发者每天都在用的那些工具——hvigor 编译、hdc 部署、uitest 查看 UI、hilog 读日志。AI 一旦拥有了这些能力它就不再是一个只能输出代码片段的文本生成器而是一个能独立完成「编码 → 编译 → 部署 → 验证 → 修复」循环的自主开发者。新的工作流 你 → 告诉 AI 需求 AI → 生成代码 AI → 自己编译 ← AI 自己做 AI → 编译报错自己读错误、自己改、自己重编译 ← AI 自己做 AI → 编译通过 → 自己部署到设备 ← AI 自己做 AI → 自己查看 UI 是否符合预期 ← AI 自己做 AI → 自己读日志检查有没有异常 ← AI 自己做 AI → 不对自己分析 UI 树 日志、自己修复 ← AI 自己做 AI → 输出验证报告含截图 关键日志 你 → 看一眼报告确认通过你的角色从「AI 的编译器和眼睛」变成了「最终审批者」。给 AI 四种能力要实现这个转变需要给 AI 补上四种它目前不具备的能力能力一自己编译、自己修鸿蒙的构建工具 hvigor 可以通过命令行调用./hvigorw--modeproject-pproductdevelop-pbuildModedebug assembleApp编译输出是结构化的——包含文件路径、行号、错误类型和详细描述。AI 完全可以自己跑这个命令自己读输出自己定位问题。具体流程AI 执行 hvigorw 编译 ↓ 编译失败 → AI 解析错误输出 ↓ AI 读取报错文件的对应代码 ↓ AI 修改代码 → 重新编译 ↓ 循环直到编译通过或达到上限比如 5 轮这里有一个关键细节不需要把整个文件发给 AI。编译错误已经告诉你哪个文件哪一行出了什么问题只需要取错误行上下 ±20 行源码就够了。一个 2000 行的文件只发 40 行token 消耗降 98%。另一个细节是错误去重。一个类型定义错误可能触发十几个下游报错「找不到属性」「类型不匹配」……全部喂给 AI 只会干扰判断。正确做法是按优先级排序每轮只处理 Top 错误修完重编译看残留。能力二自己部署、自己运行编译通过后AI 需要把应用装到设备上并启动。HarmonyOS 的hdcHarmonyOS Device Connector提供了完整的命令行接口# 安装应用hdcinstallentry/build/default/outputs/default/entry-default-signed.hap# 启动应用hdc shell aa start-aEntryAbility-baaa这两条命令就是开发者每次手动「跑一下」的自动化版本。AI 执行完就能拿到一个正在运行的应用实例接下来该「看」界面了。能力三自己看界面、自己判断这是最关键、也最有价值的能力。AI 怎么看界面不是靠截图识别——视觉模型的 UI 理解能力不够稳定容易误判。而是靠 UI 树可访问性树。HarmonyOS 的uitest工具可以把当前页面的 UI 层级结构导出为 JSONuitest dumpLayout输出的 JSON 是一棵树每个节点包含组件类型Text、Image、Button、List 等文本内容text属性元素 IDid属性位置坐标bounds是否可见、是否可点击等状态AI 读这棵树就像开发者用 DevTools 检查元素一样——它能看到页面上有什么文字、按钮在哪里、列表是否渲染了数据。这比截图对比稳定得多因为文字断言不受字体、颜色、分辨率的影响。除了看AI 还能操作# 点击指定坐标uitest uiInput click5401200# 滑动uitest uiInput swipe5401500540500500# 输入文字uitest uiInput text搜索内容AI 可以模拟用户操作然后重新 dump UI 树验证操作后的页面状态是否符合预期。能力四自己读日志、自己分析UI 树告诉 AI「界面上有什么」但无法告诉 AI「程序内部发生了什么」。一个按钮在页面上确实存在但点击后没有反应——是回调没触发是网络请求失败了还是数据解析出了异常这些信息只存在于运行日志里。开发者日常调试时最常用的手段之一就是盯着 DevEco Studio 的 Log 面板看输出。AI 同样可以做到——HarmonyOS 的hilog提供了完整的命令行接口# 实时抓取日志按应用进程过滤hdc shell hilog|grepaaa# 按日志级别过滤只看 Error 和 Warnhdc shell hilog--levelE# 按 domain/tag 过滤hdc shell hilog--tagWSRequest# 导出日志到文件hdc shell hilog-e/tmp/app.logAI 读日志能覆盖的场景是 UI 树和截图覆盖不了的问题类型UI 树能发现日志能发现按钮文字错误能不能元素缺失/布局错乱能不能点击后无响应回调未触发不能能网络请求失败/超时不能能数据解析异常JSON 字段缺失不能能空指针/类型转换崩溃不能能状态未更新业务逻辑 bug不一定能换句话说UI 树是 AI 的眼睛日志是 AI 的听诊器。一个看外表一个听内里。两者配合AI 才能做出完整的诊断。实际调试中AI 的典型做法是1. 操作前清空日志缓冲区hilog -r 2. 执行操作click / swipe / 页面跳转 3. 操作后抓取这段时间内的日志按时间范围或 tag 过滤 4. AI 分析日志 - 有 ERROR/Exception → 定位崩溃原因读对应源码修复 - 有网络请求的 URL 和响应码 → 判断接口是否异常 - 有 xlog 输出的业务日志 → 判断业务流程是否走到预期分支 - 日志正常但 UI 不对 → 结合 UI 树分析渲染问题这里有一个实用技巧让 AI 在生成业务代码时在关键分支埋入带特定 tag 的日志。比如// AI 生成的代码中自动加入调试日志xlog.info(PullRefresh,开始刷新当前页码: ${this.page})// ... 请求完成后xlog.info(PullRefresh,刷新完成返回 ${data.length} 条数据)这样 AI 在验证阶段读日志时就能直接看到业务流程是否按预期执行。相当于 AI 给自己装了调试探针——它知道自己在哪些关键位置留了日志读日志时就能快速定位问题。需要注意的是日志量可能很大。一个应用启动后几秒内就可能产生上千条日志。全部发给 AI 会浪费大量 token。正确做法是预处理按 tag 过滤只保留应用自身的日志按级别过滤优先保留 Error 和 Warn截取操作前后的时间窗口。通常经过这些过滤后日志量可以从几千行压缩到几十行足够 AI 做出准确判断。实现方案Python 封装层 AI 调用为什么用 Python主项目是 ArkTS但验证层我们选择了 Python。原因很实际hdc和uitest的 Python 封装生态更成熟社区现成方案多验证脚本与业务代码解耦独立维护不会污染项目代码AI 可以在同一轮对话中同时生成 ArkTS 业务代码和 Python 验证脚本封装层设计Python 层封装一个HdcHelper把 hdc 和 uitest 的命令行调用包装成语义化的函数classHdcHelper:defbuild(self)-BuildResult:执行 hvigorw 编译返回结构化的编译结果...definstall_and_launch(self,bundle_name:str):安装 HAP 包并启动应用...defdump_layout(self)-dict:导出当前页面的 UI 树...defscreenshot(self,name:str)-str:截图并返回本地路径...defclick_text(self,text:str):在 UI 树中找到指定文字并点击...defhas_text(self,text:str)-bool:检查当前页面是否存在某文案...defswipe(self,x1,y1,x2,y2,ms:int):模拟滑动手势...defclear_log(self):清空日志缓冲区...defget_log(self,tag:strNone,level:strNone)-str:抓取日志可按 tag/级别过滤...defget_errors(self)-str:只获取 Error 级别日志...AI 的自主调试循环有了这些能力AI 的工作方式变成了1. AI 根据需求生成/修改代码同时在关键分支埋入调试日志 2. AI 调用 build() 编译 - 失败 → AI 读错误信息读对应源码修改代码回到 2 - 成功 → 继续 3. AI 调用 install_and_launch() 部署并启动应用 4. AI 调用 clear_log() 清空日志缓冲区 5. AI 执行操作click / swipe / 页面跳转 6. AI 调用 dump_layout() 查看当前页面 UI 状态 7. AI 调用 get_log() / get_errors() 抓取运行日志 8. AI 综合诊断 - UI 树异常 → 修改代码回到 2 - 日志中有 ERROR/Exception → 定位崩溃或逻辑错误修改代码回到 2 - 日志中业务流程未走到预期分支 → 修改代码回到 2 - UI 和日志均正常 → 继续 9. AI 调用 screenshot() 截图留档 10. AI 输出验证报告含截图 UI 树快照 关键日志片段注意这个循环里没有人。不是人编译了告诉 AI 结果不是人看了界面告诉 AI 哪里不对不是人翻了日志告诉你哪里报错。AI 自己编译、自己看 UI 树、自己读日志、自己综合诊断、自己修复。验证脚本也可以 AI 生成对于复杂场景AI 在生成业务代码的同时可以同步生成一个 Python 验证脚本deftest_home_pull_to_refresh():hdcHdcHelper()hdc.install_and_launch(aaa)# 等待首页加载asserthdc.has_text(推荐),首页未加载hdc.screenshot(01_home_loaded)# 清空日志准备捕获刷新操作的日志hdc.clear_log()# 执行下拉操作hdc.swipe(540,1500,540,500,500)# 检查日志确认刷新流程走到了预期分支loghdc.get_log(tagPullRefresh)assert刷新完成inlog,刷新流程未完成请检查日志# 验证 UI刷新后数据更新asserthdc.has_text(刚刚更新),下拉刷新未生效hdc.screenshot(02_after_refresh)这个脚本本身也是 AI 生成的——AI 知道需求是「下拉刷新」所以它知道要验证「下拉后数据更新」。脚本运行后的结果通过/失败、截图、UI 树快照同样可以作为 AI 自我修复的输入。整体架构┌──────────────────────────────────────────────┐ │ 开发者 │ │ 输入需求描述 → 等待 → 审批最终结果 │ └─────────────────┬────────────────────────────┘ │ ┌─────────────────▼────────────────────────────┐ │ AI 自主开发循环 │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 生成代码 │──→│ 自己编译 │──→│ 自己部署 │ │ │ │ 埋日志 │ └────┬─────┘ └────┬─────┘ │ │ └──────────┘ │ │ │ │ ↑ 编译失败 │ │ │ │ 自己读错误 │ │ │ │ 自己修改 │ │ │ │ │ │ │ │ │ └──→ 回到修改 ──┘ │ │ │ │ │ │ │ ┌────▼──────┐ │ │ │ │ 清空日志 │ │ │ │ │ 执行操作 │ │ │ │ └────┬──────┘ │ │ │ │ │ │ │ ┌──────────▼───────┐ │ │ ├──── 不对自己改 ←│ 自己看 UI 读日志 │ │ │ │ │ UI 树 hilog │ │ │ │ │ 截图留档 │ │ │ │ └──────────────────┘ │ │ ┌────▼──────────────────────────────────┐ │ │ │ 输出验证报告 │ │ │ │ 代码变更 截图 UI 树快照 关键日志 │ │ │ └───────────────────────────────────────┘ │ └──────────────────────────────────────────────┘实践中踩过的坑1. UI 树的时序问题dumpLayout拿到的是执行那一刻的 UI 快照。页面中的异步内容网络请求、动画渲染可能还没完成AI 就会看到「元素缺失」并误判为 bug。解法引入轮询等待。对预期应出现的元素在 5 秒超时窗口内周期性重试 dump而非一次失败就判定为 bug。页面跳转后设置 1 秒固定延迟再首次 dump。2. 编译错误的级联膨胀一个类型定义错误可能触发十几个下游报错。如果 AI 试图一次性修所有报错很容易改东改西、越改越乱。解法每轮只处理 Top-3 错误按类型错误 语法错误 警告排序。修完重编译很多下游报错会自然消失。3. Token 消耗AI 自己编译、自己看 UI 树意味着每轮循环都要消耗 token。一个需求迭代 5-6 轮下来token 消耗可能是纯代码生成的 3-5 倍。解法分层上下文 按需检索。核心规范固定注入~500 token组件文档按需求关键词动态检索~1000 token不要全量灌入。同时编译错误只发错误行 ±20 行源码UI 树只发相关子树而非整棵树。4. AI 陷入死循环某些情况下 AI 会反复修改同一段代码但始终修不对——比如对某个 ArkUI API 的理解本身就有误。解法设置熔断机制。编译最多重试 5 轮UI 验证最多重试 3 轮。超过上限就终止循环输出完整的错误报告包含所有尝试过的修改和失败原因交给人介入。现在就能做的事你不需要一次性搭完整个自动化系统。但有一件事今天就可以做而且会立刻提升 AI 辅助编码的质量整理你的AGENTS.md。把代码规范、组件索引、架构约定、禁用手法写成 AI 可消费的格式。这份文档做两件事即使没有自动化流水线你每次跟 AI 对话时把它作为上下文喂进去AI 生成的代码质量会显著提升——因为它知道了你项目的规矩。当你准备搭建自动化流水线时这份文档就是 AI 的「项目知识库」直接复用。下一步你可以尝试让 AI 自己跑编译命令、自己读编译输出。大多数 AI 编码助手已经支持执行终端命令——你只需要在 prompt 里告诉它「写完代码后执行./hvigorw ...编译如果报错就自己读错误信息并修复直到编译通过。」再下一步才是接入hdc和uitest让 AI 学会自己看界面。流水线的终点是 AI 全自主但起点是教会 AI 使用工具。