@godscene/core 1.7.11
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/LICENSE +21 -0
- package/README.md +9 -0
- package/dist/es/agent/agent.mjs +767 -0
- package/dist/es/agent/common.mjs +0 -0
- package/dist/es/agent/execution-session.mjs +39 -0
- package/dist/es/agent/index.mjs +6 -0
- package/dist/es/agent/task-builder.mjs +343 -0
- package/dist/es/agent/task-cache.mjs +212 -0
- package/dist/es/agent/tasks.mjs +428 -0
- package/dist/es/agent/ui-utils.mjs +101 -0
- package/dist/es/agent/utils.mjs +167 -0
- package/dist/es/ai-model/auto-glm/actions.mjs +237 -0
- package/dist/es/ai-model/auto-glm/index.mjs +6 -0
- package/dist/es/ai-model/auto-glm/parser.mjs +237 -0
- package/dist/es/ai-model/auto-glm/planning.mjs +69 -0
- package/dist/es/ai-model/auto-glm/prompt.mjs +220 -0
- package/dist/es/ai-model/auto-glm/util.mjs +7 -0
- package/dist/es/ai-model/connectivity.mjs +136 -0
- package/dist/es/ai-model/conversation-history.mjs +193 -0
- package/dist/es/ai-model/index.mjs +12 -0
- package/dist/es/ai-model/inspect.mjs +395 -0
- package/dist/es/ai-model/llm-planning.mjs +231 -0
- package/dist/es/ai-model/prompt/common.mjs +5 -0
- package/dist/es/ai-model/prompt/describe.mjs +64 -0
- package/dist/es/ai-model/prompt/extraction.mjs +129 -0
- package/dist/es/ai-model/prompt/llm-locator.mjs +49 -0
- package/dist/es/ai-model/prompt/llm-planning.mjs +584 -0
- package/dist/es/ai-model/prompt/llm-section-locator.mjs +42 -0
- package/dist/es/ai-model/prompt/order-sensitive-judge.mjs +33 -0
- package/dist/es/ai-model/prompt/playwright-generator.mjs +115 -0
- package/dist/es/ai-model/prompt/ui-tars-planning.mjs +34 -0
- package/dist/es/ai-model/prompt/util.mjs +57 -0
- package/dist/es/ai-model/prompt/yaml-generator.mjs +201 -0
- package/dist/es/ai-model/service-caller/codex-app-server.mjs +573 -0
- package/dist/es/ai-model/service-caller/image-detail.mjs +4 -0
- package/dist/es/ai-model/service-caller/index.mjs +648 -0
- package/dist/es/ai-model/service-caller/request-timeout.mjs +47 -0
- package/dist/es/ai-model/ui-tars-planning.mjs +247 -0
- package/dist/es/common.mjs +382 -0
- package/dist/es/device/device-options.mjs +0 -0
- package/dist/es/device/index.mjs +340 -0
- package/dist/es/dump/html-utils.mjs +290 -0
- package/dist/es/dump/index.mjs +3 -0
- package/dist/es/dump/screenshot-restoration.mjs +30 -0
- package/dist/es/dump/screenshot-store.mjs +125 -0
- package/dist/es/index.mjs +17 -0
- package/dist/es/report-cli.mjs +149 -0
- package/dist/es/report-generator.mjs +203 -0
- package/dist/es/report-markdown.mjs +216 -0
- package/dist/es/report.mjs +287 -0
- package/dist/es/screenshot-item.mjs +120 -0
- package/dist/es/service/index.mjs +272 -0
- package/dist/es/service/utils.mjs +13 -0
- package/dist/es/skill/index.mjs +35 -0
- package/dist/es/task-runner.mjs +261 -0
- package/dist/es/task-timing.mjs +10 -0
- package/dist/es/tree.mjs +11 -0
- package/dist/es/types.mjs +202 -0
- package/dist/es/utils.mjs +232 -0
- package/dist/es/yaml/builder.mjs +11 -0
- package/dist/es/yaml/index.mjs +4 -0
- package/dist/es/yaml/player.mjs +425 -0
- package/dist/es/yaml/utils.mjs +100 -0
- package/dist/es/yaml.mjs +0 -0
- package/dist/lib/agent/agent.js +815 -0
- package/dist/lib/agent/common.js +5 -0
- package/dist/lib/agent/execution-session.js +73 -0
- package/dist/lib/agent/index.js +76 -0
- package/dist/lib/agent/task-builder.js +380 -0
- package/dist/lib/agent/task-cache.js +264 -0
- package/dist/lib/agent/tasks.js +471 -0
- package/dist/lib/agent/ui-utils.js +153 -0
- package/dist/lib/agent/utils.js +238 -0
- package/dist/lib/ai-model/auto-glm/actions.js +271 -0
- package/dist/lib/ai-model/auto-glm/index.js +64 -0
- package/dist/lib/ai-model/auto-glm/parser.js +280 -0
- package/dist/lib/ai-model/auto-glm/planning.js +103 -0
- package/dist/lib/ai-model/auto-glm/prompt.js +257 -0
- package/dist/lib/ai-model/auto-glm/util.js +44 -0
- package/dist/lib/ai-model/connectivity.js +180 -0
- package/dist/lib/ai-model/conversation-history.js +227 -0
- package/dist/lib/ai-model/index.js +127 -0
- package/dist/lib/ai-model/inspect.js +441 -0
- package/dist/lib/ai-model/llm-planning.js +268 -0
- package/dist/lib/ai-model/prompt/common.js +39 -0
- package/dist/lib/ai-model/prompt/describe.js +98 -0
- package/dist/lib/ai-model/prompt/extraction.js +169 -0
- package/dist/lib/ai-model/prompt/llm-locator.js +86 -0
- package/dist/lib/ai-model/prompt/llm-planning.js +621 -0
- package/dist/lib/ai-model/prompt/llm-section-locator.js +79 -0
- package/dist/lib/ai-model/prompt/order-sensitive-judge.js +70 -0
- package/dist/lib/ai-model/prompt/playwright-generator.js +176 -0
- package/dist/lib/ai-model/prompt/ui-tars-planning.js +71 -0
- package/dist/lib/ai-model/prompt/util.js +103 -0
- package/dist/lib/ai-model/prompt/yaml-generator.js +262 -0
- package/dist/lib/ai-model/service-caller/codex-app-server.js +622 -0
- package/dist/lib/ai-model/service-caller/image-detail.js +38 -0
- package/dist/lib/ai-model/service-caller/index.js +716 -0
- package/dist/lib/ai-model/service-caller/request-timeout.js +93 -0
- package/dist/lib/ai-model/ui-tars-planning.js +281 -0
- package/dist/lib/common.js +491 -0
- package/dist/lib/device/device-options.js +18 -0
- package/dist/lib/device/index.js +467 -0
- package/dist/lib/dump/html-utils.js +366 -0
- package/dist/lib/dump/index.js +58 -0
- package/dist/lib/dump/screenshot-restoration.js +64 -0
- package/dist/lib/dump/screenshot-store.js +165 -0
- package/dist/lib/index.js +184 -0
- package/dist/lib/report-cli.js +189 -0
- package/dist/lib/report-generator.js +244 -0
- package/dist/lib/report-markdown.js +253 -0
- package/dist/lib/report.js +333 -0
- package/dist/lib/screenshot-item.js +154 -0
- package/dist/lib/service/index.js +306 -0
- package/dist/lib/service/utils.js +47 -0
- package/dist/lib/skill/index.js +69 -0
- package/dist/lib/task-runner.js +298 -0
- package/dist/lib/task-timing.js +44 -0
- package/dist/lib/tree.js +51 -0
- package/dist/lib/types.js +298 -0
- package/dist/lib/utils.js +314 -0
- package/dist/lib/yaml/builder.js +55 -0
- package/dist/lib/yaml/index.js +79 -0
- package/dist/lib/yaml/player.js +459 -0
- package/dist/lib/yaml/utils.js +153 -0
- package/dist/lib/yaml.js +18 -0
- package/dist/types/agent/agent.d.ts +220 -0
- package/dist/types/agent/common.d.ts +0 -0
- package/dist/types/agent/execution-session.d.ts +36 -0
- package/dist/types/agent/index.d.ts +9 -0
- package/dist/types/agent/task-builder.d.ts +34 -0
- package/dist/types/agent/task-cache.d.ts +49 -0
- package/dist/types/agent/tasks.d.ts +70 -0
- package/dist/types/agent/ui-utils.d.ts +14 -0
- package/dist/types/agent/utils.d.ts +25 -0
- package/dist/types/ai-model/auto-glm/actions.d.ts +78 -0
- package/dist/types/ai-model/auto-glm/index.d.ts +6 -0
- package/dist/types/ai-model/auto-glm/parser.d.ts +18 -0
- package/dist/types/ai-model/auto-glm/planning.d.ts +12 -0
- package/dist/types/ai-model/auto-glm/prompt.d.ts +27 -0
- package/dist/types/ai-model/auto-glm/util.d.ts +13 -0
- package/dist/types/ai-model/connectivity.d.ts +20 -0
- package/dist/types/ai-model/conversation-history.d.ts +105 -0
- package/dist/types/ai-model/index.d.ts +16 -0
- package/dist/types/ai-model/inspect.d.ts +67 -0
- package/dist/types/ai-model/llm-planning.d.ts +19 -0
- package/dist/types/ai-model/prompt/common.d.ts +2 -0
- package/dist/types/ai-model/prompt/describe.d.ts +1 -0
- package/dist/types/ai-model/prompt/extraction.d.ts +7 -0
- package/dist/types/ai-model/prompt/llm-locator.d.ts +3 -0
- package/dist/types/ai-model/prompt/llm-planning.d.ts +10 -0
- package/dist/types/ai-model/prompt/llm-section-locator.d.ts +3 -0
- package/dist/types/ai-model/prompt/order-sensitive-judge.d.ts +2 -0
- package/dist/types/ai-model/prompt/playwright-generator.d.ts +26 -0
- package/dist/types/ai-model/prompt/ui-tars-planning.d.ts +2 -0
- package/dist/types/ai-model/prompt/util.d.ts +33 -0
- package/dist/types/ai-model/prompt/yaml-generator.d.ts +102 -0
- package/dist/types/ai-model/service-caller/codex-app-server.d.ts +42 -0
- package/dist/types/ai-model/service-caller/image-detail.d.ts +2 -0
- package/dist/types/ai-model/service-caller/index.d.ts +60 -0
- package/dist/types/ai-model/service-caller/request-timeout.d.ts +32 -0
- package/dist/types/ai-model/ui-tars-planning.d.ts +72 -0
- package/dist/types/common.d.ts +288 -0
- package/dist/types/device/device-options.d.ts +155 -0
- package/dist/types/device/index.d.ts +2565 -0
- package/dist/types/dump/html-utils.d.ts +75 -0
- package/dist/types/dump/index.d.ts +5 -0
- package/dist/types/dump/screenshot-restoration.d.ts +8 -0
- package/dist/types/dump/screenshot-store.d.ts +49 -0
- package/dist/types/index.d.ts +21 -0
- package/dist/types/report-cli.d.ts +36 -0
- package/dist/types/report-generator.d.ts +88 -0
- package/dist/types/report-markdown.d.ts +24 -0
- package/dist/types/report.d.ts +52 -0
- package/dist/types/screenshot-item.d.ts +67 -0
- package/dist/types/service/index.d.ts +24 -0
- package/dist/types/service/utils.d.ts +2 -0
- package/dist/types/skill/index.d.ts +25 -0
- package/dist/types/task-runner.d.ts +50 -0
- package/dist/types/task-timing.d.ts +8 -0
- package/dist/types/tree.d.ts +4 -0
- package/dist/types/types.d.ts +684 -0
- package/dist/types/utils.d.ts +45 -0
- package/dist/types/yaml/builder.d.ts +2 -0
- package/dist/types/yaml/index.d.ts +4 -0
- package/dist/types/yaml/player.d.ts +34 -0
- package/dist/types/yaml/utils.d.ts +9 -0
- package/dist/types/yaml.d.ts +215 -0
- package/package.json +130 -0
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
import { getMidsceneLocationSchema } from "../common.mjs";
|
|
2
|
+
import { getDebug } from "@godscene/shared/logger";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
function _define_property(obj, key, value) {
|
|
5
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
6
|
+
value: value,
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true
|
|
10
|
+
});
|
|
11
|
+
else obj[key] = value;
|
|
12
|
+
return obj;
|
|
13
|
+
}
|
|
14
|
+
class AbstractInterface {
|
|
15
|
+
constructor(){
|
|
16
|
+
_define_property(this, "mjpegStreamUrl", void 0);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const defineAction = (config)=>config;
|
|
20
|
+
const actionTapParamSchema = z.object({
|
|
21
|
+
locate: getMidsceneLocationSchema().describe('The element to be tapped')
|
|
22
|
+
});
|
|
23
|
+
const defineActionTap = (call)=>defineAction({
|
|
24
|
+
name: 'Tap',
|
|
25
|
+
description: 'Tap the element',
|
|
26
|
+
interfaceAlias: 'aiTap',
|
|
27
|
+
paramSchema: actionTapParamSchema,
|
|
28
|
+
sample: {
|
|
29
|
+
locate: {
|
|
30
|
+
prompt: 'the "Submit" button'
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
call
|
|
34
|
+
});
|
|
35
|
+
const actionRightClickParamSchema = z.object({
|
|
36
|
+
locate: getMidsceneLocationSchema().describe('The element to be right clicked')
|
|
37
|
+
});
|
|
38
|
+
const defineActionRightClick = (call)=>defineAction({
|
|
39
|
+
name: 'RightClick',
|
|
40
|
+
description: 'Right click the element',
|
|
41
|
+
interfaceAlias: 'aiRightClick',
|
|
42
|
+
paramSchema: actionRightClickParamSchema,
|
|
43
|
+
sample: {
|
|
44
|
+
locate: {
|
|
45
|
+
prompt: 'the file icon on the desktop'
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
call
|
|
49
|
+
});
|
|
50
|
+
const actionDoubleClickParamSchema = z.object({
|
|
51
|
+
locate: getMidsceneLocationSchema().describe('The element to be double clicked')
|
|
52
|
+
});
|
|
53
|
+
const defineActionDoubleClick = (call)=>defineAction({
|
|
54
|
+
name: 'DoubleClick',
|
|
55
|
+
description: 'Double click the element',
|
|
56
|
+
interfaceAlias: 'aiDoubleClick',
|
|
57
|
+
paramSchema: actionDoubleClickParamSchema,
|
|
58
|
+
sample: {
|
|
59
|
+
locate: {
|
|
60
|
+
prompt: 'the folder icon'
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
call
|
|
64
|
+
});
|
|
65
|
+
const actionHoverParamSchema = z.object({
|
|
66
|
+
locate: getMidsceneLocationSchema().describe('The element to be hovered')
|
|
67
|
+
});
|
|
68
|
+
const defineActionHover = (call)=>defineAction({
|
|
69
|
+
name: 'Hover',
|
|
70
|
+
description: 'Move the mouse to the element',
|
|
71
|
+
interfaceAlias: 'aiHover',
|
|
72
|
+
paramSchema: actionHoverParamSchema,
|
|
73
|
+
sample: {
|
|
74
|
+
locate: {
|
|
75
|
+
prompt: 'the navigation menu item "Products"'
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
call
|
|
79
|
+
});
|
|
80
|
+
const inputLocateDescription = 'the position of the placeholder or text content in the target input field. If there is no content, locate the center of the input field.';
|
|
81
|
+
const actionInputParamSchema = z.object({
|
|
82
|
+
value: z.union([
|
|
83
|
+
z.string(),
|
|
84
|
+
z.number()
|
|
85
|
+
]).transform((val)=>String(val)).describe('The text to input. Provide the final content for replace/append modes, or an empty string when using clear mode to remove existing text.'),
|
|
86
|
+
locate: getMidsceneLocationSchema().describe(inputLocateDescription).optional(),
|
|
87
|
+
mode: z["enum"]([
|
|
88
|
+
'replace',
|
|
89
|
+
'clear',
|
|
90
|
+
'typeOnly'
|
|
91
|
+
]).default('replace').describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - clear the field without inputting new text.')
|
|
92
|
+
});
|
|
93
|
+
const defineActionInput = (call)=>defineAction({
|
|
94
|
+
name: 'Input',
|
|
95
|
+
description: 'Input the value into the element',
|
|
96
|
+
interfaceAlias: 'aiInput',
|
|
97
|
+
paramSchema: actionInputParamSchema,
|
|
98
|
+
sample: {
|
|
99
|
+
value: 'test@example.com',
|
|
100
|
+
locate: {
|
|
101
|
+
prompt: 'the email input field'
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
call: (param)=>{
|
|
105
|
+
if ('append' === param.mode) param.mode = 'typeOnly';
|
|
106
|
+
return call(param);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
const actionKeyboardPressParamSchema = z.object({
|
|
110
|
+
locate: getMidsceneLocationSchema().describe('The element to be clicked before pressing the key').optional(),
|
|
111
|
+
keyName: z.string().describe("The key to be pressed. Use '+' for key combinations, e.g., 'Control+A', 'Shift+Enter'")
|
|
112
|
+
});
|
|
113
|
+
const defineActionKeyboardPress = (call)=>defineAction({
|
|
114
|
+
name: 'KeyboardPress',
|
|
115
|
+
description: 'Press a key or key combination, like "Enter", "Tab", "Escape", or "Control+A", "Shift+Enter". Do not use this to type text.',
|
|
116
|
+
interfaceAlias: 'aiKeyboardPress',
|
|
117
|
+
paramSchema: actionKeyboardPressParamSchema,
|
|
118
|
+
sample: {
|
|
119
|
+
keyName: 'Enter'
|
|
120
|
+
},
|
|
121
|
+
call
|
|
122
|
+
});
|
|
123
|
+
const actionScrollParamSchema = z.object({
|
|
124
|
+
scrollType: z["enum"]([
|
|
125
|
+
'singleAction',
|
|
126
|
+
'scrollToBottom',
|
|
127
|
+
'scrollToTop',
|
|
128
|
+
'scrollToRight',
|
|
129
|
+
'scrollToLeft'
|
|
130
|
+
]).default('singleAction').describe('The scroll behavior: "singleAction" for a single scroll action, "scrollToBottom" for scrolling all the way to the bottom by rapidly scrolling 5-10 times (skipping intermediate content until reaching the bottom), "scrollToTop" for scrolling all the way to the top by rapidly scrolling 5-10 times (skipping intermediate content until reaching the top), "scrollToRight" for scrolling all the way to the right by rapidly scrolling multiple times, "scrollToLeft" for scrolling all the way to the left by rapidly scrolling multiple times'),
|
|
131
|
+
direction: z["enum"]([
|
|
132
|
+
'down',
|
|
133
|
+
'up',
|
|
134
|
+
'right',
|
|
135
|
+
'left'
|
|
136
|
+
]).default('down').describe('The direction to scroll. Only effective when scrollType is "singleAction".'),
|
|
137
|
+
distance: z.number().nullable().optional().describe('The distance in pixels to scroll'),
|
|
138
|
+
locate: getMidsceneLocationSchema().optional().describe('Describe the target element to be scrolled on, like "the table" or "the list" or "the content area" or "the scrollable area". Do NOT provide a general intent like "scroll to find some element"')
|
|
139
|
+
});
|
|
140
|
+
const defineActionScroll = (call)=>defineAction({
|
|
141
|
+
name: 'Scroll',
|
|
142
|
+
description: 'Scroll the page or a scrollable element to browse content. This is the preferred way to scroll on all platforms, including mobile. Supports scrollToBottom/scrollToTop for boundary navigation. Default: direction `down`, scrollType `singleAction`, distance `null`.',
|
|
143
|
+
interfaceAlias: 'aiScroll',
|
|
144
|
+
paramSchema: actionScrollParamSchema,
|
|
145
|
+
sample: {
|
|
146
|
+
direction: 'down',
|
|
147
|
+
scrollType: 'singleAction',
|
|
148
|
+
locate: {
|
|
149
|
+
prompt: 'the center of the product list area'
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
call
|
|
153
|
+
});
|
|
154
|
+
const actionDragAndDropParamSchema = z.object({
|
|
155
|
+
from: getMidsceneLocationSchema().describe('The position to be dragged'),
|
|
156
|
+
to: getMidsceneLocationSchema().describe('The position to be dropped')
|
|
157
|
+
});
|
|
158
|
+
const defineActionDragAndDrop = (call)=>defineAction({
|
|
159
|
+
name: 'DragAndDrop',
|
|
160
|
+
description: 'Pick up a specific UI element and move it to a new position (e.g., reorder a card, move a file into a folder, sort list items). The element itself moves with your finger/mouse.',
|
|
161
|
+
interfaceAlias: 'aiDragAndDrop',
|
|
162
|
+
paramSchema: actionDragAndDropParamSchema,
|
|
163
|
+
sample: {
|
|
164
|
+
from: {
|
|
165
|
+
prompt: 'the "report.pdf" file icon'
|
|
166
|
+
},
|
|
167
|
+
to: {
|
|
168
|
+
prompt: 'the upload drop zone'
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
call
|
|
172
|
+
});
|
|
173
|
+
const ActionLongPressParamSchema = z.object({
|
|
174
|
+
locate: getMidsceneLocationSchema().describe('The element to be long pressed'),
|
|
175
|
+
duration: z.number().optional().describe('Long press duration in milliseconds')
|
|
176
|
+
});
|
|
177
|
+
const defineActionLongPress = (call)=>defineAction({
|
|
178
|
+
name: 'LongPress',
|
|
179
|
+
description: 'Long press the element',
|
|
180
|
+
interfaceAlias: 'aiLongPress',
|
|
181
|
+
paramSchema: ActionLongPressParamSchema,
|
|
182
|
+
sample: {
|
|
183
|
+
locate: {
|
|
184
|
+
prompt: 'the message bubble'
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
call
|
|
188
|
+
});
|
|
189
|
+
const ActionSwipeParamSchema = z.object({
|
|
190
|
+
start: getMidsceneLocationSchema().optional().describe('Starting point of the swipe gesture, if not specified, the center of the page will be used'),
|
|
191
|
+
direction: z["enum"]([
|
|
192
|
+
'up',
|
|
193
|
+
'down',
|
|
194
|
+
'left',
|
|
195
|
+
'right'
|
|
196
|
+
]).optional().describe('The direction to swipe (required when using distance). The direction means the direction of the finger swipe.'),
|
|
197
|
+
distance: z.number().optional().describe('The distance in pixels to swipe (mutually exclusive with end)'),
|
|
198
|
+
end: getMidsceneLocationSchema().optional().describe('Ending point of the swipe gesture (mutually exclusive with distance)'),
|
|
199
|
+
duration: z.number().default(300).describe('Duration of the swipe gesture in milliseconds'),
|
|
200
|
+
repeat: z.number().optional().describe('The number of times to repeat the swipe gesture. 1 for default, 0 for infinite (e.g. endless swipe until the end of the page)')
|
|
201
|
+
});
|
|
202
|
+
function normalizeMobileSwipeParam(param, screenSize) {
|
|
203
|
+
const { width, height } = screenSize;
|
|
204
|
+
const { start, end } = param;
|
|
205
|
+
const startPoint = start ? {
|
|
206
|
+
x: start.center[0],
|
|
207
|
+
y: start.center[1]
|
|
208
|
+
} : {
|
|
209
|
+
x: width / 2,
|
|
210
|
+
y: height / 2
|
|
211
|
+
};
|
|
212
|
+
let endPoint;
|
|
213
|
+
if (end) endPoint = {
|
|
214
|
+
x: end.center[0],
|
|
215
|
+
y: end.center[1]
|
|
216
|
+
};
|
|
217
|
+
else if (param.distance) {
|
|
218
|
+
const direction = param.direction;
|
|
219
|
+
if (!direction) throw new Error('direction is required for swipe gesture');
|
|
220
|
+
endPoint = {
|
|
221
|
+
x: startPoint.x + ('right' === direction ? param.distance : 'left' === direction ? -param.distance : 0),
|
|
222
|
+
y: startPoint.y + ('down' === direction ? param.distance : 'up' === direction ? -param.distance : 0)
|
|
223
|
+
};
|
|
224
|
+
} else throw new Error('Either end or distance must be specified for swipe gesture');
|
|
225
|
+
endPoint.x = Math.max(0, Math.min(endPoint.x, width));
|
|
226
|
+
endPoint.y = Math.max(0, Math.min(endPoint.y, height));
|
|
227
|
+
const duration = param.duration ?? 300;
|
|
228
|
+
let repeatCount = 'number' == typeof param.repeat ? param.repeat : 1;
|
|
229
|
+
if (0 === repeatCount) repeatCount = 10;
|
|
230
|
+
return {
|
|
231
|
+
startPoint,
|
|
232
|
+
endPoint,
|
|
233
|
+
duration,
|
|
234
|
+
repeatCount
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
const defineActionSwipe = (call)=>defineAction({
|
|
238
|
+
name: 'Swipe',
|
|
239
|
+
description: 'Perform a touch gesture for interactions beyond regular scrolling (e.g., flip pages in a carousel, dismiss a notification, swipe-to-delete a list item). For regular content scrolling, use Scroll instead. Use "distance" + "direction" for relative movement, or "end" for precise endpoint.',
|
|
240
|
+
paramSchema: ActionSwipeParamSchema,
|
|
241
|
+
sample: {
|
|
242
|
+
start: {
|
|
243
|
+
prompt: 'center of the notification'
|
|
244
|
+
},
|
|
245
|
+
end: {
|
|
246
|
+
prompt: 'upper edge of the screen'
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
call
|
|
250
|
+
});
|
|
251
|
+
const actionClearInputParamSchema = z.object({
|
|
252
|
+
locate: getMidsceneLocationSchema().describe('The input field to be cleared').optional()
|
|
253
|
+
});
|
|
254
|
+
const defineActionClearInput = (call)=>defineAction({
|
|
255
|
+
name: 'ClearInput',
|
|
256
|
+
description: inputLocateDescription,
|
|
257
|
+
interfaceAlias: 'aiClearInput',
|
|
258
|
+
paramSchema: actionClearInputParamSchema,
|
|
259
|
+
sample: {
|
|
260
|
+
locate: {
|
|
261
|
+
prompt: 'the search input field'
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
call
|
|
265
|
+
});
|
|
266
|
+
const actionCursorMoveParamSchema = z.object({
|
|
267
|
+
direction: z["enum"]([
|
|
268
|
+
'left',
|
|
269
|
+
'right'
|
|
270
|
+
]).describe('The direction to move the cursor'),
|
|
271
|
+
times: z.number().int().min(1).default(1).describe('The number of times to move the cursor in the specified direction')
|
|
272
|
+
});
|
|
273
|
+
const defineActionCursorMove = (call)=>defineAction({
|
|
274
|
+
name: 'CursorMove',
|
|
275
|
+
description: 'Move the text cursor (caret) left or right within an input field or text area. Use this to reposition the cursor without selecting text.',
|
|
276
|
+
paramSchema: actionCursorMoveParamSchema,
|
|
277
|
+
sample: {
|
|
278
|
+
direction: 'left',
|
|
279
|
+
times: 3
|
|
280
|
+
},
|
|
281
|
+
call
|
|
282
|
+
});
|
|
283
|
+
const ActionPinchParamSchema = z.object({
|
|
284
|
+
locate: getMidsceneLocationSchema().optional().describe('The element to pinch on. If not specified, the center of the screen will be used'),
|
|
285
|
+
direction: z["enum"]([
|
|
286
|
+
'in',
|
|
287
|
+
'out'
|
|
288
|
+
]).describe('Pinch direction. "in" = pinch fingers together (zoom out / shrink), "out" = spread fingers apart (zoom in / enlarge).'),
|
|
289
|
+
distance: z.number().positive().optional().describe('How far each finger moves in pixels. Defaults to a quarter of the shorter screen dimension.'),
|
|
290
|
+
duration: z.number().default(500).optional().describe('Duration of the pinch gesture in milliseconds')
|
|
291
|
+
});
|
|
292
|
+
const defineActionPinch = (call)=>defineAction({
|
|
293
|
+
name: 'Pinch',
|
|
294
|
+
description: 'Perform a two-finger pinch gesture. Use direction "in" to pinch fingers together (zoom out), or "out" to spread fingers apart (zoom in). Optionally specify distance for how far each finger moves.',
|
|
295
|
+
interfaceAlias: 'aiPinch',
|
|
296
|
+
paramSchema: ActionPinchParamSchema,
|
|
297
|
+
sample: {
|
|
298
|
+
locate: {
|
|
299
|
+
prompt: 'the map area'
|
|
300
|
+
},
|
|
301
|
+
direction: 'out',
|
|
302
|
+
distance: 200
|
|
303
|
+
},
|
|
304
|
+
call
|
|
305
|
+
});
|
|
306
|
+
function normalizePinchParam(param, screenSize) {
|
|
307
|
+
const { width, height } = screenSize;
|
|
308
|
+
const element = param.locate;
|
|
309
|
+
const centerX = element ? Math.round(element.center[0]) : Math.round(width / 2);
|
|
310
|
+
const centerY = element ? Math.round(element.center[1]) : Math.round(height / 2);
|
|
311
|
+
const duration = param.duration ?? 500;
|
|
312
|
+
const baseDistance = Math.round(Math.min(width, height) / 4);
|
|
313
|
+
const fingerDistance = param.distance ?? baseDistance;
|
|
314
|
+
const startDistance = baseDistance;
|
|
315
|
+
const endDistance = 'out' === param.direction ? baseDistance + fingerDistance : Math.max(10, baseDistance - fingerDistance);
|
|
316
|
+
return {
|
|
317
|
+
centerX,
|
|
318
|
+
centerY,
|
|
319
|
+
startDistance,
|
|
320
|
+
endDistance,
|
|
321
|
+
duration
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
const ActionSleepParamSchema = z.object({
|
|
325
|
+
timeMs: z.number().default(1000).optional().describe('Sleep duration in milliseconds, defaults to 1000ms (1 second)')
|
|
326
|
+
});
|
|
327
|
+
const defineActionSleep = ()=>defineAction({
|
|
328
|
+
name: 'Sleep',
|
|
329
|
+
description: 'Wait for a specified duration before continuing. Defaults to 1 second (1000ms) if not specified.',
|
|
330
|
+
paramSchema: ActionSleepParamSchema,
|
|
331
|
+
sample: {
|
|
332
|
+
timeMs: 2000
|
|
333
|
+
},
|
|
334
|
+
call: async (param)=>{
|
|
335
|
+
const duration = param?.timeMs ?? 1000;
|
|
336
|
+
getDebug('device:common-action')(`Sleeping for ${duration}ms`);
|
|
337
|
+
await new Promise((resolve)=>setTimeout(resolve, duration));
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
export { AbstractInterface, ActionLongPressParamSchema, ActionPinchParamSchema, ActionSleepParamSchema, ActionSwipeParamSchema, actionClearInputParamSchema, actionCursorMoveParamSchema, actionDoubleClickParamSchema, actionDragAndDropParamSchema, actionHoverParamSchema, actionInputParamSchema, actionKeyboardPressParamSchema, actionRightClickParamSchema, actionScrollParamSchema, actionTapParamSchema, defineAction, defineActionClearInput, defineActionCursorMove, defineActionDoubleClick, defineActionDragAndDrop, defineActionHover, defineActionInput, defineActionKeyboardPress, defineActionLongPress, defineActionPinch, defineActionRightClick, defineActionScroll, defineActionSleep, defineActionSwipe, defineActionTap, normalizeMobileSwipeParam, normalizePinchParam };
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import * as __rspack_external_node_fs_5ea92f0c from "node:fs";
|
|
2
|
+
import { antiEscapeScriptTag, escapeScriptTag } from "@godscene/shared/utils";
|
|
3
|
+
var __webpack_modules__ = {
|
|
4
|
+
"node:fs" (module) {
|
|
5
|
+
module.exports = __rspack_external_node_fs_5ea92f0c;
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
var __webpack_module_cache__ = {};
|
|
9
|
+
function __webpack_require__(moduleId) {
|
|
10
|
+
var cachedModule = __webpack_module_cache__[moduleId];
|
|
11
|
+
if (void 0 !== cachedModule) return cachedModule.exports;
|
|
12
|
+
var module = __webpack_module_cache__[moduleId] = {
|
|
13
|
+
exports: {}
|
|
14
|
+
};
|
|
15
|
+
__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
|
16
|
+
return module.exports;
|
|
17
|
+
}
|
|
18
|
+
var external_node_fs_ = __webpack_require__("node:fs");
|
|
19
|
+
const escapeContent = escapeScriptTag;
|
|
20
|
+
const unescapeContent = antiEscapeScriptTag;
|
|
21
|
+
const STREAMING_CHUNK_SIZE = 65536;
|
|
22
|
+
function streamScanTags(filePath, openTag, closeTag, onMatch) {
|
|
23
|
+
const fd = (0, external_node_fs_.openSync)(filePath, 'r');
|
|
24
|
+
const fileSize = (0, external_node_fs_.statSync)(filePath).size;
|
|
25
|
+
const buffer = Buffer.alloc(STREAMING_CHUNK_SIZE);
|
|
26
|
+
let position = 0;
|
|
27
|
+
let leftover = '';
|
|
28
|
+
let capturing = false;
|
|
29
|
+
let currentContent = '';
|
|
30
|
+
try {
|
|
31
|
+
while(position < fileSize){
|
|
32
|
+
const bytesRead = (0, external_node_fs_.readSync)(fd, buffer, 0, STREAMING_CHUNK_SIZE, position);
|
|
33
|
+
const chunk = leftover + buffer.toString('utf-8', 0, bytesRead);
|
|
34
|
+
position += bytesRead;
|
|
35
|
+
let searchStart = 0;
|
|
36
|
+
while(searchStart < chunk.length)if (capturing) {
|
|
37
|
+
const endIdx = chunk.indexOf(closeTag, searchStart);
|
|
38
|
+
if (-1 !== endIdx) {
|
|
39
|
+
currentContent += chunk.slice(searchStart, endIdx);
|
|
40
|
+
const shouldStop = onMatch(currentContent);
|
|
41
|
+
if (shouldStop) return;
|
|
42
|
+
capturing = false;
|
|
43
|
+
currentContent = '';
|
|
44
|
+
searchStart = endIdx + closeTag.length;
|
|
45
|
+
} else {
|
|
46
|
+
currentContent += chunk.slice(searchStart, -closeTag.length);
|
|
47
|
+
leftover = chunk.slice(-closeTag.length);
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
const startIdx = chunk.indexOf(openTag, searchStart);
|
|
52
|
+
if (-1 !== startIdx) {
|
|
53
|
+
capturing = true;
|
|
54
|
+
currentContent = chunk.slice(startIdx + openTag.length);
|
|
55
|
+
const endIdx = currentContent.indexOf(closeTag);
|
|
56
|
+
if (-1 !== endIdx) {
|
|
57
|
+
const shouldStop = onMatch(currentContent.slice(0, endIdx));
|
|
58
|
+
if (shouldStop) return;
|
|
59
|
+
capturing = false;
|
|
60
|
+
currentContent = '';
|
|
61
|
+
searchStart = startIdx + openTag.length + endIdx + closeTag.length;
|
|
62
|
+
} else {
|
|
63
|
+
leftover = currentContent.slice(-closeTag.length);
|
|
64
|
+
currentContent = currentContent.slice(0, -closeTag.length);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
leftover = chunk.slice(-openTag.length);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} finally{
|
|
74
|
+
(0, external_node_fs_.closeSync)(fd);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function extractImageByIdSync(htmlPath, imageId) {
|
|
78
|
+
const targetTag = `<script type="midscene-image" data-id="${imageId}">`;
|
|
79
|
+
const closeTag = "<\/script>";
|
|
80
|
+
let result = null;
|
|
81
|
+
streamScanTags(htmlPath, targetTag, closeTag, (content)=>{
|
|
82
|
+
result = unescapeContent(content);
|
|
83
|
+
return true;
|
|
84
|
+
});
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
function streamImageScriptsToFile(srcFilePath, destFilePath) {
|
|
88
|
+
const { appendFileSync } = __webpack_require__("node:fs");
|
|
89
|
+
const openTag = '<script type="midscene-image"';
|
|
90
|
+
const closeTag = "<\/script>";
|
|
91
|
+
streamScanTags(srcFilePath, openTag, closeTag, (content)=>{
|
|
92
|
+
appendFileSync(destFilePath, `${openTag}${content}${closeTag}\n`);
|
|
93
|
+
return false;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
function extractLastDumpScriptSync(filePath) {
|
|
97
|
+
const openTagPrefix = '<script type="midscene_web_dump"';
|
|
98
|
+
const closeTag = "<\/script>";
|
|
99
|
+
let lastContent = '';
|
|
100
|
+
const fd = (0, external_node_fs_.openSync)(filePath, 'r');
|
|
101
|
+
const fileSize = (0, external_node_fs_.statSync)(filePath).size;
|
|
102
|
+
const buffer = Buffer.alloc(STREAMING_CHUNK_SIZE);
|
|
103
|
+
let position = 0;
|
|
104
|
+
let leftover = '';
|
|
105
|
+
let capturing = false;
|
|
106
|
+
let currentContent = '';
|
|
107
|
+
try {
|
|
108
|
+
while(position < fileSize){
|
|
109
|
+
const bytesRead = (0, external_node_fs_.readSync)(fd, buffer, 0, STREAMING_CHUNK_SIZE, position);
|
|
110
|
+
const chunk = leftover + buffer.toString('utf-8', 0, bytesRead);
|
|
111
|
+
position += bytesRead;
|
|
112
|
+
let searchStart = 0;
|
|
113
|
+
while(searchStart < chunk.length)if (capturing) {
|
|
114
|
+
const endIdx = chunk.indexOf(closeTag, searchStart);
|
|
115
|
+
if (-1 !== endIdx) {
|
|
116
|
+
currentContent += chunk.slice(searchStart, endIdx);
|
|
117
|
+
lastContent = currentContent.trim();
|
|
118
|
+
capturing = false;
|
|
119
|
+
currentContent = '';
|
|
120
|
+
searchStart = endIdx + closeTag.length;
|
|
121
|
+
} else {
|
|
122
|
+
currentContent += chunk.slice(searchStart, -closeTag.length);
|
|
123
|
+
leftover = chunk.slice(-closeTag.length);
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
const startIdx = chunk.indexOf(openTagPrefix, searchStart);
|
|
128
|
+
if (-1 !== startIdx) {
|
|
129
|
+
const tagEndIdx = chunk.indexOf('>', startIdx);
|
|
130
|
+
if (-1 !== tagEndIdx) {
|
|
131
|
+
capturing = true;
|
|
132
|
+
currentContent = chunk.slice(tagEndIdx + 1);
|
|
133
|
+
const endIdx = currentContent.indexOf(closeTag);
|
|
134
|
+
if (-1 !== endIdx) {
|
|
135
|
+
lastContent = currentContent.slice(0, endIdx).trim();
|
|
136
|
+
capturing = false;
|
|
137
|
+
currentContent = '';
|
|
138
|
+
searchStart = tagEndIdx + 1 + endIdx + closeTag.length;
|
|
139
|
+
} else {
|
|
140
|
+
leftover = currentContent.slice(-closeTag.length);
|
|
141
|
+
currentContent = currentContent.slice(0, -closeTag.length);
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
} else {
|
|
145
|
+
leftover = chunk.slice(startIdx);
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
leftover = chunk.slice(-openTagPrefix.length);
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
} finally{
|
|
155
|
+
(0, external_node_fs_.closeSync)(fd);
|
|
156
|
+
}
|
|
157
|
+
return lastContent;
|
|
158
|
+
}
|
|
159
|
+
function extractAllDumpScriptsSync(filePath) {
|
|
160
|
+
const results = [];
|
|
161
|
+
streamDumpScriptsSync(filePath, (dumpScript)=>{
|
|
162
|
+
results.push(dumpScript);
|
|
163
|
+
return false;
|
|
164
|
+
});
|
|
165
|
+
return results;
|
|
166
|
+
}
|
|
167
|
+
function streamDumpScriptsSync(filePath, onMatch) {
|
|
168
|
+
const openTagPrefix = '<script type="midscene_web_dump"';
|
|
169
|
+
const closeTag = "<\/script>";
|
|
170
|
+
const fd = (0, external_node_fs_.openSync)(filePath, 'r');
|
|
171
|
+
const fileSize = (0, external_node_fs_.statSync)(filePath).size;
|
|
172
|
+
const buffer = Buffer.alloc(STREAMING_CHUNK_SIZE);
|
|
173
|
+
let position = 0;
|
|
174
|
+
let leftover = '';
|
|
175
|
+
let capturing = false;
|
|
176
|
+
let currentContent = '';
|
|
177
|
+
let currentOpenTag = '';
|
|
178
|
+
try {
|
|
179
|
+
while(position < fileSize){
|
|
180
|
+
const bytesRead = (0, external_node_fs_.readSync)(fd, buffer, 0, STREAMING_CHUNK_SIZE, position);
|
|
181
|
+
const chunk = leftover + buffer.toString('utf-8', 0, bytesRead);
|
|
182
|
+
position += bytesRead;
|
|
183
|
+
let searchStart = 0;
|
|
184
|
+
while(searchStart < chunk.length)if (capturing) {
|
|
185
|
+
const endIdx = chunk.indexOf(closeTag, searchStart);
|
|
186
|
+
if (-1 !== endIdx) {
|
|
187
|
+
currentContent += chunk.slice(searchStart, endIdx);
|
|
188
|
+
const shouldStop = onMatch({
|
|
189
|
+
openTag: currentOpenTag,
|
|
190
|
+
content: currentContent.trim()
|
|
191
|
+
});
|
|
192
|
+
if (shouldStop) return;
|
|
193
|
+
capturing = false;
|
|
194
|
+
currentContent = '';
|
|
195
|
+
currentOpenTag = '';
|
|
196
|
+
searchStart = endIdx + closeTag.length;
|
|
197
|
+
} else {
|
|
198
|
+
currentContent += chunk.slice(searchStart, -closeTag.length);
|
|
199
|
+
leftover = chunk.slice(-closeTag.length);
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
} else {
|
|
203
|
+
const startIdx = chunk.indexOf(openTagPrefix, searchStart);
|
|
204
|
+
if (-1 !== startIdx) {
|
|
205
|
+
const tagEndIdx = chunk.indexOf('>', startIdx);
|
|
206
|
+
if (-1 !== tagEndIdx) {
|
|
207
|
+
capturing = true;
|
|
208
|
+
currentOpenTag = chunk.slice(startIdx, tagEndIdx + 1);
|
|
209
|
+
currentContent = chunk.slice(tagEndIdx + 1);
|
|
210
|
+
const endIdx = currentContent.indexOf(closeTag);
|
|
211
|
+
if (-1 !== endIdx) {
|
|
212
|
+
const shouldStop = onMatch({
|
|
213
|
+
openTag: currentOpenTag,
|
|
214
|
+
content: currentContent.slice(0, endIdx).trim()
|
|
215
|
+
});
|
|
216
|
+
if (shouldStop) return;
|
|
217
|
+
capturing = false;
|
|
218
|
+
currentContent = '';
|
|
219
|
+
currentOpenTag = '';
|
|
220
|
+
searchStart = tagEndIdx + 1 + endIdx + closeTag.length;
|
|
221
|
+
} else {
|
|
222
|
+
leftover = currentContent.slice(-closeTag.length);
|
|
223
|
+
currentContent = currentContent.slice(0, -closeTag.length);
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
} else {
|
|
227
|
+
leftover = chunk.slice(startIdx);
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
} else {
|
|
231
|
+
leftover = chunk.slice(-openTagPrefix.length);
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
} finally{
|
|
237
|
+
(0, external_node_fs_.closeSync)(fd);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
function parseImageScripts(html) {
|
|
241
|
+
const imageMap = {};
|
|
242
|
+
const regex = /<script type="midscene-image" data-id="([^"]+)">([\s\S]*?)<\/script>/g;
|
|
243
|
+
for (const match of html.matchAll(regex)){
|
|
244
|
+
const [, id, content] = match;
|
|
245
|
+
imageMap[id] = unescapeContent(content);
|
|
246
|
+
}
|
|
247
|
+
return imageMap;
|
|
248
|
+
}
|
|
249
|
+
function parseDumpScript(html) {
|
|
250
|
+
const scriptOpenTag = '<script type="midscene_web_dump"';
|
|
251
|
+
const scriptCloseTag = "<\/script>";
|
|
252
|
+
const lastOpenIndex = html.lastIndexOf(scriptOpenTag);
|
|
253
|
+
if (-1 === lastOpenIndex) throw new Error("No dump script found in HTML");
|
|
254
|
+
const tagEndIndex = html.indexOf('>', lastOpenIndex);
|
|
255
|
+
if (-1 === tagEndIndex) throw new Error("No dump script found in HTML");
|
|
256
|
+
const closeIndex = html.indexOf(scriptCloseTag, tagEndIndex);
|
|
257
|
+
if (-1 === closeIndex) throw new Error("No dump script found in HTML");
|
|
258
|
+
const content = html.substring(tagEndIndex + 1, closeIndex);
|
|
259
|
+
return unescapeContent(content);
|
|
260
|
+
}
|
|
261
|
+
function parseDumpScriptAttributes(html) {
|
|
262
|
+
const regex = /<script type="midscene_web_dump"([^>]*)>/;
|
|
263
|
+
const match = regex.exec(html);
|
|
264
|
+
if (!match) return {};
|
|
265
|
+
const attrString = match[1];
|
|
266
|
+
const attributes = {};
|
|
267
|
+
const attrRegex = /(\w+)="([^"]*)"/g;
|
|
268
|
+
for (const attrMatch of attrString.matchAll(attrRegex)){
|
|
269
|
+
const [, key, value] = attrMatch;
|
|
270
|
+
if ('type' !== key) attributes[key] = decodeURIComponent(value);
|
|
271
|
+
}
|
|
272
|
+
return attributes;
|
|
273
|
+
}
|
|
274
|
+
function generateImageScriptTag(id, data) {
|
|
275
|
+
return '<script type="midscene-image" data-id="' + id + '">' + escapeContent(data) + "<\/script>";
|
|
276
|
+
}
|
|
277
|
+
let _baseUrlFixScript;
|
|
278
|
+
function getBaseUrlFixScript() {
|
|
279
|
+
if (!_baseUrlFixScript) {
|
|
280
|
+
const close = "<\/script>";
|
|
281
|
+
_baseUrlFixScript = '\n<script>(function(){var p=window.location.pathname;if(p.endsWith("/")||/\\.\\w+$/.test(p))return;var b=document.createElement("base");b.href=p+"/";document.head.insertBefore(b,document.head.firstChild)})()' + close + '\n';
|
|
282
|
+
}
|
|
283
|
+
return _baseUrlFixScript;
|
|
284
|
+
}
|
|
285
|
+
function generateDumpScriptTag(json, attributes) {
|
|
286
|
+
let attrString = '';
|
|
287
|
+
if (attributes && Object.keys(attributes).length > 0) attrString = ' ' + Object.entries(attributes).map(([k, v])=>k + '="' + encodeURIComponent(v) + '"').join(' ');
|
|
288
|
+
return '<script type="midscene_web_dump"' + attrString + '>' + escapeContent(json) + "<\/script>";
|
|
289
|
+
}
|
|
290
|
+
export { STREAMING_CHUNK_SIZE, escapeContent, extractAllDumpScriptsSync, extractImageByIdSync, extractLastDumpScriptSync, generateDumpScriptTag, generateImageScriptTag, getBaseUrlFixScript, parseDumpScript, parseDumpScriptAttributes, parseImageScripts, streamDumpScriptsSync, streamImageScriptsToFile, streamScanTags, unescapeContent };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { restoreImageReferences } from "./screenshot-restoration.mjs";
|
|
2
|
+
import { escapeContent, generateDumpScriptTag, generateImageScriptTag, parseDumpScript, parseDumpScriptAttributes, parseImageScripts, unescapeContent } from "./html-utils.mjs";
|
|
3
|
+
export { escapeContent, generateDumpScriptTag, generateImageScriptTag, parseDumpScript, parseDumpScriptAttributes, parseImageScripts, restoreImageReferences, unescapeContent };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { normalizeScreenshotRef } from "./screenshot-store.mjs";
|
|
2
|
+
function restoreImageReferences(data, resolveImage) {
|
|
3
|
+
if ('string' == typeof data) return data;
|
|
4
|
+
if (Array.isArray(data)) return data.map((item)=>restoreImageReferences(item, resolveImage));
|
|
5
|
+
if ('object' == typeof data && null !== data) {
|
|
6
|
+
const refLike = normalizeScreenshotRef(data);
|
|
7
|
+
if (refLike) {
|
|
8
|
+
let resolved = null;
|
|
9
|
+
const lazy = Object.defineProperties({}, {
|
|
10
|
+
base64: {
|
|
11
|
+
get () {
|
|
12
|
+
if (null === resolved) resolved = resolveImage(refLike);
|
|
13
|
+
return resolved;
|
|
14
|
+
},
|
|
15
|
+
enumerable: true
|
|
16
|
+
},
|
|
17
|
+
capturedAt: {
|
|
18
|
+
value: refLike.capturedAt,
|
|
19
|
+
enumerable: true
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
return lazy;
|
|
23
|
+
}
|
|
24
|
+
const result = {};
|
|
25
|
+
for (const [key, value] of Object.entries(data))result[key] = restoreImageReferences(value, resolveImage);
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
return data;
|
|
29
|
+
}
|
|
30
|
+
export { restoreImageReferences };
|