@midscene/visualizer 0.26.2 → 0.26.3-beta-20250813021342.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/blank_polyfill.mjs +2 -0
- package/dist/es/component/blackboard.css +12 -5
- package/dist/es/component/blackboard.mjs +266 -0
- package/dist/es/component/color.mjs +35 -0
- package/dist/es/component/describer.css +9 -5
- package/dist/es/component/describer.mjs +128 -0
- package/dist/es/component/env-config.mjs +112 -0
- package/dist/es/component/github-star.css +1 -0
- package/dist/es/component/github-star.mjs +20 -0
- package/dist/es/component/logo.css +5 -3
- package/dist/es/component/logo.mjs +20 -0
- package/dist/es/component/misc.mjs +54 -0
- package/dist/es/component/pixi-loader.mjs +16 -0
- package/dist/es/component/player.css +88 -70
- package/dist/es/component/player.mjs +628 -0
- package/dist/es/component/playground/ConfigSelector.mjs +53 -0
- package/dist/es/component/playground/ContextPreview.mjs +39 -0
- package/dist/es/component/playground/HistorySelector.mjs +193 -0
- package/dist/es/component/playground/PlaygroundResult.mjs +60 -0
- package/dist/es/component/playground/PromptInput.mjs +225 -0
- package/dist/es/component/playground/ServiceModeControl.mjs +100 -0
- package/dist/es/component/playground/index.css +140 -98
- package/dist/es/component/playground/playground-constants.mjs +45 -0
- package/dist/es/component/playground/playground-utils.mjs +89 -0
- package/dist/es/component/playground/useServerValid.mjs +27 -0
- package/dist/es/component/playground/useStaticPageAgent.mjs +12 -0
- package/dist/es/component/replay-scripts.mjs +271 -0
- package/dist/es/component/shiny-text.css +33 -22
- package/dist/es/component/shiny-text.mjs +15 -0
- package/dist/es/component/store/history.mjs +55 -0
- package/dist/es/component/store/store.mjs +128 -0
- package/dist/es/icons/close.mjs +19 -0
- package/dist/es/icons/history.mjs +30 -0
- package/dist/es/icons/magnifying-glass.mjs +39 -0
- package/dist/es/icons/setting.mjs +20 -0
- package/dist/es/index.mjs +21 -0
- package/dist/es/init.mjs +10 -0
- package/dist/es/{utils.js → utils.mjs} +51 -75
- package/dist/lib/blank_polyfill.js +34 -38
- package/dist/lib/component/blackboard.css +12 -5
- package/dist/lib/component/blackboard.js +293 -306
- package/dist/lib/component/color.js +64 -74
- package/dist/lib/component/describer.css +9 -5
- package/dist/lib/component/describer.js +158 -198
- package/dist/lib/component/env-config.js +142 -147
- package/dist/lib/component/github-star.css +1 -0
- package/dist/lib/component/github-star.js +51 -62
- package/dist/lib/component/logo.css +5 -3
- package/dist/lib/component/logo.js +53 -56
- package/dist/lib/component/misc.js +85 -84
- package/dist/lib/component/pixi-loader.js +49 -80
- package/dist/lib/component/player.css +88 -70
- package/dist/lib/component/player.js +627 -738
- package/dist/lib/component/playground/ConfigSelector.js +91 -92
- package/dist/lib/component/playground/ContextPreview.js +80 -72
- package/dist/lib/component/playground/HistorySelector.js +234 -197
- package/dist/lib/component/playground/PlaygroundResult.js +100 -103
- package/dist/lib/component/playground/PromptInput.js +250 -237
- package/dist/lib/component/playground/ServiceModeControl.js +124 -124
- package/dist/lib/component/playground/index.css +140 -98
- package/dist/lib/component/playground/playground-constants.js +97 -73
- package/dist/lib/component/playground/playground-types.js +17 -31
- package/dist/lib/component/playground/playground-utils.js +140 -168
- package/dist/lib/component/playground/useServerValid.js +55 -86
- package/dist/lib/component/playground/useStaticPageAgent.js +45 -51
- package/dist/lib/component/replay-scripts.js +291 -373
- package/dist/lib/component/shiny-text.css +33 -22
- package/dist/lib/component/shiny-text.js +46 -57
- package/dist/lib/component/store/history.js +58 -64
- package/dist/lib/component/store/store.js +132 -128
- package/dist/lib/icons/close.js +53 -0
- package/dist/lib/icons/history.js +64 -0
- package/dist/lib/icons/magnifying-glass.js +73 -0
- package/dist/lib/icons/setting.js +54 -0
- package/dist/lib/index.js +158 -124
- package/dist/lib/init.js +39 -46
- package/dist/lib/utils.js +105 -109
- package/dist/types/blank_polyfill.d.ts +2 -2
- package/dist/types/component/playground/ConfigSelector.d.ts +1 -0
- package/dist/types/component/playground/ContextPreview.d.ts +1 -0
- package/dist/types/component/playground/HistorySelector.d.ts +1 -0
- package/dist/types/component/playground/PlaygroundResult.d.ts +1 -0
- package/dist/types/component/playground/PromptInput.d.ts +1 -0
- package/dist/types/component/playground/ServiceModeControl.d.ts +1 -0
- package/package.json +16 -18
- package/dist/es/assets/close.909351c0.svg +0 -4
- package/dist/es/assets/history.164a4eab.svg +0 -4
- package/dist/es/assets/magnifying-glass.9498e70e.svg +0 -12
- package/dist/es/assets/setting.80ab7285.svg +0 -11
- package/dist/es/blank_polyfill.js +0 -10
- package/dist/es/component/blackboard.js +0 -286
- package/dist/es/component/color.js +0 -49
- package/dist/es/component/describer.js +0 -173
- package/dist/es/component/env-config.js +0 -117
- package/dist/es/component/github-star.js +0 -31
- package/dist/es/component/logo.js +0 -25
- package/dist/es/component/misc.js +0 -63
- package/dist/es/component/pixi-loader.js +0 -51
- package/dist/es/component/player.js +0 -746
- package/dist/es/component/playground/ConfigSelector.js +0 -64
- package/dist/es/component/playground/ContextPreview.js +0 -42
- package/dist/es/component/playground/HistorySelector.js +0 -168
- package/dist/es/component/playground/PlaygroundResult.js +0 -73
- package/dist/es/component/playground/PromptInput.js +0 -212
- package/dist/es/component/playground/ServiceModeControl.js +0 -100
- package/dist/es/component/playground/playground-constants.js +0 -39
- package/dist/es/component/playground/playground-types.js +0 -6
- package/dist/es/component/playground/playground-utils.js +0 -141
- package/dist/es/component/playground/useServerValid.js +0 -58
- package/dist/es/component/playground/useStaticPageAgent.js +0 -20
- package/dist/es/component/replay-scripts.js +0 -361
- package/dist/es/component/shiny-text.js +0 -30
- package/dist/es/component/store/history.js +0 -34
- package/dist/es/component/store/store.js +0 -99
- package/dist/es/index.js +0 -79
- package/dist/es/init.js +0 -17
- package/dist/index.css +0 -595
- package/dist/index.js +0 -1
- package/dist/lib/assets/close.909351c0.svg +0 -4
- package/dist/lib/assets/history.164a4eab.svg +0 -4
- package/dist/lib/assets/magnifying-glass.9498e70e.svg +0 -12
- package/dist/lib/assets/setting.80ab7285.svg +0 -11
- package/dist/lib/component/common.css +0 -0
- /package/dist/es/component/{common.css → playground/playground-types.mjs} +0 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button } from "antd";
|
|
3
|
+
import blackboard from "../blackboard.mjs";
|
|
4
|
+
import { iconForStatus } from "../misc.mjs";
|
|
5
|
+
import playground_demo_ui_context from "../playground-demo-ui-context.json";
|
|
6
|
+
import "./index.css";
|
|
7
|
+
const ContextPreview = (param)=>{
|
|
8
|
+
let { uiContextPreview, setUiContextPreview, showContextPreview } = param;
|
|
9
|
+
if (!showContextPreview) return null;
|
|
10
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
11
|
+
className: "form-part context-panel",
|
|
12
|
+
children: [
|
|
13
|
+
/*#__PURE__*/ jsx("h3", {
|
|
14
|
+
children: "UI Context"
|
|
15
|
+
}),
|
|
16
|
+
uiContextPreview ? /*#__PURE__*/ jsx(blackboard, {
|
|
17
|
+
uiContext: uiContextPreview,
|
|
18
|
+
hideController: true
|
|
19
|
+
}) : /*#__PURE__*/ jsxs("div", {
|
|
20
|
+
children: [
|
|
21
|
+
iconForStatus('failed'),
|
|
22
|
+
" No UI context",
|
|
23
|
+
/*#__PURE__*/ jsx(Button, {
|
|
24
|
+
type: "link",
|
|
25
|
+
onClick: (e)=>{
|
|
26
|
+
e.preventDefault();
|
|
27
|
+
setUiContextPreview(playground_demo_ui_context);
|
|
28
|
+
},
|
|
29
|
+
children: "Load Demo"
|
|
30
|
+
}),
|
|
31
|
+
/*#__PURE__*/ jsx("div", {
|
|
32
|
+
children: "To load the UI context, you can either use the demo data above, or click the 'Send to Playground' in the report page."
|
|
33
|
+
})
|
|
34
|
+
]
|
|
35
|
+
})
|
|
36
|
+
]
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
export { ContextPreview };
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, Input, Modal, Typography } from "antd";
|
|
3
|
+
import { useMemo, useState } from "react";
|
|
4
|
+
import icons_close from "../../icons/close.mjs";
|
|
5
|
+
import icons_history from "../../icons/history.mjs";
|
|
6
|
+
import magnifying_glass from "../../icons/magnifying-glass.mjs";
|
|
7
|
+
import { useHistoryStore } from "../store/history.mjs";
|
|
8
|
+
import "./index.css";
|
|
9
|
+
const { Text } = Typography;
|
|
10
|
+
const HistorySelector = (param)=>{
|
|
11
|
+
let { onSelect } = param;
|
|
12
|
+
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
13
|
+
const [searchText, setSearchText] = useState('');
|
|
14
|
+
const history = useHistoryStore((state)=>state.history);
|
|
15
|
+
const clearHistory = useHistoryStore((state)=>state.clearHistory);
|
|
16
|
+
const groupedHistory = useMemo(()=>{
|
|
17
|
+
const now = Date.now();
|
|
18
|
+
const sevenDaysAgo = now - 604800000;
|
|
19
|
+
const oneYearAgo = now - 31536000000;
|
|
20
|
+
const filteredHistory = history.filter((item)=>item.prompt.toLowerCase().includes(searchText.toLowerCase()));
|
|
21
|
+
const groups = {
|
|
22
|
+
recent7Days: filteredHistory.filter((item)=>item.timestamp >= sevenDaysAgo),
|
|
23
|
+
recent1Year: filteredHistory.filter((item)=>item.timestamp < sevenDaysAgo && item.timestamp >= oneYearAgo),
|
|
24
|
+
older: filteredHistory.filter((item)=>item.timestamp < oneYearAgo)
|
|
25
|
+
};
|
|
26
|
+
return groups;
|
|
27
|
+
}, [
|
|
28
|
+
history,
|
|
29
|
+
searchText
|
|
30
|
+
]);
|
|
31
|
+
const handleHistoryClick = (item)=>{
|
|
32
|
+
onSelect(item);
|
|
33
|
+
setIsModalOpen(false);
|
|
34
|
+
};
|
|
35
|
+
const handleClearHistory = ()=>{
|
|
36
|
+
clearHistory();
|
|
37
|
+
setSearchText('');
|
|
38
|
+
setIsModalOpen(false);
|
|
39
|
+
};
|
|
40
|
+
const renderHistoryGroup = (title, items)=>{
|
|
41
|
+
if (0 === items.length) return null;
|
|
42
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
43
|
+
className: "history-group",
|
|
44
|
+
children: [
|
|
45
|
+
/*#__PURE__*/ jsx("div", {
|
|
46
|
+
className: "history-group-title",
|
|
47
|
+
children: title
|
|
48
|
+
}),
|
|
49
|
+
items.map((item, index)=>/*#__PURE__*/ jsx("div", {
|
|
50
|
+
className: "history-item",
|
|
51
|
+
onClick: ()=>handleHistoryClick(item),
|
|
52
|
+
children: item.prompt
|
|
53
|
+
}, `${item.timestamp}-${index}`))
|
|
54
|
+
]
|
|
55
|
+
}, title);
|
|
56
|
+
};
|
|
57
|
+
return /*#__PURE__*/ jsxs(Fragment, {
|
|
58
|
+
children: [
|
|
59
|
+
/*#__PURE__*/ jsx("div", {
|
|
60
|
+
className: "selector-trigger",
|
|
61
|
+
onClick: ()=>setIsModalOpen(true),
|
|
62
|
+
children: /*#__PURE__*/ jsx(icons_history, {
|
|
63
|
+
width: 24,
|
|
64
|
+
height: 24
|
|
65
|
+
})
|
|
66
|
+
}),
|
|
67
|
+
/*#__PURE__*/ jsx(Modal, {
|
|
68
|
+
open: isModalOpen,
|
|
69
|
+
onCancel: ()=>setIsModalOpen(false),
|
|
70
|
+
footer: null,
|
|
71
|
+
width: "100%",
|
|
72
|
+
closable: false,
|
|
73
|
+
centered: false,
|
|
74
|
+
transitionName: "",
|
|
75
|
+
maskTransitionName: "",
|
|
76
|
+
style: {
|
|
77
|
+
margin: 0,
|
|
78
|
+
padding: 0,
|
|
79
|
+
maxWidth: 'none',
|
|
80
|
+
top: 'auto',
|
|
81
|
+
bottom: 0
|
|
82
|
+
},
|
|
83
|
+
styles: {
|
|
84
|
+
wrapper: {
|
|
85
|
+
alignItems: 'flex-end',
|
|
86
|
+
justifyContent: 'center',
|
|
87
|
+
paddingBottom: 0,
|
|
88
|
+
display: 'flex'
|
|
89
|
+
},
|
|
90
|
+
body: {
|
|
91
|
+
height: '70vh',
|
|
92
|
+
padding: 0,
|
|
93
|
+
margin: 0
|
|
94
|
+
},
|
|
95
|
+
content: {
|
|
96
|
+
height: '70vh',
|
|
97
|
+
borderRadius: '12px 12px 0 0',
|
|
98
|
+
margin: 0,
|
|
99
|
+
padding: 0,
|
|
100
|
+
marginBottom: 0,
|
|
101
|
+
position: 'fixed',
|
|
102
|
+
bottom: 0,
|
|
103
|
+
left: 0,
|
|
104
|
+
right: 0
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
maskClosable: true,
|
|
108
|
+
destroyOnClose: true,
|
|
109
|
+
children: /*#__PURE__*/ jsxs("div", {
|
|
110
|
+
className: "history-modal-container",
|
|
111
|
+
children: [
|
|
112
|
+
/*#__PURE__*/ jsxs("div", {
|
|
113
|
+
className: "history-modal-header",
|
|
114
|
+
children: [
|
|
115
|
+
/*#__PURE__*/ jsxs(Text, {
|
|
116
|
+
strong: true,
|
|
117
|
+
style: {
|
|
118
|
+
fontSize: '16px'
|
|
119
|
+
},
|
|
120
|
+
children: [
|
|
121
|
+
"History (",
|
|
122
|
+
history.length,
|
|
123
|
+
")"
|
|
124
|
+
]
|
|
125
|
+
}),
|
|
126
|
+
/*#__PURE__*/ jsx(Button, {
|
|
127
|
+
size: "small",
|
|
128
|
+
type: "text",
|
|
129
|
+
icon: /*#__PURE__*/ jsx(icons_close, {
|
|
130
|
+
width: 16,
|
|
131
|
+
height: 16
|
|
132
|
+
}),
|
|
133
|
+
onClick: ()=>setIsModalOpen(false),
|
|
134
|
+
className: "close-button"
|
|
135
|
+
})
|
|
136
|
+
]
|
|
137
|
+
}),
|
|
138
|
+
/*#__PURE__*/ jsx("div", {
|
|
139
|
+
className: "history-search-section",
|
|
140
|
+
children: /*#__PURE__*/ jsxs("div", {
|
|
141
|
+
className: "search-input-wrapper",
|
|
142
|
+
children: [
|
|
143
|
+
/*#__PURE__*/ jsx(Input, {
|
|
144
|
+
placeholder: "Search",
|
|
145
|
+
value: searchText,
|
|
146
|
+
onChange: (e)=>setSearchText(e.target.value),
|
|
147
|
+
prefix: /*#__PURE__*/ jsx(magnifying_glass, {
|
|
148
|
+
width: 18,
|
|
149
|
+
height: 18
|
|
150
|
+
}),
|
|
151
|
+
className: "search-input",
|
|
152
|
+
allowClear: true
|
|
153
|
+
}),
|
|
154
|
+
/*#__PURE__*/ jsx(Button, {
|
|
155
|
+
type: "link",
|
|
156
|
+
onClick: handleClearHistory,
|
|
157
|
+
className: "clear-button",
|
|
158
|
+
disabled: 0 === history.length,
|
|
159
|
+
children: "Clear"
|
|
160
|
+
})
|
|
161
|
+
]
|
|
162
|
+
})
|
|
163
|
+
}),
|
|
164
|
+
/*#__PURE__*/ jsx("div", {
|
|
165
|
+
className: "history-content",
|
|
166
|
+
children: 0 === history.length ? /*#__PURE__*/ jsx("div", {
|
|
167
|
+
className: "no-results",
|
|
168
|
+
children: /*#__PURE__*/ jsx(Text, {
|
|
169
|
+
type: "secondary",
|
|
170
|
+
children: "No history record"
|
|
171
|
+
})
|
|
172
|
+
}) : /*#__PURE__*/ jsxs(Fragment, {
|
|
173
|
+
children: [
|
|
174
|
+
renderHistoryGroup('Last 7 days', groupedHistory.recent7Days),
|
|
175
|
+
renderHistoryGroup('Last 1 year', groupedHistory.recent1Year),
|
|
176
|
+
renderHistoryGroup('Earlier', groupedHistory.older),
|
|
177
|
+
searchText && 0 === groupedHistory.recent7Days.length && 0 === groupedHistory.recent1Year.length && 0 === groupedHistory.older.length && /*#__PURE__*/ jsx("div", {
|
|
178
|
+
className: "no-results",
|
|
179
|
+
children: /*#__PURE__*/ jsx(Text, {
|
|
180
|
+
type: "secondary",
|
|
181
|
+
children: "No matching history record"
|
|
182
|
+
})
|
|
183
|
+
})
|
|
184
|
+
]
|
|
185
|
+
})
|
|
186
|
+
})
|
|
187
|
+
]
|
|
188
|
+
})
|
|
189
|
+
})
|
|
190
|
+
]
|
|
191
|
+
});
|
|
192
|
+
};
|
|
193
|
+
export { HistorySelector };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { LoadingOutlined } from "@ant-design/icons";
|
|
3
|
+
import { Spin } from "antd";
|
|
4
|
+
import { Player } from "../player.mjs";
|
|
5
|
+
import shiny_text from "../shiny-text.mjs";
|
|
6
|
+
import { emptyResultTip, serverLaunchTip } from "./playground-constants.mjs";
|
|
7
|
+
import "./index.css";
|
|
8
|
+
const PlaygroundResultView = (param)=>{
|
|
9
|
+
let { result, loading, serverValid, serviceMode, replayScriptsInfo, replayCounter, loadingProgressText, verticalMode = false, notReadyMessage, fitMode } = param;
|
|
10
|
+
let resultWrapperClassName = 'result-wrapper';
|
|
11
|
+
if (verticalMode) resultWrapperClassName += ' vertical-mode-result';
|
|
12
|
+
if (replayScriptsInfo && verticalMode) resultWrapperClassName += ' result-wrapper-compact';
|
|
13
|
+
let resultDataToShow = emptyResultTip;
|
|
14
|
+
if (serverValid || 'Server' !== serviceMode) {
|
|
15
|
+
if (loading) resultDataToShow = /*#__PURE__*/ jsxs("div", {
|
|
16
|
+
className: "loading-container",
|
|
17
|
+
children: [
|
|
18
|
+
/*#__PURE__*/ jsx(Spin, {
|
|
19
|
+
spinning: loading,
|
|
20
|
+
indicator: /*#__PURE__*/ jsx(LoadingOutlined, {
|
|
21
|
+
spin: true
|
|
22
|
+
})
|
|
23
|
+
}),
|
|
24
|
+
/*#__PURE__*/ jsx("div", {
|
|
25
|
+
className: "loading-progress-text loading-progress-text-progress",
|
|
26
|
+
children: /*#__PURE__*/ jsx(shiny_text, {
|
|
27
|
+
text: loadingProgressText,
|
|
28
|
+
speed: 3
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
]
|
|
32
|
+
});
|
|
33
|
+
else if (replayScriptsInfo) resultDataToShow = /*#__PURE__*/ jsx(Player, {
|
|
34
|
+
replayScripts: replayScriptsInfo.scripts,
|
|
35
|
+
imageWidth: replayScriptsInfo.width,
|
|
36
|
+
imageHeight: replayScriptsInfo.height,
|
|
37
|
+
reportFileContent: ('In-Browser-Extension' === serviceMode || 'Server' === serviceMode) && (null == result ? void 0 : result.reportHTML) ? null == result ? void 0 : result.reportHTML : null,
|
|
38
|
+
fitMode: fitMode
|
|
39
|
+
}, replayCounter);
|
|
40
|
+
else if (null == result ? void 0 : result.error) resultDataToShow = /*#__PURE__*/ jsx("pre", {
|
|
41
|
+
children: null == result ? void 0 : result.error
|
|
42
|
+
});
|
|
43
|
+
else if ((null == result ? void 0 : result.result) !== void 0) resultDataToShow = 'string' == typeof (null == result ? void 0 : result.result) ? /*#__PURE__*/ jsx("pre", {
|
|
44
|
+
children: null == result ? void 0 : result.result
|
|
45
|
+
}) : /*#__PURE__*/ jsx("pre", {
|
|
46
|
+
children: JSON.stringify(null == result ? void 0 : result.result, null, 2)
|
|
47
|
+
});
|
|
48
|
+
} else resultDataToShow = serverLaunchTip(notReadyMessage);
|
|
49
|
+
return /*#__PURE__*/ jsx("div", {
|
|
50
|
+
className: resultWrapperClassName,
|
|
51
|
+
style: {
|
|
52
|
+
height: '100%',
|
|
53
|
+
display: 'flex',
|
|
54
|
+
flexDirection: 'column',
|
|
55
|
+
flex: '1 1 auto'
|
|
56
|
+
},
|
|
57
|
+
children: resultDataToShow
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
export { PlaygroundResultView };
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { BorderOutlined, SendOutlined } from "@ant-design/icons";
|
|
3
|
+
import { Button, Form, Input, Radio, Space, Tooltip } from "antd";
|
|
4
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
5
|
+
import { useHistoryStore } from "../store/history.mjs";
|
|
6
|
+
import { ConfigSelector } from "./ConfigSelector.mjs";
|
|
7
|
+
import { HistorySelector } from "./HistorySelector.mjs";
|
|
8
|
+
import { actionNameForType, getPlaceholderForType } from "./playground-utils.mjs";
|
|
9
|
+
import "./index.css";
|
|
10
|
+
const { TextArea } = Input;
|
|
11
|
+
const PromptInput = (param)=>{
|
|
12
|
+
let { runButtonEnabled, form, serviceMode, selectedType, dryMode, stoppable, loading, onRun, onStop, clearPromptAfterRun = true } = param;
|
|
13
|
+
const [hoveringSettings, setHoveringSettings] = useState(false);
|
|
14
|
+
const [promptValue, setPromptValue] = useState('');
|
|
15
|
+
const placeholder = getPlaceholderForType(selectedType);
|
|
16
|
+
const textAreaRef = useRef(null);
|
|
17
|
+
const history = useHistoryStore((state)=>state.history);
|
|
18
|
+
const addHistory = useHistoryStore((state)=>state.addHistory);
|
|
19
|
+
const lastHistory = history[0];
|
|
20
|
+
useEffect(()=>{
|
|
21
|
+
if (lastHistory) {
|
|
22
|
+
form.setFieldsValue({
|
|
23
|
+
type: lastHistory.type || 'aiAction',
|
|
24
|
+
prompt: lastHistory.prompt || ''
|
|
25
|
+
});
|
|
26
|
+
setPromptValue(lastHistory.prompt || '');
|
|
27
|
+
} else {
|
|
28
|
+
form.setFieldsValue({
|
|
29
|
+
type: 'aiAction',
|
|
30
|
+
prompt: ''
|
|
31
|
+
});
|
|
32
|
+
setPromptValue('');
|
|
33
|
+
}
|
|
34
|
+
}, []);
|
|
35
|
+
const handleSelectHistory = useCallback((historyItem)=>{
|
|
36
|
+
form.setFieldsValue({
|
|
37
|
+
prompt: historyItem.prompt,
|
|
38
|
+
type: historyItem.type
|
|
39
|
+
});
|
|
40
|
+
setPromptValue(historyItem.prompt);
|
|
41
|
+
}, [
|
|
42
|
+
form
|
|
43
|
+
]);
|
|
44
|
+
const handlePromptChange = useCallback((e)=>{
|
|
45
|
+
const value = e.target.value;
|
|
46
|
+
setPromptValue(value);
|
|
47
|
+
form.setFieldValue('prompt', value);
|
|
48
|
+
}, [
|
|
49
|
+
form
|
|
50
|
+
]);
|
|
51
|
+
const isRunButtonEnabled = runButtonEnabled && promptValue.trim().length > 0;
|
|
52
|
+
const handleRunWithHistory = useCallback(()=>{
|
|
53
|
+
const values = form.getFieldsValue();
|
|
54
|
+
if (values.prompt) addHistory({
|
|
55
|
+
type: values.type,
|
|
56
|
+
prompt: values.prompt,
|
|
57
|
+
timestamp: Date.now()
|
|
58
|
+
});
|
|
59
|
+
onRun();
|
|
60
|
+
if (clearPromptAfterRun) {
|
|
61
|
+
setPromptValue('');
|
|
62
|
+
form.setFieldValue('prompt', '');
|
|
63
|
+
}
|
|
64
|
+
}, [
|
|
65
|
+
form,
|
|
66
|
+
addHistory,
|
|
67
|
+
onRun
|
|
68
|
+
]);
|
|
69
|
+
const handleKeyDown = useCallback((e)=>{
|
|
70
|
+
if ('Enter' === e.key && e.metaKey && isRunButtonEnabled) {
|
|
71
|
+
handleRunWithHistory();
|
|
72
|
+
e.preventDefault();
|
|
73
|
+
e.stopPropagation();
|
|
74
|
+
} else if ('Enter' === e.key) setTimeout(()=>{
|
|
75
|
+
if (textAreaRef.current) {
|
|
76
|
+
const textarea = textAreaRef.current.resizableTextArea.textArea;
|
|
77
|
+
const selectionStart = textarea.selectionStart;
|
|
78
|
+
const value = textarea.value;
|
|
79
|
+
const lastNewlineIndex = value.lastIndexOf('\n');
|
|
80
|
+
const isAtLastLine = -1 === lastNewlineIndex || selectionStart > lastNewlineIndex;
|
|
81
|
+
if (isAtLastLine) textarea.scrollTop = textarea.scrollHeight;
|
|
82
|
+
}
|
|
83
|
+
}, 0);
|
|
84
|
+
}, [
|
|
85
|
+
handleRunWithHistory,
|
|
86
|
+
isRunButtonEnabled
|
|
87
|
+
]);
|
|
88
|
+
const handleMouseEnter = useCallback(()=>{
|
|
89
|
+
setHoveringSettings(true);
|
|
90
|
+
}, []);
|
|
91
|
+
const handleMouseLeave = useCallback(()=>{
|
|
92
|
+
setHoveringSettings(false);
|
|
93
|
+
}, []);
|
|
94
|
+
const renderActionButton = useCallback(()=>{
|
|
95
|
+
const runButton = (text)=>/*#__PURE__*/ jsx(Button, {
|
|
96
|
+
type: "primary",
|
|
97
|
+
icon: /*#__PURE__*/ jsx(SendOutlined, {}),
|
|
98
|
+
style: {
|
|
99
|
+
borderRadius: 20,
|
|
100
|
+
zIndex: 999
|
|
101
|
+
},
|
|
102
|
+
onClick: handleRunWithHistory,
|
|
103
|
+
disabled: !isRunButtonEnabled,
|
|
104
|
+
loading: loading,
|
|
105
|
+
children: text
|
|
106
|
+
});
|
|
107
|
+
if (dryMode) return 'aiAction' === selectedType ? /*#__PURE__*/ jsx(Tooltip, {
|
|
108
|
+
title: "Start executing until some interaction actions need to be performed. You can see the process of planning and locating.",
|
|
109
|
+
children: runButton('Dry Run')
|
|
110
|
+
}) : runButton('Run');
|
|
111
|
+
if (stoppable) return /*#__PURE__*/ jsx(Button, {
|
|
112
|
+
icon: /*#__PURE__*/ jsx(BorderOutlined, {}),
|
|
113
|
+
onClick: onStop,
|
|
114
|
+
style: {
|
|
115
|
+
borderRadius: 20,
|
|
116
|
+
zIndex: 999
|
|
117
|
+
},
|
|
118
|
+
children: "Stop"
|
|
119
|
+
});
|
|
120
|
+
return runButton('Run');
|
|
121
|
+
}, [
|
|
122
|
+
dryMode,
|
|
123
|
+
loading,
|
|
124
|
+
handleRunWithHistory,
|
|
125
|
+
onStop,
|
|
126
|
+
isRunButtonEnabled,
|
|
127
|
+
selectedType,
|
|
128
|
+
stoppable
|
|
129
|
+
]);
|
|
130
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
131
|
+
className: "prompt-input-wrapper",
|
|
132
|
+
children: [
|
|
133
|
+
/*#__PURE__*/ jsxs(Space, {
|
|
134
|
+
className: "mode-radio-group-wrapper",
|
|
135
|
+
children: [
|
|
136
|
+
/*#__PURE__*/ jsx(Form.Item, {
|
|
137
|
+
name: "type",
|
|
138
|
+
style: {
|
|
139
|
+
margin: 0
|
|
140
|
+
},
|
|
141
|
+
children: /*#__PURE__*/ jsxs(Radio.Group, {
|
|
142
|
+
buttonStyle: "solid",
|
|
143
|
+
disabled: !runButtonEnabled,
|
|
144
|
+
className: "mode-radio-group",
|
|
145
|
+
children: [
|
|
146
|
+
/*#__PURE__*/ jsx(Tooltip, {
|
|
147
|
+
title: "Auto Planning: plan the steps and execute",
|
|
148
|
+
children: /*#__PURE__*/ jsx(Radio.Button, {
|
|
149
|
+
value: "aiAction",
|
|
150
|
+
children: actionNameForType('aiAction')
|
|
151
|
+
})
|
|
152
|
+
}),
|
|
153
|
+
/*#__PURE__*/ jsx(Tooltip, {
|
|
154
|
+
title: "Extract data directly from the UI",
|
|
155
|
+
children: /*#__PURE__*/ jsx(Radio.Button, {
|
|
156
|
+
value: "aiQuery",
|
|
157
|
+
children: actionNameForType('aiQuery')
|
|
158
|
+
})
|
|
159
|
+
}),
|
|
160
|
+
/*#__PURE__*/ jsx(Tooltip, {
|
|
161
|
+
title: "Understand the UI and determine if the assertion is true",
|
|
162
|
+
children: /*#__PURE__*/ jsx(Radio.Button, {
|
|
163
|
+
value: "aiAssert",
|
|
164
|
+
children: actionNameForType('aiAssert')
|
|
165
|
+
})
|
|
166
|
+
}),
|
|
167
|
+
/*#__PURE__*/ jsx(Tooltip, {
|
|
168
|
+
title: "Instant Action: click something",
|
|
169
|
+
children: /*#__PURE__*/ jsx(Radio.Button, {
|
|
170
|
+
value: "aiTap",
|
|
171
|
+
children: actionNameForType('aiTap')
|
|
172
|
+
})
|
|
173
|
+
})
|
|
174
|
+
]
|
|
175
|
+
})
|
|
176
|
+
}),
|
|
177
|
+
/*#__PURE__*/ jsxs("div", {
|
|
178
|
+
className: "action-icons",
|
|
179
|
+
children: [
|
|
180
|
+
/*#__PURE__*/ jsx(HistorySelector, {
|
|
181
|
+
onSelect: handleSelectHistory
|
|
182
|
+
}),
|
|
183
|
+
/*#__PURE__*/ jsx("div", {
|
|
184
|
+
className: hoveringSettings ? 'settings-wrapper settings-wrapper-hover' : 'settings-wrapper',
|
|
185
|
+
onMouseEnter: handleMouseEnter,
|
|
186
|
+
onMouseLeave: handleMouseLeave,
|
|
187
|
+
children: /*#__PURE__*/ jsx(ConfigSelector, {
|
|
188
|
+
enableTracking: 'In-Browser-Extension' === serviceMode,
|
|
189
|
+
showDeepThinkOption: 'aiTap' === selectedType
|
|
190
|
+
})
|
|
191
|
+
})
|
|
192
|
+
]
|
|
193
|
+
})
|
|
194
|
+
]
|
|
195
|
+
}),
|
|
196
|
+
/*#__PURE__*/ jsxs("div", {
|
|
197
|
+
className: `main-side-console-input ${!runButtonEnabled ? 'disabled' : ''} ${loading ? 'loading' : ''}`,
|
|
198
|
+
children: [
|
|
199
|
+
/*#__PURE__*/ jsx(Form.Item, {
|
|
200
|
+
name: "prompt",
|
|
201
|
+
style: {
|
|
202
|
+
margin: 0
|
|
203
|
+
},
|
|
204
|
+
children: /*#__PURE__*/ jsx(TextArea, {
|
|
205
|
+
className: "main-side-console-input-textarea",
|
|
206
|
+
disabled: !runButtonEnabled,
|
|
207
|
+
rows: 4,
|
|
208
|
+
placeholder: placeholder,
|
|
209
|
+
autoFocus: true,
|
|
210
|
+
onKeyDown: handleKeyDown,
|
|
211
|
+
onChange: handlePromptChange,
|
|
212
|
+
value: promptValue,
|
|
213
|
+
ref: textAreaRef
|
|
214
|
+
})
|
|
215
|
+
}),
|
|
216
|
+
/*#__PURE__*/ jsx("div", {
|
|
217
|
+
className: "form-controller-wrapper",
|
|
218
|
+
children: renderActionButton()
|
|
219
|
+
})
|
|
220
|
+
]
|
|
221
|
+
})
|
|
222
|
+
]
|
|
223
|
+
});
|
|
224
|
+
};
|
|
225
|
+
export { PromptInput };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { overrideAIConfig } from "@midscene/shared/env";
|
|
3
|
+
import { Button, Tooltip } from "antd";
|
|
4
|
+
import { useEffect } from "react";
|
|
5
|
+
import { EnvConfig } from "../env-config.mjs";
|
|
6
|
+
import { iconForStatus } from "../misc.mjs";
|
|
7
|
+
import { useEnvConfig } from "../store/store.mjs";
|
|
8
|
+
import { overrideServerConfig } from "./playground-utils.mjs";
|
|
9
|
+
import { useServerValid } from "./useServerValid.mjs";
|
|
10
|
+
import "./index.css";
|
|
11
|
+
const TITLE_TEXT = {
|
|
12
|
+
Server: 'Server Status',
|
|
13
|
+
'In-Browser': 'In-Browser'
|
|
14
|
+
};
|
|
15
|
+
const SWITCH_BUTTON_TEXT = {
|
|
16
|
+
Server: 'Switch to In-Browser Mode',
|
|
17
|
+
'In-Browser': 'Switch to Server Mode'
|
|
18
|
+
};
|
|
19
|
+
const ServiceModeControl = (param)=>{
|
|
20
|
+
let { serviceMode } = param;
|
|
21
|
+
const { setServiceMode, config } = useEnvConfig();
|
|
22
|
+
const serverValid = useServerValid('Server' === serviceMode);
|
|
23
|
+
const renderServerTip = ()=>{
|
|
24
|
+
if (serverValid) return /*#__PURE__*/ jsx(Tooltip, {
|
|
25
|
+
title: "Connected",
|
|
26
|
+
children: /*#__PURE__*/ jsx("div", {
|
|
27
|
+
className: "server-tip",
|
|
28
|
+
children: iconForStatus('connected')
|
|
29
|
+
})
|
|
30
|
+
});
|
|
31
|
+
return /*#__PURE__*/ jsx(Tooltip, {
|
|
32
|
+
title: "Connection failed",
|
|
33
|
+
children: /*#__PURE__*/ jsx("div", {
|
|
34
|
+
className: "server-tip",
|
|
35
|
+
children: iconForStatus('failed')
|
|
36
|
+
})
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
const renderSwitchButton = ()=>{
|
|
40
|
+
const nextMode = 'Server' === serviceMode ? 'In-Browser' : 'Server';
|
|
41
|
+
const buttonText = SWITCH_BUTTON_TEXT[serviceMode];
|
|
42
|
+
return /*#__PURE__*/ jsx(Tooltip, {
|
|
43
|
+
title: /*#__PURE__*/ jsxs("span", {
|
|
44
|
+
children: [
|
|
45
|
+
"Server Mode: send the request through the server ",
|
|
46
|
+
/*#__PURE__*/ jsx("br", {}),
|
|
47
|
+
"In-Browser Mode: send the request through the browser fetch API (The AI service should support CORS in this case)"
|
|
48
|
+
]
|
|
49
|
+
}),
|
|
50
|
+
children: /*#__PURE__*/ jsx(Button, {
|
|
51
|
+
type: "link",
|
|
52
|
+
onClick: (e)=>{
|
|
53
|
+
e.preventDefault();
|
|
54
|
+
setServiceMode(nextMode);
|
|
55
|
+
},
|
|
56
|
+
children: buttonText
|
|
57
|
+
})
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
useEffect(()=>{
|
|
61
|
+
overrideAIConfig(config);
|
|
62
|
+
if ('Server' === serviceMode) overrideServerConfig(config);
|
|
63
|
+
}, [
|
|
64
|
+
config,
|
|
65
|
+
serviceMode
|
|
66
|
+
]);
|
|
67
|
+
const statusContent = 'Server' === serviceMode && renderServerTip();
|
|
68
|
+
const title = TITLE_TEXT[serviceMode];
|
|
69
|
+
return /*#__PURE__*/ jsxs(Fragment, {
|
|
70
|
+
children: [
|
|
71
|
+
/*#__PURE__*/ jsxs("div", {
|
|
72
|
+
style: {
|
|
73
|
+
display: 'flex',
|
|
74
|
+
alignItems: 'center',
|
|
75
|
+
justifyContent: 'space-between',
|
|
76
|
+
gap: '10px'
|
|
77
|
+
},
|
|
78
|
+
children: [
|
|
79
|
+
/*#__PURE__*/ jsx("h3", {
|
|
80
|
+
style: {
|
|
81
|
+
whiteSpace: 'nowrap',
|
|
82
|
+
margin: 0,
|
|
83
|
+
flexShrink: 0
|
|
84
|
+
},
|
|
85
|
+
children: title
|
|
86
|
+
}),
|
|
87
|
+
statusContent,
|
|
88
|
+
/*#__PURE__*/ jsx(EnvConfig, {
|
|
89
|
+
showTooltipWhenEmpty: 'Server' !== serviceMode
|
|
90
|
+
})
|
|
91
|
+
]
|
|
92
|
+
}),
|
|
93
|
+
/*#__PURE__*/ jsx("div", {
|
|
94
|
+
className: "switch-btn-wrapper",
|
|
95
|
+
children: renderSwitchButton()
|
|
96
|
+
})
|
|
97
|
+
]
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
export { ServiceModeControl };
|