@mobileaidev/ai-app-bridge 0.3.6 → 0.3.7

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.
package/README.md CHANGED
@@ -7,7 +7,7 @@ discovery. Every request checks the mapping before dispatch. Mutating requests
7
7
  are never replayed after a missing route or uncertain result. For manual cleanup,
8
8
  pass the exact serial and returned Host port to `remove-forward`.
9
9
 
10
- This source version is `0.3.6`; registry publication is a separate release step.
10
+ This source version is `0.3.7`; registry publication is a separate release step.
11
11
  The default installation includes the Script/Intent and capture contracts below.
12
12
  Local package verification does not change npm dist-tags.
13
13
  The supported Node range is `>=26.3.0 <27`; this release was checked on 26.3.0.
@@ -60,7 +60,7 @@ domains, commands, and options, then call `run` with the selected command.
60
60
 
61
61
  ```bash
62
62
  # Install the current stable release; see docs/RELEASE.md for packaging.
63
- npm install -g @mobileaidev/ai-app-bridge@0.3.6
63
+ npm install -g @mobileaidev/ai-app-bridge@0.3.7
64
64
 
65
65
  ai-app-bridge status --package-name io.github.mobileaidev.aiappbridge.sample
66
66
  ai-app-bridge tree --package-name io.github.mobileaidev.aiappbridge.sample
@@ -1752,18 +1752,52 @@ function parseForegroundWindow(raw) {
1752
1752
  'mResumedActivity',
1753
1753
  'mFocusedApp',
1754
1754
  ];
1755
- for (const marker of markers) {
1756
- const line = lines.find((item) => item.includes(marker));
1757
- if (!line) continue;
1758
- const component = parseComponentFromWindowLine(line);
1755
+ const records = [];
1756
+ const focusedDisplayIds = new Set();
1757
+ let displayId = null;
1758
+ for (const line of lines) {
1759
+ if (/^WINDOW MANAGER\b/.test(line)) displayId = null;
1760
+ const display = line.match(/^\s*Display: mDisplayId=(\d+)\b/);
1761
+ if (display) displayId = Number(display[1]);
1762
+ const focusedDisplay = line.match(/^\s*mTopFocusedDisplayId=(-?\d+)\b/);
1763
+ if (focusedDisplay) focusedDisplayIds.add(Number(focusedDisplay[1]));
1764
+ const focus = line.match(/^\s*(mCurrentFocus|mTopResumedActivity|mResumedActivity|mFocusedApp)(?:\[(\d+)\])?\s*[:=]\s*(.*)$/);
1765
+ if (!focus) continue;
1766
+ const component = parseComponentFromWindowLine(focus[3]);
1759
1767
  if (!component) continue;
1768
+ records.push({
1769
+ source: focus[1],
1770
+ displayId: focus[2] === undefined ? displayId : Number(focus[2]),
1771
+ value: focus[3].trim(),
1772
+ component,
1773
+ raw: line.trim(),
1774
+ });
1775
+ }
1776
+ for (const marker of markers) {
1777
+ const unique = new Map();
1778
+ for (const record of records.filter((item) => item.source === marker)) {
1779
+ unique.set(`${record.displayId}:${record.value}`, record);
1780
+ }
1781
+ const candidates = [...unique.values()];
1782
+ if (!candidates.length) continue;
1783
+ const focusedDisplayId = focusedDisplayIds.size === 1 ? [...focusedDisplayIds][0] : null;
1784
+ const selected = candidates.length === 1 ? candidates
1785
+ : candidates.filter((item) => focusedDisplayId !== null && item.displayId === focusedDisplayId);
1786
+ if (selected.length !== 1) {
1787
+ return {
1788
+ ok: false,
1789
+ error: 'foreground_ambiguous',
1790
+ source: marker,
1791
+ focusedDisplayId,
1792
+ candidates: candidates.map((item) => ({ displayId: item.displayId, ...item.component, raw: item.raw })),
1793
+ };
1794
+ }
1795
+ const record = selected[0];
1760
1796
  return {
1761
1797
  ok: true,
1762
1798
  source: marker,
1763
- packageName: component.packageName,
1764
- activity: component.activity,
1765
- component: component.component,
1766
- raw: line.trim(),
1799
+ ...record.component,
1800
+ raw: record.raw,
1767
1801
  };
1768
1802
  }
1769
1803
  return {
@@ -1,4 +1,4 @@
1
- # Optional UI executors (0.3.6)
1
+ # Optional UI executors (0.3.7)
2
2
 
3
3
  Bridge keeps its existing SDK paths and exposes optional executors through `capabilities`, `run`, and JavaScript/Python Script. Select an executor explicitly. No command silently changes a touch into a setter, switches framework after failure, or repeats an uncertain action.
4
4
 
@@ -26,9 +26,9 @@ android {
26
26
  }
27
27
  }
28
28
  dependencies {
29
- androidTestImplementation("com.github.mobileAiDev.ai-app-bridge:ai-app-bridge-test-instrumentation:0.3.6")
29
+ androidTestImplementation("com.github.mobileAiDev.ai-app-bridge:ai-app-bridge-test-instrumentation:0.3.7")
30
30
  // Optional H5 adapter:
31
- androidTestImplementation("com.github.mobileAiDev.ai-app-bridge:ai-app-bridge-test-espresso-web:0.3.6")
31
+ androidTestImplementation("com.github.mobileAiDev.ai-app-bridge:ai-app-bridge-test-espresso-web:0.3.7")
32
32
  }
33
33
  ```
