@mobileaidev/ai-app-bridge 0.3.8 → 0.4.1
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 +54 -39
- package/bin/ai-app-bridge.js +56 -17
- package/bin/command-discovery.js +19 -4
- package/bin/command-registry.js +17 -4
- package/bin/command-request.js +68 -4
- package/bin/execution-host.js +31 -5
- package/bin/execution-runtime.js +17 -10
- package/bin/executors/preparation.js +19 -5
- package/bin/extraction/json-value.js +26 -0
- package/bin/extraction/prepare.js +57 -0
- package/bin/extraction/regex.js +30 -0
- package/bin/extraction/runner.js +77 -0
- package/bin/ios-execution.js +6 -0
- package/bin/ios-provider.js +3 -2
- package/bin/mcp-server.js +15 -20
- package/bin/public-reply.js +184 -0
- package/bin/response-store.js +60 -0
- package/bin/runtime-client.js +32 -15
- package/bin/runtime-directory.js +37 -8
- package/bin/script/node-runtime-adapter.js +139 -123
- package/bin/script/python-runtime-adapter.js +1 -1
- package/bin/script/script-diagnostics.js +21 -0
- package/bin/script/script-durable-restore.js +1 -0
- package/bin/script/script-sdk.js +39 -4
- package/bin/script/script-sdk.py +79 -7
- package/bin/script/script-session-channel.js +27 -10
- package/bin/script/script-supervisor.js +8 -0
- package/bin/shared-kernel/argument-schema.js +44 -12
- package/bin/shared-kernel/evidence-archive.js +2 -2
- package/bin/shared-kernel/evidence-schema.js +16 -1
- package/bin/shared-kernel/evidence-store.js +3 -3
- package/bin/shared-kernel/execution-contracts.js +13 -5
- package/docs/COMMAND_CONTRACT.md +102 -19
- package/docs/EVIDENCE_ARCHIVE.md +14 -1
- package/docs/INSTALLATION.md +74 -0
- package/docs/INTENT_FOREGROUND.md +4 -1
- package/docs/OPTIONAL_EXECUTORS.md +14 -14
- package/docs/RELEASE.md +71 -122
- package/docs/RESPONSE_EXTRACTION.md +126 -0
- package/docs/SCRIPT_AUTHORING.md +125 -6
- package/node_modules/@mobileaidev/segmented-fact-store-native/PREBUILDS.md +29 -0
- package/node_modules/@mobileaidev/segmented-fact-store-native/binding-path.js +29 -0
- package/node_modules/@mobileaidev/segmented-fact-store-native/binding.gyp +1 -0
- package/node_modules/@mobileaidev/segmented-fact-store-native/index.js +1 -3
- package/node_modules/@mobileaidev/segmented-fact-store-native/install.js +5 -0
- package/node_modules/@mobileaidev/segmented-fact-store-native/package.json +11 -5
- package/node_modules/@mobileaidev/segmented-fact-store-native/prebuilds/darwin-arm64/segmented_fact_store.node +0 -0
- package/node_modules/@mobileaidev/segmented-fact-store-native/prebuilds/darwin-x64/segmented_fact_store.node +0 -0
- package/node_modules/@mobileaidev/segmented-fact-store-native/prebuilds/linux-arm64-glibc/segmented_fact_store.node +0 -0
- package/node_modules/@mobileaidev/segmented-fact-store-native/prebuilds/linux-x64-glibc/segmented_fact_store.node +0 -0
- package/node_modules/@mobileaidev/segmented-fact-store-native/prebuilds/manifest.json +27 -0
- package/node_modules/@mobileaidev/segmented-fact-store-native/scripts/build-release-prebuilds.js +33 -0
- package/node_modules/@mobileaidev/segmented-fact-store-native/scripts/stage-prebuild.js +17 -0
- package/package.json +12 -5
- package/runtime/executors/android/prepare.init.gradle +22 -0
- package/runtime/executors/playwright/package-lock.json +2 -2
- package/runtime/executors/playwright/package.json +1 -1
- package/skills/ai-app-bridge-use/SKILL.md +19 -4
package/docs/COMMAND_CONTRACT.md
CHANGED
|
@@ -13,7 +13,7 @@ a light command directory. Use `capabilities {"command":"tap-text"}`
|
|
|
13
13
|
for its current `inputSchema`, platform, role and supported entrypoints. Domain
|
|
14
14
|
`execution` contains Intent, Script, runtime lifecycle and device ownership;
|
|
15
15
|
`evidence` contains archive operations.
|
|
16
|
-
`
|
|
16
|
+
Discovery has a fixed 96 KiB budget. Broad `includeOptions:true` queries may return `discovery_output_too_large`; use the returned narrower query. Schemas are never silently pruned.
|
|
17
17
|
|
|
18
18
|
Load only the operation needed for Intent, Script or evidence, for example
|
|
19
19
|
`capabilities {"command":"intent","operation":"start"}`. To inspect an Intent
|
|
@@ -24,10 +24,19 @@ runtime contract. Intent terminal decisions remain available in the selected
|
|
|
24
24
|
decision schema. Unsupported operations or scope combinations return an error
|
|
25
25
|
with the offending field. Omit filters to read the complete command contract.
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Business parameters are under `run.arguments`. The required top-level `extract` chooses delivery; explicit `null` requests the original result within budget:
|
|
28
28
|
|
|
29
29
|
```json
|
|
30
|
-
{
|
|
30
|
+
{
|
|
31
|
+
"command": "tap-text",
|
|
32
|
+
"extract": null,
|
|
33
|
+
"arguments": {
|
|
34
|
+
"serial": "DEVICE",
|
|
35
|
+
"packageName": "com.example.app",
|
|
36
|
+
"targetText": "设置",
|
|
37
|
+
"provider": "auto"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
31
40
|
```
|
|
32
41
|
|
|
33
42
|
Names are canonical and case-sensitive. Unknown arguments, aliases, invalid
|
|
@@ -55,8 +64,8 @@ provider access and device ownership through their execution-specific contracts.
|
|
|
55
64
|
### Shared runtime lifecycle
|
|
56
65
|
|
|
57
66
|
The first executing command starts a local runtime. `runtime --operation start`
|
|
58
|
-
starts it explicitly; `runtime --operation status` inspects it without starting
|
|
59
|
-
one; `runtime --operation stop` cancels and drains active work before releasing
|
|
67
|
+
starts it explicitly; `runtime --operation status --extract null` inspects it without starting
|
|
68
|
+
one; `runtime --operation stop --extract null` cancels and drains active work before releasing
|
|
60
69
|
its ownership. CLI exit, MCP EOF and client SIGINT/SIGTERM close only that client.
|
|
61
70
|
Use `intent`/`script --operation cancel --operation-id ID` to cancel one task.
|
|
62
71
|
The same operation ID can be queried and controlled from either entrypoint.
|
|
@@ -93,12 +102,26 @@ there; Script freezes its `cwd`, source and target before starting. Subsequent
|
|
|
93
102
|
clients cannot change those paths. `evidence verify` is offline in both adapters
|
|
94
103
|
and requires neither a running runtime nor an available FactStore.
|
|
95
104
|
|
|
96
|
-
CLI results are one JSON envelope:
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
105
|
+
CLI results are one compact JSON envelope:
|
|
106
|
+
`{command, execution, control, extraction, delivery, kind, value?, failureStage?}`.
|
|
107
|
+
MCP returns this same body in tool text; no second `_meta`, `_history` or
|
|
108
|
+
`structuredContent` copy is attached. `execution` records the command outcome;
|
|
109
|
+
`control` retains continuation, current pending questions, receipts and capture
|
|
110
|
+
coverage. With `extract:null`, `value` is the command's original value including
|
|
111
|
+
`_feedback`; otherwise it is the extracted JSON value when delivered.
|
|
112
|
+
|
|
113
|
+
The default final-body budget is 96 KiB UTF-8. `output.maxBytes` can select
|
|
114
|
+
16–256 KiB. Overflow never returns a truncated JSON document or a large original
|
|
115
|
+
fallback. Inspect `control.source`: only `persisted:true` provides a readable
|
|
116
|
+
ref. Retry extraction with `response read` and this ref; repeating the original
|
|
117
|
+
action with the same requestId is not a recovery guarantee. Original response
|
|
118
|
+
snapshots and their exports preserve the original JSON representation.
|
|
119
|
+
|
|
120
|
+
Exit 0 means requested delivery succeeded; 1 means validation/execution failed
|
|
121
|
+
or remained unknown; 2 means the command succeeded but extraction/delivery
|
|
122
|
+
failed. `failureStage` prioritizes validation, execution, extraction, delivery.
|
|
123
|
+
MCP sets `isError` consistently. See [response extraction](RESPONSE_EXTRACTION.md)
|
|
124
|
+
for exact examples, budgets, ref recovery and the distinction from Script.
|
|
102
125
|
|
|
103
126
|
`batch`, `smoke`, `launch-native-test` and `launch-flutter` were removed. Use a
|
|
104
127
|
code Script for sequences, `launch-app` for a Flutter app's actual launcher, and
|
|
@@ -503,6 +526,30 @@ or call budget prevents another Agent call. Malformed replies remain
|
|
|
503
526
|
`waiting_for_decision` with a field error and require explicit correction; they
|
|
504
527
|
neither dispatch nor trigger another Agent request automatically.
|
|
505
528
|
|
|
529
|
+
A supervised Intent is driven by the caller: observe, decide against the
|
|
530
|
+
observed revision, observe again, judge independently. One complete lifecycle,
|
|
531
|
+
as sent to `run` (the repository test suite runs this sequence against the
|
|
532
|
+
current contract with an injected device):
|
|
533
|
+
|
|
534
|
+
```json lifecycle-example
|
|
535
|
+
{"command":"intent","extract":null,"arguments":{"operation":"start","goal":"Open the Labels screen","target":{"platform":"android","serial":"<serial>","packageName":"<package>"}}}
|
|
536
|
+
{"command":"intent","extract":null,"arguments":{"operation":"decide","operationId":"<operationId>","decision":{"decisionId":"d-1","agentDecision":"act","basedOnRevision":1,"action":{"action":"tap","selector":{"text":"Labels"}}}}}
|
|
537
|
+
{"command":"intent","extract":null,"arguments":{"operation":"status","operationId":"<operationId>","limit":20}}
|
|
538
|
+
{"command":"intent","extract":null,"arguments":{"operation":"status","operationId":"<operationId>","limit":20,"afterSequence":"<history.lastSequence of the previous page>"}}
|
|
539
|
+
{"command":"intent","extract":null,"arguments":{"operation":"decide","operationId":"<operationId>","decision":{"decisionId":"d-2","agentDecision":"complete","basedOnRevision":2}}}
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
`start` and each `decide` return the committed observation with its `revision`
|
|
543
|
+
and `summary`; the next decision must carry that `revision` as
|
|
544
|
+
`basedOnRevision`. `status` returns the current state plus one history page.
|
|
545
|
+
`limit` bounds entries, not bytes: a page of `summary` entries can still be
|
|
546
|
+
large, so read the current state with a small `limit` and page history
|
|
547
|
+
deliberately. The next page's `afterSequence` is the previous page's
|
|
548
|
+
`history.lastSequence`; it is not an `eventSequence`, which belongs to Script.
|
|
549
|
+
Supervised mode never acts on its own: without a decision the Intent stays
|
|
550
|
+
`waiting_for_decision` until `timeoutMs`, and `complete` records the caller's
|
|
551
|
+
judgment rather than evidence of the business outcome.
|
|
552
|
+
|
|
506
553
|
Every decision requires `decisionId`, positive integer `basedOnRevision`, and
|
|
507
554
|
`agentDecision`. `act` requires a provider-specific `action`; terminal decisions
|
|
508
555
|
`complete/fail/inconclusive` forbid one. Tap uses an exact `selector` object, with
|
|
@@ -1186,7 +1233,23 @@ exact and come from one fresh visible provider tree; metadata, hidden windows
|
|
|
1186
1233
|
and text from another provider cannot complete a condition. For example:
|
|
1187
1234
|
|
|
1188
1235
|
```json
|
|
1189
|
-
{
|
|
1236
|
+
{
|
|
1237
|
+
"command": "wait-text",
|
|
1238
|
+
"extract": null,
|
|
1239
|
+
"arguments": {
|
|
1240
|
+
"serial": "DEVICE",
|
|
1241
|
+
"packageName": "com.example.app",
|
|
1242
|
+
"provider": "native",
|
|
1243
|
+
"targetText": "Save, draft",
|
|
1244
|
+
"requireText": [
|
|
1245
|
+
"Editor"
|
|
1246
|
+
],
|
|
1247
|
+
"absentText": [
|
|
1248
|
+
"Loading"
|
|
1249
|
+
],
|
|
1250
|
+
"timeoutMs": 5000
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1190
1253
|
```
|
|
1191
1254
|
|
|
1192
1255
|
At least one condition is required. Pure absence or Activity-only waits require
|
|
@@ -1491,7 +1554,7 @@ The operation holds the phone's mutation lease through package verification.
|
|
|
1491
1554
|
For example, after receiving a fresh observation:
|
|
1492
1555
|
|
|
1493
1556
|
```json
|
|
1494
|
-
{"command":"intent","arguments":{"operation":"decide","operationId":"FROM_START","decision":{"decisionId":"choice-1","basedOnRevision":2,"agentDecision":"act","action":{"action":"tap","selector":{"resourceName":"ID_FROM_ACTUAL_OBSERVATION"}}}}}
|
|
1557
|
+
{"command":"intent","extract":null,"arguments":{"operation":"decide","operationId":"FROM_START","decision":{"decisionId":"choice-1","basedOnRevision":2,"agentDecision":"act","action":{"action":"tap","selector":{"resourceName":"ID_FROM_ACTUAL_OBSERVATION"}}}}}
|
|
1495
1558
|
```
|
|
1496
1559
|
|
|
1497
1560
|
Completion requires the matching original shell-job receipt, a successful
|
|
@@ -1535,11 +1598,11 @@ provider operation. A history failure never retries or rewrites that operation.
|
|
|
1535
1598
|
Intent/Script required evidence commits retain their existing strict admission
|
|
1536
1599
|
and terminal-evidence contracts.
|
|
1537
1600
|
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1601
|
+
Public replies carry command recording status in `control.history` with schema
|
|
1602
|
+
`aab.command-history/v1`, where applicable. Full Intent history and original
|
|
1603
|
+
business values remain in value; only page/continuation fields are protected.
|
|
1604
|
+
CLI and MCP share the same compact body. There is no duplicate `_history` or
|
|
1605
|
+
MCP `_meta["ai-app-bridge/history"]` attachment.
|
|
1543
1606
|
|
|
1544
1607
|
- `stored`: this invocation's action and returned Host evidence references were
|
|
1545
1608
|
committed. It is not a claim of complete mobile history or business correctness.
|
|
@@ -1562,7 +1625,16 @@ Background observer health remains separate from this foreground write report.
|
|
|
1562
1625
|
Trigger the runtime permission request through the App's existing flow, then call:
|
|
1563
1626
|
|
|
1564
1627
|
```json
|
|
1565
|
-
{
|
|
1628
|
+
{
|
|
1629
|
+
"command": "permission-dialog",
|
|
1630
|
+
"extract": null,
|
|
1631
|
+
"arguments": {
|
|
1632
|
+
"serial": "DEVICE",
|
|
1633
|
+
"packageName": "com.example.app",
|
|
1634
|
+
"permission": "android.permission.RECORD_AUDIO",
|
|
1635
|
+
"outcome": "allow-once"
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1566
1638
|
```
|
|
1567
1639
|
|
|
1568
1640
|
This MCP entry returns an ordinary Intent ID, the actual UI summary, and
|
|
@@ -1671,6 +1743,17 @@ tree or publish cached layout as current UI. Query a provider's observation
|
|
|
1671
1743
|
command for its live lease state. These endpoints require rebuilt SDKs;
|
|
1672
1744
|
installing a new CLI cannot patch an installed application's old SDK.
|
|
1673
1745
|
|
|
1746
|
+
iOS observation control uses the SDK's bounded capture lease, not physical-device
|
|
1747
|
+
action ownership. A rejected control or lost response cannot block later UI
|
|
1748
|
+
actions, and its HTTP request does not mark an enclosing UI action dispatched.
|
|
1749
|
+
An older Host may have left an `ios-command` / `ios-ui-observation` ownership
|
|
1750
|
+
marker. Explicit `ios-execution --operation reconcile` retires only that marker
|
|
1751
|
+
after checking the recorded device and any supplied bundle identity. Its receipt
|
|
1752
|
+
reports `reason: observation_control_not_device_mutation` and
|
|
1753
|
+
`observationOutcome: unknown`; it does not claim that observation started or
|
|
1754
|
+
stopped successfully. Other unresolved actions still require their original
|
|
1755
|
+
completion proof. Runtime restart alone does not erase the durable journal.
|
|
1756
|
+
|
|
1674
1757
|
Ordinary CLI/MCP `feedback=full` opens a window before the action and releases
|
|
1675
1758
|
it in finally. If observation is unavailable, the action is rejected before
|
|
1676
1759
|
dispatch; acquiring evidence does not mark the enclosing UI action dispatched.
|
package/docs/EVIDENCE_ARCHIVE.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Record, export and verify execution evidence
|
|
2
2
|
|
|
3
3
|
Discover the public MCP command with `capabilities {"command":"evidence"}`.
|
|
4
|
-
It works for
|
|
4
|
+
It works for Intent operation IDs, Script execution IDs and saved response IDs, including
|
|
5
5
|
records retained after the execution runtime has restarted. CLI and MCP use the
|
|
6
6
|
same operation IDs and export command. Export does not require a
|
|
7
7
|
connected phone or a live worker.
|
|
@@ -9,6 +9,7 @@ connected phone or a live worker.
|
|
|
9
9
|
```json
|
|
10
10
|
{
|
|
11
11
|
"command": "evidence",
|
|
12
|
+
"extract": null,
|
|
12
13
|
"arguments": {
|
|
13
14
|
"operation": "export",
|
|
14
15
|
"namespace": "intent",
|
|
@@ -24,6 +25,16 @@ queued writes, and freezes the retained records for exactly that namespace
|
|
|
24
25
|
and operation. The parent directory must exist; the output directory must
|
|
25
26
|
not exist. No existing directory is replaced.
|
|
26
27
|
|
|
28
|
+
For a saved public response, use `namespace: "response"` and the unchanged
|
|
29
|
+
`control.source.ref.operationId`. A response record stores the final command
|
|
30
|
+
result and execution/control facts in `snapshotBase64`, using canonical UTF-8
|
|
31
|
+
JSON bytes after feedback has been added. The decoded bytes are exactly the
|
|
32
|
+
input used for extraction. They can differ from a UI history record captured
|
|
33
|
+
earlier. Export and verification preserve these bytes and use the existing
|
|
34
|
+
evidence checksum; no second snapshot checksum or archive format is added.
|
|
35
|
+
Only `control.source.persisted: true` supplies a readable ref. Missing, expired
|
|
36
|
+
or evicted responses fail reads; they never cause a device query or action.
|
|
37
|
+
|
|
27
38
|
The response includes `archiveDir`, `manifestPath`, `manifestSha256`,
|
|
28
39
|
`recordCount`, `targets`, and `coverage`. Save the returned manifest SHA256
|
|
29
40
|
separately when handing the archive to an author or reviewer.
|
|
@@ -52,6 +63,7 @@ Move or copy the directory as a unit, then call:
|
|
|
52
63
|
```json
|
|
53
64
|
{
|
|
54
65
|
"command": "evidence",
|
|
66
|
+
"extract": null,
|
|
55
67
|
"arguments": {
|
|
56
68
|
"operation": "verify",
|
|
57
69
|
"archiveDir": "/absolute/moved-archive",
|
|
@@ -181,6 +193,7 @@ Use the same public export call with `includeRecordedPayloads: true`:
|
|
|
181
193
|
```json
|
|
182
194
|
{
|
|
183
195
|
"command": "evidence",
|
|
196
|
+
"extract": null,
|
|
184
197
|
"arguments": {
|
|
185
198
|
"operation": "export",
|
|
186
199
|
"namespace": "script",
|
|
@@ -0,0 +1,74 @@
|
|
|
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 the coordinated 0.4.1 release.
|
|
9
|
+
Registry publication is a separate step; before
|
|
10
|
+
publication, use the reviewed local tarball instead of expecting this registry
|
|
11
|
+
version to resolve.
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"mcpServers": {
|
|
16
|
+
"ai-app-bridge": {
|
|
17
|
+
"command": "npx",
|
|
18
|
+
"args": ["--yes", "--package", "@mobileaidev/ai-app-bridge@0.4.1", "ai-app-bridge-mcp"]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
For a local tarball, replace the package/version argument with its absolute
|
|
25
|
+
`.tgz` path. Pin a version; do not let an unrelated global CLI installation
|
|
26
|
+
silently determine the MCP server version. After upgrading, reconnect the MCP
|
|
27
|
+
client so it loads the new code. Read mismatch diagnostics before stopping any
|
|
28
|
+
shared Runtime: an older client should be upgraded without stopping a newer owner.
|
|
29
|
+
|
|
30
|
+
## Requirements
|
|
31
|
+
|
|
32
|
+
| Layer | Requirement |
|
|
33
|
+
| --- | --- |
|
|
34
|
+
| Host runtime | Node >=26.3.0 <27; validation baseline 26.3.0 |
|
|
35
|
+
| macOS Host | arm64 or x64, macOS 13.5+ |
|
|
36
|
+
| Linux Host | arm64 or x64, glibc 2.28+, kernel 4.18+; Node's libstdc++ and libatomic runtime requirements |
|
|
37
|
+
| Native store | Bundled Node-API 8 addon selected by OS/architecture/libc, checksum checked; no compiler/Python during normal install |
|
|
38
|
+
| JS/regex extraction and ordinary commands | No Python interpreter needed |
|
|
39
|
+
| Python Script/extraction | Python 3.9+; optionally set AI_APP_BRIDGE_PYTHON |
|
|
40
|
+
| Android provider | ADB and a connected device; SDK commands need the App's debuggable Bridge integration |
|
|
41
|
+
| iOS/WDA provider | macOS, Xcode and the device/provider setup in COMMAND_CONTRACT |
|
|
42
|
+
| Web providers | Browser/App connection required by the selected provider |
|
|
43
|
+
|
|
44
|
+
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).
|
|
45
|
+
It does not imply validation on every later OS or Node minor release. Native
|
|
46
|
+
Windows, musl/Alpine and other architectures are outside this native Host matrix;
|
|
47
|
+
the POSIX store does not acquire Windows support from a sample cmd.exe config.
|
|
48
|
+
WDA 14.1.1 is installed as an npm dependency on all platforms, but preparation
|
|
49
|
+
and execution use macOS. No split WDA package is required for basic MCP use.
|
|
50
|
+
|
|
51
|
+
Missing/corrupt/unsupported prebuilds fail with the actual OS, architecture and
|
|
52
|
+
Node-API information. Normal install never silently compiles, downloads a
|
|
53
|
+
substitute addon or chooses another storage backend. Release checks must verify
|
|
54
|
+
each matrix artifact; a Mac build alone is not Linux acceptance.
|
|
55
|
+
|
|
56
|
+
## Development and release verification
|
|
57
|
+
|
|
58
|
+
Native maintainers may explicitly run `npm run build` in
|
|
59
|
+
`native/segmented-fact-store` to build from source with node-gyp and stage their
|
|
60
|
+
local artifact. This requires the developer's compiler/Python. Release artifacts
|
|
61
|
+
must also record their actual ABI minimum; never label a newer glibc build 2.28.
|
|
62
|
+
The loader and startup fingerprint use the same selected `.node` file.
|
|
63
|
+
|
|
64
|
+
`npm run verify:package -- /absolute/new/output` creates a real tarball and a
|
|
65
|
+
fresh installation outside the repository. It denies compiler/Python commands
|
|
66
|
+
for install and the pure MCP npx checks, verifies the loaded artifact/checksum,
|
|
67
|
+
then uses a separate normal environment for the existing two-language regression.
|
|
68
|
+
It checks first/repeated npx start, schema discovery, JS/regex, source ref recovery,
|
|
69
|
+
MCP disconnection versus Runtime lifetime, durable store restart and controlled
|
|
70
|
+
ADB scenarios. This is package/transport evidence, not physical-device acceptance.
|
|
71
|
+
|
|
72
|
+
`npm test` runs functional checks and then a serial performance group. Use
|
|
73
|
+
`npm run test:performance` on an otherwise quiet host for the timing gate;
|
|
74
|
+
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": [
|
|
16
|
+
"foregroundPackages": [
|
|
17
|
+
"com.coloros.filemanager"
|
|
18
|
+
]
|
|
16
19
|
}
|
|
17
20
|
}
|
|
18
21
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Optional UI executors (0.
|
|
1
|
+
# Optional UI executors (0.4.1)
|
|
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
|
|
|
@@ -20,12 +20,12 @@ These dependencies are isolated from ordinary production source sets. They are v
|
|
|
20
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
21
|
|
|
22
22
|
```sh
|
|
23
|
-
ai-app-bridge executor-prepare --platform android --project-dir /project \
|
|
23
|
+
ai-app-bridge executor-prepare --extract null --platform android --project-dir /project \
|
|
24
24
|
--module :app --variant debug --adapters '["espresso-web"]'
|
|
25
|
-
ai-app-bridge executor-prepare --platform flutter --project-dir /flutter-app \
|
|
25
|
+
ai-app-bridge executor-prepare --extract null --platform flutter --project-dir /flutter-app \
|
|
26
26
|
--flutter-path /flutter-sdk/bin/flutter
|
|
27
|
-
ai-app-bridge executor-prepare --platform ios
|
|
28
|
-
ai-app-bridge executor-prepare --platform web --browser chromium
|
|
27
|
+
ai-app-bridge executor-prepare --extract null --platform ios
|
|
28
|
+
ai-app-bridge executor-prepare --extract null --platform web --browser chromium
|
|
29
29
|
```
|
|
30
30
|
|
|
31
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.
|
|
@@ -52,9 +52,9 @@ android {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
dependencies {
|
|
55
|
-
androidTestImplementation("com.github.mobileAiDev.ai-app-bridge:ai-app-bridge-test-instrumentation:0.
|
|
55
|
+
androidTestImplementation("com.github.mobileAiDev.ai-app-bridge:ai-app-bridge-test-instrumentation:0.4.1")
|
|
56
56
|
// Optional H5 adapter:
|
|
57
|
-
androidTestImplementation("com.github.mobileAiDev.ai-app-bridge:ai-app-bridge-test-espresso-web:0.
|
|
57
|
+
androidTestImplementation("com.github.mobileAiDev.ai-app-bridge:ai-app-bridge-test-espresso-web:0.4.1")
|
|
58
58
|
}
|
|
59
59
|
```
|
|
60
60
|
|
|
@@ -74,8 +74,8 @@ Opening a session **restarts and instruments the target application**. Install t
|
|
|
74
74
|
./gradlew :app:assembleDebug :app:assembleDebugAndroidTest
|
|
75
75
|
adb -s DEVICE install -r -t app/build/outputs/apk/debug/app-debug.apk
|
|
76
76
|
adb -s DEVICE install -r -t app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk
|
|
77
|
-
ai-app-bridge android-executor --operation status --serial DEVICE
|
|
78
|
-
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 \
|
|
79
79
|
--package-name example.app \
|
|
80
80
|
--instrumentation example.app.test/androidx.test.runner.AndroidJUnitRunner \
|
|
81
81
|
--test-class example.app.BridgeSessionTest --activity example.app.MainActivity
|
|
@@ -109,7 +109,7 @@ Espresso text actions have different semantics. `replaceText` is the framework's
|
|
|
109
109
|
|
|
110
110
|
## Flutter
|
|
111
111
|
|
|
112
|
-
Add `ai_app_bridge_test: 0.
|
|
112
|
+
Add `ai_app_bridge_test: 0.4.1` 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.
|
|
113
113
|
|
|
114
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.
|
|
115
115
|
|
|
@@ -124,7 +124,7 @@ void main() => aiAppBridgeTest(app.main);
|
|
|
124
124
|
flutter build apk --debug --target integration_test/bridge_test.dart \
|
|
125
125
|
--dart-define=INTEGRATION_TEST_SHOULD_REPORT_RESULTS_TO_NATIVE=false
|
|
126
126
|
adb -s DEVICE install -r -t build/app/outputs/flutter-apk/app-debug.apk
|
|
127
|
-
ai-app-bridge flutter-executor --operation open --serial DEVICE \
|
|
127
|
+
ai-app-bridge flutter-executor --extract null --operation open --serial DEVICE \
|
|
128
128
|
--package-name example.app --activity example.app.MainActivity
|
|
129
129
|
```
|
|
130
130
|
|
|
@@ -133,9 +133,9 @@ This version supports the standard **Android Flutter embedder**, with its normal
|
|
|
133
133
|
## Web
|
|
134
134
|
|
|
135
135
|
```sh
|
|
136
|
-
ai-app-bridge web-executor --operation status --browser chromium
|
|
137
|
-
ai-app-bridge web-executor --operation prepare --browser chromium --timeout-ms 300000
|
|
138
|
-
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
|
|
139
139
|
```
|
|
140
140
|
|
|
141
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,122 +1,71 @@
|
|
|
1
|
-
# 0.
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
##
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
1. 完成源码审阅并冻结一个提交,核对以下命令的产物确实来自它;包含当前 untracked 的实际源码、测试和文档,排除本机生成目录。所有对外发行版本使用同一个 `0.3.8`,若需要改版本,先同时更新上表涉及的 manifest 与固定依赖。
|
|
74
|
-
2. 维护者推送提交与 `0.3.8` 标签,让 JitPack 构建 Android SDK/插件。确认两条公开坐标可解析后,再发布依赖它们的 Flutter 包。本地 Gradle project/path/AAR 替换不能证明 JitPack 坐标可消费。
|
|
75
|
-
3. 原生 iOS 消费相同 Git tag 的根 package;完成根 package 的 iOS 构建,不仅构建 `ios/ai-app-bridge-ios/Package.swift`。Flutter iOS 则检查实际 pub 包内 Swift/C 源码与声明相符。
|
|
76
|
-
4. CLI 与 Web SDK 可分别发布到 npm 的 `latest` dist-tag。CLI 的 native store 已打包随行,不等待一个不存在的单独 registry 依赖。Flutter 包发布以第 2 步完成为前提。
|
|
77
|
-
5. 同步 npm `next` 指向 `0.3.8`,让已有候选入口也使用本次正式版。将 GitHub `main` 与发行提交同步,并创建非预发布的 GitHub Release。
|
|
78
|
-
6. 从 registry/tag 安装刚发布的确切版本,读取 `capabilities` 和版本,核对来源及支持范围,确认默认安装入口指向本次发行版本。正式发布不自动等于全平台生产验收完成。
|
|
79
|
-
|
|
80
|
-
正式发布命令需在对应目录由维护者执行,例如 npm 使用 `npm publish --tag latest`;pub 使用 `flutter pub publish`。这些命令属于发布动作,不能混入本地验证脚本。
|
|
81
|
-
|
|
82
|
-
## 本地检查与最终包验证
|
|
83
|
-
|
|
84
|
-
以下检查不发布版本。路径相对仓库根;输出使用新的、Git 忽略的目录。
|
|
85
|
-
|
|
86
|
-
```sh
|
|
87
|
-
swift package --package-path . dump-package
|
|
88
|
-
swift package --package-path ios/ai-app-bridge-ios dump-package
|
|
89
|
-
|
|
90
|
-
cd desktop/ai-app-bridge-cli
|
|
91
|
-
npm pack --dry-run --json --ignore-scripts
|
|
92
|
-
|
|
93
|
-
cd ../../web/ai-app-bridge-web
|
|
94
|
-
npm pack --dry-run --json --ignore-scripts
|
|
95
|
-
|
|
96
|
-
cd ../../flutter/ai_app_bridge_flutter
|
|
97
|
-
flutter pub publish --dry-run
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
`dump-package` 只证明 manifest 可解析及目标声明,不能替代 iOS 编译;`npm pack --dry-run` 只证明拟打包文件清单,不能替代安装;pub dry-run 中的分析/网络检查结果应原样记录。干净安装与 Host 协议验证必须在核心源码冻结、没有运行中修改时执行:
|
|
101
|
-
|
|
102
|
-
```sh
|
|
103
|
-
cd desktop/ai-app-bridge-cli
|
|
104
|
-
npm ci
|
|
105
|
-
npm run verify:package -- ../../build/ai_app_bridge_artifacts/release-package-NEW
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
`verify:package` 在仓库外安装实际 tarball,检查 native 安装编译、CLI/MCP 共享运行时、控制接口与随包运行时身份。它使用受控 ADB,不声称完成新真机业务验收。报告、tgz 哈希、安装日志和源码提交身份一起交接;已运行的旧包验证不能代替后来修改过的包。
|
|
109
|
-
|
|
110
|
-
CLI 的 `files` 已排除旧 `fact-cache.js` 发布载荷及 fake/P9/旧设备 adapter;旧 fact-cache 实现仅保留为 `test-support` 测试夹具,无生产引用。各 npm 包和 Flutter 目录的 `LICENSE`/`NOTICE` 均来自仓库根原文,发行时核对内容一致,不生成替代版权说明。
|
|
111
|
-
|
|
112
|
-
## 升级进程与后续修复
|
|
113
|
-
|
|
114
|
-
npm 升级不会替换已连接的 MCP 进程。用 `ai-app-bridge --version` 核对本机入口;
|
|
115
|
-
已有工作结束后显式停止旧 Runtime,并在 Cursor 等客户端重连 MCP,核对 initialize
|
|
116
|
-
中的 `serverInfo.version`。工具描述仍有旧 `batch`/`smoke` 时刷新客户端缓存。
|
|
117
|
-
|
|
118
|
-
实际发布状态与验证边界见仓库 `docs/RELEASE_HANDOFF_0.3.8_2026-09-15.md`。
|
|
119
|
-
Android Gradle 插件的 `webSocketCaptureEnabled`、`logInstrumentationEnabled`、
|
|
120
|
-
`webViewDebuggingEnabled` 没有对应插桩实现,现明确弃用并在显式设置时输出提示;
|
|
121
|
-
旧配置仍可构建。当前有效开关是 `enabled`、`okHttpCaptureEnabled`,以及可选
|
|
122
|
-
`runtimeDependencyNotation`。不要把弃用选项的配置值当作采集功能已经启用。
|
|
1
|
+
# 0.4.1 统一补丁发行检查
|
|
2
|
+
|
|
3
|
+
源码版本、可发布验收、registry 发布和正在运行的客户端是四个不同状态。
|
|
4
|
+
本文件描述发行操作;源码中的版本号不代表 npm/JitPack/pub.dev 已发布。
|
|
5
|
+
0.4.0 改善版的实施与放行证据记录于仓库
|
|
6
|
+
`docs/IMPROVEMENT_RELEASE_V1_2026-09-18.md` 及各 M1–M5 交付记录。
|
|
7
|
+
0.4.1 统一发布全部 Bridge 组件,Host 修复与回归证据见
|
|
8
|
+
`docs/HOST_0.4.0_GROK_REVIEW_2026-09-19.md`;设备及 Web SDK 仅同步版本与依赖。
|
|
9
|
+
|
|
10
|
+
本次修复 iOS 观察控制误占设备动作 ownership,并为旧误记 marker 提供
|
|
11
|
+
显式 reconcile;提取临时目录清理失败改为 cleanupError,保留原提取结果。
|
|
12
|
+
超预算 reference 交付和 extract 必填合同不变;设备端执行合同不变。
|
|
13
|
+
|
|
14
|
+
## 兼容与迁移
|
|
15
|
+
|
|
16
|
+
0.4.0 的外部 run 必填 `extract`,不提取显式 null;CLI `--extract null`。
|
|
17
|
+
返回公共封套含 execution/control/extraction/delivery,删除额外 `_history`、
|
|
18
|
+
`_meta` 副本。旧请求不自动补字段。业务 value 在 null 且预算内保持原值,
|
|
19
|
+
Script 的内部 ctx.call 仍返回 ok/result。Runtime 协议仍是 aab.runtime/v1。
|
|
20
|
+
|
|
21
|
+
调用方先核对 execution 和控制字段;提取失败后用原 source ref 调 response
|
|
22
|
+
read,不重放动作。详见 [公共提取合同与完整示例](RESPONSE_EXTRACTION.md)。
|
|
23
|
+
发现正文超预算时按 command/operation 收窄,不静默裁剪 schema。
|
|
24
|
+
|
|
25
|
+
## 发行资源
|
|
26
|
+
|
|
27
|
+
| 资源 | 源码版本 | 发行渠道 |
|
|
28
|
+
| --- | --- | --- |
|
|
29
|
+
| Desktop CLI/MCP | 0.4.1 | npm @mobileaidev/ai-app-bridge |
|
|
30
|
+
| 嵌入式 native store | 0.2.0 | 随主包 bundleDependencies,包括四个预编译 addon |
|
|
31
|
+
| Android SDK / Gradle plugin / executor modules | 0.4.1 | 同仓库 Git tag / JitPack |
|
|
32
|
+
| iOS Swift 包 | Git tag 0.4.1 | 根 Package.swift |
|
|
33
|
+
| Flutter SDK / test helper | 0.4.1 | pub.dev;Android 固定依赖同版 SDK |
|
|
34
|
+
| Web SDK | 0.4.1 | npm @mobileaidev/ai-app-bridge-web |
|
|
35
|
+
|
|
36
|
+
UIA bundle、WDA 14.1.1、iOS WDA 模板、Playwright helper 与三类范例随主包。
|
|
37
|
+
未改变代码的设备组件不需要仅为 Host 返回合同重新安装;需要测试新发行
|
|
38
|
+
设备产物时记录实际版本/包/序列号,不能用旧安装冒充新包验收。
|
|
39
|
+
|
|
40
|
+
## 发布前门禁
|
|
41
|
+
|
|
42
|
+
本次必须通过新增缺陷回归、Host 完整功能/性能组、真实 iPhone 恢复验证及
|
|
43
|
+
最终 tarball 安装检查。SDK 同步版本后重新验证构建与公开依赖;未变更的
|
|
44
|
+
原生 addon 复用 0.4.0 四平台验收,并核实归档字节相同。
|
|
45
|
+
|
|
46
|
+
1. 固定审核提交,核对工作包和 A01–A16,保留失败与未验证项。完整 npm
|
|
47
|
+
功能组与安静环境串行性能组通过,范例由文档读取实际执行。
|
|
48
|
+
2. 对 [Host 支持矩阵](INSTALLATION.md) 的四个 artifact 校验 checksum 和
|
|
49
|
+
实际加载,运行 native tests 与全新 tarball 安装。正常安装和纯 MCP
|
|
50
|
+
JS/regex 路径禁止调用本地编译器/Python;Python 回归使用单独环境。
|
|
51
|
+
3. 核对 npm pack 清单真实包含 addon、加载器、source read/worker 和文档,
|
|
52
|
+
codeFingerprint 哈希实际选中的二进制。固定版本 npx 首次/重复启动、
|
|
53
|
+
MCP 断连后 Runtime 存续、明确 stop/restart 与持久化恢复均有证据。
|
|
54
|
+
4. 核实实际 CLI 路径、MCP 启动版本/指纹、Runtime code/config/Node 身份,
|
|
55
|
+
并检查受影响消费脚本的 extract/公共响应迁移。安装成功不替代入口更新。
|
|
56
|
+
5. Android/Swift/Flutter/Web 的发行清单和版本一致。需要时运行相应构建,
|
|
57
|
+
真实设备证据和离线/受控 ADB 测试分开记录。三类实际任务对照保留来源、
|
|
58
|
+
时间、目标和原始记录,不能将缺设备写成不适用。
|
|
59
|
+
|
|
60
|
+
## 对外发布顺序
|
|
61
|
+
|
|
62
|
+
本次推送已验收提交与统一 `0.4.1` tag,核实 JitPack 公开坐标成功解析,
|
|
63
|
+
再发布依赖它们的 Flutter SDK/helper。Web npm 与主 CLI/MCP npm 分别发布
|
|
64
|
+
已经验证的 tarball,核实 `latest`/`next` 均为 0.4.1、公开下载 checksum
|
|
65
|
+
与候选包一致,并创建对应 GitHub Release。保留旧 `0.4.0` tag 不动。远端流水线
|
|
66
|
+
成功与设备业务验收分别列明。本地构建或 MavenLocal/path 替换不能证明公开
|
|
67
|
+
坐标可安装。
|
|
68
|
+
|
|
69
|
+
客户端升级时退出旧 MCP 再重新连接。若是旧客户端碰到新 Runtime,先升
|
|
70
|
+
客户端;只有明确 Runtime 是待升级一侧时,在其任务结束后显式 stop。
|
|
71
|
+
同版本不同指纹只能说明构建或 Node 环境不一致,不能凭 hash 判断新旧。
|