@midscene/visualizer 0.27.5-beta-20250828012822.0 → 0.27.5

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.
@@ -3,8 +3,8 @@ import { Form, Input, InputNumber, Select } from "antd";
3
3
  const { TextArea } = Input;
4
4
  const renderLabel = (label, isOptional)=>`${label}${isOptional ? ' (Optional)' : ''}`;
5
5
  const TextField = (param)=>{
6
- let { name, label, isRequired, marginBottom } = param;
7
- const placeholder = `Enter ${name}`;
6
+ let { name, label, isRequired, marginBottom, placeholder: customPlaceholder } = param;
7
+ const placeholder = customPlaceholder || `Enter ${name}`;
8
8
  return /*#__PURE__*/ jsx(Form.Item, {
9
9
  name: [
10
10
  'params',
@@ -26,7 +26,8 @@ const TextField = (param)=>{
26
26
  }, name);
27
27
  };
28
28
  const LocateField = (param)=>{
29
- let { name, label, isRequired, marginBottom } = param;
29
+ let { name, label, isRequired, marginBottom, placeholder: customPlaceholder } = param;
30
+ const placeholder = customPlaceholder || `Describe the ${name}, use natural language`;
30
31
  return /*#__PURE__*/ jsx(Form.Item, {
31
32
  name: [
32
33
  'params',
@@ -36,7 +37,7 @@ const LocateField = (param)=>{
36
37
  rules: isRequired ? [
37
38
  {
38
39
  required: true,
39
- message: `Please describe the ${name}`
40
+ message: `The ${name} is required`
40
41
  }
41
42
  ] : [],
42
43
  style: {
@@ -44,12 +45,12 @@ const LocateField = (param)=>{
44
45
  },
45
46
  children: /*#__PURE__*/ jsx(TextArea, {
46
47
  rows: 2,
47
- placeholder: `Describe the ${name}, use natural language`
48
+ placeholder: placeholder
48
49
  })
49
50
  }, name);
50
51
  };
51
52
  const EnumField = (param)=>{
52
- let { name, label, fieldSchema, isRequired, marginBottom } = param;
53
+ let { name, label, fieldSchema, isRequired, marginBottom, placeholder: customPlaceholder } = param;
53
54
  const enumValues = fieldSchema._def.values || [];
54
55
  const selectOptions = enumValues.map((value)=>({
55
56
  value,
@@ -71,14 +72,15 @@ const EnumField = (param)=>{
71
72
  marginBottom
72
73
  },
73
74
  children: /*#__PURE__*/ jsx(Select, {
74
- placeholder: `Select ${name}`,
75
+ placeholder: customPlaceholder || `Select ${name}`,
75
76
  options: selectOptions
76
77
  })
77
78
  }, name);
78
79
  };
79
80
  const NumberField = (param)=>{
80
- let { name, label, isRequired, marginBottom } = param;
81
- const placeholder = 'distance' === name ? 500 : 0;
81
+ let { name, label, isRequired, marginBottom, placeholder: customPlaceholder } = param;
82
+ const defaultPlaceholder = 'distance' === name ? 500 : 0;
83
+ const placeholderValue = customPlaceholder ? Number(customPlaceholder) || defaultPlaceholder : defaultPlaceholder;
82
84
  const min = 0;
83
85
  const max = 'distance' === name ? 10000 : void 0;
84
86
  return /*#__PURE__*/ jsx(Form.Item, {
@@ -109,7 +111,7 @@ const NumberField = (param)=>{
109
111
  marginBottom
110
112
  },
111
113
  children: /*#__PURE__*/ jsx(InputNumber, {
112
- placeholder: placeholder.toString(),
114
+ placeholder: placeholderValue.toString(),
113
115
  min: min,
114
116
  max: max,
115
117
  step: 'distance' === name ? 10 : 1,
@@ -30,13 +30,42 @@ const PromptInput = (param)=>{
30
30
  const needsStructuredParams = useMemo(()=>{
31
31
  if (actionSpace) {
32
32
  const action = actionSpace.find((a)=>a.interfaceAlias === selectedType || a.name === selectedType);
33
- return !!(null == action ? void 0 : action.paramSchema);
33
+ if (!(null == action ? void 0 : action.paramSchema)) return false;
34
+ if (isZodObjectSchema(action.paramSchema)) {
35
+ const schema = action.paramSchema;
36
+ const shape = schema.shape || {};
37
+ const shapeKeys = Object.keys(shape);
38
+ return shapeKeys.length > 0;
39
+ }
40
+ return true;
34
41
  }
35
42
  return false;
36
43
  }, [
37
44
  selectedType,
38
45
  actionSpace
39
46
  ]);
47
+ const needsAnyInput = useMemo(()=>{
48
+ if (actionSpace && actionSpace.length > 0) {
49
+ const action = actionSpace.find((a)=>a.interfaceAlias === selectedType || a.name === selectedType);
50
+ if (action) {
51
+ if (action.paramSchema && isZodObjectSchema(action.paramSchema)) {
52
+ const schema = action.paramSchema;
53
+ const shape = schema.shape || {};
54
+ const hasRequiredFields = Object.keys(shape).some((key)=>{
55
+ const field = shape[key];
56
+ const { isOptional } = unwrapZodType(field);
57
+ return !isOptional;
58
+ });
59
+ return hasRequiredFields;
60
+ }
61
+ return !!action.paramSchema;
62
+ }
63
+ }
64
+ return true;
65
+ }, [
66
+ selectedType,
67
+ actionSpace
68
+ ]);
40
69
  const showDataExtractionOptions = useMemo(()=>{
41
70
  const dataExtractionMethods = [
42
71
  'aiQuery',
@@ -56,11 +85,12 @@ const PromptInput = (param)=>{
56
85
  const action = actionSpace.find((a)=>a.interfaceAlias === selectedType || a.name === selectedType);
57
86
  if ((null == action ? void 0 : action.paramSchema) && isZodObjectSchema(action.paramSchema)) {
58
87
  const schema = action.paramSchema;
59
- return Object.keys(schema.shape).some((key)=>{
88
+ const hasLocateField = Object.keys(schema.shape).some((key)=>{
60
89
  const field = schema.shape[key];
61
90
  const { actualField } = unwrapZodType(field);
62
91
  return isLocateField(actualField);
63
92
  });
93
+ return hasLocateField;
64
94
  }
65
95
  }
66
96
  return false;
@@ -68,14 +98,43 @@ const PromptInput = (param)=>{
68
98
  selectedType,
69
99
  actionSpace
70
100
  ]);
101
+ const hasConfigOptions = useMemo(()=>{
102
+ const hasTracking = 'In-Browser-Extension' === serviceMode;
103
+ const hasDeepThink = showDeepThinkOption;
104
+ const hasDataExtraction = showDataExtractionOptions && !hideDomAndScreenshotOptions;
105
+ return hasTracking || hasDeepThink || hasDataExtraction;
106
+ }, [
107
+ serviceMode,
108
+ showDeepThinkOption,
109
+ showDataExtractionOptions,
110
+ hideDomAndScreenshotOptions
111
+ ]);
112
+ const availableDropdownMethods = useMemo(()=>{
113
+ const metadataMethods = Object.keys(apiMetadata);
114
+ if (!actionSpace || 0 === actionSpace.length) return metadataMethods;
115
+ const availableMethods = actionSpace.map((action)=>action.interfaceAlias || action.name);
116
+ const finalMethods = new Set();
117
+ metadataMethods.forEach((method)=>{
118
+ const methodInfo = apiMetadata[method];
119
+ if ((null == methodInfo ? void 0 : methodInfo.group) === 'extraction' || (null == methodInfo ? void 0 : methodInfo.group) === 'validation') finalMethods.add(method);
120
+ else if (availableMethods.includes(method)) finalMethods.add(method);
121
+ });
122
+ availableMethods.forEach((method)=>{
123
+ finalMethods.add(method);
124
+ });
125
+ return Array.from(finalMethods);
126
+ }, [
127
+ actionSpace
128
+ ]);
71
129
  const getDefaultParams = useCallback(()=>{
72
130
  if (!needsStructuredParams || !actionSpace) return {};
73
131
  const action = actionSpace.find((a)=>a.interfaceAlias === selectedType || a.name === selectedType);
74
132
  if ((null == action ? void 0 : action.paramSchema) && isZodObjectSchema(action.paramSchema)) {
75
133
  const defaultParams = {};
76
134
  const schema = action.paramSchema;
77
- Object.keys(schema.shape).forEach((key)=>{
78
- const field = schema.shape[key];
135
+ const shape = schema.shape || {};
136
+ Object.keys(shape).forEach((key)=>{
137
+ const field = shape[key];
79
138
  const defaultValue = extractDefaultValue(field);
80
139
  if (void 0 !== defaultValue) defaultParams[key] = defaultValue;
81
140
  });
@@ -152,7 +211,8 @@ const PromptInput = (param)=>{
152
211
  const action = actionSpace.find((a)=>a.interfaceAlias === selectedType || a.name === selectedType);
153
212
  if ((null == action ? void 0 : action.paramSchema) && isZodObjectSchema(action.paramSchema)) {
154
213
  const schema = action.paramSchema;
155
- return 1 === Object.keys(schema.shape).length;
214
+ const shape = schema.shape || {};
215
+ return 1 === Object.keys(shape).length;
156
216
  }
157
217
  return false;
158
218
  }, [
@@ -177,10 +237,11 @@ const PromptInput = (param)=>{
177
237
  let locateValue = '';
178
238
  const otherValues = [];
179
239
  const schema = action.paramSchema;
180
- Object.keys(schema.shape).forEach((key)=>{
240
+ const shape = schema.shape || {};
241
+ Object.keys(shape).forEach((key)=>{
181
242
  const paramValue = values.params[key];
182
243
  if (null != paramValue && '' !== paramValue) {
183
- const field = schema.shape[key];
244
+ const field = shape[key];
184
245
  const { actualField } = unwrapZodType(field);
185
246
  if (isLocateField(actualField)) locateValue = String(paramValue);
186
247
  else if ('distance' === key) otherValues.push(`${paramValue}`);
@@ -252,19 +313,33 @@ const PromptInput = (param)=>{
252
313
  const action = actionSpace.find((a)=>a.interfaceAlias === selectedType || a.name === selectedType);
253
314
  if ((null == action ? void 0 : action.paramSchema) && isZodObjectSchema(action.paramSchema)) {
254
315
  const schema = action.paramSchema;
255
- const schemaKeys = Object.keys(schema.shape);
316
+ const shape = schema.shape || {};
317
+ const schemaKeys = Object.keys(shape);
256
318
  if (1 === schemaKeys.length) {
257
319
  const key = schemaKeys[0];
258
- const field = schema.shape[key];
320
+ const field = shape[key];
259
321
  const { actualField } = unwrapZodType(field);
260
322
  const isLocateFieldFlag = isLocateField(actualField);
261
- let placeholderText = '';
262
- if (isLocateFieldFlag) placeholderText = 'Describe the element you want to interact with';
263
- else {
264
- placeholderText = `Enter ${key}`;
265
- if ('keyName' === key) placeholderText = 'Enter key name or text to type';
266
- if ('value' === key) placeholderText = 'Enter text to input';
267
- }
323
+ const placeholderText = (()=>{
324
+ var _fieldAsAny__def;
325
+ const fieldAsAny = actualField;
326
+ if (null == (_fieldAsAny__def = fieldAsAny._def) ? void 0 : _fieldAsAny__def.description) return fieldAsAny._def.description;
327
+ if (fieldAsAny.description) return fieldAsAny.description;
328
+ if (actionSpace) {
329
+ const action = actionSpace.find((a)=>a.interfaceAlias === selectedType || a.name === selectedType);
330
+ if ((null == action ? void 0 : action.paramSchema) && 'object' == typeof action.paramSchema && 'shape' in action.paramSchema) {
331
+ var _fieldDef__def;
332
+ const shape = action.paramSchema.shape || {};
333
+ const fieldDef = shape[key];
334
+ if (null == fieldDef ? void 0 : null == (_fieldDef__def = fieldDef._def) ? void 0 : _fieldDef__def.description) return fieldDef._def.description;
335
+ if (null == fieldDef ? void 0 : fieldDef.description) return fieldDef.description;
336
+ }
337
+ }
338
+ if (isLocateFieldFlag) return 'Describe the element you want to interact with';
339
+ if ('keyName' === key) return 'Enter key name or text to type';
340
+ if ('value' === key) return 'Enter text to input';
341
+ return `Enter ${key}`;
342
+ })();
268
343
  return /*#__PURE__*/ jsx(Form.Item, {
269
344
  name: [
270
345
  'params',
@@ -285,18 +360,36 @@ const PromptInput = (param)=>{
285
360
  const fields = [];
286
361
  schemaKeys.forEach((key, index)=>{
287
362
  var _actualField__def, _actualField__def1;
288
- const fieldSchema = schema.shape[key];
363
+ const fieldSchema = shape[key];
289
364
  const { actualField, isOptional } = unwrapZodType(fieldSchema);
290
365
  const isLocateFieldFlag = isLocateField(actualField);
291
366
  const label = key.charAt(0).toUpperCase() + key.slice(1);
292
367
  const isRequired = !isOptional;
293
368
  const marginBottom = index === schemaKeys.length - 1 ? 0 : 12;
369
+ const placeholder = (()=>{
370
+ var _fieldAsAny__def;
371
+ const fieldAsAny = actualField;
372
+ if (null == (_fieldAsAny__def = fieldAsAny._def) ? void 0 : _fieldAsAny__def.description) return fieldAsAny._def.description;
373
+ if (fieldAsAny.description) return fieldAsAny.description;
374
+ if (actionSpace) {
375
+ const action = actionSpace.find((a)=>a.interfaceAlias === selectedType || a.name === selectedType);
376
+ if ((null == action ? void 0 : action.paramSchema) && 'object' == typeof action.paramSchema && 'shape' in action.paramSchema) {
377
+ var _fieldDef__def;
378
+ const shape = action.paramSchema.shape || {};
379
+ const fieldDef = shape[key];
380
+ if (null == fieldDef ? void 0 : null == (_fieldDef__def = fieldDef._def) ? void 0 : _fieldDef__def.description) return fieldDef._def.description;
381
+ if (null == fieldDef ? void 0 : fieldDef.description) return fieldDef.description;
382
+ }
383
+ }
384
+ if (isLocateFieldFlag) return 'Describe the element you want to interact with';
385
+ })();
294
386
  const fieldProps = {
295
387
  name: key,
296
388
  label,
297
389
  fieldSchema: actualField,
298
390
  isRequired,
299
- marginBottom
391
+ marginBottom,
392
+ placeholder
300
393
  };
301
394
  if (isLocateFieldFlag) fields.push(/*#__PURE__*/ jsx(LocateField, {
302
395
  ...fieldProps
@@ -419,45 +512,77 @@ const PromptInput = (param)=>{
419
512
  }),
420
513
  /*#__PURE__*/ jsx(Dropdown, {
421
514
  menu: (()=>{
422
- const hiddenAPIs = Object.keys(apiMetadata).filter((api)=>!defaultMainButtons.includes(api));
515
+ const hiddenAPIs = availableDropdownMethods.filter((api)=>!defaultMainButtons.includes(api));
423
516
  const groupedItems = [];
424
- const interactionAPIs = hiddenAPIs.filter((api)=>'interaction' === apiMetadata[api].group);
517
+ const interactionAPIs = hiddenAPIs.filter((api)=>{
518
+ var _apiMetadata_api;
519
+ return (null == (_apiMetadata_api = apiMetadata[api]) ? void 0 : _apiMetadata_api.group) === 'interaction';
520
+ });
425
521
  if (interactionAPIs.length > 0) groupedItems.push({
426
522
  key: 'interaction-group',
427
523
  type: 'group',
428
524
  label: 'Interaction APIs',
429
- children: interactionAPIs.map((api)=>({
525
+ children: interactionAPIs.map((api)=>{
526
+ var _apiMetadata_api;
527
+ return {
430
528
  key: api,
431
529
  label: actionNameForType(api),
432
- title: apiMetadata[api].title,
530
+ title: (null == (_apiMetadata_api = apiMetadata[api]) ? void 0 : _apiMetadata_api.title) || '',
433
531
  onClick: ()=>{
434
532
  form.setFieldValue('type', api);
435
533
  }
436
- }))
534
+ };
535
+ })
536
+ });
537
+ const extractionAPIs = hiddenAPIs.filter((api)=>{
538
+ var _apiMetadata_api;
539
+ return (null == (_apiMetadata_api = apiMetadata[api]) ? void 0 : _apiMetadata_api.group) === 'extraction';
437
540
  });
438
- const extractionAPIs = hiddenAPIs.filter((api)=>'extraction' === apiMetadata[api].group);
439
541
  if (extractionAPIs.length > 0) groupedItems.push({
440
542
  key: 'extraction-group',
441
543
  type: 'group',
442
544
  label: 'Data Extraction APIs',
443
- children: extractionAPIs.map((api)=>({
545
+ children: extractionAPIs.map((api)=>{
546
+ var _apiMetadata_api;
547
+ return {
444
548
  key: api,
445
549
  label: actionNameForType(api),
446
- title: apiMetadata[api].title,
550
+ title: (null == (_apiMetadata_api = apiMetadata[api]) ? void 0 : _apiMetadata_api.title) || '',
447
551
  onClick: ()=>{
448
552
  form.setFieldValue('type', api);
449
553
  }
450
- }))
554
+ };
555
+ })
556
+ });
557
+ const validationAPIs = hiddenAPIs.filter((api)=>{
558
+ var _apiMetadata_api;
559
+ return (null == (_apiMetadata_api = apiMetadata[api]) ? void 0 : _apiMetadata_api.group) === 'validation';
451
560
  });
452
- const validationAPIs = hiddenAPIs.filter((api)=>'validation' === apiMetadata[api].group);
453
561
  if (validationAPIs.length > 0) groupedItems.push({
454
562
  key: 'validation-group',
455
563
  type: 'group',
456
564
  label: 'Validation APIs',
457
- children: validationAPIs.map((api)=>({
565
+ children: validationAPIs.map((api)=>{
566
+ var _apiMetadata_api;
567
+ return {
458
568
  key: api,
459
569
  label: actionNameForType(api),
460
- title: apiMetadata[api].title,
570
+ title: (null == (_apiMetadata_api = apiMetadata[api]) ? void 0 : _apiMetadata_api.title) || '',
571
+ onClick: ()=>{
572
+ form.setFieldValue('type', api);
573
+ }
574
+ };
575
+ })
576
+ });
577
+ const deviceSpecificAPIs = hiddenAPIs.filter((api)=>!apiMetadata[api]);
578
+ if (deviceSpecificAPIs.length > 0) groupedItems.push({
579
+ key: 'device-specific-group',
580
+ type: 'group',
581
+ label: 'Device-Specific APIs',
582
+ children: deviceSpecificAPIs.map((api)=>({
583
+ key: api,
584
+ label: actionNameForType(api),
585
+ title: '',
461
586
  onClick: ()=>{
462
587
  form.setFieldValue('type', api);
463
588
  }
@@ -495,7 +620,7 @@ const PromptInput = (param)=>{
495
620
  history: historyForSelectedType,
496
621
  currentType: selectedType
497
622
  }),
498
- /*#__PURE__*/ jsx("div", {
623
+ hasConfigOptions && /*#__PURE__*/ jsx("div", {
499
624
  className: hoveringSettings ? 'settings-wrapper settings-wrapper-hover' : 'settings-wrapper',
500
625
  onMouseEnter: handleMouseEnter,
501
626
  onMouseLeave: handleMouseLeave,
@@ -513,7 +638,7 @@ const PromptInput = (param)=>{
513
638
  /*#__PURE__*/ jsxs("div", {
514
639
  className: `main-side-console-input ${!runButtonEnabled ? 'disabled' : ''} ${loading ? 'loading' : ''}`,
515
640
  children: [
516
- needsStructuredParams ? hasSingleStructuredParam ? renderStructuredParams() : /*#__PURE__*/ jsx("div", {
641
+ needsAnyInput ? needsStructuredParams ? hasSingleStructuredParam ? renderStructuredParams() : /*#__PURE__*/ jsx("div", {
517
642
  className: "structured-params-container",
518
643
  children: renderStructuredParams()
519
644
  }) : /*#__PURE__*/ jsx(Form.Item, {
@@ -531,6 +656,18 @@ const PromptInput = (param)=>{
531
656
  onChange: handlePromptChange,
532
657
  ref: textAreaRef
533
658
  })
659
+ }) : /*#__PURE__*/ jsxs("div", {
660
+ className: "no-input-method",
661
+ style: {
662
+ padding: '20px',
663
+ textAlign: 'center',
664
+ color: '#666',
665
+ fontSize: '14px'
666
+ },
667
+ children: [
668
+ 'Click "Run" to execute ',
669
+ actionNameForType(selectedType)
670
+ ]
534
671
  }),
535
672
  /*#__PURE__*/ jsx("div", {
536
673
  className: "form-controller-wrapper",
@@ -58,11 +58,18 @@ body {
58
58
  border-radius: 11px;
59
59
  align-items: center;
60
60
  gap: 2px;
61
+ max-width: 160px;
61
62
  padding: 0 8px;
62
63
  font-size: 12px;
63
64
  display: inline-flex;
64
65
  }
65
66
 
67
+ .prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .more-apis-button .ant-btn-content {
68
+ text-overflow: ellipsis;
69
+ white-space: nowrap;
70
+ overflow: hidden;
71
+ }
72
+
66
73
  .prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .more-apis-button:hover {
67
74
  background-color: #e6e6e6;
68
75
  }
@@ -0,0 +1,114 @@
1
+ import { findAllMidsceneLocatorField } from "@midscene/core/ai-model";
2
+ const formatErrorMessage = (e)=>{
3
+ const errorMessage = (null == e ? void 0 : e.message) || '';
4
+ if (errorMessage.includes('of different extension')) return 'Conflicting extension detected. Please disable the suspicious plugins and refresh the page. Guide: https://midscenejs.com/quick-experience.html#faq';
5
+ return errorMessage || 'Unknown error';
6
+ };
7
+ async function parseStructuredParams(action, params) {
8
+ let options = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : {};
9
+ if (!(null == action ? void 0 : action.paramSchema) || !('shape' in action.paramSchema)) return [
10
+ params.prompt || '',
11
+ options
12
+ ];
13
+ const schema = action.paramSchema;
14
+ const keys = Object.keys(schema.shape);
15
+ const paramObj = {
16
+ ...options
17
+ };
18
+ keys.forEach((key)=>{
19
+ if (void 0 !== params[key] && null !== params[key] && '' !== params[key]) paramObj[key] = params[key];
20
+ });
21
+ return [
22
+ paramObj
23
+ ];
24
+ }
25
+ function validateStructuredParams(value, action) {
26
+ if (!value.params) return {
27
+ valid: false,
28
+ errorMessage: 'Parameters are required'
29
+ };
30
+ if (!(null == action ? void 0 : action.paramSchema)) return {
31
+ valid: true
32
+ };
33
+ try {
34
+ var _action_paramSchema;
35
+ const paramsForValidation = {
36
+ ...value.params
37
+ };
38
+ const schema = action.paramSchema;
39
+ if (schema) {
40
+ const locatorFieldKeys = findAllMidsceneLocatorField(schema);
41
+ locatorFieldKeys.forEach((key)=>{
42
+ if ('string' == typeof paramsForValidation[key]) paramsForValidation[key] = {
43
+ midscene_location_field_flag: true,
44
+ prompt: paramsForValidation[key],
45
+ center: [
46
+ 0,
47
+ 0
48
+ ],
49
+ rect: {
50
+ left: 0,
51
+ top: 0,
52
+ width: 0,
53
+ height: 0
54
+ }
55
+ };
56
+ });
57
+ }
58
+ null == (_action_paramSchema = action.paramSchema) || _action_paramSchema.parse(paramsForValidation);
59
+ } catch (error) {
60
+ const zodError = error;
61
+ if (zodError.errors && zodError.errors.length > 0) {
62
+ const errorMessages = zodError.errors.filter((err)=>{
63
+ const path = err.path.join('.');
64
+ return !path.includes('center') && !path.includes('rect') && !path.includes('midscene_location_field_flag');
65
+ }).map((err)=>{
66
+ const field = err.path.join('.');
67
+ return `${field}: ${err.message}`;
68
+ });
69
+ if (errorMessages.length > 0) return {
70
+ valid: false,
71
+ errorMessage: `Validation error: ${errorMessages.join(', ')}`
72
+ };
73
+ } else {
74
+ const errorMsg = error instanceof Error ? error.message : 'Unknown validation error';
75
+ return {
76
+ valid: false,
77
+ errorMessage: `Parameter validation failed: ${errorMsg}`
78
+ };
79
+ }
80
+ }
81
+ return {
82
+ valid: true
83
+ };
84
+ }
85
+ async function executeAction(activeAgent, actionType, actionSpace, value, deepThink) {
86
+ const action = null == actionSpace ? void 0 : actionSpace.find((a)=>a.interfaceAlias === actionType || a.name === actionType);
87
+ if (action && 'function' == typeof activeAgent.callActionInActionSpace) if (!value.params) return await activeAgent.callActionInActionSpace(action.name, {
88
+ prompt: value.prompt,
89
+ deepThink
90
+ });
91
+ else {
92
+ const parsedParams = await parseStructuredParams(action, value.params, {
93
+ deepThink
94
+ });
95
+ return await activeAgent.callActionInActionSpace(action.name, parsedParams[0]);
96
+ }
97
+ {
98
+ const prompt = value.prompt;
99
+ if ('aiAssert' === actionType) {
100
+ const { pass, thought } = await (null == activeAgent ? void 0 : activeAgent.aiAssert(prompt, void 0, {
101
+ keepRawResponse: true
102
+ })) || {};
103
+ return {
104
+ pass,
105
+ thought
106
+ };
107
+ }
108
+ if (activeAgent && 'function' == typeof activeAgent[actionType]) return await activeAgent[actionType](prompt, {
109
+ deepThink
110
+ });
111
+ throw new Error(`Unknown action type: ${actionType}`);
112
+ }
113
+ }
114
+ export { executeAction, formatErrorMessage, validateStructuredParams };
@@ -1,5 +1,5 @@
1
1
  import { PLAYGROUND_SERVER_PORT } from "@midscene/shared/constants";
2
- import { ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED, StaticPage, StaticPageAgent } from "@midscene/web/playground";
2
+ import { StaticPage, StaticPageAgent } from "@midscene/web/playground";
3
3
  import { isZodObjectSchema, unwrapZodType } from "./types.mjs";
4
4
  const serverBase = `http://localhost:${PLAYGROUND_SERVER_PORT}`;
5
5
  const checkServerStatus = async ()=>{
@@ -11,7 +11,7 @@ const checkServerStatus = async ()=>{
11
11
  }
12
12
  };
13
13
  const requestPlaygroundServer = async function(context, type, prompt) {
14
- let { requestId, deepThink, screenshotIncluded, domIncluded } = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : {};
14
+ let { requestId, deepThink, params, screenshotIncluded, domIncluded } = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : {};
15
15
  const payload = {
16
16
  context,
17
17
  type,
@@ -21,6 +21,7 @@ const requestPlaygroundServer = async function(context, type, prompt) {
21
21
  if (deepThink) payload.deepThink = deepThink;
22
22
  if (void 0 !== screenshotIncluded) payload.screenshotIncluded = screenshotIncluded;
23
23
  if (void 0 !== domIncluded) payload.domIncluded = domIncluded;
24
+ if (params) payload.params = params;
24
25
  const res = await fetch(`${serverBase}/execute`, {
25
26
  method: 'POST',
26
27
  headers: {
@@ -61,9 +62,31 @@ const getTaskProgress = async (requestId)=>{
61
62
  };
62
63
  }
63
64
  };
65
+ const getActionSpace = async (context)=>{
66
+ try {
67
+ if (!context) return [];
68
+ const response = await fetch(`${serverBase}/action-space`, {
69
+ method: 'POST',
70
+ headers: {
71
+ 'Content-Type': 'application/json'
72
+ },
73
+ body: JSON.stringify({
74
+ context
75
+ })
76
+ });
77
+ if (response.ok) return await response.json();
78
+ return [];
79
+ } catch (error) {
80
+ console.error('Failed to get action space:', error);
81
+ return [];
82
+ }
83
+ };
64
84
  const actionNameForType = (type)=>{
65
85
  const typeWithoutAi = type.startsWith('ai') ? type.slice(2) : type;
66
- return typeWithoutAi.replace(/([A-Z])/g, ' $1').trim();
86
+ const fullName = typeWithoutAi.replace(/([A-Z])/g, ' $1').trim();
87
+ const words = fullName.split(' ');
88
+ if (words.length > 3) return words.slice(-3).join(' ');
89
+ return fullName;
67
90
  };
68
91
  const staticAgentFromContext = (context)=>{
69
92
  const page = new StaticPage(context);
@@ -72,8 +95,7 @@ const staticAgentFromContext = (context)=>{
72
95
  const formatErrorMessage = (e)=>{
73
96
  const errorMessage = (null == e ? void 0 : e.message) || '';
74
97
  if (errorMessage.includes('of different extension')) return 'Conflicting extension detected. Please disable the suspicious plugins and refresh the page. Guide: https://midscenejs.com/quick-experience.html#faq';
75
- if (!(null == errorMessage ? void 0 : errorMessage.includes(ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED))) return errorMessage;
76
- return 'Unknown error';
98
+ return errorMessage || 'Unknown error';
77
99
  };
78
100
  const getPlaceholderForType = (type)=>{
79
101
  if ('aiQuery' === type) return 'What do you want to query?';
@@ -100,13 +122,29 @@ const blankResult = {
100
122
  };
101
123
  const isRunButtonEnabled = (runButtonEnabled, needsStructuredParams, params, actionSpace, selectedType, promptValue)=>{
102
124
  if (!runButtonEnabled) return false;
125
+ const needsAnyInput = (()=>{
126
+ if (actionSpace) {
127
+ const action = actionSpace.find((a)=>a.interfaceAlias === selectedType || a.name === selectedType);
128
+ if (action) {
129
+ if (!action.paramSchema) return false;
130
+ if ('object' == typeof action.paramSchema && 'shape' in action.paramSchema) {
131
+ const shape = action.paramSchema.shape || {};
132
+ const shapeKeys = Object.keys(shape);
133
+ return shapeKeys.length > 0;
134
+ }
135
+ }
136
+ }
137
+ return true;
138
+ })();
139
+ if (!needsAnyInput) return true;
103
140
  if (needsStructuredParams) {
104
141
  const currentParams = params || {};
105
142
  const action = null == actionSpace ? void 0 : actionSpace.find((a)=>a.interfaceAlias === selectedType || a.name === selectedType);
106
143
  if ((null == action ? void 0 : action.paramSchema) && isZodObjectSchema(action.paramSchema)) {
107
144
  const schema = action.paramSchema;
108
- return Object.keys(schema.shape).every((key)=>{
109
- const field = schema.shape[key];
145
+ const shape = schema.shape || {};
146
+ return Object.keys(shape).every((key)=>{
147
+ const field = shape[key];
110
148
  const { isOptional } = unwrapZodType(field);
111
149
  const value = currentParams[key];
112
150
  return isOptional || void 0 !== value && '' !== value && null !== value;
@@ -116,4 +154,4 @@ const isRunButtonEnabled = (runButtonEnabled, needsStructuredParams, params, act
116
154
  }
117
155
  return promptValue.trim().length > 0;
118
156
  };
119
- export { actionNameForType, blankResult, cancelTask, checkServerStatus, formatErrorMessage, getPlaceholderForType, getTaskProgress, isRunButtonEnabled, overrideServerConfig, requestPlaygroundServer, serverBase, staticAgentFromContext };
157
+ export { actionNameForType, blankResult, cancelTask, checkServerStatus, formatErrorMessage, getActionSpace, getPlaceholderForType, getTaskProgress, isRunButtonEnabled, overrideServerConfig, requestPlaygroundServer, serverBase, staticAgentFromContext };