34
34
 
@@ -81,7 +81,7 @@ The rule must start **before** Activity/composition creation. The adapter uses a
81
81
 
82
82
  ## Flutter
83
83
 
84
- Add `ai_app_bridge_test: 0.3.6` to the application's `dev_dependencies`. The helper takes `flutter_test` and `integration_test` from the **same Flutter SDK** as the application. It is a Dart test helper, not an additional Android plugin with its own AGP/Kotlin versions.
84
+ Add `ai_app_bridge_test: 0.3.7` to the application's `dev_dependencies`. The helper takes `flutter_test` and `integration_test` from the **same Flutter SDK** as the application. It is a Dart test helper, not an additional Android plugin with its own AGP/Kotlin versions.
85
85
 
86
86
  The helper declares Flutter **>=3.41.0** and Dart **>=3.11.0 <4.0.0**. This release was built and exercised with Flutter **3.41.9 on Android API 25** and **3.44.8 on Android API 36**. These are the verified combinations; newer SDK versions still need validation with the application's plugin graph.
87
87
 
package/docs/RELEASE.md CHANGED
@@ -1,8 +1,13 @@
1
- # 0.3.6 发行与接入交接
1
+ # 0.3.7 发行与接入交接
2
2
 
3
3
  本文件记录正式版的依赖关系和出仓库交付入口。封版要求是同一提交的源码、发行包与公开接入合同一致;单个样本的测试进度不改变包版本或发布状态。推送 Git、创建远端标签及发布 npm/pub 包由维护者执行。
4
4
 
5
- ## 0.3.6 新增
5
+ ## 0.3.7 修复
6
+
7
+ - Android Host 读取全部焦点记录,跳过 `null`,不再依赖记录排列顺序。只有一个有效窗口时直接使用;多个窗口通过系统 `mTopFocusedDisplayId` 选择,仍不能唯一定位时返回 `foreground_ambiguous`。
8
+ - 包名匹配、SDK 窗口与控件身份校验沿用既有路径。App SDK 只同步发行版本。
9
+
10
+ ## 随本版包含的 0.3.6 能力
6
11
 
7
12
  - Android、iOS、Flutter、Web 与内嵌 H5 的持续 UI 观察默认关闭;仅按需开启 100–5000 ms 的观察窗口,期限到达、主动停止或相应生命周期退出时清理观察任务。新增三个平台观察控制命令,公开命令共 121 个。
8
13
  - Flutter 当前树改为显式读取 `/v1/flutter/snapshot`,状态请求不再触发树遍历;CLI/MCP 与 App 内 SDK 需要配套升级。Android 指纹编码减少 JNI 调用与临时分配。实测证据及边界见仓库中的 UI 观察性能评估记录。
@@ -12,7 +17,7 @@
12
17
  - 公开 capabilities + run、Python/JS Script 的 app.test 权限、观测身份、原始回执、取消和设备占用接线。
13
18
  - Compose 主包/测试包版本检查;按测试配置隔离依赖,不自动升级业务 AGP/Kotlin/Compose。
14
19
  - Android 7 权限输出的零 flags 省略及空格分隔格式支持,来源为实际 API-25 环境和 AOSP Settings 输出实现。
15
- - 本地交付和外部发布分开记录;这份源码不表示 npm/JitPack/pub.dev 已发布 0.3.6
20
+ - 本地交付和外部发布分开记录;这份源码不表示 npm/JitPack/pub.dev 已发布 0.3.7
16
21
 
17
22
  接入合同、具体依赖和实测性能见 [OPTIONAL_EXECUTORS.md](OPTIONAL_EXECUTORS.md)。
18
23
 
@@ -36,18 +41,18 @@
36
41
 
