@midscene/visualizer 0.28.7-beta-20250915040112.0 → 0.28.7-beta-20250915133700.0

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 (32) hide show
  1. package/dist/es/component/history-selector/index.css +18 -17
  2. package/dist/es/component/history-selector/index.mjs +5 -43
  3. package/dist/es/component/playground/index.css +42 -3
  4. package/dist/es/component/playground-result/index.css +0 -1
  5. package/dist/es/component/playground-result/index.mjs +1 -2
  6. package/dist/es/component/prompt-input/index.css +42 -2
  7. package/dist/es/component/service-mode-control/index.mjs +2 -2
  8. package/dist/es/component/universal-playground/index.css +2 -2
  9. package/dist/es/component/universal-playground/index.mjs +16 -16
  10. package/dist/es/hooks/usePlaygroundExecution.mjs +27 -12
  11. package/dist/es/hooks/usePlaygroundState.mjs +6 -8
  12. package/dist/es/hooks/useSafeOverrideAIConfig.mjs +24 -0
  13. package/dist/es/index.mjs +2 -1
  14. package/dist/lib/component/history-selector/index.css +18 -17
  15. package/dist/lib/component/history-selector/index.js +4 -42
  16. package/dist/lib/component/playground/index.css +42 -3
  17. package/dist/lib/component/playground-result/index.css +0 -1
  18. package/dist/lib/component/playground-result/index.js +1 -2
  19. package/dist/lib/component/prompt-input/index.css +42 -2
  20. package/dist/lib/component/service-mode-control/index.js +2 -2
  21. package/dist/lib/component/universal-playground/index.css +2 -2
  22. package/dist/lib/component/universal-playground/index.js +16 -16
  23. package/dist/lib/hooks/usePlaygroundExecution.js +27 -12
  24. package/dist/lib/hooks/usePlaygroundState.js +6 -8
  25. package/dist/lib/hooks/useSafeOverrideAIConfig.js +61 -0
  26. package/dist/lib/index.js +7 -0
  27. package/dist/types/hooks/usePlaygroundExecution.d.ts +1 -1
  28. package/dist/types/hooks/usePlaygroundState.d.ts +1 -1
  29. package/dist/types/hooks/useSafeOverrideAIConfig.d.ts +16 -0
  30. package/dist/types/index.d.ts +1 -0
  31. package/dist/types/types.d.ts +6 -10
  32. package/package.json +5 -5
@@ -1,9 +1,26 @@
1
+ .history-modal-overlay {
2
+ z-index: 1000;
3
+ background: rgba(0, 0, 0, .45);
4
+ justify-content: stretch;
5
+ align-items: flex-end;
6
+ display: flex;
7
+ position: absolute;
8
+ top: 0;
9
+ bottom: 0;
10
+ left: 0;
11
+ right: 0;
12
+ }
13
+
1
14
  .history-modal-container {
15
+ z-index: 1001;
16
+ background: #fff;
2
17
  border-radius: 12px 12px 0 0;
3
18
  flex-direction: column;
4
- height: 70vh;
19
+ width: 100%;
20
+ height: 400px;
5
21
  display: flex;
6
22
  overflow: hidden;
23
+ box-shadow: 0 8px 24px rgba(0, 0, 0, .12);
7
24
  }
8
25
 
9
26
  .history-modal-container .history-modal-header {
@@ -114,19 +131,3 @@
114
131
  padding: 40px 20px;
115
132
  }
116
133
 
117
- .ant-modal-wrap .ant-modal-content {
118
- animation: .3s cubic-bezier(.4, 0, .2, 1) forwards slideUpFromBottom !important;
119
- }
120
-
121
- @keyframes slideUpFromBottom {
122
- 0% {
123
- opacity: 0;
124
- transform: translateY(100%);
125
- }
126
-
127
- 100% {
128
- opacity: 1;
129
- transform: translateY(0);
130
- }
131
- }
132
-
@@ -1,5 +1,5 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
- import { Button, Input, Modal, Typography } from "antd";
2
+ import { Button, Input, Typography } from "antd";
3
3
  import { useMemo, useState } from "react";
