手机任务执行器(AI → AutoJS)
用途
把 PC 端的 AI 视作"大脑",手机端的 AutoJS 视作"双手":用户用一句话描述要在手机上做的事,AI 拆解成步骤链,逐步下发到手机执行,全部做完或失败才向用户汇报一次。
用户侧使用教程:
<skill_dir>/使用示例.md——按场景整理的「用户对 AI 说什么」示例集(操控手机/看屏幕/传文件/长任务/沉淀模板与项目/安全边界)。新用户首次使用、或用户问"能做什么/怎么用"时,主动推荐该文档。
典型使用人群:能说话打字但行动不便的用户——语音转文字 → AI → 手机,间接控制手机。
省 token 设计(贯穿本技能,必须遵守)
本技能面向长期高频使用者,AI 算力要花钱,每一轮交互都要省 token:
- 只传路径不传代码:模板脚本存 PC 一份(
scripts/tasks/),下发时只传path+args(几十字节),手机按名从中继下载执行; - 极简回执:模板默认只回
{ok:1}/{ok:0, err:"原因"}。AI 不得要求脚本回传整棵 UI 树或大段文本; - 全自动连跑:中间步骤不产生用户对话,逐步静默执行,终态一次性汇报;
- 截图代替读屏:需要"看"屏幕时用
GET /screenshot(二进制直传 PC 落盘,不经过 AI 上下文),AI 再用 Read 读图。禁止让手机回传整棵 UI 控件树 JSON(即 dump 整屏控件的原始大 JSON);但允许用inspect_control_*等模板结构化地只取回需要的text/id/desc,见「第 3 步」回退链第三级。(注:Read读图依赖调用方模型是否多模态——非多模态模型读图会被过滤,属正常现象,按「第 3 步:看屏幕」里的规则处理:先present_files把图展示给用户,AI 自己读不到就用ocr/inspect_control_*/问用户替代,不要武断判定模型能力。) - 模板两级读取:规划时只跑
node scripts/scan-tasks.js拿全部模板的 name+description(不读脚本、不读正文);选中模板后才 Read 它的tasks/<name>/TASK.md全文。description 即选择依据,正文即决策契约。 - 2K 文本预算:任务回执进入上下文前由
run-task.js硬性把关——超过 2000 字符自动截为「400 字预览 + 全文落盘路径」(scripts/task-results/<taskId>.txt,resultTruncated:true);OCR 大屏文字优先用{"query":"关键词"}过滤在源头减量(见 ocr 模板)。
前置条件(手机端四项权限,缺一不可)
手机上必须安装 AutoJS6 应用。AutoJS6官网:https://docs.autojs6.com/#/
- 无障碍服务:设置 → 应用 → AutoJs6 → 无障碍 → 开启;
- 截图权限:手机端脚本启动时自动申请,弹窗点"立即开始";
- 悬浮窗权限:设置 → 应用 → AutoJs6 → 权限管理 → 悬浮窗 → 允许;
- 后台运行:设置 → 应用 → AutoJs6 → 省电策略设为"无限制",并在自启动管理中允许自启动(否则锁屏/切后台后常驻客户端被系统杀掉,任务中断)。
约定
<skill_dir>= 本技能根目录(SKILL.md 所在目录)。- AI 现场写的一次性脚本,写到
<skill_dir>/temp/目录下。 - AI 端要写 AutoJS 多文件工程(要部署到手机的项目),统一写到
<skill_dir>/scripts/autojs-project/<工程名>/目录(每个工程一个子目录,内部结构参照同目录的autojs-min-project-template范本)。该目录已预置project1/空位可直接使用,scripts/autojs代码参考例子/autojs-projects/ColorWheel这个是一个autojs的色轮界面的project可以参考。一次性单文件临时脚本仍放temp/(见「现场脚本规范」)。工程编码硬约束(ES5 / var only 等)见「部署真实工程 → 工程代码编写规范」。 - 默认端口 9421。改动须同步三处:①
curl localhost:9421/health;②autojs-task-phone-client.js的SERVER_PORT;③run-task.js的DEFAULT_URL。 - Shell 路径约定(硬规则):本机下发命令走 Git Bash(POSIX shell),路径分隔符一律用正斜杠
/(如/c/Users/...)。**严禁在命令里写 Windows 反斜杠\**——POSIX shell 把\当转义符,会把它悄悄吞掉,导致skills\autojs变成skillsautojs、路径拼接错、cd/命令找不到文件。推荐先cd进技能目录(POSIX 正斜杠形式,本环境已验证可用),再用相对路径scripts/run-task.js调脚本 + 只写模板名,连tasks/...长路径都不用拼。 - MSYS 参数改写陷阱(本环境实测):Git Bash 会把以
/开头的参数(如--target-dir /sdcard/Download)自动改写成 Windows 路径(实测/sdcard/Download被改成D:/software/Git/Git/sdcard/Download,手机端拼出非法路径下发失败)。给--target-dir、delete-folder --path这类手机路径参数传/sdcard形态时,命令前必须加MSYS_NO_PATHCONV=1(如MSYS_NO_PATHCONV=1 node scripts/pc-to-phone.js a.txt --target-dir /sdcard/Download)。 - node 参数路径陷阱(本环境实测):把脚本绝对路径直接作为 node 参数时,
/c/Users/...这种 POSIX 形式会被 Windows 版 node 当成「当前盘根下的相对路径」(如解析成d:\c\Users\...)而找不到文件。正确做法见上:先cd进技能目录、再node scripts/run-task.js ...;若一定要给 node 传绝对脚本路径,请用带盘符前缀的C:/Users/.../run-task.js,不要写/c/Users/.../run-task.js。
手机端目录架构 v3(scripts-from-computer)
手机端 AutoJS 脚本根目录(files.getSdcardPath() + "脚本" 动态拼接,全链路禁止硬编码物理路径)下:
- 用户自己写的脚本:永远留在根目录,本技能绝不触碰(技能自身也不在根目录留任何文件);
scripts-from-computer/:本技能从 PC 下发的一切产物的隔离区——client/常驻客户端本体(自更新直接落位、可手动启动;客户端启动时「自归位」到这里);single/模板单脚本 + 临时探针脚本(run-task 下发落位);project/<工程名>/AI 项目工程(deploy-project 部署、run-project 运行、delete-project 清理);data/配套数据(task-args/<taskId>.json按单参数、relay-config.json中继地址、beep.wav等资源);files/PC 传给手机的一般文件缺省落点(pc-to-phone / send-file-to-phone 不显式指定--target-dir时)。
- 命名规范:本技能新建的文件夹/文件一律小写中划线(kebab-case),避免大小写歧义导致的找不到文件。
脚本清单
scripts/autojs-relay-server.js:PC 端中继服务(HTTP + WebSocket,Node.js ES6),AI 启动。架构细节见scripts/relay/ARCHITECTURE.md。scripts/autojs-task-phone-client.js:手机端常驻客户端(严格 ES5,变量一律 var),用户复制到手机 AutoJs6 运行。保活、断线重连、按名下载脚本执行、回传结果。scripts/run-task.js:AI 侧桥接脚本——把模板名/脚本文件 + 参数 POST 到中继/run(异步任务单),默认轮询任务单最多 30 秒等回执并打印(外壳形状与旧版兼容);长任务加--wait 0立即返回 taskId。四种调用方式与路径硬规则见「第 2 步」;任务单控制:--status <taskId>(查状态/进度/结果,跨会话可查)、--stop <taskId>(强杀)、--list [数量](列最近任务单)。不带参数运行打印完整用法。scripts/self-test.js:一键回归自测——健康检查、参数/剪贴板往返、截图压缩、delete-path 护栏、工程全生命周期、任务单列表一次跑完,输出 ✅/❌ 汇总与退出码。改中继/客户端/模板后跑它即可自证未改坏(node scripts/self-test.js)。scripts/get-lan-ip.js:取电脑局域网 IP(node <skill_dir>/scripts/get-lan-ip.js --first),手机填 IP 时用。详见references/获取电脑局域网IP.md。scripts/pc-to-phone.js:把电脑上的任意文件传到手机(PC→手机 通道一键入口,高频刚需)。node scripts/pc-to-phone.js <本地文件> [--target-dir <手机目录>] [--target-name <手机文件名>] [--keep]用法要点:路径一律以技能目录为基准写相对路径;<本地文件>是数据参数(要传输的文件),别和 node 脚本路径搞混;--target-dir缺省经 /health 动态推导为scripts-from-computer/files/(显式指定则指哪打哪),--keep保留电脑中转副本(默认回执后清理)。反方向(手机→电脑)用模板download-file。scripts/deploy-project.js:把电脑上的 AutoJS 多文件工程(含图片/音频等资源)部署到手机并运行——复杂工程(多模块 / 带资源,单文件模板装不下)用它而非单文件模板。用法node scripts/deploy-project.js <工程目录> [--name <工程名>] [--main <入口.js>] [--run|--no-run] [--args '<json>'] [--keep],参数默认值与机制见「部署真实工程(多文件 + 资源)」一节。scripts/run-project.js:运行已部署到手机的工程(不重新下发文件)。换参数反复跑已部署工程时用。用法node scripts/run-project.js <工程名> [--main <入口.js>] [--args '<json>'] [--wait 秒](与 run-task.js 同一套任务单模型:默认等 30 秒回执,--wait 0立返 taskId)。scripts/update-phone-client.js:PC 一键更新并重启手机端常驻客户端(免手动)。手机端代码改动后跑它即完成「下发新版直接落到scripts-from-computer/client/(覆盖)+ 触发自重启」。用法node scripts/update-phone-client.js(默认用技能自带客户端),或--path <其他位置的客户端.js>(数据参数,非脚本路径)。机制见「自动更新手机客户端」一节。scripts/delete-project.js:删除手机上已部署的工程(清理用)。node scripts/delete-project.js demo(删scripts-from-computer/project/demo)或--path <任意 sdcard 存储内路径>。手机端带安全护栏:传入路径先规范化(解析符号链接与..),只放行 sdcard 存储内路径。scripts/tasks/<name>/:任务模板库,每个任务一个文件夹,内含<name>.js(脚本)与TASK.md(说明书)。AI 规划时先跑scripts/scan-tasks.js扫描全部模板的 name+description 挑模板(成功任务的历史实测耗时会自动附为描述末尾的[平均 X 秒]——截尾平均:去掉 1/3 最大与 1/3 最小后取均值,剔除冷启动/弹窗干扰离群值;滚动保留最近 10 次),选中后才 Read 对应tasks/<name>/TASK.md全文。开发者新建/扩展模板见references/AI_新建模板手册.md(AI 建模板总手册:决策流程 + 分类骨架 + 自检清单,照抄即可扩展)。scripts/scan-tasks.js:扫描任务模板库,只提取每个TASK.md前言的 name+description。node scripts/scan-tasks.js输出 JSON(给 AI 规划用,最省 token);node scripts/scan-tasks.js --human输出「共 N 个 + 可读清单」(给用户朗读用)。中继GET /templates也复用同一份扫描逻辑。
参考文档(references)
<skill_dir>/references/ 下是手机端 AutoJs6 API 与建模板的权威参考,按需查阅(写/改脚本前翻对应文档,少踩坑):
references/autojs6_device_docs.md— 设备(Device)模块:device.width/device.height取分辨率、getBattery()电量、getMusicVolume()音量、亮度、vibrate()振动等。要拿屏幕宽高或设备信息就查它。references/AutoJs6_Engines_引擎文档.md— UiSelector / 控件定位 API:text()/id()/bounds()/desc()选择器与engines引擎管理。写inspect_control_*/tap-text等控件类脚本必查。references/autojs6_images_doc.md— images 图片模块:captureScreen()截图、images.clip()裁剪、images.toBytes()转字节。写screenshot/crop-screenshot必查。references/AutoJS6-OCR文档.md— OCR 文字识别:屏幕文字提取的参数与用法。写ocr模板必查。references/autojs6_http_doc.md— http 网络请求模块:发 HTTP 请求的用法(手机端回传数据时底层用得到)。references/AutoJS6_Files_Doc.md— files 文件读写模块:files.read()/files.write()等,模板读任务单注入的__TASK_ARGS_PATH参数文件即依赖它。references/现场脚本规范.md— 现场脚本规范(原正文三大段之一,按需读):temp/ 一次性脚本约定、标准回执骨架、建文件 vs 建目录高频坑。references/部署真实工程.md— 部署真实工程:多文件工程结构、deploy/run/delete-project 全流程与硬约束。references/自动更新手机客户端.md— 自动更新手机客户端:update-phone-client 自举机制与假死排障。references/截图权限与弹框处理.md— 截图权限与"立即开始"弹框:凡captureScreen()/ocr()的脚本,必须内置「后台点立即开始 + requestScreenCapture + sleep」前置代码,照此文档加。references/获取电脑局域网IP.md— 取电脑局域网 IP:手机连 PC 中继时填的 IP 怎么拿(脚本已自动排除虚拟网卡 / Clash fake-ip)。references/手机端常驻客户端说明.md— 手机端常驻客户端与连接状态悬浮球:客户端职责与指令清单、悬浮球三色(红=未连接/绿=已连接/蓝=任务执行中)、呼吸/拖动/吸附行为、可调常量,及「截图中悬浮球恒为蓝色属正常」的排障说明。改客户端代码或调悬浮球时查阅。references/手机连接排障.md— 手机未连接五步排障:取 IP、改 SERVER_IP、手机跑客户端、权限/WiFi 检查、连接确认(「手机未连接时的处理」完整版)。references/AI_新建模板手册.md— AI 新建/扩展模板总手册:决策流程 + 分类骨架 + 核心规范 + 自检清单,照抄即可扩展新模板(详见「现场脚本规范」节引用)。references/AI_AutoJS编码强制规范.md— 写任何手机端 JS 脚本前必读:严格 ES5(var only)、UI 线程禁止 sleep/耗时、耗时 API 必须threads.start多线程、颜色字面量 int 溢出等底层硬约束 + 编码前自检清单。本技能最高频的"静默崩溃/卡死/超时"都源于违反它,写/改 JS 前先读。references/引擎_self_识别与isSelf判定.md— 判断"某引擎是不是自己"(isSelf / 自保护):为什么不能用eng === myEngine、正确的单 id 要素判定法(已废弃旧的 id+文件名双要素)、防御式写法与临时名陷阱,附id/source/cwd三字段真机实测取证表。凡写list-running-scripts/stop-script-by-id/ 任何要标 self 或自保护的模板必查。scripts/autojs代码参考例子/— AutoJS JS 代码例子库:一批可直接参考的 .js 示例。以后写/改手机端 JS 脚本遇到 API 用法或写法问题,去 scripts/autojs代码参考例子/ 下按分类翻
执行 SOP(AI 必须按此顺序)
安装依赖是前提
cd scripts && npm install
第 0 步:健康检查
curl -s http://localhost:9421/health 2>/dev/null | grep -q '"status":"ok"'
- 命令失败/无响应 → 中继没启动:
node <skill_dir>/scripts/autojs-relay-server.js启动,等约 1 秒再跑 health 确认(已在跑就绝不重启——重复启动会触发端口清理、踢掉已连手机;脚本自带指纹自保护兜底)。 {"phone":"connected"}→ 进入第 1 步。{"phone":"disconnected"}→ 走「手机未连接时的处理」。
第 1 步:拆解任务(两级读取,省 token)
把用户的一句话拆成步骤链。先跑 node <skill_dir>/scripts/scan-tasks.js 拿全部模板的 name+description 挑模板(两级读取原则见「省 token 设计」#5);选中某模板后,才 Read 它的 tasks/<name>/TASK.md 全文,理解场景/坑/兜底,必要时按「临时副本优先」改脚本再下发。模板覆盖不了的步骤才现场写脚本(写入 <skill_dir>/temp/,遵守「现场脚本规范」)。
第 2 步:逐步下发(模板优先)
run-task.js 已 cwd 无关,推荐用模板名直接调用,无需拼 tasks/... 长路径(模板名自动解析成 tasks/<name>/<name>.js 下发手机按名下载):
# 推荐:先 cd 到技能目录(<skill_dir> = 本技能根目录,即 autojs-task-runner-yashu/;用相对路径,别写死你电脑的绝对路径),再用相对路径调脚本 + 模板名
cd <skill_dir> && \
node scripts/run-task.js open-app --args '{"name":"MT管理器"}'
# 等价写法:node scripts/run-task.js --path tasks/open-app/open-app.js --args '{"name":"MT管理器"}'
# 等价写法:node scripts/run-task.js --name open-app --args '{"name":"MT管理器"}'
**路径硬规则(必须记牢,本技能最易踩的坑)**:分隔符一律正斜杠
/禁反斜杠\;node 参数禁用/c/...形式绝对路径;任务参数只写模板名不手拼tasks/...——三条的唯一权威说明见上方「约定」节。
- 响应
{"success":true,"taskId":"...","status":"success","result":"{\"ok\":1}"}→ 该步成功,继续下一步(result 是 JSON 字符串,需再解析一次;taskId 是任务单号,报错排障时引用它)。注意status字段是任务单生命周期状态(submitted/running/success/failed/stopped):success只代表「任务单正常跑完并拿到回执」,业务成败要看result里的ok——如启动期失败(脚本 404)时status仍为success而result.ok=0、result.phase="client";中继侧提交超时熔断则result.phase="relay"; {"ok":0,"err":"..."}→ 立即换策略重试一次(如 tap-text 找不到就截图看屏幕),仍失败则终止并向用户汇报卡在哪一步;- 长/短任务判断(经验法则):① 单一原子操作(点击/滑动/按键/截屏/开 App 等,耗时恒定且 <30 秒)→ 短,走默认同步等待;② 耗时随规模变化(批量 N 个文件/App)或不可预估(录课/等界面条件/大文件传输)→ 长;③ 拿不准 → 走默认(超时非失败,taskId 接管);④ 模板描述末尾的
[平均 X 秒]是历史实测耗时(截尾平均,成功任务自动记录),直接据此判断; - 长任务提交(判定为长后):加
--wait 0立即返回 taskId,不阻塞对话:node scripts/run-task.js --status <taskId>查状态/进度/心跳(模板里用注入的__reportProgress("3/10 下载中")上报进度,长任务模板骨架见tasks/long-task-demo/);- 卡死可
node scripts/run-task.js --stop <taskId>强杀;--list列最近任务单——结果落盘中继电脑,会话结束也能事后按单号取回; - 等待期手机可照常并发其他操作(截屏/点按/传文件)。
- 界面跳转类步骤后,插一步
wait(500~1500ms)再操作下一步。 - 短任务默认等待 30 秒后输出
{"success":false,"timeout":true,...}→ 注意这不是失败:任务仍在手机上运行,可用--status继续查询(提交后 60 秒仍未被手机接单的,中继会熔断为 failed,err含「提交超时熔断」、result.phase="relay",任务单不会永久悬挂)。若任务落为 failed 且 err 是「引擎已退出但未收到回执」→ 脚本静默崩溃,第一嫌疑是回执没走autojs_result广播(单纯console.log不会回传)——机制、标准回执骨架与「建好即广播」规则见references/现场脚本规范.md,这是最高频的想当然错误,排障时优先排除它。 - 回执超限处置(
resultTruncated:true):此时回执只有 400 字预览 + 全文落盘路径(resultFile),严禁把落盘全文整段读进上下文——用 grep / 按行 offset 只取所需片段。智能分流:① 意图明确的中间步骤(如"找某按钮坐标")→ 直接对落盘文件 grep 提取片段继续任务,终态汇报里说明「结果超限已按需提取,全文在 <路径>」;② 意图不明、或全文本身就是交付物 → 反向提问用户选择:看摘要即可 / 把全文文件交给用户 / 换关键词过滤重取 / 改用局部手段(crop 区域截屏、区域 OCR)重做。
第 3 步:看屏幕(需要时)
curl -s http://localhost:9421/screenshot
返回 {"success":true,"path":"<PC本地路径>"},用 Read 读该 PNG 判断界面状态,再决定下一步。截图不经过 AI 上下文,只有读图才消耗 token,按需使用。
- 只看局部区域:若已知道某控件的包围盒(如经
inspect_control_by_*探测出的 bounds),用crop-screenshot模板按left/top/right/bottom四元组裁剪该区域并回传电脑 PNG(看"某个控件长什么样"最省,比整屏再肉眼找块强)。调用见其TASK.md。 - 截图角落的彩色圆点不是故障:手机屏幕右缘的圆形发光点是「连接状态悬浮球」(红=未连接、绿=已连接、蓝=任务执行中)。截屏本身就是一次任务(客户端先变蓝再抓屏),故经中继拍的每张截图里它必然是蓝色,属正常现象,勿据此误判连接或任务状态。细节见
references/手机端常驻客户端说明.md。
截图结果是否必须展示给用户 —— 分两种情况(关键区分):
- 情况 A · 用户明确要求截图 / 截图,或截图本身就是交付物:
/screenshot与crop-screenshot回传的是 PC 本地 PNG 的绝对路径(形如{"success":true,"path":"..."})。这是硬规则,不可省略——AI 不能只把回执丢给用户就结束,必须:① 用present_files把 PNG 作为结果文件呈现(生成预览/卡片),让用户直接看到那张图;② 哪怕预览打不开,也必须在回复正文里附上图片的绝对路径,保证用户能自行打开查看。- 情况 B · 截图仅用于 AI 内部校验(例如"打开抖音后截图确认是否真的打开了"):此时截图不需要推给用户。AI 自行
Read/ocr判断界面状态后,只在终态汇报里给出校验结论(如"已帮您打开抖音" / "没打开,卡在 XX")即可。这种情况不展示图不算违反硬规则——用户要的是结果,不是那张中间截图。 判断原则:截图是"给用户看的"还是"给自己校验的"?前者必须展示,后者只报结论。 展示与 AI 自行 Read 判断下一步不冲突,两者可同时做。关于「AI 能否读图」——按实际情况测试,勿武断判定:调用方使用的 AI 模型能力参差不齐——有的多模态可直读图片/视频,有的仅支持文字、读图会被过滤(表现为
Content filtered或读不到内容)。据此:
- 情况 A「把图展示给用户」是硬规则,与 AI 能力无关:用户恒能看图,故无论 AI 自己能否读图,都必须
present_files+ 附绝对路径;- 「AI 读图判断下一步」是尽力而为(仅影响情况 B 的校验方式):AI 若不确定自己能否读图,先
Read实测一次——能识别就据此决策,被过滤则改用ocr取文字 /inspect_control_*取控件 / 或直接问用户,不要仅凭一次报错或主观假设就断言「模型支持/不支持」;- 以实测为准:本技能不预设 AI 必须能读图,也不假设它不能。
落地文件硬规则(文本 / 数据类交付物,与截图同级,不可省略): 凡是任务执行在 PC 上生成了文件(脚本回执里的
file字段、或 AI 自己 Write 的导出文件),AI 在终态汇报里必须把该文件的绝对路径完整写出来(带盘符,形如D:/xxx/yyy.txt,正斜杠或反斜杠均可,但必须完整、可直接定位),不得只写文件名(如user_apps_xxx.txt)或只给相对路径。同时仍用present_files把文件作为结果呈现(打开预览/卡片)。 理由:技能产物常落在.workbuddy/等隐藏目录,用户只有完整绝对路径才能复制到资源管理器地址栏找到文件;只给文件名他无从定位。 适用:所有"把结果写盘"的模板(如get-all-apps落地用户 App 名单)、截图文件、AI 自行落盘的导出文件等。回执里若带file字段,直接把该值原样抄给用户即可。
识别屏幕内容的三个优先级(回退链)
"看屏幕"的本质是把屏幕上的文字/状态读出来交给 AI 判断下一步。优先级按省 token + 可靠性排序——先用最省钱、最稳定的方法,只有在前一层不满足时才回退到更贵的方案,不要跳级、不要卡死在某一级:
- 第一级 · 控件树提取文字(最优先):用
inspect_control_by_*模板遍历 UI 控件树,取回所有控件的text/id/desc。- 适用:要判断"界面是否真的变化了、变了哪个控件",或需要结构化控件语义时;
- 特点:比 OCR 更准(控件自带语义),且不需要大模型读图,最省 token;返回数据更大时按需过滤即可;
- 回退条件:若控件树不完整 / 取不到目标控件 / 不能满足判断需求,或者APP屏蔽了无障碍, 无法获取控件信息, 则回退第二级。
- 第二级 · OCR 取文字:调用
ocr模板识别屏幕文字(纯文本数组,通常也很省 token)。- 适用:模型不必读图、但只需"屏幕有哪些文字"就能判断时;
- 文字多的屏(设置页/列表页)优先带
{"query":"关键词"}过滤,只取命中项;detail:true仅在确需逐项坐标/置信度时用——两者都是防大回执撑爆上下文; - 回退条件:若 OCR 结果不足以判断界面是否真的变化了(如界面是纯图形、无明显文字),或不足以满足用户需求(用户要的是结构/控件而非文字),→ 回退第三级。
- 第三级 · 截屏 + 模型直读(最低优先级):用
GET /screenshot或crop-screenshot截屏回 PC,让模型直接读图识别内容。- 适用:前两级都不满足、且调用方模型支持多模态(能读图片/视频)时,才用这一层;
- 特点:信息最全、最省心,但最贵、最耗 token,因此放到最后,不做默认方案;
- 回退条件:若模型不支持多模态(读图被过滤 /
Content filtered/ 读不到内容),本级别不可用,且前两级也都失败时,直接问用户,不要硬猜。
回退操作原则:
- 从第一级往下逐级实测:控件树能否满足?OCR 能否满足? 只有在前两级都不行时,再用截图 + 模型直读;
- 用于内部校验的截图 / OCR / 控件结果(情况 B),只需在终态汇报里给出结论(如"已打开抖音"),不强制把图推给用户;仅当用户明确要求看、或截图即交付物(情况 A)时,才须遵守「展示给用户」硬规则(
present_files+ 附绝对路径)。OCR 与控件结果同理:内部校验用只汇报结论,用户要看才展示。 - 第三级都拿不到可用信息时,直接问用户,不要硬猜。
第 4 步:终态一次性汇报
全部步骤完成 → 一句话汇报结果(如"已帮您打开设置并连上 WiFi");失败 → 汇报卡在第几步、原因、建议用户怎么手动补救。中间过程不打扰用户。
用户问答:查询模板清单(不执行任务)
当用户问"现在有多少个手机任务模板"/"有哪些模板"/"列出所有手机任务"等纯查询问题时,不要走执行 SOP,直接跑扫描器并朗读结果(无需手机在线、不消耗手机任务 token):
node <skill_dir>/scripts/scan-tasks.js --human
输出形如:
共 8 个手机任务模板:
· tap-point — 按屏幕坐标 (x,y) 点按
· tap-text — 点按含指定文字的控件
...
把这段清单直接念给用户即可。若要让外部程序/中继取数,也可 curl -s http://localhost:9421/templates 取 JSON {count, tasks},但用户问答场景下优先用 --human 命令行,结果更友好。
注意:这是"只读查询"——不要为此启动任务、不要下发任何脚本、不要要求手机在线。
现场脚本规范(一次性脚本 · 模板覆盖不了时)
AI 现场写的一次性脚本写到 <skill_dir>/temp/(下发时 PC 读取内容「内联直发」,位置无关;落手机后统一进 scripts-from-computer/single/),用 node scripts/run-task.js <文件> --args '{...}' 下发。写之前必须先读 references/现场脚本规范.md(严格 ES5/var only、UI 线程禁耗时、耗时 API 进 threads.start、标准回执骨架、建文件 vs 建目录的高频坑——最高频的「静默崩溃/收不到回执」都源于违反它)。新建可复用模板则读 references/AI_新建模板手册.md。
部署真实工程(多文件 + 资源)
复杂任务(多模块 / 带图片音频资源)用 deploy-project 部署整个工程目录到手机 scripts-from-computer/project/<名>/ 并自动运行入口;PC 工程统一放 <skill_dir>/scripts/autojs-project/<工程名>/。硬约束:严格 ES5/var only(require 遇 ES6 整个入口静默崩)、入口必须标准回执收尾、模块相对 require。完整结构与用法见 references/部署真实工程.md。
自动更新手机客户端(PC 一键,免手动)
手机端代码(autojs-task-phone-client.js)改动后,PC 跑 node scripts/update-phone-client.js 一键完成「新版直接下发到 scripts-from-computer/client/ + 触发自重启」,无需手动。机制与假死排障见 references/自动更新手机客户端.md。
手机未连接时的处理(AI 必须主动)
触发条件:第 0 步 health 返回 {"phone":"disconnected"} 或中继没起。绝不能只甩一句"请连接手机"——按 references/手机连接排障.md 的五步流程主动带着用户连:① AI 自己跑 get-lan-ip.js 取局域网 IP → ② 指导用户改客户端 var SERVER_IP → ③ 手机 AutoJs6 运行 autojs-task-phone-client.js → ④ 同一 WiFi + 四项权限(无障碍/悬浮窗/后台/截图)→ ⑤ 用户回报"连上了"后 health 复查。完整步骤与给用户的话术见该文档;注:中继重启/网络闪断会自愈重连,只有客户端引擎死亡才需要走此流程。
安全边界(红线)
- 支付、转账、删除、授权类不可逆操作:即使是全自动模式,执行该步前也要先向用户确认一次;
- 一次一个 UI 任务:run 类任务单虽支持并发(回执按 taskId 归位互不串线),但手机屏幕同一时刻只能做一件事,UI 自动化任务仍要逐步串行下发、切勿并发;截屏/更新客户端/删工程等同步短操作在中继侧仍互斥(并发会返回 429)。
注意事项
- 熄屏/锁屏症状识别(高频误判点):截图回传全黑帧 + 剪贴板读写返回空 + OCR 内容异常,而
open-app等"假成功"(am start不需亮屏)——十有八九是手机熄屏/自动锁屏了,请用户点亮解锁后重试,勿往脚本 bug 方向排查。 - 手机端脚本严格 ES5 / var only:AutoJs6 Rhino 引擎对 ES6 支持不全,这是硬性约束。
- 现场脚本不要 setInterval 保活:经 /run 下发的脚本由中继托管,正常 exit 即可;只有常驻客户端需要 setInterval 保活。
- 性能:涉及 UI 树查找的步骤(tap-text 等)在界面层级深时会慢一些,属正常,等回执即可。
- 截图类脚本必须内置权限前置代码:凡调用
captureScreen()/ocr(...)的手机端脚本,最前面必须有「后台线程用textMatch正则多候选自动点掉授权弹框(按钮文案因 ROM 而异:小米『立即开始』、部分机型『开始截图』等)+requestScreenCapture()+sleep(500)」这段代码,否则截图失败或脚本卡死(表现为"回执为空")。模板screenshot/crop-screenshot/ocr/tap-text/unfollow-official-accounts已内置,新建截图模板照references/截图权限与弹框处理.md加。