37
42
  ## 新增可选分发物
38
43
 
39
- Android `ai-app-bridge-test-core`、`ai-app-bridge-test-uia`、`ai-app-bridge-test-espresso`、`ai-app-bridge-test-instrumentation`、`ai-app-bridge-test-espresso-web`、`ai-app-bridge-test-compose` 均使用 0.3.6,通过 androidTestImplementation 消费。Gradle 插件增加 `io.github.mobileaidev.aiappbridge.test` 依赖校验入口。新 Flutter 包 `ai_app_bridge_test` 使用 0.3.6,只作为 dev_dependency;它的发布不依赖 Android SDK 的 JitPack 坐标。
44
+ Android `ai-app-bridge-test-core`、`ai-app-bridge-test-uia`、`ai-app-bridge-test-espresso`、`ai-app-bridge-test-instrumentation`、`ai-app-bridge-test-espresso-web`、`ai-app-bridge-test-compose` 均使用 0.3.7,通过 androidTestImplementation 消费。Gradle 插件增加 `io.github.mobileaidev.aiappbridge.test` 依赖校验入口。新 Flutter 包 `ai_app_bridge_test` 使用 0.3.7,只作为 dev_dependency;它的发布不依赖 Android SDK 的 JitPack 坐标。
40
45
 
41
46
  ## 版本与消费方式
42
47
 
43
48
  | 交付物 | 发行版本 | 独立消费入口 | 发布依赖 |
44
49
  | --- | --- | --- | --- |
45
- | Android SDK | `0.3.6` | JitPack `com.github.mobileAiDev.ai-app-bridge:ai-app-bridge-android:0.3.6` | 同名 Git tag,JitPack 对该提交成功构建 |
46
- | Android Gradle 插件 | `0.3.6` | JitPack `ai-app-bridge-gradle-plugin` 模块及插件 ID `io.github.mobileaidev.aiappbridge.android` | 与 SDK 相同的 Git tag;不再使用旧默认 `0.2.8` |
47
- | 原生 iOS SDK | Git tag `0.3.6` | Git URL 的仓库根 `Package.swift`,产品 `AiAppBridgeIOS` | 根清单包含 Swift runtime、C adapter 和 segmented C store,无外部 C 包路径 |
48
- | Flutter 插件 | `0.3.6` | pub `ai_app_bridge_flutter` | Android 固定依赖上述 SDK;iOS Swift/C 源码随插件分发 |
49
- | Desktop CLI/MCP | `0.3.6` | npm `@mobileaidev/ai-app-bridge` | 包含 UIA bundle、WDA 模板和 native store 源码;WDA 上游固定 `14.1.1` |
50
- | Web SDK | `0.3.6` | npm `@mobileaidev/ai-app-bridge-web` | 独立浏览器源码包,无 npm 对 CLI 的安装依赖 |
50
+ | Android SDK | `0.3.7` | JitPack `com.github.mobileAiDev.ai-app-bridge:ai-app-bridge-android:0.3.7` | 同名 Git tag,JitPack 对该提交成功构建 |
51
+ | Android Gradle 插件 | `0.3.7` | JitPack `ai-app-bridge-gradle-plugin` 模块及插件 ID `io.github.mobileaidev.aiappbridge.android` | 与 SDK 相同的 Git tag;不再使用旧默认 `0.2.8` |
52
+ | 原生 iOS SDK | Git tag `0.3.7` | Git URL 的仓库根 `Package.swift`,产品 `AiAppBridgeIOS` | 根清单包含 Swift runtime、C adapter 和 segmented C store,无外部 C 包路径 |
53
+ | Flutter 插件 | `0.3.7` | pub `ai_app_bridge_flutter` | Android 固定依赖上述 SDK;iOS Swift/C 源码随插件分发 |
54
+ | Desktop CLI/MCP | `0.3.7` | npm `@mobileaidev/ai-app-bridge` | 包含 UIA bundle、WDA 模板和 native store 源码;WDA 上游固定 `14.1.1` |
55
+ | Web SDK | `0.3.7` | npm `@mobileaidev/ai-app-bridge-web` | 独立浏览器源码包,无 npm 对 CLI 的安装依赖 |
51
56
  | Native store | `0.1.0` | 随 CLI 的 bundled dependency 安装 | 不要求另行发布到 npm;`file:../../native/segmented-fact-store` 是工作区构建入口,最终 tarball 必须包含该依赖源码 |
52
57
 
