Skip to content

XScript v0.2.5

Choose a tag to compare

@github-actions github-actions released this 15 Oct 16:54
· 136 commits to main since this release

新增

  • GitHub Actions:持续集成 + 推 tag 自动发布:.github/workflows/ci.yml(push / PR 到 main)跑管理后台与 MCP 测试(Python 3.10 和 3.12)、设备端 Python 运行时测试、Web IDE 的 node 测试(无头 Chrome)、VS Code 扩展单元测试 + vsix 打包、Web 控制台构建、Kotlin JVM 测试 + debug APK + 16KB 检查、App 与插件版本一致检查;release.yml(tag vX.Y.Z)重新跑 CI,检查 tag / versionName / 插件版本 / CHANGELOG,用仓库 Secret 构建签名 APK,打包 vsix,生成 SHA256SUMS,校验签名证书和 16KB 对齐,再创建 GitHub Release(缺 Secret 时直接失败,绝不发布未签名 APK)。scripts/release.sh 新增 verify-apk 和 notes。没有覆盖的(设备 / 模拟器端到端、真实 VS Code 宿主测试等)见 docs/发布.md。
  • README 里的 VS Code 插件说明和截图;发布时一起打包 vsix:根 README 新增「VS Code 插件」一节(侧边栏 + 运行日志、断点调试两张真实截图,真实 VS Code 连模拟器上的演示工程,截图由 ide/vscode-extension/scripts/vscode-screenshots.sh 通过 DevTools 协议生成,不需要屏幕录制权限)。新增 scripts/release.sh(check / prepare / build / publish)和 发布流程:发布时构建 xscript-vscode-X.Y.Z.vsix,和签名 APK 一起放进 dist/release/,SHA256SUMS 同时覆盖两者,再用 gh release create 附到同一个 GitHub Release。插件版本号 = App 发布版本号(现为 0.2.4,原 0.2.0 未发布过),verify.sh 检查两者一致;插件暂不上架应用市场。
  • VS Code 扩展验证不再弹登录:查明弹出来的是 Welcome 页 + 内置 Copilot Chat 的「Sign in」、内置 GitHub Authentication 读写钥匙串(创建登录钥匙串里的「Code Safe Storage」条目)、Edit Sessions 的云端更改提示,并且会在真实 ~/.vscode 里写文件。vscode-host-test.sh 现在用临时 HOME、关掉 GitHub / Microsoft 认证和 Copilot 内置扩展、--use-mock-keychain、临时配置里关掉 AI / 欢迎页 / 云端更改 / 遥测 / 更新;新增 vscode-no-prompt-check.sh 读取编辑器实际显示的内容和 macOS 窗口来证明没有提示;成功运行自动删除临时目录;重新运行的检查改成轮询状态,不再偶发失败。
  • VS Code 扩展对齐 AScript 官方扩展:对照应用市场里的 AScript 扩展 0.3.0(读了它的 vsix 清单和官方文档)补齐:
    • 活动栏 XScript 视图:保存的设备(在线 / 离线、运行状态、行内运行 / 停止)、手机上的工程(行内运行 / 拉取)、工具入口。
    • 设备管理:添加 / 编辑 / 删除、选择运行设备(编辑器右上角手机图标,记在工作区设置)、扫描设备(ADB 含自动 adb forward,加局域网 9860 端口)。
    • 新建工程(空 / Hello / AScript 写法模板,生成 __init__.py + build.as + res/);build.as 也被识别为工程。
    • 同步:增量上传(按大小 + 内容摘要,只传新增和修改的文件)、.vscode/.syncignore(gitignore 风格,和 AScript 同一路径)、从设备拉取工程(有差异先确认)、工程同步 菜单。
    • 运行:Ctrl+Shift+R(AScript 同款,F6 保留);再次运行先停止再同步再启动;运行时 ▶ 换成 ■(xscript.running 上下文)。
    • 另有 ADB 终端、投屏、命令中文标题(package.nls.zh-cn.json)、设置 xscript.adbPath / xscript.scanLan。
    • 不做的(AScript 自家服务或格式、或 XScript 不适用):Windows 本地运行、iOS、.was 导包与上传分发、官网 / 云控入口、自动下载 scrcpy、公网地址 + 密码设备;逐项对照见 ide/vscode-extension/README.md。
    • 验证:38 个单元测试;scripts/vscode-host-test.sh(原 cursor-host-test.sh,现在只用真实 VS Code 1.142,隔离配置)在 mock 和两台模拟器上各 36 项通过,含经 VS Code 调试 API 在断点处停下并求值、截图、扫描、运行 / 重新运行 / 停止 / 拉取。
  • 修复:调试启动偶发超时:「等待调试器初始化」的 20 秒超时用了测试里被缩短的 sleep,机器忙时偶尔把握手判成超时(verify.sh 里见过一次);改用真实计时器。
  • Python 版本统一为 3.10+:管理后台的 requires-python 从 3.11 降到 3.10,和设备(3.10)、MCP 服务(3.10+)一致;3.10 通过环境标记使用 websockets 16.1.1 / sqlalchemy 2.0.54,3.11+ 仍用 17.1 / 2.1.1。scripts/verify.sh 新增 3.10 检查(.venv310,用 uv 自动创建,无 uv 或离线时跳过)。顺带让打包队列的 asyncio.Queue 在运行中的事件循环里才创建。不支持 3.9:mcp 包本身要求 3.10+。文档补充了 AScript(设备 3.8,电脑 3.9–3.13)和 XScript 的 Python 版本对照。
  • 支持 16KB 页面设备(numpy / OpenCV / Pillow 恢复可用):以前在 16KB 页面的设备或模拟器上,内置 numpy 导入失败(library "libopenblas.so" not found),OpenCV、Pillow、图片字库(CvFontLib)、screen.capture_cv()、OCR 和 YOLO 跟着不可用。根因是 Chaquopy 17 提供的 numpy 1.23.3、opencv-python 4.5.1.48、Pillow 9.2.0 的原生库只按 4KB 对齐,没有可升级的对齐版本。现在清单里开启 android:pageSizeCompat="enabled"(系统的 16KB 兼容模式),16KB 和 4KB 页面的模拟器上这些功能都通过(device_cvfont_e2e.py、device_ml_e2e.py、新的 device_native_e2e.py、截图 / 调试 / 链接启动冒烟)。新增 scripts/check_16kb.py <apk>(zipalign -c -P 16、所有 .so(含 pip 轮子里的)的 ELF 对齐、清单属性;--strict 要求全部 16KB 对齐)和 scripts/device_native_e2e.py <设备地址>。限制:轮子里仍有 4KB 对齐的原生库,兼容模式首次加载稍慢、内存略高,只在 Android 17 模拟器验证过;彻底对齐需要自己用 NDK 重编这些轮子或等 Chaquopy 发布。
  • 网页 IDE:撤销替换、正则防卡死、手机屏幕布局:
    • 撤销替换:搜索面板新增「撤销替换」,一步撤销最近一次「全部替换」(含写入设备的文件;替换后又被改过的文件不动并列出)。
    • 正则防卡死:正则模式下,(a+)+、(\w*)* 这类嵌套无限重复直接拒绝;其余正则在 Web Worker 里运行,单个文件超过 2.5 秒就中止并提示「正则表达式运行超时」,页面不会卡死;正则最长 1000 个字符。
    • 手机屏幕(宽度 ≤ 600px):文件区改成「☰ 文件」抽屉(点文件或点编辑区自动收起),工具栏、调试区和日志区压缩,补全弹窗不再超出屏幕。已在无头 Chrome 移动模拟和两台模拟器自带的 Chrome(155 / 113,真实触摸和屏幕尺寸)实测。
    • 补全弹窗:窄屏上输入长行时浏览器会自动横向滚动跟随光标,以前这会把补全弹窗关掉(手机上长行几乎没法补全);现在滚动时弹窗跟着光标重新定位,光标滚出视野才关闭。
  • 网页 IDE:重命名 / 移动文件和文件夹:目录树里选中后按 F2、点「重命名」、右键菜单,或直接拖到目标文件夹。已打开的标签页、未保存的修改、断点和展开状态跟着走;目标已存在返回冲突,不会覆盖;入口 __init__.py 受保护。设备接口新增 POST /projects/{name}/move({"from","to"},400/404/409,单次原子重命名)。
  • 链接启动:浏览器真实页面验证:新增 scripts/device_scheme_e2e.py 和 scripts/device_packed_scheme_e2e.py,在两台模拟器的 Chrome(113 / 155)里点真实网页上的链接,覆盖确认框(显示工程名和来源、取消不运行、运行才启动)、stop 不弹窗、params 传入脚本、非法名 / 工程不存在 / 已有脚本在运行的提示、JS 按钮和无点击跳转(都只到确认框)、三种模式,以及打包 App 自己的协议(只运行打包的小程序,name= 其他工程被拒绝,xscript:// 只有主 App 响应)。
  • VS Code / Cursor 扩展:打包 vsix、真实编辑器加载验证、调试日志点修复:npm run package 生成 xscript-vscode-0.1.0.vsix;scripts/cursor-host-test.sh 把它装进 Cursor(隔离配置)并在扩展宿主里检查激活、11 条命令、调试类型和快捷键;scripts/debug-smoke-advanced.js 在模拟器上实测条件断点、命中次数、日志点和修改变量。修复:调试控制台里看不到日志点的输出(适配器把 debugpy 带 source / line 的 stdout 当重复丢掉了)。
  • VS Code / Cursor 扩展:一键调试:在 Python 文件里按 Alt+F6(或编辑器右上角的调试按钮、资源管理器里右键工程文件夹 Debug Project on Device):自动保存并上传工程、在手机上启动调试器、连接并进入 VS Code 自带的调试界面;行断点、条件 / 命中次数断点、日志点、单步、调用栈、变量、监视 / 调试控制台求值都走标准调试协议,经设备已有的 /debug/* 接口转发,不用改手机端。也可以在 launch.json 里写 {"type":"xscript","request":"launch","projectRoot":"${workspaceFolder}"}。电脑上的文件路径和手机上的路径自动互相转换;停止调试会终止手机上的脚本,「断开但不终止」则让它继续跑完。
  • 卡密:续期叠加、体验卡、多设备卡、滥用告警(管理后台):
    • 续期叠加:设备在同一应用上还有未到期的卡时,新激活的卡从旧卡到期时刻起算(旧卡已过期或没有则从现在起算;永久卡不叠加;解绑后换回不重复叠加)。生成批次时可关闭「续期叠加」。
    • 体验卡:有效期按小时(最长 30 天),只绑定一台设备,不参与叠加;每台设备在每个应用上只能用一张,解绑或删除体验卡都不会重置(trial_uses 表)。
    • 多设备卡:一张卡可绑定 1–100 台设备,共用同一个到期时间;超出上限返回「卡密绑定的设备数已达上限」。可以只解绑其中一台(POST /api/cards/actions 的 device 参数),被解绑设备的授权在联网复核时失效。
    • 滥用告警:24 小时窗口内检测四种情况——同一张卡被多台设备尝试、单设备激活大量卡密、单 IP 为大量设备激活、单 IP 反复猜不存在的卡密;命中后写入审计日志(card.abuse)、列在「卡密 → 滥用告警」,并通过订阅了「卡密滥用告警」的机器人 / Webhook 发出(同一对象每小时一次)。阈值在「系统设置 → 安全」里配置,0 为关闭。
    • 数据库自动升级(schema v4);旧卡密按普通单设备卡处理。体验卡、多设备卡和叠加开关在生成卡密时设置,都需要操作员以上权限;阈值只有管理员能改。
  • 后台:登录 IP 白名单(系统设置 → 安全):每行一个 IP 或网段(IPv4 / IPv6、CIDR),设置后只有名单内的 IP 能登录后台、使用已登录的会话和 API 令牌;留空 = 不限制。保存时名单不包含你当前的 IP 会被拒绝,避免把自己锁在外面;被拦截的登录写入审计日志(auth.ip_denied,限频)。设备云控 /ws、/license/* 和 /pub/* 不受影响。万一仍被锁在外面,在服务器上运行 xscript-server reset-allowlist。
  • 后台:App 公告和 APK 强制更新(新页面「应用运营」;打包的 App 端见下一条):
    • 公告:按应用包名(* = 所有应用)、级别(通知 / 提醒 / 紧急)、起止时间、启停管理,操作员以上可编辑;公开接口 GET /pub/app-notices?app=&version_code=(最多 5 条,纯文本)。
    • 版本更新:管理员为每个应用设置最新版本(选一个打包成功的任务,或填外部下载链接)和「最低版本号」;公开接口 GET /pub/app-update?app=&version_code= 返回是否有更新、是否必须更新、下载地址、sha256 和说明;/pub/app-update/apk 下载本站打包的 APK。被引用的打包任务不能删除,也不会被存储清理删除;APK 被清掉时不会把用户锁在 App 外。
  • 打包的 App 接入公告和强制更新:打包出来的 App(后台打包会自动填入服务器公网地址,命令行用 --ops-server,缺省回退到 --update-server / --license-server)打开首页时向后台取公告和更新信息,最多每分钟一次,冷启动一定检查:
    • 新公告弹窗显示一次(紧急 / 提醒有标记),首页新增「公告」行可随时重看。
    • 有新版本时提示(可「稍后」),首页「应用更新」行显示状态。
    • 版本号低于后台设置的最低版本时必须更新:首页弹出无法关闭的对话框,脚本不能启动(界面、链接启动、定时任务、云控都被拦住);点「下载并安装」下载 APK、校验大小和 SHA-256,再交给系统安装程序(需要允许安装未知应用)。
    • 不会把用户锁死:后台没有可用的 APK(被清理)时返回「无更新」,限制自动解除;版本号达到最低版本后不再拦截;下载或校验失败可以重试,不会安装。
    • 新增权限 REQUEST_INSTALL_PACKAGES 和 FileProvider(只暴露缓存里的 updates/ 目录)。
  • 模拟器截图权限和 /screen 缩放的真机验证:新增 scripts/emulator_grant_capture.sh [序列号](用 uiautomator 点掉系统的录屏授权对话框,API 34 的「Start now」和 API 37 的「Share entire screen」两种对话框都认)和 scripts/device_screen_smoke.py <设备地址>(检查 /screen 以及 ?max=、?format=jpg&quality= 的尺寸、格式、不放大、非法值忽略)。两个模拟器(16KB / 4KB 页)都通过。
  • 卡密:App 内续期、设备黑名单、告警重启不丢:
    • 打包的 App 已激活后,点首页「卡密授权」行变成「续期」对话框:显示当前到期时间,输入新卡密后从当前到期时间起叠加;成功提示「续期成功,有效至 …(延长 N 天)」。在模拟器上用真实打包的授权 App 验证了 30 + 30 + 15 + 7 天的连续叠加,以及服务端各张卡的到期时间。
    • 设备黑名单(卡密 → 设备黑名单,操作员以上可改):黑名单里的设备不能再激活卡密,已激活的授权在 App 下次联网复核时失效(离线授权码不受影响);滥用告警里「单设备激活大量卡密」一行有「加入黑名单」按钮;加入 / 移除都进审计日志。接口 GET/POST /api/cards/bans、DELETE /api/cards/bans/<设备>。
    • 滥用告警窗口持久化:24 小时的统计窗口和「同一对象每小时最多一次」的冷却写入数据库(abuse_events、abuse_reports),重启后继续计数、不会重复告警。
  • 链接启动:xscript://run?name=<工程>[&params=<JSON>] 运行脚本,xscript://stop 停止;打包出来的 App 用包名作协议,只能运行自己的小程序。首页新增「链接启动」开关:每次确认(默认)/ 直接运行 / 已关闭。
  • 图片字库(CvFontLib):ascript.android.screen.gp_tasks.CvFontLib(part_img, font_lib, confidence, rect, spacing, rgb),用一组字符小图做模板匹配,按行、按左右顺序拼出文字;也可放进 GP 管线,或用 CvFontLib.recognize(...) 直接得到文字。已用真实 OpenCV 在主机上测试,并在 4KB 页面的 Android 14 模拟器上用设备内置的 numpy 1.23.3 / OpenCV 4.5.1 跑通同一组 13 个测试。
  • 网页 IDE:多标签页关闭:标签页右侧有 × 按钮,也支持鼠标中键、Alt+W 和右键菜单(关闭 / 关闭其他 / 关闭右侧 / 关闭已保存 / 全部关闭);有未保存修改的文件先确认再关闭。
  • 网页 IDE:工程内搜索 / 替换:Ctrl/Cmd+Shift+F 或「搜索」按钮;区分大小写、全字、正则、文件过滤(*.py, lib/**, !tests/**),结果按文件分组、点击跳转;全部替换或按文件替换,替换前确认,没有未保存修改的文件直接写入,有未保存修改的只改编辑器内容。
  • 网页 IDE:手机截图面板:截取一帧,点击取坐标和颜色,插入坐标到编辑器,保存到工程 res/img/ 或下载。
  • 网页 IDE:API 补全:输入时弹出(或 Ctrl/Cmd+空格)xscript.* / ascript.* 的模块路径、函数、类和成员,带签名和说明;认识 import、from ... import、别名和 x = Class() 实例,也补全文件内的名字、内置函数和关键字;字符串和注释里不弹出。索引由 scripts/gen_completions.py 从运行时源码生成,verify.sh 检查是否过期,离线可用。
  • 网页 IDE:语法检查:本地检查括号、字符串、冒号、缩进和 Python 2 print,红色波浪线、行号标记和状态栏问题数(点击跳转);保守设计,用 Python 标准库 1373 个文件和 3000 个随机破坏的样本对照 CPython 验证过零误报。

修复

  • 模板匹配漏掉细线小图(图片字库读不全):搜索多个目标时的「半分辨率预筛」对小模板(不到 48 像素)把 1 像素的细笔画抹掉,导致完全相同的小图(置信度 1.0)被判为不匹配;用真实字体渲染的 0、6、8 等数字因此整个丢失(2026-10:15 读成 22-1:15)。现在只对 48 像素以上的模板做预筛;影响所有 find_images / 图片字库调用,只会多找到、不会少找到。用 Pillow 渲染的真实字体字形在 4KB 页面模拟器上端到端验证(scripts/device_cvfont_e2e.py,9 个用例);在 4KB 页面模拟器上同时验证了运行时 pip(PyPI 纯 Python 包 + Chaquopy 源的原生包 MarkupSafe + requirements.txt 自动安装)、PaddleOCR v5 模型下载与识别、YOLO11n 经 ONNX Runtime 检测(scripts/device_ml_e2e.py)。

  • 中 · 透明模板找图(设备):带透明通道的模板在 Android 内置的 OpenCV 4.5.1 上永远找不到。原因是该版本的 matchTemplate 会把 uint8 掩码原地改成 0/1,随后「掩码 > 128」得到 0 个有效像素,得分全为 0;主机上的 OpenCV 4.10 不会这样,所以主机测试一直是绿的。现在先计算有效像素再传入掩码副本,并补了回归测试。这是在 4KB 页面模拟器上首次运行 numpy/cv2 相关测试时发现的。