@mobileaidev/ai-app-bridge 0.3.7 → 0.4.0

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 (64) hide show
  1. package/README.md +52 -39
  2. package/bin/ai-app-bridge.js +56 -17
  3. package/bin/command-discovery.js +19 -4
  4. package/bin/command-registry.js +21 -6
  5. package/bin/command-request.js +68 -4
  6. package/bin/execution-host.js +32 -5
  7. package/bin/execution-runtime.js +17 -10
  8. package/bin/executors/command-schema.js +1 -1
  9. package/bin/executors/preparation.js +262 -0
  10. package/bin/extraction/json-value.js +26 -0
  11. package/bin/extraction/prepare.js +57 -0
  12. package/bin/extraction/regex.js +30 -0
  13. package/bin/extraction/runner.js +77 -0
  14. package/bin/intent/install-intent.js +3 -1
  15. package/bin/ios-provider.js +2 -2
  16. package/bin/ios-wda-project.js +48 -1
  17. package/bin/mcp-server.js +15 -20
  18. package/bin/public-reply.js +184 -0
  19. package/bin/response-store.js +60 -0
  20. package/bin/runtime-client.js +32 -15
  21. package/bin/runtime-directory.js +37 -8
  22. package/bin/script/node-runtime-adapter.js +139 -123
  23. package/bin/script/python-runtime-adapter.js +1 -1
  24. package/bin/script/script-diagnostics.js +21 -0
  25. package/bin/script/script-durable-restore.js +1 -0
  26. package/bin/script/script-host-port.js +3 -2
  27. package/bin/script/script-sdk.js +39 -4
  28. package/bin/script/script-sdk.py +79 -7
  29. package/bin/script/script-session-channel.js +27 -10
  30. package/bin/script/script-supervisor.js +8 -0
  31. package/bin/shared-kernel/argument-schema.js +44 -12
  32. package/bin/shared-kernel/evidence-archive.js +2 -2
  33. package/bin/shared-kernel/evidence-schema.js +16 -1
  34. package/bin/shared-kernel/evidence-store.js +3 -3
  35. package/bin/shared-kernel/execution-contracts.js +13 -5
  36. package/bin/shared-kernel/execution-target.js +4 -0
  37. package/bin/shared-kernel/request-context.js +2 -2
  38. package/bin/target-execution.js +2 -0
  39. package/docs/COMMAND_CONTRACT.md +91 -19
  40. package/docs/EVIDENCE_ARCHIVE.md +14 -1
  41. package/docs/INSTALLATION.md +73 -0
  42. package/docs/INTENT_FOREGROUND.md +4 -1
  43. package/docs/OPTIONAL_EXECUTORS.md +41 -13
  44. package/docs/RELEASE.md +60 -113
  45. package/docs/RESPONSE_EXTRACTION.md +122 -0
  46. package/docs/SCRIPT_AUTHORING.md +125 -6
  47. package/node_modules/@mobileaidev/segmented-fact-store-native/PREBUILDS.md +29 -0
  48. package/node_modules/@mobileaidev/segmented-fact-store-native/binding-path.js +29 -0
  49. package/node_modules/@mobileaidev/segmented-fact-store-native/binding.gyp +1 -0
  50. package/node_modules/@mobileaidev/segmented-fact-store-native/index.js +1 -3
  51. package/node_modules/@mobileaidev/segmented-fact-store-native/install.js +5 -0
  52. package/node_modules/@mobileaidev/segmented-fact-store-native/package.json +11 -5
  53. package/node_modules/@mobileaidev/segmented-fact-store-native/prebuilds/darwin-arm64/segmented_fact_store.node +0 -0
  54. package/node_modules/@mobileaidev/segmented-fact-store-native/prebuilds/darwin-x64/segmented_fact_store.node +0 -0
  55. package/node_modules/@mobileaidev/segmented-fact-store-native/prebuilds/linux-arm64-glibc/segmented_fact_store.node +0 -0
  56. package/node_modules/@mobileaidev/segmented-fact-store-native/prebuilds/linux-x64-glibc/segmented_fact_store.node +0 -0
  57. package/node_modules/@mobileaidev/segmented-fact-store-native/prebuilds/manifest.json +27 -0
  58. package/node_modules/@mobileaidev/segmented-fact-store-native/scripts/build-release-prebuilds.js +33 -0
  59. package/node_modules/@mobileaidev/segmented-fact-store-native/scripts/stage-prebuild.js +17 -0
  60. package/package.json +12 -5
  61. package/runtime/executors/android/prepare.init.gradle +92 -0
  62. package/runtime/executors/playwright/package-lock.json +2 -2
  63. package/runtime/executors/playwright/package.json +1 -1
  64. package/skills/ai-app-bridge-use/SKILL.md +19 -4