53
58
  Flutter 的 podspec 是随 pub 插件消费的本地 podspec,不是独立 CocoaPods trunk 发布包;原生 iOS 使用根 Swift package。Flutter SwiftPM 的 `../FlutterFramework` 由 Flutter 的集成生成,不能当作本仓库的外部私有依赖,也不应将本机 Flutter framework 打包进插件。
@@ -56,11 +61,11 @@ Host 支持范围声明为 Node `>=26.3.0 <27`,本轮实际验证基线是 **2
56
61
 
57
62
  ## 发布顺序
58
63
 
59
- 1. 完成源码审阅并冻结一个提交,核对以下命令的产物确实来自它;包含当前 untracked 的实际源码、测试和文档,排除本机生成目录。所有对外发行版本使用同一个 `0.3.6`,若需要改版本,先同时更新上表涉及的 manifest 与固定依赖。
60
- 2. 维护者推送提交与 `0.3.6` 标签,让 JitPack 构建 Android SDK/插件。确认两条公开坐标可解析后,再发布依赖它们的 Flutter 包。本地 Gradle project/path/AAR 替换不能证明 JitPack 坐标可消费。
64
+ 1. 完成源码审阅并冻结一个提交,核对以下命令的产物确实来自它;包含当前 untracked 的实际源码、测试和文档,排除本机生成目录。所有对外发行版本使用同一个 `0.3.7`,若需要改版本,先同时更新上表涉及的 manifest 与固定依赖。
65
+ 2. 维护者推送提交与 `0.3.7` 标签,让 JitPack 构建 Android SDK/插件。确认两条公开坐标可解析后,再发布依赖它们的 Flutter 包。本地 Gradle project/path/AAR 替换不能证明 JitPack 坐标可消费。
61
66
  3. 原生 iOS 消费相同 Git tag 的根 package;完成根 package 的 iOS 构建,不仅构建 `ios/ai-app-bridge-ios/Package.swift`。Flutter iOS 则检查实际 pub 包内 Swift/C 源码与声明相符。
62
67
  4. CLI 与 Web SDK 可分别发布到 npm 的 `latest` dist-tag。CLI 的 native store 已打包随行,不等待一个不存在的单独 registry 依赖。Flutter 包发布以第 2 步完成为前提。
63
- 5. 同步 npm `next` 指向 `0.3.6`,让已有候选入口也使用本次正式版。将 GitHub `main` 与发行提交同步,并创建非预发布的 GitHub Release。
68
+ 5. 同步 npm `next` 指向 `0.3.7`,让已有候选入口也使用本次正式版。将 GitHub `main` 与发行提交同步,并创建非预发布的 GitHub Release。
64
69
  6. 从 registry/tag 安装刚发布的确切版本,读取 `capabilities` 和版本,核对来源及支持范围,确认默认安装入口指向本次发行版本。正式发布不自动等于全平台生产验收完成。
65
70
 
66
71
  正式发布命令需在对应目录由维护者执行,例如 npm 使用 `npm publish --tag latest`;pub 使用 `flutter pub publish`。这些命令属于发布动作,不能混入本地验证脚本。
@@ -101,7 +106,7 @@ npm 升级不会替换已连接的 MCP 进程。用 `ai-app-bridge --version`
101
106
  已有工作结束后显式停止旧 Runtime,并在 Cursor 等客户端重连 MCP,核对 initialize
102
107
  中的 `serverInfo.version`。工具描述仍有旧 `batch`/`smoke` 时刷新客户端缓存。
103
108
 
104
- 实际发布状态与验证边界见仓库 `docs/EXECUTOR_DELIVERY_0.3.6.md`。
109
+ 实际发布状态与验证边界见仓库 `docs/RELEASE_HANDOFF_0.3.7_2026-09-15.md`。
105
110
  Android Gradle 插件的 `webSocketCaptureEnabled`、`logInstrumentationEnabled`、
106
111
  `webViewDebuggingEnabled` 没有对应插桩实现,现明确弃用并在显式设置时输出提示;
107
112
  旧配置仍可构建。当前有效开关是 `enabled`、`okHttpCaptureEnabled`,以及可选
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mobileaidev/ai-app-bridge",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "description": "Desktop CLI and MCP server for AI App Bridge across Android, iOS, Flutter, WebView, and Web targets.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "ai-app-bridge-playwright-runtime",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "ai-app-bridge-playwright-runtime",
9
- "version": "0.3.6",
9
+ "version": "0.3.7",
10
10
  "dependencies": {
11
11
  "playwright": "1.63.0"
12
12
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-app-bridge-playwright-runtime",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "private": true,
5
5
  "description": "Optional, isolated browser runtime managed by AI App Bridge.",
6
6
  "engines": { "node": ">=26.3.0 <27" },