@midscene/harmony 1.6.3-beta-20260403070857.0 → 1.6.3
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/dist/es/bin.mjs +38 -2
- package/dist/es/cli.mjs +41 -4
- package/dist/es/index.mjs +38 -2
- package/dist/es/mcp-server.mjs +39 -3
- package/dist/lib/bin.js +38 -2
- package/dist/lib/cli.js +41 -4
- package/dist/lib/index.js +38 -2
- package/dist/lib/mcp-server.js +39 -3
- package/dist/types/index.d.ts +7 -0
- package/dist/types/mcp-server.d.ts +7 -0
- package/package.json +4 -4
- package/static/index.html +1 -1
- package/static/static/js/index.eb5d1f53.js +896 -0
- package/static/static/js/index.eb5d1f53.js.map +1 -0
- package/static/static/js/index.8f5d1da7.js +0 -896
- package/static/static/js/index.8f5d1da7.js.map +0 -1
- /package/static/static/js/{index.8f5d1da7.js.LICENSE.txt → index.eb5d1f53.js.LICENSE.txt} +0 -0
package/dist/es/bin.mjs
CHANGED
|
@@ -37,7 +37,8 @@ const defaultAppNameMapping = {
|
|
|
37
37
|
Browser: 'com.huawei.hmos.browser',
|
|
38
38
|
应用市场: 'com.huawei.appmarket',
|
|
39
39
|
AppGallery: 'com.huawei.appmarket',
|
|
40
|
-
华为音乐: 'com.huawei.
|
|
40
|
+
华为音乐: 'com.huawei.hmsapp.music',
|
|
41
|
+
Music: 'com.huawei.hmsapp.music',
|
|
41
42
|
华为视频: 'com.huawei.hmos.video',
|
|
42
43
|
天气: 'com.huawei.hmos.weather',
|
|
43
44
|
Weather: 'com.huawei.hmos.weather',
|
|
@@ -196,7 +197,8 @@ class HdcClient {
|
|
|
196
197
|
return names.find((n)=>n !== bundleName && n.endsWith('Ability') && !n.includes('Extension') && !n.includes('Service') && !n.includes('Form') && !n.includes('Dialog'));
|
|
197
198
|
}
|
|
198
199
|
async forceStop(bundleName) {
|
|
199
|
-
await this.shell(`aa force-stop ${bundleName}`);
|
|
200
|
+
const output = await this.shell(`aa force-stop ${bundleName}`);
|
|
201
|
+
if (output.includes('error:')) throw new Error(`Failed to force stop ${bundleName}: ${output.trim()}`);
|
|
200
202
|
}
|
|
201
203
|
async getScreenInfo() {
|
|
202
204
|
const stdout = await this.shell('hidumper -s RenderService -a screen');
|
|
@@ -476,6 +478,21 @@ class device_HarmonyDevice {
|
|
|
476
478
|
}
|
|
477
479
|
return this;
|
|
478
480
|
}
|
|
481
|
+
async terminate(uri) {
|
|
482
|
+
const bundlePart = uri.includes('/') ? uri.split('/')[0] : uri;
|
|
483
|
+
const resolved = this.resolvePackageName(bundlePart) ?? bundlePart;
|
|
484
|
+
const hdc = await this.getHdc();
|
|
485
|
+
try {
|
|
486
|
+
debugDevice(`Terminating app: ${resolved}`);
|
|
487
|
+
await hdc.forceStop(resolved);
|
|
488
|
+
debugDevice(`Successfully terminated: ${resolved}`);
|
|
489
|
+
} catch (error) {
|
|
490
|
+
debugDevice(`Error terminating ${resolved}: ${error}`);
|
|
491
|
+
throw new Error(`Failed to terminate ${resolved}: ${error.message}`, {
|
|
492
|
+
cause: error
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
}
|
|
479
496
|
async getScreenSize() {
|
|
480
497
|
if (this.cachedScreenSize) return this.cachedScreenSize;
|
|
481
498
|
const hdc = await this.getHdc();
|
|
@@ -783,6 +800,9 @@ const runHdcShellParamSchema = z.object({
|
|
|
783
800
|
const launchParamSchema = z.object({
|
|
784
801
|
uri: z.string().describe('App name, bundle name, or URL to launch. Prioritize using the exact bundle name or URL the user has provided. If none provided, use the accurate app name.')
|
|
785
802
|
});
|
|
803
|
+
const terminateParamSchema = z.object({
|
|
804
|
+
uri: z.string().describe('Bundle name or app name to terminate. Prioritize using the exact bundle name the user provided. If the bundle is unknown, use the accurate app name shown on screen, such as Settings or Music.')
|
|
805
|
+
});
|
|
786
806
|
const createPlatformActions = (device)=>({
|
|
787
807
|
RunHdcShell: defineAction({
|
|
788
808
|
name: 'RunHdcShell',
|
|
@@ -811,6 +831,16 @@ const createPlatformActions = (device)=>({
|
|
|
811
831
|
await device.launch(param.uri);
|
|
812
832
|
}
|
|
813
833
|
}),
|
|
834
|
+
Terminate: defineAction({
|
|
835
|
+
name: 'Terminate',
|
|
836
|
+
description: 'Terminate (force-stop) a HarmonyOS app by bundle name or mapped app name',
|
|
837
|
+
interfaceAlias: 'terminate',
|
|
838
|
+
paramSchema: terminateParamSchema,
|
|
839
|
+
call: async (param)=>{
|
|
840
|
+
if (!param.uri || '' === param.uri.trim()) throw new Error('Terminate requires a non-empty uri parameter');
|
|
841
|
+
await device.terminate(param.uri);
|
|
842
|
+
}
|
|
843
|
+
}),
|
|
814
844
|
HarmonyBackButton: defineAction({
|
|
815
845
|
name: 'HarmonyBackButton',
|
|
816
846
|
description: 'Trigger the system "back" operation on HarmonyOS devices',
|
|
@@ -870,6 +900,12 @@ class HarmonyAgent extends Agent {
|
|
|
870
900
|
uri
|
|
871
901
|
});
|
|
872
902
|
}
|
|
903
|
+
async terminate(uri) {
|
|
904
|
+
const action = this.wrapActionInActionSpace('Terminate');
|
|
905
|
+
return action({
|
|
906
|
+
uri
|
|
907
|
+
});
|
|
908
|
+
}
|
|
873
909
|
async runHdcShell(command) {
|
|
874
910
|
const action = this.wrapActionInActionSpace('RunHdcShell');
|
|
875
911
|
return action({
|
package/dist/es/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { createReportCliCommands, getMidsceneLocationSchema, z } from "@midscene/core";
|
|
1
2
|
import { CLIError, runToolsCLI } from "@midscene/shared/cli";
|
|
2
|
-
import { getMidsceneLocationSchema, z } from "@midscene/core";
|
|
3
3
|
import { getDebug } from "@midscene/shared/logger";
|
|
4
4
|
import { BaseMidsceneTools } from "@midscene/shared/mcp";
|
|
5
5
|
import { Agent } from "@midscene/core/agent";
|
|
@@ -34,7 +34,8 @@ const defaultAppNameMapping = {
|
|
|
34
34
|
Browser: 'com.huawei.hmos.browser',
|
|
35
35
|
应用市场: 'com.huawei.appmarket',
|
|
36
36
|
AppGallery: 'com.huawei.appmarket',
|
|
37
|
-
华为音乐: 'com.huawei.
|
|
37
|
+
华为音乐: 'com.huawei.hmsapp.music',
|
|
38
|
+
Music: 'com.huawei.hmsapp.music',
|
|
38
39
|
华为视频: 'com.huawei.hmos.video',
|
|
39
40
|
天气: 'com.huawei.hmos.weather',
|
|
40
41
|
Weather: 'com.huawei.hmos.weather',
|
|
@@ -193,7 +194,8 @@ class HdcClient {
|
|
|
193
194
|
return names.find((n)=>n !== bundleName && n.endsWith('Ability') && !n.includes('Extension') && !n.includes('Service') && !n.includes('Form') && !n.includes('Dialog'));
|
|
194
195
|
}
|
|
195
196
|
async forceStop(bundleName) {
|
|
196
|
-
await this.shell(`aa force-stop ${bundleName}`);
|
|
197
|
+
const output = await this.shell(`aa force-stop ${bundleName}`);
|
|
198
|
+
if (output.includes('error:')) throw new Error(`Failed to force stop ${bundleName}: ${output.trim()}`);
|
|
197
199
|
}
|
|
198
200
|
async getScreenInfo() {
|
|
199
201
|
const stdout = await this.shell('hidumper -s RenderService -a screen');
|
|
@@ -473,6 +475,21 @@ class HarmonyDevice {
|
|
|
473
475
|
}
|
|
474
476
|
return this;
|
|
475
477
|
}
|
|
478
|
+
async terminate(uri) {
|
|
479
|
+
const bundlePart = uri.includes('/') ? uri.split('/')[0] : uri;
|
|
480
|
+
const resolved = this.resolvePackageName(bundlePart) ?? bundlePart;
|
|
481
|
+
const hdc = await this.getHdc();
|
|
482
|
+
try {
|
|
483
|
+
debugDevice(`Terminating app: ${resolved}`);
|
|
484
|
+
await hdc.forceStop(resolved);
|
|
485
|
+
debugDevice(`Successfully terminated: ${resolved}`);
|
|
486
|
+
} catch (error) {
|
|
487
|
+
debugDevice(`Error terminating ${resolved}: ${error}`);
|
|
488
|
+
throw new Error(`Failed to terminate ${resolved}: ${error.message}`, {
|
|
489
|
+
cause: error
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
}
|
|
476
493
|
async getScreenSize() {
|
|
477
494
|
if (this.cachedScreenSize) return this.cachedScreenSize;
|
|
478
495
|
const hdc = await this.getHdc();
|
|
@@ -780,6 +797,9 @@ const runHdcShellParamSchema = z.object({
|
|
|
780
797
|
const launchParamSchema = z.object({
|
|
781
798
|
uri: z.string().describe('App name, bundle name, or URL to launch. Prioritize using the exact bundle name or URL the user has provided. If none provided, use the accurate app name.')
|
|
782
799
|
});
|
|
800
|
+
const terminateParamSchema = z.object({
|
|
801
|
+
uri: z.string().describe('Bundle name or app name to terminate. Prioritize using the exact bundle name the user provided. If the bundle is unknown, use the accurate app name shown on screen, such as Settings or Music.')
|
|
802
|
+
});
|
|
783
803
|
const createPlatformActions = (device)=>({
|
|
784
804
|
RunHdcShell: defineAction({
|
|
785
805
|
name: 'RunHdcShell',
|
|
@@ -808,6 +828,16 @@ const createPlatformActions = (device)=>({
|
|
|
808
828
|
await device.launch(param.uri);
|
|
809
829
|
}
|
|
810
830
|
}),
|
|
831
|
+
Terminate: defineAction({
|
|
832
|
+
name: 'Terminate',
|
|
833
|
+
description: 'Terminate (force-stop) a HarmonyOS app by bundle name or mapped app name',
|
|
834
|
+
interfaceAlias: 'terminate',
|
|
835
|
+
paramSchema: terminateParamSchema,
|
|
836
|
+
call: async (param)=>{
|
|
837
|
+
if (!param.uri || '' === param.uri.trim()) throw new Error('Terminate requires a non-empty uri parameter');
|
|
838
|
+
await device.terminate(param.uri);
|
|
839
|
+
}
|
|
840
|
+
}),
|
|
811
841
|
HarmonyBackButton: defineAction({
|
|
812
842
|
name: 'HarmonyBackButton',
|
|
813
843
|
description: 'Trigger the system "back" operation on HarmonyOS devices',
|
|
@@ -867,6 +897,12 @@ class HarmonyAgent extends Agent {
|
|
|
867
897
|
uri
|
|
868
898
|
});
|
|
869
899
|
}
|
|
900
|
+
async terminate(uri) {
|
|
901
|
+
const action = this.wrapActionInActionSpace('Terminate');
|
|
902
|
+
return action({
|
|
903
|
+
uri
|
|
904
|
+
});
|
|
905
|
+
}
|
|
870
906
|
async runHdcShell(command) {
|
|
871
907
|
const action = this.wrapActionInActionSpace('RunHdcShell');
|
|
872
908
|
return action({
|
|
@@ -954,7 +990,8 @@ class HarmonyMidsceneTools extends BaseMidsceneTools {
|
|
|
954
990
|
const tools = new HarmonyMidsceneTools();
|
|
955
991
|
runToolsCLI(tools, 'midscene-harmony', {
|
|
956
992
|
stripPrefix: 'harmony_',
|
|
957
|
-
version: "1.6.3
|
|
993
|
+
version: "1.6.3",
|
|
994
|
+
extraCommands: createReportCliCommands()
|
|
958
995
|
}).catch((e)=>{
|
|
959
996
|
if (!(e instanceof CLIError)) console.error(e);
|
|
960
997
|
process.exit(e instanceof CLIError ? e.exitCode : 1);
|
package/dist/es/index.mjs
CHANGED
|
@@ -165,7 +165,8 @@ class HdcClient {
|
|
|
165
165
|
return names.find((n)=>n !== bundleName && n.endsWith('Ability') && !n.includes('Extension') && !n.includes('Service') && !n.includes('Form') && !n.includes('Dialog'));
|
|
166
166
|
}
|
|
167
167
|
async forceStop(bundleName) {
|
|
168
|
-
await this.shell(`aa force-stop ${bundleName}`);
|
|
168
|
+
const output = await this.shell(`aa force-stop ${bundleName}`);
|
|
169
|
+
if (output.includes('error:')) throw new Error(`Failed to force stop ${bundleName}: ${output.trim()}`);
|
|
169
170
|
}
|
|
170
171
|
async getScreenInfo() {
|
|
171
172
|
const stdout = await this.shell('hidumper -s RenderService -a screen');
|
|
@@ -445,6 +446,21 @@ class HarmonyDevice {
|
|
|
445
446
|
}
|
|
446
447
|
return this;
|
|
447
448
|
}
|
|
449
|
+
async terminate(uri) {
|
|
450
|
+
const bundlePart = uri.includes('/') ? uri.split('/')[0] : uri;
|
|
451
|
+
const resolved = this.resolvePackageName(bundlePart) ?? bundlePart;
|
|
452
|
+
const hdc = await this.getHdc();
|
|
453
|
+
try {
|
|
454
|
+
debugDevice(`Terminating app: ${resolved}`);
|
|
455
|
+
await hdc.forceStop(resolved);
|
|
456
|
+
debugDevice(`Successfully terminated: ${resolved}`);
|
|
457
|
+
} catch (error) {
|
|
458
|
+
debugDevice(`Error terminating ${resolved}: ${error}`);
|
|
459
|
+
throw new Error(`Failed to terminate ${resolved}: ${error.message}`, {
|
|
460
|
+
cause: error
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
}
|
|
448
464
|
async getScreenSize() {
|
|
449
465
|
if (this.cachedScreenSize) return this.cachedScreenSize;
|
|
450
466
|
const hdc = await this.getHdc();
|
|
@@ -752,6 +768,9 @@ const runHdcShellParamSchema = z.object({
|
|
|
752
768
|
const launchParamSchema = z.object({
|
|
753
769
|
uri: z.string().describe('App name, bundle name, or URL to launch. Prioritize using the exact bundle name or URL the user has provided. If none provided, use the accurate app name.')
|
|
754
770
|
});
|
|
771
|
+
const terminateParamSchema = z.object({
|
|
772
|
+
uri: z.string().describe('Bundle name or app name to terminate. Prioritize using the exact bundle name the user provided. If the bundle is unknown, use the accurate app name shown on screen, such as Settings or Music.')
|
|
773
|
+
});
|
|
755
774
|
const createPlatformActions = (device)=>({
|
|
756
775
|
RunHdcShell: defineAction({
|
|
757
776
|
name: 'RunHdcShell',
|
|
@@ -780,6 +799,16 @@ const createPlatformActions = (device)=>({
|
|
|
780
799
|
await device.launch(param.uri);
|
|
781
800
|
}
|
|
782
801
|
}),
|
|
802
|
+
Terminate: defineAction({
|
|
803
|
+
name: 'Terminate',
|
|
804
|
+
description: 'Terminate (force-stop) a HarmonyOS app by bundle name or mapped app name',
|
|
805
|
+
interfaceAlias: 'terminate',
|
|
806
|
+
paramSchema: terminateParamSchema,
|
|
807
|
+
call: async (param)=>{
|
|
808
|
+
if (!param.uri || '' === param.uri.trim()) throw new Error('Terminate requires a non-empty uri parameter');
|
|
809
|
+
await device.terminate(param.uri);
|
|
810
|
+
}
|
|
811
|
+
}),
|
|
783
812
|
HarmonyBackButton: defineAction({
|
|
784
813
|
name: 'HarmonyBackButton',
|
|
785
814
|
description: 'Trigger the system "back" operation on HarmonyOS devices',
|
|
@@ -825,7 +854,8 @@ const defaultAppNameMapping = {
|
|
|
825
854
|
Browser: 'com.huawei.hmos.browser',
|
|
826
855
|
应用市场: 'com.huawei.appmarket',
|
|
827
856
|
AppGallery: 'com.huawei.appmarket',
|
|
828
|
-
华为音乐: 'com.huawei.
|
|
857
|
+
华为音乐: 'com.huawei.hmsapp.music',
|
|
858
|
+
Music: 'com.huawei.hmsapp.music',
|
|
829
859
|
华为视频: 'com.huawei.hmos.video',
|
|
830
860
|
天气: 'com.huawei.hmos.weather',
|
|
831
861
|
Weather: 'com.huawei.hmos.weather',
|
|
@@ -872,6 +902,12 @@ class HarmonyAgent extends Agent {
|
|
|
872
902
|
uri
|
|
873
903
|
});
|
|
874
904
|
}
|
|
905
|
+
async terminate(uri) {
|
|
906
|
+
const action = this.wrapActionInActionSpace('Terminate');
|
|
907
|
+
return action({
|
|
908
|
+
uri
|
|
909
|
+
});
|
|
910
|
+
}
|
|
875
911
|
async runHdcShell(command) {
|
|
876
912
|
const action = this.wrapActionInActionSpace('RunHdcShell');
|
|
877
913
|
return action({
|
package/dist/es/mcp-server.mjs
CHANGED
|
@@ -33,7 +33,8 @@ const defaultAppNameMapping = {
|
|
|
33
33
|
Browser: 'com.huawei.hmos.browser',
|
|
34
34
|
应用市场: 'com.huawei.appmarket',
|
|
35
35
|
AppGallery: 'com.huawei.appmarket',
|
|
36
|
-
华为音乐: 'com.huawei.
|
|
36
|
+
华为音乐: 'com.huawei.hmsapp.music',
|
|
37
|
+
Music: 'com.huawei.hmsapp.music',
|
|
37
38
|
华为视频: 'com.huawei.hmos.video',
|
|
38
39
|
天气: 'com.huawei.hmos.weather',
|
|
39
40
|
Weather: 'com.huawei.hmos.weather',
|
|
@@ -192,7 +193,8 @@ class HdcClient {
|
|
|
192
193
|
return names.find((n)=>n !== bundleName && n.endsWith('Ability') && !n.includes('Extension') && !n.includes('Service') && !n.includes('Form') && !n.includes('Dialog'));
|
|
193
194
|
}
|
|
194
195
|
async forceStop(bundleName) {
|
|
195
|
-
await this.shell(`aa force-stop ${bundleName}`);
|
|
196
|
+
const output = await this.shell(`aa force-stop ${bundleName}`);
|
|
197
|
+
if (output.includes('error:')) throw new Error(`Failed to force stop ${bundleName}: ${output.trim()}`);
|
|
196
198
|
}
|
|
197
199
|
async getScreenInfo() {
|
|
198
200
|
const stdout = await this.shell('hidumper -s RenderService -a screen');
|
|
@@ -472,6 +474,21 @@ class HarmonyDevice {
|
|
|
472
474
|
}
|
|
473
475
|
return this;
|
|
474
476
|
}
|
|
477
|
+
async terminate(uri) {
|
|
478
|
+
const bundlePart = uri.includes('/') ? uri.split('/')[0] : uri;
|
|
479
|
+
const resolved = this.resolvePackageName(bundlePart) ?? bundlePart;
|
|
480
|
+
const hdc = await this.getHdc();
|
|
481
|
+
try {
|
|
482
|
+
debugDevice(`Terminating app: ${resolved}`);
|
|
483
|
+
await hdc.forceStop(resolved);
|
|
484
|
+
debugDevice(`Successfully terminated: ${resolved}`);
|
|
485
|
+
} catch (error) {
|
|
486
|
+
debugDevice(`Error terminating ${resolved}: ${error}`);
|
|
487
|
+
throw new Error(`Failed to terminate ${resolved}: ${error.message}`, {
|
|
488
|
+
cause: error
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
}
|
|
475
492
|
async getScreenSize() {
|
|
476
493
|
if (this.cachedScreenSize) return this.cachedScreenSize;
|
|
477
494
|
const hdc = await this.getHdc();
|
|
@@ -779,6 +796,9 @@ const runHdcShellParamSchema = z.object({
|
|
|
779
796
|
const launchParamSchema = z.object({
|
|
780
797
|
uri: z.string().describe('App name, bundle name, or URL to launch. Prioritize using the exact bundle name or URL the user has provided. If none provided, use the accurate app name.')
|
|
781
798
|
});
|
|
799
|
+
const terminateParamSchema = z.object({
|
|
800
|
+
uri: z.string().describe('Bundle name or app name to terminate. Prioritize using the exact bundle name the user provided. If the bundle is unknown, use the accurate app name shown on screen, such as Settings or Music.')
|
|
801
|
+
});
|
|
782
802
|
const createPlatformActions = (device)=>({
|
|
783
803
|
RunHdcShell: defineAction({
|
|
784
804
|
name: 'RunHdcShell',
|
|
@@ -807,6 +827,16 @@ const createPlatformActions = (device)=>({
|
|
|
807
827
|
await device.launch(param.uri);
|
|
808
828
|
}
|
|
809
829
|
}),
|
|
830
|
+
Terminate: defineAction({
|
|
831
|
+
name: 'Terminate',
|
|
832
|
+
description: 'Terminate (force-stop) a HarmonyOS app by bundle name or mapped app name',
|
|
833
|
+
interfaceAlias: 'terminate',
|
|
834
|
+
paramSchema: terminateParamSchema,
|
|
835
|
+
call: async (param)=>{
|
|
836
|
+
if (!param.uri || '' === param.uri.trim()) throw new Error('Terminate requires a non-empty uri parameter');
|
|
837
|
+
await device.terminate(param.uri);
|
|
838
|
+
}
|
|
839
|
+
}),
|
|
810
840
|
HarmonyBackButton: defineAction({
|
|
811
841
|
name: 'HarmonyBackButton',
|
|
812
842
|
description: 'Trigger the system "back" operation on HarmonyOS devices',
|
|
@@ -866,6 +896,12 @@ class HarmonyAgent extends Agent {
|
|
|
866
896
|
uri
|
|
867
897
|
});
|
|
868
898
|
}
|
|
899
|
+
async terminate(uri) {
|
|
900
|
+
const action = this.wrapActionInActionSpace('Terminate');
|
|
901
|
+
return action({
|
|
902
|
+
uri
|
|
903
|
+
});
|
|
904
|
+
}
|
|
869
905
|
async runHdcShell(command) {
|
|
870
906
|
const action = this.wrapActionInActionSpace('RunHdcShell');
|
|
871
907
|
return action({
|
|
@@ -957,7 +993,7 @@ class HarmonyMCPServer extends BaseMCPServer {
|
|
|
957
993
|
constructor(toolsManager){
|
|
958
994
|
super({
|
|
959
995
|
name: '@midscene/harmony-mcp',
|
|
960
|
-
version: "1.6.3
|
|
996
|
+
version: "1.6.3",
|
|
961
997
|
description: 'Control the HarmonyOS device using natural language commands'
|
|
962
998
|
}, toolsManager);
|
|
963
999
|
}
|
package/dist/lib/bin.js
CHANGED
|
@@ -53,7 +53,8 @@ const defaultAppNameMapping = {
|
|
|
53
53
|
Browser: 'com.huawei.hmos.browser',
|
|
54
54
|
应用市场: 'com.huawei.appmarket',
|
|
55
55
|
AppGallery: 'com.huawei.appmarket',
|
|
56
|
-
华为音乐: 'com.huawei.
|
|
56
|
+
华为音乐: 'com.huawei.hmsapp.music',
|
|
57
|
+
Music: 'com.huawei.hmsapp.music',
|
|
57
58
|
华为视频: 'com.huawei.hmos.video',
|
|
58
59
|
天气: 'com.huawei.hmos.weather',
|
|
59
60
|
Weather: 'com.huawei.hmos.weather',
|
|
@@ -222,7 +223,8 @@ class HdcClient {
|
|
|
222
223
|
return names.find((n)=>n !== bundleName && n.endsWith('Ability') && !n.includes('Extension') && !n.includes('Service') && !n.includes('Form') && !n.includes('Dialog'));
|
|
223
224
|
}
|
|
224
225
|
async forceStop(bundleName) {
|
|
225
|
-
await this.shell(`aa force-stop ${bundleName}`);
|
|
226
|
+
const output = await this.shell(`aa force-stop ${bundleName}`);
|
|
227
|
+
if (output.includes('error:')) throw new Error(`Failed to force stop ${bundleName}: ${output.trim()}`);
|
|
226
228
|
}
|
|
227
229
|
async getScreenInfo() {
|
|
228
230
|
const stdout = await this.shell('hidumper -s RenderService -a screen');
|
|
@@ -502,6 +504,21 @@ class device_HarmonyDevice {
|
|
|
502
504
|
}
|
|
503
505
|
return this;
|
|
504
506
|
}
|
|
507
|
+
async terminate(uri) {
|
|
508
|
+
const bundlePart = uri.includes('/') ? uri.split('/')[0] : uri;
|
|
509
|
+
const resolved = this.resolvePackageName(bundlePart) ?? bundlePart;
|
|
510
|
+
const hdc = await this.getHdc();
|
|
511
|
+
try {
|
|
512
|
+
debugDevice(`Terminating app: ${resolved}`);
|
|
513
|
+
await hdc.forceStop(resolved);
|
|
514
|
+
debugDevice(`Successfully terminated: ${resolved}`);
|
|
515
|
+
} catch (error) {
|
|
516
|
+
debugDevice(`Error terminating ${resolved}: ${error}`);
|
|
517
|
+
throw new Error(`Failed to terminate ${resolved}: ${error.message}`, {
|
|
518
|
+
cause: error
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
}
|
|
505
522
|
async getScreenSize() {
|
|
506
523
|
if (this.cachedScreenSize) return this.cachedScreenSize;
|
|
507
524
|
const hdc = await this.getHdc();
|
|
@@ -809,6 +826,9 @@ const runHdcShellParamSchema = core_namespaceObject.z.object({
|
|
|
809
826
|
const launchParamSchema = core_namespaceObject.z.object({
|
|
810
827
|
uri: core_namespaceObject.z.string().describe('App name, bundle name, or URL to launch. Prioritize using the exact bundle name or URL the user has provided. If none provided, use the accurate app name.')
|
|
811
828
|
});
|
|
829
|
+
const terminateParamSchema = core_namespaceObject.z.object({
|
|
830
|
+
uri: core_namespaceObject.z.string().describe('Bundle name or app name to terminate. Prioritize using the exact bundle name the user provided. If the bundle is unknown, use the accurate app name shown on screen, such as Settings or Music.')
|
|
831
|
+
});
|
|
812
832
|
const createPlatformActions = (device)=>({
|
|
813
833
|
RunHdcShell: (0, device_namespaceObject.defineAction)({
|
|
814
834
|
name: 'RunHdcShell',
|
|
@@ -837,6 +857,16 @@ const createPlatformActions = (device)=>({
|
|
|
837
857
|
await device.launch(param.uri);
|
|
838
858
|
}
|
|
839
859
|
}),
|
|
860
|
+
Terminate: (0, device_namespaceObject.defineAction)({
|
|
861
|
+
name: 'Terminate',
|
|
862
|
+
description: 'Terminate (force-stop) a HarmonyOS app by bundle name or mapped app name',
|
|
863
|
+
interfaceAlias: 'terminate',
|
|
864
|
+
paramSchema: terminateParamSchema,
|
|
865
|
+
call: async (param)=>{
|
|
866
|
+
if (!param.uri || '' === param.uri.trim()) throw new Error('Terminate requires a non-empty uri parameter');
|
|
867
|
+
await device.terminate(param.uri);
|
|
868
|
+
}
|
|
869
|
+
}),
|
|
840
870
|
HarmonyBackButton: (0, device_namespaceObject.defineAction)({
|
|
841
871
|
name: 'HarmonyBackButton',
|
|
842
872
|
description: 'Trigger the system "back" operation on HarmonyOS devices',
|
|
@@ -896,6 +926,12 @@ class HarmonyAgent extends agent_namespaceObject.Agent {
|
|
|
896
926
|
uri
|
|
897
927
|
});
|
|
898
928
|
}
|
|
929
|
+
async terminate(uri) {
|
|
930
|
+
const action = this.wrapActionInActionSpace('Terminate');
|
|
931
|
+
return action({
|
|
932
|
+
uri
|
|
933
|
+
});
|
|
934
|
+
}
|
|
899
935
|
async runHdcShell(command) {
|
|
900
936
|
const action = this.wrapActionInActionSpace('RunHdcShell');
|
|
901
937
|
return action({
|
package/dist/lib/cli.js
CHANGED
|
@@ -21,8 +21,8 @@ var __webpack_require__ = {};
|
|
|
21
21
|
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
22
22
|
})();
|
|
23
23
|
var __webpack_exports__ = {};
|
|
24
|
-
const cli_namespaceObject = require("@midscene/shared/cli");
|
|
25
24
|
const core_namespaceObject = require("@midscene/core");
|
|
25
|
+
const cli_namespaceObject = require("@midscene/shared/cli");
|
|
26
26
|
const logger_namespaceObject = require("@midscene/shared/logger");
|
|
27
27
|
const mcp_namespaceObject = require("@midscene/shared/mcp");
|
|
28
28
|
const agent_namespaceObject = require("@midscene/core/agent");
|
|
@@ -50,7 +50,8 @@ const defaultAppNameMapping = {
|
|
|
50
50
|
Browser: 'com.huawei.hmos.browser',
|
|
51
51
|
应用市场: 'com.huawei.appmarket',
|
|
52
52
|
AppGallery: 'com.huawei.appmarket',
|
|
53
|
-
华为音乐: 'com.huawei.
|
|
53
|
+
华为音乐: 'com.huawei.hmsapp.music',
|
|
54
|
+
Music: 'com.huawei.hmsapp.music',
|
|
54
55
|
华为视频: 'com.huawei.hmos.video',
|
|
55
56
|
天气: 'com.huawei.hmos.weather',
|
|
56
57
|
Weather: 'com.huawei.hmos.weather',
|
|
@@ -218,7 +219,8 @@ class HdcClient {
|
|
|
218
219
|
return names.find((n)=>n !== bundleName && n.endsWith('Ability') && !n.includes('Extension') && !n.includes('Service') && !n.includes('Form') && !n.includes('Dialog'));
|
|
219
220
|
}
|
|
220
221
|
async forceStop(bundleName) {
|
|
221
|
-
await this.shell(`aa force-stop ${bundleName}`);
|
|
222
|
+
const output = await this.shell(`aa force-stop ${bundleName}`);
|
|
223
|
+
if (output.includes('error:')) throw new Error(`Failed to force stop ${bundleName}: ${output.trim()}`);
|
|
222
224
|
}
|
|
223
225
|
async getScreenInfo() {
|
|
224
226
|
const stdout = await this.shell('hidumper -s RenderService -a screen');
|
|
@@ -498,6 +500,21 @@ class HarmonyDevice {
|
|
|
498
500
|
}
|
|
499
501
|
return this;
|
|
500
502
|
}
|
|
503
|
+
async terminate(uri) {
|
|
504
|
+
const bundlePart = uri.includes('/') ? uri.split('/')[0] : uri;
|
|
505
|
+
const resolved = this.resolvePackageName(bundlePart) ?? bundlePart;
|
|
506
|
+
const hdc = await this.getHdc();
|
|
507
|
+
try {
|
|
508
|
+
debugDevice(`Terminating app: ${resolved}`);
|
|
509
|
+
await hdc.forceStop(resolved);
|
|
510
|
+
debugDevice(`Successfully terminated: ${resolved}`);
|
|
511
|
+
} catch (error) {
|
|
512
|
+
debugDevice(`Error terminating ${resolved}: ${error}`);
|
|
513
|
+
throw new Error(`Failed to terminate ${resolved}: ${error.message}`, {
|
|
514
|
+
cause: error
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
}
|
|
501
518
|
async getScreenSize() {
|
|
502
519
|
if (this.cachedScreenSize) return this.cachedScreenSize;
|
|
503
520
|
const hdc = await this.getHdc();
|
|
@@ -805,6 +822,9 @@ const runHdcShellParamSchema = core_namespaceObject.z.object({
|
|
|
805
822
|
const launchParamSchema = core_namespaceObject.z.object({
|
|
806
823
|
uri: core_namespaceObject.z.string().describe('App name, bundle name, or URL to launch. Prioritize using the exact bundle name or URL the user has provided. If none provided, use the accurate app name.')
|
|
807
824
|
});
|
|
825
|
+
const terminateParamSchema = core_namespaceObject.z.object({
|
|
826
|
+
uri: core_namespaceObject.z.string().describe('Bundle name or app name to terminate. Prioritize using the exact bundle name the user provided. If the bundle is unknown, use the accurate app name shown on screen, such as Settings or Music.')
|
|
827
|
+
});
|
|
808
828
|
const createPlatformActions = (device)=>({
|
|
809
829
|
RunHdcShell: (0, device_namespaceObject.defineAction)({
|
|
810
830
|
name: 'RunHdcShell',
|
|
@@ -833,6 +853,16 @@ const createPlatformActions = (device)=>({
|
|
|
833
853
|
await device.launch(param.uri);
|
|
834
854
|
}
|
|
835
855
|
}),
|
|
856
|
+
Terminate: (0, device_namespaceObject.defineAction)({
|
|
857
|
+
name: 'Terminate',
|
|
858
|
+
description: 'Terminate (force-stop) a HarmonyOS app by bundle name or mapped app name',
|
|
859
|
+
interfaceAlias: 'terminate',
|
|
860
|
+
paramSchema: terminateParamSchema,
|
|
861
|
+
call: async (param)=>{
|
|
862
|
+
if (!param.uri || '' === param.uri.trim()) throw new Error('Terminate requires a non-empty uri parameter');
|
|
863
|
+
await device.terminate(param.uri);
|
|
864
|
+
}
|
|
865
|
+
}),
|
|
836
866
|
HarmonyBackButton: (0, device_namespaceObject.defineAction)({
|
|
837
867
|
name: 'HarmonyBackButton',
|
|
838
868
|
description: 'Trigger the system "back" operation on HarmonyOS devices',
|
|
@@ -892,6 +922,12 @@ class HarmonyAgent extends agent_namespaceObject.Agent {
|
|
|
892
922
|
uri
|
|
893
923
|
});
|
|
894
924
|
}
|
|
925
|
+
async terminate(uri) {
|
|
926
|
+
const action = this.wrapActionInActionSpace('Terminate');
|
|
927
|
+
return action({
|
|
928
|
+
uri
|
|
929
|
+
});
|
|
930
|
+
}
|
|
895
931
|
async runHdcShell(command) {
|
|
896
932
|
const action = this.wrapActionInActionSpace('RunHdcShell');
|
|
897
933
|
return action({
|
|
@@ -979,7 +1015,8 @@ class HarmonyMidsceneTools extends mcp_namespaceObject.BaseMidsceneTools {
|
|
|
979
1015
|
const tools = new HarmonyMidsceneTools();
|
|
980
1016
|
(0, cli_namespaceObject.runToolsCLI)(tools, 'midscene-harmony', {
|
|
981
1017
|
stripPrefix: 'harmony_',
|
|
982
|
-
version: "1.6.3
|
|
1018
|
+
version: "1.6.3",
|
|
1019
|
+
extraCommands: (0, core_namespaceObject.createReportCliCommands)()
|
|
983
1020
|
}).catch((e)=>{
|
|
984
1021
|
if (!(e instanceof cli_namespaceObject.CLIError)) console.error(e);
|
|
985
1022
|
process.exit(e instanceof cli_namespaceObject.CLIError ? e.exitCode : 1);
|
package/dist/lib/index.js
CHANGED
|
@@ -202,7 +202,8 @@ class HdcClient {
|
|
|
202
202
|
return names.find((n)=>n !== bundleName && n.endsWith('Ability') && !n.includes('Extension') && !n.includes('Service') && !n.includes('Form') && !n.includes('Dialog'));
|
|
203
203
|
}
|
|
204
204
|
async forceStop(bundleName) {
|
|
205
|
-
await this.shell(`aa force-stop ${bundleName}`);
|
|
205
|
+
const output = await this.shell(`aa force-stop ${bundleName}`);
|
|
206
|
+
if (output.includes('error:')) throw new Error(`Failed to force stop ${bundleName}: ${output.trim()}`);
|
|
206
207
|
}
|
|
207
208
|
async getScreenInfo() {
|
|
208
209
|
const stdout = await this.shell('hidumper -s RenderService -a screen');
|
|
@@ -482,6 +483,21 @@ class HarmonyDevice {
|
|
|
482
483
|
}
|
|
483
484
|
return this;
|
|
484
485
|
}
|
|
486
|
+
async terminate(uri) {
|
|
487
|
+
const bundlePart = uri.includes('/') ? uri.split('/')[0] : uri;
|
|
488
|
+
const resolved = this.resolvePackageName(bundlePart) ?? bundlePart;
|
|
489
|
+
const hdc = await this.getHdc();
|
|
490
|
+
try {
|
|
491
|
+
debugDevice(`Terminating app: ${resolved}`);
|
|
492
|
+
await hdc.forceStop(resolved);
|
|
493
|
+
debugDevice(`Successfully terminated: ${resolved}`);
|
|
494
|
+
} catch (error) {
|
|
495
|
+
debugDevice(`Error terminating ${resolved}: ${error}`);
|
|
496
|
+
throw new Error(`Failed to terminate ${resolved}: ${error.message}`, {
|
|
497
|
+
cause: error
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
}
|
|
485
501
|
async getScreenSize() {
|
|
486
502
|
if (this.cachedScreenSize) return this.cachedScreenSize;
|
|
487
503
|
const hdc = await this.getHdc();
|
|
@@ -789,6 +805,9 @@ const runHdcShellParamSchema = core_namespaceObject.z.object({
|
|
|
789
805
|
const launchParamSchema = core_namespaceObject.z.object({
|
|
790
806
|
uri: core_namespaceObject.z.string().describe('App name, bundle name, or URL to launch. Prioritize using the exact bundle name or URL the user has provided. If none provided, use the accurate app name.')
|
|
791
807
|
});
|
|
808
|
+
const terminateParamSchema = core_namespaceObject.z.object({
|
|
809
|
+
uri: core_namespaceObject.z.string().describe('Bundle name or app name to terminate. Prioritize using the exact bundle name the user provided. If the bundle is unknown, use the accurate app name shown on screen, such as Settings or Music.')
|
|
810
|
+
});
|
|
792
811
|
const createPlatformActions = (device)=>({
|
|
793
812
|
RunHdcShell: (0, device_namespaceObject.defineAction)({
|
|
794
813
|
name: 'RunHdcShell',
|
|
@@ -817,6 +836,16 @@ const createPlatformActions = (device)=>({
|
|
|
817
836
|
await device.launch(param.uri);
|
|
818
837
|
}
|
|
819
838
|
}),
|
|
839
|
+
Terminate: (0, device_namespaceObject.defineAction)({
|
|
840
|
+
name: 'Terminate',
|
|
841
|
+
description: 'Terminate (force-stop) a HarmonyOS app by bundle name or mapped app name',
|
|
842
|
+
interfaceAlias: 'terminate',
|
|
843
|
+
paramSchema: terminateParamSchema,
|
|
844
|
+
call: async (param)=>{
|
|
845
|
+
if (!param.uri || '' === param.uri.trim()) throw new Error('Terminate requires a non-empty uri parameter');
|
|
846
|
+
await device.terminate(param.uri);
|
|
847
|
+
}
|
|
848
|
+
}),
|
|
820
849
|
HarmonyBackButton: (0, device_namespaceObject.defineAction)({
|
|
821
850
|
name: 'HarmonyBackButton',
|
|
822
851
|
description: 'Trigger the system "back" operation on HarmonyOS devices',
|
|
@@ -863,7 +892,8 @@ const defaultAppNameMapping = {
|
|
|
863
892
|
Browser: 'com.huawei.hmos.browser',
|
|
864
893
|
应用市场: 'com.huawei.appmarket',
|
|
865
894
|
AppGallery: 'com.huawei.appmarket',
|
|
866
|
-
华为音乐: 'com.huawei.
|
|
895
|
+
华为音乐: 'com.huawei.hmsapp.music',
|
|
896
|
+
Music: 'com.huawei.hmsapp.music',
|
|
867
897
|
华为视频: 'com.huawei.hmos.video',
|
|
868
898
|
天气: 'com.huawei.hmos.weather',
|
|
869
899
|
Weather: 'com.huawei.hmos.weather',
|
|
@@ -910,6 +940,12 @@ class HarmonyAgent extends agent_namespaceObject.Agent {
|
|
|
910
940
|
uri
|
|
911
941
|
});
|
|
912
942
|
}
|
|
943
|
+
async terminate(uri) {
|
|
944
|
+
const action = this.wrapActionInActionSpace('Terminate');
|
|
945
|
+
return action({
|
|
946
|
+
uri
|
|
947
|
+
});
|
|
948
|
+
}
|
|
913
949
|
async runHdcShell(command) {
|
|
914
950
|
const action = this.wrapActionInActionSpace('RunHdcShell');
|
|
915
951
|
return action({
|