@midscene/visualizer 1.0.1-beta-20251209112631.0 → 1.0.1-beta-20251211095502.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 (27) hide show
  1. package/dist/es/component/player/index.mjs +2 -2
  2. package/dist/es/component/playground-result/index.mjs +12 -5
  3. package/dist/es/component/shiny-text/index.css +20 -3
  4. package/dist/es/component/shiny-text/index.mjs +3 -2
  5. package/dist/es/component/universal-playground/index.css +0 -1
  6. package/dist/es/component/universal-playground/index.mjs +49 -52
  7. package/dist/es/component/universal-playground/providers/indexeddb-storage-provider.mjs +13 -18
  8. package/dist/es/component/universal-playground/providers/storage-provider.mjs +2 -2
  9. package/dist/es/hooks/usePlaygroundExecution.mjs +105 -20
  10. package/dist/es/index.mjs +2 -2
  11. package/dist/es/store/store.mjs +23 -2
  12. package/dist/lib/component/player/index.js +1 -1
  13. package/dist/lib/component/playground-result/index.js +12 -5
  14. package/dist/lib/component/shiny-text/index.css +20 -3
  15. package/dist/lib/component/shiny-text/index.js +3 -2
  16. package/dist/lib/component/universal-playground/index.css +0 -1
  17. package/dist/lib/component/universal-playground/index.js +49 -51
  18. package/dist/lib/component/universal-playground/providers/indexeddb-storage-provider.js +13 -18
  19. package/dist/lib/component/universal-playground/providers/storage-provider.js +2 -2
  20. package/dist/lib/hooks/usePlaygroundExecution.js +105 -20
  21. package/dist/lib/index.js +3 -0
  22. package/dist/lib/store/store.js +26 -5
  23. package/dist/types/hooks/usePlaygroundExecution.d.ts +1 -1
  24. package/dist/types/index.d.ts +1 -1
  25. package/dist/types/store/store.d.ts +5 -1
  26. package/dist/types/types.d.ts +8 -2
  27. package/package.json +5 -5
@@ -9,7 +9,7 @@ import { CaretRightOutlined, DownloadOutlined, ExportOutlined, LoadingOutlined }
9
9
  import { Dropdown, Spin, Switch, Tooltip, message } from "antd";
10
10
  import global_perspective from "../../icons/global-perspective.mjs";
11
11
  import player_setting from "../../icons/player-setting.mjs";
12
- import { useBlackboardPreference } from "../../store/store.mjs";
12
+ import { useGlobalPreference } from "../../store/store.mjs";
13
13
  import { getTextureFromCache, loadTexture } from "../../utils/pixi-loader.mjs";
14
14
  import { rectMarkForItem } from "../blackboard/index.mjs";
15
15
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
@@ -190,7 +190,7 @@ function Player(props) {
190
190
  var _scripts_;
191
191
  const [titleText, setTitleText] = useState('');
192
192
  const [subTitleText, setSubTitleText] = useState('');
193
- const { autoZoom, setAutoZoom } = useBlackboardPreference();
193
+ const { autoZoom, setAutoZoom } = useGlobalPreference();
194
194
  useEffect(()=>{
195
195
  if ((null == props ? void 0 : props.autoZoom) !== void 0) setAutoZoom(props.autoZoom);
196
196
  }, [
@@ -29,11 +29,18 @@ const PlaygroundResultView = ({ result, loading, serverValid, serviceMode, repla
29
29
  })
30
30
  ]
31
31
  });
