@mobileaidev/ai-app-bridge 0.2.2 → 0.2.4
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/bin/ai-app-bridge.js +49 -32
- package/bin/mcp-server.js +74 -46
- package/package.json +1 -1
package/bin/ai-app-bridge.js
CHANGED
|
@@ -782,25 +782,41 @@ async function ensureForward(ctx) {
|
|
|
782
782
|
};
|
|
783
783
|
}
|
|
784
784
|
|
|
785
|
-
async function resolveDevicePort(ctx) {
|
|
786
|
-
if (ctx.explicitPort) return { port: ctx.port, source: 'explicit-port' };
|
|
787
|
-
try {
|
|
788
|
-
const result = await adb(ctx, ['shell', 'run-as', ctx.packageName, 'cat', 'files/ai_app_bridge_port.json']);
|
|
789
|
-
const state = JSON.parse(result.stdout.trim());
|
|
790
|
-
const discoveredPort = Number(state.port);
|
|
791
|
-
if (state.ok === true && Number.isInteger(discoveredPort) && discoveredPort > 0) {
|
|
792
|
-
return { port: discoveredPort, source: 'package-port-file', state };
|
|
793
|
-
}
|
|
794
|
-
} catch (error) {
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
785
|
+
async function resolveDevicePort(ctx) {
|
|
786
|
+
if (ctx.explicitPort) return { port: ctx.port, source: 'explicit-port' };
|
|
787
|
+
try {
|
|
788
|
+
const result = await adb(ctx, ['shell', 'run-as', ctx.packageName, 'cat', 'files/ai_app_bridge_port.json']);
|
|
789
|
+
const state = JSON.parse(result.stdout.trim());
|
|
790
|
+
const discoveredPort = Number(state.port);
|
|
791
|
+
if (state.ok === true && Number.isInteger(discoveredPort) && discoveredPort > 0) {
|
|
792
|
+
return { port: discoveredPort, source: 'package-port-file', state };
|
|
793
|
+
}
|
|
794
|
+
} catch (error) {
|
|
795
|
+
if (!shouldUseDefaultPortFallback(ctx)) {
|
|
796
|
+
ctx.devicePortSource = 'package-port-file';
|
|
797
|
+
ctx.devicePortError = firstErrorLine(error);
|
|
798
|
+
error.aiAppBridgePortDiscovery = true;
|
|
799
|
+
throw error;
|
|
800
|
+
}
|
|
801
|
+
return {
|
|
802
|
+
port: ctx.port,
|
|
803
|
+
source: 'default-port',
|
|
804
|
+
error: firstErrorLine(error),
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
if (!shouldUseDefaultPortFallback(ctx)) {
|
|
808
|
+
const error = new Error(`bridge port discovery failed for explicit package: ${ctx.packageName}`);
|
|
809
|
+
error.aiAppBridgePortDiscovery = true;
|
|
810
|
+
ctx.devicePortSource = 'package-port-file';
|
|
811
|
+
ctx.devicePortError = firstErrorLine(error);
|
|
812
|
+
throw error;
|
|
813
|
+
}
|
|
814
|
+
return { port: ctx.port, source: 'default-port' };
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
function shouldUseDefaultPortFallback(ctx) {
|
|
818
|
+
return !ctx.explicitPackageName;
|
|
819
|
+
}
|
|
804
820
|
|
|
805
821
|
async function bridgeStatus(ctx, options = {}) {
|
|
806
822
|
try {
|
|
@@ -953,17 +969,17 @@ function normalizeBridgeError(error) {
|
|
|
953
969
|
suggestion: 'Confirm the target app is running and that the resolved bridge port belongs to this package.',
|
|
954
970
|
};
|
|
955
971
|
}
|
|
956
|
-
if (lower.includes('adb timed out')) {
|
|
957
|
-
return {
|
|
958
|
-
code: 'adb_timeout',
|
|
959
|
-
message,
|
|
960
|
-
suggestion: 'Check the device state and retry; if the bridge port is known, pass --port to skip package port discovery.',
|
|
961
|
-
};
|
|
962
|
-
}
|
|
963
|
-
if (lower.includes('run-as') || lower.includes('package not found')) {
|
|
964
|
-
return {
|
|
965
|
-
code: 'bridge_port_discovery_failed',
|
|
966
|
-
message,
|
|
972
|
+
if (lower.includes('adb timed out')) {
|
|
973
|
+
return {
|
|
974
|
+
code: 'adb_timeout',
|
|
975
|
+
message,
|
|
976
|
+
suggestion: 'Check the device state and retry; if the bridge port is known, pass --port to skip package port discovery.',
|
|
977
|
+
};
|
|
978
|
+
}
|
|
979
|
+
if (error?.aiAppBridgePortDiscovery || lower.includes('bridge port discovery failed') || lower.includes('run-as') || lower.includes('package not found')) {
|
|
980
|
+
return {
|
|
981
|
+
code: 'bridge_port_discovery_failed',
|
|
982
|
+
message,
|
|
967
983
|
suggestion: 'Install a debuggable build for the requested package or pass --port explicitly.',
|
|
968
984
|
};
|
|
969
985
|
}
|
|
@@ -4299,8 +4315,9 @@ module.exports = {
|
|
|
4299
4315
|
compactNetworkRecord,
|
|
4300
4316
|
pruneGeneratedArtifacts,
|
|
4301
4317
|
shouldSkipInstallerTapForInstalledPackage,
|
|
4302
|
-
shouldDismissKeyboardForPoint,
|
|
4303
|
-
|
|
4318
|
+
shouldDismissKeyboardForPoint,
|
|
4319
|
+
shouldUseDefaultPortFallback,
|
|
4320
|
+
screenshotOutputPath,
|
|
4304
4321
|
statusSearchText,
|
|
4305
4322
|
uiautomatorLockPath,
|
|
4306
4323
|
waitTextConditionsMet,
|
package/bin/mcp-server.js
CHANGED
|
@@ -17,13 +17,15 @@ const serverInstructions = [
|
|
|
17
17
|
].join(' ');
|
|
18
18
|
|
|
19
19
|
let buffer = Buffer.alloc(0);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
|
|
21
|
+
function startServer() {
|
|
22
|
+
process.stdin.on('data', (chunk) => {
|
|
23
|
+
buffer = Buffer.concat([buffer, chunk]);
|
|
24
|
+
drainMessages();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
process.stdin.on('error', () => {});
|
|
28
|
+
}
|
|
27
29
|
|
|
28
30
|
function drainMessages() {
|
|
29
31
|
while (true) {
|
|
@@ -565,9 +567,13 @@ function runBridgeChecked(command, args = {}) {
|
|
|
565
567
|
return runBridge(command, args);
|
|
566
568
|
}
|
|
567
569
|
|
|
568
|
-
async function runBridge(command, args) {
|
|
569
|
-
|
|
570
|
-
|
|
570
|
+
async function runBridge(command, args) {
|
|
571
|
+
return runProcess(buildBridgeCliArgs(command, args));
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
function buildBridgeCliArgs(command, args = {}) {
|
|
575
|
+
const cliArgs = [cliScript, command];
|
|
576
|
+
addCommonArgs(cliArgs, args);
|
|
571
577
|
addArg(cliArgs, 'initial-route', args.initialRoute);
|
|
572
578
|
addArg(cliArgs, 'activity', args.activity);
|
|
573
579
|
addArg(cliArgs, 'component', args.component);
|
|
@@ -601,33 +607,45 @@ async function runBridge(command, args) {
|
|
|
601
607
|
addArg(cliArgs, 'page-url-filter', args.pageUrlFilter);
|
|
602
608
|
addArg(cliArgs, 'url-filter', args.urlFilter);
|
|
603
609
|
addArg(cliArgs, 'method', args.method);
|
|
604
|
-
addArg(cliArgs, 'status-code', args.statusCode);
|
|
605
|
-
addArg(cliArgs, 'compact', args.compact);
|
|
606
|
-
addArg(cliArgs, 'full', args.full);
|
|
607
|
-
addArg(cliArgs, '
|
|
608
|
-
addArg(cliArgs, '
|
|
609
|
-
addArg(cliArgs, '
|
|
610
|
-
addArg(cliArgs, '
|
|
611
|
-
addArg(cliArgs, 'max-
|
|
612
|
-
addArg(cliArgs, '
|
|
613
|
-
addArg(cliArgs, '
|
|
614
|
-
addArg(cliArgs, '
|
|
615
|
-
addArg(cliArgs, '
|
|
616
|
-
addArg(cliArgs, '
|
|
617
|
-
addArg(cliArgs, '
|
|
618
|
-
addArg(cliArgs, '
|
|
610
|
+
addArg(cliArgs, 'status-code', args.statusCode);
|
|
611
|
+
addArg(cliArgs, 'compact', args.compact);
|
|
612
|
+
addArg(cliArgs, 'full', args.full);
|
|
613
|
+
addArg(cliArgs, 'text-filter', args.textFilter);
|
|
614
|
+
addArg(cliArgs, 'resource-id-filter', args.resourceIdFilter);
|
|
615
|
+
addArg(cliArgs, 'class-filter', args.classFilter);
|
|
616
|
+
addArg(cliArgs, 'visible-only', args.visibleOnly);
|
|
617
|
+
addArg(cliArgs, 'max-nodes', args.maxNodes);
|
|
618
|
+
addArg(cliArgs, 'max-depth', args.maxDepth);
|
|
619
|
+
addArg(cliArgs, 'no-bodies', args.noBodies);
|
|
620
|
+
addArg(cliArgs, 'duration-ms', args.durationMs);
|
|
621
|
+
addArg(cliArgs, 'include-response-body', args.includeResponseBody);
|
|
622
|
+
addArg(cliArgs, 'body-max-bytes', args.bodyMaxBytes);
|
|
623
|
+
addArg(cliArgs, 'max-events', args.maxEvents);
|
|
624
|
+
addArg(cliArgs, 'keep-forward', args.keepForward);
|
|
625
|
+
addArg(cliArgs, 'key-code', args.keyCode);
|
|
626
|
+
addArg(cliArgs, 'payload', args.payload);
|
|
627
|
+
addArg(cliArgs, 'delta', args.delta);
|
|
628
|
+
addArg(cliArgs, 'max-swipes', args.maxSwipes);
|
|
629
|
+
addArg(cliArgs, 'permission', args.permission);
|
|
630
|
+
addArg(cliArgs, 'op', args.op);
|
|
631
|
+
addArg(cliArgs, 'mode', args.mode);
|
|
632
|
+
addArg(cliArgs, 'script', args.script);
|
|
633
|
+
addArg(cliArgs, 'selector', args.selector);
|
|
619
634
|
addArg(cliArgs, 'target-text', args.targetText);
|
|
620
635
|
addArg(cliArgs, 'value', args.value);
|
|
621
636
|
addArg(cliArgs, 'exact', args.exact);
|
|
622
637
|
addArg(cliArgs, 'button-text', args.buttonText);
|
|
623
638
|
addArg(cliArgs, 'resource-id', args.resourceId);
|
|
624
|
-
addArg(cliArgs, 'attempts', args.attempts);
|
|
625
|
-
addArg(cliArgs, 'interval-ms', args.intervalMs);
|
|
626
|
-
addArg(cliArgs, 'delta-x', args.deltaX);
|
|
627
|
-
addArg(cliArgs, 'delta-y', args.deltaY);
|
|
628
|
-
addArg(cliArgs, '
|
|
629
|
-
addArg(cliArgs, '
|
|
630
|
-
addArg(cliArgs, '
|
|
639
|
+
addArg(cliArgs, 'attempts', args.attempts);
|
|
640
|
+
addArg(cliArgs, 'interval-ms', args.intervalMs);
|
|
641
|
+
addArg(cliArgs, 'delta-x', args.deltaX);
|
|
642
|
+
addArg(cliArgs, 'delta-y', args.deltaY);
|
|
643
|
+
addArg(cliArgs, 'require-text', args.requireText);
|
|
644
|
+
addArg(cliArgs, 'absent-text', args.absentText);
|
|
645
|
+
addArg(cliArgs, 'require-activity', args.requireActivity);
|
|
646
|
+
addArg(cliArgs, 'since-id', args.sinceId);
|
|
647
|
+
addArg(cliArgs, 'since-ms', args.sinceMs);
|
|
648
|
+
addArg(cliArgs, 'limit', args.limit);
|
|
631
649
|
addArg(cliArgs, 'pid', args.pid);
|
|
632
650
|
addArg(cliArgs, 'app-pid', args.appPid);
|
|
633
651
|
addArg(cliArgs, 'tag', args.tag);
|
|
@@ -635,19 +653,21 @@ async function runBridge(command, args) {
|
|
|
635
653
|
addArg(cliArgs, 'grep', args.grep);
|
|
636
654
|
addArg(cliArgs, 'lines', args.lines);
|
|
637
655
|
addArg(cliArgs, 'since', args.since);
|
|
638
|
-
addArg(cliArgs, 'follow', args.follow);
|
|
639
|
-
addArg(cliArgs, 'duration-sec', args.durationSec);
|
|
640
|
-
addArg(cliArgs, 'clear', args.clear);
|
|
641
|
-
|
|
642
|
-
|
|
656
|
+
addArg(cliArgs, 'follow', args.follow);
|
|
657
|
+
addArg(cliArgs, 'duration-sec', args.durationSec);
|
|
658
|
+
addArg(cliArgs, 'clear', args.clear);
|
|
659
|
+
addArg(cliArgs, 'skip-flutter-launch', args.skipFlutterLaunch);
|
|
660
|
+
return cliArgs;
|
|
661
|
+
}
|
|
643
662
|
|
|
644
663
|
async function runSmoke(args) {
|
|
645
664
|
const cliArgs = [cliScript, 'smoke'];
|
|
646
|
-
addCommonArgs(cliArgs, args);
|
|
647
|
-
addArg(cliArgs, 'out-file', args.outFile);
|
|
648
|
-
addArg(cliArgs, 'artifact-dir', args.artifactDir || defaultArtifactDirFor('smoke', args));
|
|
649
|
-
|
|
650
|
-
|
|
665
|
+
addCommonArgs(cliArgs, args);
|
|
666
|
+
addArg(cliArgs, 'out-file', args.outFile);
|
|
667
|
+
addArg(cliArgs, 'artifact-dir', args.artifactDir || defaultArtifactDirFor('smoke', args));
|
|
668
|
+
addArg(cliArgs, 'skip-flutter-launch', args.skipFlutterLaunch);
|
|
669
|
+
return runProcess(cliArgs);
|
|
670
|
+
}
|
|
651
671
|
|
|
652
672
|
function defaultArtifactDirFor(command, args) {
|
|
653
673
|
if (args.outFile) return '';
|
|
@@ -776,7 +796,15 @@ function send(message) {
|
|
|
776
796
|
process.stdout.write(body);
|
|
777
797
|
}
|
|
778
798
|
|
|
779
|
-
function writeLog(text) {
|
|
780
|
-
process.stderr.write(`${text}\n`);
|
|
781
|
-
}
|
|
782
|
-
|
|
799
|
+
function writeLog(text) {
|
|
800
|
+
process.stderr.write(`${text}\n`);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
if (require.main === module) {
|
|
804
|
+
startServer();
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
module.exports = {
|
|
808
|
+
buildBridgeCliArgs,
|
|
809
|
+
startServer,
|
|
810
|
+
};
|