@midscene/visualizer 0.28.10-beta-20250917081519.0 → 0.28.10-beta-20250917142241.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.
- package/dist/es/component/history-selector/index.css +17 -15
- package/dist/es/component/history-selector/index.mjs +20 -4
- package/dist/es/component/nav-actions/index.mjs +32 -0
- package/dist/es/component/nav-actions/style.css +35 -0
- package/dist/es/component/player/index.css +2 -2
- package/dist/es/component/playground/index.css +22 -6
- package/dist/es/component/prompt-input/index.css +22 -6
- package/dist/es/component/prompt-input/index.mjs +39 -7
- package/dist/es/component/universal-playground/index.css +2 -2
- package/dist/es/component/universal-playground/providers/storage-provider.mjs +68 -4
- package/dist/es/hooks/usePlaygroundState.mjs +2 -1
- package/dist/es/index.mjs +2 -2
- package/dist/lib/component/history-selector/index.css +17 -15
- package/dist/lib/component/history-selector/index.js +19 -3
- package/dist/lib/component/nav-actions/index.js +66 -0
- package/dist/lib/component/nav-actions/style.css +35 -0
- package/dist/lib/component/player/index.css +2 -2
- package/dist/lib/component/playground/index.css +22 -6
- package/dist/lib/component/prompt-input/index.css +22 -6
- package/dist/lib/component/prompt-input/index.js +38 -6
- package/dist/lib/component/universal-playground/index.css +2 -2
- package/dist/lib/component/universal-playground/providers/storage-provider.js +68 -4
- package/dist/lib/hooks/usePlaygroundState.js +2 -1
- package/dist/lib/index.js +4 -4
- package/dist/types/component/nav-actions/index.d.ts +10 -0
- package/dist/types/component/universal-playground/providers/storage-provider.d.ts +9 -0
- package/dist/types/index.d.ts +2 -1
- package/package.json +6 -6
- package/dist/es/component/github-star/index.css +0 -4
- package/dist/es/component/github-star/index.mjs +0 -20
- package/dist/lib/component/github-star/index.css +0 -4
- package/dist/lib/component/github-star/index.js +0 -54
- package/dist/types/component/github-star/index.d.ts +0 -2
|
@@ -1,26 +1,28 @@
|
|
|
1
|
+
.history-selector-wrapper {
|
|
2
|
+
position: relative;
|
|
3
|
+
}
|
|
4
|
+
|
|
1
5
|
.history-modal-overlay {
|
|
2
|
-
z-index:
|
|
3
|
-
background:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
right:
|
|
6
|
+
z-index: 9999;
|
|
7
|
+
background: #fff;
|
|
8
|
+
border: 1px solid rgba(0, 0, 0, .08);
|
|
9
|
+
border-radius: 12px;
|
|
10
|
+
width: 320px;
|
|
11
|
+
height: 400px;
|
|
12
|
+
position: fixed;
|
|
13
|
+
top: auto;
|
|
14
|
+
bottom: 20px;
|
|
15
|
+
right: 20px;
|
|
16
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, .12);
|
|
12
17
|
}
|
|
13
18
|
|
|
14
19
|
.history-modal-container {
|
|
15
|
-
|
|
16
|
-
background: #fff;
|
|
17
|
-
border-radius: 12px 12px 0 0;
|
|
20
|
+
border-radius: 12px;
|
|
18
21
|
flex-direction: column;
|
|
19
22
|
width: 100%;
|
|
20
|
-
height:
|
|
23
|
+
height: 100%;
|
|
21
24
|
display: flex;
|
|
22
25
|
overflow: hidden;
|
|
23
|
-
box-shadow: 0 8px 24px rgba(0, 0, 0, .12);
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
.history-modal-container .history-modal-header {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Button, Input, Typography } from "antd";
|
|
3
|
-
import { useMemo, useState } from "react";
|
|
3
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
import icons_close from "../../icons/close.mjs";
|
|
5
5
|
import icons_history from "../../icons/history.mjs";
|
|
6
6
|
import magnifying_glass from "../../icons/magnifying-glass.mjs";
|
|
@@ -12,6 +12,7 @@ const HistorySelector = (param)=>{
|
|
|
12
12
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
13
13
|
const [searchText, setSearchText] = useState('');
|
|
14
14
|
const clearHistory = useHistoryStore((state)=>state.clearHistory);
|
|
15
|
+
const modalRef = useRef(null);
|
|
15
16
|
const groupedHistory = useMemo(()=>{
|
|
16
17
|
const now = Date.now();
|
|
17
18
|
const sevenDaysAgo = now - 604800000;
|
|
@@ -36,6 +37,21 @@ const HistorySelector = (param)=>{
|
|
|
36
37
|
setSearchText('');
|
|
37
38
|
setIsModalOpen(false);
|
|
38
39
|
};
|
|
40
|
+
useEffect(()=>{
|
|
41
|
+
if (!isModalOpen) return;
|
|
42
|
+
const handleClickOutside = (event)=>{
|
|
43
|
+
if (modalRef.current && !modalRef.current.contains(event.target)) setIsModalOpen(false);
|
|
44
|
+
};
|
|
45
|
+
const timer = setTimeout(()=>{
|
|
46
|
+
document.addEventListener('click', handleClickOutside);
|
|
47
|
+
}, 100);
|
|
48
|
+
return ()=>{
|
|
49
|
+
clearTimeout(timer);
|
|
50
|
+
document.removeEventListener('click', handleClickOutside);
|
|
51
|
+
};
|
|
52
|
+
}, [
|
|
53
|
+
isModalOpen
|
|
54
|
+
]);
|
|
39
55
|
const renderHistoryGroup = (title, items)=>{
|
|
40
56
|
if (0 === items.length) return null;
|
|
41
57
|
return /*#__PURE__*/ jsxs("div", {
|
|
@@ -53,7 +69,8 @@ const HistorySelector = (param)=>{
|
|
|
53
69
|
]
|
|
54
70
|
}, title);
|
|
55
71
|
};
|
|
56
|
-
return /*#__PURE__*/ jsxs(
|
|
72
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
73
|
+
className: "history-selector-wrapper",
|
|
57
74
|
children: [
|
|
58
75
|
/*#__PURE__*/ jsx("div", {
|
|
59
76
|
className: "selector-trigger",
|
|
@@ -65,10 +82,9 @@ const HistorySelector = (param)=>{
|
|
|
65
82
|
}),
|
|
66
83
|
isModalOpen && /*#__PURE__*/ jsx("div", {
|
|
67
84
|
className: "history-modal-overlay",
|
|
68
|
-
|
|
85
|
+
ref: modalRef,
|
|
69
86
|
children: /*#__PURE__*/ jsxs("div", {
|
|
70
87
|
className: "history-modal-container",
|
|
71
|
-
onClick: (e)=>e.stopPropagation(),
|
|
72
88
|
children: [
|
|
73
89
|
/*#__PURE__*/ jsxs("div", {
|
|
74
90
|
className: "history-modal-header",
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { GithubOutlined, QuestionCircleOutlined } from "@ant-design/icons";
|
|
3
|
+
import { Typography } from "antd";
|
|
4
|
+
import { EnvConfig } from "../env-config/index.mjs";
|
|
5
|
+
import "./style.css";
|
|
6
|
+
function NavActions(param) {
|
|
7
|
+
let { showEnvConfig = true, showTooltipWhenEmpty = false, showModelName = false, githubUrl = 'https://github.com/web-infra-dev/midscene', helpUrl = 'https://midscenejs.com/quick-experience.html', className = '' } = param;
|
|
8
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
9
|
+
className: `nav-actions ${className}`,
|
|
10
|
+
children: [
|
|
11
|
+
/*#__PURE__*/ jsx(Typography.Link, {
|
|
12
|
+
href: githubUrl,
|
|
13
|
+
target: "_blank",
|
|
14
|
+
children: /*#__PURE__*/ jsx(GithubOutlined, {
|
|
15
|
+
className: "nav-icon"
|
|
16
|
+
})
|
|
17
|
+
}),
|
|
18
|
+
/*#__PURE__*/ jsx(Typography.Link, {
|
|
19
|
+
href: helpUrl,
|
|
20
|
+
target: "_blank",
|
|
21
|
+
children: /*#__PURE__*/ jsx(QuestionCircleOutlined, {
|
|
22
|
+
className: "nav-icon"
|
|
23
|
+
})
|
|
24
|
+
}),
|
|
25
|
+
showEnvConfig && /*#__PURE__*/ jsx(EnvConfig, {
|
|
26
|
+
showTooltipWhenEmpty: showTooltipWhenEmpty,
|
|
27
|
+
showModelName: showModelName
|
|
28
|
+
})
|
|
29
|
+
]
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
export { NavActions };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
.nav-actions {
|
|
2
|
+
align-items: center;
|
|
3
|
+
gap: 8px;
|
|
4
|
+
display: flex;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.nav-actions .nav-icon {
|
|
8
|
+
color: rgba(0, 0, 0, .65);
|
|
9
|
+
cursor: pointer;
|
|
10
|
+
font-size: 16px;
|
|
11
|
+
transition: color .3s;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.nav-actions .nav-icon:hover {
|
|
15
|
+
color: #2b83ff;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.nav-actions a {
|
|
19
|
+
align-items: center;
|
|
20
|
+
text-decoration: none;
|
|
21
|
+
display: flex;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.nav-actions a:hover .nav-icon {
|
|
25
|
+
color: #2b83ff;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
[data-theme="dark"] .nav-actions .nav-icon {
|
|
29
|
+
color: rgba(255, 255, 255, .65);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
[data-theme="dark"] .nav-actions .nav-icon:hover {
|
|
33
|
+
color: #2b83ff;
|
|
34
|
+
}
|
|
35
|
+
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
min-height: 200px;
|
|
31
31
|
aspect-ratio: var(--canvas-aspect-ratio, 16 / 9);
|
|
32
32
|
background-color: #fff;
|
|
33
|
-
border-top-left-radius:
|
|
34
|
-
border-top-right-radius:
|
|
33
|
+
border-top-left-radius: 4px;
|
|
34
|
+
border-top-right-radius: 4px;
|
|
35
35
|
flex: none;
|
|
36
36
|
justify-content: center;
|
|
37
37
|
align-items: center;
|
|
@@ -44,21 +44,34 @@
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group {
|
|
47
|
-
scrollbar-width:
|
|
48
|
-
-ms-overflow-style: none;
|
|
47
|
+
scrollbar-width: thin;
|
|
49
48
|
flex: 1;
|
|
50
49
|
align-items: center;
|
|
51
50
|
gap: 8px;
|
|
52
51
|
min-width: 0;
|
|
53
52
|
height: 100%;
|
|
54
|
-
margin-right:
|
|
53
|
+
margin-right: 60px;
|
|
55
54
|
display: flex;
|
|
56
55
|
overflow-x: auto;
|
|
57
56
|
overflow-y: hidden;
|
|
58
57
|
}
|
|
59
58
|
|
|
60
59
|
.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group::-webkit-scrollbar {
|
|
61
|
-
|
|
60
|
+
height: 6px;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group::-webkit-scrollbar-track {
|
|
64
|
+
background: #f1f1f1;
|
|
65
|
+
border-radius: 3px;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group::-webkit-scrollbar-thumb {
|
|
69
|
+
background: #c1c1c1;
|
|
70
|
+
border-radius: 3px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group::-webkit-scrollbar-thumb:hover {
|
|
74
|
+
background: #a8a8a8;
|
|
62
75
|
}
|
|
63
76
|
|
|
64
77
|
.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .ant-form-item {
|
|
@@ -146,10 +159,13 @@
|
|
|
146
159
|
|
|
147
160
|
.prompt-input-wrapper .mode-radio-group-wrapper .action-icons {
|
|
148
161
|
z-index: 10;
|
|
149
|
-
background: #fff;
|
|
162
|
+
background: linear-gradient(to right, rgba(0, 0, 0, 0) 0%, rgba(255, 255, 255, .5) 20%, rgba(255, 255, 255, .8) 40%, rgba(255, 255, 255, .95) 60%, #fff 70%);
|
|
150
163
|
flex-shrink: 0;
|
|
164
|
+
justify-content: flex-end;
|
|
151
165
|
align-items: center;
|
|
152
|
-
|
|
166
|
+
gap: 8px;
|
|
167
|
+
width: 80px;
|
|
168
|
+
padding-left: 20px;
|
|
153
169
|
display: flex;
|
|
154
170
|
position: absolute;
|
|
155
171
|
top: 50%;
|
|
@@ -10,21 +10,34 @@
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group {
|
|
13
|
-
scrollbar-width:
|
|
14
|
-
-ms-overflow-style: none;
|
|
13
|
+
scrollbar-width: thin;
|
|
15
14
|
flex: 1;
|
|
16
15
|
align-items: center;
|
|
17
16
|
gap: 8px;
|
|
18
17
|
min-width: 0;
|
|
19
18
|
height: 100%;
|
|
20
|
-
margin-right:
|
|
19
|
+
margin-right: 60px;
|
|
21
20
|
display: flex;
|
|
22
21
|
overflow-x: auto;
|
|
23
22
|
overflow-y: hidden;
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group::-webkit-scrollbar {
|
|
27
|
-
|
|
26
|
+
height: 6px;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group::-webkit-scrollbar-track {
|
|
30
|
+
background: #f1f1f1;
|
|
31
|
+
border-radius: 3px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group::-webkit-scrollbar-thumb {
|
|
35
|
+
background: #c1c1c1;
|
|
36
|
+
border-radius: 3px;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group::-webkit-scrollbar-thumb:hover {
|
|
40
|
+
background: #a8a8a8;
|
|
28
41
|
}
|
|
29
42
|
|
|
30
43
|
.prompt-input-wrapper .mode-radio-group-wrapper .mode-radio-group .ant-form-item {
|
|
@@ -112,10 +125,13 @@
|
|
|
112
125
|
|
|
113
126
|
.prompt-input-wrapper .mode-radio-group-wrapper .action-icons {
|
|
114
127
|
z-index: 10;
|
|
115
|
-
background: #fff;
|
|
128
|
+
background: linear-gradient(to right, rgba(0, 0, 0, 0) 0%, rgba(255, 255, 255, .5) 20%, rgba(255, 255, 255, .8) 40%, rgba(255, 255, 255, .95) 60%, #fff 70%);
|
|
116
129
|
flex-shrink: 0;
|
|
130
|
+
justify-content: flex-end;
|
|
117
131
|
align-items: center;
|
|
118
|
-
|
|
132
|
+
gap: 8px;
|
|
133
|
+
width: 80px;
|
|
134
|
+
padding-left: 20px;
|
|
119
135
|
display: flex;
|
|
120
136
|
position: absolute;
|
|
121
137
|
top: 50%;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { BorderOutlined, DownOutlined, SendOutlined } from "@ant-design/icons";
|
|
3
3
|
import "./index.css";
|
|
4
|
-
import { Button, Dropdown, Form, Input, Radio,
|
|
4
|
+
import { Button, Dropdown, Form, Input, Radio, Tooltip } from "antd";
|
|
5
5
|
import react, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
6
6
|
import { useHistoryStore } from "../../store/history.mjs";
|
|
7
7
|
import { extractDefaultValue, isLocateField, isZodObjectSchema, unwrapZodType } from "../../types.mjs";
|
|
@@ -17,6 +17,7 @@ const PromptInput = (param)=>{
|
|
|
17
17
|
const [promptValue, setPromptValue] = useState('');
|
|
18
18
|
const placeholder = getPlaceholderForType(selectedType);
|
|
19
19
|
const textAreaRef = useRef(null);
|
|
20
|
+
const modeRadioGroupRef = useRef(null);
|
|
20
21
|
const params = Form.useWatch('params', form);
|
|
21
22
|
const lastHistoryRef = useRef(null);
|
|
22
23
|
const history = useHistoryStore((state)=>state.history);
|
|
@@ -160,6 +161,27 @@ const PromptInput = (param)=>{
|
|
|
160
161
|
lastSelectedType,
|
|
161
162
|
setLastSelectedType
|
|
162
163
|
]);
|
|
164
|
+
const scrollToSelectedItem = useCallback(()=>{
|
|
165
|
+
const container = modeRadioGroupRef.current;
|
|
166
|
+
if (!container) return;
|
|
167
|
+
let targetElement = null;
|
|
168
|
+
const selectedRadioButton = container.querySelector('.ant-radio-button-wrapper-checked');
|
|
169
|
+
const dropdownButton = container.querySelector('.more-apis-button.selected-from-dropdown');
|
|
170
|
+
if (selectedRadioButton) targetElement = selectedRadioButton;
|
|
171
|
+
else if (dropdownButton) targetElement = dropdownButton;
|
|
172
|
+
if (targetElement) {
|
|
173
|
+
const containerRect = container.getBoundingClientRect();
|
|
174
|
+
const targetRect = targetElement.getBoundingClientRect();
|
|
175
|
+
const targetLeft = targetRect.left - containerRect.left + container.scrollLeft;
|
|
176
|
+
const targetWidth = targetRect.width;
|
|
177
|
+
const containerWidth = containerRect.width;
|
|
178
|
+
const optimalScrollLeft = targetLeft - (containerWidth - targetWidth) / 2;
|
|
179
|
+
container.scrollTo({
|
|
180
|
+
left: Math.max(0, optimalScrollLeft),
|
|
181
|
+
behavior: 'smooth'
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}, []);
|
|
163
185
|
useEffect(()=>{
|
|
164
186
|
const lastHistory = historyForSelectedType[0];
|
|
165
187
|
if (lastHistory && lastHistoryRef.current && lastHistory.timestamp === lastHistoryRef.current.timestamp) return;
|
|
@@ -186,6 +208,15 @@ const PromptInput = (param)=>{
|
|
|
186
208
|
form,
|
|
187
209
|
getDefaultParams
|
|
188
210
|
]);
|
|
211
|
+
useEffect(()=>{
|
|
212
|
+
const timeoutId = setTimeout(()=>{
|
|
213
|
+
scrollToSelectedItem();
|
|
214
|
+
}, 100);
|
|
215
|
+
return ()=>clearTimeout(timeoutId);
|
|
216
|
+
}, [
|
|
217
|
+
selectedType,
|
|
218
|
+
scrollToSelectedItem
|
|
219
|
+
]);
|
|
189
220
|
const formPromptValue = Form.useWatch('prompt', form);
|
|
190
221
|
useEffect(()=>{
|
|
191
222
|
if (formPromptValue !== promptValue) setPromptValue(formPromptValue || '');
|
|
@@ -501,11 +532,12 @@ const PromptInput = (param)=>{
|
|
|
501
532
|
return /*#__PURE__*/ jsxs("div", {
|
|
502
533
|
className: "prompt-input-wrapper",
|
|
503
534
|
children: [
|
|
504
|
-
/*#__PURE__*/ jsxs(
|
|
535
|
+
/*#__PURE__*/ jsxs("div", {
|
|
505
536
|
className: "mode-radio-group-wrapper",
|
|
506
537
|
children: [
|
|
507
538
|
/*#__PURE__*/ jsxs("div", {
|
|
508
539
|
className: "mode-radio-group",
|
|
540
|
+
ref: modeRadioGroupRef,
|
|
509
541
|
children: [
|
|
510
542
|
/*#__PURE__*/ jsx(Form.Item, {
|
|
511
543
|
name: "type",
|
|
@@ -632,11 +664,6 @@ const PromptInput = (param)=>{
|
|
|
632
664
|
/*#__PURE__*/ jsxs("div", {
|
|
633
665
|
className: "action-icons",
|
|
634
666
|
children: [
|
|
635
|
-
/*#__PURE__*/ jsx(HistorySelector, {
|
|
636
|
-
onSelect: handleSelectHistory,
|
|
637
|
-
history: historyForSelectedType,
|
|
638
|
-
currentType: selectedType
|
|
639
|
-
}),
|
|
640
667
|
hasConfigOptions && /*#__PURE__*/ jsx("div", {
|
|
641
668
|
className: hoveringSettings ? 'settings-wrapper settings-wrapper-hover' : 'settings-wrapper',
|
|
642
669
|
onMouseEnter: handleMouseEnter,
|
|
@@ -647,6 +674,11 @@ const PromptInput = (param)=>{
|
|
|
647
674
|
showDataExtractionOptions: showDataExtractionOptions,
|
|
648
675
|
hideDomAndScreenshotOptions: hideDomAndScreenshotOptions
|
|
649
676
|
})
|
|
677
|
+
}),
|
|
678
|
+
/*#__PURE__*/ jsx(HistorySelector, {
|
|
679
|
+
onSelect: handleSelectHistory,
|
|
680
|
+
history: historyForSelectedType,
|
|
681
|
+
currentType: selectedType
|
|
650
682
|
})
|
|
651
683
|
]
|
|
652
684
|
})
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
.playground-container .middle-dialog-area .clear-button-container {
|
|
33
33
|
z-index: 10;
|
|
34
34
|
position: absolute;
|
|
35
|
-
top:
|
|
36
|
-
right:
|
|
35
|
+
top: 16px;
|
|
36
|
+
right: 0;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
.playground-container .middle-dialog-area .clear-button-container .clear-button {
|
|
@@ -9,15 +9,48 @@ function _define_property(obj, key, value) {
|
|
|
9
9
|
return obj;
|
|
10
10
|
}
|
|
11
11
|
class LocalStorageProvider {
|
|
12
|
+
checkStorageSpace() {
|
|
13
|
+
try {
|
|
14
|
+
const testKey = 'storage-test';
|
|
15
|
+
const testData = 'x'.repeat(102400);
|
|
16
|
+
localStorage.setItem(testKey, testData);
|
|
17
|
+
localStorage.removeItem(testKey);
|
|
18
|
+
return true;
|
|
19
|
+
} catch (e) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
12
23
|
async saveMessages(messages) {
|
|
13
24
|
try {
|
|
14
|
-
|
|
25
|
+
if (!this.checkStorageSpace()) {
|
|
26
|
+
console.warn('Low storage space detected, clearing old data...');
|
|
27
|
+
await this.handleQuotaExceeded();
|
|
28
|
+
}
|
|
29
|
+
const messagesToSave = messages.slice(-this.maxStorageItems);
|
|
30
|
+
const lightMessages = messagesToSave.map((msg)=>({
|
|
15
31
|
...msg,
|
|
16
32
|
result: void 0
|
|
17
33
|
}));
|
|
18
|
-
|
|
34
|
+
const messageData = JSON.stringify(lightMessages);
|
|
35
|
+
localStorage.setItem(this.messagesKey, messageData);
|
|
19
36
|
} catch (error) {
|
|
20
|
-
|
|
37
|
+
if (error instanceof DOMException && 'QuotaExceededError' === error.name) {
|
|
38
|
+
console.warn('LocalStorage quota exceeded, attempting to clear old data and retry...');
|
|
39
|
+
await this.handleQuotaExceeded();
|
|
40
|
+
try {
|
|
41
|
+
const recentMessages = messages.slice(-10);
|
|
42
|
+
const lightRecentMessages = recentMessages.map((msg)=>({
|
|
43
|
+
...msg,
|
|
44
|
+
result: void 0
|
|
45
|
+
}));
|
|
46
|
+
const messageData = JSON.stringify(lightRecentMessages);
|
|
47
|
+
localStorage.setItem(this.messagesKey, messageData);
|
|
48
|
+
console.info('Successfully saved recent messages after clearing storage');
|
|
49
|
+
} catch (retryError) {
|
|
50
|
+
console.error('Failed to save even after clearing storage:', retryError);
|
|
51
|
+
await this.clearMessages();
|
|
52
|
+
}
|
|
53
|
+
} else console.error('Failed to save messages to localStorage:', error);
|
|
21
54
|
}
|
|
22
55
|
}
|
|
23
56
|
async loadMessages() {
|
|
@@ -63,12 +96,43 @@ class LocalStorageProvider {
|
|
|
63
96
|
const resultKey = `${this.resultsKey}-${id}`;
|
|
64
97
|
localStorage.setItem(resultKey, JSON.stringify(result));
|
|
65
98
|
} catch (error) {
|
|
66
|
-
|
|
99
|
+
if (error instanceof DOMException && 'QuotaExceededError' === error.name) {
|
|
100
|
+
console.warn('LocalStorage quota exceeded when saving result, clearing old results...');
|
|
101
|
+
await this.handleQuotaExceeded();
|
|
102
|
+
try {
|
|
103
|
+
const resultKey = `${this.resultsKey}-${id}`;
|
|
104
|
+
localStorage.setItem(resultKey, JSON.stringify(result));
|
|
105
|
+
} catch (retryError) {
|
|
106
|
+
console.error('Failed to save result even after clearing storage:', retryError);
|
|
107
|
+
}
|
|
108
|
+
} else console.error('Failed to save result to localStorage:', error);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async handleQuotaExceeded() {
|
|
112
|
+
try {
|
|
113
|
+
const keys = Object.keys(localStorage);
|
|
114
|
+
const resultKeys = keys.filter((key)=>key.startsWith(this.resultsKey));
|
|
115
|
+
const keysToRemove = resultKeys.slice(0, Math.max(1, Math.floor(resultKeys.length / 2)));
|
|
116
|
+
keysToRemove.forEach((key)=>{
|
|
117
|
+
localStorage.removeItem(key);
|
|
118
|
+
});
|
|
119
|
+
console.info(`Cleared ${keysToRemove.length} old result entries to free up storage space`);
|
|
120
|
+
const playgroundKeys = keys.filter((key)=>key.includes('playground') || key.includes('agent') || key.startsWith('midscene'));
|
|
121
|
+
if (playgroundKeys.length > 10) {
|
|
122
|
+
const additionalKeysToRemove = playgroundKeys.slice(0, Math.floor(playgroundKeys.length / 3));
|
|
123
|
+
additionalKeysToRemove.forEach((key)=>{
|
|
124
|
+
if (key !== this.messagesKey) localStorage.removeItem(key);
|
|
125
|
+
});
|
|
126
|
+
console.info(`Cleared ${additionalKeysToRemove.length} additional playground-related entries`);
|
|
127
|
+
}
|
|
128
|
+
} catch (error) {
|
|
129
|
+
console.error('Failed to handle quota exceeded:', error);
|
|
67
130
|
}
|
|
68
131
|
}
|
|
69
132
|
constructor(namespace = 'playground'){
|
|
70
133
|
_define_property(this, "messagesKey", void 0);
|
|
71
134
|
_define_property(this, "resultsKey", void 0);
|
|
135
|
+
_define_property(this, "maxStorageItems", 50);
|
|
72
136
|
this.messagesKey = `${namespace}-messages`;
|
|
73
137
|
this.resultsKey = `${namespace}-results`;
|
|
74
138
|
}
|
|
@@ -40,7 +40,8 @@ function usePlaygroundState(playgroundSDK, storage, contextProvider) {
|
|
|
40
40
|
}, []);
|
|
41
41
|
useEffect(()=>{
|
|
42
42
|
if ((null == storage ? void 0 : storage.saveMessages) && infoList.length > 1) storage.saveMessages(infoList).catch((error)=>{
|
|
43
|
-
console.
|
|
43
|
+
if (error instanceof DOMException && 'QuotaExceededError' === error.name) console.warn('Storage quota exceeded - some messages may not be saved persistently');
|
|
44
|
+
else console.error('Failed to save messages:', error);
|
|
44
45
|
});
|
|
45
46
|
}, [
|
|
46
47
|
infoList,
|
package/dist/es/index.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { useEnvConfig } from "./store/store.mjs";
|
|
|
5
5
|
import { colorForName, globalThemeConfig, highlightColorForType } from "./utils/color.mjs";
|
|
6
6
|
import { EnvConfig } from "./component/env-config/index.mjs";
|
|
7
7
|
import { EnvConfigReminder } from "./component/env-config-reminder/index.mjs";
|
|
8
|
+
import { NavActions } from "./component/nav-actions/index.mjs";
|
|
8
9
|
import { Logo } from "./component/logo/index.mjs";
|
|
9
10
|
import { iconForStatus, timeCostStrElement } from "./component/misc/index.mjs";
|
|
10
11
|
import { useServerValid } from "./hooks/useServerValid.mjs";
|
|
@@ -15,11 +16,10 @@ import { ContextPreview } from "./component/context-preview/index.mjs";
|
|
|
15
16
|
import { PromptInput } from "./component/prompt-input/index.mjs";
|
|
16
17
|
import { Player } from "./component/player/index.mjs";
|
|
17
18
|
import { Blackboard } from "./component/blackboard/index.mjs";
|
|
18
|
-
import { GithubStar } from "./component/github-star/index.mjs";
|
|
19
19
|
import { actionNameForType, getPlaceholderForType, staticAgentFromContext } from "./utils/playground-utils.mjs";
|
|
20
20
|
import { filterBase64Value, timeStr } from "./utils/index.mjs";
|
|
21
21
|
import shiny_text from "./component/shiny-text/index.mjs";
|
|
22
22
|
import universal_playground, { UniversalPlayground } from "./component/universal-playground/index.mjs";
|
|
23
23
|
import { LocalStorageProvider, MemoryStorageProvider, NoOpStorageProvider } from "./component/universal-playground/providers/storage-provider.mjs";
|
|
24
24
|
import { AgentContextProvider, BaseContextProvider, NoOpContextProvider, StaticContextProvider } from "./component/universal-playground/providers/context-provider.mjs";
|
|
25
|
-
export { AgentContextProvider, BaseContextProvider, Blackboard, ContextPreview, EnvConfig, EnvConfigReminder,
|
|
25
|
+
export { AgentContextProvider, BaseContextProvider, Blackboard, ContextPreview, EnvConfig, EnvConfigReminder, LocalStorageProvider, Logo, MemoryStorageProvider, NavActions, 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,26 +1,28 @@
|
|
|
1
|
+
.history-selector-wrapper {
|
|
2
|
+
position: relative;
|
|
3
|
+
}
|
|
4
|
+
|
|
1
5
|
.history-modal-overlay {
|
|
2
|
-
z-index:
|
|
3
|
-
background:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
right:
|
|
6
|
+
z-index: 9999;
|
|
7
|
+
background: #fff;
|
|
8
|
+
border: 1px solid rgba(0, 0, 0, .08);
|
|
9
|
+
border-radius: 12px;
|
|
10
|
+
width: 320px;
|
|
11
|
+
height: 400px;
|
|
12
|
+
position: fixed;
|
|
13
|
+
top: auto;
|
|
14
|
+
bottom: 20px;
|
|
15
|
+
right: 20px;
|
|
16
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, .12);
|
|
12
17
|
}
|
|
13
18
|
|
|
14
19
|
.history-modal-container {
|
|
15
|
-
|
|
16
|
-
background: #fff;
|
|
17
|
-
border-radius: 12px 12px 0 0;
|
|
20
|
+
border-radius: 12px;
|
|
18
21
|
flex-direction: column;
|
|
19
22
|
width: 100%;
|
|
20
|
-
height:
|
|
23
|
+
height: 100%;
|
|
21
24
|
display: flex;
|
|
22
25
|
overflow: hidden;
|
|
23
|
-
box-shadow: 0 8px 24px rgba(0, 0, 0, .12);
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
.history-modal-container .history-modal-header {
|
|
@@ -52,6 +52,7 @@ const HistorySelector = (param)=>{
|
|
|
52
52
|
const [isModalOpen, setIsModalOpen] = (0, external_react_namespaceObject.useState)(false);
|
|
53
53
|
const [searchText, setSearchText] = (0, external_react_namespaceObject.useState)('');
|
|
54
54
|
const clearHistory = (0, external_store_history_js_namespaceObject.useHistoryStore)((state)=>state.clearHistory);
|
|
55
|
+
const modalRef = (0, external_react_namespaceObject.useRef)(null);
|
|
55
56
|
const groupedHistory = (0, external_react_namespaceObject.useMemo)(()=>{
|
|
56
57
|
const now = Date.now();
|
|
57
58
|
const sevenDaysAgo = now - 604800000;
|
|
@@ -76,6 +77,21 @@ const HistorySelector = (param)=>{
|
|
|
76
77
|
setSearchText('');
|
|
77
78
|
setIsModalOpen(false);
|
|
78
79
|
};
|
|
80
|
+
(0, external_react_namespaceObject.useEffect)(()=>{
|
|
81
|
+
if (!isModalOpen) return;
|
|
82
|
+
const handleClickOutside = (event)=>{
|
|
83
|
+
if (modalRef.current && !modalRef.current.contains(event.target)) setIsModalOpen(false);
|
|
84
|
+
};
|
|
85
|
+
const timer = setTimeout(()=>{
|
|
86
|
+
document.addEventListener('click', handleClickOutside);
|
|
87
|
+
}, 100);
|
|
88
|
+
return ()=>{
|
|
89
|
+
clearTimeout(timer);
|
|
90
|
+
document.removeEventListener('click', handleClickOutside);
|
|
91
|
+
};
|
|
92
|
+
}, [
|
|
93
|
+
isModalOpen
|
|
94
|
+
]);
|
|
79
95
|
const renderHistoryGroup = (title, items)=>{
|
|
80
96
|
if (0 === items.length) return null;
|
|
81
97
|
return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)("div", {
|
|
@@ -93,7 +109,8 @@ const HistorySelector = (param)=>{
|
|
|
93
109
|
]
|
|
94
110
|
}, title);
|
|
95
111
|
};
|
|
96
|
-
return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)(
|
|
112
|
+
return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)("div", {
|
|
113
|
+
className: "history-selector-wrapper",
|
|
97
114
|
children: [
|
|
98
115
|
/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("div", {
|
|
99
116
|
className: "selector-trigger",
|
|
@@ -105,10 +122,9 @@ const HistorySelector = (param)=>{
|
|
|
105
122
|
}),
|
|
106
123
|
isModalOpen && /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("div", {
|
|
107
124
|
className: "history-modal-overlay",
|
|
108
|
-
|
|
125
|
+
ref: modalRef,
|
|
109
126
|
children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)("div", {
|
|
110
127
|
className: "history-modal-container",
|
|
111
|
-
onClick: (e)=>e.stopPropagation(),
|
|
112
128
|
children: [
|
|
113
129
|
/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)("div", {
|
|
114
130
|
className: "history-modal-header",
|