32
- else if (replayScriptsInfo) resultDataToShow = /*#__PURE__*/ jsx(Player, {
33
- replayScripts: replayScriptsInfo.scripts,
34
- imageWidth: replayScriptsInfo.width,
35
- imageHeight: replayScriptsInfo.height,
36
- reportFileContent: ('In-Browser-Extension' === serviceMode || 'Server' === serviceMode) && (null == result ? void 0 : result.reportHTML) ? null == result ? void 0 : result.reportHTML : null,
32
+ else if (replayScriptsInfo) {
33
+ const reportContent = ('In-Browser-Extension' === serviceMode || 'Server' === serviceMode) && (null == result ? void 0 : result.reportHTML) ? null == result ? void 0 : result.reportHTML : null;
34
+ resultDataToShow = /*#__PURE__*/ jsx(Player, {
35
+ replayScripts: replayScriptsInfo.scripts,
36
+ imageWidth: replayScriptsInfo.width,
37
+ imageHeight: replayScriptsInfo.height,
38
+ reportFileContent: reportContent,
39
+ fitMode: fitMode,
40
+ autoZoom: autoZoom
41
+ }, replayCounter);
42
+ } else if ((null == result ? void 0 : result.reportHTML) && ('In-Browser-Extension' === serviceMode || 'Server' === serviceMode)) resultDataToShow = /*#__PURE__*/ jsx(Player, {
43
+ reportFileContent: result.reportHTML,
37
44
  fitMode: fitMode,
38
45
  autoZoom: autoZoom
39
46
  }, replayCounter);
@@ -13,6 +13,23 @@
13
13
  overflow: hidden;
14
14
  }
15
15
 
16
+ .shiny-text.theme-blue {
17
+ background-image: linear-gradient(45deg, #2b83ff, #6a11cb, #2575fc, #4481eb);
18
+ }
19
+
20
+ .shiny-text.theme-purple {
21
+ background-image: linear-gradient(45deg, #667eea, #764ba2, #b06ab3, #9d50bb);
22
+ }
23
+
24
+ .shiny-text.theme-green {
25
+ background-image: linear-gradient(45deg, #11998e, #38ef7d, #2dd4bf, #10b981);
26
+ }
27
+
28
+ .shiny-text.theme-rainbow {
29
+ background-image: linear-gradient(45deg, #ff0080, #ff8c00, #40e0d0, #9d50bb, #ff0080);
30
+ background-size: 400%;
31
+ }
32
+
16
33
  .shiny-text:after {
17
34
  content: "";
18
35
  width: 120%;
@@ -28,9 +45,9 @@
28
45
  }
29
46
 
30
47
  .shiny-text.disabled {
31
- background: #2b83ff;
32
- -webkit-background-clip: text;
33
- background-clip: text;
48
+ color: #000;
49
+ background: none;
50
+ font-weight: normal;
34
51
  animation: none;
35
52
  }
36
53
 
@@ -1,11 +1,12 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import "./index.css";
3
- const ShinyText = ({ text, disabled = false, speed = 5, className = '' })=>{
3
+ const ShinyText = ({ text, disabled = false, speed = 5, className = '', colorTheme = 'blue' })=>{
4
4
  const style = {
5
5
  '--animation-duration': `${speed}s`
6
6
  };
7
+ const themeClass = `theme-${colorTheme}`;
7
8
  return /*#__PURE__*/ jsx("div", {
8
- className: `shiny-text ${disabled ? 'disabled' : ''} ${className}`,
9
+ className: `shiny-text ${themeClass} ${disabled ? 'disabled' : ''} ${className}`,
9
10
  style: style,
10
11
  children: text
11
12
  });
@@ -160,7 +160,6 @@
160
160
  }
161
161
 
162
162
  .playground-container .progress-description {
163
- color: #000;
164
163
  padding: 8px 0;
165
164
  font-size: 14px;
166
165
  line-height: 22px;
@@ -1,6 +1,6 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import icons, { ArrowDownOutlined, ClearOutlined, LoadingOutlined } from "@ant-design/icons";
3
- import { Button, Form, List, Typography, message } from "antd";
3
+ import { Alert, Button, Form, List, Typography, message } from "antd";
4
4
  import { useCallback, useEffect, useMemo, useState } from "react";
5
5
  import { usePlaygroundExecution } from "../../hooks/usePlaygroundExecution.mjs";
6
6
  import { usePlaygroundState } from "../../hooks/usePlaygroundState.mjs";
@@ -12,6 +12,7 @@ import "./index.css";
12
12
  import avatar from "../../icons/avatar.mjs";
13
13
  import { defaultMainButtons } from "../../utils/constants.mjs";
14
14
  import { PromptInput } from "../prompt-input/index.mjs";
15
+ import shiny_text from "../shiny-text/index.mjs";
15
16
  import { createStorageProvider, detectBestStorageType } from "./providers/storage-provider.mjs";
16
17
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
17
18
  try {
@@ -46,11 +47,16 @@ function getSDKId(sdk) {
46
47
  }
47
48
  function ErrorMessage({ error }) {
48
49
  if (!error) return null;
49
- return /*#__PURE__*/ jsxs("span", {
50
- children: [
51
- "Error: ",
52
- error
53
- ]
50
+ const cleanError = error.replace(/^(Error:\s*)+/, 'Error: ');
51
+ return /*#__PURE__*/ jsx(Alert, {
52
+ message: /*#__PURE__*/ jsx("span", {
53
+ style: {
54
+ color: '#ff4d4f'
55
+ },
56
+ children: cleanError
57
+ }),
58
+ type: "error",
59
+ showIcon: true
54
60
  });
55
61
  }
56
62
  function UniversalPlayground({ playgroundSDK, storage, contextProvider, config: componentConfig = {}, branding = {}, className = '', dryMode = false, showContextPreview = true }) {
@@ -93,7 +99,7 @@ function UniversalPlayground({ playgroundSDK, storage, contextProvider, config:
93
99
  playgroundSDK
94
100
  ]);
95
101
  const { loading, setLoading, infoList, setInfoList, actionSpace, actionSpaceLoading, uiContextPreview, setUiContextPreview, showScrollToBottomButton, verticalMode, replayCounter, setReplayCounter, infoListRef, currentRunningIdRef, interruptedFlagRef, clearInfoList, handleScrollToBottom } = usePlaygroundState(playgroundSDK, effectiveStorage, contextProvider);
96
- const { handleRun: executeAction, handleStop, canStop } = usePlaygroundExecution(playgroundSDK, effectiveStorage, actionSpace, loading, setLoading, infoList, setInfoList, replayCounter, setReplayCounter, verticalMode, currentRunningIdRef, interruptedFlagRef);
102
+ const { handleRun: executeAction, handleStop, canStop } = usePlaygroundExecution(playgroundSDK, effectiveStorage, actionSpace, loading, setLoading, setInfoList, replayCounter, setReplayCounter, verticalMode, currentRunningIdRef, interruptedFlagRef);
97
103
  useEffect(()=>{
98
104
  if ((null == playgroundSDK ? void 0 : playgroundSDK.overrideConfig) && config) playgroundSDK.overrideConfig(config).catch((error)=>{
99
105
  console.error('Failed to override SDK config:', error);
@@ -116,6 +122,12 @@ function UniversalPlayground({ playgroundSDK, storage, contextProvider, config:
116
122
  const configAlreadySet = Object.keys(config || {}).length >= 1;
117
123
  const runButtonEnabled = componentConfig.serverMode || !dryMode && !actionSpaceLoading && configAlreadySet;
118
124
  const selectedType = Form.useWatch('type', form);
125
+ const serviceMode = useMemo(()=>{
126
+ if (!playgroundSDK || 'function' != typeof playgroundSDK.getServiceMode) return 'Server';
127
+ return playgroundSDK.getServiceMode();
128
+ }, [
129
+ playgroundSDK
130
+ ]);
119
131
  const finalShowContextPreview = showContextPreview && false !== componentConfig.showContextPreview;
120
132
  const layout = componentConfig.layout || 'vertical';
121
133
  const showVersionInfo = false !== componentConfig.showVersionInfo;
@@ -154,9 +166,7 @@ function UniversalPlayground({ playgroundSDK, storage, contextProvider, config:
154
166
  children: /*#__PURE__*/ jsx(List, {
155
167
  itemLayout: "vertical",
156
168
  dataSource: infoList,
157
- renderItem: (item)=>{
158
- var _item_result;
159
- return /*#__PURE__*/ jsx(List.Item, {
169
+ renderItem: (item)=>/*#__PURE__*/ jsx(List.Item, {
160
170
  className: "list-item",
161
171
  children: 'user' === item.type ? /*#__PURE__*/ jsx("div", {
162
172
  className: "user-message-container",
@@ -189,9 +199,10 @@ function UniversalPlayground({ playgroundSDK, storage, contextProvider, config:
189
199
  ]
190
200
  }),
191
201
  description && /*#__PURE__*/ jsx("div", {
192
- children: /*#__PURE__*/ jsx("span", {
202
+ children: /*#__PURE__*/ jsx(shiny_text, {
203
+ text: description,
193
204
  className: "progress-description",
194
- children: description
205
+ disabled: !shouldShowLoading
195
206
  })
196
207
  }),
197
208
  (null == (_item_result2 = item.result) ? void 0 : _item_result2.error) && /*#__PURE__*/ jsx(ErrorMessage, {
@@ -233,50 +244,36 @@ function UniversalPlayground({ playgroundSDK, storage, contextProvider, config:
233
244
  })
234
245
  ]
235
246
  }),
236
- (item.content || item.result) && /*#__PURE__*/ jsxs("div", {
247
+ (item.content || item.result) && /*#__PURE__*/ jsx("div", {
237
248
  className: "system-message-content",
238
- children: [
239
- 'result' === item.type && (null == (_item_result = item.result) ? void 0 : _item_result.error) && /*#__PURE__*/ jsxs("div", {
240
- className: "error-message",
241
- children: [
242
- /*#__PURE__*/ jsx("div", {
243
- className: "divider"
244
- }),
245
- /*#__PURE__*/ jsx(ErrorMessage, {
246
- error: item.result.error
247
- })
248
- ]
249
- }),
250
- 'result' === item.type ? /*#__PURE__*/ jsx(PlaygroundResultView, {
251
- result: item.result || null,
252
- loading: item.loading || false,
253
- serverValid: true,
254
- serviceMode: 'Server',
255
- replayScriptsInfo: item.replayScriptsInfo || null,
256
- replayCounter: item.replayCounter || 0,
257
- loadingProgressText: item.loadingProgressText || '',
258
- verticalMode: item.verticalMode || false,
259
- fitMode: "width"
260
- }) : /*#__PURE__*/ jsxs(Fragment, {
261
- children: [
262
- /*#__PURE__*/ jsx("div", {
263
- className: "system-message-text",
264
- children: item.content
265
- }),
266
- item.loading && item.loadingProgressText && /*#__PURE__*/ jsx("div", {
267
- className: "loading-progress-text",
268
- children: /*#__PURE__*/ jsx("span", {
269
- children: item.loadingProgressText
270
- })
249
+ children: 'result' === item.type ? /*#__PURE__*/ jsx(PlaygroundResultView, {
250
+ result: item.result || null,
251
+ loading: item.loading || false,
252
+ serverValid: true,
253
+ serviceMode: serviceMode,
254
+ replayScriptsInfo: item.replayScriptsInfo || null,
255
+ replayCounter: item.replayCounter || 0,
256
+ loadingProgressText: item.loadingProgressText || '',
257
+ verticalMode: item.verticalMode || false,
258
+ fitMode: "width"
259
+ }) : /*#__PURE__*/ jsxs(Fragment, {
260
+ children: [
261
+ /*#__PURE__*/ jsx("div", {
262
+ className: "system-message-text",
263
+ children: item.content
264
+ }),
265
+ item.loading && item.loadingProgressText && /*#__PURE__*/ jsx("div", {
266
+ className: "loading-progress-text",
267
+ children: /*#__PURE__*/ jsx("span", {
268
+ children: item.loadingProgressText
271
269
  })
272
- ]
273
- })
274
- ]
270
+ })
271
+ ]
272
+ })
275
273
  })
276
274
  ]
277
275
  })
278
- }, item.id);
279
- }
276
+ }, item.id)
280
277
  })
281
278
  }),
282
279
  showScrollToBottomButton && false !== componentConfig.enableScrollToBottom && /*#__PURE__*/ jsx(Button, {
@@ -296,7 +293,7 @@ function UniversalPlayground({ playgroundSDK, storage, contextProvider, config:
296
293
  /*#__PURE__*/ jsx(PromptInput, {
297
294
  runButtonEnabled: runButtonEnabled,
298
295
  form: form,
299
- serviceMode: 'Server',
296
+ serviceMode: serviceMode,
300
297
  selectedType: selectedType,
301
298
  dryMode: dryMode,
302
299
  stoppable: canStop,
@@ -81,7 +81,7 @@ class IndexedDBStorageProvider {
81
81
  const messagesToSave = messages.slice(-MAX_STORED_MESSAGES);
82
82
  yield Promise.all(messagesToSave.map((msg, index)=>{
83
83
  const lightMessage = _object_spread_props(_object_spread({}, msg), {
84
- result: void 0
84
+ result: 'result' === msg.type ? void 0 : msg.result
85
85
  });
86
86
  const data = {
87
87
  id: msg.id || `msg-${index}`,
@@ -153,28 +153,23 @@ class IndexedDBStorageProvider {
153
153
  }
154
154
  compressResultForStorage(result) {
155
155
  var _result_result_dump, _result_result;
156
- if (!(null == (_result_result = result.result) ? void 0 : null == (_result_result_dump = _result_result.dump) ? void 0 : _result_result_dump.executions)) return result;
157
- const compressedExecutions = result.result.dump.executions.map((execution)=>{
158
- var _execution_tasks;
159
- return _object_spread_props(_object_spread({}, execution), {
160
- tasks: (null == (_execution_tasks = execution.tasks) ? void 0 : _execution_tasks.map((task)=>{
161
- var _task_recorder;
162
- var _this_compressScreenshotIfNeeded;
163
- return _object_spread_props(_object_spread({}, task), {
164
- uiContext: task.uiContext ? _object_spread_props(_object_spread({}, task.uiContext), {
165
- screenshotBase64: null != (_this_compressScreenshotIfNeeded = this.compressScreenshotIfNeeded(task.uiContext.screenshotBase64)) ? _this_compressScreenshotIfNeeded : task.uiContext.screenshotBase64
166
- }) : task.uiContext,
167
- recorder: null == (_task_recorder = task.recorder) ? void 0 : _task_recorder.map((record)=>_object_spread_props(_object_spread({}, record), {
168
- screenshot: this.compressScreenshotIfNeeded(record.screenshot)
169
- }))
170
- });
171
- })) || []
156
+ if (!(null == (_result_result = result.result) ? void 0 : null == (_result_result_dump = _result_result.dump) ? void 0 : _result_result_dump.tasks)) return result;
157
+ const compressedTasks = result.result.dump.tasks.map((task)=>{
158
+ var _task_recorder;
159
+ var _this_compressScreenshotIfNeeded;
160
+ return _object_spread_props(_object_spread({}, task), {
161
+ uiContext: task.uiContext ? _object_spread_props(_object_spread({}, task.uiContext), {
162
+ screenshotBase64: null != (_this_compressScreenshotIfNeeded = this.compressScreenshotIfNeeded(task.uiContext.screenshotBase64)) ? _this_compressScreenshotIfNeeded : task.uiContext.screenshotBase64
163
+ }) : task.uiContext,
164
+ recorder: null == (_task_recorder = task.recorder) ? void 0 : _task_recorder.map((record)=>_object_spread_props(_object_spread({}, record), {
165
+ screenshot: this.compressScreenshotIfNeeded(record.screenshot)
166
+ }))
172
167
  });
173
168
  });
174
169
  return _object_spread_props(_object_spread({}, result), {
175
170
  result: _object_spread_props(_object_spread({}, result.result), {
176
171
  dump: _object_spread_props(_object_spread({}, result.result.dump), {
177
- executions: compressedExecutions
172
+ tasks: compressedTasks
178
173
  })
179
174
  })
180
175
  });
@@ -88,7 +88,7 @@ class LocalStorageProvider {
88
88
  }
89
89
  const messagesToSave = messages.slice(-this.maxStorageItems);
90
90
  const lightMessages = messagesToSave.map((msg)=>_object_spread_props(_object_spread({}, msg), {
91
- result: void 0
91
+ result: 'result' === msg.type ? void 0 : msg.result
92
92
  }));
93
93
  const messageData = JSON.stringify(lightMessages);
94
94
  localStorage.setItem(this.messagesKey, messageData);
@@ -99,7 +99,7 @@ class LocalStorageProvider {
99
99
  try {
100
100
  const recentMessages = messages.slice(-10);
101
101
  const lightRecentMessages = recentMessages.map((msg)=>_object_spread_props(_object_spread({}, msg), {
102
- result: void 0
102
+ result: 'result' === msg.type ? void 0 : msg.result
103
103
  }));
104
104
  const messageData = JSON.stringify(lightRecentMessages);
105
105
  localStorage.setItem(this.messagesKey, messageData);
@@ -1,3 +1,4 @@
1
+ import { paramStr, typeStr } from "@midscene/core/agent";
1
2
  import { useCallback } from "react";
2
3
  import { useEnvConfig } from "../store/store.mjs";
3
4
  import { noReplayAPIs } from "@midscene/playground";
@@ -71,7 +72,33 @@ function _object_spread_props(target, source) {
71
72
  });
72
73
  return target;
73
74
  }
74
- function usePlaygroundExecution(playgroundSDK, storage, actionSpace, loading, setLoading, infoList, setInfoList, replayCounter, setReplayCounter, verticalMode, currentRunningIdRef, interruptedFlagRef) {
75
+ function buildProgressContent(task) {
76
+ const action = typeStr(task);
77
+ const description = paramStr(task);
78
+ return description ? `${action} - ${description}` : action;
79
+ }
80
+ function wrapExecutionDumpForReplay(dump) {
81
+ const modelBriefsSet = new Set();
82
+ if ((null == dump ? void 0 : dump.tasks) && Array.isArray(dump.tasks)) dump.tasks.forEach((task)=>{
83
+ if (task.usage) {
84
+ const { model_name, model_description, intent } = task.usage;
85
+ if (intent && model_name) modelBriefsSet.add(model_description ? `${intent}/${model_name}(${model_description})` : `${intent}/${model_name}`);
86
+ }
87
+ });
88
+ else console.warn('[wrapExecutionDumpForReplay] Invalid dump structure:', dump);
89
+ const modelBriefs = [
90
+ ...modelBriefsSet
91
+ ];
92
+ return {
93
+ sdkVersion: '',
94
+ groupName: 'Playground Execution',
95
+ modelBriefs,
96
+ executions: [
97
+ dump
98
+ ]
99
+ };
100
+ }
101
+ function usePlaygroundExecution(playgroundSDK, storage, actionSpace, loading, setLoading, setInfoList, replayCounter, setReplayCounter, verticalMode, currentRunningIdRef, interruptedFlagRef) {
75
102
  const { deepThink, screenshotIncluded, domIncluded } = useEnvConfig();
76
103
  const handleRun = useCallback((value)=>_async_to_generator(function*() {
77
104
  if (!playgroundSDK) return void console.warn('PlaygroundSDK is not available');
@@ -105,21 +132,30 @@ function usePlaygroundExecution(playgroundSDK, storage, actionSpace, loading, se
105
132
  try {
106
133
  currentRunningIdRef.current = thisRunningId;
107
134
  interruptedFlagRef.current[thisRunningId] = false;
108
- if (playgroundSDK.onProgressUpdate) playgroundSDK.onProgressUpdate(()=>{});
109
- if (playgroundSDK.onProgressUpdate) playgroundSDK.onProgressUpdate((tip)=>{
110
- if (interruptedFlagRef.current[thisRunningId]) return;
111
- setInfoList((prev)=>{
112
- const lastItem = prev[prev.length - 1];
113
- if (lastItem && 'progress' === lastItem.type && lastItem.content === tip) return prev;
114
- const progressItem = {
115
- id: `progress-${thisRunningId}-${Date.now()}`,
135
+ if (playgroundSDK.onDumpUpdate) playgroundSDK.onDumpUpdate((_, executionDump)=>{
136
+ var _executionDump_tasks;
137
+ if (interruptedFlagRef.current[thisRunningId] || !(null == executionDump ? void 0 : null == (_executionDump_tasks = executionDump.tasks) ? void 0 : _executionDump_tasks.length)) return;
138
+ const progressItems = executionDump.tasks.map((task, index)=>{
139
+ var _task_timing;
140
+ return {
141
+ id: `progress-${thisRunningId}-task-${index}`,
116
142
  type: 'progress',
117
- content: tip,
118
- timestamp: new Date()
143
+ content: buildProgressContent(task),
144
+ timestamp: new Date((null == (_task_timing = task.timing) ? void 0 : _task_timing.start) || Date.now()),
145
+ result: task.error ? {
146
+ error: String(task.error),
147
+ result: null
148
+ } : void 0
119
149
  };
150
+ });
151
+ setInfoList((prev)=>{
152
+ const systemItemIndex = prev.findIndex((item)=>item.id === `system-${thisRunningId}`);
153
+ if (-1 === systemItemIndex) return prev;
154
+ const listWithoutCurrentProgress = prev.filter((item)=>!('progress' === item.type && item.id.startsWith(`progress-${thisRunningId}-`)));
120
155
  return [
121
- ...prev,
122
- progressItem
156
+ ...listWithoutCurrentProgress.slice(0, systemItemIndex + 1),
157
+ ...progressItems,
158
+ ...listWithoutCurrentProgress.slice(systemItemIndex + 1)
123
159
  ];
124
160
  });
125
161
  });
@@ -139,6 +175,10 @@ function usePlaygroundExecution(playgroundSDK, storage, actionSpace, loading, se
139
175
  } catch (e) {
140
176
  result.error = (null == e ? void 0 : e.message) || String(e);
141
177
  console.error('Playground execution error:', e);
178
+ if ('object' == typeof e && null !== e) {
179
+ if (e.dump) result.dump = e.dump;
180
+ if (e.reportHTML) result.reportHTML = e.reportHTML;
181
+ }
142
182
  }
143
183
  if (interruptedFlagRef.current[thisRunningId]) return;
144
184
  setLoading(false);
@@ -146,10 +186,13 @@ function usePlaygroundExecution(playgroundSDK, storage, actionSpace, loading, se
146
186
  let replayInfo = null;
147
187
  let counter = replayCounter;
148
188
  if ((null == result ? void 0 : result.dump) && !noReplayAPIs.includes(actionType)) {
149
- const info = allScriptsFromDump(result.dump);
150
- setReplayCounter((c)=>c + 1);
151
- replayInfo = info;
152
- counter = replayCounter + 1;
189
+ if (result.dump.tasks && Array.isArray(result.dump.tasks)) {
190
+ const groupedDump = wrapExecutionDumpForReplay(result.dump);
191
+ const info = allScriptsFromDump(groupedDump);
192
+ setReplayCounter((c)=>c + 1);
193
+ replayInfo = info;
194
+ counter = replayCounter + 1;
195
+ }
153
196
  }
154
197
  setInfoList((prev)=>prev.map((item)=>item.id === `system-${thisRunningId}` ? _object_spread_props(_object_spread({}, item), {
155
198
  content: '',
@@ -205,15 +248,55 @@ function usePlaygroundExecution(playgroundSDK, storage, actionSpace, loading, se
205
248
  const handleStop = useCallback(()=>_async_to_generator(function*() {
206
249
  const thisRunningId = currentRunningIdRef.current;
207
250
  if (thisRunningId && playgroundSDK && playgroundSDK.cancelExecution) try {
251
+ let executionData = null;
252
+ if (playgroundSDK.getCurrentExecutionData) try {
253
+ executionData = yield playgroundSDK.getCurrentExecutionData();
254
+ } catch (error) {
255
+ console.error('Failed to get execution data before stop:', error);
256
+ }
208
257
  yield playgroundSDK.cancelExecution(thisRunningId.toString());
209
258
  interruptedFlagRef.current[thisRunningId] = true;
210
259
  setLoading(false);
211
260
  if (playgroundSDK.onProgressUpdate) playgroundSDK.onProgressUpdate(()=>{});
212
- setInfoList((prev)=>prev.map((item)=>item.id === `system-${thisRunningId}` && item.loading ? _object_spread_props(_object_spread({}, item), {
213
- content: 'Operation stopped',
261
+ if (playgroundSDK.onDumpUpdate) playgroundSDK.onDumpUpdate(()=>{});
262
+ setInfoList((prev)=>prev.map((item)=>item.id === `system-${thisRunningId}` ? _object_spread_props(_object_spread({}, item), {
263
+ content: '',
214
264
  loading: false,
215
265
  loadingProgressText: ''
216
266
  }) : item));
267
+ if (executionData && (executionData.dump || executionData.reportHTML)) {
268
+ const resultItem = {
269
+ id: `stop-result-${thisRunningId}`,
270
+ type: 'result',
271
+ content: 'Execution stopped by user',
272
+ timestamp: new Date(),
273
+ result: {
274
+ result: null,
275
+ dump: executionData.dump,
276
+ reportHTML: executionData.reportHTML,
277
+ error: null
278
+ },
279
+ loading: false,
280
+ verticalMode,
281
+ replayCounter
282
+ };
283
+ setInfoList((prev)=>[
284
+ ...prev,
285
+ resultItem
286
+ ]);
287
+ } else {
288
+ const stopItem = {
289
+ id: `stop-${thisRunningId}`,
290
+ type: 'system',
291
+ content: 'Operation stopped',
292
+ timestamp: new Date(),
293
+ loading: false
294
+ };
295
+ setInfoList((prev)=>[
296
+ ...prev,
297
+ stopItem
298
+ ]);
299
+ }
217
300
  const separatorItem = {
218
301
  id: `separator-${thisRunningId}`,
219
302
  type: 'separator',
@@ -232,7 +315,9 @@ function usePlaygroundExecution(playgroundSDK, storage, actionSpace, loading, se
232
315
  currentRunningIdRef,
233
316
  interruptedFlagRef,
234
317
  setLoading,
235
- setInfoList
318
+ setInfoList,
319
+ verticalMode,
320
+ replayCounter
236
321
  ]);
237
322
  const canStop = loading && !!currentRunningIdRef.current && !!playgroundSDK && !!playgroundSDK.cancelExecution;
238
323
  return {
package/dist/es/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { allScriptsFromDump, generateAnimationScripts } from "./utils/replay-scripts.mjs";
2
- import { useEnvConfig } from "./store/store.mjs";
2
+ import { useEnvConfig, useGlobalPreference } from "./store/store.mjs";
3
3
  import { colorForName, globalThemeConfig, highlightColorForType } from "./utils/color.mjs";
4
4
  import { EnvConfig } from "./component/env-config/index.mjs";
5
5
  import { EnvConfigReminder } from "./component/env-config-reminder/index.mjs";
@@ -22,4 +22,4 @@ import shiny_text from "./component/shiny-text/index.mjs";
22
22
  import universal_playground, { UniversalPlayground } from "./component/universal-playground/index.mjs";
23
23
  import { IndexedDBStorageProvider, LocalStorageProvider, MemoryStorageProvider, NoOpStorageProvider, StorageType, createStorageProvider, detectBestStorageType } 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, IndexedDBStorageProvider, LocalStorageProvider, Logo, MemoryStorageProvider, NavActions, NoOpContextProvider, NoOpStorageProvider, Player, PlaygroundResultView, PromptInput, screenshot_viewer as ScreenshotViewer, ServiceModeControl, shiny_text as ShinyText, StaticContextProvider, StorageType, UniversalPlayground, universal_playground as UniversalPlaygroundDefault, actionNameForType, allScriptsFromDump, colorForName, createStorageProvider, detectBestStorageType, filterBase64Value, generateAnimationScripts, getPlaceholderForType, globalThemeConfig, highlightColorForType, iconForStatus, safeOverrideAIConfig, staticAgentFromContext, timeCostStrElement, timeStr, useEnvConfig, useSafeOverrideAIConfig, useServerValid, useTheme };
25
+ export { AgentContextProvider, BaseContextProvider, Blackboard, ContextPreview, EnvConfig, EnvConfigReminder, IndexedDBStorageProvider, LocalStorageProvider, Logo, MemoryStorageProvider, NavActions, NoOpContextProvider, NoOpStorageProvider, Player, PlaygroundResultView, PromptInput, screenshot_viewer as ScreenshotViewer, ServiceModeControl, shiny_text as ShinyText, StaticContextProvider, StorageType, UniversalPlayground, universal_playground as UniversalPlaygroundDefault, actionNameForType, allScriptsFromDump, colorForName, createStorageProvider, detectBestStorageType, filterBase64Value, generateAnimationScripts, getPlaceholderForType, globalThemeConfig, highlightColorForType, iconForStatus, safeOverrideAIConfig, staticAgentFromContext, timeCostStrElement, timeStr, useEnvConfig, useGlobalPreference, useSafeOverrideAIConfig, useServerValid, useTheme };
@@ -30,6 +30,8 @@ const { create: store_create } = external_zustand_namespaceObject;
30
30
  const AUTO_ZOOM_KEY = 'midscene-auto-zoom';
31
31
  const BACKGROUND_VISIBLE_KEY = 'midscene-background-visible';
32
32
  const ELEMENTS_VISIBLE_KEY = 'midscene-elements-visible';
33
+ const MODEL_CALL_DETAILS_KEY = 'midscene-model-call-details';
34
+ const DARK_MODE_KEY = 'midscene-dark-mode';
33
35
  const parseBooleanParam = (value)=>{
34
36
  if (null === value) return;
35
37
  const normalized = value.trim().toLowerCase();
@@ -51,16 +53,23 @@ const getQueryPreference = (paramName)=>{
51
53
  const searchParams = new URLSearchParams(window.location.search);
52
54
  return parseBooleanParam(searchParams.get(paramName));
53
55
  };
54
- const useBlackboardPreference = store_create((set)=>{
56
+ const useGlobalPreference = store_create((set)=>{
55
57
  const savedAutoZoom = 'false' !== localStorage.getItem(AUTO_ZOOM_KEY);
56
58
  const savedBackgroundVisible = 'false' !== localStorage.getItem(BACKGROUND_VISIBLE_KEY);
57
59
  const savedElementsVisible = 'false' !== localStorage.getItem(ELEMENTS_VISIBLE_KEY);
60
+ const savedModelCallDetails = 'true' === localStorage.getItem(MODEL_CALL_DETAILS_KEY);
61
+ const savedDarkMode = 'true' === localStorage.getItem(DARK_MODE_KEY);
58
62
  const autoZoomFromQuery = getQueryPreference('focusOnCursor');
59
63
  const elementsVisibleFromQuery = getQueryPreference('showElementMarkers');
64
+ const darkModeFromQuery = getQueryPreference('darkMode');
65
+ const initialDarkMode = void 0 === darkModeFromQuery ? savedDarkMode : darkModeFromQuery;
66
+ if (void 0 !== darkModeFromQuery) localStorage.setItem(DARK_MODE_KEY, initialDarkMode.toString());
60
67
  return {
61
68
  backgroundVisible: savedBackgroundVisible,
62
69
  elementsVisible: void 0 === elementsVisibleFromQuery ? savedElementsVisible : elementsVisibleFromQuery,
63
70
  autoZoom: void 0 === autoZoomFromQuery ? savedAutoZoom : autoZoomFromQuery,
71
+ modelCallDetailsEnabled: savedModelCallDetails,
72
+ darkModeEnabled: initialDarkMode,
64
73
  setBackgroundVisible: (visible)=>{
65
74
  set({
66
75
  backgroundVisible: visible
@@ -78,6 +87,18 @@ const useBlackboardPreference = store_create((set)=>{
78
87
  autoZoom: enabled
79
88
  });
80
89
  localStorage.setItem(AUTO_ZOOM_KEY, enabled.toString());
90
+ },
91
+ setModelCallDetailsEnabled: (enabled)=>{
92
+ set({
93
+ modelCallDetailsEnabled: enabled
94
+ });
95
+ localStorage.setItem(MODEL_CALL_DETAILS_KEY, enabled.toString());
96
+ },
97
+ setDarkModeEnabled: (enabled)=>{
98
+ set({
99
+ darkModeEnabled: enabled
100
+ });
101
+ localStorage.setItem(DARK_MODE_KEY, enabled.toString());
81
102
  }
82
103
  };
83
104
  });
@@ -219,4 +240,4 @@ const useEnvConfig = store_create((set, get)=>{
219
240
  }
220
241
  };
221
242
  });
222
- export { useBlackboardPreference, useEnvConfig };
243
+ export { useEnvConfig, useGlobalPreference };
@@ -229,7 +229,7 @@ function Player(props) {
229
229
  var _scripts_;
230
230
  const [titleText, setTitleText] = (0, external_react_namespaceObject.useState)('');
231
231
  const [subTitleText, setSubTitleText] = (0, external_react_namespaceObject.useState)('');
232
- const { autoZoom, setAutoZoom } = (0, store_js_namespaceObject.useBlackboardPreference)();
232
+ const { autoZoom, setAutoZoom } = (0, store_js_namespaceObject.useGlobalPreference)();
233
233
  (0, external_react_namespaceObject.useEffect)(()=>{
234
234
  if ((null == props ? void 0 : props.autoZoom) !== void 0) setAutoZoom(props.autoZoom);
235
235
  }, [