@midscene/visualizer 1.7.5-beta-20260421030751.0 → 1.7.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.
Files changed (28) hide show
  1. package/dist/es/component/config-selector/index.mjs +7 -1
  2. package/dist/es/component/history-selector/index.css +1 -3
  3. package/dist/es/component/history-selector/index.mjs +33 -5
  4. package/dist/es/component/playground/index.css +9 -1
  5. package/dist/es/component/prompt-input/index.css +9 -1
  6. package/dist/es/component/prompt-input/index.mjs +44 -45
  7. package/dist/es/component/universal-playground/index.css +129 -0
  8. package/dist/es/component/universal-playground/index.mjs +13 -8
  9. package/dist/es/hooks/useMinimalTypeGate.mjs +47 -0
  10. package/dist/es/hooks/usePlaygroundExecution.mjs +1 -0
  11. package/dist/es/utils/progress-action-icon.mjs +49 -0
  12. package/dist/lib/component/config-selector/index.js +7 -1
  13. package/dist/lib/component/history-selector/index.css +1 -3
  14. package/dist/lib/component/history-selector/index.js +33 -5
  15. package/dist/lib/component/playground/index.css +9 -1
  16. package/dist/lib/component/prompt-input/index.css +9 -1
  17. package/dist/lib/component/prompt-input/index.js +44 -46
  18. package/dist/lib/component/universal-playground/index.css +129 -0
  19. package/dist/lib/component/universal-playground/index.js +13 -8
  20. package/dist/lib/hooks/useMinimalTypeGate.js +81 -0
  21. package/dist/lib/hooks/usePlaygroundExecution.js +1 -0
  22. package/dist/lib/utils/progress-action-icon.js +86 -0
  23. package/dist/types/component/config-selector/index.d.ts +1 -0
  24. package/dist/types/component/history-selector/index.d.ts +1 -0
  25. package/dist/types/hooks/useMinimalTypeGate.d.ts +72 -0
  26. package/dist/types/types.d.ts +32 -9
  27. package/dist/types/utils/progress-action-icon.d.ts +16 -0
  28. package/package.json +5 -5
@@ -4,7 +4,7 @@ import setting from "../../icons/setting.mjs";
4
4
  import { useEnvConfig } from "../../store/store.mjs";
5
5
  import { alwaysRefreshScreenInfoTip, autoDismissKeyboardTip, deepLocateTip, deepThinkTip, domIncludedTip, imeStrategyTip, keyboardDismissStrategyTip, screenshotIncludedTip, trackingTip } from "../../utils/constants.mjs";
6
6
  import { getDeviceCapabilities, hasDeviceSpecificConfig } from "../../utils/device-capabilities.mjs";
