@avasapp/agent-bridge 0.4.2 → 0.6.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.
- package/README.md +36 -14
- package/dist/adapters/ably.cjs +79 -3
- package/dist/adapters/ably.d.cts +2 -1
- package/dist/adapters/async-storage.cjs +158 -0
- package/dist/adapters/async-storage.d.cts +14 -0
- package/dist/adapters/device.cjs +1110 -0
- package/dist/adapters/device.d.cts +49 -0
- package/dist/adapters/expo-router.cjs +112 -6
- package/dist/adapters/expo-router.d.cts +1 -1
- package/dist/adapters/jotai.cjs +266 -0
- package/dist/adapters/jotai.d.cts +19 -0
- package/dist/adapters/react-native-mmkv.cjs +80 -0
- package/dist/adapters/react-native-mmkv.d.cts +3 -1
- package/dist/adapters/react-native-webview.d.cts +1 -1
- package/dist/adapters/react-navigation.cjs +293 -0
- package/dist/adapters/react-navigation.d.cts +55 -0
- package/dist/adapters/redux.cjs +322 -0
- package/dist/adapters/redux.d.cts +28 -0
- package/dist/adapters/secure-store.cjs +169 -0
- package/dist/adapters/secure-store.d.cts +28 -0
- package/dist/adapters/socket-io.cjs +77 -3
- package/dist/adapters/socket-io.d.cts +2 -1
- package/dist/adapters/tanstack-query.cjs +3 -0
- package/dist/adapters/tanstack-query.d.cts +13 -4
- package/dist/adapters/zustand.cjs +193 -22
- package/dist/adapters/zustand.d.cts +11 -15
- package/dist/{chunk-TA2OLPPT.js → chunk-Y6QFU5ON.js} +477 -165
- package/dist/cli.js +2370 -103
- package/dist/client/index.cjs +441 -136
- package/dist/client/index.d.ts +67 -4
- package/dist/client/index.js +5 -3
- package/dist/expo/index.d.cts +1 -1
- package/dist/network/index.cjs +320 -73
- package/dist/network/index.d.cts +18 -3
- package/dist/noop/async-storage.cjs +26 -0
- package/dist/noop/device.cjs +26 -0
- package/dist/noop/jotai.cjs +26 -0
- package/dist/noop/react-navigation.cjs +26 -0
- package/dist/noop/realtime.cjs +6 -1
- package/dist/noop/redux.cjs +28 -0
- package/dist/noop/secure-store.cjs +26 -0
- package/dist/realtime/index.cjs +71 -4
- package/dist/realtime/index.d.cts +21 -2
- package/dist/runtime/index.cjs +838 -128
- package/dist/runtime/index.d.cts +4 -2
- package/dist/store-common-j0cHHvBr.d.cts +23 -0
- package/dist/{types-BmpykP1P.d.cts → types-qlwdcGjt.d.cts} +22 -0
- package/entries/async-storage.cjs +9 -0
- package/entries/device.cjs +9 -0
- package/entries/jotai.cjs +9 -0
- package/entries/react-navigation.cjs +9 -0
- package/entries/redux.cjs +9 -0
- package/entries/secure-store.cjs +9 -0
- package/package.json +34 -2
- package/skills/agent-bridge/SKILL.md +70 -22
- package/skills/agent-bridge/references/device.md +21 -0
- package/skills/agent-bridge/references/flows.md +19 -8
- package/skills/agent-bridge/references/large-data.md +6 -6
- package/skills/agent-bridge/references/network.md +25 -7
- package/skills/agent-bridge/references/realtime.md +5 -5
- package/skills/agent-bridge/references/restore.md +25 -7
- package/skills/agent-bridge/references/screen.md +25 -11
- package/skills/agent-bridge/references/state.md +31 -11
- package/skills/agent-bridge/references/webview.md +9 -9
- package/skills/agent-bridge/references/writing-scenarios.md +3 -3
|
@@ -1,22 +1,36 @@
|
|
|
1
1
|
# See and use the screen
|
|
2
2
|
|
|
3
3
|
```sh
|
|
4
|
-
npx agent-bridge call screen.snapshot #
|
|
5
|
-
npx agent-bridge call screen.
|
|
6
|
-
npx agent-bridge call screen.
|
|
7
|
-
npx agent-bridge call screen.
|
|
8
|
-
npx agent-bridge call screen.press '
|
|
9
|
-
npx agent-bridge call screen.
|
|
10
|
-
npx agent-bridge call screen.
|
|
11
|
-
npx agent-bridge call screen.
|
|
12
|
-
npx agent-bridge call screen.
|
|
13
|
-
npx agent-bridge call screen.
|
|
4
|
+
npx @avasapp/agent-bridge call screen.snapshot # one line per element: `button #save "Save" disabled` (`hidden` counts what was skipped; {"all":true} lists everything)
|
|
5
|
+
npx @avasapp/agent-bridge call screen.snapshot '{"kinds":["input","button"],"within":"checkout-form"}' # only those kinds, only inside that target
|
|
6
|
+
npx @avasapp/agent-bridge call screen.snapshot --json # JSON with rects and `role` (the text form already shows actions=, readonly, offscreen); `@x,y` on a line is `{"at":[x,y]}`, `index=N` is `{"index":N}`
|
|
7
|
+
npx @avasapp/agent-bridge call screen.findText "Payment" # text or accessibility label; {"labels":false} for text only
|
|
8
|
+
npx @avasapp/agent-bridge call screen.press '"add-plant"' # by testID, label or text
|
|
9
|
+
npx @avasapp/agent-bridge call screen.press '[{"at":[350,60]}]' # icon-only button: by point; {"index":1} picks among matches; {"force":true} presses disabled
|
|
10
|
+
npx @avasapp/agent-bridge call screen.press '["save-plant", {"scroll":true}]' # scrolls an off-screen target into view first
|
|
11
|
+
npx @avasapp/agent-bridge call screen.press '"Swipe to confirm"' # no onPress: sends the "activate" accessibility action
|
|
12
|
+
npx @avasapp/agent-bridge call screen.press '["Volume", {"action":"increment"}]' # any action in the element's snapshot `actions`
|
|
13
|
+
npx @avasapp/agent-bridge call screen.press '["Item 80", {"scroll":true}]' # a row a FlatList has not rendered yet: pages the main list until it shows up (waitFor does not page)
|
|
14
|
+
npx @avasapp/agent-bridge call screen.press '["Message", {"long":true}]' # onPressIn, onLongPress, onPressOut; errors when there is no onLongPress
|
|
15
|
+
npx @avasapp/agent-bridge call screen.press '"dark-mode"' # a Switch is toggled with onValueChange(!value)
|
|
16
|
+
npx @avasapp/agent-bridge call screen.setValue '["volume", 7]' # Switch true/false, Slider number, Picker or SegmentedControl item; reads the value back
|
|
17
|
+
npx @avasapp/agent-bridge call screen.scroll '"Notes"' # bring a target to the middle of its ScrollView/FlatList; {"toEnd":true}, {"by":400}, [{"toEnd":true},{"within":"list"}]
|
|
18
|
+
npx @avasapp/agent-bridge call screen.refresh # pull to refresh (the RefreshControl's onRefresh); then screen.waitFor the data
|
|
19
|
+
npx @avasapp/agent-bridge call screen.fill '["plant-name", "Fern"]' # runs the input's handlers
|
|
20
|
+
npx @avasapp/agent-bridge call screen.waitFor '"Name is required"' # {"gone": true} waits for it to go
|
|
21
|
+
npx @avasapp/agent-bridge call screen.waitFor '["Section title", {"scroll":true}]' # also below the fold: scrolls it into view (not with gone)
|
|
14
22
|
```
|
|
15
23
|
|
|
16
24
|
`press` and `fill` return once the app has rendered the result, so the next
|
|
17
|
-
check sees it. `fill` skips the keyboard: autocorrect and native-only input
|
|
25
|
+
check sees it. `fill` also takes `{"submit":true}` and `{"type":true}` (per-character, for debounced search); `""` clears. A press that hit an ancestor's handler says `via: "ancestor"`: check it did what you meant. `fill` skips the keyboard: autocorrect and native-only input
|
|
18
26
|
behaviour need one real typing step from agent-device.
|
|
19
27
|
|
|
28
|
+
A swipe-to-confirm or slider with no `onPress` shows as a button (or a view)
|
|
29
|
+
with `actions` in the snapshot. `press` calls its `onAccessibilityAction` with
|
|
30
|
+
`activate`, as a screen reader's double tap does, and the reply says
|
|
31
|
+
`via: "accessibilityAction:activate"`. A gesture control with no `actions`
|
|
32
|
+
needs a real swipe from agent-device.
|
|
33
|
+
|
|
20
34
|
A WebView shows in the snapshot as one element (`webview "checkout"`);
|
|
21
35
|
`screen.*` can't reach inside it. See [webview.md](webview.md).
|
|
22
36
|
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
## Set state
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
|
-
npx agent-bridge call query.pin '[["features"], <data>]' # stays through refetches
|
|
7
|
-
npx agent-bridge call store.call '["settings", "setTheme", "dark"]'
|
|
8
|
-
npx agent-bridge call router.navigate /inbox
|
|
9
|
-
npx agent-bridge call router.current
|
|
10
|
-
npx agent-bridge call router.dismiss # closes a route-based modal
|
|
6
|
+
npx @avasapp/agent-bridge call query.pin '[["features"], <data>]' # stays through refetches
|
|
7
|
+
npx @avasapp/agent-bridge call store.call '["settings", "setTheme", "dark"]'
|
|
8
|
+
npx @avasapp/agent-bridge call router.navigate /inbox
|
|
9
|
+
npx @avasapp/agent-bridge call router.current # React Navigation apps: nav.navigate Inbox, nav.current
|
|
10
|
+
npx @avasapp/agent-bridge call router.dismiss # closes a route-based modal
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
`router.back` only pops the navigator: an in-app modal or sheet the app renders
|
|
@@ -19,18 +19,38 @@ own tool (e.g. `modal.close`) if it has one; check `tools` first.
|
|
|
19
19
|
Read the current value first and change only what you need:
|
|
20
20
|
|
|
21
21
|
```sh
|
|
22
|
-
npx agent-bridge call query.get '["todos", 1]' # a flat key or '[["todos", 1]]'
|
|
23
|
-
npx agent-bridge call query.list '["todos"]' # key prefix; shows isStale, isInvalidated, fetchStatus
|
|
24
|
-
npx agent-bridge call query.refetch '["todos"]' # {matched, refetched, data}; errors when nothing matches
|
|
25
|
-
npx agent-bridge call store.get '["app", "auth.isLoggedIn"]' # or ["app","auth","isLoggedIn"]
|
|
26
|
-
npx agent-bridge call store.get '["app", {"pick": ["auth.isLoggedIn", "settings.fontScale"]}]'
|
|
27
|
-
npx agent-bridge call store.get '["app", {"keys": true}]' # top-level keys and types, no values
|
|
22
|
+
npx @avasapp/agent-bridge call query.get '["todos", 1]' # a flat key or '[["todos", 1]]'
|
|
23
|
+
npx @avasapp/agent-bridge call query.list '["todos"]' # key prefix; shows isStale, isInvalidated, fetchStatus
|
|
24
|
+
npx @avasapp/agent-bridge call query.refetch '["todos"]' # {matched, refetched, data}; errors when nothing matches
|
|
25
|
+
npx @avasapp/agent-bridge call store.get '["app", "auth.isLoggedIn"]' # or ["app","auth","isLoggedIn"]
|
|
26
|
+
npx @avasapp/agent-bridge call store.get '["app", {"pick": ["auth.isLoggedIn", "settings.fontScale"]}]'
|
|
27
|
+
npx @avasapp/agent-bridge call store.get '["app", {"keys": true}]' # top-level keys and types, no values
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
`query.get` errors on a key that is not cached (with similar keys), so a
|
|
31
31
|
`null` reply means the data is undefined. For a large query, narrow it with
|
|
32
32
|
`pages` or `path`; see [large-data.md](large-data.md).
|
|
33
33
|
|
|
34
|
+
## Redux and Jotai
|
|
35
|
+
|
|
36
|
+
Same ideas under their own prefixes, so a Zustand `store.*` and these can coexist.
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
npx @avasapp/agent-bridge call redux.list
|
|
40
|
+
npx @avasapp/agent-bridge call redux.get '["auth", "user.name"]' # or [] for the whole state
|
|
41
|
+
npx @avasapp/agent-bridge call redux.dispatch '[{"type":"cart/add","payload":"apple"}]'
|
|
42
|
+
npx @avasapp/agent-bridge call redux.set '["auth", {"token": "abc"}]' # merge into a slice
|
|
43
|
+
npx @avasapp/agent-bridge call jotai.list # read-write or read-only
|
|
44
|
+
npx @avasapp/agent-bridge call jotai.get '["user", "name"]'
|
|
45
|
+
npx @avasapp/agent-bridge call jotai.set '["count", 5]' # writable atoms only
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`redux.set` and restore need the app to wrap its root reducer in
|
|
49
|
+
`bridgeReducer()` (inside `persistReducer` with redux-persist); without it they
|
|
50
|
+
fail and say so. `redux.set` merges into object slices only. `redux.dispatch`
|
|
51
|
+
sends plain actions only. `jotai.set` refuses atoms whose value isn't the one
|
|
52
|
+
sent (action atoms, `atomWithReducer`). Redacted slices, atoms and paths print as `"[redacted]"`.
|
|
53
|
+
|
|
34
54
|
## Argument shapes
|
|
35
55
|
|
|
36
56
|
Arguments are a JSON array (or a single JSON value): the array is spread into
|
|
@@ -5,15 +5,15 @@
|
|
|
5
5
|
`tools`), use the same verbs on the page:
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
|
-
npx agent-bridge call webview.list # name, url, loaded, allowed
|
|
9
|
-
npx agent-bridge call webview.snapshot '"checkout"' # buttons, links, inputs, text in the page
|
|
10
|
-
npx agent-bridge call webview.press '["Pay now", {"webview": "checkout"}]'
|
|
11
|
-
npx agent-bridge call webview.fill '["Email", "ada@example.com"]' # {"submit":true} presses Enter
|
|
12
|
-
npx agent-bridge call webview.waitFor '["Payment complete", {"timeoutMs": 8000}]' # {"gone":true}
|
|
13
|
-
npx agent-bridge call webview.messages '"checkout"' # page <-> app, last 100, bodies cut at 2 KB
|
|
14
|
-
npx agent-bridge call webview.message 17 # one in full
|
|
15
|
-
npx agent-bridge call webview.send '["checkout", {"type": "auth", "ok": true}]' # as if the app sent it
|
|
16
|
-
npx agent-bridge call webview.receive '["checkout", {"type": "done"}]' # runs the app's onMessage
|
|
8
|
+
npx @avasapp/agent-bridge call webview.list # name, url, loaded, allowed
|
|
9
|
+
npx @avasapp/agent-bridge call webview.snapshot '"checkout"' # buttons, links, inputs, text in the page
|
|
10
|
+
npx @avasapp/agent-bridge call webview.press '["Pay now", {"webview": "checkout"}]'
|
|
11
|
+
npx @avasapp/agent-bridge call webview.fill '["Email", "ada@example.com"]' # {"submit":true} presses Enter
|
|
12
|
+
npx @avasapp/agent-bridge call webview.waitFor '["Payment complete", {"timeoutMs": 8000}]' # {"gone":true}
|
|
13
|
+
npx @avasapp/agent-bridge call webview.messages '"checkout"' # page <-> app, last 100, bodies cut at 2 KB
|
|
14
|
+
npx @avasapp/agent-bridge call webview.message 17 # one in full
|
|
15
|
+
npx @avasapp/agent-bridge call webview.send '["checkout", {"type": "auth", "ok": true}]' # as if the app sent it
|
|
16
|
+
npx @avasapp/agent-bridge call webview.receive '["checkout", {"type": "done"}]' # runs the app's onMessage
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
Targets match in `screen.*` order: `data-testid` (also `data-test-id`,
|
|
@@ -56,8 +56,8 @@ useAgentBridge({ tools, scenarios })
|
|
|
56
56
|
is back in its real state. If `apply` throws, the callbacks it had registered
|
|
57
57
|
run straight away.
|
|
58
58
|
- Tools: `scenario.list`, `scenario.apply [name, options?]` (applying an active
|
|
59
|
-
one again undoes it first) and `scenario.restore`.
|
|
60
|
-
lists them.
|
|
59
|
+
one again undoes it first) and `scenario.restore`.
|
|
60
|
+
`npx @avasapp/agent-bridge scenarios` lists them.
|
|
61
61
|
- Flows declare scenarios with `export const scenario` or
|
|
62
62
|
`export const scenarios`; see [flows.md](flows.md).
|
|
63
63
|
|
|
@@ -93,5 +93,5 @@ In a release build it's always open. `realtime.connection` isn't enough on its
|
|
|
93
93
|
own: it hides the state from the app, but the client still connects.
|
|
94
94
|
|
|
95
95
|
The agent-bridge repo's example app has a complete local `signedIn` in
|
|
96
|
-
`example/src/dev/scenarios.ts`, and `example/flows/checks/signed-in.mjs`
|
|
96
|
+
`example/src/dev/scenarios.ts`, and `example/flows/checks/signed-in.flow.mjs`
|
|
97
97
|
declares it.
|