@midscene/harmony 1.6.3-beta-20260403070857.0 → 1.6.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/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.hmos.music',
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.hmos.music',
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-beta-20260403070857.0"
993
+ version: "1.6.4",
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.hmos.music',
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({
@@ -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.hmos.music',
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-beta-20260403070857.0",
996
+ version: "1.6.4",
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.hmos.music',
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.hmos.music',
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-beta-20260403070857.0"
1018
+ version: "1.6.4",
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.hmos.music',
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({