@midscene/harmony 1.5.4-beta-20260310084708.0 → 1.5.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
@@ -218,7 +218,7 @@ class HdcClient {
218
218
  width: Number.parseInt(renderSizeMatch[1], 10),
219
219
  height: Number.parseInt(renderSizeMatch[2], 10)
220
220
  };
221
- const displayStdout = await this.shell('hidumper -s DisplayManagerService -a -a');
221
+ const displayStdout = await this.shell('hidumper -s DisplayManagerService -a');
222
222
  const displayMatch = displayStdout.match(/activeModes.*?(\d{3,5}),\s*(\d{3,5})/);
223
223
  if (displayMatch) return {
224
224
  width: Number.parseInt(displayMatch[1], 10),
@@ -250,6 +250,15 @@ function device_define_property(obj, key, value) {
250
250
  else obj[key] = value;
251
251
  return obj;
252
252
  }
253
+ const harmonyInputParamSchema = z.object({
254
+ value: z.string().describe('The text to input. Provide the final content for replace/append modes, or an empty string when using clear mode to remove existing text.'),
255
+ mode: z.preprocess((val)=>'append' === val ? 'typeOnly' : val, z["enum"]([
256
+ 'replace',
257
+ 'clear',
258
+ 'typeOnly'
259
+ ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - attempt to clear the field (limited support on HarmonyOS).')),
260
+ locate: getMidsceneLocationSchema().describe('The input field to be filled').optional()
261
+ });
253
262
  const defaultScrollUntilTimes = 10;
254
263
  const defaultSwipeSpeed = 600;
255
264
  const defaultFastSwipeSpeed = 2000;
@@ -304,15 +313,13 @@ class device_HarmonyDevice {
304
313
  name: 'Input',
305
314
  description: 'Input text into the input field',
306
315
  interfaceAlias: 'aiInput',
307
- paramSchema: z.object({
308
- value: z.string().describe('The text to input. Provide the final content for replace/append modes, or an empty string when using clear mode to remove existing text.'),
309
- mode: z.preprocess((val)=>'append' === val ? 'typeOnly' : val, z["enum"]([
310
- 'replace',
311
- 'clear',
312
- 'typeOnly'
313
- ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - attempt to clear the field (limited support on HarmonyOS).')),
314
- locate: getMidsceneLocationSchema().describe('The input field to be filled').optional()
315
- }),
316
+ paramSchema: harmonyInputParamSchema,
317
+ sample: {
318
+ value: 'test@example.com',
319
+ locate: {
320
+ prompt: 'the email input field'
321
+ }
322
+ },
316
323
  call: async (param)=>{
317
324
  const element = param.locate;
318
325
  if ('clear' === param.mode) return void await this.clearInput(element);
@@ -373,6 +380,11 @@ class device_HarmonyDevice {
373
380
  duration: z.number().optional().describe('The duration of the long press in milliseconds'),
374
381
  locate: getMidsceneLocationSchema().describe('The element to be long pressed')
375
382
  }),
383
+ sample: {
384
+ locate: {
385
+ prompt: 'the message bubble'
386
+ }
387
+ },
376
388
  call: async (param)=>{
377
389
  const element = param.locate;
378
390
  if (!element) throw new Error('LongPress requires an element to be located');
@@ -774,6 +786,9 @@ const createPlatformActions = (device)=>({
774
786
  description: 'Execute HDC shell command on HarmonyOS device',
775
787
  interfaceAlias: 'runHdcShell',
776
788
  paramSchema: runHdcShellParamSchema,
789
+ sample: {
790
+ command: 'hidumper -s WindowManagerService -a'
791
+ },
777
792
  call: async (param)=>{
778
793
  if (!param.command || '' === param.command.trim()) throw new Error('RunHdcShell requires a non-empty command parameter');
779
794
  const hdc = await device.getHdc();
@@ -785,6 +800,9 @@ const createPlatformActions = (device)=>({
785
800
  description: 'Launch a HarmonyOS app or URL',
786
801
  interfaceAlias: 'launch',
787
802
  paramSchema: launchParamSchema,
803
+ sample: {
804
+ uri: 'com.example.app'
805
+ },
788
806
  call: async (param)=>{
789
807
  if (!param.uri || '' === param.uri.trim()) throw new Error('Launch requires a non-empty uri parameter');
790
808
  await device.launch(param.uri);
package/dist/es/cli.mjs CHANGED
@@ -215,7 +215,7 @@ class HdcClient {
215
215
  width: Number.parseInt(renderSizeMatch[1], 10),
216
216
  height: Number.parseInt(renderSizeMatch[2], 10)
217
217
  };
218
- const displayStdout = await this.shell('hidumper -s DisplayManagerService -a -a');
218
+ const displayStdout = await this.shell('hidumper -s DisplayManagerService -a');
219
219
  const displayMatch = displayStdout.match(/activeModes.*?(\d{3,5}),\s*(\d{3,5})/);
220
220
  if (displayMatch) return {
221
221
  width: Number.parseInt(displayMatch[1], 10),
@@ -247,6 +247,15 @@ function device_define_property(obj, key, value) {
247
247
  else obj[key] = value;
248
248
  return obj;
249
249
  }
250
+ const harmonyInputParamSchema = z.object({
251
+ value: z.string().describe('The text to input. Provide the final content for replace/append modes, or an empty string when using clear mode to remove existing text.'),
252
+ mode: z.preprocess((val)=>'append' === val ? 'typeOnly' : val, z["enum"]([
253
+ 'replace',
254
+ 'clear',
255
+ 'typeOnly'
256
+ ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - attempt to clear the field (limited support on HarmonyOS).')),
257
+ locate: getMidsceneLocationSchema().describe('The input field to be filled').optional()
258
+ });
250
259
  const defaultScrollUntilTimes = 10;
251
260
  const defaultSwipeSpeed = 600;
252
261
  const defaultFastSwipeSpeed = 2000;
@@ -301,15 +310,13 @@ class HarmonyDevice {
301
310
  name: 'Input',
302
311
  description: 'Input text into the input field',
303
312
  interfaceAlias: 'aiInput',
304
- paramSchema: z.object({
305
- value: z.string().describe('The text to input. Provide the final content for replace/append modes, or an empty string when using clear mode to remove existing text.'),
306
- mode: z.preprocess((val)=>'append' === val ? 'typeOnly' : val, z["enum"]([
307
- 'replace',
308
- 'clear',
309
- 'typeOnly'
310
- ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - attempt to clear the field (limited support on HarmonyOS).')),
311
- locate: getMidsceneLocationSchema().describe('The input field to be filled').optional()
312
- }),
313
+ paramSchema: harmonyInputParamSchema,
314
+ sample: {
315
+ value: 'test@example.com',
316
+ locate: {
317
+ prompt: 'the email input field'
318
+ }
319
+ },
313
320
  call: async (param)=>{
314
321
  const element = param.locate;
315
322
  if ('clear' === param.mode) return void await this.clearInput(element);
@@ -370,6 +377,11 @@ class HarmonyDevice {
370
377
  duration: z.number().optional().describe('The duration of the long press in milliseconds'),
371
378
  locate: getMidsceneLocationSchema().describe('The element to be long pressed')
372
379
  }),
380
+ sample: {
381
+ locate: {
382
+ prompt: 'the message bubble'
383
+ }
384
+ },
373
385
  call: async (param)=>{
374
386
  const element = param.locate;
375
387
  if (!element) throw new Error('LongPress requires an element to be located');
@@ -771,6 +783,9 @@ const createPlatformActions = (device)=>({
771
783
  description: 'Execute HDC shell command on HarmonyOS device',
772
784
  interfaceAlias: 'runHdcShell',
773
785
  paramSchema: runHdcShellParamSchema,
786
+ sample: {
787
+ command: 'hidumper -s WindowManagerService -a'
788
+ },
774
789
  call: async (param)=>{
775
790
  if (!param.command || '' === param.command.trim()) throw new Error('RunHdcShell requires a non-empty command parameter');
776
791
  const hdc = await device.getHdc();
@@ -782,6 +797,9 @@ const createPlatformActions = (device)=>({
782
797
  description: 'Launch a HarmonyOS app or URL',
783
798
  interfaceAlias: 'launch',
784
799
  paramSchema: launchParamSchema,
800
+ sample: {
801
+ uri: 'com.example.app'
802
+ },
785
803
  call: async (param)=>{
786
804
  if (!param.uri || '' === param.uri.trim()) throw new Error('Launch requires a non-empty uri parameter');
787
805
  await device.launch(param.uri);
@@ -933,7 +951,7 @@ class HarmonyMidsceneTools extends BaseMidsceneTools {
933
951
  const tools = new HarmonyMidsceneTools();
934
952
  runToolsCLI(tools, 'midscene-harmony', {
935
953
  stripPrefix: 'harmony_',
936
- version: "1.5.4-beta-20260310084708.0"
954
+ version: "1.5.4"
937
955
  }).catch((e)=>{
938
956
  if (!(e instanceof CLIError)) console.error(e);
939
957
  process.exit(e instanceof CLIError ? e.exitCode : 1);
package/dist/es/index.mjs CHANGED
@@ -182,7 +182,7 @@ class HdcClient {
182
182
  width: Number.parseInt(renderSizeMatch[1], 10),
183
183
  height: Number.parseInt(renderSizeMatch[2], 10)
184
184
  };
185
- const displayStdout = await this.shell('hidumper -s DisplayManagerService -a -a');
185
+ const displayStdout = await this.shell('hidumper -s DisplayManagerService -a');
186
186
  const displayMatch = displayStdout.match(/activeModes.*?(\d{3,5}),\s*(\d{3,5})/);
187
187
  if (displayMatch) return {
188
188
  width: Number.parseInt(displayMatch[1], 10),
@@ -214,6 +214,15 @@ function device_define_property(obj, key, value) {
214
214
  else obj[key] = value;
215
215
  return obj;
216
216
  }
217
+ const harmonyInputParamSchema = z.object({
218
+ value: z.string().describe('The text to input. Provide the final content for replace/append modes, or an empty string when using clear mode to remove existing text.'),
219
+ mode: z.preprocess((val)=>'append' === val ? 'typeOnly' : val, z["enum"]([
220
+ 'replace',
221
+ 'clear',
222
+ 'typeOnly'
223
+ ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - attempt to clear the field (limited support on HarmonyOS).')),
224
+ locate: getMidsceneLocationSchema().describe('The input field to be filled').optional()
225
+ });
217
226
  const defaultScrollUntilTimes = 10;
218
227
  const defaultSwipeSpeed = 600;
219
228
  const defaultFastSwipeSpeed = 2000;
@@ -268,15 +277,13 @@ class HarmonyDevice {
268
277
  name: 'Input',
269
278
  description: 'Input text into the input field',
270
279
  interfaceAlias: 'aiInput',
271
- paramSchema: z.object({
272
- value: z.string().describe('The text to input. Provide the final content for replace/append modes, or an empty string when using clear mode to remove existing text.'),
273
- mode: z.preprocess((val)=>'append' === val ? 'typeOnly' : val, z["enum"]([
274
- 'replace',
275
- 'clear',
276
- 'typeOnly'
277
- ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - attempt to clear the field (limited support on HarmonyOS).')),
278
- locate: getMidsceneLocationSchema().describe('The input field to be filled').optional()
279
- }),
280
+ paramSchema: harmonyInputParamSchema,
281
+ sample: {
282
+ value: 'test@example.com',
283
+ locate: {
284
+ prompt: 'the email input field'
285
+ }
286
+ },
280
287
  call: async (param)=>{
281
288
  const element = param.locate;
282
289
  if ('clear' === param.mode) return void await this.clearInput(element);
@@ -337,6 +344,11 @@ class HarmonyDevice {
337
344
  duration: z.number().optional().describe('The duration of the long press in milliseconds'),
338
345
  locate: getMidsceneLocationSchema().describe('The element to be long pressed')
339
346
  }),
347
+ sample: {
348
+ locate: {
349
+ prompt: 'the message bubble'
350
+ }
351
+ },
340
352
  call: async (param)=>{
341
353
  const element = param.locate;
342
354
  if (!element) throw new Error('LongPress requires an element to be located');
@@ -738,6 +750,9 @@ const createPlatformActions = (device)=>({
738
750
  description: 'Execute HDC shell command on HarmonyOS device',
739
751
  interfaceAlias: 'runHdcShell',
740
752
  paramSchema: runHdcShellParamSchema,
753
+ sample: {
754
+ command: 'hidumper -s WindowManagerService -a'
755
+ },
741
756
  call: async (param)=>{
742
757
  if (!param.command || '' === param.command.trim()) throw new Error('RunHdcShell requires a non-empty command parameter');
743
758
  const hdc = await device.getHdc();
@@ -749,6 +764,9 @@ const createPlatformActions = (device)=>({
749
764
  description: 'Launch a HarmonyOS app or URL',
750
765
  interfaceAlias: 'launch',
751
766
  paramSchema: launchParamSchema,
767
+ sample: {
768
+ uri: 'com.example.app'
769
+ },
752
770
  call: async (param)=>{
753
771
  if (!param.uri || '' === param.uri.trim()) throw new Error('Launch requires a non-empty uri parameter');
754
772
  await device.launch(param.uri);
@@ -214,7 +214,7 @@ class HdcClient {
214
214
  width: Number.parseInt(renderSizeMatch[1], 10),
215
215
  height: Number.parseInt(renderSizeMatch[2], 10)
216
216
  };
217
- const displayStdout = await this.shell('hidumper -s DisplayManagerService -a -a');
217
+ const displayStdout = await this.shell('hidumper -s DisplayManagerService -a');
218
218
  const displayMatch = displayStdout.match(/activeModes.*?(\d{3,5}),\s*(\d{3,5})/);
219
219
  if (displayMatch) return {
220
220
  width: Number.parseInt(displayMatch[1], 10),
@@ -246,6 +246,15 @@ function device_define_property(obj, key, value) {
246
246
  else obj[key] = value;
247
247
  return obj;
248
248
  }
249
+ const harmonyInputParamSchema = z.object({
250
+ value: z.string().describe('The text to input. Provide the final content for replace/append modes, or an empty string when using clear mode to remove existing text.'),
251
+ mode: z.preprocess((val)=>'append' === val ? 'typeOnly' : val, z["enum"]([
252
+ 'replace',
253
+ 'clear',
254
+ 'typeOnly'
255
+ ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - attempt to clear the field (limited support on HarmonyOS).')),
256
+ locate: getMidsceneLocationSchema().describe('The input field to be filled').optional()
257
+ });
249
258
  const defaultScrollUntilTimes = 10;
250
259
  const defaultSwipeSpeed = 600;
251
260
  const defaultFastSwipeSpeed = 2000;
@@ -300,15 +309,13 @@ class HarmonyDevice {
300
309
  name: 'Input',
301
310
  description: 'Input text into the input field',
302
311
  interfaceAlias: 'aiInput',
303
- paramSchema: z.object({
304
- value: z.string().describe('The text to input. Provide the final content for replace/append modes, or an empty string when using clear mode to remove existing text.'),
305
- mode: z.preprocess((val)=>'append' === val ? 'typeOnly' : val, z["enum"]([
306
- 'replace',
307
- 'clear',
308
- 'typeOnly'
309
- ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - attempt to clear the field (limited support on HarmonyOS).')),
310
- locate: getMidsceneLocationSchema().describe('The input field to be filled').optional()
311
- }),
312
+ paramSchema: harmonyInputParamSchema,
313
+ sample: {
314
+ value: 'test@example.com',
315
+ locate: {
316
+ prompt: 'the email input field'
317
+ }
318
+ },
312
319
  call: async (param)=>{
313
320
  const element = param.locate;
314
321
  if ('clear' === param.mode) return void await this.clearInput(element);
@@ -369,6 +376,11 @@ class HarmonyDevice {
369
376
  duration: z.number().optional().describe('The duration of the long press in milliseconds'),
370
377
  locate: getMidsceneLocationSchema().describe('The element to be long pressed')
371
378
  }),
379
+ sample: {
380
+ locate: {
381
+ prompt: 'the message bubble'
382
+ }
383
+ },
372
384
  call: async (param)=>{
373
385
  const element = param.locate;
374
386
  if (!element) throw new Error('LongPress requires an element to be located');
@@ -770,6 +782,9 @@ const createPlatformActions = (device)=>({
770
782
  description: 'Execute HDC shell command on HarmonyOS device',
771
783
  interfaceAlias: 'runHdcShell',
772
784
  paramSchema: runHdcShellParamSchema,
785
+ sample: {
786
+ command: 'hidumper -s WindowManagerService -a'
787
+ },
773
788
  call: async (param)=>{
774
789
  if (!param.command || '' === param.command.trim()) throw new Error('RunHdcShell requires a non-empty command parameter');
775
790
  const hdc = await device.getHdc();
@@ -781,6 +796,9 @@ const createPlatformActions = (device)=>({
781
796
  description: 'Launch a HarmonyOS app or URL',
782
797
  interfaceAlias: 'launch',
783
798
  paramSchema: launchParamSchema,
799
+ sample: {
800
+ uri: 'com.example.app'
801
+ },
784
802
  call: async (param)=>{
785
803
  if (!param.uri || '' === param.uri.trim()) throw new Error('Launch requires a non-empty uri parameter');
786
804
  await device.launch(param.uri);
@@ -936,7 +954,7 @@ class HarmonyMCPServer extends BaseMCPServer {
936
954
  constructor(toolsManager){
937
955
  super({
938
956
  name: '@midscene/harmony-mcp',
939
- version: "1.5.4-beta-20260310084708.0",
957
+ version: "1.5.4",
940
958
  description: 'Control the HarmonyOS device using natural language commands'
941
959
  }, toolsManager);
942
960
  }
package/dist/lib/bin.js CHANGED
@@ -244,7 +244,7 @@ class HdcClient {
244
244
  width: Number.parseInt(renderSizeMatch[1], 10),
245
245
  height: Number.parseInt(renderSizeMatch[2], 10)
246
246
  };
247
- const displayStdout = await this.shell('hidumper -s DisplayManagerService -a -a');
247
+ const displayStdout = await this.shell('hidumper -s DisplayManagerService -a');
248
248
  const displayMatch = displayStdout.match(/activeModes.*?(\d{3,5}),\s*(\d{3,5})/);
249
249
  if (displayMatch) return {
250
250
  width: Number.parseInt(displayMatch[1], 10),
@@ -276,6 +276,15 @@ function device_define_property(obj, key, value) {
276
276
  else obj[key] = value;
277
277
  return obj;
278
278
  }
279
+ const harmonyInputParamSchema = core_namespaceObject.z.object({
280
+ value: core_namespaceObject.z.string().describe('The text to input. Provide the final content for replace/append modes, or an empty string when using clear mode to remove existing text.'),
281
+ mode: core_namespaceObject.z.preprocess((val)=>'append' === val ? 'typeOnly' : val, core_namespaceObject.z["enum"]([
282
+ 'replace',
283
+ 'clear',
284
+ 'typeOnly'
285
+ ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - attempt to clear the field (limited support on HarmonyOS).')),
286
+ locate: (0, core_namespaceObject.getMidsceneLocationSchema)().describe('The input field to be filled').optional()
287
+ });
279
288
  const defaultScrollUntilTimes = 10;
280
289
  const defaultSwipeSpeed = 600;
281
290
  const defaultFastSwipeSpeed = 2000;
@@ -330,15 +339,13 @@ class device_HarmonyDevice {
330
339
  name: 'Input',
331
340
  description: 'Input text into the input field',
332
341
  interfaceAlias: 'aiInput',
333
- paramSchema: core_namespaceObject.z.object({
334
- value: core_namespaceObject.z.string().describe('The text to input. Provide the final content for replace/append modes, or an empty string when using clear mode to remove existing text.'),
335
- mode: core_namespaceObject.z.preprocess((val)=>'append' === val ? 'typeOnly' : val, core_namespaceObject.z["enum"]([
336
- 'replace',
337
- 'clear',
338
- 'typeOnly'
339
- ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - attempt to clear the field (limited support on HarmonyOS).')),
340
- locate: (0, core_namespaceObject.getMidsceneLocationSchema)().describe('The input field to be filled').optional()
341
- }),
342
+ paramSchema: harmonyInputParamSchema,
343
+ sample: {
344
+ value: 'test@example.com',
345
+ locate: {
346
+ prompt: 'the email input field'
347
+ }
348
+ },
342
349
  call: async (param)=>{
343
350
  const element = param.locate;
344
351
  if ('clear' === param.mode) return void await this.clearInput(element);
@@ -399,6 +406,11 @@ class device_HarmonyDevice {
399
406
  duration: core_namespaceObject.z.number().optional().describe('The duration of the long press in milliseconds'),
400
407
  locate: (0, core_namespaceObject.getMidsceneLocationSchema)().describe('The element to be long pressed')
401
408
  }),
409
+ sample: {
410
+ locate: {
411
+ prompt: 'the message bubble'
412
+ }
413
+ },
402
414
  call: async (param)=>{
403
415
  const element = param.locate;
404
416
  if (!element) throw new Error('LongPress requires an element to be located');
@@ -800,6 +812,9 @@ const createPlatformActions = (device)=>({
800
812
  description: 'Execute HDC shell command on HarmonyOS device',
801
813
  interfaceAlias: 'runHdcShell',
802
814
  paramSchema: runHdcShellParamSchema,
815
+ sample: {
816
+ command: 'hidumper -s WindowManagerService -a'
817
+ },
803
818
  call: async (param)=>{
804
819
  if (!param.command || '' === param.command.trim()) throw new Error('RunHdcShell requires a non-empty command parameter');
805
820
  const hdc = await device.getHdc();
@@ -811,6 +826,9 @@ const createPlatformActions = (device)=>({
811
826
  description: 'Launch a HarmonyOS app or URL',
812
827
  interfaceAlias: 'launch',
813
828
  paramSchema: launchParamSchema,
829
+ sample: {
830
+ uri: 'com.example.app'
831
+ },
814
832
  call: async (param)=>{
815
833
  if (!param.uri || '' === param.uri.trim()) throw new Error('Launch requires a non-empty uri parameter');
816
834
  await device.launch(param.uri);
package/dist/lib/cli.js CHANGED
@@ -240,7 +240,7 @@ class HdcClient {
240
240
  width: Number.parseInt(renderSizeMatch[1], 10),
241
241
  height: Number.parseInt(renderSizeMatch[2], 10)
242
242
  };
243
- const displayStdout = await this.shell('hidumper -s DisplayManagerService -a -a');
243
+ const displayStdout = await this.shell('hidumper -s DisplayManagerService -a');
244
244
  const displayMatch = displayStdout.match(/activeModes.*?(\d{3,5}),\s*(\d{3,5})/);
245
245
  if (displayMatch) return {
246
246
  width: Number.parseInt(displayMatch[1], 10),
@@ -272,6 +272,15 @@ function device_define_property(obj, key, value) {
272
272
  else obj[key] = value;
273
273
  return obj;
274
274
  }
275
+ const harmonyInputParamSchema = core_namespaceObject.z.object({
276
+ value: core_namespaceObject.z.string().describe('The text to input. Provide the final content for replace/append modes, or an empty string when using clear mode to remove existing text.'),
277
+ mode: core_namespaceObject.z.preprocess((val)=>'append' === val ? 'typeOnly' : val, core_namespaceObject.z["enum"]([
278
+ 'replace',
279
+ 'clear',
280
+ 'typeOnly'
281
+ ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - attempt to clear the field (limited support on HarmonyOS).')),
282
+ locate: (0, core_namespaceObject.getMidsceneLocationSchema)().describe('The input field to be filled').optional()
283
+ });
275
284
  const defaultScrollUntilTimes = 10;
276
285
  const defaultSwipeSpeed = 600;
277
286
  const defaultFastSwipeSpeed = 2000;
@@ -326,15 +335,13 @@ class HarmonyDevice {
326
335
  name: 'Input',
327
336
  description: 'Input text into the input field',
328
337
  interfaceAlias: 'aiInput',
329
- paramSchema: core_namespaceObject.z.object({
330
- value: core_namespaceObject.z.string().describe('The text to input. Provide the final content for replace/append modes, or an empty string when using clear mode to remove existing text.'),
331
- mode: core_namespaceObject.z.preprocess((val)=>'append' === val ? 'typeOnly' : val, core_namespaceObject.z["enum"]([
332
- 'replace',
333
- 'clear',
334
- 'typeOnly'
335
- ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - attempt to clear the field (limited support on HarmonyOS).')),
336
- locate: (0, core_namespaceObject.getMidsceneLocationSchema)().describe('The input field to be filled').optional()
337
- }),
338
+ paramSchema: harmonyInputParamSchema,
339
+ sample: {
340
+ value: 'test@example.com',
341
+ locate: {
342
+ prompt: 'the email input field'
343
+ }
344
+ },
338
345
  call: async (param)=>{
339
346
  const element = param.locate;
340
347
  if ('clear' === param.mode) return void await this.clearInput(element);
@@ -395,6 +402,11 @@ class HarmonyDevice {
395
402
  duration: core_namespaceObject.z.number().optional().describe('The duration of the long press in milliseconds'),
396
403
  locate: (0, core_namespaceObject.getMidsceneLocationSchema)().describe('The element to be long pressed')
397
404
  }),
405
+ sample: {
406
+ locate: {
407
+ prompt: 'the message bubble'
408
+ }
409
+ },
398
410
  call: async (param)=>{
399
411
  const element = param.locate;
400
412
  if (!element) throw new Error('LongPress requires an element to be located');
@@ -796,6 +808,9 @@ const createPlatformActions = (device)=>({
796
808
  description: 'Execute HDC shell command on HarmonyOS device',
797
809
  interfaceAlias: 'runHdcShell',
798
810
  paramSchema: runHdcShellParamSchema,
811
+ sample: {
812
+ command: 'hidumper -s WindowManagerService -a'
813
+ },
799
814
  call: async (param)=>{
800
815
  if (!param.command || '' === param.command.trim()) throw new Error('RunHdcShell requires a non-empty command parameter');
801
816
  const hdc = await device.getHdc();
@@ -807,6 +822,9 @@ const createPlatformActions = (device)=>({
807
822
  description: 'Launch a HarmonyOS app or URL',
808
823
  interfaceAlias: 'launch',
809
824
  paramSchema: launchParamSchema,
825
+ sample: {
826
+ uri: 'com.example.app'
827
+ },
810
828
  call: async (param)=>{
811
829
  if (!param.uri || '' === param.uri.trim()) throw new Error('Launch requires a non-empty uri parameter');
812
830
  await device.launch(param.uri);
@@ -958,7 +976,7 @@ class HarmonyMidsceneTools extends mcp_namespaceObject.BaseMidsceneTools {
958
976
  const tools = new HarmonyMidsceneTools();
959
977
  (0, cli_namespaceObject.runToolsCLI)(tools, 'midscene-harmony', {
960
978
  stripPrefix: 'harmony_',
961
- version: "1.5.4-beta-20260310084708.0"
979
+ version: "1.5.4"
962
980
  }).catch((e)=>{
963
981
  if (!(e instanceof cli_namespaceObject.CLIError)) console.error(e);
964
982
  process.exit(e instanceof cli_namespaceObject.CLIError ? e.exitCode : 1);
package/dist/lib/index.js CHANGED
@@ -223,7 +223,7 @@ class HdcClient {
223
223
  width: Number.parseInt(renderSizeMatch[1], 10),
224
224
  height: Number.parseInt(renderSizeMatch[2], 10)
225
225
  };
226
- const displayStdout = await this.shell('hidumper -s DisplayManagerService -a -a');
226
+ const displayStdout = await this.shell('hidumper -s DisplayManagerService -a');
227
227
  const displayMatch = displayStdout.match(/activeModes.*?(\d{3,5}),\s*(\d{3,5})/);
228
228
  if (displayMatch) return {
229
229
  width: Number.parseInt(displayMatch[1], 10),
@@ -255,6 +255,15 @@ function device_define_property(obj, key, value) {
255
255
  else obj[key] = value;
256
256
  return obj;
257
257
  }
258
+ const harmonyInputParamSchema = core_namespaceObject.z.object({
259
+ value: core_namespaceObject.z.string().describe('The text to input. Provide the final content for replace/append modes, or an empty string when using clear mode to remove existing text.'),
260
+ mode: core_namespaceObject.z.preprocess((val)=>'append' === val ? 'typeOnly' : val, core_namespaceObject.z["enum"]([
261
+ 'replace',
262
+ 'clear',
263
+ 'typeOnly'
264
+ ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - attempt to clear the field (limited support on HarmonyOS).')),
265
+ locate: (0, core_namespaceObject.getMidsceneLocationSchema)().describe('The input field to be filled').optional()
266
+ });
258
267
  const defaultScrollUntilTimes = 10;
259
268
  const defaultSwipeSpeed = 600;
260
269
  const defaultFastSwipeSpeed = 2000;
@@ -309,15 +318,13 @@ class HarmonyDevice {
309
318
  name: 'Input',
310
319
  description: 'Input text into the input field',
311
320
  interfaceAlias: 'aiInput',
312
- paramSchema: core_namespaceObject.z.object({
313
- value: core_namespaceObject.z.string().describe('The text to input. Provide the final content for replace/append modes, or an empty string when using clear mode to remove existing text.'),
314
- mode: core_namespaceObject.z.preprocess((val)=>'append' === val ? 'typeOnly' : val, core_namespaceObject.z["enum"]([
315
- 'replace',
316
- 'clear',
317
- 'typeOnly'
318
- ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - attempt to clear the field (limited support on HarmonyOS).')),
319
- locate: (0, core_namespaceObject.getMidsceneLocationSchema)().describe('The input field to be filled').optional()
320
- }),
321
+ paramSchema: harmonyInputParamSchema,
322
+ sample: {
323
+ value: 'test@example.com',
324
+ locate: {
325
+ prompt: 'the email input field'
326
+ }
327
+ },
321
328
  call: async (param)=>{
322
329
  const element = param.locate;
323
330
  if ('clear' === param.mode) return void await this.clearInput(element);
@@ -378,6 +385,11 @@ class HarmonyDevice {
378
385
  duration: core_namespaceObject.z.number().optional().describe('The duration of the long press in milliseconds'),
379
386
  locate: (0, core_namespaceObject.getMidsceneLocationSchema)().describe('The element to be long pressed')
380
387
  }),
388
+ sample: {
389
+ locate: {
390
+ prompt: 'the message bubble'
391
+ }
392
+ },
381
393
  call: async (param)=>{
382
394
  const element = param.locate;
383
395
  if (!element) throw new Error('LongPress requires an element to be located');
@@ -779,6 +791,9 @@ const createPlatformActions = (device)=>({
779
791
  description: 'Execute HDC shell command on HarmonyOS device',
780
792
  interfaceAlias: 'runHdcShell',
781
793
  paramSchema: runHdcShellParamSchema,
794
+ sample: {
795
+ command: 'hidumper -s WindowManagerService -a'
796
+ },
782
797
  call: async (param)=>{
783
798
  if (!param.command || '' === param.command.trim()) throw new Error('RunHdcShell requires a non-empty command parameter');
784
799
  const hdc = await device.getHdc();
@@ -790,6 +805,9 @@ const createPlatformActions = (device)=>({
790
805
  description: 'Launch a HarmonyOS app or URL',
791
806
  interfaceAlias: 'launch',
792
807
  paramSchema: launchParamSchema,
808
+ sample: {
809
+ uri: 'com.example.app'
810
+ },
793
811
  call: async (param)=>{
794
812
  if (!param.uri || '' === param.uri.trim()) throw new Error('Launch requires a non-empty uri parameter');
795
813
  await device.launch(param.uri);