7
- const ConfigSelector = ({ showDeepLocateOption = false, showDeepThinkOption = false, enableTracking = false, showDataExtractionOptions = false, hideDomAndScreenshotOptions = false, deviceType, trigger })=>{
7
+ const ConfigSelector = ({ showDeepLocateOption = false, showDeepThinkOption = false, enableTracking = false, showDataExtractionOptions = false, hideDomAndScreenshotOptions = false, deviceType, trigger, popupPlacement = 'bottomRight' })=>{
8
8
  const forceSameTabNavigation = useEnvConfig((state)=>state.forceSameTabNavigation);
9
9
  const setForceSameTabNavigation = useEnvConfig((state)=>state.setForceSameTabNavigation);
10
10
  const deepLocate = useEnvConfig((state)=>state.deepLocate);
@@ -30,9 +30,15 @@ const ConfigSelector = ({ showDeepLocateOption = false, showDeepThinkOption = fa
30
30
  return /*#__PURE__*/ jsx("div", {
31
31
  className: "selector-trigger",
32
32
  children: /*#__PURE__*/ jsx(Dropdown, {
33
+ getPopupContainer: (triggerNode)=>triggerNode.ownerDocument.body,
33
34
  menu: {
34
35
  items: configItems
35
36
  },
37
+ overlayClassName: "config-selector-dropdown",
38
+ overlayStyle: {
39
+ zIndex: 10010
40
+ },
41
+ placement: popupPlacement,
36
42
  trigger: [
37
43
  'click'
38
44
  ],
@@ -8,11 +8,9 @@
8
8
  border: 1px solid rgba(0, 0, 0, .08);
9
9
  border-radius: 12px;
10
10
  width: 320px;
11
+ max-width: min(320px, 100vw - 32px);
11
12
  height: 400px;
12
13
  position: fixed;
13
- top: auto;
14
- bottom: 20px;
15
- right: 20px;
16
14
  box-shadow: 0 8px 24px rgba(0, 0, 0, .12);
17
15
  }
18
16
 
@@ -1,17 +1,24 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Button, Input, Typography } from "antd";
3
3
  import { useEffect, useMemo, useRef, useState } from "react";
4
+ import { createPortal } from "react-dom";
4
5
  import icons_close from "../../icons/close.mjs";
5
6
  import icons_history from "../../icons/history.mjs";
6
7
  import magnifying_glass from "../../icons/magnifying-glass.mjs";
7
8
  import { useHistoryStore } from "../../store/history.mjs";
8
9
  import "./index.css";
9
10
  const { Text } = Typography;
10
- const HistorySelector = ({ onSelect, history, currentType, trigger })=>{
11
+ const HISTORY_MODAL_WIDTH = 320;
12
+ const HISTORY_MODAL_HEIGHT = 400;
13
+ const HISTORY_MODAL_GUTTER = 16;
14
+ const HISTORY_MODAL_OFFSET = 8;
15
+ const HistorySelector = ({ onSelect, history, currentType, trigger, popupPlacement = 'bottom' })=>{
11
16
  const [isModalOpen, setIsModalOpen] = useState(false);
12
17
  const [searchText, setSearchText] = useState('');
13
18
  const clearHistory = useHistoryStore((state)=>state.clearHistory);
14
19
  const modalRef = useRef(null);
20
+ const triggerRef = useRef(null);
21
+ const [overlayPosition, setOverlayPosition] = useState(null);
15
22
  const groupedHistory = useMemo(()=>{
16
23
  const now = Date.now();
17
24
  const sevenDaysAgo = now - 604800000;
@@ -38,18 +45,37 @@ const HistorySelector = ({ onSelect, history, currentType, trigger })=>{
38
45
  };
39
46
  useEffect(()=>{
40
47
  if (!isModalOpen) return;
48
+ const updateOverlayPosition = ()=>{
49
+ if (!triggerRef.current) return;
50
+ const triggerRect = triggerRef.current.getBoundingClientRect();
51
+ const maxLeft = Math.max(HISTORY_MODAL_GUTTER, window.innerWidth - HISTORY_MODAL_WIDTH - HISTORY_MODAL_GUTTER);
52
+ const maxTop = Math.max(HISTORY_MODAL_GUTTER, window.innerHeight - HISTORY_MODAL_HEIGHT - HISTORY_MODAL_GUTTER);
53
+ const left = Math.min(Math.max(HISTORY_MODAL_GUTTER, triggerRect.right - HISTORY_MODAL_WIDTH), maxLeft);
54
+ const preferredTop = 'top' === popupPlacement ? triggerRect.top - HISTORY_MODAL_HEIGHT - HISTORY_MODAL_OFFSET : triggerRect.bottom + HISTORY_MODAL_OFFSET;
55
+ const top = Math.min(Math.max(HISTORY_MODAL_GUTTER, preferredTop), maxTop);
56
+ setOverlayPosition({
57
+ left,
58
+ top
59
+ });
60
+ };
41
61
  const handleClickOutside = (event)=>{
42
- if (modalRef.current && !modalRef.current.contains(event.target)) setIsModalOpen(false);
62
+ if (modalRef.current && !modalRef.current.contains(event.target) && triggerRef.current && !triggerRef.current.contains(event.target)) setIsModalOpen(false);
43
63
  };
64
+ updateOverlayPosition();
44
65
  const timer = setTimeout(()=>{
45
66
  document.addEventListener('click', handleClickOutside);
46
67
  }, 100);
68
+ window.addEventListener('resize', updateOverlayPosition);
69
+ window.addEventListener('scroll', updateOverlayPosition, true);
47
70
  return ()=>{
48
71
  clearTimeout(timer);
49
72
  document.removeEventListener('click', handleClickOutside);
73
+ window.removeEventListener('resize', updateOverlayPosition);
74
+ window.removeEventListener('scroll', updateOverlayPosition, true);
50
75
  };
51
76
  }, [
52
- isModalOpen
77
+ isModalOpen,
78
+ popupPlacement
53
79
  ]);
54
80
  const renderHistoryGroup = (title, items)=>{
55
81
  if (0 === items.length) return null;
@@ -74,14 +100,16 @@ const HistorySelector = ({ onSelect, history, currentType, trigger })=>{
74
100
  /*#__PURE__*/ jsx("div", {
75
101
  className: "selector-trigger",
76
102
  onClick: ()=>setIsModalOpen(true),
103
+ ref: triggerRef,
77
104
  children: null != trigger ? trigger : /*#__PURE__*/ jsx(icons_history, {
78
105
  width: 24,
79
106
  height: 24
80
107
  })
81
108
  }),
82
- isModalOpen && /*#__PURE__*/ jsx("div", {
109
+ isModalOpen && overlayPosition && /*#__PURE__*/ createPortal(/*#__PURE__*/ jsx("div", {
83
110
  className: "history-modal-overlay",
84
111
  ref: modalRef,
112
+ style: overlayPosition,
85
113
  children: /*#__PURE__*/ jsxs("div", {
86
114
  className: "history-modal-container",
87
115
  children: [
@@ -162,7 +190,7 @@ const HistorySelector = ({ onSelect, history, currentType, trigger })=>{
162
190
  })
163
191
  ]
164
192
  })
165
- })
193
+ }), document.body)
166
194
  ]
167
195
  });
168
196
  };
@@ -624,6 +624,14 @@
624
624
  height: 16px;
625
625
  }
626
626
 
627
+ .prompt-input-wrapper-minimal .minimal-main-side-console-input .minimal-action-icon-fallback {
628
+ color: #878787;
629
+ flex-shrink: 0;
630
+ width: 16px;
631
+ height: 16px;
632
+ display: block;
633
+ }
634
+
627
635
  .prompt-input-wrapper-minimal .minimal-main-side-console-input .minimal-action-label {
628
636
  color: #878787;
629
637
  white-space: nowrap;
@@ -805,7 +813,7 @@
805
813
  background: none !important;
806
814
  }
807
815
 
808
- [data-theme="dark"] .prompt-input-wrapper.prompt-input-wrapper-minimal .minimal-main-side-console-input .minimal-toolbar-icon-fallback {
816
+ [data-theme="dark"] .prompt-input-wrapper.prompt-input-wrapper-minimal .minimal-main-side-console-input .minimal-toolbar-icon-fallback, [data-theme="dark"] .prompt-input-wrapper.prompt-input-wrapper-minimal .minimal-main-side-console-input .minimal-action-icon-fallback {
809
817
  color: rgba(255, 255, 255, .72) !important;
810
818
  }
811
819
 
@@ -532,6 +532,14 @@
532
532
  height: 16px;
533
533
  }
534
534
 
535
+ .prompt-input-wrapper-minimal .minimal-main-side-console-input .minimal-action-icon-fallback {
536
+ color: #878787;
537
+ flex-shrink: 0;
538
+ width: 16px;
539
+ height: 16px;
540
+ display: block;
541
+ }
542
+
535
543
  .prompt-input-wrapper-minimal .minimal-main-side-console-input .minimal-action-label {
536
544
  color: #878787;
537
545
  white-space: nowrap;
@@ -713,7 +721,7 @@
713
721
  background: none !important;
714
722
  }
715
723
 
716
- [data-theme="dark"] .prompt-input-wrapper.prompt-input-wrapper-minimal .minimal-main-side-console-input .minimal-toolbar-icon-fallback {
724
+ [data-theme="dark"] .prompt-input-wrapper.prompt-input-wrapper-minimal .minimal-main-side-console-input .minimal-toolbar-icon-fallback, [data-theme="dark"] .prompt-input-wrapper.prompt-input-wrapper-minimal .minimal-main-side-console-input .minimal-action-icon-fallback {
717
725
  color: rgba(255, 255, 255, .72) !important;
718
726
  }
719
727
 
@@ -13,8 +13,8 @@ import { getAvailablePromptActionTypes, getInlineStructuredFieldConfig } from ".
13
13
  import { ConfigSelector } from "../config-selector/index.mjs";
14
14
  import { BooleanField, EnumField, LocateField, NumberField, TextField } from "../form-field/index.mjs";
15
15
  import { HistorySelector } from "../history-selector/index.mjs";
16
+ import { useMinimalTypeGate } from "../../hooks/useMinimalTypeGate.mjs";
16
17
  import icons_history from "../../icons/history.mjs";
17
- import setting from "../../icons/setting.mjs";
18
18
  function _define_property(obj, key, value) {
19
19
  if (key in obj) Object.defineProperty(obj, key, {
20
20
  value: value,
@@ -39,10 +39,15 @@ function _object_spread(target) {
39
39
  return target;
40
40
  }
41
41
  const { TextArea } = Input;
42
+ const STUDIO_MINIMAL_PROMPT_ICONS = {
43
+ action: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAOdEVYdFNvZnR3YXJlAEZpZ21hnrGWYwAAASdJREFUeAHtlt3NgjAUhg8/CVx+G8gGX5xAnUDdQMcgkIgJBLbQEXQD3MAR6gZewgXgOUn9iRp6vAC96JM07YG36Zv+nBZAwySO4ymWgUoXRdEfaYGJyRElSbKyLGuHJVdpHcc5khb7RMCAZcA0TU82PYZ8IPsoZ4ttoEu0ga8bMB6DNE1X8H6jTUBuLmQL7SxkLbDkzz/ruhZBEKxfDGRZNm2aZgc9UFXVLAzDPbVvS1AUxQGrE3SPwHK8BganBy7NBuTU+r5vKLSNbG5RuwQF+hRoA9rA76RifMl4+JjI4Z5yu0KUZTnE8c4U3GbAdd3/HgYnPNu2R9eg98uIvmOGfL2M2tCpWBv4BQPiqW7j9IGWZ4CODT7X5pRAVFrUjEn7eNQ0bVwAyWpjMDlJKpAAAAAASUVORK5CYII=',
44
+ actionChevron: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAOdEVYdFNvZnR3YXJlAEZpZ21hnrGWYwAAAUxJREFUeAHtUztOw0AQ3V1SuLCldP4VuEyHuQE34Aqho0tugHKCwBFyApwTYEoqyAlwCsufKkgu3NjmjfkoCDu7KSP5SaNZ774Zv9nZYWzAgH2MAdu2z4+J4apEy7I8uBDWlGV5uQNU4gRTBOd8CUfqPU3THlXjzlRIUH8HdwuLYB8wX9d1XhRFKIuVXpHjONd1XQdN0+yEED48h72iojGOr9I0fT4ULyTKPSR/aJVwPk+SZIuEET6n33uBrOmyHoTs694XSLz62cyybI3k96iEqgjodbFjAWVLVNDAnvo4dEYc4vZxOiswTXMGdXMsIyidsn7cwLbExU9mXQTeocqDe28POffo3tkBuK57UVXVG63RLz/P8w3rq2BvmH6byiSI43hD3DaZEP/68WcODMOg9z5BySs0dcEUgXl4wVzQ0h+NRhN8r9mAAaeDT7K0eaMcqhtVAAAAAElFTkSuQmCC',
45
+ settings: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAOdEVYdFNvZnR3YXJlAEZpZ21hnrGWYwAAAaFJREFUeAHtlt9tgzAQxi8EJa/pBMkIHYENygalG7RvSQQKlfjz2I5ANkg3oBukG6QbtI9IIPq5ihHQOBXmFImqPwnZBvtsf9ydTfQPA77vz4IguCENDGJgOp3ux+PxLgxDnzrCsgAw/zZmGPOO48iUFci4wE42xITKXlEUO9d1X34s4NjZISZU9qCSjeKqastKWZYpMaKyNxqNto02MRDHcXmsJqvV6q7LWBYnxK4+SBOTeHDw2HAwn4aGlg9EUfQE2e+xYwchtaUeaPmAmFyUyH4W9aThA9jZ7alOiN39crl8O/FpoRpzjrq96hcgj2/wwVcNQlxb6/X6VdRrYaeNtGfUVvXbgE9iRNprOCHktPF/Z+3OeZ4fPM9LZbumgHjX2Qnr9rSioE/ma6MVBZDvWWQ/cbLR0GE5jEQoQhFLpGIkpvcuY1nOAkyeiBKJSRSXPw37UCkgbrWmaSZwsBkxoLInHBgJ6EG2KwUgn801+Tl78hyRVApkWfaIexxp4rRfqOzBUdN6+29cyYAMvQN1hCUMIbc1mUyu4VzDz4wX5wvRfah9kIOcwwAAAABJRU5ErkJggg=='
46
+ };
42
47
  const PromptInput = ({ runButtonEnabled, form, serviceMode, selectedType, dryMode, stoppable, loading, onRun, onStop, clearPromptAfterRun = true, actionSpace, hideDomAndScreenshotOptions = false, deviceType, chrome })=>{
48
+ var _chrome_icons, _chrome_icons1, _chrome_icons2;
43
49
  const [hoveringSettings, setHoveringSettings] = useState(false);
44
50
  const [promptValue, setPromptValue] = useState('');
45
- const [minimalHasExplicitTypeSelection, setMinimalHasExplicitTypeSelection] = useState(false);
46
51
  const placeholder = getPlaceholderForType(selectedType);
47
52
  const isMinimalChrome = (null == chrome ? void 0 : chrome.variant) === 'minimal';
48
53
  const resolvedPlaceholder = (null == chrome ? void 0 : chrome.placeholder) || placeholder;
@@ -59,7 +64,16 @@ const PromptInput = ({ runButtonEnabled, form, serviceMode, selectedType, dryMod
59
64
  history,
60
65
  selectedType
61
66
  ]);
62
- const skipMinimalSyncRef = useRef(false);
67
+ const handleMinimalTypeGateReset = useCallback(()=>{
68
+ lastHistoryRef.current = null;
69
+ setPromptValue('');
70
+ }, []);
71
+ const { markExplicitSelection, skipNextRestore, shouldSkipRestoreOnce } = useMinimalTypeGate({
72
+ enabled: isMinimalChrome,
73
+ form,
74
+ selectedType,
75
+ onAfterReset: handleMinimalTypeGateReset
76
+ });
63
77
  const needsStructuredParams = useMemo(()=>{
64
78
  if (actionSpace) {
65
79
  const action = actionSpace.find((a)=>a.interfaceAlias === selectedType || a.name === selectedType);
@@ -157,11 +171,11 @@ const PromptInput = ({ runButtonEnabled, form, serviceMode, selectedType, dryMod
157
171
  availableDropdownMethods
158
172
  ]);
159
173
  const handleTypeSelect = useCallback((api)=>{
160
- if (isMinimalChrome) setMinimalHasExplicitTypeSelection(true);
174
+ markExplicitSelection();
161
175
  form.setFieldValue('type', api);
162
176
  }, [
163
177
  form,
164
- isMinimalChrome
178
+ markExplicitSelection
165
179
  ]);
166
180
  const apiGroupDefinitions = useMemo(()=>[
167
181
  {
@@ -245,22 +259,6 @@ const PromptInput = ({ runButtonEnabled, form, serviceMode, selectedType, dryMod
245
259
  }), [
246
260
  hiddenApiGroupItems
247
261
  ]);
248
- useEffect(()=>{
249
- if (!isMinimalChrome || minimalHasExplicitTypeSelection || !selectedType || 'aiAct' === selectedType) return;
250
- skipMinimalSyncRef.current = false;
251
- lastHistoryRef.current = null;
252
- form.setFieldsValue({
253
- type: 'aiAct',
254
- prompt: '',
255
- params: {}
256
- });
257
- setPromptValue('');
258
- }, [
259
- form,
260
- minimalHasExplicitTypeSelection,
261
- isMinimalChrome,
262
- selectedType
263
- ]);
264
262
  const getDefaultParams = useCallback(()=>{
265
263
  if (!needsStructuredParams || !actionSpace) return {};
266
264
  const action = actionSpace.find((a)=>a.interfaceAlias === selectedType || a.name === selectedType);
@@ -318,10 +316,7 @@ const PromptInput = ({ runButtonEnabled, form, serviceMode, selectedType, dryMod
318
316
  }
319
317
  }, []);
320
318
  useEffect(()=>{
321
- if (skipMinimalSyncRef.current) {
322
- skipMinimalSyncRef.current = false;
323
- return;
324
- }
319
+ if (shouldSkipRestoreOnce()) return;
325
320
  if (isMinimalChrome) {
326
321
  const defaultParams = getDefaultParams();
327
322
  form.setFieldsValue({
@@ -356,7 +351,8 @@ const PromptInput = ({ runButtonEnabled, form, serviceMode, selectedType, dryMod
356
351
  historyForSelectedType,
357
352
  form,
358
353
  getDefaultParams,
359
- isMinimalChrome
354
+ isMinimalChrome,
355
+ shouldSkipRestoreOnce
360
356
  ]);
361
357
  useEffect(()=>{
362
358
  const timeoutId = setTimeout(()=>{
@@ -375,8 +371,8 @@ const PromptInput = ({ runButtonEnabled, form, serviceMode, selectedType, dryMod
375
371
  promptValue
376
372
  ]);
377
373
  const handleSelectHistory = useCallback((historyItem)=>{
378
- if (isMinimalChrome) setMinimalHasExplicitTypeSelection(true);
379
- skipMinimalSyncRef.current = historyItem.type !== selectedType;
374
+ markExplicitSelection();
375
+ if (historyItem.type !== selectedType) skipNextRestore();
380
376
  form.setFieldsValue({
381
377
  prompt: historyItem.prompt,
382
378
  type: historyItem.type,
@@ -385,8 +381,9 @@ const PromptInput = ({ runButtonEnabled, form, serviceMode, selectedType, dryMod
385
381
  setPromptValue(historyItem.prompt);
386
382
  }, [
387
383
  form,
388
- isMinimalChrome,
389
- selectedType
384
+ markExplicitSelection,
385
+ selectedType,
386
+ skipNextRestore
390
387
  ]);
391
388
  const handlePromptChange = useCallback((e)=>{
392
389
  const value = e.target.value;
@@ -719,8 +716,14 @@ const PromptInput = ({ runButtonEnabled, form, serviceMode, selectedType, dryMod
719
716
  actionNameForType(selectedType)
720
717
  ]
721
718
  });
719
+ var _chrome_icons_action;
720
+ const minimalActionIconSrc = null != (_chrome_icons_action = null == chrome ? void 0 : null == (_chrome_icons = chrome.icons) ? void 0 : _chrome_icons.action) ? _chrome_icons_action : STUDIO_MINIMAL_PROMPT_ICONS.action;
721
+ var _chrome_icons_actionChevron;
722
+ const minimalActionChevronSrc = null != (_chrome_icons_actionChevron = null == chrome ? void 0 : null == (_chrome_icons1 = chrome.icons) ? void 0 : _chrome_icons1.actionChevron) ? _chrome_icons_actionChevron : STUDIO_MINIMAL_PROMPT_ICONS.actionChevron;
723
+ var _chrome_icons_settings;
724
+ const minimalSettingsIconSrc = null != (_chrome_icons_settings = null == chrome ? void 0 : null == (_chrome_icons2 = chrome.icons) ? void 0 : _chrome_icons2.settings) ? _chrome_icons_settings : STUDIO_MINIMAL_PROMPT_ICONS.settings;
722
725
  if (isMinimalChrome) {
723
- var _chrome_icons, _chrome_icons1, _chrome_icons2, _chrome_icons3;
726
+ var _chrome_icons3;
724
727
  return /*#__PURE__*/ jsxs("div", {
725
728
  className: "prompt-input-wrapper prompt-input-wrapper-minimal",
726
729
  children: [
@@ -756,21 +759,19 @@ const PromptInput = ({ runButtonEnabled, form, serviceMode, selectedType, dryMod
756
759
  disabled: !runButtonEnabled,
757
760
  type: "button",
758
761
  children: [
759
- (null == chrome ? void 0 : null == (_chrome_icons = chrome.icons) ? void 0 : _chrome_icons.action) ? /*#__PURE__*/ jsx("img", {
762
+ /*#__PURE__*/ jsx("img", {
760
763
  alt: "",
761
764
  className: "minimal-action-icon",
762
- src: chrome.icons.action
763
- }) : null,
765
+ src: minimalActionIconSrc
766
+ }),
764
767
  /*#__PURE__*/ jsx("span", {
765
768
  className: "minimal-action-label",
766
769
  children: actionButtonLabel
767
770
  }),
768
- (null == chrome ? void 0 : null == (_chrome_icons1 = chrome.icons) ? void 0 : _chrome_icons1.actionChevron) ? /*#__PURE__*/ jsx("img", {
771
+ /*#__PURE__*/ jsx("img", {
769
772
  alt: "",
770
773
  className: "minimal-action-chevron",
771
- src: chrome.icons.actionChevron
772
- }) : /*#__PURE__*/ jsx(DownOutlined, {
773
- className: "minimal-action-chevron-fallback"
774
+ src: minimalActionChevronSrc
774
775
  })
775
776
  ]
776
777
  })
@@ -779,11 +780,12 @@ const PromptInput = ({ runButtonEnabled, form, serviceMode, selectedType, dryMod
779
780
  onSelect: handleSelectHistory,
780
781
  history: historyForSelectedType,
781
782
  currentType: selectedType,
783
+ popupPlacement: "top",
782
784
  trigger: /*#__PURE__*/ jsx("button", {
783
785
  "aria-label": "Open prompt history",
784
786
  className: "minimal-icon-trigger",
785
787
  type: "button",
786
- children: (null == chrome ? void 0 : null == (_chrome_icons2 = chrome.icons) ? void 0 : _chrome_icons2.history) ? /*#__PURE__*/ jsx("img", {
788
+ children: (null == chrome ? void 0 : null == (_chrome_icons3 = chrome.icons) ? void 0 : _chrome_icons3.history) ? /*#__PURE__*/ jsx("img", {
787
789
  alt: "",
788
790
  className: "minimal-toolbar-icon",
789
791
  src: chrome.icons.history
@@ -805,18 +807,15 @@ const PromptInput = ({ runButtonEnabled, form, serviceMode, selectedType, dryMod
805
807
  showDataExtractionOptions: showDataExtractionOptions,
806
808
  hideDomAndScreenshotOptions: hideDomAndScreenshotOptions,
807
809
  deviceType: deviceType,
810
+ popupPlacement: "topRight",
808
811
  trigger: /*#__PURE__*/ jsx("button", {
809
812
  "aria-label": "Open run configuration",
810
813
  className: "minimal-icon-trigger",
811
814
  type: "button",
812
- children: (null == chrome ? void 0 : null == (_chrome_icons3 = chrome.icons) ? void 0 : _chrome_icons3.settings) ? /*#__PURE__*/ jsx("img", {
815
+ children: /*#__PURE__*/ jsx("img", {
813
816
  alt: "",
814
817
  className: "minimal-toolbar-icon",
815
- src: chrome.icons.settings
816
- }) : /*#__PURE__*/ jsx(setting, {
817
- className: "minimal-toolbar-icon minimal-toolbar-icon-fallback",
818
- width: 16,
819
- height: 16
818
+ src: minimalSettingsIconSrc
820
819
  })
821
820
  })
822
821
  })
@@ -370,6 +370,135 @@
370
370
  text-decoration: underline;
371
371
  }
372
372
 
373
+ .playground-container.playground-conversation-skin .middle-dialog-area .info-list-container {
374
+ padding: 20px 16px 32px;
375
+ }
376
+
377
+ .playground-container.playground-conversation-skin .middle-dialog-area .info-list-container .ant-list-items {
378
+ flex-direction: column;
379
+ gap: 16px;
380
+ display: flex;
381
+ }
382
+
383
+ .playground-container.playground-conversation-skin .middle-dialog-area .info-list-container .list-item {
384
+ padding: 0;
385
+ }
386
+
387
+ .playground-container.playground-conversation-skin .user-message-container {
388
+ margin: 0;
389
+ }
390
+
391
+ .playground-container.playground-conversation-skin .user-message-container .user-message-bubble {
392
+ border-radius: 12px;
393
+ max-width: min(80%, 280px);
394
+ padding: 8px 16px;
395
+ font-size: 14px;
396
+ line-height: 22px;
397
+ }
398
+
399
+ .playground-container.playground-conversation-skin .bottom-input-section {
400
+ border-top: 1px solid var(--midscene-border-subtle);
401
+ background: var(--midscene-surface);
402
+ flex-shrink: 0;
403
+ padding: 12px;
404
+ }
405
+
406
+ .playground-container.playground-conversation-skin .list-item:has(.progress-action-item) {
407
+ padding-left: 0;
408
+ position: relative;
409
+ }
410
+
411
+ .playground-container.playground-conversation-skin .list-item > div:has( > .progress-action-item) {
412
+ flex-direction: column;
413
+ align-items: flex-start;
414
+ gap: 8px;
415
+ display: flex;
416
+ }
417
+
418
+ .playground-container.playground-conversation-skin .progress-action-item {
419
+ color: rgba(0, 0, 0, .7);
420
+ background: rgba(0, 0, 0, .08);
421
+ border-radius: 38px;
422
+ flex-direction: row-reverse;
423
+ justify-content: flex-end;
424
+ align-items: center;
425
+ gap: 8px;
426
+ width: -moz-fit-content;
427
+ width: fit-content;
428
+ max-width: 100%;
429
+ height: 28px;
430
+ margin: 0 0 0 24px;
431
+ padding: 2px 12px 2px 4px;
432
+ font-size: 14px;
433
+ line-height: 22px;
434
+ display: flex;
435
+ }
436
+
437
+ .playground-container.playground-conversation-skin .progress-action-item .progress-status-icon {
438
+ justify-content: center;
439
+ align-items: center;
440
+ width: 24px;
441
+ height: 24px;
442
+ margin-left: 0;
443
+ font-size: 14px;
444
+ display: inline-flex;
445
+ }
446
+
447
+ .playground-container.playground-conversation-skin .progress-action-item + div {
448
+ width: 100%;
449
+ margin: 0;
450
+ padding-left: 20px;
451
+ }
452
+
453
+ .playground-container.playground-conversation-skin .progress-description {
454
+ color: rgba(0, 0, 0, .85);
455
+ margin: 0;
456
+ padding: 0;
457
+ }
458
+
459
+ .playground-container.playground-conversation-skin .system-message-content, .playground-container.playground-conversation-skin .system-message-content .system-message-text {
460
+ color: rgba(0, 0, 0, .85);
461
+ font-size: 14px;
462
+ line-height: 22px;
463
+ }
464
+
465
+ .playground-container.playground-conversation-skin .list-item:has(.progress-action-item) + .list-item:has(.progress-action-item) {
466
+ margin-top: -8px;
467
+ }
468
+
469
+ .playground-container.playground-conversation-skin .list-item:has(.progress-action-item):has( + .list-item .progress-action-item):after {
470
+ content: "";
471
+ pointer-events: none;
472
+ background: rgba(0, 0, 0, .08);
473
+ width: 1px;
474
+ position: absolute;
475
+ top: 23px;
476
+ bottom: -16px;
477
+ left: 12px;
478
+ }
479
+
480
+ .playground-container.playground-conversation-skin .list-item:has(.progress-action-item) + .list-item:has(.progress-action-item):has( + .list-item .progress-action-item):after {
481
+ top: 0;
482
+ }
483
+
484
+ .playground-container.playground-conversation-skin .progress-group-toggle {
485
+ margin: 0 0 8px;
486
+ padding-left: 4px;
487
+ }
488
+
489
+ [data-theme="dark"] .playground-container.playground-conversation-skin .progress-action-item {
490
+ color: rgba(255, 255, 255, .7);
491
+ background: rgba(255, 255, 255, .08);
492
+ }
493
+
494
+ [data-theme="dark"] .playground-container.playground-conversation-skin .list-item:has(.progress-action-item):has( + .list-item .progress-action-item):after {
495
+ background: rgba(255, 255, 255, .12);
496
+ }
497
+
498
+ [data-theme="dark"] .playground-container.playground-conversation-skin .system-message-content, [data-theme="dark"] .playground-container.playground-conversation-skin .system-message-content .system-message-text, [data-theme="dark"] .playground-container.playground-conversation-skin .progress-description {
499
+ color: var(--midscene-text-primary);
500
+ }
501
+
373
502
  [data-theme="dark"] .universal-playground .error-hint {
374
503
  color: rgba(255, 255, 255, .45);
375
504
  }
@@ -11,6 +11,7 @@ import { PlaygroundResultView } from "../playground-result/index.mjs";
11
11
  import "./index.css";
12
12
  import avatar from "../../icons/avatar.mjs";
13
13
  import { defaultMainButtons } from "../../utils/constants.mjs";
14
+ import { resolveProgressActionIcon } from "../../utils/progress-action-icon.mjs";
14
15
  import { PromptInput } from "../prompt-input/index.mjs";
15
16
  import shiny_text from "../shiny-text/index.mjs";
16
17
  import { createStorageProvider, detectBestStorageType } from "./providers/storage-provider.mjs";
@@ -149,9 +150,11 @@ function UniversalPlayground({ playgroundSDK, storage, contextProvider, config:
149
150
  const layout = componentConfig.layout || 'vertical';
150
151
  const showVersionInfo = false !== componentConfig.showVersionInfo;
151
152
  const deviceType = componentConfig.deviceType;
152
- const collapsibleProgressGroup = true === componentConfig.collapsibleProgressGroup;
153
- var _componentConfig_progressGroupLabel;
154
- const progressGroupLabel = null != (_componentConfig_progressGroupLabel = componentConfig.progressGroupLabel) ? _componentConfig_progressGroupLabel : 'Execution Flow';
153
+ var _componentConfig_executionFlow;
154
+ const executionFlowConfig = null != (_componentConfig_executionFlow = componentConfig.executionFlow) ? _componentConfig_executionFlow : {};
155
+ const collapsibleProgressGroup = true === executionFlowConfig.collapsible;
156
+ var _executionFlowConfig_label;
157
+ const progressGroupLabel = null != (_executionFlowConfig_label = executionFlowConfig.label) ? _executionFlowConfig_label : 'Execution Flow';
155
158
  const [collapsedProgressGroups, setCollapsedProgressGroups] = useState(()=>new Set());
156
159
  const toggleProgressGroup = useCallback((groupId)=>{
157
160
  setCollapsedProgressGroups((prev)=>{
@@ -252,12 +255,14 @@ function UniversalPlayground({ playgroundSDK, storage, contextProvider, config:
252
255
  })
253
256
  }) : 'progress' === item.type ? /*#__PURE__*/ jsx("div", {
254
257
  children: (()=>{
255
- var _parts_, _item_result, _item_result1, _item_result2;
258
+ var _parts_, _item_result, _item_result1;
256
259
  const parts = item.content.split(' - ');
257
260
  const action = null == (_parts_ = parts[0]) ? void 0 : _parts_.trim();
258
261
  const description = parts.slice(1).join(' - ').trim();
259
262
  const isLatestProgress = item.id === latestProgressId;
260
263
  const shouldShowLoading = loading && isLatestProgress;
264
+ const state = shouldShowLoading ? 'loading' : (null == (_item_result = item.result) ? void 0 : _item_result.error) ? 'error' : 'completed';
265
+ const domainIcon = 'completed' === state ? resolveProgressActionIcon(item.actionKind, executionFlowConfig.resolveActionIcon) : null;
261
266
  return /*#__PURE__*/ jsxs(Fragment, {
262
267
  children: [
263
268
  action && /*#__PURE__*/ jsxs("span", {
@@ -265,10 +270,10 @@ function UniversalPlayground({ playgroundSDK, storage, contextProvider, config:
265
270
  children: [
266
271
  action,
267
272
  /*#__PURE__*/ jsx("span", {
268
- className: `progress-status-icon ${shouldShowLoading ? 'loading' : (null == (_item_result = item.result) ? void 0 : _item_result.error) ? 'error' : 'completed'}`,
269
- children: shouldShowLoading ? /*#__PURE__*/ jsx(LoadingOutlined, {
273
+ className: `progress-status-icon ${state}`,
274
+ children: 'loading' === state ? /*#__PURE__*/ jsx(LoadingOutlined, {
270
275
  spin: true
271
- }) : (null == (_item_result1 = item.result) ? void 0 : _item_result1.error) ? '✗' : '✓'
276
+ }) : 'error' === state ? '✗' : null !== domainIcon ? domainIcon : '✓'
272
277
  })
273
278
  ]
274
279
  }),
@@ -279,7 +284,7 @@ function UniversalPlayground({ playgroundSDK, storage, contextProvider, config:
279
284
  disabled: !shouldShowLoading
280
285
  })
281
286
  }),
282
- (null == (_item_result2 = item.result) ? void 0 : _item_result2.error) && /*#__PURE__*/ jsx(ErrorMessage, {
287
+ (null == (_item_result1 = item.result) ? void 0 : _item_result1.error) && /*#__PURE__*/ jsx(ErrorMessage, {
283
288
  error: item.result.error
284
289
  })
285
290
  ]
@@ -0,0 +1,47 @@
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
+ function useMinimalTypeGate(options) {
3
+ const { enabled, form, selectedType, onAfterReset, defaultType = 'aiAct' } = options;
4
+ const [hasExplicitSelection, setHasExplicitSelection] = useState(false);
5
+ const skipNextRestoreRef = useRef(false);
6
+ useEffect(()=>{
7
+ if (!enabled || hasExplicitSelection || !selectedType || selectedType === defaultType) return;
8
+ skipNextRestoreRef.current = false;
9
+ form.setFieldsValue({
10
+ type: defaultType,
11
+ prompt: '',
12
+ params: {}
13
+ });
14
+ null == onAfterReset || onAfterReset();
15
+ }, [
16
+ enabled,
17
+ hasExplicitSelection,
18
+ selectedType,
19
+ defaultType,
20
+ form,
21
+ onAfterReset
22
+ ]);
23
+ const markExplicitSelection = useCallback(()=>{
24
+ if (!enabled) return;
25
+ setHasExplicitSelection(true);
26
+ }, [
27
+ enabled
28
+ ]);
29
+ const skipNextRestore = useCallback(()=>{
30
+ skipNextRestoreRef.current = true;
31
+ }, []);
32
+ const shouldSkipRestoreOnce = useCallback(()=>{
33
+ if (!skipNextRestoreRef.current) return false;
34
+ skipNextRestoreRef.current = false;
35
+ return true;
36
+ }, []);
37
+ return useMemo(()=>({
38
+ markExplicitSelection,
39
+ skipNextRestore,
40
+ shouldSkipRestoreOnce
41
+ }), [
42
+ markExplicitSelection,
43
+ skipNextRestore,
44
+ shouldSkipRestoreOnce
45
+ ]);
46
+ }
47
+ export { useMinimalTypeGate };
@@ -143,6 +143,7 @@ function usePlaygroundExecution(options) {
143
143
  id: `progress-${thisRunningId}-task-${index}`,
144
144
  type: 'progress',
145
145
  content: buildProgressContent(task),
146
+ actionKind: typeStr(task),
146
147
  timestamp: new Date((null == (_task_timing = task.timing) ? void 0 : _task_timing.start) || Date.now()),
147
148
  result: task.error ? {
148
149
  error: formatError(task.error),