4
4
  import icons_close from "../../icons/close.mjs";
5
5
  import icons_history from "../../icons/history.mjs";
@@ -63,50 +63,12 @@ const HistorySelector = (param)=>{
63
63
  height: 24
64
64
  })
65
65
  }),
66
- /*#__PURE__*/ jsx(Modal, {
67
- open: isModalOpen,
68
- onCancel: ()=>setIsModalOpen(false),
69
- footer: null,
70
- width: "100%",
71
- closable: false,
72
- centered: false,
73
- transitionName: "",
74
- maskTransitionName: "",
75
- style: {
76
- margin: 0,
77
- padding: 0,
78
- maxWidth: 'none',
79
- top: 'auto',
80
- bottom: 0
81
- },
82
- styles: {
83
- wrapper: {
84
- alignItems: 'flex-end',
85
- justifyContent: 'center',
86
- paddingBottom: 0,
87
- display: 'flex'
88
- },
89
- body: {
90
- height: '70vh',
91
- padding: 0,
92
- margin: 0
93
- },
94
- content: {
95
- height: '70vh',
96
- borderRadius: '12px 12px 0 0',
97
- margin: 0,
98
- padding: 0,
99
- marginBottom: 0,
100
- position: 'fixed',
101
- bottom: 0,
102
- left: 0,
103
- right: 0
104
- }
105
- },
106
- maskClosable: true,
107
- destroyOnClose: true,
66
+ isModalOpen && /*#__PURE__*/ jsx("div", {
67
+ className: "history-modal-overlay",
68
+ onClick: ()=>setIsModalOpen(false),
108
69
  children: /*#__PURE__*/ jsxs("div", {
109
70
  className: "history-modal-container",
71
+ onClick: (e)=>e.stopPropagation(),
110
72
  children: [
111
73
  /*#__PURE__*/ jsxs("div", {
112
74
  className: "history-modal-header",
@@ -1,6 +1,5 @@
1
1
  .result-wrapper {
2
2
  justify-content: center;
3
- align-items: center;
4
3
  height: 100%;
5
4
  margin: 4px 0;
6
5
  display: flex;
@@ -38,24 +37,50 @@
38
37
  }
39
38
 
40
39
  .prompt-input-wrapper .mode-radio-group-wrapper {
41
- justify-content: space-between;
42
40
  align-items: center;
41
+ gap: 8px;
43
42
  display: flex;
43
+ position: relative;
44
44
  }
45
45
 
46
46
  .prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group {
47
+ scrollbar-width: none;
48
+ -ms-overflow-style: none;
49
+ flex: 1;
47
50
  align-items: center;
51
+ gap: 8px;
52
+ min-width: 0;
48
53
  height: 100%;
54
+ margin-right: 80px;
55
+ display: flex;
56
+ overflow-x: auto;
57
+ overflow-y: hidden;
58
+ }
59
+
60
+ .prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group::-webkit-scrollbar {
61
+ display: none;
62
+ }
63
+
64
+ .prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .ant-form-item {
65
+ flex-shrink: 0;
66
+ margin: 0 !important;
67
+ }
68
+
69
+ .prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .ant-form-item .ant-radio-group {
70
+ flex-wrap: nowrap;
71
+ gap: 8px;
49
72
  display: flex;
50
73
  }
51
74
 
52
75
  .prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .ant-radio-button-wrapper {
53
76
  height: 24px;
54
77
  box-shadow: none;
78
+ white-space: nowrap;
55
79
  background-color: #f7f7f7;
56
80
  border: none;
57
81
  border-radius: 11px;
58
- margin-right: 8px;
82
+ flex-shrink: 0;
83
+ margin-right: 0;
59
84
  padding: 0 8px;
60
85
  font-size: 12px;
61
86
  line-height: 24px;
@@ -79,12 +104,18 @@
79
104
  color: #fff;
80
105
  }
81
106
 
107
+ .prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .ant-dropdown-trigger {
108
+ flex-shrink: 0;
109
+ }
110
+
82
111
  .prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .more-apis-button {
83
112
  height: 24px;
84
113
  box-shadow: none;
114
+ white-space: nowrap;
85
115
  background-color: #f7f7f7;
86
116
  border: none;
87
117
  border-radius: 11px;
118
+ flex-shrink: 0;
88
119
  align-items: center;
89
120
  gap: 2px;
90
121
  max-width: 160px;
@@ -114,8 +145,16 @@
114
145
  }
115
146
 
116
147
  .prompt-input-wrapper .mode-radio-group-wrapper .action-icons {
148
+ z-index: 10;
149
+ background: #fff;
150
+ flex-shrink: 0;
117
151
  align-items: center;
152
+ padding-left: 8px;
118
153
  display: flex;
154
+ position: absolute;
155
+ top: 50%;
156
+ right: 0;
157
+ transform: translateY(-50%);
119
158
  }
120
159
 
121
160
  .prompt-input-wrapper .main-side-console-input {
@@ -1,6 +1,5 @@
1
1
  .result-wrapper {
2
2
  justify-content: center;
3
- align-items: center;
4
3
  height: 100%;
5
4
  margin: 4px 0;
6
5
  display: flex;
@@ -54,8 +54,7 @@ const PlaygroundResultView = (param)=>{
54
54
  display: 'flex',
55
55
  flexDirection: 'column',
56
56
  flex: '1 1 auto',
57
- justifyContent: 'center',
58
- alignItems: 'center'
57
+ justifyContent: 'center'
59
58
  },
60
59
  children: resultDataToShow
61
60
  });
@@ -3,24 +3,50 @@
3
3
  }
4
4
 
5
5
  .prompt-input-wrapper .mode-radio-group-wrapper {
6
- justify-content: space-between;
7
6
  align-items: center;
7
+ gap: 8px;
8
8
  display: flex;
9
+ position: relative;
9
10
  }
10
11
 
11
12
  .prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group {
13
+ scrollbar-width: none;
14
+ -ms-overflow-style: none;
15
+ flex: 1;
12
16
  align-items: center;
17
+ gap: 8px;
18
+ min-width: 0;
13
19
  height: 100%;
20
+ margin-right: 80px;
21
+ display: flex;
22
+ overflow-x: auto;
23
+ overflow-y: hidden;
24
+ }
25
+
26
+ .prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group::-webkit-scrollbar {
27
+ display: none;
28
+ }
29
+
30
+ .prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .ant-form-item {
31
+ flex-shrink: 0;
32
+ margin: 0 !important;
33
+ }
34
+
35
+ .prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .ant-form-item .ant-radio-group {
36
+ flex-wrap: nowrap;
37
+ gap: 8px;
14
38
  display: flex;
15
39
  }
16
40
 
17
41
  .prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .ant-radio-button-wrapper {
18
42
  height: 24px;
19
43
  box-shadow: none;
44
+ white-space: nowrap;
20
45
  background-color: #f7f7f7;
21
46
  border: none;
22
47
  border-radius: 11px;
23
- margin-right: 8px;
48
+ flex-shrink: 0;
49
+ margin-right: 0;
24
50
  padding: 0 8px;
25
51
  font-size: 12px;
26
52
  line-height: 24px;
@@ -44,12 +70,18 @@
44
70
  color: #fff;
45
71
  }
46
72
 
73
+ .prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .ant-dropdown-trigger {
74
+ flex-shrink: 0;
75
+ }
76
+
47
77
  .prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .more-apis-button {
48
78
  height: 24px;
49
79
  box-shadow: none;
80
+ white-space: nowrap;
50
81
  background-color: #f7f7f7;
51
82
  border: none;
52
83
  border-radius: 11px;
84
+ flex-shrink: 0;
53
85
  align-items: center;
54
86
  gap: 2px;
55
87
  max-width: 160px;
@@ -79,8 +111,16 @@
79
111
  }
80
112
 
81
113
  .prompt-input-wrapper .mode-radio-group-wrapper .action-icons {
114
+ z-index: 10;
115
+ background: #fff;
116
+ flex-shrink: 0;
82
117
  align-items: center;
118
+ padding-left: 8px;
83
119
  display: flex;
120
+ position: absolute;
121
+ top: 50%;
122
+ right: 0;
123
+ transform: translateY(-50%);
84
124
  }
85
125
 
86
126
  .prompt-input-wrapper .main-side-console-input {
@@ -1,8 +1,8 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { PlaygroundSDK } from "@midscene/playground";
3
- import { overrideAIConfig } from "@midscene/shared/env";
4
3
  import { Button, Tooltip } from "antd";
5
4
  import { useEffect } from "react";
5
+ import { safeOverrideAIConfig } from "../../hooks/useSafeOverrideAIConfig.mjs";
6
6
  import { useServerValid } from "../../hooks/useServerValid.mjs";
7
7
  import { useEnvConfig } from "../../store/store.mjs";
8
8
  import { EnvConfig } from "../env-config/index.mjs";
@@ -57,7 +57,7 @@ const ServiceModeControl = (param)=>{
57
57
  });
58
58
  };
59
59
  useEffect(()=>{
60
- overrideAIConfig(config);
60
+ safeOverrideAIConfig(config, false, false);
61
61
  if ('Server' === serviceMode) {
62
62
  const playgroundSDK = new PlaygroundSDK({
63
63
  type: 'remote-execution'
@@ -4,13 +4,13 @@
4
4
  width: 100%;
5
5
  height: 100vh;
6
6
  display: flex;
7
+ position: relative;
7
8
  }
8
9
 
9
10
  .playground-container .command-form {
10
11
  flex-direction: column;
11
12
  width: 100%;
12
13
  height: 100%;
13
- padding: 0 12px;
14
14
  display: flex;
15
15
  }
16
16
 
@@ -119,7 +119,7 @@
119
119
 
120
120
  .playground-container .user-message-container .user-message-bubble {
121
121
  color: rgba(0, 0, 0, .85);
122
- text-align: center;
122
+ text-align: left;
123
123
  background: #f2f4f7;
124
124
  border-radius: 12px;
125
125
  max-width: 80%;
@@ -11,7 +11,12 @@ import { PlaygroundResultView } from "../playground-result/index.mjs";
11
11
  import "./index.css";
12
12
  import avatar from "../../icons/avatar.mjs";
13
13
  import { PromptInput } from "../prompt-input/index.mjs";
14
+ import { LocalStorageProvider } from "./providers/storage-provider.mjs";
14
15
  const { Text } = Typography;
16
+ function getSDKId(sdk) {
17
+ if (sdk.id && 'string' == typeof sdk.id) return `agent-${sdk.id}`;
18
+ return 'playground-default';
19
+ }
15
20
  function ErrorMessage(param) {
16
21
  let { error } = param;
17
22
  if (!error) return null;
@@ -35,26 +40,21 @@ function ErrorMessage(param) {
35
40
  function UniversalPlayground(param) {
36
41
  let { playgroundSDK, storage, contextProvider, config: componentConfig = {}, branding = {}, className = '', dryMode = false, showContextPreview = true } = param;
37
42
  const [form] = Form.useForm();
38
- const { deepThink, screenshotIncluded, domIncluded, config } = useEnvConfig();
39
- const enablePersistence = false !== componentConfig.enablePersistence;
40
- const { loading, setLoading, infoList, setInfoList, actionSpace, actionSpaceLoading, uiContextPreview, setUiContextPreview, showScrollToBottomButton, verticalMode, replayCounter, setReplayCounter, infoListRef, currentRunningIdRef, interruptedFlagRef, clearInfoList, handleScrollToBottom } = usePlaygroundState(playgroundSDK, storage, contextProvider, enablePersistence);
41
- const { handleRun: executeAction, handleStop, canStop } = usePlaygroundExecution(playgroundSDK, storage, actionSpace, loading, setLoading, infoList, setInfoList, replayCounter, setReplayCounter, verticalMode, currentRunningIdRef, interruptedFlagRef);
43
+ const { config } = useEnvConfig();
44
+ const effectiveStorage = (()=>{
45
+ if (storage) return storage;
46
+ const namespace = componentConfig.storageNamespace || getSDKId(playgroundSDK);
47
+ return new LocalStorageProvider(namespace);
48
+ })();
49
+ const { loading, setLoading, infoList, setInfoList, actionSpace, actionSpaceLoading, uiContextPreview, setUiContextPreview, showScrollToBottomButton, verticalMode, replayCounter, setReplayCounter, infoListRef, currentRunningIdRef, interruptedFlagRef, clearInfoList, handleScrollToBottom } = usePlaygroundState(playgroundSDK, effectiveStorage, contextProvider);
50
+ const { handleRun: executeAction, handleStop, canStop } = usePlaygroundExecution(playgroundSDK, effectiveStorage, actionSpace, loading, setLoading, infoList, setInfoList, replayCounter, setReplayCounter, verticalMode, currentRunningIdRef, interruptedFlagRef);
42
51
  useEffect(()=>{
43
- const completeConfig = {
44
- ...config,
45
- deepThink,
46
- screenshotIncluded,
47
- domIncluded
48
- };
49
- if (playgroundSDK.overrideConfig) playgroundSDK.overrideConfig(completeConfig).catch((error)=>{
52
+ if ((null == playgroundSDK ? void 0 : playgroundSDK.overrideConfig) && config) playgroundSDK.overrideConfig(config).catch((error)=>{
50
53
  console.error('Failed to override SDK config:', error);
51
54
  });
52
55
  }, [
53
56
  playgroundSDK,
54
- config,
55
- deepThink,
56
- screenshotIncluded,
57
- domIncluded
57
+ config
58
58
  ]);
59
59
  const handleFormRun = useCallback(async ()=>{
60
60
  try {
@@ -245,7 +245,7 @@ function UniversalPlayground(param) {
245
245
  /*#__PURE__*/ jsxs("div", {
246
246
  className: "bottom-input-section",
247
247
  children: [
248
- !componentConfig.serverMode && /*#__PURE__*/ jsx(EnvConfigReminder, {}),
248
+ componentConfig.showEnvConfigReminder ? /*#__PURE__*/ jsx(EnvConfigReminder, {}) : null,
249
249
  /*#__PURE__*/ jsx(PromptInput, {
250
250
  runButtonEnabled: runButtonEnabled,
251
251
  form: form,
@@ -1,4 +1,5 @@
1
1
  import { useCallback } from "react";
2
+ import { useEnvConfig } from "../store/store.mjs";
2
3
  import { BLANK_RESULT } from "../utils/constants.mjs";
3
4
  import { allScriptsFromDump } from "../utils/replay-scripts.mjs";
4
5
  const noReplayAPIs = [
@@ -6,7 +7,9 @@ const noReplayAPIs = [
6
7
  'aiAssert'
7
8
  ];
8
9
  function usePlaygroundExecution(playgroundSDK, storage, actionSpace, loading, setLoading, infoList, setInfoList, replayCounter, setReplayCounter, verticalMode, currentRunningIdRef, interruptedFlagRef) {
10
+ const { deepThink, screenshotIncluded, domIncluded } = useEnvConfig();
9
11
  const handleRun = useCallback(async (value)=>{
12
+ if (!playgroundSDK) return void console.warn('PlaygroundSDK is not available');
10
13
  const thisRunningId = Date.now();
11
14
  const actionType = value.type;
12
15
  const displayContent = `${value.type}: ${value.prompt || JSON.stringify(value.params)}`;
@@ -39,21 +42,29 @@ function usePlaygroundExecution(playgroundSDK, storage, actionSpace, loading, se
39
42
  try {
40
43
  currentRunningIdRef.current = thisRunningId;
41
44
  interruptedFlagRef.current[thisRunningId] = false;
45
+ if (playgroundSDK.onProgressUpdate) playgroundSDK.onProgressUpdate(()=>{});
42
46
  if (playgroundSDK.onProgressUpdate) playgroundSDK.onProgressUpdate((tip)=>{
43
47
  if (interruptedFlagRef.current[thisRunningId]) return;
44
- const progressItem = {
45
- id: `progress-${thisRunningId}-${Date.now()}`,
46
- type: 'progress',
47
- content: tip,
48
- timestamp: new Date()
49
- };
50
- setInfoList((prev)=>[
48
+ setInfoList((prev)=>{
49
+ const lastItem = prev[prev.length - 1];
50
+ if (lastItem && 'progress' === lastItem.type && lastItem.content === tip) return prev;
51
+ const progressItem = {
52
+ id: `progress-${thisRunningId}-${Date.now()}`,
53
+ type: 'progress',
54
+ content: tip,
55
+ timestamp: new Date()
56
+ };
57
+ return [
51
58
  ...prev,
52
59
  progressItem
53
- ]);
60
+ ];
61
+ });
54
62
  });
55
63
  result.result = await playgroundSDK.executeAction(actionType, value, {
56
- requestId: thisRunningId.toString()
64
+ requestId: thisRunningId.toString(),
65
+ deepThink,
66
+ screenshotIncluded,
67
+ domIncluded
57
68
  });
58
69
  if ('object' == typeof result.result && null !== result.result) {
59
70
  const resultObj = result.result;
@@ -124,14 +135,18 @@ function usePlaygroundExecution(playgroundSDK, storage, actionSpace, loading, se
124
135
  setReplayCounter,
125
136
  verticalMode,
126
137
  currentRunningIdRef,
127
- interruptedFlagRef
138
+ interruptedFlagRef,
139
+ deepThink,
140
+ screenshotIncluded,
141
+ domIncluded
128
142
  ]);
129
143
  const handleStop = useCallback(async ()=>{
130
144
  const thisRunningId = currentRunningIdRef.current;
131
- if (thisRunningId && playgroundSDK.cancelExecution) try {
145
+ if (thisRunningId && playgroundSDK && playgroundSDK.cancelExecution) try {
132
146
  await playgroundSDK.cancelExecution(thisRunningId.toString());
133
147
  interruptedFlagRef.current[thisRunningId] = true;
134
148
  setLoading(false);
149
+ if (playgroundSDK.onProgressUpdate) playgroundSDK.onProgressUpdate(()=>{});
135
150
  setInfoList((prev)=>prev.map((item)=>item.id === `system-${thisRunningId}` && item.loading ? {
136
151
  ...item,
137
152
  content: 'Operation stopped',
@@ -158,7 +173,7 @@ function usePlaygroundExecution(playgroundSDK, storage, actionSpace, loading, se
158
173
  setLoading,
159
174
  setInfoList
160
175
  ]);
161
- const canStop = loading && !!currentRunningIdRef.current && !!playgroundSDK.cancelExecution;
176
+ const canStop = loading && !!currentRunningIdRef.current && !!playgroundSDK && !!playgroundSDK.cancelExecution;
162
177
  return {
163
178
  handleRun,
164
179
  handleStop,
@@ -1,7 +1,6 @@
1
1
  import { useCallback, useEffect, useRef, useState } from "react";
2
2
  import { WELCOME_MESSAGE_TEMPLATE } from "../utils/constants.mjs";
3
3
  function usePlaygroundState(playgroundSDK, storage, contextProvider) {
4
- let enablePersistence = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : true;
5
4
  const [loading, setLoading] = useState(false);
6
5
  const [infoList, setInfoList] = useState([]);
7
6
  const [actionSpace, setActionSpace] = useState([]);
@@ -20,7 +19,7 @@ function usePlaygroundState(playgroundSDK, storage, contextProvider) {
20
19
  id: 'welcome',
21
20
  timestamp: new Date()
22
21
  };
23
- if (enablePersistence && (null == storage ? void 0 : storage.loadMessages)) try {
22
+ if (null == storage ? void 0 : storage.loadMessages) try {
24
23
  const storedMessages = await storage.loadMessages();
25
24
  const hasWelcomeMessage = storedMessages.some((msg)=>'welcome' === msg.id);
26
25
  hasWelcomeMessage ? setInfoList(storedMessages) : setInfoList([
@@ -40,13 +39,12 @@ function usePlaygroundState(playgroundSDK, storage, contextProvider) {
40
39
  if (0 === infoList.length) initializeMessages();
41
40
  }, []);
42
41
  useEffect(()=>{
43
- if (enablePersistence && (null == storage ? void 0 : storage.saveMessages) && infoList.length > 1) storage.saveMessages(infoList).catch((error)=>{
42
+ if ((null == storage ? void 0 : storage.saveMessages) && infoList.length > 1) storage.saveMessages(infoList).catch((error)=>{
44
43
  console.error('Failed to save messages:', error);
45
44
  });
46
45
  }, [
47
46
  infoList,
48
- storage,
49
- enablePersistence
47
+ storage
50
48
  ]);
51
49
  useEffect(()=>{
52
50
  if (!(null == contextProvider ? void 0 : contextProvider.getUIContext) || uiContextPreview) return;
@@ -62,6 +60,7 @@ function usePlaygroundState(playgroundSDK, storage, contextProvider) {
62
60
  setActionSpaceLoading(true);
63
61
  try {
64
62
  var _contextProvider_getUIContext;
63
+ if (!playgroundSDK) return void setActionSpace([]);
65
64
  const context = uiContextPreview || await (null == contextProvider ? void 0 : null == (_contextProvider_getUIContext = contextProvider.getUIContext) ? void 0 : _contextProvider_getUIContext.call(contextProvider));
66
65
  const space = await playgroundSDK.getActionSpace(context);
67
66
  setActionSpace(space || []);
@@ -135,14 +134,13 @@ function usePlaygroundState(playgroundSDK, storage, contextProvider) {
135
134
  setInfoList([
136
135
  welcomeMessage
137
136
  ]);
138
- if (enablePersistence && (null == storage ? void 0 : storage.clearMessages)) try {
137
+ if (null == storage ? void 0 : storage.clearMessages) try {
139
138
  await storage.clearMessages();
140
139
  } catch (error) {
141
140
  console.error('Failed to clear stored messages:', error);
142
141
  }
143
142
  }, [
144
- storage,
145
- enablePersistence
143
+ storage
146
144
  ]);
147
145
  const refreshContext = useCallback(async ()=>{
148
146
  if (null == contextProvider ? void 0 : contextProvider.refreshContext) try {
@@ -0,0 +1,24 @@
1
+ import { overrideAIConfig } from "@midscene/shared/env";
2
+ import { message } from "antd";
3
+ function safeOverrideAIConfig(newConfig) {
4
+ let extendMode = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : false, showErrorMessage = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : true;
5
+ try {
6
+ overrideAIConfig(newConfig, extendMode);
7
+ return true;
8
+ } catch (error) {
9
+ const err = error instanceof Error ? error : new Error(String(error));
10
+ console.error('Failed to override AI config:', err);
11
+ if (showErrorMessage) message.error(`Failed to apply AI configuration: ${err.message}`);
12
+ return false;
13
+ }
14
+ }
15
+ function useSafeOverrideAIConfig() {
16
+ const applyConfig = function(newConfig) {
17
+ let extendMode = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : false, showErrorMessage = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : true;
18
+ return safeOverrideAIConfig(newConfig, extendMode, showErrorMessage);
19
+ };
20
+ return {
21
+ applyConfig
22
+ };
23
+ }
24
+ export { safeOverrideAIConfig, useSafeOverrideAIConfig };
package/dist/es/index.mjs CHANGED
@@ -8,6 +8,7 @@ import { EnvConfigReminder } from "./component/env-config-reminder/index.mjs";
8
8
  import { Logo } from "./component/logo/index.mjs";
9
9
  import { iconForStatus, timeCostStrElement } from "./component/misc/index.mjs";
10
10
  import { useServerValid } from "./hooks/useServerValid.mjs";
11
+ import { safeOverrideAIConfig, useSafeOverrideAIConfig } from "./hooks/useSafeOverrideAIConfig.mjs";
11
12
  import { PlaygroundResultView } from "./component/playground-result/index.mjs";
12
13
  import { ServiceModeControl } from "./component/service-mode-control/index.mjs";
13
14
  import { ContextPreview } from "./component/context-preview/index.mjs";
@@ -21,4 +22,4 @@ import shiny_text from "./component/shiny-text/index.mjs";
21
22
  import universal_playground, { UniversalPlayground } from "./component/universal-playground/index.mjs";
22
23
  import { LocalStorageProvider, MemoryStorageProvider, NoOpStorageProvider } from "./component/universal-playground/providers/storage-provider.mjs";
23
24
  import { AgentContextProvider, BaseContextProvider, NoOpContextProvider, StaticContextProvider } from "./component/universal-playground/providers/context-provider.mjs";
24
- export { AgentContextProvider, BaseContextProvider, Blackboard, ContextPreview, EnvConfig, EnvConfigReminder, GithubStar, LocalStorageProvider, Logo, MemoryStorageProvider, NoOpContextProvider, NoOpStorageProvider, Player, PlaygroundResultView, PromptInput, ServiceModeControl, shiny_text as ShinyText, StaticContextProvider, UniversalPlayground, universal_playground as UniversalPlaygroundDefault, actionNameForType, allScriptsFromDump, colorForName, filterBase64Value, generateAnimationScripts, getPlaceholderForType, globalThemeConfig, highlightColorForType, iconForStatus, staticAgentFromContext, timeCostStrElement, timeStr, useEnvConfig, useServerValid };
25
+ export { AgentContextProvider, BaseContextProvider, Blackboard, ContextPreview, EnvConfig, EnvConfigReminder, GithubStar, LocalStorageProvider, Logo, MemoryStorageProvider, NoOpContextProvider, NoOpStorageProvider, Player, PlaygroundResultView, PromptInput, ServiceModeControl, shiny_text as ShinyText, StaticContextProvider, UniversalPlayground, universal_playground as UniversalPlaygroundDefault, actionNameForType, allScriptsFromDump, colorForName, filterBase64Value, generateAnimationScripts, getPlaceholderForType, globalThemeConfig, highlightColorForType, iconForStatus, safeOverrideAIConfig, staticAgentFromContext, timeCostStrElement, timeStr, useEnvConfig, useSafeOverrideAIConfig, useServerValid };
@@ -1,9 +1,26 @@
1
+ .history-modal-overlay {
2
+ z-index: 1000;
3
+ background: rgba(0, 0, 0, .45);
4
+ justify-content: stretch;
5
+ align-items: flex-end;
6
+ display: flex;
7
+ position: absolute;
8
+ top: 0;
9
+ bottom: 0;
10
+ left: 0;
11
+ right: 0;
12
+ }
13
+
1
14
  .history-modal-container {
15
+ z-index: 1001;
16
+ background: #fff;
2
17
  border-radius: 12px 12px 0 0;
3
18
  flex-direction: column;
4
- height: 70vh;
19
+ width: 100%;
20
+ height: 400px;
5
21
  display: flex;
6
22
  overflow: hidden;
23
+ box-shadow: 0 8px 24px rgba(0, 0, 0, .12);
7
24
  }
8
25
 
9
26
  .history-modal-container .history-modal-header {
@@ -114,19 +131,3 @@
114
131
  padding: 40px 20px;
115
132
  }
116
133
 
117
- .ant-modal-wrap .ant-modal-content {
118
- animation: .3s cubic-bezier(.4, 0, .2, 1) forwards slideUpFromBottom !important;
119
- }
120
-
121
- @keyframes slideUpFromBottom {
122
- 0% {
123
- opacity: 0;
124
- transform: translateY(100%);
125
- }
126
-
127
- 100% {
128
- opacity: 1;
129
- transform: translateY(0);
130
- }
131
- }
132
-