@midscene/visualizer 0.28.10-beta-20250919094051.0 → 0.28.10
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/player/index.mjs +38 -15
- package/dist/es/component/universal-playground/index.css +1 -1
- package/dist/es/component/universal-playground/index.mjs +29 -5
- package/dist/es/component/universal-playground/providers/indexeddb-storage-provider.mjs +207 -0
- package/dist/es/component/universal-playground/providers/storage-provider.mjs +42 -3
- package/dist/es/hooks/usePlaygroundState.mjs +28 -3
- package/dist/es/index.mjs +2 -2
- package/dist/es/utils/replay-scripts.mjs +59 -32
- package/dist/lib/component/player/index.js +38 -15
- package/dist/lib/component/universal-playground/index.css +1 -1
- package/dist/lib/component/universal-playground/index.js +27 -3
- package/dist/lib/component/universal-playground/providers/indexeddb-storage-provider.js +247 -0
- package/dist/lib/component/universal-playground/providers/storage-provider.js +60 -3
- package/dist/lib/hooks/usePlaygroundState.js +28 -3
- package/dist/lib/index.js +14 -2
- package/dist/lib/utils/replay-scripts.js +59 -32
- package/dist/types/component/universal-playground/providers/indexeddb-storage-provider.d.ts +71 -0
- package/dist/types/component/universal-playground/providers/storage-provider.d.ts +16 -0
- package/dist/types/hooks/usePlaygroundExecution.d.ts +1 -1
- package/dist/types/hooks/usePlaygroundState.d.ts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/utils/replay-scripts.d.ts +2 -0
- package/package.json +5 -5
|
@@ -42,8 +42,9 @@ const capitalizeFirstLetter = (str)=>{
|
|
|
42
42
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
43
43
|
};
|
|
44
44
|
const allScriptsFromDump = (dump)=>{
|
|
45
|
-
|
|
46
|
-
let
|
|
45
|
+
const dimensionsSet = new Set();
|
|
46
|
+
let firstWidth;
|
|
47
|
+
let firstHeight;
|
|
47
48
|
let sdkVersion;
|
|
48
49
|
const modelBriefsSet = new Set();
|
|
49
50
|
dump.executions.forEach((execution)=>{
|
|
@@ -51,12 +52,17 @@ const allScriptsFromDump = (dump)=>{
|
|
|
51
52
|
execution.tasks.forEach((task)=>{
|
|
52
53
|
var _task_uiContext_size, _task_uiContext;
|
|
53
54
|
if (null == (_task_uiContext = task.uiContext) ? void 0 : null == (_task_uiContext_size = _task_uiContext.size) ? void 0 : _task_uiContext_size.width) {
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
const w = task.uiContext.size.width;
|
|
56
|
+
const h = task.uiContext.size.height;
|
|
57
|
+
if (!firstWidth) {
|
|
58
|
+
firstWidth = w;
|
|
59
|
+
firstHeight = h;
|
|
60
|
+
}
|
|
61
|
+
dimensionsSet.add(`${w}x${h}`);
|
|
56
62
|
}
|
|
57
63
|
});
|
|
58
64
|
});
|
|
59
|
-
if (!
|
|
65
|
+
if (!firstWidth || !firstHeight) {
|
|
60
66
|
console.warn('width or height is missing in dump file');
|
|
61
67
|
return {
|
|
62
68
|
scripts: [],
|
|
@@ -66,7 +72,7 @@ const allScriptsFromDump = (dump)=>{
|
|
|
66
72
|
}
|
|
67
73
|
const allScripts = [];
|
|
68
74
|
dump.executions.forEach((execution)=>{
|
|
69
|
-
const scripts = generateAnimationScripts(execution, -1,
|
|
75
|
+
const scripts = generateAnimationScripts(execution, -1, firstWidth, firstHeight);
|
|
70
76
|
if (scripts) allScripts.push(...scripts);
|
|
71
77
|
execution.tasks.forEach((task)=>{
|
|
72
78
|
if (task.usage) {
|
|
@@ -93,8 +99,8 @@ const allScriptsFromDump = (dump)=>{
|
|
|
93
99
|
})();
|
|
94
100
|
return {
|
|
95
101
|
scripts: allScriptsWithoutIntermediateDoneFrame,
|
|
96
|
-
width,
|
|
97
|
-
height,
|
|
102
|
+
width: firstWidth,
|
|
103
|
+
height: firstHeight,
|
|
98
104
|
sdkVersion,
|
|
99
105
|
modelBriefs
|
|
100
106
|
};
|
|
@@ -143,14 +149,16 @@ const generateAnimationScripts = (execution, task, imageWidth, imageHeight)=>{
|
|
|
143
149
|
if ('Planning' === task.type) {
|
|
144
150
|
const planningTask = task;
|
|
145
151
|
if (planningTask.recorder && planningTask.recorder.length > 0) {
|
|
146
|
-
var _planningTask_recorder_, _planningTask_recorder;
|
|
152
|
+
var _planningTask_recorder_, _planningTask_recorder, _task_uiContext_size, _task_uiContext, _task_uiContext_size1, _task_uiContext1;
|
|
147
153
|
scripts.push({
|
|
148
154
|
type: 'img',
|
|
149
155
|
img: null == (_planningTask_recorder = planningTask.recorder) ? void 0 : null == (_planningTask_recorder_ = _planningTask_recorder[0]) ? void 0 : _planningTask_recorder_.screenshot,
|
|
150
156
|
camera: 0 === index ? fullPageCameraState : void 0,
|
|
151
157
|
duration: stillDuration,
|
|
152
158
|
title: typeStr(task),
|
|
153
|
-
subTitle: paramStr(task)
|
|
159
|
+
subTitle: paramStr(task),
|
|
160
|
+
imageWidth: (null == (_task_uiContext = task.uiContext) ? void 0 : null == (_task_uiContext_size = _task_uiContext.size) ? void 0 : _task_uiContext_size.width) || imageWidth,
|
|
161
|
+
imageHeight: (null == (_task_uiContext1 = task.uiContext) ? void 0 : null == (_task_uiContext_size1 = _task_uiContext1.size) ? void 0 : _task_uiContext_size1.height) || imageHeight
|
|
154
162
|
});
|
|
155
163
|
}
|
|
156
164
|
} else if ('Insight' === task.type && 'Locate' === task.subType) {
|
|
@@ -166,16 +174,21 @@ const generateAnimationScripts = (execution, task, imageWidth, imageHeight)=>{
|
|
|
166
174
|
};
|
|
167
175
|
const context = insightTask.uiContext;
|
|
168
176
|
if (null == context ? void 0 : context.screenshotBase64) {
|
|
169
|
-
var _insightTask_log, _insightTask_output1, _insightDump_taskInfo;
|
|
177
|
+
var _insightTask_log, _insightTask_output1, _insightDump_taskInfo, _context_size, _context_size1;
|
|
170
178
|
const insightDump = null == (_insightTask_log = insightTask.log) ? void 0 : _insightTask_log.dump;
|
|
171
179
|
const insightContentLength = context.tree ? treeToList(context.tree).length : 0;
|
|
172
|
-
if (context.screenshotBase64)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
180
|
+
if (context.screenshotBase64) {
|
|
181
|
+
var _context_size2, _context_size3;
|
|
182
|
+
scripts.push({
|
|
183
|
+
type: 'img',
|
|
184
|
+
img: context.screenshotBase64,
|
|
185
|
+
duration: stillAfterInsightDuration,
|
|
186
|
+
title,
|
|
187
|
+
subTitle,
|
|
188
|
+
imageWidth: (null == (_context_size2 = context.size) ? void 0 : _context_size2.width) || imageWidth,
|
|
189
|
+
imageHeight: (null == (_context_size3 = context.size) ? void 0 : _context_size3.height) || imageHeight
|
|
190
|
+
});
|
|
191
|
+
}
|
|
179
192
|
let cameraState;
|
|
180
193
|
cameraState = currentCameraState === fullPageCameraState ? void 0 : insightCameraState ? mergeTwoCameraState(currentCameraState, insightCameraState) : void 0;
|
|
181
194
|
scripts.push({
|
|
@@ -188,7 +201,9 @@ const generateAnimationScripts = (execution, task, imageWidth, imageHeight)=>{
|
|
|
188
201
|
duration: insightContentLength > 20 ? locateDuration : 0.5 * locateDuration,
|
|
189
202
|
insightCameraDuration: locateDuration,
|
|
190
203
|
title,
|
|
191
|
-
subTitle
|
|
204
|
+
subTitle,
|
|
205
|
+
imageWidth: (null == (_context_size = context.size) ? void 0 : _context_size.width) || imageWidth,
|
|
206
|
+
imageHeight: (null == (_context_size1 = context.size) ? void 0 : _context_size1.height) || imageHeight
|
|
192
207
|
});
|
|
193
208
|
scripts.push({
|
|
194
209
|
type: 'sleep',
|
|
@@ -199,7 +214,7 @@ const generateAnimationScripts = (execution, task, imageWidth, imageHeight)=>{
|
|
|
199
214
|
insightOnTop = true;
|
|
200
215
|
}
|
|
201
216
|
} else if ('Action' === task.type && 'FalsyConditionStatement' !== task.subType) {
|
|
202
|
-
var _task_recorder_, _task_recorder, _task_recorder_1, _task_recorder1;
|
|
217
|
+
var _task_recorder_, _task_recorder, _task_uiContext_size2, _task_uiContext2, _task_uiContext_size3, _task_uiContext3, _task_recorder_1, _task_recorder1;
|
|
203
218
|
const title = typeStr(task);
|
|
204
219
|
const subTitle = paramStr(task);
|
|
205
220
|
scripts.push(pointerScript(mousePointer, title, subTitle));
|
|
@@ -210,7 +225,9 @@ const generateAnimationScripts = (execution, task, imageWidth, imageHeight)=>{
|
|
|
210
225
|
duration: actionDuration,
|
|
211
226
|
camera: 'Sleep' === task.subType ? fullPageCameraState : insightCameraState,
|
|
212
227
|
title,
|
|
213
|
-
subTitle
|
|
228
|
+
subTitle,
|
|
229
|
+
imageWidth: (null == (_task_uiContext2 = task.uiContext) ? void 0 : null == (_task_uiContext_size2 = _task_uiContext2.size) ? void 0 : _task_uiContext_size2.width) || imageWidth,
|
|
230
|
+
imageHeight: (null == (_task_uiContext3 = task.uiContext) ? void 0 : null == (_task_uiContext_size3 = _task_uiContext3.size) ? void 0 : _task_uiContext_size3.height) || imageHeight
|
|
214
231
|
});
|
|
215
232
|
if (insightOnTop) {
|
|
216
233
|
scripts.push({
|
|
@@ -223,7 +240,7 @@ const generateAnimationScripts = (execution, task, imageWidth, imageHeight)=>{
|
|
|
223
240
|
}
|
|
224
241
|
const imgStillDuration = index < taskCount - 1 ? stillDuration : 0;
|
|
225
242
|
if (null == (_task_recorder1 = task.recorder) ? void 0 : null == (_task_recorder_1 = _task_recorder1[1]) ? void 0 : _task_recorder_1.screenshot) {
|
|
226
|
-
var _task_recorder_2, _task_recorder2;
|
|
243
|
+
var _task_recorder_2, _task_recorder2, _task_uiContext_size4, _task_uiContext4, _task_uiContext_size5, _task_uiContext5;
|
|
227
244
|
scripts.push({
|
|
228
245
|
type: 'spinning-pointer',
|
|
229
246
|
duration: actionSpinningPointerDuration,
|
|
@@ -236,7 +253,9 @@ const generateAnimationScripts = (execution, task, imageWidth, imageHeight)=>{
|
|
|
236
253
|
img: null == (_task_recorder2 = task.recorder) ? void 0 : null == (_task_recorder_2 = _task_recorder2[1]) ? void 0 : _task_recorder_2.screenshot,
|
|
237
254
|
duration: imgStillDuration,
|
|
238
255
|
title,
|
|
239
|
-
subTitle
|
|
256
|
+
subTitle,
|
|
257
|
+
imageWidth: (null == (_task_uiContext4 = task.uiContext) ? void 0 : null == (_task_uiContext_size4 = _task_uiContext4.size) ? void 0 : _task_uiContext_size4.width) || imageWidth,
|
|
258
|
+
imageHeight: (null == (_task_uiContext5 = task.uiContext) ? void 0 : null == (_task_uiContext_size5 = _task_uiContext5.size) ? void 0 : _task_uiContext_size5.height) || imageHeight
|
|
240
259
|
});
|
|
241
260
|
} else scripts.push({
|
|
242
261
|
type: 'sleep',
|
|
@@ -249,16 +268,22 @@ const generateAnimationScripts = (execution, task, imageWidth, imageHeight)=>{
|
|
|
249
268
|
const title = typeStr(task);
|
|
250
269
|
const subTitle = paramStr(task);
|
|
251
270
|
const screenshot = null == (_task_recorder3 = task.recorder) ? void 0 : null == (_task_recorder_3 = _task_recorder3[task.recorder.length - 1]) ? void 0 : _task_recorder_3.screenshot;
|
|
252
|
-
if (screenshot)
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
271
|
+
if (screenshot) {
|
|
272
|
+
var _task_uiContext_size6, _task_uiContext6, _task_uiContext_size7, _task_uiContext7;
|
|
273
|
+
scripts.push({
|
|
274
|
+
type: 'img',
|
|
275
|
+
img: screenshot,
|
|
276
|
+
duration: stillDuration,
|
|
277
|
+
camera: fullPageCameraState,
|
|
278
|
+
title,
|
|
279
|
+
subTitle,
|
|
280
|
+
imageWidth: (null == (_task_uiContext6 = task.uiContext) ? void 0 : null == (_task_uiContext_size6 = _task_uiContext6.size) ? void 0 : _task_uiContext_size6.width) || imageWidth,
|
|
281
|
+
imageHeight: (null == (_task_uiContext7 = task.uiContext) ? void 0 : null == (_task_uiContext_size7 = _task_uiContext7.size) ? void 0 : _task_uiContext_size7.height) || imageHeight
|
|
282
|
+
});
|
|
283
|
+
}
|
|
260
284
|
}
|
|
261
285
|
if ('finished' !== task.status) {
|
|
286
|
+
var _task_uiContext_size8, _task_uiContext8, _task_uiContext_size9, _task_uiContext9;
|
|
262
287
|
errorStateFlag = true;
|
|
263
288
|
const errorTitle = typeStr(task);
|
|
264
289
|
const errorMsg = task.errorMessage || 'unknown error';
|
|
@@ -269,7 +294,9 @@ const generateAnimationScripts = (execution, task, imageWidth, imageHeight)=>{
|
|
|
269
294
|
camera: fullPageCameraState,
|
|
270
295
|
duration: stillDuration,
|
|
271
296
|
title: errorTitle,
|
|
272
|
-
subTitle: errorSubTitle
|
|
297
|
+
subTitle: errorSubTitle,
|
|
298
|
+
imageWidth: (null == (_task_uiContext8 = task.uiContext) ? void 0 : null == (_task_uiContext_size8 = _task_uiContext8.size) ? void 0 : _task_uiContext_size8.width) || imageWidth,
|
|
299
|
+
imageHeight: (null == (_task_uiContext9 = task.uiContext) ? void 0 : null == (_task_uiContext_size9 = _task_uiContext9.size) ? void 0 : _task_uiContext_size9.height) || imageHeight
|
|
273
300
|
});
|
|
274
301
|
return;
|
|
275
302
|
}
|
|
@@ -212,9 +212,29 @@ function Player(props) {
|
|
|
212
212
|
const cameraState = (0, external_react_namespaceObject.useRef)({
|
|
213
213
|
...basicCameraState
|
|
214
214
|
});
|
|
215
|
-
const
|
|
215
|
+
const resizeCanvasIfNeeded = async (newWidth, newHeight)=>{
|
|
216
|
+
if (app.screen.width !== newWidth || app.screen.height !== newHeight) {
|
|
217
|
+
app.renderer.resize(newWidth, newHeight);
|
|
218
|
+
if (divContainerRef.current) {
|
|
219
|
+
const aspectRatio = newWidth / newHeight;
|
|
220
|
+
divContainerRef.current.style.setProperty('--canvas-aspect-ratio', aspectRatio.toString());
|
|
221
|
+
}
|
|
222
|
+
const newBasicCameraState = {
|
|
223
|
+
left: 0,
|
|
224
|
+
top: 0,
|
|
225
|
+
width: newWidth,
|
|
226
|
+
pointerLeft: Math.round(newWidth / 2),
|
|
227
|
+
pointerTop: Math.round(newHeight / 2)
|
|
228
|
+
};
|
|
229
|
+
cameraState.current = newBasicCameraState;
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
const repaintImage = async (scriptWidth, scriptHeight)=>{
|
|
216
233
|
const imgToUpdate = currentImg.current;
|
|
217
234
|
if (!imgToUpdate) return void console.warn('no image to update');
|
|
235
|
+
const targetWidth = scriptWidth || imageWidth;
|
|
236
|
+
const targetHeight = scriptHeight || imageHeight;
|
|
237
|
+
await resizeCanvasIfNeeded(targetWidth, targetHeight);
|
|
218
238
|
if (!(0, pixi_loader_js_namespaceObject.getTextureFromCache)(imgToUpdate)) {
|
|
219
239
|
console.warn('image not loaded', imgToUpdate);
|
|
220
240
|
await (0, pixi_loader_js_namespaceObject.loadTexture)(imgToUpdate);
|
|
@@ -228,8 +248,8 @@ function Player(props) {
|
|
|
228
248
|
if (child) windowContentContainer.removeChild(child);
|
|
229
249
|
sprite.label = mainImgLabel;
|
|
230
250
|
sprite.zIndex = LAYER_ORDER_IMG;
|
|
231
|
-
sprite.width =
|
|
232
|
-
sprite.height =
|
|
251
|
+
sprite.width = targetWidth;
|
|
252
|
+
sprite.height = targetHeight;
|
|
233
253
|
windowContentContainer.addChild(sprite);
|
|
234
254
|
};
|
|
235
255
|
const spinningPointer = (frame)=>{
|
|
@@ -287,9 +307,10 @@ function Player(props) {
|
|
|
287
307
|
pointerSprite.current.zIndex = LAYER_ORDER_POINTER;
|
|
288
308
|
windowContentContainer.addChild(pointerSprite.current);
|
|
289
309
|
};
|
|
290
|
-
const updateCamera = (state)=>{
|
|
310
|
+
const updateCamera = (state, currentWidth)=>{
|
|
291
311
|
cameraState.current = state;
|
|
292
|
-
const
|
|
312
|
+
const effectiveWidth = currentWidth || app.screen.width || imageWidth;
|
|
313
|
+
const newScale = autoZoom ? Math.max(1, effectiveWidth / state.width) : 1;
|
|
293
314
|
windowContentContainer.scale.set(newScale);
|
|
294
315
|
windowContentContainer.x = autoZoom ? Math.round(canvasPaddingLeft - state.left * newScale) : canvasPaddingLeft;
|
|
295
316
|
windowContentContainer.y = autoZoom ? Math.round(canvasPaddingTop - state.top * newScale) : canvasPaddingTop;
|
|
@@ -303,6 +324,8 @@ function Player(props) {
|
|
|
303
324
|
}
|
|
304
325
|
};
|
|
305
326
|
const cameraAnimation = async (targetState, duration, frame)=>{
|
|
327
|
+
const currentCanvasWidth = app.screen.width || imageWidth;
|
|
328
|
+
const currentCanvasHeight = app.screen.height || imageHeight;
|
|
306
329
|
if (!autoZoom) {
|
|
307
330
|
const currentState = {
|
|
308
331
|
...cameraState.current
|
|
@@ -322,7 +345,7 @@ function Player(props) {
|
|
|
322
345
|
pointerLeft: startPointerLeft + (targetState.pointerLeft - startPointerLeft) * progress,
|
|
323
346
|
pointerTop: startPointerTop + (targetState.pointerTop - startPointerTop) * progress
|
|
324
347
|
};
|
|
325
|
-
updateCamera(nextState);
|
|
348
|
+
updateCamera(nextState, currentCanvasWidth);
|
|
326
349
|
if (elapsedTime < duration) frame(animate);
|
|
327
350
|
else resolve();
|
|
328
351
|
};
|
|
@@ -337,7 +360,7 @@ function Player(props) {
|
|
|
337
360
|
const startTop = currentState.top;
|
|
338
361
|
const startPointerLeft = currentState.pointerLeft;
|
|
339
362
|
const startPointerTop = currentState.pointerTop;
|
|
340
|
-
const startScale = currentState.width /
|
|
363
|
+
const startScale = currentState.width / currentCanvasWidth;
|
|
341
364
|
const startTime = performance.now();
|
|
342
365
|
const shouldMovePointer = 'number' == typeof targetState.pointerLeft && 'number' == typeof targetState.pointerTop && (targetState.pointerLeft !== startPointerLeft || targetState.pointerTop !== startPointerTop);
|
|
343
366
|
const pointerMoveDuration = shouldMovePointer ? 0.375 * duration : 0;
|
|
@@ -362,19 +385,19 @@ function Player(props) {
|
|
|
362
385
|
const cameraElapsedTime = elapsedTime - cameraMoveStart;
|
|
363
386
|
const rawCameraProgress = Math.min(cameraElapsedTime / cameraMoveDuration, 1);
|
|
364
387
|
const cameraProgress = cubicImage(rawCameraProgress);
|
|
365
|
-
const targetScale = targetState.width /
|
|
388
|
+
const targetScale = targetState.width / currentCanvasWidth;
|
|
366
389
|
const progressScale = startScale + (targetScale - startScale) * cameraProgress;
|
|
367
|
-
const progressWidth =
|
|
368
|
-
const progressHeight =
|
|
390
|
+
const progressWidth = currentCanvasWidth * progressScale;
|
|
391
|
+
const progressHeight = currentCanvasHeight * progressScale;
|
|
369
392
|
nextState.width = progressWidth;
|
|
370
393
|
const progressLeft = startLeft + (targetState.left - startLeft) * cameraProgress;
|
|
371
394
|
const progressTop = startTop + (targetState.top - startTop) * cameraProgress;
|
|
372
|
-
const horizontalExceed = progressLeft + progressWidth -
|
|
373
|
-
const verticalExceed = progressTop + progressHeight -
|
|
395
|
+
const horizontalExceed = progressLeft + progressWidth - currentCanvasWidth;
|
|
396
|
+
const verticalExceed = progressTop + progressHeight - currentCanvasHeight;
|
|
374
397
|
nextState.left = horizontalExceed > 0 ? progressLeft + horizontalExceed : progressLeft;
|
|
375
398
|
nextState.top = verticalExceed > 0 ? progressTop + verticalExceed : progressTop;
|
|
376
399
|
}
|
|
377
|
-
updateCamera(nextState);
|
|
400
|
+
updateCamera(nextState, currentCanvasWidth);
|
|
378
401
|
if (elapsedTime < duration) frame(animate);
|
|
379
402
|
else resolve();
|
|
380
403
|
};
|
|
@@ -511,7 +534,7 @@ function Player(props) {
|
|
|
511
534
|
var _item_context;
|
|
512
535
|
if (!item.img) throw new Error('img is required');
|
|
513
536
|
currentImg.current = item.img;
|
|
514
|
-
await repaintImage();
|
|
537
|
+
await repaintImage(item.imageWidth, item.imageHeight);
|
|
515
538
|
const elements = (null == (_item_context = item.context) ? void 0 : _item_context.tree) ? (0, extractor_namespaceObject.treeToList)(item.context.tree) : [];
|
|
516
539
|
const highlightElements = item.highlightElement ? [
|
|
517
540
|
item.highlightElement
|
|
@@ -528,7 +551,7 @@ function Player(props) {
|
|
|
528
551
|
} else if ('img' === item.type) {
|
|
529
552
|
if (item.img && item.img !== currentImg.current) {
|
|
530
553
|
currentImg.current = item.img;
|
|
531
|
-
await repaintImage();
|
|
554
|
+
await repaintImage(item.imageWidth, item.imageHeight);
|
|
532
555
|
}
|
|
533
556
|
if (item.camera) await cameraAnimation(item.camera, item.duration, frame);
|
|
534
557
|
else await sleep(item.duration);
|
|
@@ -91,10 +91,10 @@
|
|
|
91
91
|
.playground-container .middle-dialog-area .scroll-to-bottom-button {
|
|
92
92
|
z-index: 10;
|
|
93
93
|
background: #fff;
|
|
94
|
+
border: 1px solid rgba(0, 0, 0, .08);
|
|
94
95
|
position: absolute;
|
|
95
96
|
bottom: 10px;
|
|
96
97
|
right: 0;
|
|
97
|
-
box-shadow: 0 4px 8px rgba(0, 0, 0, .04);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
.playground-container .middle-dialog-area .scroll-to-bottom-button:hover {
|
|
@@ -81,11 +81,35 @@ function UniversalPlayground(param) {
|
|
|
81
81
|
let { playgroundSDK, storage, contextProvider, config: componentConfig = {}, branding = {}, className = '', dryMode = false, showContextPreview = true } = param;
|
|
82
82
|
const [form] = external_antd_namespaceObject.Form.useForm();
|
|
83
83
|
const { config } = (0, store_js_namespaceObject.useEnvConfig)();
|
|
84
|
-
const
|
|
84
|
+
const [sdkReady, setSdkReady] = (0, external_react_namespaceObject.useState)(false);
|
|
85
|
+
(0, external_react_namespaceObject.useEffect)(()=>{
|
|
86
|
+
const initializeSDK = async ()=>{
|
|
87
|
+
if (playgroundSDK && 'function' == typeof playgroundSDK.checkStatus) try {
|
|
88
|
+
await playgroundSDK.checkStatus();
|
|
89
|
+
setSdkReady(true);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.warn('Failed to initialize SDK, using default namespace:', error);
|
|
92
|
+
setSdkReady(true);
|
|
93
|
+
}
|
|
94
|
+
else setSdkReady(true);
|
|
95
|
+
};
|
|
96
|
+
initializeSDK();
|
|
97
|
+
}, [
|
|
98
|
+
playgroundSDK
|
|
99
|
+
]);
|
|
100
|
+
const effectiveStorage = (0, external_react_namespaceObject.useMemo)(()=>{
|
|
85
101
|
if (storage) return storage;
|
|
102
|
+
if (!sdkReady) return null;
|
|
86
103
|
const namespace = componentConfig.storageNamespace || getSDKId(playgroundSDK);
|
|
87
|
-
|
|
88
|
-
|
|
104
|
+
const bestStorageType = (0, storage_provider_js_namespaceObject.detectBestStorageType)();
|
|
105
|
+
console.log(`Using ${bestStorageType} storage for namespace: ${namespace}`);
|
|
106
|
+
return (0, storage_provider_js_namespaceObject.createStorageProvider)(bestStorageType, namespace);
|
|
107
|
+
}, [
|
|
108
|
+
storage,
|
|
109
|
+
sdkReady,
|
|
110
|
+
componentConfig.storageNamespace,
|
|
111
|
+
playgroundSDK
|
|
112
|
+
]);
|
|
89
113
|
const { loading, setLoading, infoList, setInfoList, actionSpace, actionSpaceLoading, uiContextPreview, setUiContextPreview, showScrollToBottomButton, verticalMode, replayCounter, setReplayCounter, infoListRef, currentRunningIdRef, interruptedFlagRef, clearInfoList, handleScrollToBottom } = (0, usePlaygroundState_js_namespaceObject.usePlaygroundState)(playgroundSDK, effectiveStorage, contextProvider);
|
|
90
114
|
const { handleRun: executeAction, handleStop, canStop } = (0, usePlaygroundExecution_js_namespaceObject.usePlaygroundExecution)(playgroundSDK, effectiveStorage, actionSpace, loading, setLoading, infoList, setInfoList, replayCounter, setReplayCounter, verticalMode, currentRunningIdRef, interruptedFlagRef);
|
|
91
115
|
(0, external_react_namespaceObject.useEffect)(()=>{
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
IndexedDBStorageProvider: ()=>IndexedDBStorageProvider,
|
|
28
|
+
NoOpStorageProvider: ()=>NoOpStorageProvider,
|
|
29
|
+
MemoryStorageProvider: ()=>MemoryStorageProvider
|
|
30
|
+
});
|
|
31
|
+
const baseDB_namespaceObject = require("@midscene/shared/baseDB");
|
|
32
|
+
function _define_property(obj, key, value) {
|
|
33
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
34
|
+
value: value,
|
|
35
|
+
enumerable: true,
|
|
36
|
+
configurable: true,
|
|
37
|
+
writable: true
|
|
38
|
+
});
|
|
39
|
+
else obj[key] = value;
|
|
40
|
+
return obj;
|
|
41
|
+
}
|
|
42
|
+
const DB_NAME = 'midscene_playground';
|
|
43
|
+
const DB_VERSION = 1;
|
|
44
|
+
const MESSAGES_STORE = 'playground_messages';
|
|
45
|
+
const RESULTS_STORE = 'playground_results';
|
|
46
|
+
const MAX_STORED_MESSAGES = 100;
|
|
47
|
+
const MAX_STORED_RESULTS = 50;
|
|
48
|
+
class IndexedDBStorageProvider {
|
|
49
|
+
async saveMessages(messages) {
|
|
50
|
+
await (0, baseDB_namespaceObject.withErrorHandling)(async ()=>{
|
|
51
|
+
await this.dbManager.clear(MESSAGES_STORE);
|
|
52
|
+
const messagesToSave = messages.slice(-MAX_STORED_MESSAGES);
|
|
53
|
+
await Promise.all(messagesToSave.map((msg, index)=>{
|
|
54
|
+
const lightMessage = {
|
|
55
|
+
...msg,
|
|
56
|
+
result: void 0
|
|
57
|
+
};
|
|
58
|
+
const data = {
|
|
59
|
+
id: msg.id || `msg-${index}`,
|
|
60
|
+
data: lightMessage,
|
|
61
|
+
timestamp: msg.timestamp ? msg.timestamp.getTime() : Date.now() + index
|
|
62
|
+
};
|
|
63
|
+
return this.dbManager.put(MESSAGES_STORE, data);
|
|
64
|
+
}));
|
|
65
|
+
}, 'Failed to save messages to IndexedDB', void 0, this.messagesCleanup);
|
|
66
|
+
}
|
|
67
|
+
async loadMessages() {
|
|
68
|
+
const result = await (0, baseDB_namespaceObject.withErrorHandling)(async ()=>{
|
|
69
|
+
const messages = await this.dbManager.getAll(MESSAGES_STORE, true);
|
|
70
|
+
if (0 === messages.length) return [];
|
|
71
|
+
return Promise.all(messages.map(async (msg)=>{
|
|
72
|
+
const item = msg.data;
|
|
73
|
+
const restoredItem = {
|
|
74
|
+
...item,
|
|
75
|
+
timestamp: new Date(item.timestamp)
|
|
76
|
+
};
|
|
77
|
+
if ('result' === item.type && item.id) {
|
|
78
|
+
const fullResult = await this.loadResult(item.id);
|
|
79
|
+
if (fullResult) {
|
|
80
|
+
restoredItem.result = fullResult.result;
|
|
81
|
+
restoredItem.replayScriptsInfo = fullResult.replayScriptsInfo;
|
|
82
|
+
restoredItem.replayCounter = fullResult.replayCounter;
|
|
83
|
+
restoredItem.verticalMode = fullResult.verticalMode;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return restoredItem;
|
|
87
|
+
}));
|
|
88
|
+
}, 'Failed to load messages from IndexedDB', [], this.messagesCleanup);
|
|
89
|
+
return result || [];
|
|
90
|
+
}
|
|
91
|
+
async clearMessages() {
|
|
92
|
+
await (0, baseDB_namespaceObject.withErrorHandling)(async ()=>{
|
|
93
|
+
await Promise.all([
|
|
94
|
+
this.dbManager.clear(MESSAGES_STORE),
|
|
95
|
+
this.dbManager.clear(RESULTS_STORE)
|
|
96
|
+
]);
|
|
97
|
+
}, 'Failed to clear messages from IndexedDB');
|
|
98
|
+
}
|
|
99
|
+
async saveResult(id, result) {
|
|
100
|
+
await (0, baseDB_namespaceObject.withErrorHandling)(async ()=>{
|
|
101
|
+
const compressedResult = this.compressResultForStorage(result);
|
|
102
|
+
const data = {
|
|
103
|
+
id,
|
|
104
|
+
data: compressedResult,
|
|
105
|
+
timestamp: Date.now(),
|
|
106
|
+
size: JSON.stringify(compressedResult).length
|
|
107
|
+
};
|
|
108
|
+
await this.dbManager.put(RESULTS_STORE, data);
|
|
109
|
+
}, 'Failed to save result to IndexedDB', void 0, this.resultsCleanup);
|
|
110
|
+
}
|
|
111
|
+
async loadResult(id) {
|
|
112
|
+
const result = await (0, baseDB_namespaceObject.withErrorHandling)(async ()=>{
|
|
113
|
+
const data = await this.dbManager.get(RESULTS_STORE, id);
|
|
114
|
+
return (null == data ? void 0 : data.data) || null;
|
|
115
|
+
}, 'Failed to load result from IndexedDB', null);
|
|
116
|
+
return result || null;
|
|
117
|
+
}
|
|
118
|
+
compressResultForStorage(result) {
|
|
119
|
+
var _result_result_dump, _result_result;
|
|
120
|
+
if (!(null == (_result_result = result.result) ? void 0 : null == (_result_result_dump = _result_result.dump) ? void 0 : _result_result_dump.executions)) return result;
|
|
121
|
+
const compressedExecutions = result.result.dump.executions.map((execution)=>{
|
|
122
|
+
var _execution_tasks;
|
|
123
|
+
return {
|
|
124
|
+
...execution,
|
|
125
|
+
tasks: (null == (_execution_tasks = execution.tasks) ? void 0 : _execution_tasks.map((task)=>{
|
|
126
|
+
var _task_recorder;
|
|
127
|
+
var _this_compressScreenshotIfNeeded;
|
|
128
|
+
return {
|
|
129
|
+
...task,
|
|
130
|
+
uiContext: task.uiContext ? {
|
|
131
|
+
...task.uiContext,
|
|
132
|
+
screenshotBase64: null != (_this_compressScreenshotIfNeeded = this.compressScreenshotIfNeeded(task.uiContext.screenshotBase64)) ? _this_compressScreenshotIfNeeded : task.uiContext.screenshotBase64
|
|
133
|
+
} : task.uiContext,
|
|
134
|
+
recorder: null == (_task_recorder = task.recorder) ? void 0 : _task_recorder.map((record)=>({
|
|
135
|
+
...record,
|
|
136
|
+
screenshot: this.compressScreenshotIfNeeded(record.screenshot)
|
|
137
|
+
}))
|
|
138
|
+
};
|
|
139
|
+
})) || []
|
|
140
|
+
};
|
|
141
|
+
});
|
|
142
|
+
return {
|
|
143
|
+
...result,
|
|
144
|
+
result: {
|
|
145
|
+
...result.result,
|
|
146
|
+
dump: {
|
|
147
|
+
...result.result.dump,
|
|
148
|
+
executions: compressedExecutions
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
compressScreenshotIfNeeded(screenshot) {
|
|
154
|
+
if (!screenshot) return screenshot;
|
|
155
|
+
if (screenshot.length > 1048576) {
|
|
156
|
+
const sizeKB = Math.round(screenshot.length / 1024);
|
|
157
|
+
return `[COMPRESSED: ${sizeKB}KB screenshot removed for storage]`;
|
|
158
|
+
}
|
|
159
|
+
return screenshot;
|
|
160
|
+
}
|
|
161
|
+
async getStorageStats() {
|
|
162
|
+
const result = await (0, baseDB_namespaceObject.withErrorHandling)(async ()=>{
|
|
163
|
+
const [messageCount, resultCount] = await Promise.all([
|
|
164
|
+
this.dbManager.count(MESSAGES_STORE),
|
|
165
|
+
this.dbManager.count(RESULTS_STORE)
|
|
166
|
+
]);
|
|
167
|
+
return {
|
|
168
|
+
messageCount,
|
|
169
|
+
resultCount
|
|
170
|
+
};
|
|
171
|
+
}, 'Failed to get storage statistics', {
|
|
172
|
+
messageCount: 0,
|
|
173
|
+
resultCount: 0
|
|
174
|
+
});
|
|
175
|
+
return result || {
|
|
176
|
+
messageCount: 0,
|
|
177
|
+
resultCount: 0
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
async cleanup() {
|
|
181
|
+
await Promise.all([
|
|
182
|
+
this.messagesCleanup(),
|
|
183
|
+
this.resultsCleanup()
|
|
184
|
+
]);
|
|
185
|
+
}
|
|
186
|
+
constructor(namespace = 'playground'){
|
|
187
|
+
_define_property(this, "dbManager", void 0);
|
|
188
|
+
_define_property(this, "namespace", void 0);
|
|
189
|
+
_define_property(this, "messagesCleanup", void 0);
|
|
190
|
+
_define_property(this, "resultsCleanup", void 0);
|
|
191
|
+
this.namespace = namespace;
|
|
192
|
+
this.dbManager = new baseDB_namespaceObject.IndexedDBManager(`${DB_NAME}_${namespace}`, DB_VERSION, [
|
|
193
|
+
{
|
|
194
|
+
name: MESSAGES_STORE,
|
|
195
|
+
keyPath: 'id'
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
name: RESULTS_STORE,
|
|
199
|
+
keyPath: 'id'
|
|
200
|
+
}
|
|
201
|
+
]);
|
|
202
|
+
this.messagesCleanup = (0, baseDB_namespaceObject.createCleanupFunction)(this.dbManager, MESSAGES_STORE, MAX_STORED_MESSAGES);
|
|
203
|
+
this.resultsCleanup = (0, baseDB_namespaceObject.createCleanupFunction)(this.dbManager, RESULTS_STORE, MAX_STORED_RESULTS);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
class MemoryStorageProvider {
|
|
207
|
+
async saveMessages(messages) {
|
|
208
|
+
this.messages = [
|
|
209
|
+
...messages
|
|
210
|
+
];
|
|
211
|
+
}
|
|
212
|
+
async loadMessages() {
|
|
213
|
+
return [
|
|
214
|
+
...this.messages
|
|
215
|
+
];
|
|
216
|
+
}
|
|
217
|
+
async clearMessages() {
|
|
218
|
+
this.messages = [];
|
|
219
|
+
this.results.clear();
|
|
220
|
+
}
|
|
221
|
+
async saveResult(id, result) {
|
|
222
|
+
this.results.set(id, result);
|
|
223
|
+
}
|
|
224
|
+
constructor(){
|
|
225
|
+
_define_property(this, "messages", []);
|
|
226
|
+
_define_property(this, "results", new Map());
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
class NoOpStorageProvider {
|
|
230
|
+
async saveMessages(_messages) {}
|
|
231
|
+
async loadMessages() {
|
|
232
|
+
return [];
|
|
233
|
+
}
|
|
234
|
+
async clearMessages() {}
|
|
235
|
+
async saveResult(_id, _result) {}
|
|
236
|
+
}
|
|
237
|
+
exports.IndexedDBStorageProvider = __webpack_exports__.IndexedDBStorageProvider;
|
|
238
|
+
exports.MemoryStorageProvider = __webpack_exports__.MemoryStorageProvider;
|
|
239
|
+
exports.NoOpStorageProvider = __webpack_exports__.NoOpStorageProvider;
|
|
240
|
+
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
241
|
+
"IndexedDBStorageProvider",
|
|
242
|
+
"MemoryStorageProvider",
|
|
243
|
+
"NoOpStorageProvider"
|
|
244
|
+
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
|
|
245
|
+
Object.defineProperty(exports, '__esModule', {
|
|
246
|
+
value: true
|
|
247
|
+
});
|