@@ -0,0 +1,73 @@
1
+ # Installation and supported Host platforms
2
+
3
+ The simplest path is a supported Node installation and one MCP configuration.
4
+ The same npm package contains CLI and MCP; running only MCP is supported.
5
+ FactStore is an embedded library bundled in that package. There is no separate
6
+ database, FactStore service or CLI process to install first.
7
+
8
+ This source targets 0.4.0. Registry publication is a separate step; before
9
+ publication, use the reviewed local tarball instead of expecting this registry
10
+ version to resolve.
11
+
12
+ ```json
13
+ {
14
+ "mcpServers": {
15
+ "ai-app-bridge": {
16
+ "command": "npx",
17
+ "args": ["--yes", "--package", "@mobileaidev/ai-app-bridge@0.4.0", "ai-app-bridge-mcp"]
18
+ }
19
+ }
20
+ }
21
+ ```
22
+
23
+ For a local tarball, replace the package/version argument with its absolute
24
+ `.tgz` path. Pin a version; do not let an unrelated global CLI installation
25
+ silently determine the MCP server version. After upgrading, reconnect the MCP
26
+ client so it loads the new code. Read mismatch diagnostics before stopping any
27
+ shared Runtime: an older client should be upgraded without stopping a newer owner.
28
+
29
+ ## Requirements
30
+
31
+ | Layer | Requirement |
32
+ | --- | --- |
33
+ | Host runtime | Node >=26.3.0 <27; validation baseline 26.3.0 |
34
+ | macOS Host | arm64 or x64, macOS 13.5+ |
35
+ | Linux Host | arm64 or x64, glibc 2.28+, kernel 4.18+; Node's libstdc++ and libatomic runtime requirements |
36
+ | Native store | Bundled Node-API 8 addon selected by OS/architecture/libc, checksum checked; no compiler/Python during normal install |
37
+ | JS/regex extraction and ordinary commands | No Python interpreter needed |
38
+ | Python Script/extraction | Python 3.9+; optionally set AI_APP_BRIDGE_PYTHON |
39
+ | Android provider | ADB and a connected device; SDK commands need the App's debuggable Bridge integration |
40
+ | iOS/WDA provider | macOS, Xcode and the device/provider setup in COMMAND_CONTRACT |
41
+ | Web providers | Browser/App connection required by the selected provider |
42
+
43
+ The Node OS/library baseline follows [Node 26.3.0 build/platform requirements](https://github.com/nodejs/node/blob/v26.3.0/BUILDING.md#platform-list).
44
+ It does not imply validation on every later OS or Node minor release. Native
45
+ Windows, musl/Alpine and other architectures are outside this native Host matrix;
46
+ the POSIX store does not acquire Windows support from a sample cmd.exe config.
47
+ WDA 14.1.1 is installed as an npm dependency on all platforms, but preparation
48
+ and execution use macOS. No split WDA package is required for basic MCP use.
49
+
50
+ Missing/corrupt/unsupported prebuilds fail with the actual OS, architecture and
51
+ Node-API information. Normal install never silently compiles, downloads a
52
+ substitute addon or chooses another storage backend. Release checks must verify
53
+ each matrix artifact; a Mac build alone is not Linux acceptance.
54
+
55
+ ## Development and release verification
56
+
57
+ Native maintainers may explicitly run `npm run build` in
58
+ `native/segmented-fact-store` to build from source with node-gyp and stage their
59
+ local artifact. This requires the developer's compiler/Python. Release artifacts
60
+ must also record their actual ABI minimum; never label a newer glibc build 2.28.
61
+ The loader and startup fingerprint use the same selected `.node` file.
62
+
63
+ `npm run verify:package -- /absolute/new/output` creates a real tarball and a
64
+ fresh installation outside the repository. It denies compiler/Python commands
65
+ for install and the pure MCP npx checks, verifies the loaded artifact/checksum,
66
+ then uses a separate normal environment for the existing two-language regression.
67
+ It checks first/repeated npx start, schema discovery, JS/regex, source ref recovery,
68
+ MCP disconnection versus Runtime lifetime, durable store restart and controlled
69
+ ADB scenarios. This is package/transport evidence, not physical-device acceptance.
70
+
71
+ `npm test` runs functional checks and then a serial performance group. Use
72
+ `npm run test:performance` on an otherwise quiet host for the timing gate;
73
+ existing p95 thresholds are unchanged.
@@ -5,6 +5,7 @@ An Intent can keep its original business target while navigating through explici
5
5
  ```json
6
6
  {
7
7
  "command": "intent",
8
+ "extract": null,
8
9
  "arguments": {
9
10
  "operation": "start",
10
11
  "goal": "Export a backup, choose its file in the system picker, and return to the notes app",
@@ -12,7 +13,9 @@ An Intent can keep its original business target while navigating through explici
12
13
  "target": {
13
14
  "serial": "DEVICE_SERIAL",
14
15
  "packageName": "io.github.mobileaidev.notallyx.sample",
15
- "foregroundPackages": ["com.coloros.filemanager"]
16
+ "foregroundPackages": [
17
+ "com.coloros.filemanager"
18
+ ]
16
19
  }
17
20
  }
18
21
  }
@@ -1,4 +1,4 @@
1
- # Optional UI executors (0.3.7)
1
+ # Optional UI executors (0.4.0)
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
 
@@ -15,9 +15,35 @@ Bridge keeps its existing SDK paths and exposes optional executors through `capa
15
15
 
16
16
  These dependencies are isolated from ordinary production source sets. They are visible in build metadata and diagnostics. They do not disappear from the installation or compatibility requirements. Android does **not** need a separate business App, repository, or Gradle project. The standard test APK is an Android test artifact.
17
17
 
18
- ## Android: one entry in the existing application
18
+ ## Automatic preparation in the existing project
19
19
 
20
- Add the selected artifacts to the application's `androidTestImplementation` configuration. All Bridge artifacts use the same version:
20
+ Use `executor-prepare` from CLI, MCP `run`, or JavaScript/Python `ctx.call` with `app.test`. This is a Host operation: it does not require a device target, install an App, start UI observation, or open an executor session. Preparation uses the selected project's existing toolchain and keeps its application ID. The result separates preparation from installation and session readiness.
21
+
22
+ ```sh
23
+ ai-app-bridge executor-prepare --extract null --platform android --project-dir /project \
24
+ --module :app --variant debug --adapters '["espresso-web"]'
25
+ ai-app-bridge executor-prepare --extract null --platform flutter --project-dir /flutter-app \
26
+ --flutter-path /flutter-sdk/bin/flutter
27
+ ai-app-bridge executor-prepare --extract null --platform ios
28
+ ai-app-bridge executor-prepare --extract null --platform web --browser chromium
29
+ ```
30
+
31
+ - Android: a temporary Gradle init script adds the test dependencies and a generated session class only for this invocation. The dependency-check plugin is applied automatically. The result contains the actual application ID, instrumentation component, test class, APK paths and SHA-256 values. Existing matching test dependencies/runners are reused; conflicting Bridge test dependencies are rejected. Business Gradle, manifest and source files are not edited. Select the actual module and debuggable variant; flavors and APK splits retain their original identities. The current build integration uses the AGP 7.4–8.x variant API on macOS/Linux; AGP 9 and Windows preparation are not part of this profile. A local `file:` Maven `repositoryUrl` can explicitly select development artifacts; ordinary preparation resolves the same release version from JitPack.
32
+ - Flutter: the command runs the project's selected Flutter executable, adds the exact `ai_app_bridge_test` version to `dev_dependencies` with Pub, and generates a test entry under `build/ai-app-bridge`. It supports Pub workspaces, an explicit `entrypoint`, `flavor`, `dartDefines`, and `mainArguments` for applications whose main accepts a string list. Pubspec/lock changes are visible configuration; the result lists them. Main Dart code is not edited. The helper uses the same Flutter SDK as the App. Baseline resolution uses `pub get --enforce-lockfile`: commit a valid application/workspace lockfile first. This prevents dependency changes before comparison, including on a new computer. If adding the helper changes an existing production dependency version or Pub fails midway, preparation restores the pubspec/lock and reports the conflict or original error. A successful dependency solve is followed by a real debug build. Repeated preparation reuses the exact resolved helper. `testPackagePath` explicitly selects a local helper during development and must carry the matching Bridge version. The current WidgetTester host remains Android-only; iOS Flutter controls use the existing iOS Flutter SDK/WDA paths.
33
+ - iOS: checks Xcode and prepares a pinned WDA project in the managed executor directory. Source hashes are verified before reuse. `ios-setup --start-wda` reuses that project to sign, build and launch the Runner for the explicitly selected phone. Xcode, signing credentials, device trust and Enable UI Automation are still required. No XCTest source is added to the business application.
34
+ - Web: uses the existing pinned Playwright/browser preparation, outside the page SDK. It can be reused without modifying the web project or adding browser dependencies to its production bundle.
35
+
36
+ Generated files and logs are placed under the project's `build/ai-app-bridge/prepare/<id>`; each preparation writes `result.json`, including failures. Mobile preparation reports `built-not-installed` (iOS source preparation reports `source-prepared`). Install the returned matching artifacts with the public install commands, then open the selected executor. JS/Python workflow changes do not require rebuilding an already prepared App; changes to application code or test dependencies do.
37
+
38
+ Installing the npm package alone does not install Android SDK/JDK, Flutter, Xcode, Python, or project-specific tools such as Rust. Preparation reports the missing prerequisite or original compiler log; it never upgrades a business toolchain to hide a conflict.
39
+
40
+ Android uses the project's Gradle wrapper. For a monorepo that shares a wrapper outside `projectDir`, pass its exact path as `--gradle-path /path/to/gradlew`. Existing matching test dependencies and a custom test runner are retained. Installing a generated androidTest APK does not require it to declare an application version; manifest package, signature and installed APK bytes are still verified.
41
+
42
+ Android WebView H5 requires the optional `espresso-web` adapter and the application's existing JavaScript configuration. iOS WKWebView uses the existing bound H5 SDK path. Playwright manages browser pages; it is not silently used as the controller for a native App's embedded WebView.
43
+
44
+ ## Android: optional manual customization
45
+
46
+ Automatic preparation generates the entry and dependencies below. Add them manually only when the project needs custom test rules or adapters. All Bridge artifacts use the same version:
21
47
 
22
48
  ```kotlin
23
49
  android {
@@ -26,9 +52,9 @@ android {
26
52
  }
27
53
  }
28
54
  dependencies {
29
- androidTestImplementation("com.github.mobileAiDev.ai-app-bridge:ai-app-bridge-test-instrumentation:0.3.7")
55
+ androidTestImplementation("com.github.mobileAiDev.ai-app-bridge:ai-app-bridge-test-instrumentation:0.4.0")
30
56
  // Optional H5 adapter:
31
- androidTestImplementation("com.github.mobileAiDev.ai-app-bridge:ai-app-bridge-test-espresso-web:0.3.7")
57
+ androidTestImplementation("com.github.mobileAiDev.ai-app-bridge:ai-app-bridge-test-espresso-web:0.4.0")
32
58
  }
33
59
  ```
34
60
 
@@ -48,8 +74,8 @@ Opening a session **restarts and instruments the target application**. Install t
48
74
  ./gradlew :app:assembleDebug :app:assembleDebugAndroidTest
49
75
  adb -s DEVICE install -r -t app/build/outputs/apk/debug/app-debug.apk
50
76
  adb -s DEVICE install -r -t app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk
51
- ai-app-bridge android-executor --operation status --serial DEVICE
52
- ai-app-bridge android-executor --operation open --serial DEVICE \
77
+ ai-app-bridge android-executor --extract null --operation status --serial DEVICE
78
+ ai-app-bridge android-executor --extract null --operation open --serial DEVICE \
53
79
  --package-name example.app \
54
80
  --instrumentation example.app.test/androidx.test.runner.AndroidJUnitRunner \
55
81
  --test-class example.app.BridgeSessionTest --activity example.app.MainActivity
@@ -79,11 +105,13 @@ Compose is optional and its runtime is supplied by the consumer. The initial Com
79
105
 
80
106
  The rule must start **before** Activity/composition creation. The adapter uses automatic test clock advancement and idle frame ticks; animation timing is not wall-clock fidelity. `click` uses Compose touch input; `composeInput`, `composeReplaceText`, `composeClearText`, scroll semantics and `semanticLongClick` are explicit semantics operations. WebView/platform Views and system dialogs require their corresponding adapters. No private Compose field reflection is used by Bridge.
81
107
 
108
+ Espresso text actions have different semantics. `replaceText` is the framework's setter path; a custom editor can deliberately suppress its business listeners, so an immediate text readback is insufficient. `replaceTextViaInputConnection` explicitly selects the editor's full text and commits through its `InputConnection`, reporting `espresso-input-connection`. It supports Unicode when the editor accepts that connection and does not fall back to a setter. `typeText` injects key input and has the framework's keyboard character limits. Reopen the screen and check persisted application state for all three paths; none alone proves a physical keyboard/IME workflow. Espresso observations include checked state for `Checkable` widgets.
109
+
82
110
  ## Flutter
83
111
 
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.
112
+ Add `ai_app_bridge_test: 0.4.0` 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
113
 
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.
114
+ The helper declares Flutter **>=3.41.0** and Dart **>=3.11.0 <4.0.0**. The 0.3.8 automatic preparation was exercised with LocalSend on Flutter **3.41.9 / Android API 36**, preserving all 214 production dependency versions. Earlier executor validation covered Flutter 3.41.9 / API 25 and 3.44.8 / API 36. These are specific verified combinations; other SDK versions still need validation with the application's plugin graph.
87
115
 
88
116
  ```dart
89
117
  // integration_test/bridge_test.dart
@@ -96,7 +124,7 @@ void main() => aiAppBridgeTest(app.main);
96
124
  flutter build apk --debug --target integration_test/bridge_test.dart \
97
125
  --dart-define=INTEGRATION_TEST_SHOULD_REPORT_RESULTS_TO_NATIVE=false
98
126
  adb -s DEVICE install -r -t build/app/outputs/flutter-apk/app-debug.apk
99
- ai-app-bridge flutter-executor --operation open --serial DEVICE \
127
+ ai-app-bridge flutter-executor --extract null --operation open --serial DEVICE \
100
128
  --package-name example.app --activity example.app.MainActivity
101
129
  ```
102
130
 
@@ -105,9 +133,9 @@ This version supports the standard **Android Flutter embedder**, with its normal
105
133
  ## Web
106
134
 
107
135
  ```sh
108
- ai-app-bridge web-executor --operation status --browser chromium
109
- ai-app-bridge web-executor --operation prepare --browser chromium --timeout-ms 300000
110
- ai-app-bridge web-executor --operation open --url http://localhost:3000 --browser chromium
136
+ ai-app-bridge web-executor --extract null --operation status --browser chromium
137
+ ai-app-bridge web-executor --extract null --operation prepare --browser chromium --timeout-ms 300000
138
+ ai-app-bridge web-executor --extract null --operation open --url http://localhost:3000 --browser chromium
111
139
  ```
112
140
 
113
141
  The CLI manages exact Playwright **1.63.0**, an included npm lock file and matching browser downloads. `prepare` is explicit; normal SDK usage does not download browsers. Cache keys include the dependency lock digest, OS and CPU architecture. Node **26.3.x** is the verified Host baseline (`>=26.3.0 <27` contract). Browser preparation is serialized and reports failures. `status` separates the static version from actual executable availability.
package/docs/RELEASE.md CHANGED
@@ -1,113 +1,60 @@
1
- # 0.3.7 发行与接入交接
2
-
3
- 本文件记录正式版的依赖关系和出仓库交付入口。封版要求是同一提交的源码、发行包与公开接入合同一致;单个样本的测试进度不改变包版本或发布状态。推送 Git、创建远端标签及发布 npm/pub 包由维护者执行。
4
-
5
- ## 0.3.7 修复
6
-
7
- - Android Host 读取全部焦点记录,跳过 `null`,不再依赖记录排列顺序。只有一个有效窗口时直接使用;多个窗口通过系统 `mTopFocusedDisplayId` 选择,仍不能唯一定位时返回 `foreground_ambiguous`。
8
- - 包名匹配、SDK 窗口与控件身份校验沿用既有路径。App SDK 只同步发行版本。
9
-
10
- ## 随本版包含的 0.3.6 能力
11
-
12
- - Android、iOS、Flutter、Web 与内嵌 H5 的持续 UI 观察默认关闭;仅按需开启 100–5000 ms 的观察窗口,期限到达、主动停止或相应生命周期退出时清理观察任务。新增三个平台观察控制命令,公开命令共 121 个。
13
- - Flutter 当前树改为显式读取 `/v1/flutter/snapshot`,状态请求不再触发树遍历;CLI/MCP 与 App 内 SDK 需要配套升级。Android 指纹编码减少 JNI 调用与临时分配。实测证据及边界见仓库中的 UI 观察性能评估记录。
14
-
15
- - 可选 Android Instrumentation 会话,复用业务 androidTest;UI Automator、Espresso、Espresso-Web 和 Compose 可在同一会话内选择。
16
- - 可选 Flutter integration_test/WidgetTester 测试入口,以及 Host 管理的 Playwright 1.63.0 浏览器执行器。
17
- - 公开 capabilities + run、Python/JS Script 的 app.test 权限、观测身份、原始回执、取消和设备占用接线。
18
- - Compose 主包/测试包版本检查;按测试配置隔离依赖,不自动升级业务 AGP/Kotlin/Compose。
19
- - Android 7 权限输出的零 flags 省略及空格分隔格式支持,来源为实际 API-25 环境和 AOSP Settings 输出实现。
20
- - 本地交付和外部发布分开记录;这份源码不表示 npm/JitPack/pub.dev 已发布 0.3.7。
21
-
22
- 接入合同、具体依赖和实测性能见 [OPTIONAL_EXECUTORS.md](OPTIONAL_EXECUTORS.md)。
23
-
24
- ## 随本版包含的 0.3.5 修复
25
-
26
- - 修正 UIA nodeRef 原回执对账,正常重启和死进程后的显式启动可完成原 session 审计;未知回执和失效引用仍受保护。
27
- - UIA node runtime 支持 Android API 25+,保留 POSIX 原子重命名、fsync、进程锁与原始 Binder 回调;不使用 dump 或坐标回退。Android 7 权限观察支持未初始化的权限状态以及旧 ActivityManager 的身份字段。
28
- - iOS 对未就绪的 list 快照先执行所选设备的 details 探测;原始 4016 使用断言拒绝可按精确调用公开对账,不删除占用记录。
29
- - WDA 启动前持久保存 XCTest 调用身份。原始启用自动化超时能结算;旧 ios-setup 记录用原公开响应、Host action 与 XCTest 结果公开对账,未知结果继续保留。
30
- - 没有待处理安装时,cancel-install 明确返回 install_action_not_pending,不把空操作报告成安装取消成功。
31
- - 各 SDK 同步版本;原生 SDK 设备执行逻辑沿用 0.3.4。真实业务验收与渠道发布状态单独记录。
32
-
33
- ## 随本版包含的 0.3.3 修复
34
-
35
- - Native 观察按当前 Activity 的窗口组选择节点,保留 Dialog/Popup;修复返回和前进时 Activity 与节点不一致。
36
- - Android 安装与执行校验实际探测 standalone、toybox、busybox 的 SHA-256;保留完整性校验,不要求固定 PATH 命令。
37
- - iOS 未安装 App 的明确启动拒绝及时释放设备;未知回执保留原始结果文件并支持公开核对,不因 JSON 版本号差异拒绝有效结果。
38
- - `device-ownership cancel-install` 可凭原 actionId 取消遗留 PM 会话;恢复只读同一份回执,不重发安装,也不声称回滚。
39
- - CLI `--version`、录制目录、错误字段、Script 起步权限及 Reader UIA 只读重试修正;明确 freeze 与 MCP 重连语义。
40
- - Android Gradle 无实现的历史开关发出弃用提示,旧 DSL 仍可构建;各端统一版本。
41
-
42
- ## 新增可选分发物
43
-
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 坐标。
45
-
46
- ## 版本与消费方式
47
-
48
- | 交付物 | 发行版本 | 独立消费入口 | 发布依赖 |
49
- | --- | --- | --- | --- |
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 的安装依赖 |
56
- | Native store | `0.1.0` | 随 CLI 的 bundled dependency 安装 | 不要求另行发布到 npm;`file:../../native/segmented-fact-store` 是工作区构建入口,最终 tarball 必须包含该依赖源码 |
57
-
58
- Flutter 的 podspec 是随 pub 插件消费的本地 podspec,不是独立 CocoaPods trunk 发布包;原生 iOS 使用根 Swift package。Flutter SwiftPM 的 `../FlutterFramework` 由 Flutter 的集成生成,不能当作本仓库的外部私有依赖,也不应将本机 Flutter framework 打包进插件。
59
-
60
- Host 支持范围声明为 Node `>=26.3.0 <27`,本轮实际验证基线是 **26.3.0**。共享 runtime 与查询索引依赖 `node:sqlite`,native store 安装需要 node-gyp 所需的 Python 和 C/C++ 编译工具。未对其他 Node 版本或跨主版本兼容作实测声明。Python Script 另需可用的 `python3`,从实际 `script runtime-status` 读取环境能力。
61
-
62
- ## 发布顺序
63
-
64
- 1. 完成源码审阅并冻结一个提交,核对以下命令的产物确实来自它;包含当前 untracked 的实际源码、测试和文档,排除本机生成目录。所有对外发行版本使用同一个 `0.3.7`,若需要改版本,先同时更新上表涉及的 manifest 与固定依赖。
65
- 2. 维护者推送提交与 `0.3.7` 标签,让 JitPack 构建 Android SDK/插件。确认两条公开坐标可解析后,再发布依赖它们的 Flutter 包。本地 Gradle project/path/AAR 替换不能证明 JitPack 坐标可消费。
66
- 3. 原生 iOS 消费相同 Git tag 的根 package;完成根 package 的 iOS 构建,不仅构建 `ios/ai-app-bridge-ios/Package.swift`。Flutter iOS 则检查实际 pub 包内 Swift/C 源码与声明相符。
67
- 4. CLI 与 Web SDK 可分别发布到 npm 的 `latest` dist-tag。CLI 的 native store 已打包随行,不等待一个不存在的单独 registry 依赖。Flutter 包发布以第 2 步完成为前提。
68
- 5. 同步 npm `next` 指向 `0.3.7`,让已有候选入口也使用本次正式版。将 GitHub `main` 与发行提交同步,并创建非预发布的 GitHub Release。
69
- 6. 从 registry/tag 安装刚发布的确切版本,读取 `capabilities` 和版本,核对来源及支持范围,确认默认安装入口指向本次发行版本。正式发布不自动等于全平台生产验收完成。
70
-
71
- 正式发布命令需在对应目录由维护者执行,例如 npm 使用 `npm publish --tag latest`;pub 使用 `flutter pub publish`。这些命令属于发布动作,不能混入本地验证脚本。
72
-
73
- ## 本地检查与最终包验证
74
-
75
- 以下检查不发布版本。路径相对仓库根;输出使用新的、Git 忽略的目录。
76
-
77
- ```sh
78
- swift package --package-path . dump-package
79
- swift package --package-path ios/ai-app-bridge-ios dump-package
80
-
81
- cd desktop/ai-app-bridge-cli
82
- npm pack --dry-run --json --ignore-scripts
83
-
84
- cd ../../web/ai-app-bridge-web
85
- npm pack --dry-run --json --ignore-scripts
86
-
87
- cd ../../flutter/ai_app_bridge_flutter
88
- flutter pub publish --dry-run
89
- ```
90
-
91
- `dump-package` 只证明 manifest 可解析及目标声明,不能替代 iOS 编译;`npm pack --dry-run` 只证明拟打包文件清单,不能替代安装;pub dry-run 中的分析/网络检查结果应原样记录。干净安装与 Host 协议验证必须在核心源码冻结、没有运行中修改时执行:
92
-
93
- ```sh
94
- cd desktop/ai-app-bridge-cli
95
- npm ci
96
- npm run verify:package -- ../../build/ai_app_bridge_artifacts/release-package-NEW
97
- ```
98
-
99
- `verify:package` 在仓库外安装实际 tarball,检查 native 安装编译、CLI/MCP 共享运行时、控制接口与随包运行时身份。它使用受控 ADB,不声称完成新真机业务验收。报告、tgz 哈希、安装日志和源码提交身份一起交接;已运行的旧包验证不能代替后来修改过的包。
100
-
101
- CLI 的 `files` 已排除旧 `fact-cache.js` 发布载荷及 fake/P9/旧设备 adapter;旧 fact-cache 实现仅保留为 `test-support` 测试夹具,无生产引用。各 npm 包和 Flutter 目录的 `LICENSE`/`NOTICE` 均来自仓库根原文,发行时核对内容一致,不生成替代版权说明。
102
-
103
- ## 升级进程与后续修复
104
-
105
- npm 升级不会替换已连接的 MCP 进程。用 `ai-app-bridge --version` 核对本机入口;
106
- 已有工作结束后显式停止旧 Runtime,并在 Cursor 等客户端重连 MCP,核对 initialize
107
- 中的 `serverInfo.version`。工具描述仍有旧 `batch`/`smoke` 时刷新客户端缓存。
108
-
109
- 实际发布状态与验证边界见仓库 `docs/RELEASE_HANDOFF_0.3.7_2026-09-15.md`。
110
- Android Gradle 插件的 `webSocketCaptureEnabled`、`logInstrumentationEnabled`、
111
- `webViewDebuggingEnabled` 没有对应插桩实现,现明确弃用并在显式设置时输出提示;
112
- 旧配置仍可构建。当前有效开关是 `enabled`、`okHttpCaptureEnabled`,以及可选
113
- `runtimeDependencyNotation`。不要把弃用选项的配置值当作采集功能已经启用。
1
+ # 0.4.0 改善版发行检查
2
+
3
+ 源码版本、可发布验收、registry 发布和正在运行的客户端是四个不同状态。
4
+ 本文件描述发行操作;源码中的版本号不代表 npm/JitPack/pub.dev 已发布。
5
+ 当前实施与放行证据统一记录于仓库 `docs/IMPROVEMENT_RELEASE_V1_2026-09-18.md`
6
+ 及各 M1–M5 交付记录。最终 A01–A16 对账未全通过前不宣称完整发布验收。
7
+
8
+ ## 兼容与迁移
9
+
10
+ 0.4.0 的外部 run 必填 `extract`,不提取显式 null;CLI `--extract null`。
11
+ 返回公共封套含 execution/control/extraction/delivery,删除额外 `_history`、
12
+ `_meta` 副本。旧请求不自动补字段。业务 value 在 null 且预算内保持原值,
13
+ Script 的内部 ctx.call 仍返回 ok/result。Runtime 协议仍是 aab.runtime/v1。
14
+
15
+ 调用方先核对 execution 和控制字段;提取失败后用原 source ref 调 response
16
+ read,不重放动作。详见 [公共提取合同与完整示例](RESPONSE_EXTRACTION.md)。
17
+ 发现正文超预算时按 command/operation 收窄,不静默裁剪 schema。
18
+
19
+ ## 发行资源
20
+
21
+ | 资源 | 源码版本 | 发行渠道 |
22
+ | --- | --- | --- |
23
+ | Desktop CLI/MCP | 0.4.0 | npm @mobileaidev/ai-app-bridge |
24
+ | 嵌入式 native store | 0.2.0 | 随主包 bundleDependencies,包括四个预编译 addon |
25
+ | Android SDK / Gradle plugin / executor modules | 0.4.0 | 同仓库 Git tag / JitPack |
26
+ | iOS Swift 包 | Git tag 0.4.0 | 根 Package.swift |
27
+ | Flutter SDK / test helper | 0.4.0 | pub.dev;Android 固定依赖同版 SDK |
28
+ | Web SDK | 0.4.0 | npm @mobileaidev/ai-app-bridge-web |
29
+
30
+ UIA bundle、WDA 14.1.1、iOS WDA 模板、Playwright helper 与三类范例随主包。
31
+ 未改变代码的设备组件不需要仅为 Host 返回合同重新安装;需要测试新发行
32
+ 设备产物时记录实际版本/包/序列号,不能用旧安装冒充新包验收。
33
+
34
+ ## 发布前门禁
35
+
36
+ 1. 固定审核提交,核对工作包和 A01–A16,保留失败与未验证项。完整 npm
37
+ 功能组与安静环境串行性能组通过,范例由文档读取实际执行。
38
+ 2. 对 [Host 支持矩阵](INSTALLATION.md) 的四个 artifact 校验 checksum 和
39
+ 实际加载,运行 native tests 与全新 tarball 安装。正常安装和纯 MCP
40
+ JS/regex 路径禁止调用本地编译器/Python;Python 回归使用单独环境。
41
+ 3. 核对 npm pack 清单真实包含 addon、加载器、source read/worker 和文档,
42
+ codeFingerprint 哈希实际选中的二进制。固定版本 npx 首次/重复启动、
43
+ MCP 断连后 Runtime 存续、明确 stop/restart 与持久化恢复均有证据。
44
+ 4. 核实实际 CLI 路径、MCP 启动版本/指纹、Runtime code/config/Node 身份,
45
+ 并检查受影响消费脚本的 extract/公共响应迁移。安装成功不替代入口更新。
46
+ 5. Android/Swift/Flutter/Web 的发行清单和版本一致。需要时运行相应构建,
47
+ 真实设备证据和离线/受控 ADB 测试分开记录。三类实际任务对照保留来源、
48
+ 时间、目标和原始记录,不能将缺设备写成不适用。
49
+
50
+ ## 对外发布顺序
51
+
52
+ 在已授权的发布操作中,维护者先推送已验收提交和 0.4.0 tag,核实 JitPack
53
+ 公开坐标成功解析,再发布依赖它们的 Flutter SDK/helper。Web npm 与主
54
+ CLI/MCP npm 分别发布,并核实 registry 实际返回的 tarball/checksum;设置
55
+ 对应 dist-tag 和 GitHub Release。远端流水线成功与设备业务验收分别列明。
56
+ 本地构建或 MavenLocal/path 替换不能证明公开坐标可安装。
57
+
58
+ 客户端升级时退出旧 MCP 再重新连接。若是旧客户端碰到新 Runtime,先升
59
+ 客户端;只有明确 Runtime 是待升级一侧时,在其任务结束后显式 stop。
60
+ 同版本不同指纹只能说明构建或 Node 环境不一致,不能凭 hash 判断新旧。
@@ -0,0 +1,122 @@
1
+ # Response extraction (0.4.0)
2
+
3
+ Every CLI/MCP run must state what to return. Use `extract:null` for the original
4
+ result within the body budget, or select the fields needed for the current task.
5
+ `extract` and `output` are top-level request fields, separate from business
6
+ `arguments`. The old request without extract is rejected before dispatch.
7
+ Internal Script `ctx.call(command, args)` stays unchanged (`ok`, `result`).
8
+
9
+ ```json extraction-example
10
+ {"command":"runtime","arguments":{"operation":"status"},"extract":null}
11
+ ```
12
+
13
+ ```bash
14
+ ai-app-bridge runtime --operation status --extract null
15
+ ```
16
+
17
+ A small response can be read in full. Large trees, network records and logs are
18
+ better extracted near the Host. This saves response/context bytes, not the
19
+ original collection time. Capture duration, history limit and extraction solve
20
+ different problems; a one-item page can still exceed the byte budget.
21
+
22
+ ## One query, one extraction
23
+
24
+ Regex requires a string at `inputPath` (JSON Pointer). Empty path selects a text
25
+ response; escape `/` as `~1` and `~` as `~0`. Flags are unique `i`, `m`, `s`, `u`;
26
+ all matches are returned with `match`, `groups` and `namedGroups`.
27
+ Unmatched captures are null. At most 1,000 matches are allowed; overflow fails.
28
+
29
+ ```json extraction-example
30
+ {"command":"runtime","arguments":{"operation":"status"},"extract":{"mode":"regex","pattern":"stopped|running","inputPath":"/status"}}
31
+ ```
32
+
33
+ For structured responses, both languages receive exactly
34
+ `ctx.inputs = {kind, response, execution, control}`. `response` is the original
35
+ command value, including its final feedback. This is a short local transform;
36
+ it has no Script `ctx.call`, agent decisions or assertion API.
37
+
38
+ ```json extraction-example
39
+ {"command":"runtime","arguments":{"operation":"status"},"extract":{"mode":"script","language":"javascript","source":"module.exports.main = ctx => ({status:ctx.inputs.response.status, commandOk:ctx.inputs.execution.ok});"}}
40
+ ```
41
+
42
+ ```json extraction-example
43
+ {"command":"runtime","arguments":{"operation":"status"},"extract":{"mode":"script","language":"python","source":"def main(ctx):\n return {\"status\": ctx.inputs[\"response\"][\"status\"], \"commandOk\": ctx.inputs[\"execution\"][\"ok\"]}\n"}}
44
+ ```
45
+
46
+ Use exactly one of `source` and `sourcePath` for scripts. Relative paths resolve
47
+ from the caller directory; the Host freezes the file before executing the
48
+ command. Syntax checks do not execute top-level code. Source is at most 64 KiB
49
+ UTF-8. Python requires Python 3.9+; ordinary, JS and regex calls need no Python.
50
+
51
+ Return strict JSON: null, booleans, strings, finite numbers, arrays and objects.
52
+ Integers outside ±9,007,199,254,740,991 are rejected, including Python values
53
+ before serialization. Convert intentionally to a string inside your source.
54
+ Unsupported types, cycles and sparse JS arrays fail rather than being coerced.
55
+
56
+ ## Read the three outcomes separately
57
+
58
+ The shared compact body is
59
+ `{command, execution, control, extraction, delivery, kind, value?, failureStage?}`.
60
+ `execution` records the original command outcome and dispatch facts. Successful
61
+ extraction cannot convert a failed or unknown command into success. `control`
62
+ preserves operation IDs, receipts, Intent revisions, Script event cursors and
63
+ current pending questions, and capture coverage/pagination. Histories remain in
64
+ value; only their page controls are protected separately.
65
+
66
+ `extraction.status` is skipped, succeeded or failed. `delivery` reports actual
67
+ UTF-8 body bytes and the limit. `failureStage` gives the first failing stage in
68
+ validation → execution → extraction → delivery order. CLI exit codes are 0 for
69
+ requested delivery, 1 for validation/failed or unknown execution, and 2 when a
70
+ known successful command could not be extracted/delivered. MCP uses `isError`
71
+ consistently. A successful Script execution is separate from its business verdict.
72
+
73
+ Preserve source identity, timestamps, state and coverage needed by the actual
74
+ assertion. A selected successful row does not prove complete business coverage.
75
+
76
+ ## Retry extraction without repeating the action
77
+
78
+ Non-null extraction attempts to retain the original response. A null response
79
+ that would exceed the budget also attempts retention. `control.source` is the
80
+ only ref location. Only `persisted:true` makes that ref readable. Null within
81
+ budget normally reports `persisted:false, reason:not_requested`; offline local
82
+ commands report `offline`. Saving and extraction may fail independently.
83
+
84
+ On extraction failure or overflow, copy the original ref and change only the
85
+ extraction in a `response read`. The current read execution is separate from
86
+ original facts in `control.origin`; `control.source` still identifies the same
87
+ snapshot. Repeated reads neither replay devices nor create nested snapshots.
88
+
89
+ ```json
90
+ {
91
+ "command": "response",
92
+ "arguments": {"operation":"read","ref":{"namespace":"response","evidenceId":"<original evidenceId>","checksum":"<original checksum>","operationId":"<original operationId>"}},
93
+ "extract": {"mode":"script","language":"javascript","source":"module.exports.main = ctx => ctx.inputs.response;"},
94
+ "output": {"maxBytes":262144}
95
+ }
96
+ ```
97
+
98
+ A ref is subject to existing evidence retention. Missing/evicted/corrupt sources
99
+ fail explicitly. Reissuing the original action with the same requestId is not a
100
+ substitute for ref recovery: deduplication can expire and does not survive every
101
+ Host lifetime. Snapshot/export JSON preserves original values; binary responses
102
+ are base64 for null delivery and are not extractable in this version.
103
+
104
+ ## Limits and diagnosis
105
+
106
+ | Limit | Value |
107
+ | --- | --- |
108
+ | Final compact UTF-8 body | 96 KiB default; output.maxBytes 16–256 KiB |
109
+ | Source snapshot / extraction input | 8 MiB original UTF-8 JSON |
110
+ | Returned extraction value | 256 KiB (the enclosing body still has its budget) |
111
+ | Extraction timeout | 2,000 ms default; timeoutMs 1–10,000; includes worker startup/input |
112
+ | Active extractions | 2; no queue; busy still preserves the original action result/ref |
113
+ | Failed worker diagnostics | Most recent 8 KiB stderr; stack at most 20 frames and 8 KiB |
114
+
115
+ No budget error returns a truncated JSON document or dumps the large original
116
+ value. If the protected controls themselves cannot fit, `controlComplete:false`
117
+ and `control_over_budget` prohibit continuing from incomplete controls. Use a
118
+ real ref when available, with a sufficient budget or a narrower command query.
119
+ Discovery/help has a separate fixed 96 KiB limit; follow its command/operation
120
+ hint. Runtime stop drains active extraction workers; CLI/MCP disconnect alone
121
+ keeps the shared Runtime alive. Extraction is trusted local code, with bounded
122
+ worker/channel lifetime rather than an OS/process-tree sandbox.