agent-device 0.7.22 → 0.8.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 +52 -1
- package/dist/src/224.js +2 -2
- package/dist/src/bin.js +56 -56
- package/dist/src/client-types.d.ts +4 -2
- package/dist/src/daemon/install-source-resolution.d.ts +5 -0
- package/dist/src/daemon/request-lock-policy.d.ts +2 -0
- package/dist/src/daemon/session-selector.d.ts +7 -0
- package/dist/src/daemon/types.d.ts +3 -0
- package/dist/src/daemon-client.d.ts +2 -0
- package/dist/src/daemon.js +35 -35
- package/dist/src/platforms/install-source.d.ts +3 -0
- package/dist/src/utils/args.d.ts +15 -3
- package/dist/src/utils/cli-config.d.ts +9 -0
- package/dist/src/utils/cli-option-schema.d.ts +19 -0
- package/dist/src/utils/cli-options.d.ts +13 -0
- package/dist/src/utils/command-schema.d.ts +5 -0
- package/dist/src/utils/session-binding.d.ts +18 -0
- package/package.json +1 -1
- package/skills/agent-device/SKILL.md +36 -0
- package/skills/agent-device/references/remote-tenancy.md +11 -0
- package/skills/agent-device/references/session-management.md +36 -0
|
@@ -13,6 +13,7 @@ type MaterializeInstallableOptions = {
|
|
|
13
13
|
isDirectory(): boolean;
|
|
14
14
|
}) => boolean;
|
|
15
15
|
installableLabel: string;
|
|
16
|
+
allowArchiveExtraction?: boolean;
|
|
16
17
|
signal?: AbortSignal;
|
|
17
18
|
downloadTimeoutMs?: number;
|
|
18
19
|
};
|
|
@@ -23,4 +24,6 @@ export type MaterializedInstallable = {
|
|
|
23
24
|
};
|
|
24
25
|
export declare function materializeInstallablePath(options: MaterializeInstallableOptions): Promise<MaterializedInstallable>;
|
|
25
26
|
export declare function expandSourcePath(inputPath: string): string;
|
|
27
|
+
export declare function validateDownloadSourceUrl(parsedUrl: URL): Promise<void>;
|
|
28
|
+
export declare function isTrustedInstallSourceUrl(sourceUrl: string | URL): boolean;
|
|
26
29
|
export {};
|
package/dist/src/utils/args.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CliFlags } from './command-schema.ts';
|
|
1
|
+
import { type CliFlags, type FlagKey } from './command-schema.ts';
|
|
2
2
|
type ParsedArgs = {
|
|
3
3
|
command: string | null;
|
|
4
4
|
positionals: string[];
|
|
@@ -8,8 +8,20 @@ type ParsedArgs = {
|
|
|
8
8
|
type ParseArgsOptions = {
|
|
9
9
|
strictFlags?: boolean;
|
|
10
10
|
};
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
type ParsedFlagRecord = {
|
|
12
|
+
key: FlagKey;
|
|
13
|
+
token: string;
|
|
14
|
+
};
|
|
15
|
+
type RawParsedArgs = ParsedArgs & {
|
|
16
|
+
providedFlags: ParsedFlagRecord[];
|
|
17
|
+
};
|
|
18
|
+
type FinalizeArgsOptions = ParseArgsOptions & {
|
|
19
|
+
defaultFlags?: Partial<CliFlags>;
|
|
20
|
+
};
|
|
21
|
+
export declare function parseArgs(argv: string[], options?: FinalizeArgsOptions): ParsedArgs;
|
|
22
|
+
export declare function parseRawArgs(argv: string[]): RawParsedArgs;
|
|
23
|
+
export declare function finalizeParsedArgs(parsed: RawParsedArgs, options?: FinalizeArgsOptions): ParsedArgs;
|
|
24
|
+
export declare function toDaemonFlags(flags: CliFlags): Omit<CliFlags, 'json' | 'config' | 'help' | 'version'>;
|
|
13
25
|
export declare function usage(): string;
|
|
14
26
|
export declare function usageForCommand(command: string): string | null;
|
|
15
27
|
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type CliFlags } from './command-schema.ts';
|
|
2
|
+
type EnvMap = Record<string, string | undefined>;
|
|
3
|
+
export declare function resolveConfigBackedFlagDefaults(options: {
|
|
4
|
+
command: string | null;
|
|
5
|
+
cwd: string;
|
|
6
|
+
cliFlags: CliFlags;
|
|
7
|
+
env?: EnvMap;
|
|
8
|
+
}): Partial<CliFlags>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type FlagDefinition, type FlagKey } from './command-schema.ts';
|
|
2
|
+
export type OptionSpec = {
|
|
3
|
+
key: FlagKey;
|
|
4
|
+
flagDefinitions: readonly FlagDefinition[];
|
|
5
|
+
config: {
|
|
6
|
+
enabled: boolean;
|
|
7
|
+
key: string;
|
|
8
|
+
};
|
|
9
|
+
env: {
|
|
10
|
+
names: readonly string[];
|
|
11
|
+
};
|
|
12
|
+
supportsCommand(command: string | null): boolean;
|
|
13
|
+
};
|
|
14
|
+
export declare function getOptionSpecs(): readonly OptionSpec[];
|
|
15
|
+
export declare function getOptionSpec(key: FlagKey): OptionSpec | undefined;
|
|
16
|
+
export declare function getOptionSpecForToken(token: string): OptionSpec | undefined;
|
|
17
|
+
export declare function getConfigurableOptionSpecs(command: string | null): OptionSpec[];
|
|
18
|
+
export declare function isFlagSupportedForCommand(key: FlagKey, command: string | null): boolean;
|
|
19
|
+
export declare function parseOptionValueFromSource(spec: OptionSpec, value: unknown, sourceLabel: string, rawKey: string): unknown;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CliFlags } from './command-schema.ts';
|
|
2
|
+
type EnvMap = Record<string, string | undefined>;
|
|
3
|
+
export declare function resolveCliOptions(argv: string[], options?: {
|
|
4
|
+
cwd?: string;
|
|
5
|
+
env?: EnvMap;
|
|
6
|
+
strictFlags?: boolean;
|
|
7
|
+
}): {
|
|
8
|
+
command: string | null;
|
|
9
|
+
positionals: string[];
|
|
10
|
+
flags: CliFlags;
|
|
11
|
+
warnings: string[];
|
|
12
|
+
};
|
|
13
|
+
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export type CliFlags = {
|
|
2
2
|
json: boolean;
|
|
3
|
+
config?: string;
|
|
3
4
|
stateDir?: string;
|
|
4
5
|
daemonBaseUrl?: string;
|
|
5
6
|
daemonAuthToken?: string;
|
|
@@ -9,6 +10,9 @@ export type CliFlags = {
|
|
|
9
10
|
sessionIsolation?: 'none' | 'tenant';
|
|
10
11
|
runId?: string;
|
|
11
12
|
leaseId?: string;
|
|
13
|
+
sessionLock?: 'reject' | 'strip';
|
|
14
|
+
sessionLocked?: boolean;
|
|
15
|
+
sessionLockConflicts?: 'reject' | 'strip';
|
|
12
16
|
platform?: 'ios' | 'android' | 'apple';
|
|
13
17
|
target?: 'mobile' | 'tv';
|
|
14
18
|
device?: string;
|
|
@@ -84,6 +88,7 @@ type CommandSchema = {
|
|
|
84
88
|
};
|
|
85
89
|
export declare const GLOBAL_FLAG_KEYS: Set<keyof CliFlags>;
|
|
86
90
|
export declare function getFlagDefinition(token: string): FlagDefinition | undefined;
|
|
91
|
+
export declare function getFlagDefinitions(): readonly FlagDefinition[];
|
|
87
92
|
export declare function getCommandSchema(command: string | null): CommandSchema | undefined;
|
|
88
93
|
export declare function getCliCommandNames(): string[];
|
|
89
94
|
export declare function getSchemaCapabilityKeys(): string[];
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CliFlags } from './command-schema.ts';
|
|
2
|
+
import type { DaemonLockPolicy } from '../daemon/types.ts';
|
|
3
|
+
export type BindingSettings = {
|
|
4
|
+
defaultPlatform?: CliFlags['platform'];
|
|
5
|
+
lockPolicy?: DaemonLockPolicy;
|
|
6
|
+
};
|
|
7
|
+
type BindingPolicyOverrides = Pick<Partial<CliFlags>, 'sessionLock' | 'sessionLocked' | 'sessionLockConflicts'>;
|
|
8
|
+
type LockableFlags = Pick<Partial<CliFlags>, 'platform' | 'target' | 'device' | 'udid' | 'serial' | 'iosSimulatorDeviceSet' | 'androidDeviceAllowlist'>;
|
|
9
|
+
type BindingOptions = {
|
|
10
|
+
env?: NodeJS.ProcessEnv;
|
|
11
|
+
policyOverrides?: BindingPolicyOverrides;
|
|
12
|
+
configuredPlatform?: CliFlags['platform'];
|
|
13
|
+
configuredSession?: string;
|
|
14
|
+
inheritedPlatform?: CliFlags['platform'];
|
|
15
|
+
};
|
|
16
|
+
export declare function applyDefaultPlatformBinding<T extends LockableFlags>(flags: T, options?: BindingOptions): T;
|
|
17
|
+
export declare function resolveBindingSettings(options: BindingOptions): BindingSettings;
|
|
18
|
+
export {};
|
package/package.json
CHANGED
|
@@ -35,6 +35,8 @@ Use this skill as a router, not a full manual.
|
|
|
35
35
|
- Android local QA: use `install` or `reinstall` for `.apk`/`.aab` files, then relaunch by installed package name.
|
|
36
36
|
- Android React Native + Metro flows: set runtime hints with `runtime set` before `open <package> --relaunch`.
|
|
37
37
|
- In mixed-device environments, always pin the exact target with `--serial`, `--device`, `--udid`, or an isolation scope.
|
|
38
|
+
- For session-bound automation runs, prefer a pre-bound session/platform instead of repeating selectors on every command: set `AGENT_DEVICE_SESSION`, set `AGENT_DEVICE_PLATFORM`, and the daemon will enforce the shared lock policy across CLI, typed client, and RPC entry points.
|
|
39
|
+
- Use `--session-lock reject|strip` (or `AGENT_DEVICE_SESSION_LOCK`) only when you need to override the default reject behavior. Lock mode applies to nested `batch` steps too.
|
|
38
40
|
|
|
39
41
|
## Canonical Flows
|
|
40
42
|
|
|
@@ -73,6 +75,35 @@ agent-device close
|
|
|
73
75
|
|
|
74
76
|
Do not use `open <apk|aab> --relaunch` on Android. Install/reinstall binaries first, then relaunch by package.
|
|
75
77
|
|
|
78
|
+
### 1c) Session-Bound Automation Flow
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
export AGENT_DEVICE_SESSION=qa-ios
|
|
82
|
+
export AGENT_DEVICE_PLATFORM=ios
|
|
83
|
+
export AGENT_DEVICE_SESSION_LOCK=strip
|
|
84
|
+
|
|
85
|
+
agent-device open MyApp --relaunch
|
|
86
|
+
agent-device snapshot -i
|
|
87
|
+
agent-device batch --steps-file /tmp/qa-steps.json --json
|
|
88
|
+
agent-device close
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Use this for orchestrators that must preserve one bound session/device across many plain CLI calls without a wrapper script. In `strip` mode, conflicting selectors such as `--target`, `--device`, `--udid`, `--serial`, and isolation-scope overrides are ignored instead of retargeting the run.
|
|
92
|
+
|
|
93
|
+
### 1d) Android Emulator Session-Bound Flow
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
export AGENT_DEVICE_SESSION=qa-android
|
|
97
|
+
export AGENT_DEVICE_PLATFORM=android
|
|
98
|
+
|
|
99
|
+
agent-device reinstall MyApp /path/to/app-debug.apk --serial emulator-5554
|
|
100
|
+
agent-device --session-lock reject open com.example.myapp --relaunch
|
|
101
|
+
agent-device snapshot -i
|
|
102
|
+
agent-device close --shutdown
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Use this when an Android emulator session must stay pinned while an agent or test runner issues plain CLI commands over time.
|
|
106
|
+
|
|
76
107
|
### 2) Debug/Crash Flow
|
|
77
108
|
|
|
78
109
|
```bash
|
|
@@ -147,17 +178,22 @@ agent-device session list
|
|
|
147
178
|
```
|
|
148
179
|
|
|
149
180
|
Use `boot` only as fallback when `open` cannot find/connect to a ready target.
|
|
181
|
+
If the workspace repeats the same selectors or device/session flags, prefer a checked-in `agent-device.json` or `--config <path>` over repeating them inline.
|
|
182
|
+
Environment-level defaults follow the same fields via `AGENT_DEVICE_*` names, so persistent host-specific values belong there rather than in committed project config.
|
|
183
|
+
That includes bound-session defaults such as `sessionLock` / `AGENT_DEVICE_SESSION_LOCK` when automation should consistently reject or strip conflicting device routing flags.
|
|
150
184
|
For Android emulators by AVD name, use `boot --platform android --device <avd-name>`.
|
|
151
185
|
For Android emulators without GUI, add `--headless`.
|
|
152
186
|
Use `--target mobile|tv` with `--platform` (required) to pick phone/tablet vs TV targets (AndroidTV/tvOS).
|
|
153
187
|
For Android React Native + Metro flows, install or reinstall the APK first, set runtime hints with `runtime set`, then use `open <package> --relaunch`; do not use `open <apk|aab> --relaunch`.
|
|
154
188
|
For local iOS QA in mixed simulator/device environments, use `ensure-simulator` and pass `--device` or `--udid` so automation does not attach to a physical device by accident.
|
|
189
|
+
For session-bound automation, prefer `AGENT_DEVICE_SESSION` + `AGENT_DEVICE_PLATFORM`; that bound-session default now enables lock mode automatically.
|
|
155
190
|
|
|
156
191
|
Isolation scoping quick reference:
|
|
157
192
|
- `--ios-simulator-device-set <path>` scopes iOS simulator discovery + command execution to one simulator set.
|
|
158
193
|
- `--android-device-allowlist <serials>` scopes Android discovery/selection to comma/space separated serials.
|
|
159
194
|
- Scope is applied before selectors (`--device`, `--udid`, `--serial`); out-of-scope selectors fail with `DEVICE_NOT_FOUND`.
|
|
160
195
|
- With iOS simulator-set scope enabled, iOS physical devices are not enumerated.
|
|
196
|
+
- In bound-session `strip` mode, conflicting per-call scope/selectors are ignored and the configured binding is restored for the request. Batch steps still inherit the parent `--platform` when they do not set their own.
|
|
161
197
|
|
|
162
198
|
Simulator provisioning quick reference:
|
|
163
199
|
- Use `ensure-simulator` to create or reuse a named iOS simulator inside a device set before starting a session.
|
|
@@ -50,6 +50,17 @@ curl -sS "${AGENT_DEVICE_DAEMON_BASE_URL}/rpc" \
|
|
|
50
50
|
-d '{"jsonrpc":"2.0","id":"rel-1","method":"agent_device.lease.release","params":{"leaseId":"<lease-id>"}}'
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
+
Example session-locked command request:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
curl -sS "${AGENT_DEVICE_DAEMON_BASE_URL}/rpc" \
|
|
57
|
+
-H "content-type: application/json" \
|
|
58
|
+
-H "Authorization: Bearer <token>" \
|
|
59
|
+
-d '{"jsonrpc":"2.0","id":"cmd-1","method":"agent_device.command","params":{"session":"qa-ios","command":"snapshot","positionals":[],"meta":{"lockPolicy":"reject","lockPlatform":"ios","tenantId":"acme","runId":"run-123","leaseId":"<lease-id>"}}}'
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Direct RPC callers can send the same session lock concept as the CLI and typed client through `meta.lockPolicy` and optional `meta.lockPlatform`.
|
|
63
|
+
|
|
53
64
|
## Command admission contract
|
|
54
65
|
|
|
55
66
|
For tenant-isolated command execution, pass all four flags:
|
|
@@ -14,6 +14,7 @@ Sessions isolate device context. A device can only be held by one session at a t
|
|
|
14
14
|
- Name sessions semantically.
|
|
15
15
|
- Close sessions when done.
|
|
16
16
|
- Use separate sessions for parallel work.
|
|
17
|
+
- For orchestrated QA runs, prefer a pre-bound session/platform over repeating per-command selectors.
|
|
17
18
|
- For remote tenant-scoped automation, run commands with:
|
|
18
19
|
`--tenant <id> --session-isolation tenant --run-id <id> --lease-id <id>`
|
|
19
20
|
- In iOS sessions, use `open <app>`. `open <url>` opens deep links; on devices `http(s)://` opens Safari when no app is active, and custom schemes require an active app in the session.
|
|
@@ -26,6 +27,41 @@ Sessions isolate device context. A device can only be held by one session at a t
|
|
|
26
27
|
- For deterministic replay scripts, prefer selector-based actions and assertions.
|
|
27
28
|
- Use `replay -u` to update selector drift during maintenance.
|
|
28
29
|
|
|
30
|
+
## Session-bound automation
|
|
31
|
+
|
|
32
|
+
Use this when an external orchestrator must keep every CLI call on the same session/device without a wrapper script.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
export AGENT_DEVICE_SESSION=qa-ios
|
|
36
|
+
export AGENT_DEVICE_PLATFORM=ios
|
|
37
|
+
export AGENT_DEVICE_SESSION_LOCK=strip
|
|
38
|
+
|
|
39
|
+
agent-device open MyApp --relaunch
|
|
40
|
+
agent-device snapshot -i
|
|
41
|
+
agent-device press @e3
|
|
42
|
+
agent-device close
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
- `AGENT_DEVICE_SESSION` and `AGENT_DEVICE_PLATFORM` provide the default binding when `--session` and `--platform` are omitted.
|
|
46
|
+
- A configured `AGENT_DEVICE_SESSION` enables lock policy enforcement by convention. The default mode is `reject`.
|
|
47
|
+
- `--session-lock reject|strip` or `AGENT_DEVICE_SESSION_LOCK=reject|strip` controls whether conflicting selectors fail or are ignored.
|
|
48
|
+
- The daemon enforces the same lock policy for CLI requests, typed client calls, and direct RPC commands.
|
|
49
|
+
- Conflicts include explicit retargeting selectors such as `--platform`, `--target`, `--device`, `--udid`, `--serial`, `--ios-simulator-device-set`, and `--android-device-allowlist`.
|
|
50
|
+
- `--session-locked`, `--session-lock-conflicts`, `AGENT_DEVICE_SESSION_LOCKED`, and `AGENT_DEVICE_SESSION_LOCK_CONFLICTS` remain supported as compatibility aliases.
|
|
51
|
+
- Lock policy applies to nested `batch` steps too. If a step omits `platform`, it still inherits the parent batch `--platform` instead of being silently replaced by an environment default.
|
|
52
|
+
|
|
53
|
+
Android emulator variant:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
export AGENT_DEVICE_SESSION=qa-android
|
|
57
|
+
export AGENT_DEVICE_PLATFORM=android
|
|
58
|
+
|
|
59
|
+
agent-device reinstall MyApp /path/to/app-debug.apk --serial emulator-5554
|
|
60
|
+
agent-device --session-lock reject open com.example.myapp --relaunch
|
|
61
|
+
agent-device snapshot -i
|
|
62
|
+
agent-device close --shutdown
|
|
63
|
+
```
|
|
64
|
+
|
|
29
65
|
## Scoped device isolation
|
|
30
66
|
|
|
31
67
|
Use scoped discovery when sessions must not see host-global device lists.
|