mobile-agent-mcp 0.1.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/CHANGELOG.md +32 -0
- package/LICENSE +21 -0
- package/NOTICE +4 -0
- package/README.md +115 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +142 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +115 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +137 -0
- package/dist/config.js.map +1 -0
- package/dist/driver/adb.d.ts +2 -0
- package/dist/driver/adb.d.ts.map +1 -0
- package/dist/driver/adb.js +12 -0
- package/dist/driver/adb.js.map +1 -0
- package/dist/driver/dev-server.d.ts +9 -0
- package/dist/driver/dev-server.d.ts.map +1 -0
- package/dist/driver/dev-server.js +24 -0
- package/dist/driver/dev-server.js.map +1 -0
- package/dist/driver/devices.d.ts +2 -0
- package/dist/driver/devices.d.ts.map +1 -0
- package/dist/driver/devices.js +46 -0
- package/dist/driver/devices.js.map +1 -0
- package/dist/driver/doctor.d.ts +11 -0
- package/dist/driver/doctor.d.ts.map +1 -0
- package/dist/driver/doctor.js +64 -0
- package/dist/driver/doctor.js.map +1 -0
- package/dist/driver/exec.d.ts +17 -0
- package/dist/driver/exec.d.ts.map +1 -0
- package/dist/driver/exec.js +60 -0
- package/dist/driver/exec.js.map +1 -0
- package/dist/driver/maestro.d.ts +11 -0
- package/dist/driver/maestro.d.ts.map +1 -0
- package/dist/driver/maestro.js +73 -0
- package/dist/driver/maestro.js.map +1 -0
- package/dist/driver/open-url.d.ts +3 -0
- package/dist/driver/open-url.d.ts.map +1 -0
- package/dist/driver/open-url.js +26 -0
- package/dist/driver/open-url.js.map +1 -0
- package/dist/driver/screenshot.d.ts +3 -0
- package/dist/driver/screenshot.d.ts.map +1 -0
- package/dist/driver/screenshot.js +27 -0
- package/dist/driver/screenshot.js.map +1 -0
- package/dist/errors.d.ts +19 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +45 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/tools.d.ts +12 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +152 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/mcp-server.d.ts +3 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +34 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/runtime.d.ts +20 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +71 -0
- package/dist/runtime.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +4 -0
- package/dist/version.js.map +1 -0
- package/mobile-agent.config.example.json +20 -0
- package/package.json +73 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes are documented here. This project follows [Semantic Versioning](https://semver.org):
|
|
4
|
+
`MAJOR.MINOR.PATCH`: breaking, feature, or fix.
|
|
5
|
+
|
|
6
|
+
## [0.1.1] - 2026-05-30
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- Driver unit tests (Maestro arg building, adb reverse, open-url) with a mocked `spawnSync`.
|
|
11
|
+
- Biome for lint + format; `pnpm lint`, `pnpm format`, and `pnpm check` now gate on it.
|
|
12
|
+
- `CONTRIBUTING.md` with SemVer policy and release steps.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- `AgentError` no longer double-wraps the underlying `cause` when raised from config parsing.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Dropped the unused `fallback` parameter from `assertPlatform`.
|
|
21
|
+
|
|
22
|
+
## [0.1.0] - 2026-05-30
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- MCP stdio server and `mobile-agent` CLI: `doctor`, `list_devices`, `screenshot`,
|
|
27
|
+
`run_maestro_flow`, `run_smoke_flows`, `adb_reverse`, `open_url`, `open_dev_url`.
|
|
28
|
+
- Per-repo `mobile-agent.config.json` with upward discovery and env overrides.
|
|
29
|
+
- Typed errors with stable exit codes and Zod-validated config.
|
|
30
|
+
|
|
31
|
+
[0.1.1]: https://github.com/anthonysbr/mobile-agent-mcp/compare/v0.1.0...v0.1.1
|
|
32
|
+
[0.1.0]: https://github.com/anthonysbr/mobile-agent-mcp/releases/tag/v0.1.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Anthony Batista
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/NOTICE
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# mobile-agent-mcp
|
|
2
|
+
|
|
3
|
+
Drive **iOS simulators, Android emulators, and USB devices** from Cursor, Claude, Codex, or a shell. Maestro runs your flows; this package handles the host side: list devices, screenshots, deep links, `adb reverse`, per-repo config.
|
|
4
|
+
|
|
5
|
+
No Expo or Flutter lock-in. Your Maestro YAML and env vars live in your project.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -D mobile-agent-mcp
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
You need Node 20+, [Maestro](https://maestro.mobile.dev/), Xcode on macOS for iOS, and `adb` for Android.
|
|
14
|
+
|
|
15
|
+
## Config
|
|
16
|
+
|
|
17
|
+
Put `mobile-agent.config.json` in the repo root. Example: [`mobile-agent.config.example.json`](mobile-agent.config.example.json).
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"projectRoot": ".",
|
|
22
|
+
"flowsDir": "e2e/maestro/flows",
|
|
23
|
+
"screenshotDir": "artifacts/mobile-screenshots",
|
|
24
|
+
"smokeFlows": ["smoke-login", "smoke-logout"],
|
|
25
|
+
"maestro": {
|
|
26
|
+
"bin": "maestro",
|
|
27
|
+
"defaultEnv": { "APP_ID": "com.example.app" }
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Optional `devServerUrl` builds something like `exp://192.168.x.x:8081` for Maestro and `open-dev-url`:
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
"devServerUrl": {
|
|
36
|
+
"scheme": "exp",
|
|
37
|
+
"port": 8081,
|
|
38
|
+
"hostEnv": "EXPO_DEV_HOST",
|
|
39
|
+
"outputEnvKey": "EXPO_URL"
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Env overrides: `MOBILE_AGENT_PROJECT_ROOT`, `MOBILE_AGENT_FLOWS_DIR`, `MOBILE_AGENT_SCREENSHOT_DIR`, `MAESTRO_BIN`, `MAESTRO_DEVICE`.
|
|
44
|
+
|
|
45
|
+
If MCP starts from a random cwd, set `MOBILE_AGENT_PROJECT_ROOT` to your repo path.
|
|
46
|
+
|
|
47
|
+
Run `mobile-agent doctor` before a long session. Saves guessing why nothing boots.
|
|
48
|
+
|
|
49
|
+
## CLI
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
mobile-agent doctor
|
|
53
|
+
mobile-agent devices
|
|
54
|
+
mobile-agent screenshot ios
|
|
55
|
+
mobile-agent run my-flow ios -e APP_ID=com.example.app
|
|
56
|
+
mobile-agent run-all ios
|
|
57
|
+
mobile-agent adb-reverse 8081 4000
|
|
58
|
+
mobile-agent open-url "myapp://home" ios
|
|
59
|
+
mobile-agent open-dev-url ios
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Flags: `--project-root`, `--flows-dir`, `--screenshot-dir`.
|
|
63
|
+
|
|
64
|
+
## MCP
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
mobile-agent-mcp
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
| Tool | What it does |
|
|
71
|
+
|------|----------------|
|
|
72
|
+
| `doctor` | Config, flows dir, Maestro, adb/simctl |
|
|
73
|
+
| `list_devices` | Sims, USB, Maestro version |
|
|
74
|
+
| `screenshot` | PNG path |
|
|
75
|
+
| `run_maestro_flow` | One flow from `flowsDir` |
|
|
76
|
+
| `run_smoke_flows` | All `smokeFlows` |
|
|
77
|
+
| `adb_reverse` | USB Android → localhost ports |
|
|
78
|
+
| `open_url` | Any deep link |
|
|
79
|
+
| `open_dev_url` | URL from config |
|
|
80
|
+
|
|
81
|
+
**Cursor** (`.cursor/mcp.json`):
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"mcpServers": {
|
|
86
|
+
"mobile-agent": {
|
|
87
|
+
"command": "npx",
|
|
88
|
+
"args": ["-y", "mobile-agent-mcp"],
|
|
89
|
+
"env": {
|
|
90
|
+
"MOBILE_AGENT_PROJECT_ROOT": "/absolute/path/to/your/project"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Local checkout: point at `dist/mcp-server.js` instead of `npx`.
|
|
98
|
+
|
|
99
|
+
Claude Desktop: same block in `~/Library/Application Support/Claude/claude_desktop_config.json`.
|
|
100
|
+
|
|
101
|
+
No MCP? Shell works fine. See [`docs/agent-skill.md`](docs/agent-skill.md).
|
|
102
|
+
|
|
103
|
+
## Programmatic use
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
import { createRuntime } from 'mobile-agent-mcp';
|
|
107
|
+
|
|
108
|
+
const agent = createRuntime();
|
|
109
|
+
agent.doctor();
|
|
110
|
+
agent.screenshot('ios');
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Roadmap
|
|
114
|
+
|
|
115
|
+
[`ROADMAP.md`](ROADMAP.md): next up **`tail_logs`** (Metro, logcat, iOS sim logs).
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { parseEnvPairs, parsePorts } from './config.js';
|
|
5
|
+
import { formatError, getExitCode } from './errors.js';
|
|
6
|
+
import { createRuntime } from './runtime.js';
|
|
7
|
+
import { PACKAGE_NAME, PACKAGE_VERSION } from './version.js';
|
|
8
|
+
function printResult(text) {
|
|
9
|
+
process.stdout.write(`${text}\n`);
|
|
10
|
+
}
|
|
11
|
+
function printError(error) {
|
|
12
|
+
process.stderr.write(`[${PACKAGE_NAME}] ${formatError(error)}\n`);
|
|
13
|
+
process.exit(getExitCode(error));
|
|
14
|
+
}
|
|
15
|
+
const program = new Command();
|
|
16
|
+
program
|
|
17
|
+
.name('mobile-agent')
|
|
18
|
+
.description('iOS/Android simulators, emulators, and USB devices via Maestro, adb, simctl')
|
|
19
|
+
.version(PACKAGE_VERSION, '-V, --version', 'Print version')
|
|
20
|
+
.option('--project-root <path>', 'Override MOBILE_AGENT_PROJECT_ROOT')
|
|
21
|
+
.option('--flows-dir <path>', 'Override MOBILE_AGENT_FLOWS_DIR')
|
|
22
|
+
.option('--screenshot-dir <path>', 'Override MOBILE_AGENT_SCREENSHOT_DIR');
|
|
23
|
+
function createCliRuntime(command) {
|
|
24
|
+
const opts = command.parent?.opts() ?? {};
|
|
25
|
+
return createRuntime({
|
|
26
|
+
env: {
|
|
27
|
+
...process.env,
|
|
28
|
+
...(opts.projectRoot ? { MOBILE_AGENT_PROJECT_ROOT: opts.projectRoot } : {}),
|
|
29
|
+
...(opts.flowsDir ? { MOBILE_AGENT_FLOWS_DIR: opts.flowsDir } : {}),
|
|
30
|
+
...(opts.screenshotDir ? { MOBILE_AGENT_SCREENSHOT_DIR: opts.screenshotDir } : {}),
|
|
31
|
+
},
|
|
32
|
+
overrides: {
|
|
33
|
+
...(opts.projectRoot ? { projectRoot: path.resolve(opts.projectRoot) } : {}),
|
|
34
|
+
...(opts.flowsDir ? { flowsDir: path.resolve(opts.flowsDir) } : {}),
|
|
35
|
+
...(opts.screenshotDir ? { screenshotDir: path.resolve(opts.screenshotDir) } : {}),
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
program
|
|
40
|
+
.command('doctor')
|
|
41
|
+
.description('Sanity check before running flows')
|
|
42
|
+
.action((_args, command) => {
|
|
43
|
+
try {
|
|
44
|
+
const runtime = createCliRuntime(command);
|
|
45
|
+
printResult(runtime.doctor());
|
|
46
|
+
if (runtime.doctorFailed()) {
|
|
47
|
+
process.exit(4);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
printError(error);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
program
|
|
55
|
+
.command('devices')
|
|
56
|
+
.description('Sims, USB devices, Maestro version')
|
|
57
|
+
.action((_args, command) => {
|
|
58
|
+
try {
|
|
59
|
+
printResult(createCliRuntime(command).listDevices());
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
printError(error);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
program
|
|
66
|
+
.command('screenshot')
|
|
67
|
+
.argument('[platform]', 'ios or android', 'ios')
|
|
68
|
+
.description('PNG to screenshotDir; prints path')
|
|
69
|
+
.action((platform, _args, command) => {
|
|
70
|
+
try {
|
|
71
|
+
printResult(createCliRuntime(command).screenshot(platform));
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
printError(error);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
program
|
|
78
|
+
.command('run')
|
|
79
|
+
.argument('<flow>', 'Maestro flow name or path relative to flowsDir')
|
|
80
|
+
.argument('[platform]', 'ios or android', 'ios')
|
|
81
|
+
.option('-e, --env <pair...>', 'Maestro env var KEY=VALUE')
|
|
82
|
+
.description('Run one Maestro flow')
|
|
83
|
+
.action((flow, platform, options, command) => {
|
|
84
|
+
try {
|
|
85
|
+
printResult(createCliRuntime(command).runFlow(flow, platform, parseEnvPairs(options.env)));
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
printError(error);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
program
|
|
92
|
+
.command('run-all')
|
|
93
|
+
.argument('[platform]', 'ios or android', 'ios')
|
|
94
|
+
.option('-e, --env <pair...>', 'Maestro env var KEY=VALUE')
|
|
95
|
+
.description('Run every flow in smokeFlows from config')
|
|
96
|
+
.action((platform, options, command) => {
|
|
97
|
+
try {
|
|
98
|
+
printResult(createCliRuntime(command).runSmoke(platform, parseEnvPairs(options.env)));
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
printError(error);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
program
|
|
105
|
+
.command('adb-reverse')
|
|
106
|
+
.argument('[ports...]', 'TCP ports to reverse')
|
|
107
|
+
.description('adb reverse for localhost ports (USB Android)')
|
|
108
|
+
.action((ports, _args, command) => {
|
|
109
|
+
try {
|
|
110
|
+
printResult(createCliRuntime(command).adbReverse(parsePorts(ports)));
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
printError(error);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
program
|
|
117
|
+
.command('open-dev-url')
|
|
118
|
+
.argument('[platform]', 'ios or android', 'ios')
|
|
119
|
+
.description('Open URL from devServerUrl in config')
|
|
120
|
+
.action((platform, _args, command) => {
|
|
121
|
+
try {
|
|
122
|
+
printResult(createCliRuntime(command).openDevUrl(platform));
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
printError(error);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
program
|
|
129
|
+
.command('open-url')
|
|
130
|
+
.argument('<url>', 'Deep link or URL to open on device')
|
|
131
|
+
.argument('[platform]', 'ios or android', 'ios')
|
|
132
|
+
.description('Open a deep link on sim or device')
|
|
133
|
+
.action((url, platform, _args, command) => {
|
|
134
|
+
try {
|
|
135
|
+
printResult(createCliRuntime(command).openUrl(url, platform));
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
printError(error);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
program.parse();
|
|
142
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const CONFIG_FILENAME = "mobile-agent.config.json";
|
|
3
|
+
export type Platform = 'ios' | 'android';
|
|
4
|
+
declare const ConfigFileSchema: z.ZodObject<{
|
|
5
|
+
projectRoot: z.ZodOptional<z.ZodString>;
|
|
6
|
+
flowsDir: z.ZodOptional<z.ZodString>;
|
|
7
|
+
screenshotDir: z.ZodOptional<z.ZodString>;
|
|
8
|
+
smokeFlows: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
9
|
+
devServerUrl: z.ZodOptional<z.ZodObject<{
|
|
10
|
+
scheme: z.ZodOptional<z.ZodString>;
|
|
11
|
+
port: z.ZodOptional<z.ZodNumber>;
|
|
12
|
+
hostEnv: z.ZodOptional<z.ZodString>;
|
|
13
|
+
outputEnvKey: z.ZodOptional<z.ZodString>;
|
|
14
|
+
}, "strip", z.ZodTypeAny, {
|
|
15
|
+
scheme?: string | undefined;
|
|
16
|
+
port?: number | undefined;
|
|
17
|
+
hostEnv?: string | undefined;
|
|
18
|
+
outputEnvKey?: string | undefined;
|
|
19
|
+
}, {
|
|
20
|
+
scheme?: string | undefined;
|
|
21
|
+
port?: number | undefined;
|
|
22
|
+
hostEnv?: string | undefined;
|
|
23
|
+
outputEnvKey?: string | undefined;
|
|
24
|
+
}>>;
|
|
25
|
+
maestro: z.ZodOptional<z.ZodObject<{
|
|
26
|
+
bin: z.ZodOptional<z.ZodString>;
|
|
27
|
+
defaultEnv: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
28
|
+
appId: z.ZodOptional<z.ZodObject<{
|
|
29
|
+
ios: z.ZodOptional<z.ZodString>;
|
|
30
|
+
android: z.ZodOptional<z.ZodString>;
|
|
31
|
+
}, "strip", z.ZodTypeAny, {
|
|
32
|
+
ios?: string | undefined;
|
|
33
|
+
android?: string | undefined;
|
|
34
|
+
}, {
|
|
35
|
+
ios?: string | undefined;
|
|
36
|
+
android?: string | undefined;
|
|
37
|
+
}>>;
|
|
38
|
+
}, "strip", z.ZodTypeAny, {
|
|
39
|
+
bin?: string | undefined;
|
|
40
|
+
defaultEnv?: Record<string, string> | undefined;
|
|
41
|
+
appId?: {
|
|
42
|
+
ios?: string | undefined;
|
|
43
|
+
android?: string | undefined;
|
|
44
|
+
} | undefined;
|
|
45
|
+
}, {
|
|
46
|
+
bin?: string | undefined;
|
|
47
|
+
defaultEnv?: Record<string, string> | undefined;
|
|
48
|
+
appId?: {
|
|
49
|
+
ios?: string | undefined;
|
|
50
|
+
android?: string | undefined;
|
|
51
|
+
} | undefined;
|
|
52
|
+
}>>;
|
|
53
|
+
}, "strip", z.ZodTypeAny, {
|
|
54
|
+
projectRoot?: string | undefined;
|
|
55
|
+
flowsDir?: string | undefined;
|
|
56
|
+
screenshotDir?: string | undefined;
|
|
57
|
+
smokeFlows?: string[] | undefined;
|
|
58
|
+
devServerUrl?: {
|
|
59
|
+
scheme?: string | undefined;
|
|
60
|
+
port?: number | undefined;
|
|
61
|
+
hostEnv?: string | undefined;
|
|
62
|
+
outputEnvKey?: string | undefined;
|
|
63
|
+
} | undefined;
|
|
64
|
+
maestro?: {
|
|
65
|
+
bin?: string | undefined;
|
|
66
|
+
defaultEnv?: Record<string, string> | undefined;
|
|
67
|
+
appId?: {
|
|
68
|
+
ios?: string | undefined;
|
|
69
|
+
android?: string | undefined;
|
|
70
|
+
} | undefined;
|
|
71
|
+
} | undefined;
|
|
72
|
+
}, {
|
|
73
|
+
projectRoot?: string | undefined;
|
|
74
|
+
flowsDir?: string | undefined;
|
|
75
|
+
screenshotDir?: string | undefined;
|
|
76
|
+
smokeFlows?: string[] | undefined;
|
|
77
|
+
devServerUrl?: {
|
|
78
|
+
scheme?: string | undefined;
|
|
79
|
+
port?: number | undefined;
|
|
80
|
+
hostEnv?: string | undefined;
|
|
81
|
+
outputEnvKey?: string | undefined;
|
|
82
|
+
} | undefined;
|
|
83
|
+
maestro?: {
|
|
84
|
+
bin?: string | undefined;
|
|
85
|
+
defaultEnv?: Record<string, string> | undefined;
|
|
86
|
+
appId?: {
|
|
87
|
+
ios?: string | undefined;
|
|
88
|
+
android?: string | undefined;
|
|
89
|
+
} | undefined;
|
|
90
|
+
} | undefined;
|
|
91
|
+
}>;
|
|
92
|
+
export type MobileAgentConfigFile = z.infer<typeof ConfigFileSchema>;
|
|
93
|
+
export interface ResolvedConfig {
|
|
94
|
+
projectRoot: string;
|
|
95
|
+
flowsDir: string;
|
|
96
|
+
screenshotDir: string;
|
|
97
|
+
smokeFlows: string[];
|
|
98
|
+
maestroBin: string;
|
|
99
|
+
maestroDefaultEnv: Record<string, string>;
|
|
100
|
+
maestroAppIds: Partial<Record<Platform, string>>;
|
|
101
|
+
devServerUrl: MobileAgentConfigFile['devServerUrl'];
|
|
102
|
+
configPath: string | null;
|
|
103
|
+
}
|
|
104
|
+
export declare function findConfigFile(startDir?: string): string | null;
|
|
105
|
+
export interface LoadConfigOptions {
|
|
106
|
+
startDir?: string;
|
|
107
|
+
overrides?: Partial<ResolvedConfig>;
|
|
108
|
+
env?: NodeJS.ProcessEnv;
|
|
109
|
+
}
|
|
110
|
+
export declare function loadConfig(options?: LoadConfigOptions): ResolvedConfig;
|
|
111
|
+
export declare function assertPlatform(value: string | undefined): Platform;
|
|
112
|
+
export declare function parseEnvPairs(pairs: string[] | undefined): Record<string, string>;
|
|
113
|
+
export declare function parsePorts(ports: string[]): number[];
|
|
114
|
+
export {};
|
|
115
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,eAAe,6BAA6B,CAAC;AAE1D,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;AASzC,QAAA,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkBpB,CAAC;AAEH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAErE,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IACjD,YAAY,EAAE,qBAAqB,CAAC,cAAc,CAAC,CAAC;IACpD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AA0CD,wBAAgB,cAAc,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,GAAG,IAAI,CAgB9E;AAOD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAED,wBAAgB,UAAU,CAAC,OAAO,GAAE,iBAAsB,GAAG,cAAc,CAiD1E;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,CAWlE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUjF;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CASpD"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { AgentError, ErrorCode } from './errors.js';
|
|
5
|
+
export const CONFIG_FILENAME = 'mobile-agent.config.json';
|
|
6
|
+
const DevServerUrlSchema = z.object({
|
|
7
|
+
scheme: z.string().min(1).optional(),
|
|
8
|
+
port: z.number().int().positive().max(65535).optional(),
|
|
9
|
+
hostEnv: z.string().min(1).optional(),
|
|
10
|
+
outputEnvKey: z.string().min(1).optional(),
|
|
11
|
+
});
|
|
12
|
+
const ConfigFileSchema = z.object({
|
|
13
|
+
projectRoot: z.string().min(1).optional(),
|
|
14
|
+
flowsDir: z.string().min(1).optional(),
|
|
15
|
+
screenshotDir: z.string().min(1).optional(),
|
|
16
|
+
smokeFlows: z.array(z.string().min(1)).optional(),
|
|
17
|
+
devServerUrl: DevServerUrlSchema.optional(),
|
|
18
|
+
maestro: z
|
|
19
|
+
.object({
|
|
20
|
+
bin: z.string().min(1).optional(),
|
|
21
|
+
defaultEnv: z.record(z.string(), z.string()).optional(),
|
|
22
|
+
appId: z
|
|
23
|
+
.object({
|
|
24
|
+
ios: z.string().min(1).optional(),
|
|
25
|
+
android: z.string().min(1).optional(),
|
|
26
|
+
})
|
|
27
|
+
.optional(),
|
|
28
|
+
})
|
|
29
|
+
.optional(),
|
|
30
|
+
});
|
|
31
|
+
const DEFAULT_FLOWS_DIR = 'e2e/maestro/flows';
|
|
32
|
+
const DEFAULT_SCREENSHOT_DIR = 'artifacts/mobile-screenshots';
|
|
33
|
+
function readConfigFile(filePath) {
|
|
34
|
+
let raw;
|
|
35
|
+
try {
|
|
36
|
+
raw = fs.readFileSync(filePath, 'utf-8');
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
throw new AgentError(`Unable to read ${filePath}: ${error instanceof Error ? error.message : String(error)}`, ErrorCode.CONFIG_INVALID, error);
|
|
40
|
+
}
|
|
41
|
+
let parsed;
|
|
42
|
+
try {
|
|
43
|
+
parsed = JSON.parse(raw);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
throw new AgentError(`Invalid JSON in ${filePath}: ${error instanceof Error ? error.message : String(error)}`, ErrorCode.CONFIG_INVALID, error);
|
|
47
|
+
}
|
|
48
|
+
const result = ConfigFileSchema.safeParse(parsed);
|
|
49
|
+
if (!result.success) {
|
|
50
|
+
const details = result.error.issues
|
|
51
|
+
.map((issue) => `${issue.path.join('.') || 'root'}: ${issue.message}`)
|
|
52
|
+
.join('; ');
|
|
53
|
+
throw new AgentError(`Invalid ${CONFIG_FILENAME} at ${filePath}: ${details}`, ErrorCode.CONFIG_INVALID);
|
|
54
|
+
}
|
|
55
|
+
return result.data;
|
|
56
|
+
}
|
|
57
|
+
export function findConfigFile(startDir = process.cwd()) {
|
|
58
|
+
let dir = path.resolve(startDir);
|
|
59
|
+
const root = path.parse(dir).root;
|
|
60
|
+
while (true) {
|
|
61
|
+
const candidate = path.join(dir, CONFIG_FILENAME);
|
|
62
|
+
if (fs.existsSync(candidate)) {
|
|
63
|
+
return candidate;
|
|
64
|
+
}
|
|
65
|
+
if (dir === root) {
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
dir = path.dirname(dir);
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
function resolvePath(baseDir, value, fallback) {
|
|
73
|
+
const target = value ?? fallback;
|
|
74
|
+
return path.resolve(baseDir, target);
|
|
75
|
+
}
|
|
76
|
+
export function loadConfig(options = {}) {
|
|
77
|
+
const env = options.env ?? process.env;
|
|
78
|
+
const startDir = options.startDir ?? process.cwd();
|
|
79
|
+
const configSearchDir = env.MOBILE_AGENT_PROJECT_ROOT ?? startDir;
|
|
80
|
+
const configPath = findConfigFile(configSearchDir);
|
|
81
|
+
const fileConfig = configPath ? readConfigFile(configPath) : {};
|
|
82
|
+
const configBaseDir = configPath ? path.dirname(configPath) : path.resolve(startDir);
|
|
83
|
+
const projectRoot = resolvePath(configBaseDir, env.MOBILE_AGENT_PROJECT_ROOT ?? fileConfig.projectRoot, '.');
|
|
84
|
+
const flowsDir = resolvePath(projectRoot, env.MOBILE_AGENT_FLOWS_DIR ?? fileConfig.flowsDir, DEFAULT_FLOWS_DIR);
|
|
85
|
+
const screenshotDir = resolvePath(projectRoot, env.MOBILE_AGENT_SCREENSHOT_DIR ?? fileConfig.screenshotDir, DEFAULT_SCREENSHOT_DIR);
|
|
86
|
+
const maestroBin = env.MAESTRO_BIN ?? fileConfig.maestro?.bin ?? 'maestro';
|
|
87
|
+
const maestroDefaultEnv = fileConfig.maestro?.defaultEnv ?? {};
|
|
88
|
+
const maestroAppIds = fileConfig.maestro?.appId ?? {};
|
|
89
|
+
const devServerUrl = fileConfig.devServerUrl;
|
|
90
|
+
const smokeFlows = fileConfig.smokeFlows ?? [];
|
|
91
|
+
const resolved = {
|
|
92
|
+
projectRoot,
|
|
93
|
+
flowsDir,
|
|
94
|
+
screenshotDir,
|
|
95
|
+
smokeFlows,
|
|
96
|
+
maestroBin,
|
|
97
|
+
maestroDefaultEnv,
|
|
98
|
+
maestroAppIds,
|
|
99
|
+
devServerUrl,
|
|
100
|
+
configPath,
|
|
101
|
+
};
|
|
102
|
+
if (options.overrides) {
|
|
103
|
+
return { ...resolved, ...options.overrides };
|
|
104
|
+
}
|
|
105
|
+
return resolved;
|
|
106
|
+
}
|
|
107
|
+
export function assertPlatform(value) {
|
|
108
|
+
if (!value || value === 'ios') {
|
|
109
|
+
return 'ios';
|
|
110
|
+
}
|
|
111
|
+
if (value === 'android') {
|
|
112
|
+
return 'android';
|
|
113
|
+
}
|
|
114
|
+
throw new AgentError(`Unknown platform: ${value} (use ios or android)`, ErrorCode.PLATFORM_INVALID);
|
|
115
|
+
}
|
|
116
|
+
export function parseEnvPairs(pairs) {
|
|
117
|
+
const env = {};
|
|
118
|
+
for (const pair of pairs ?? []) {
|
|
119
|
+
const index = pair.indexOf('=');
|
|
120
|
+
if (index <= 0) {
|
|
121
|
+
throw new AgentError(`Invalid env pair: ${pair} (expected KEY=VALUE)`, ErrorCode.VALIDATION);
|
|
122
|
+
}
|
|
123
|
+
env[pair.slice(0, index)] = pair.slice(index + 1);
|
|
124
|
+
}
|
|
125
|
+
return env;
|
|
126
|
+
}
|
|
127
|
+
export function parsePorts(ports) {
|
|
128
|
+
const portArgs = ports.length > 0 ? ports : ['8081'];
|
|
129
|
+
return portArgs.map((port) => {
|
|
130
|
+
const value = Number(port);
|
|
131
|
+
if (!Number.isInteger(value) || value <= 0 || value > 65535) {
|
|
132
|
+
throw new AgentError(`Invalid port: ${port}`, ErrorCode.VALIDATION);
|
|
133
|
+
}
|
|
134
|
+
return value;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adb.d.ts","sourceRoot":"","sources":["../../src/driver/adb.ts"],"names":[],"mappings":"AAGA,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAUlD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AgentError, ErrorCode } from '../errors.js';
|
|
2
|
+
import { commandExists, runCommand } from './exec.js';
|
|
3
|
+
export function adbReverse(ports) {
|
|
4
|
+
if (!commandExists('adb')) {
|
|
5
|
+
throw new AgentError('adb not installed', ErrorCode.TOOL_UNAVAILABLE);
|
|
6
|
+
}
|
|
7
|
+
for (const port of ports) {
|
|
8
|
+
runCommand('adb', ['reverse', `tcp:${port}`, `tcp:${port}`]);
|
|
9
|
+
}
|
|
10
|
+
return `adb reverse ok (${ports.join(', ')})`;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=adb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adb.js","sourceRoot":"","sources":["../../src/driver/adb.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEtD,MAAM,UAAU,UAAU,CAAC,KAAe;IACxC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,UAAU,CAAC,mBAAmB,EAAE,SAAS,CAAC,gBAAgB,CAAC,CAAC;IACxE,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,UAAU,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,OAAO,IAAI,EAAE,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,mBAAmB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function detectLanIp(): string;
|
|
2
|
+
export interface DevServerUrlConfig {
|
|
3
|
+
scheme?: string;
|
|
4
|
+
port?: number;
|
|
5
|
+
hostEnv?: string;
|
|
6
|
+
outputEnvKey?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function resolveDevServerEnv(config: DevServerUrlConfig | undefined, env?: NodeJS.ProcessEnv): Record<string, string>;
|
|
9
|
+
//# sourceMappingURL=dev-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../../src/driver/dev-server.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,IAAI,MAAM,CAWpC;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,kBAAkB,GAAG,SAAS,EACtC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYxB"}
|