@midscene/core 0.27.3 → 0.27.4-beta-20250826061259.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/agent/agent.mjs.map +1 -1
- package/dist/es/agent/common.mjs +0 -0
- package/dist/es/agent/index.mjs +3 -3
- package/dist/es/agent/tasks.mjs +0 -13
- package/dist/es/agent/tasks.mjs.map +1 -1
- package/dist/es/agent/ui-utils.mjs +1 -32
- package/dist/es/agent/ui-utils.mjs.map +1 -1
- package/dist/es/agent/utils.mjs +3 -149
- package/dist/es/agent/utils.mjs.map +1 -1
- package/dist/es/ai-model/service-caller/index.mjs +1 -1
- package/dist/es/ai-model/service-caller/index.mjs.map +1 -1
- package/dist/es/device/index.mjs +91 -17
- package/dist/es/device/index.mjs.map +1 -1
- package/dist/es/types.mjs.map +1 -1
- package/dist/es/utils.mjs +2 -2
- package/dist/lib/agent/agent.js.map +1 -1
- package/dist/lib/agent/common.js +5 -0
- package/dist/lib/agent/index.js +2 -8
- package/dist/lib/agent/tasks.js +0 -13
- package/dist/lib/agent/tasks.js.map +1 -1
- package/dist/lib/agent/ui-utils.js +0 -34
- package/dist/lib/agent/ui-utils.js.map +1 -1
- package/dist/lib/agent/utils.js +1 -150
- package/dist/lib/agent/utils.js.map +1 -1
- package/dist/lib/ai-model/service-caller/index.js +1 -1
- package/dist/lib/ai-model/service-caller/index.js.map +1 -1
- package/dist/lib/device/index.js +139 -20
- package/dist/lib/device/index.js.map +1 -1
- package/dist/lib/types.js.map +1 -1
- package/dist/lib/utils.js +2 -2
- package/dist/types/agent/agent.d.ts +2 -2
- package/dist/types/agent/common.d.ts +0 -0
- package/dist/types/agent/index.d.ts +1 -2
- package/dist/types/agent/tasks.d.ts +3 -3
- package/dist/types/agent/ui-utils.d.ts +0 -4
- package/dist/types/agent/utils.d.ts +3 -4
- package/dist/types/device/index.d.ts +2240 -46
- package/dist/types/types.d.ts +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent/ui-utils.mjs","sources":["webpack://@midscene/core/./src/agent/ui-utils.ts"],"sourcesContent":["import type {\n AndroidPullParam,\n DetailedLocateParam,\n ExecutionTask,\n ExecutionTaskAction,\n ExecutionTaskInsightAssertion,\n ExecutionTaskInsightLocate,\n ExecutionTaskInsightQuery,\n ExecutionTaskPlanning,\n ScrollParam,\n} from '@/index';\n\nexport function typeStr(task: ExecutionTask) {\n return task.subType && task.subType !== 'Plan'\n ? `${task.type} / ${task.subType || ''}`\n : task.type;\n}\n\nexport function
|
|
1
|
+
{"version":3,"file":"agent/ui-utils.mjs","sources":["webpack://@midscene/core/./src/agent/ui-utils.ts"],"sourcesContent":["import type {\n AndroidPullParam,\n DetailedLocateParam,\n ExecutionTask,\n ExecutionTaskAction,\n ExecutionTaskInsightAssertion,\n ExecutionTaskInsightLocate,\n ExecutionTaskInsightQuery,\n ExecutionTaskPlanning,\n ScrollParam,\n} from '@/index';\n\nexport function typeStr(task: ExecutionTask) {\n return task.subType && task.subType !== 'Plan'\n ? `${task.type} / ${task.subType || ''}`\n : task.type;\n}\n\nexport function locateParamStr(locate?: DetailedLocateParam) {\n if (!locate) {\n return '';\n }\n\n if (typeof locate === 'string') {\n return locate;\n }\n\n if (typeof locate.prompt === 'string') {\n return locate.prompt;\n }\n\n if (typeof locate.prompt === 'object' && locate.prompt.prompt) {\n return locate.prompt.prompt;\n }\n\n return '';\n}\n\nexport function scrollParamStr(scrollParam?: ScrollParam) {\n if (!scrollParam) {\n return '';\n }\n return `${scrollParam.direction || 'down'}, ${scrollParam.scrollType || 'once'}, ${scrollParam.distance || 'distance-not-set'}`;\n}\n\nexport function pullParamStr(pullParam?: AndroidPullParam) {\n if (!pullParam) {\n return '';\n }\n const parts: string[] = [];\n parts.push(`direction: ${pullParam.direction || 'down'}`);\n if (pullParam.distance) {\n parts.push(`distance: ${pullParam.distance}`);\n }\n if (pullParam.duration) {\n parts.push(`duration: ${pullParam.duration}ms`);\n }\n return parts.join(', ');\n}\n\nexport function taskTitleStr(\n type:\n | 'Tap'\n | 'Hover'\n | 'Input'\n | 'RightClick'\n | 'KeyboardPress'\n | 'Scroll'\n | 'Action'\n | 'Query'\n | 'Assert'\n | 'WaitFor'\n | 'Locate'\n | 'Boolean'\n | 'Number'\n | 'String',\n prompt: string,\n) {\n if (prompt) {\n return `${type} - ${prompt}`;\n }\n return type;\n}\n\nexport function paramStr(task: ExecutionTask) {\n let value: string | undefined | object;\n if (task.type === 'Planning') {\n value = (task as ExecutionTaskPlanning)?.param?.userInstruction;\n }\n\n if (task.type === 'Insight') {\n value =\n (task as ExecutionTaskInsightLocate)?.param?.prompt ||\n (task as ExecutionTaskInsightLocate)?.param?.id ||\n (task as ExecutionTaskInsightQuery)?.param?.dataDemand ||\n (task as ExecutionTaskInsightAssertion)?.param?.assertion;\n }\n\n if (task.type === 'Action') {\n const locate = (task as ExecutionTaskAction)?.locate;\n const locateStr = locate ? locateParamStr(locate) : '';\n\n value = task.thought || '';\n if (typeof (task as ExecutionTaskAction)?.param?.timeMs === 'number') {\n value = `${(task as ExecutionTaskAction)?.param?.timeMs}ms`;\n } else if (\n typeof (task as ExecutionTaskAction)?.param?.scrollType === 'string'\n ) {\n value = scrollParamStr((task as ExecutionTaskAction)?.param);\n } else if (\n typeof (task as ExecutionTaskAction)?.param?.direction === 'string' &&\n (task as ExecutionTaskAction)?.subType === 'AndroidPull'\n ) {\n value = pullParamStr((task as ExecutionTaskAction)?.param);\n } else if (\n typeof (task as ExecutionTaskAction)?.param?.value !== 'undefined'\n ) {\n value = (task as ExecutionTaskAction)?.param?.value;\n }\n\n if (locateStr) {\n if (value) {\n value = `${locateStr} - ${value}`;\n } else {\n value = locateStr;\n }\n }\n }\n\n if (typeof value === 'undefined') return '';\n return typeof value === 'string'\n ? value\n : JSON.stringify(value, undefined, 2);\n}\n"],"names":["typeStr","task","locateParamStr","locate","scrollParamStr","scrollParam","pullParamStr","pullParam","parts","taskTitleStr","type","prompt","paramStr","value","_task_param","_task_param1","_task_param2","_task_param3","_task_param4","_task_param5","_task_param6","_task_param7","_task_param8","locateStr","_task_param9","_task_param10","JSON","undefined"],"mappings":"AAYO,SAASA,QAAQC,IAAmB;IACzC,OAAOA,KAAK,OAAO,IAAIA,AAAiB,WAAjBA,KAAK,OAAO,GAC/B,GAAGA,KAAK,IAAI,CAAC,GAAG,EAAEA,KAAK,OAAO,IAAI,IAAI,GACtCA,KAAK,IAAI;AACf;AAEO,SAASC,eAAeC,MAA4B;IACzD,IAAI,CAACA,QACH,OAAO;IAGT,IAAI,AAAkB,YAAlB,OAAOA,QACT,OAAOA;IAGT,IAAI,AAAyB,YAAzB,OAAOA,OAAO,MAAM,EACtB,OAAOA,OAAO,MAAM;IAGtB,IAAI,AAAyB,YAAzB,OAAOA,OAAO,MAAM,IAAiBA,OAAO,MAAM,CAAC,MAAM,EAC3D,OAAOA,OAAO,MAAM,CAAC,MAAM;IAG7B,OAAO;AACT;AAEO,SAASC,eAAeC,WAAyB;IACtD,IAAI,CAACA,aACH,OAAO;IAET,OAAO,GAAGA,YAAY,SAAS,IAAI,OAAO,EAAE,EAAEA,YAAY,UAAU,IAAI,OAAO,EAAE,EAAEA,YAAY,QAAQ,IAAI,oBAAoB;AACjI;AAEO,SAASC,aAAaC,SAA4B;IACvD,IAAI,CAACA,WACH,OAAO;IAET,MAAMC,QAAkB,EAAE;IAC1BA,MAAM,IAAI,CAAC,CAAC,WAAW,EAAED,UAAU,SAAS,IAAI,QAAQ;IACxD,IAAIA,UAAU,QAAQ,EACpBC,MAAM,IAAI,CAAC,CAAC,UAAU,EAAED,UAAU,QAAQ,EAAE;IAE9C,IAAIA,UAAU,QAAQ,EACpBC,MAAM,IAAI,CAAC,CAAC,UAAU,EAAED,UAAU,QAAQ,CAAC,EAAE,CAAC;IAEhD,OAAOC,MAAM,IAAI,CAAC;AACpB;AAEO,SAASC,aACdC,IAcY,EACZC,MAAc;IAEd,IAAIA,QACF,OAAO,GAAGD,KAAK,GAAG,EAAEC,QAAQ;IAE9B,OAAOD;AACT;AAEO,SAASE,SAASX,IAAmB;IAC1C,IAAIY;IACJ,IAAIZ,AAAc,eAAdA,KAAK,IAAI,EAAiB;YACpBa;QAARD,QAASZ,QAAAA,OAAAA,KAAAA,IAAAA,QAADa,CAAAA,cAACb,KAAgC,KAAK,AAAD,IAArCa,KAAAA,IAAAA,YAAwC,eAAe;IACjE;IAEA,IAAIb,AAAc,cAAdA,KAAK,IAAI,EAAgB;YAEzBc,cACAC,cACAC,cACAC;QAJFL,QACEE,AAACd,CAAAA,QAAAA,OAAAA,KAAAA,IAAAA,QAADc,CAAAA,eAACd,KAAqC,KAAK,AAAD,IAA1Cc,KAAAA,IAAAA,aAA6C,MAAM,AAAD,KACjDd,CAAAA,QAAAA,OAAAA,KAAAA,IAAAA,QAADe,CAAAA,eAACf,KAAqC,KAAK,AAAD,IAA1Ce,KAAAA,IAAAA,aAA6C,EAAE,AAAD,KAC7Cf,CAAAA,QAAAA,OAAAA,KAAAA,IAAAA,QAADgB,CAAAA,eAAChB,KAAoC,KAAK,AAAD,IAAzCgB,KAAAA,IAAAA,aAA4C,UAAU,AAAD,KACpDhB,CAAAA,QAAAA,OAAAA,KAAAA,IAAAA,QAADiB,CAAAA,eAACjB,KAAwC,KAAK,AAAD,IAA7CiB,KAAAA,IAAAA,aAAgD,SAAS,AAAD;IAC5D;IAEA,IAAIjB,AAAc,aAAdA,KAAK,IAAI,EAAe;YAKfkB,cAGFC,cAIAC,cAKAC;QAhBT,MAAMnB,SAAUF,QAAAA,OAAAA,KAAAA,IAAAA,KAA8B,MAAM;QACpD,MAAMsB,YAAYpB,SAASD,eAAeC,UAAU;QAEpDU,QAAQZ,KAAK,OAAO,IAAI;QACxB,IAAI,AAAwD,YAAxD,OAAQA,CAAAA,QAAAA,OAAAA,KAAAA,IAAAA,QAADkB,CAAAA,eAAClB,KAA8B,KAAK,AAAD,IAAnCkB,KAAAA,IAAAA,aAAsC,MAAM,AAAD,GAAgB;gBACzDK;YAAXX,QAAQ,GAAIZ,QAAAA,OAAAA,KAAAA,IAAAA,QAADuB,CAAAA,eAACvB,KAA8B,KAAK,AAAD,IAAnCuB,KAAAA,IAAAA,aAAsC,MAAM,CAAC,EAAE,CAAC;QAC7D,OAAO,IACL,AAA4D,YAA5D,OAAQvB,CAAAA,QAAAA,OAAAA,KAAAA,IAAAA,QAADmB,CAAAA,eAACnB,KAA8B,KAAK,AAAD,IAAnCmB,KAAAA,IAAAA,aAAsC,UAAU,AAAD,GAEtDP,QAAQT,eAAgBH,QAAAA,OAAAA,KAAAA,IAAAA,KAA8B,KAAK;aACtD,IACL,AAA2D,YAA3D,OAAQA,CAAAA,QAAAA,OAAAA,KAAAA,IAAAA,QAADoB,CAAAA,eAACpB,KAA8B,KAAK,AAAD,IAAnCoB,KAAAA,IAAAA,aAAsC,SAAS,AAAD,KACrD,AAACpB,CAAAA,QAAAA,OAAAA,KAAAA,IAAAA,KAA8B,OAAO,AAAD,MAAM,eAE3CY,QAAQP,aAAcL,QAAAA,OAAAA,KAAAA,IAAAA,KAA8B,KAAK;aACpD,IACL,AAAuD,WAA/CA,CAAAA,QAAAA,OAAAA,KAAAA,IAAAA,QAADqB,CAAAA,eAACrB,KAA8B,KAAK,AAAD,IAAnCqB,KAAAA,IAAAA,aAAsC,KAAK,AAAD,GACjD;gBACQG;YAARZ,QAASZ,QAAAA,OAAAA,KAAAA,IAAAA,QAADwB,CAAAA,gBAACxB,KAA8B,KAAK,AAAD,IAAnCwB,KAAAA,IAAAA,cAAsC,KAAK;QACrD;QAEA,IAAIF,WAEAV,QADEA,QACM,GAAGU,UAAU,GAAG,EAAEV,OAAO,GAEzBU;IAGd;IAEA,IAAI,AAAiB,WAAVV,OAAuB,OAAO;IACzC,OAAO,AAAiB,YAAjB,OAAOA,QACVA,QACAa,KAAK,SAAS,CAACb,OAAOc,QAAW;AACvC"}
|
package/dist/es/agent/utils.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { elementByPositionWithElementInfo } from "../ai-model/index.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { sleep, uploadTestInfoToServer } from "../utils.mjs";
|
|
2
|
+
import { uploadTestInfoToServer } from "../utils.mjs";
|
|
4
3
|
import { MIDSCENE_REPORT_TAG_NAME, globalConfigManager } from "@midscene/shared/env";
|
|
5
4
|
import { generateElementByPosition, getNodeFromCacheList } from "@midscene/shared/extractor";
|
|
6
5
|
import { resizeImgBase64 } from "@midscene/shared/img";
|
|
@@ -8,9 +7,7 @@ import { getDebug } from "@midscene/shared/logger";
|
|
|
8
7
|
import { assert, logMsg, uuid } from "@midscene/shared/utils";
|
|
9
8
|
import dayjs from "dayjs";
|
|
10
9
|
import { debug } from "./task-cache.mjs";
|
|
11
|
-
import { getKeyCommands } from "./ui-utils.mjs";
|
|
12
10
|
const debugProfile = getDebug('web:tool:profile');
|
|
13
|
-
getDebug('web:tool:utils');
|
|
14
11
|
async function commonContextParser(page) {
|
|
15
12
|
assert(page, 'page is required');
|
|
16
13
|
debugProfile('Getting page URL');
|
|
@@ -141,7 +138,7 @@ function trimContextByViewport(execution) {
|
|
|
141
138
|
}) : execution.tasks
|
|
142
139
|
};
|
|
143
140
|
}
|
|
144
|
-
const getMidsceneVersion = ()=>"0.27.
|
|
141
|
+
const getMidsceneVersion = ()=>"0.27.4-beta-20250826061259.0";
|
|
145
142
|
const parsePrompt = (prompt)=>{
|
|
146
143
|
if ('string' == typeof prompt) return {
|
|
147
144
|
textPrompt: prompt,
|
|
@@ -155,149 +152,6 @@ const parsePrompt = (prompt)=>{
|
|
|
155
152
|
} : void 0
|
|
156
153
|
};
|
|
157
154
|
};
|
|
158
|
-
|
|
159
|
-
{
|
|
160
|
-
name: 'Tap',
|
|
161
|
-
description: 'Tap the element',
|
|
162
|
-
interfaceAlias: 'aiTap',
|
|
163
|
-
paramSchema: z.object({
|
|
164
|
-
locate: getMidsceneLocationSchema().describe('The element to be tapped')
|
|
165
|
-
}),
|
|
166
|
-
call: async (param)=>{
|
|
167
|
-
const element = param.locate;
|
|
168
|
-
assert(element, 'Element not found, cannot tap');
|
|
169
|
-
await page.mouse.click(element.center[0], element.center[1], {
|
|
170
|
-
button: 'left'
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
},
|
|
174
|
-
{
|
|
175
|
-
name: 'RightClick',
|
|
176
|
-
description: 'Right click the element',
|
|
177
|
-
interfaceAlias: 'aiRightClick',
|
|
178
|
-
paramSchema: z.object({
|
|
179
|
-
locate: getMidsceneLocationSchema().describe('The element to be right clicked')
|
|
180
|
-
}),
|
|
181
|
-
call: async (param)=>{
|
|
182
|
-
const element = param.locate;
|
|
183
|
-
assert(element, 'Element not found, cannot right click');
|
|
184
|
-
await page.mouse.click(element.center[0], element.center[1], {
|
|
185
|
-
button: 'right'
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
},
|
|
189
|
-
{
|
|
190
|
-
name: 'Hover',
|
|
191
|
-
description: 'Move the mouse to the element',
|
|
192
|
-
interfaceAlias: 'aiHover',
|
|
193
|
-
paramSchema: z.object({
|
|
194
|
-
locate: getMidsceneLocationSchema().describe('The element to be hovered')
|
|
195
|
-
}),
|
|
196
|
-
call: async (param)=>{
|
|
197
|
-
const element = param.locate;
|
|
198
|
-
assert(element, 'Element not found, cannot hover');
|
|
199
|
-
await page.mouse.move(element.center[0], element.center[1]);
|
|
200
|
-
}
|
|
201
|
-
},
|
|
202
|
-
{
|
|
203
|
-
name: 'Input',
|
|
204
|
-
description: 'Replace the input field with a new value. `value` is the final that should be filled in the input box. No matter what modifications are required, just provide the final value to replace the existing input value. Giving a blank string means clear the input field.',
|
|
205
|
-
interfaceAlias: 'aiInput',
|
|
206
|
-
paramSchema: z.object({
|
|
207
|
-
value: z.string().describe('The final value that should be filled in the input box'),
|
|
208
|
-
locate: getMidsceneLocationSchema().describe('The input field to be filled').optional()
|
|
209
|
-
}),
|
|
210
|
-
call: async (param)=>{
|
|
211
|
-
const element = param.locate;
|
|
212
|
-
if (element) {
|
|
213
|
-
await page.clearInput(element);
|
|
214
|
-
if (!param || !param.value) return;
|
|
215
|
-
}
|
|
216
|
-
await page.keyboard.type(param.value);
|
|
217
|
-
}
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
name: 'KeyboardPress',
|
|
221
|
-
description: 'Press a function key, like "Enter", "Tab", "Escape". Do not use this to type text.',
|
|
222
|
-
interfaceAlias: 'aiKeyboardPress',
|
|
223
|
-
paramSchema: z.object({
|
|
224
|
-
locate: getMidsceneLocationSchema().describe('The element to be clicked before pressing the key').optional(),
|
|
225
|
-
keyName: z.string().describe('The key to be pressed')
|
|
226
|
-
}),
|
|
227
|
-
call: async (param)=>{
|
|
228
|
-
const element = param.locate;
|
|
229
|
-
if (element) await page.mouse.click(element.center[0], element.center[1], {
|
|
230
|
-
button: 'left'
|
|
231
|
-
});
|
|
232
|
-
const keys = getKeyCommands(param.keyName);
|
|
233
|
-
await page.keyboard.press(keys);
|
|
234
|
-
}
|
|
235
|
-
},
|
|
236
|
-
{
|
|
237
|
-
name: 'Scroll',
|
|
238
|
-
description: 'Scroll the page or an element. The direction to scroll, the scroll type, and the distance to scroll. The distance is the number of pixels to scroll. If not specified, use `down` direction, `once` scroll type, and `null` distance.',
|
|
239
|
-
interfaceAlias: 'aiScroll',
|
|
240
|
-
paramSchema: z.object({
|
|
241
|
-
direction: z["enum"]([
|
|
242
|
-
'down',
|
|
243
|
-
'up',
|
|
244
|
-
'right',
|
|
245
|
-
'left'
|
|
246
|
-
]).default('down').describe('The direction to scroll'),
|
|
247
|
-
scrollType: z["enum"]([
|
|
248
|
-
'once',
|
|
249
|
-
'untilBottom',
|
|
250
|
-
'untilTop',
|
|
251
|
-
'untilRight',
|
|
252
|
-
'untilLeft'
|
|
253
|
-
]).default('once').describe('The scroll type'),
|
|
254
|
-
distance: z.number().nullable().optional().describe('The distance in pixels to scroll'),
|
|
255
|
-
locate: getMidsceneLocationSchema().optional().describe('The element to be scrolled')
|
|
256
|
-
}),
|
|
257
|
-
call: async (param)=>{
|
|
258
|
-
const element = param.locate;
|
|
259
|
-
const startingPoint = element ? {
|
|
260
|
-
left: element.center[0],
|
|
261
|
-
top: element.center[1]
|
|
262
|
-
} : void 0;
|
|
263
|
-
const scrollToEventName = null == param ? void 0 : param.scrollType;
|
|
264
|
-
if ('untilTop' === scrollToEventName) await page.scrollUntilTop(startingPoint);
|
|
265
|
-
else if ('untilBottom' === scrollToEventName) await page.scrollUntilBottom(startingPoint);
|
|
266
|
-
else if ('untilRight' === scrollToEventName) await page.scrollUntilRight(startingPoint);
|
|
267
|
-
else if ('untilLeft' === scrollToEventName) await page.scrollUntilLeft(startingPoint);
|
|
268
|
-
else if ('once' !== scrollToEventName && scrollToEventName) throw new Error(`Unknown scroll event type: ${scrollToEventName}, param: ${JSON.stringify(param)}`);
|
|
269
|
-
else {
|
|
270
|
-
if ((null == param ? void 0 : param.direction) !== 'down' && param && param.direction) if ('up' === param.direction) await page.scrollUp(param.distance || void 0, startingPoint);
|
|
271
|
-
else if ('left' === param.direction) await page.scrollLeft(param.distance || void 0, startingPoint);
|
|
272
|
-
else if ('right' === param.direction) await page.scrollRight(param.distance || void 0, startingPoint);
|
|
273
|
-
else throw new Error(`Unknown scroll direction: ${param.direction}`);
|
|
274
|
-
else await page.scrollDown((null == param ? void 0 : param.distance) || void 0, startingPoint);
|
|
275
|
-
await sleep(500);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
},
|
|
279
|
-
{
|
|
280
|
-
name: 'DragAndDrop',
|
|
281
|
-
description: 'Drag and drop the element',
|
|
282
|
-
paramSchema: z.object({
|
|
283
|
-
from: getMidsceneLocationSchema().describe('The position to be dragged'),
|
|
284
|
-
to: getMidsceneLocationSchema().describe('The position to be dropped')
|
|
285
|
-
}),
|
|
286
|
-
call: async (param)=>{
|
|
287
|
-
const from = param.from;
|
|
288
|
-
const to = param.to;
|
|
289
|
-
assert(from, 'missing "from" param for drag and drop');
|
|
290
|
-
assert(to, 'missing "to" param for drag and drop');
|
|
291
|
-
await page.mouse.drag({
|
|
292
|
-
x: from.center[0],
|
|
293
|
-
y: from.center[1]
|
|
294
|
-
}, {
|
|
295
|
-
x: to.center[0],
|
|
296
|
-
y: to.center[1]
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
];
|
|
301
|
-
export { commonContextParser, commonWebActionsForWebPage, generateCacheId, getCurrentExecutionFile, getMidsceneVersion, getReportFileName, matchElementFromCache, matchElementFromPlan, parsePrompt, printReportMsg, trimContextByViewport };
|
|
155
|
+
export { commonContextParser, generateCacheId, getCurrentExecutionFile, getMidsceneVersion, getReportFileName, matchElementFromCache, matchElementFromPlan, parsePrompt, printReportMsg, trimContextByViewport };
|
|
302
156
|
|
|
303
157
|
//# sourceMappingURL=utils.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent/utils.mjs","sources":["webpack://@midscene/core/./src/agent/utils.ts"],"sourcesContent":["import { elementByPositionWithElementInfo } from '@/ai-model';\nimport type { AbstractPage } from '@/device';\nimport type {\n BaseElement,\n DeviceAction,\n ElementTreeNode,\n ExecutionDump,\n ExecutionTask,\n ExecutorContext,\n MidsceneLocationResultType,\n PlanningLocateParam,\n TMultimodalPrompt,\n TUserPrompt,\n UIContext,\n} from '@/index';\nimport { getMidsceneLocationSchema, z } from '@/index';\nimport { sleep, uploadTestInfoToServer } from '@/utils';\nimport {\n MIDSCENE_REPORT_TAG_NAME,\n globalConfigManager,\n} from '@midscene/shared/env';\nimport type { ElementInfo } from '@midscene/shared/extractor';\nimport {\n generateElementByPosition,\n getNodeFromCacheList,\n} from '@midscene/shared/extractor';\nimport { resizeImgBase64 } from '@midscene/shared/img';\nimport { getDebug } from '@midscene/shared/logger';\nimport { _keyDefinitions } from '@midscene/shared/us-keyboard-layout';\nimport { assert, logMsg, uuid } from '@midscene/shared/utils';\nimport dayjs from 'dayjs';\nimport { debug as cacheDebug } from './task-cache';\nimport type { PageTaskExecutor } from './tasks';\nimport { getKeyCommands } from './ui-utils';\n\nconst debugProfile = getDebug('web:tool:profile');\nconst debugUtils = getDebug('web:tool:utils');\n\nexport async function commonContextParser(\n page: AbstractPage,\n): Promise<UIContext> {\n assert(page, 'page is required');\n\n debugProfile('Getting page URL');\n const url = await page.url();\n debugProfile('URL end');\n\n debugProfile('Uploading test info to server');\n uploadTestInfoToServer({ testUrl: url });\n debugProfile('UploadTestInfoToServer end');\n\n let screenshotBase64 = await page.screenshotBase64();\n assert(screenshotBase64!, 'screenshotBase64 is required');\n\n const size = await page.size();\n debugProfile(`size: ${size.width}x${size.height} dpr: ${size.dpr}`);\n\n if (size.dpr && size.dpr > 1) {\n debugProfile('Resizing screenshot for high DPR display');\n screenshotBase64 = await resizeImgBase64(screenshotBase64, {\n width: size.width,\n height: size.height,\n });\n debugProfile('ResizeImgBase64 end');\n }\n\n return {\n tree: {\n node: null,\n children: [],\n },\n size,\n screenshotBase64: screenshotBase64!,\n url,\n };\n}\n\nexport function getReportFileName(tag = 'web') {\n const reportTagName = globalConfigManager.getEnvConfigValue(\n MIDSCENE_REPORT_TAG_NAME,\n );\n const dateTimeInFileName = dayjs().format('YYYY-MM-DD_HH-mm-ss');\n // ensure uniqueness at the same time\n const uniqueId = uuid().substring(0, 8);\n return `${reportTagName || tag}-${dateTimeInFileName}-${uniqueId}`;\n}\n\nexport function printReportMsg(filepath: string) {\n logMsg(`Midscene - report file updated: ${filepath}`);\n}\n\n/**\n * Get the current execution file name\n * @returns The name of the current execution file\n */\nexport function getCurrentExecutionFile(trace?: string): string | false {\n const error = new Error();\n const stackTrace = trace || error.stack;\n const pkgDir = process.cwd() || '';\n if (stackTrace) {\n const stackLines = stackTrace.split('\\n');\n for (const line of stackLines) {\n if (\n line.includes('.spec.') ||\n line.includes('.test.') ||\n line.includes('.ts') ||\n line.includes('.js')\n ) {\n const match = line.match(/(?:at\\s+)?(.*?\\.(?:spec|test)\\.[jt]s)/);\n if (match?.[1]) {\n const targetFileName = match[1]\n .replace(pkgDir, '')\n .trim()\n .replace('at ', '');\n return targetFileName;\n }\n }\n }\n }\n return false;\n}\n\nconst testFileIndex = new Map<string, number>();\n\nexport function generateCacheId(fileName?: string): string {\n let taskFile = fileName || getCurrentExecutionFile();\n if (!taskFile) {\n taskFile = uuid();\n console.warn(\n 'Midscene - using random UUID for cache id. Cache may be invalid.',\n );\n }\n\n if (testFileIndex.has(taskFile)) {\n const currentIndex = testFileIndex.get(taskFile);\n if (currentIndex !== undefined) {\n testFileIndex.set(taskFile, currentIndex + 1);\n }\n } else {\n testFileIndex.set(taskFile, 1);\n }\n return `${taskFile}-${testFileIndex.get(taskFile)}`;\n}\n\nexport function matchElementFromPlan(\n planLocateParam: PlanningLocateParam,\n tree: ElementTreeNode<BaseElement>,\n) {\n if (!planLocateParam) {\n return undefined;\n }\n if (planLocateParam.id) {\n return getNodeFromCacheList(planLocateParam.id);\n }\n\n if (planLocateParam.bbox) {\n const centerPosition = {\n x: Math.floor((planLocateParam.bbox[0] + planLocateParam.bbox[2]) / 2),\n y: Math.floor((planLocateParam.bbox[1] + planLocateParam.bbox[3]) / 2),\n };\n let element = elementByPositionWithElementInfo(tree, centerPosition);\n\n if (!element) {\n element = generateElementByPosition(centerPosition) as BaseElement;\n }\n\n return element;\n }\n\n return undefined;\n}\n\nexport async function matchElementFromCache(\n taskExecutor: PageTaskExecutor,\n xpaths: string[] | undefined,\n cachePrompt: TUserPrompt,\n cacheable: boolean | undefined,\n) {\n try {\n if (\n xpaths?.length &&\n taskExecutor.taskCache?.isCacheResultUsed &&\n cacheable !== false &&\n (taskExecutor.page as any).getElementInfoByXpath\n ) {\n // hit cache, use new id\n for (let i = 0; i < xpaths.length; i++) {\n const element = await (taskExecutor.page as any).getElementInfoByXpath(\n xpaths[i],\n );\n\n if (element?.id) {\n cacheDebug('cache hit, prompt: %s', cachePrompt);\n cacheDebug(\n 'found a new element with same xpath, xpath: %s, id: %s',\n xpaths[i],\n element?.id,\n );\n return element;\n }\n }\n }\n } catch (error) {\n cacheDebug('get element info by xpath error: ', error);\n }\n}\n\nexport function trimContextByViewport(execution: ExecutionDump) {\n function filterVisibleTree(\n node: ElementTreeNode<BaseElement>,\n ): ElementTreeNode<BaseElement> | null {\n if (!node) return null;\n\n // recursively process all children\n const filteredChildren = Array.isArray(node.children)\n ? (node.children\n .map(filterVisibleTree)\n .filter((child) => child !== null) as ElementTreeNode<BaseElement>[])\n : [];\n\n // if the current node is visible, keep it and the filtered children\n if (node.node && node.node.isVisible === true) {\n return {\n ...node,\n children: filteredChildren,\n };\n }\n\n // if the current node is invisible, but has visible children, create an empty node to include these children\n if (filteredChildren.length > 0) {\n return {\n node: null,\n children: filteredChildren,\n };\n }\n\n // if the current node is invisible and has no visible children, return null\n return null;\n }\n\n return {\n ...execution,\n tasks: Array.isArray(execution.tasks)\n ? execution.tasks.map((task: ExecutionTask) => {\n const newTask = { ...task };\n if (task.pageContext?.tree) {\n newTask.pageContext = {\n ...task.pageContext,\n tree: filterVisibleTree(task.pageContext.tree) || {\n node: null,\n children: [],\n },\n };\n }\n return newTask;\n })\n : execution.tasks,\n };\n}\n\ndeclare const __VERSION__: string | undefined;\n\nexport const getMidsceneVersion = (): string => {\n if (typeof __VERSION__ !== 'undefined') {\n return __VERSION__;\n } else if (\n process.env.__VERSION__ &&\n process.env.__VERSION__ !== 'undefined'\n ) {\n return process.env.__VERSION__;\n }\n throw new Error('__VERSION__ inject failed during build');\n};\n\nexport const parsePrompt = (\n prompt: TUserPrompt,\n): {\n textPrompt: string;\n multimodalPrompt?: TMultimodalPrompt;\n} => {\n if (typeof prompt === 'string') {\n return {\n textPrompt: prompt,\n multimodalPrompt: undefined,\n };\n }\n return {\n textPrompt: prompt.prompt,\n multimodalPrompt: prompt.images\n ? {\n images: prompt.images,\n convertHttpImage2Base64: !!prompt.convertHttpImage2Base64,\n }\n : undefined,\n };\n};\n\nexport const commonWebActionsForWebPage = <T extends AbstractPage>(\n page: T,\n): DeviceAction<any>[] => [\n {\n name: 'Tap',\n description: 'Tap the element',\n interfaceAlias: 'aiTap',\n paramSchema: z.object({\n locate: getMidsceneLocationSchema().describe('The element to be tapped'),\n }),\n call: async (param) => {\n const element = param.locate;\n assert(element, 'Element not found, cannot tap');\n await page.mouse.click(element.center[0], element.center[1], {\n button: 'left',\n });\n },\n } as DeviceAction<{\n locate: MidsceneLocationResultType;\n }>,\n {\n name: 'RightClick',\n description: 'Right click the element',\n interfaceAlias: 'aiRightClick',\n paramSchema: z.object({\n locate: getMidsceneLocationSchema().describe(\n 'The element to be right clicked',\n ),\n }),\n call: async (param) => {\n const element = param.locate;\n assert(element, 'Element not found, cannot right click');\n await page.mouse.click(element.center[0], element.center[1], {\n button: 'right',\n });\n },\n } as DeviceAction<{\n locate: MidsceneLocationResultType;\n }>,\n {\n name: 'Hover',\n description: 'Move the mouse to the element',\n interfaceAlias: 'aiHover',\n paramSchema: z.object({\n locate: getMidsceneLocationSchema().describe('The element to be hovered'),\n }),\n call: async (param) => {\n const element = param.locate;\n assert(element, 'Element not found, cannot hover');\n await page.mouse.move(element.center[0], element.center[1]);\n },\n } as DeviceAction<{\n locate: MidsceneLocationResultType;\n }>,\n {\n name: 'Input',\n description:\n 'Replace the input field with a new value. `value` is the final that should be filled in the input box. No matter what modifications are required, just provide the final value to replace the existing input value. Giving a blank string means clear the input field.',\n interfaceAlias: 'aiInput',\n paramSchema: z.object({\n value: z\n .string()\n .describe('The final value that should be filled in the input box'),\n locate: getMidsceneLocationSchema()\n .describe('The input field to be filled')\n .optional(),\n }),\n call: async (param) => {\n const element = param.locate;\n if (element) {\n await page.clearInput(element as unknown as ElementInfo);\n\n if (!param || !param.value) {\n return;\n }\n }\n\n // Note: there is another implementation in AndroidDevicePage, which is more complex\n await page.keyboard.type(param.value);\n },\n } as DeviceAction<{\n value: string;\n locate: MidsceneLocationResultType;\n }>,\n {\n name: 'KeyboardPress',\n description:\n 'Press a function key, like \"Enter\", \"Tab\", \"Escape\". Do not use this to type text.',\n interfaceAlias: 'aiKeyboardPress',\n paramSchema: z.object({\n locate: getMidsceneLocationSchema()\n .describe('The element to be clicked before pressing the key')\n .optional(),\n keyName: z.string().describe('The key to be pressed'),\n }),\n call: async (param) => {\n const element = param.locate;\n if (element) {\n await page.mouse.click(element.center[0], element.center[1], {\n button: 'left',\n });\n }\n\n const keys = getKeyCommands(param.keyName);\n await page.keyboard.press(keys as any); // TODO: fix this type error\n },\n } as DeviceAction<{\n keyName: string;\n locate: MidsceneLocationResultType;\n }>,\n {\n name: 'Scroll',\n description:\n 'Scroll the page or an element. The direction to scroll, the scroll type, and the distance to scroll. The distance is the number of pixels to scroll. If not specified, use `down` direction, `once` scroll type, and `null` distance.',\n interfaceAlias: 'aiScroll',\n paramSchema: z.object({\n direction: z\n .enum(['down', 'up', 'right', 'left'])\n .default('down')\n .describe('The direction to scroll'),\n scrollType: z\n .enum(['once', 'untilBottom', 'untilTop', 'untilRight', 'untilLeft'])\n .default('once')\n .describe('The scroll type'),\n distance: z\n .number()\n .nullable()\n .optional()\n .describe('The distance in pixels to scroll'),\n locate: getMidsceneLocationSchema()\n .optional()\n .describe('The element to be scrolled'),\n }),\n call: async (param) => {\n const element = param.locate;\n const startingPoint = element\n ? {\n left: element.center[0],\n top: element.center[1],\n }\n : undefined;\n const scrollToEventName = param?.scrollType;\n if (scrollToEventName === 'untilTop') {\n await page.scrollUntilTop(startingPoint);\n } else if (scrollToEventName === 'untilBottom') {\n await page.scrollUntilBottom(startingPoint);\n } else if (scrollToEventName === 'untilRight') {\n await page.scrollUntilRight(startingPoint);\n } else if (scrollToEventName === 'untilLeft') {\n await page.scrollUntilLeft(startingPoint);\n } else if (scrollToEventName === 'once' || !scrollToEventName) {\n if (param?.direction === 'down' || !param || !param.direction) {\n await page.scrollDown(param?.distance || undefined, startingPoint);\n } else if (param.direction === 'up') {\n await page.scrollUp(param.distance || undefined, startingPoint);\n } else if (param.direction === 'left') {\n await page.scrollLeft(param.distance || undefined, startingPoint);\n } else if (param.direction === 'right') {\n await page.scrollRight(param.distance || undefined, startingPoint);\n } else {\n throw new Error(`Unknown scroll direction: ${param.direction}`);\n }\n // until mouse event is done\n await sleep(500);\n } else {\n throw new Error(\n `Unknown scroll event type: ${scrollToEventName}, param: ${JSON.stringify(\n param,\n )}`,\n );\n }\n },\n } as DeviceAction<{\n scrollType:\n | 'once'\n | 'untilBottom'\n | 'untilTop'\n | 'untilRight'\n | 'untilLeft';\n direction: 'up' | 'down';\n distance?: number;\n duration?: number;\n locate: MidsceneLocationResultType;\n }>,\n {\n name: 'DragAndDrop',\n description: 'Drag and drop the element',\n paramSchema: z.object({\n from: getMidsceneLocationSchema().describe('The position to be dragged'),\n to: getMidsceneLocationSchema().describe('The position to be dropped'),\n }),\n call: async (param) => {\n const from = param.from;\n const to = param.to;\n assert(from, 'missing \"from\" param for drag and drop');\n assert(to, 'missing \"to\" param for drag and drop');\n await page.mouse.drag(\n {\n x: from.center[0],\n y: from.center[1],\n },\n {\n x: to.center[0],\n y: to.center[1],\n },\n );\n },\n } as DeviceAction<{\n from: MidsceneLocationResultType;\n to: MidsceneLocationResultType;\n }>,\n];\n"],"names":["debugProfile","getDebug","commonContextParser","page","assert","url","uploadTestInfoToServer","screenshotBase64","size","resizeImgBase64","getReportFileName","tag","reportTagName","globalConfigManager","MIDSCENE_REPORT_TAG_NAME","dateTimeInFileName","dayjs","uniqueId","uuid","printReportMsg","filepath","logMsg","getCurrentExecutionFile","trace","error","Error","stackTrace","pkgDir","process","stackLines","line","match","targetFileName","testFileIndex","Map","generateCacheId","fileName","taskFile","console","currentIndex","undefined","matchElementFromPlan","planLocateParam","tree","getNodeFromCacheList","centerPosition","Math","element","elementByPositionWithElementInfo","generateElementByPosition","matchElementFromCache","taskExecutor","xpaths","cachePrompt","cacheable","_taskExecutor_taskCache","i","cacheDebug","trimContextByViewport","execution","filterVisibleTree","node","filteredChildren","Array","child","task","_task_pageContext","newTask","getMidsceneVersion","__VERSION__","parsePrompt","prompt","commonWebActionsForWebPage","z","getMidsceneLocationSchema","param","keys","getKeyCommands","startingPoint","scrollToEventName","JSON","sleep","from","to"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"agent/utils.mjs","sources":["webpack://@midscene/core/./src/agent/utils.ts"],"sourcesContent":["import { elementByPositionWithElementInfo } from '@/ai-model';\nimport type { AbstractDevice } from '@/device';\nimport type {\n BaseElement,\n ElementTreeNode,\n ExecutionDump,\n ExecutionTask,\n ExecutorContext,\n PlanningLocateParam,\n TMultimodalPrompt,\n TUserPrompt,\n UIContext,\n} from '@/index';\nimport { uploadTestInfoToServer } from '@/utils';\nimport {\n MIDSCENE_REPORT_TAG_NAME,\n globalConfigManager,\n} from '@midscene/shared/env';\nimport {\n generateElementByPosition,\n getNodeFromCacheList,\n} from '@midscene/shared/extractor';\nimport { resizeImgBase64 } from '@midscene/shared/img';\nimport { getDebug } from '@midscene/shared/logger';\nimport { _keyDefinitions } from '@midscene/shared/us-keyboard-layout';\nimport { assert, logMsg, uuid } from '@midscene/shared/utils';\nimport dayjs from 'dayjs';\nimport { debug as cacheDebug } from './task-cache';\nimport type { PageTaskExecutor } from './tasks';\n\nconst debugProfile = getDebug('web:tool:profile');\n\nexport async function commonContextParser(\n page: AbstractDevice,\n): Promise<UIContext> {\n assert(page, 'page is required');\n\n debugProfile('Getting page URL');\n const url = await page.url();\n debugProfile('URL end');\n\n debugProfile('Uploading test info to server');\n uploadTestInfoToServer({ testUrl: url });\n debugProfile('UploadTestInfoToServer end');\n\n let screenshotBase64 = await page.screenshotBase64();\n assert(screenshotBase64!, 'screenshotBase64 is required');\n\n const size = await page.size();\n debugProfile(`size: ${size.width}x${size.height} dpr: ${size.dpr}`);\n\n if (size.dpr && size.dpr > 1) {\n debugProfile('Resizing screenshot for high DPR display');\n screenshotBase64 = await resizeImgBase64(screenshotBase64, {\n width: size.width,\n height: size.height,\n });\n debugProfile('ResizeImgBase64 end');\n }\n\n return {\n tree: {\n node: null,\n children: [],\n },\n size,\n screenshotBase64: screenshotBase64!,\n url,\n };\n}\n\nexport function getReportFileName(tag = 'web') {\n const reportTagName = globalConfigManager.getEnvConfigValue(\n MIDSCENE_REPORT_TAG_NAME,\n );\n const dateTimeInFileName = dayjs().format('YYYY-MM-DD_HH-mm-ss');\n // ensure uniqueness at the same time\n const uniqueId = uuid().substring(0, 8);\n return `${reportTagName || tag}-${dateTimeInFileName}-${uniqueId}`;\n}\n\nexport function printReportMsg(filepath: string) {\n logMsg(`Midscene - report file updated: ${filepath}`);\n}\n\n/**\n * Get the current execution file name\n * @returns The name of the current execution file\n */\nexport function getCurrentExecutionFile(trace?: string): string | false {\n const error = new Error();\n const stackTrace = trace || error.stack;\n const pkgDir = process.cwd() || '';\n if (stackTrace) {\n const stackLines = stackTrace.split('\\n');\n for (const line of stackLines) {\n if (\n line.includes('.spec.') ||\n line.includes('.test.') ||\n line.includes('.ts') ||\n line.includes('.js')\n ) {\n const match = line.match(/(?:at\\s+)?(.*?\\.(?:spec|test)\\.[jt]s)/);\n if (match?.[1]) {\n const targetFileName = match[1]\n .replace(pkgDir, '')\n .trim()\n .replace('at ', '');\n return targetFileName;\n }\n }\n }\n }\n return false;\n}\n\nconst testFileIndex = new Map<string, number>();\n\nexport function generateCacheId(fileName?: string): string {\n let taskFile = fileName || getCurrentExecutionFile();\n if (!taskFile) {\n taskFile = uuid();\n console.warn(\n 'Midscene - using random UUID for cache id. Cache may be invalid.',\n );\n }\n\n if (testFileIndex.has(taskFile)) {\n const currentIndex = testFileIndex.get(taskFile);\n if (currentIndex !== undefined) {\n testFileIndex.set(taskFile, currentIndex + 1);\n }\n } else {\n testFileIndex.set(taskFile, 1);\n }\n return `${taskFile}-${testFileIndex.get(taskFile)}`;\n}\n\nexport function matchElementFromPlan(\n planLocateParam: PlanningLocateParam,\n tree: ElementTreeNode<BaseElement>,\n) {\n if (!planLocateParam) {\n return undefined;\n }\n if (planLocateParam.id) {\n return getNodeFromCacheList(planLocateParam.id);\n }\n\n if (planLocateParam.bbox) {\n const centerPosition = {\n x: Math.floor((planLocateParam.bbox[0] + planLocateParam.bbox[2]) / 2),\n y: Math.floor((planLocateParam.bbox[1] + planLocateParam.bbox[3]) / 2),\n };\n let element = elementByPositionWithElementInfo(tree, centerPosition);\n\n if (!element) {\n element = generateElementByPosition(centerPosition) as BaseElement;\n }\n\n return element;\n }\n\n return undefined;\n}\n\nexport async function matchElementFromCache(\n taskExecutor: PageTaskExecutor,\n xpaths: string[] | undefined,\n cachePrompt: TUserPrompt,\n cacheable: boolean | undefined,\n) {\n try {\n if (\n xpaths?.length &&\n taskExecutor.taskCache?.isCacheResultUsed &&\n cacheable !== false &&\n (taskExecutor.page as any).getElementInfoByXpath\n ) {\n // hit cache, use new id\n for (let i = 0; i < xpaths.length; i++) {\n const element = await (taskExecutor.page as any).getElementInfoByXpath(\n xpaths[i],\n );\n\n if (element?.id) {\n cacheDebug('cache hit, prompt: %s', cachePrompt);\n cacheDebug(\n 'found a new element with same xpath, xpath: %s, id: %s',\n xpaths[i],\n element?.id,\n );\n return element;\n }\n }\n }\n } catch (error) {\n cacheDebug('get element info by xpath error: ', error);\n }\n}\n\nexport function trimContextByViewport(execution: ExecutionDump) {\n function filterVisibleTree(\n node: ElementTreeNode<BaseElement>,\n ): ElementTreeNode<BaseElement> | null {\n if (!node) return null;\n\n // recursively process all children\n const filteredChildren = Array.isArray(node.children)\n ? (node.children\n .map(filterVisibleTree)\n .filter((child) => child !== null) as ElementTreeNode<BaseElement>[])\n : [];\n\n // if the current node is visible, keep it and the filtered children\n if (node.node && node.node.isVisible === true) {\n return {\n ...node,\n children: filteredChildren,\n };\n }\n\n // if the current node is invisible, but has visible children, create an empty node to include these children\n if (filteredChildren.length > 0) {\n return {\n node: null,\n children: filteredChildren,\n };\n }\n\n // if the current node is invisible and has no visible children, return null\n return null;\n }\n\n return {\n ...execution,\n tasks: Array.isArray(execution.tasks)\n ? execution.tasks.map((task: ExecutionTask) => {\n const newTask = { ...task };\n if (task.pageContext?.tree) {\n newTask.pageContext = {\n ...task.pageContext,\n tree: filterVisibleTree(task.pageContext.tree) || {\n node: null,\n children: [],\n },\n };\n }\n return newTask;\n })\n : execution.tasks,\n };\n}\n\ndeclare const __VERSION__: string | undefined;\n\nexport const getMidsceneVersion = (): string => {\n if (typeof __VERSION__ !== 'undefined') {\n return __VERSION__;\n } else if (\n process.env.__VERSION__ &&\n process.env.__VERSION__ !== 'undefined'\n ) {\n return process.env.__VERSION__;\n }\n throw new Error('__VERSION__ inject failed during build');\n};\n\nexport const parsePrompt = (\n prompt: TUserPrompt,\n): {\n textPrompt: string;\n multimodalPrompt?: TMultimodalPrompt;\n} => {\n if (typeof prompt === 'string') {\n return {\n textPrompt: prompt,\n multimodalPrompt: undefined,\n };\n }\n return {\n textPrompt: prompt.prompt,\n multimodalPrompt: prompt.images\n ? {\n images: prompt.images,\n convertHttpImage2Base64: !!prompt.convertHttpImage2Base64,\n }\n : undefined,\n };\n};\n"],"names":["debugProfile","getDebug","commonContextParser","page","assert","url","uploadTestInfoToServer","screenshotBase64","size","resizeImgBase64","getReportFileName","tag","reportTagName","globalConfigManager","MIDSCENE_REPORT_TAG_NAME","dateTimeInFileName","dayjs","uniqueId","uuid","printReportMsg","filepath","logMsg","getCurrentExecutionFile","trace","error","Error","stackTrace","pkgDir","process","stackLines","line","match","targetFileName","testFileIndex","Map","generateCacheId","fileName","taskFile","console","currentIndex","undefined","matchElementFromPlan","planLocateParam","tree","getNodeFromCacheList","centerPosition","Math","element","elementByPositionWithElementInfo","generateElementByPosition","matchElementFromCache","taskExecutor","xpaths","cachePrompt","cacheable","_taskExecutor_taskCache","i","cacheDebug","trimContextByViewport","execution","filterVisibleTree","node","filteredChildren","Array","child","task","_task_pageContext","newTask","getMidsceneVersion","__VERSION__","parsePrompt","prompt"],"mappings":"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"}
|
|
@@ -97,7 +97,7 @@ async function call(messages, AIActionTypeValue, modelPreferences, options) {
|
|
|
97
97
|
modelPreferences
|
|
98
98
|
});
|
|
99
99
|
const responseFormat = getResponseFormat(modelName, AIActionTypeValue);
|
|
100
|
-
const maxTokens = globalConfigManager.
|
|
100
|
+
const maxTokens = globalConfigManager.getEnvConfigValue(OPENAI_MAX_TOKENS);
|
|
101
101
|
const debugCall = getDebug('ai:call');
|
|
102
102
|
const debugProfileStats = getDebug('ai:profile:stats');
|
|
103
103
|
const debugProfileDetail = getDebug('ai:profile:detail');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-model/service-caller/index.mjs","sources":["webpack://@midscene/core/./src/ai-model/service-caller/index.ts"],"sourcesContent":["import { AIResponseFormat, type AIUsageInfo } from '@/types';\nimport type { CodeGenerationChunk, StreamingCallback } from '@/types';\nimport { Anthropic } from '@anthropic-ai/sdk';\nimport {\n DefaultAzureCredential,\n getBearerTokenProvider,\n} from '@azure/identity';\nimport {\n type IModelPreferences,\n MIDSCENE_API_TYPE,\n MIDSCENE_LANGSMITH_DEBUG,\n OPENAI_MAX_TOKENS,\n globalConfigManager,\n uiTarsModelVersion,\n vlLocateMode,\n} from '@midscene/shared/env';\nimport { parseBase64 } from '@midscene/shared/img';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport { ifInBrowser } from '@midscene/shared/utils';\nimport { HttpsProxyAgent } from 'https-proxy-agent';\nimport { jsonrepair } from 'jsonrepair';\nimport OpenAI, { AzureOpenAI } from 'openai';\nimport type { ChatCompletionMessageParam } from 'openai/resources/index';\nimport type { Stream } from 'openai/streaming';\nimport { SocksProxyAgent } from 'socks-proxy-agent';\nimport { AIActionType, type AIArgs } from '../common';\nimport { assertSchema } from '../prompt/assertion';\nimport { locatorSchema } from '../prompt/llm-locator';\nimport { planSchema } from '../prompt/llm-planning';\n\nasync function createChatClient({\n AIActionTypeValue,\n modelPreferences,\n}: {\n AIActionTypeValue: AIActionType;\n modelPreferences: IModelPreferences;\n}): Promise<{\n completion: OpenAI.Chat.Completions;\n style: 'openai' | 'anthropic';\n modelName: string;\n modelDescription: string;\n}> {\n const {\n socksProxy,\n httpProxy,\n modelName,\n openaiBaseURL,\n openaiApiKey,\n openaiExtraConfig,\n openaiUseAzureDeprecated,\n useAzureOpenai,\n azureOpenaiScope,\n azureOpenaiKey,\n azureOpenaiEndpoint,\n azureOpenaiApiVersion,\n azureOpenaiDeployment,\n azureExtraConfig,\n useAnthropicSdk,\n anthropicApiKey,\n modelDescription,\n } = globalConfigManager.getModelConfigByIntent(modelPreferences.intent);\n\n let openai: OpenAI | AzureOpenAI | undefined;\n\n let proxyAgent = undefined;\n const debugProxy = getDebug('ai:call:proxy');\n if (httpProxy) {\n debugProxy('using http proxy', httpProxy);\n proxyAgent = new HttpsProxyAgent(httpProxy);\n } else if (socksProxy) {\n debugProxy('using socks proxy', socksProxy);\n proxyAgent = new SocksProxyAgent(socksProxy);\n }\n\n if (openaiUseAzureDeprecated) {\n // this is deprecated\n openai = new AzureOpenAI({\n baseURL: openaiBaseURL,\n apiKey: openaiApiKey,\n httpAgent: proxyAgent,\n ...openaiExtraConfig,\n dangerouslyAllowBrowser: true,\n }) as OpenAI;\n } else if (useAzureOpenai) {\n // https://learn.microsoft.com/en-us/azure/ai-services/openai/chatgpt-quickstart?tabs=bash%2Cjavascript-key%2Ctypescript-keyless%2Cpython&pivots=programming-language-javascript#rest-api\n // keyless authentication\n let tokenProvider: any = undefined;\n if (azureOpenaiScope) {\n assert(\n !ifInBrowser,\n 'Azure OpenAI is not supported in browser with Midscene.',\n );\n const credential = new DefaultAzureCredential();\n\n tokenProvider = getBearerTokenProvider(credential, azureOpenaiScope);\n\n openai = new AzureOpenAI({\n azureADTokenProvider: tokenProvider,\n endpoint: azureOpenaiEndpoint,\n apiVersion: azureOpenaiApiVersion,\n deployment: azureOpenaiDeployment,\n ...openaiExtraConfig,\n ...azureExtraConfig,\n });\n } else {\n // endpoint, apiKey, apiVersion, deployment\n openai = new AzureOpenAI({\n apiKey: azureOpenaiKey,\n endpoint: azureOpenaiEndpoint,\n apiVersion: azureOpenaiApiVersion,\n deployment: azureOpenaiDeployment,\n dangerouslyAllowBrowser: true,\n ...openaiExtraConfig,\n ...azureExtraConfig,\n });\n }\n } else if (!useAnthropicSdk) {\n openai = new OpenAI({\n baseURL: openaiBaseURL,\n apiKey: openaiApiKey,\n httpAgent: proxyAgent,\n ...openaiExtraConfig,\n defaultHeaders: {\n ...(openaiExtraConfig?.defaultHeaders || {}),\n [MIDSCENE_API_TYPE]: AIActionTypeValue.toString(),\n },\n dangerouslyAllowBrowser: true,\n });\n }\n\n if (\n openai &&\n globalConfigManager.getEnvConfigInBoolean(MIDSCENE_LANGSMITH_DEBUG)\n ) {\n if (ifInBrowser) {\n throw new Error('langsmith is not supported in browser');\n }\n console.log('DEBUGGING MODE: langsmith wrapper enabled');\n const { wrapOpenAI } = await import('langsmith/wrappers');\n openai = wrapOpenAI(openai);\n }\n\n if (typeof openai !== 'undefined') {\n return {\n completion: openai.chat.completions,\n style: 'openai',\n modelName,\n modelDescription,\n };\n }\n\n // Anthropic\n if (useAnthropicSdk) {\n openai = new Anthropic({\n apiKey: anthropicApiKey,\n httpAgent: proxyAgent,\n dangerouslyAllowBrowser: true,\n }) as any;\n }\n\n if (typeof openai !== 'undefined' && (openai as any).messages) {\n return {\n completion: (openai as any).messages,\n style: 'anthropic',\n modelName,\n modelDescription,\n };\n }\n\n throw new Error('Openai SDK or Anthropic SDK is not initialized');\n}\n\nexport async function call(\n messages: ChatCompletionMessageParam[],\n AIActionTypeValue: AIActionType,\n modelPreferences: IModelPreferences,\n options?: {\n stream?: boolean;\n onChunk?: StreamingCallback;\n },\n): Promise<{ content: string; usage?: AIUsageInfo; isStreamed: boolean }> {\n const { completion, style, modelName, modelDescription } =\n await createChatClient({\n AIActionTypeValue,\n modelPreferences,\n });\n\n const responseFormat = getResponseFormat(modelName, AIActionTypeValue);\n\n const maxTokens = globalConfigManager.getEnvConfigInNumber(OPENAI_MAX_TOKENS);\n const debugCall = getDebug('ai:call');\n const debugProfileStats = getDebug('ai:profile:stats');\n const debugProfileDetail = getDebug('ai:profile:detail');\n\n const startTime = Date.now();\n\n const isStreaming = options?.stream && options?.onChunk;\n let content: string | undefined;\n let accumulated = '';\n let usage: OpenAI.CompletionUsage | undefined;\n let timeCost: number | undefined;\n\n const commonConfig = {\n temperature: vlLocateMode(modelPreferences) === 'vlm-ui-tars' ? 0.0 : 0.1,\n stream: !!isStreaming,\n max_tokens:\n typeof maxTokens === 'number'\n ? maxTokens\n : Number.parseInt(maxTokens || '2048', 10),\n ...(vlLocateMode(modelPreferences) === 'qwen-vl' // qwen specific config\n ? {\n vl_high_resolution_images: true,\n }\n : {}),\n };\n\n try {\n if (style === 'openai') {\n debugCall(\n `sending ${isStreaming ? 'streaming ' : ''}request to ${modelName}`,\n );\n\n if (isStreaming) {\n const stream = (await completion.create(\n {\n model: modelName,\n messages,\n response_format: responseFormat,\n ...commonConfig,\n },\n {\n stream: true,\n },\n )) as Stream<OpenAI.Chat.Completions.ChatCompletionChunk> & {\n _request_id?: string | null;\n };\n\n for await (const chunk of stream) {\n const content = chunk.choices?.[0]?.delta?.content || '';\n const reasoning_content =\n (chunk.choices?.[0]?.delta as any)?.reasoning_content || '';\n\n // Check for usage info in any chunk (OpenAI provides usage in separate chunks)\n if (chunk.usage) {\n usage = chunk.usage;\n }\n\n if (content || reasoning_content) {\n accumulated += content;\n const chunkData: CodeGenerationChunk = {\n content,\n reasoning_content,\n accumulated,\n isComplete: false,\n usage: undefined,\n };\n options.onChunk!(chunkData);\n }\n\n // Check if stream is complete\n if (chunk.choices?.[0]?.finish_reason) {\n timeCost = Date.now() - startTime;\n\n // If usage is not available from the stream, provide a basic usage info\n if (!usage) {\n // Estimate token counts based on content length (rough approximation)\n const estimatedTokens = Math.max(\n 1,\n Math.floor(accumulated.length / 4),\n );\n usage = {\n prompt_tokens: estimatedTokens,\n completion_tokens: estimatedTokens,\n total_tokens: estimatedTokens * 2,\n };\n }\n\n // Send final chunk\n const finalChunk: CodeGenerationChunk = {\n content: '',\n accumulated,\n reasoning_content: '',\n isComplete: true,\n usage: {\n prompt_tokens: usage.prompt_tokens ?? 0,\n completion_tokens: usage.completion_tokens ?? 0,\n total_tokens: usage.total_tokens ?? 0,\n time_cost: timeCost ?? 0,\n model_name: modelName,\n model_description: modelDescription,\n intent: modelPreferences.intent,\n },\n };\n options.onChunk!(finalChunk);\n break;\n }\n }\n content = accumulated;\n debugProfileStats(\n `streaming model, ${modelName}, mode, ${vlLocateMode(modelPreferences) || 'default'}, cost-ms, ${timeCost}`,\n );\n } else {\n const result = await completion.create({\n model: modelName,\n messages,\n response_format: responseFormat,\n ...commonConfig,\n } as any);\n timeCost = Date.now() - startTime;\n\n debugProfileStats(\n `model, ${modelName}, mode, ${vlLocateMode(modelPreferences) || 'default'}, ui-tars-version, ${uiTarsModelVersion(modelPreferences)}, prompt-tokens, ${result.usage?.prompt_tokens || ''}, completion-tokens, ${result.usage?.completion_tokens || ''}, total-tokens, ${result.usage?.total_tokens || ''}, cost-ms, ${timeCost}, requestId, ${result._request_id || ''}`,\n );\n\n debugProfileDetail(\n `model usage detail: ${JSON.stringify(result.usage)}`,\n );\n\n assert(\n result.choices,\n `invalid response from LLM service: ${JSON.stringify(result)}`,\n );\n content = result.choices[0].message.content!;\n usage = result.usage;\n }\n\n debugCall(`response: ${content}`);\n assert(content, 'empty content');\n } else if (style === 'anthropic') {\n const convertImageContent = (content: any) => {\n if (content.type === 'image_url') {\n const imgBase64 = content.image_url.url;\n assert(imgBase64, 'image_url is required');\n const { mimeType, body } = parseBase64(content.image_url.url);\n return {\n source: {\n type: 'base64',\n media_type: mimeType,\n data: body,\n },\n type: 'image',\n };\n }\n return content;\n };\n\n if (isStreaming) {\n const stream = (await completion.create({\n model: modelName,\n system: 'You are a versatile professional in software UI automation',\n messages: messages.map((m) => ({\n role: 'user',\n content: Array.isArray(m.content)\n ? (m.content as any).map(convertImageContent)\n : m.content,\n })),\n response_format: responseFormat,\n ...commonConfig,\n } as any)) as any;\n\n for await (const chunk of stream) {\n const content = chunk.delta?.text || '';\n if (content) {\n accumulated += content;\n const chunkData: CodeGenerationChunk = {\n content,\n accumulated,\n reasoning_content: '',\n isComplete: false,\n usage: undefined,\n };\n options.onChunk!(chunkData);\n }\n\n // Check if stream is complete\n if (chunk.type === 'message_stop') {\n timeCost = Date.now() - startTime;\n const anthropicUsage = chunk.usage;\n\n // Send final chunk\n const finalChunk: CodeGenerationChunk = {\n content: '',\n accumulated,\n reasoning_content: '',\n isComplete: true,\n usage: anthropicUsage\n ? {\n prompt_tokens: anthropicUsage.input_tokens ?? 0,\n completion_tokens: anthropicUsage.output_tokens ?? 0,\n total_tokens:\n (anthropicUsage.input_tokens ?? 0) +\n (anthropicUsage.output_tokens ?? 0),\n time_cost: timeCost ?? 0,\n model_name: modelName,\n model_description: modelDescription,\n intent: modelPreferences.intent,\n }\n : undefined,\n };\n options.onChunk!(finalChunk);\n break;\n }\n }\n content = accumulated;\n } else {\n const result = await completion.create({\n model: modelName,\n system: 'You are a versatile professional in software UI automation',\n messages: messages.map((m) => ({\n role: 'user',\n content: Array.isArray(m.content)\n ? (m.content as any).map(convertImageContent)\n : m.content,\n })),\n response_format: responseFormat,\n ...commonConfig,\n } as any);\n timeCost = Date.now() - startTime;\n content = (result as any).content[0].text as string;\n usage = result.usage;\n }\n\n assert(content, 'empty content');\n }\n // Ensure we always have usage info for streaming responses\n if (isStreaming && !usage) {\n // Estimate token counts based on content length (rough approximation)\n const estimatedTokens = Math.max(\n 1,\n Math.floor((content || '').length / 4),\n );\n usage = {\n prompt_tokens: estimatedTokens,\n completion_tokens: estimatedTokens,\n total_tokens: estimatedTokens * 2,\n };\n }\n\n return {\n content: content || '',\n usage: usage\n ? {\n prompt_tokens: usage.prompt_tokens ?? 0,\n completion_tokens: usage.completion_tokens ?? 0,\n total_tokens: usage.total_tokens ?? 0,\n time_cost: timeCost ?? 0,\n model_name: modelName,\n model_description: modelDescription,\n intent: modelPreferences.intent,\n }\n : undefined,\n isStreamed: !!isStreaming,\n };\n } catch (e: any) {\n console.error(' call AI error', e);\n const newError = new Error(\n `failed to call ${isStreaming ? 'streaming ' : ''}AI model service: ${e.message}. Trouble shooting: https://midscenejs.com/model-provider.html`,\n {\n cause: e,\n },\n );\n throw newError;\n }\n}\n\nexport const getResponseFormat = (\n modelName: string,\n AIActionTypeValue: AIActionType,\n):\n | OpenAI.ChatCompletionCreateParams['response_format']\n | OpenAI.ResponseFormatJSONObject => {\n let responseFormat:\n | OpenAI.ChatCompletionCreateParams['response_format']\n | OpenAI.ResponseFormatJSONObject\n | undefined;\n\n if (modelName.includes('gpt-4')) {\n switch (AIActionTypeValue) {\n case AIActionType.ASSERT:\n responseFormat = assertSchema;\n break;\n case AIActionType.INSPECT_ELEMENT:\n responseFormat = locatorSchema;\n break;\n case AIActionType.PLAN:\n responseFormat = planSchema;\n break;\n case AIActionType.EXTRACT_DATA:\n case AIActionType.DESCRIBE_ELEMENT:\n responseFormat = { type: AIResponseFormat.JSON };\n break;\n }\n }\n\n // gpt-4o-2024-05-13 only supports json_object response format\n if (modelName === 'gpt-4o-2024-05-13') {\n responseFormat = { type: AIResponseFormat.JSON };\n }\n\n return responseFormat;\n};\n\nexport async function callToGetJSONObject<T>(\n messages: ChatCompletionMessageParam[],\n AIActionTypeValue: AIActionType,\n modelPreferences: IModelPreferences,\n): Promise<{ content: T; usage?: AIUsageInfo }> {\n const response = await call(messages, AIActionTypeValue, modelPreferences);\n assert(response, 'empty response');\n const jsonContent = safeParseJson(response.content, modelPreferences);\n return { content: jsonContent, usage: response.usage };\n}\n\nexport async function callAiFnWithStringResponse<T>(\n msgs: AIArgs,\n AIActionTypeValue: AIActionType,\n modelPreferences: IModelPreferences,\n): Promise<{ content: string; usage?: AIUsageInfo }> {\n const { content, usage } = await call(\n msgs,\n AIActionTypeValue,\n modelPreferences,\n );\n return { content, usage };\n}\n\nexport function extractJSONFromCodeBlock(response: string) {\n try {\n // First, try to match a JSON object directly in the response\n const jsonMatch = response.match(/^\\s*(\\{[\\s\\S]*\\})\\s*$/);\n if (jsonMatch) {\n return jsonMatch[1];\n }\n\n // If no direct JSON object is found, try to extract JSON from a code block\n const codeBlockMatch = response.match(\n /```(?:json)?\\s*(\\{[\\s\\S]*?\\})\\s*```/,\n );\n if (codeBlockMatch) {\n return codeBlockMatch[1];\n }\n\n // If no code block is found, try to find a JSON-like structure in the text\n const jsonLikeMatch = response.match(/\\{[\\s\\S]*\\}/);\n if (jsonLikeMatch) {\n return jsonLikeMatch[0];\n }\n } catch {}\n // If no JSON-like structure is found, return the original response\n return response;\n}\n\nexport function preprocessDoubaoBboxJson(input: string) {\n if (input.includes('bbox')) {\n // when its values like 940 445 969 490, replace all /\\d+\\s+\\d+/g with /$1,$2/g\n while (/\\d+\\s+\\d+/.test(input)) {\n input = input.replace(/(\\d+)\\s+(\\d+)/g, '$1,$2');\n }\n }\n return input;\n}\n\nexport function safeParseJson(\n input: string,\n modelPreferences: IModelPreferences,\n) {\n const cleanJsonString = extractJSONFromCodeBlock(input);\n // match the point\n if (cleanJsonString?.match(/\\((\\d+),(\\d+)\\)/)) {\n return cleanJsonString\n .match(/\\((\\d+),(\\d+)\\)/)\n ?.slice(1)\n .map(Number);\n }\n try {\n return JSON.parse(cleanJsonString);\n } catch {}\n try {\n return JSON.parse(jsonrepair(cleanJsonString));\n } catch (e) {}\n\n if (\n vlLocateMode(modelPreferences) === 'doubao-vision' ||\n vlLocateMode(modelPreferences) === 'vlm-ui-tars'\n ) {\n const jsonString = preprocessDoubaoBboxJson(cleanJsonString);\n return JSON.parse(jsonrepair(jsonString));\n }\n throw Error(`failed to parse json response: ${input}`);\n}\n"],"names":["createChatClient","AIActionTypeValue","modelPreferences","socksProxy","httpProxy","modelName","openaiBaseURL","openaiApiKey","openaiExtraConfig","openaiUseAzureDeprecated","useAzureOpenai","azureOpenaiScope","azureOpenaiKey","azureOpenaiEndpoint","azureOpenaiApiVersion","azureOpenaiDeployment","azureExtraConfig","useAnthropicSdk","anthropicApiKey","modelDescription","globalConfigManager","openai","proxyAgent","debugProxy","getDebug","HttpsProxyAgent","SocksProxyAgent","AzureOpenAI","tokenProvider","assert","ifInBrowser","credential","DefaultAzureCredential","getBearerTokenProvider","OpenAI","MIDSCENE_API_TYPE","MIDSCENE_LANGSMITH_DEBUG","Error","console","wrapOpenAI","Anthropic","call","messages","options","completion","style","responseFormat","getResponseFormat","maxTokens","OPENAI_MAX_TOKENS","debugCall","debugProfileStats","debugProfileDetail","startTime","Date","isStreaming","content","accumulated","usage","timeCost","commonConfig","vlLocateMode","Number","stream","chunk","_chunk_choices__delta","_chunk_choices__delta1","_chunk_choices_2","reasoning_content","chunkData","undefined","estimatedTokens","Math","finalChunk","_result_usage","_result_usage1","_result_usage2","result","uiTarsModelVersion","JSON","convertImageContent","imgBase64","mimeType","body","parseBase64","m","Array","_chunk_delta","anthropicUsage","e","newError","AIActionType","assertSchema","locatorSchema","planSchema","AIResponseFormat","callToGetJSONObject","response","jsonContent","safeParseJson","callAiFnWithStringResponse","msgs","extractJSONFromCodeBlock","jsonMatch","codeBlockMatch","jsonLikeMatch","preprocessDoubaoBboxJson","input","cleanJsonString","_cleanJsonString_match","jsonrepair","jsonString"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ai-model/service-caller/index.mjs","sources":["webpack://@midscene/core/./src/ai-model/service-caller/index.ts"],"sourcesContent":["import { AIResponseFormat, type AIUsageInfo } from '@/types';\nimport type { CodeGenerationChunk, StreamingCallback } from '@/types';\nimport { Anthropic } from '@anthropic-ai/sdk';\nimport {\n DefaultAzureCredential,\n getBearerTokenProvider,\n} from '@azure/identity';\nimport {\n type IModelPreferences,\n MIDSCENE_API_TYPE,\n MIDSCENE_LANGSMITH_DEBUG,\n OPENAI_MAX_TOKENS,\n globalConfigManager,\n uiTarsModelVersion,\n vlLocateMode,\n} from '@midscene/shared/env';\nimport { parseBase64 } from '@midscene/shared/img';\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport { ifInBrowser } from '@midscene/shared/utils';\nimport { HttpsProxyAgent } from 'https-proxy-agent';\nimport { jsonrepair } from 'jsonrepair';\nimport OpenAI, { AzureOpenAI } from 'openai';\nimport type { ChatCompletionMessageParam } from 'openai/resources/index';\nimport type { Stream } from 'openai/streaming';\nimport { SocksProxyAgent } from 'socks-proxy-agent';\nimport { AIActionType, type AIArgs } from '../common';\nimport { assertSchema } from '../prompt/assertion';\nimport { locatorSchema } from '../prompt/llm-locator';\nimport { planSchema } from '../prompt/llm-planning';\n\nasync function createChatClient({\n AIActionTypeValue,\n modelPreferences,\n}: {\n AIActionTypeValue: AIActionType;\n modelPreferences: IModelPreferences;\n}): Promise<{\n completion: OpenAI.Chat.Completions;\n style: 'openai' | 'anthropic';\n modelName: string;\n modelDescription: string;\n}> {\n const {\n socksProxy,\n httpProxy,\n modelName,\n openaiBaseURL,\n openaiApiKey,\n openaiExtraConfig,\n openaiUseAzureDeprecated,\n useAzureOpenai,\n azureOpenaiScope,\n azureOpenaiKey,\n azureOpenaiEndpoint,\n azureOpenaiApiVersion,\n azureOpenaiDeployment,\n azureExtraConfig,\n useAnthropicSdk,\n anthropicApiKey,\n modelDescription,\n } = globalConfigManager.getModelConfigByIntent(modelPreferences.intent);\n\n let openai: OpenAI | AzureOpenAI | undefined;\n\n let proxyAgent = undefined;\n const debugProxy = getDebug('ai:call:proxy');\n if (httpProxy) {\n debugProxy('using http proxy', httpProxy);\n proxyAgent = new HttpsProxyAgent(httpProxy);\n } else if (socksProxy) {\n debugProxy('using socks proxy', socksProxy);\n proxyAgent = new SocksProxyAgent(socksProxy);\n }\n\n if (openaiUseAzureDeprecated) {\n // this is deprecated\n openai = new AzureOpenAI({\n baseURL: openaiBaseURL,\n apiKey: openaiApiKey,\n httpAgent: proxyAgent,\n ...openaiExtraConfig,\n dangerouslyAllowBrowser: true,\n }) as OpenAI;\n } else if (useAzureOpenai) {\n // https://learn.microsoft.com/en-us/azure/ai-services/openai/chatgpt-quickstart?tabs=bash%2Cjavascript-key%2Ctypescript-keyless%2Cpython&pivots=programming-language-javascript#rest-api\n // keyless authentication\n let tokenProvider: any = undefined;\n if (azureOpenaiScope) {\n assert(\n !ifInBrowser,\n 'Azure OpenAI is not supported in browser with Midscene.',\n );\n const credential = new DefaultAzureCredential();\n\n tokenProvider = getBearerTokenProvider(credential, azureOpenaiScope);\n\n openai = new AzureOpenAI({\n azureADTokenProvider: tokenProvider,\n endpoint: azureOpenaiEndpoint,\n apiVersion: azureOpenaiApiVersion,\n deployment: azureOpenaiDeployment,\n ...openaiExtraConfig,\n ...azureExtraConfig,\n });\n } else {\n // endpoint, apiKey, apiVersion, deployment\n openai = new AzureOpenAI({\n apiKey: azureOpenaiKey,\n endpoint: azureOpenaiEndpoint,\n apiVersion: azureOpenaiApiVersion,\n deployment: azureOpenaiDeployment,\n dangerouslyAllowBrowser: true,\n ...openaiExtraConfig,\n ...azureExtraConfig,\n });\n }\n } else if (!useAnthropicSdk) {\n openai = new OpenAI({\n baseURL: openaiBaseURL,\n apiKey: openaiApiKey,\n httpAgent: proxyAgent,\n ...openaiExtraConfig,\n defaultHeaders: {\n ...(openaiExtraConfig?.defaultHeaders || {}),\n [MIDSCENE_API_TYPE]: AIActionTypeValue.toString(),\n },\n dangerouslyAllowBrowser: true,\n });\n }\n\n if (\n openai &&\n globalConfigManager.getEnvConfigInBoolean(MIDSCENE_LANGSMITH_DEBUG)\n ) {\n if (ifInBrowser) {\n throw new Error('langsmith is not supported in browser');\n }\n console.log('DEBUGGING MODE: langsmith wrapper enabled');\n const { wrapOpenAI } = await import('langsmith/wrappers');\n openai = wrapOpenAI(openai);\n }\n\n if (typeof openai !== 'undefined') {\n return {\n completion: openai.chat.completions,\n style: 'openai',\n modelName,\n modelDescription,\n };\n }\n\n // Anthropic\n if (useAnthropicSdk) {\n openai = new Anthropic({\n apiKey: anthropicApiKey,\n httpAgent: proxyAgent,\n dangerouslyAllowBrowser: true,\n }) as any;\n }\n\n if (typeof openai !== 'undefined' && (openai as any).messages) {\n return {\n completion: (openai as any).messages,\n style: 'anthropic',\n modelName,\n modelDescription,\n };\n }\n\n throw new Error('Openai SDK or Anthropic SDK is not initialized');\n}\n\nexport async function call(\n messages: ChatCompletionMessageParam[],\n AIActionTypeValue: AIActionType,\n modelPreferences: IModelPreferences,\n options?: {\n stream?: boolean;\n onChunk?: StreamingCallback;\n },\n): Promise<{ content: string; usage?: AIUsageInfo; isStreamed: boolean }> {\n const { completion, style, modelName, modelDescription } =\n await createChatClient({\n AIActionTypeValue,\n modelPreferences,\n });\n\n const responseFormat = getResponseFormat(modelName, AIActionTypeValue);\n\n const maxTokens = globalConfigManager.getEnvConfigValue(OPENAI_MAX_TOKENS);\n const debugCall = getDebug('ai:call');\n const debugProfileStats = getDebug('ai:profile:stats');\n const debugProfileDetail = getDebug('ai:profile:detail');\n\n const startTime = Date.now();\n\n const isStreaming = options?.stream && options?.onChunk;\n let content: string | undefined;\n let accumulated = '';\n let usage: OpenAI.CompletionUsage | undefined;\n let timeCost: number | undefined;\n\n const commonConfig = {\n temperature: vlLocateMode(modelPreferences) === 'vlm-ui-tars' ? 0.0 : 0.1,\n stream: !!isStreaming,\n max_tokens:\n typeof maxTokens === 'number'\n ? maxTokens\n : Number.parseInt(maxTokens || '2048', 10),\n ...(vlLocateMode(modelPreferences) === 'qwen-vl' // qwen specific config\n ? {\n vl_high_resolution_images: true,\n }\n : {}),\n };\n\n try {\n if (style === 'openai') {\n debugCall(\n `sending ${isStreaming ? 'streaming ' : ''}request to ${modelName}`,\n );\n\n if (isStreaming) {\n const stream = (await completion.create(\n {\n model: modelName,\n messages,\n response_format: responseFormat,\n ...commonConfig,\n },\n {\n stream: true,\n },\n )) as Stream<OpenAI.Chat.Completions.ChatCompletionChunk> & {\n _request_id?: string | null;\n };\n\n for await (const chunk of stream) {\n const content = chunk.choices?.[0]?.delta?.content || '';\n const reasoning_content =\n (chunk.choices?.[0]?.delta as any)?.reasoning_content || '';\n\n // Check for usage info in any chunk (OpenAI provides usage in separate chunks)\n if (chunk.usage) {\n usage = chunk.usage;\n }\n\n if (content || reasoning_content) {\n accumulated += content;\n const chunkData: CodeGenerationChunk = {\n content,\n reasoning_content,\n accumulated,\n isComplete: false,\n usage: undefined,\n };\n options.onChunk!(chunkData);\n }\n\n // Check if stream is complete\n if (chunk.choices?.[0]?.finish_reason) {\n timeCost = Date.now() - startTime;\n\n // If usage is not available from the stream, provide a basic usage info\n if (!usage) {\n // Estimate token counts based on content length (rough approximation)\n const estimatedTokens = Math.max(\n 1,\n Math.floor(accumulated.length / 4),\n );\n usage = {\n prompt_tokens: estimatedTokens,\n completion_tokens: estimatedTokens,\n total_tokens: estimatedTokens * 2,\n };\n }\n\n // Send final chunk\n const finalChunk: CodeGenerationChunk = {\n content: '',\n accumulated,\n reasoning_content: '',\n isComplete: true,\n usage: {\n prompt_tokens: usage.prompt_tokens ?? 0,\n completion_tokens: usage.completion_tokens ?? 0,\n total_tokens: usage.total_tokens ?? 0,\n time_cost: timeCost ?? 0,\n model_name: modelName,\n model_description: modelDescription,\n intent: modelPreferences.intent,\n },\n };\n options.onChunk!(finalChunk);\n break;\n }\n }\n content = accumulated;\n debugProfileStats(\n `streaming model, ${modelName}, mode, ${vlLocateMode(modelPreferences) || 'default'}, cost-ms, ${timeCost}`,\n );\n } else {\n const result = await completion.create({\n model: modelName,\n messages,\n response_format: responseFormat,\n ...commonConfig,\n } as any);\n timeCost = Date.now() - startTime;\n\n debugProfileStats(\n `model, ${modelName}, mode, ${vlLocateMode(modelPreferences) || 'default'}, ui-tars-version, ${uiTarsModelVersion(modelPreferences)}, prompt-tokens, ${result.usage?.prompt_tokens || ''}, completion-tokens, ${result.usage?.completion_tokens || ''}, total-tokens, ${result.usage?.total_tokens || ''}, cost-ms, ${timeCost}, requestId, ${result._request_id || ''}`,\n );\n\n debugProfileDetail(\n `model usage detail: ${JSON.stringify(result.usage)}`,\n );\n\n assert(\n result.choices,\n `invalid response from LLM service: ${JSON.stringify(result)}`,\n );\n content = result.choices[0].message.content!;\n usage = result.usage;\n }\n\n debugCall(`response: ${content}`);\n assert(content, 'empty content');\n } else if (style === 'anthropic') {\n const convertImageContent = (content: any) => {\n if (content.type === 'image_url') {\n const imgBase64 = content.image_url.url;\n assert(imgBase64, 'image_url is required');\n const { mimeType, body } = parseBase64(content.image_url.url);\n return {\n source: {\n type: 'base64',\n media_type: mimeType,\n data: body,\n },\n type: 'image',\n };\n }\n return content;\n };\n\n if (isStreaming) {\n const stream = (await completion.create({\n model: modelName,\n system: 'You are a versatile professional in software UI automation',\n messages: messages.map((m) => ({\n role: 'user',\n content: Array.isArray(m.content)\n ? (m.content as any).map(convertImageContent)\n : m.content,\n })),\n response_format: responseFormat,\n ...commonConfig,\n } as any)) as any;\n\n for await (const chunk of stream) {\n const content = chunk.delta?.text || '';\n if (content) {\n accumulated += content;\n const chunkData: CodeGenerationChunk = {\n content,\n accumulated,\n reasoning_content: '',\n isComplete: false,\n usage: undefined,\n };\n options.onChunk!(chunkData);\n }\n\n // Check if stream is complete\n if (chunk.type === 'message_stop') {\n timeCost = Date.now() - startTime;\n const anthropicUsage = chunk.usage;\n\n // Send final chunk\n const finalChunk: CodeGenerationChunk = {\n content: '',\n accumulated,\n reasoning_content: '',\n isComplete: true,\n usage: anthropicUsage\n ? {\n prompt_tokens: anthropicUsage.input_tokens ?? 0,\n completion_tokens: anthropicUsage.output_tokens ?? 0,\n total_tokens:\n (anthropicUsage.input_tokens ?? 0) +\n (anthropicUsage.output_tokens ?? 0),\n time_cost: timeCost ?? 0,\n model_name: modelName,\n model_description: modelDescription,\n intent: modelPreferences.intent,\n }\n : undefined,\n };\n options.onChunk!(finalChunk);\n break;\n }\n }\n content = accumulated;\n } else {\n const result = await completion.create({\n model: modelName,\n system: 'You are a versatile professional in software UI automation',\n messages: messages.map((m) => ({\n role: 'user',\n content: Array.isArray(m.content)\n ? (m.content as any).map(convertImageContent)\n : m.content,\n })),\n response_format: responseFormat,\n ...commonConfig,\n } as any);\n timeCost = Date.now() - startTime;\n content = (result as any).content[0].text as string;\n usage = result.usage;\n }\n\n assert(content, 'empty content');\n }\n // Ensure we always have usage info for streaming responses\n if (isStreaming && !usage) {\n // Estimate token counts based on content length (rough approximation)\n const estimatedTokens = Math.max(\n 1,\n Math.floor((content || '').length / 4),\n );\n usage = {\n prompt_tokens: estimatedTokens,\n completion_tokens: estimatedTokens,\n total_tokens: estimatedTokens * 2,\n };\n }\n\n return {\n content: content || '',\n usage: usage\n ? {\n prompt_tokens: usage.prompt_tokens ?? 0,\n completion_tokens: usage.completion_tokens ?? 0,\n total_tokens: usage.total_tokens ?? 0,\n time_cost: timeCost ?? 0,\n model_name: modelName,\n model_description: modelDescription,\n intent: modelPreferences.intent,\n }\n : undefined,\n isStreamed: !!isStreaming,\n };\n } catch (e: any) {\n console.error(' call AI error', e);\n const newError = new Error(\n `failed to call ${isStreaming ? 'streaming ' : ''}AI model service: ${e.message}. Trouble shooting: https://midscenejs.com/model-provider.html`,\n {\n cause: e,\n },\n );\n throw newError;\n }\n}\n\nexport const getResponseFormat = (\n modelName: string,\n AIActionTypeValue: AIActionType,\n):\n | OpenAI.ChatCompletionCreateParams['response_format']\n | OpenAI.ResponseFormatJSONObject => {\n let responseFormat:\n | OpenAI.ChatCompletionCreateParams['response_format']\n | OpenAI.ResponseFormatJSONObject\n | undefined;\n\n if (modelName.includes('gpt-4')) {\n switch (AIActionTypeValue) {\n case AIActionType.ASSERT:\n responseFormat = assertSchema;\n break;\n case AIActionType.INSPECT_ELEMENT:\n responseFormat = locatorSchema;\n break;\n case AIActionType.PLAN:\n responseFormat = planSchema;\n break;\n case AIActionType.EXTRACT_DATA:\n case AIActionType.DESCRIBE_ELEMENT:\n responseFormat = { type: AIResponseFormat.JSON };\n break;\n }\n }\n\n // gpt-4o-2024-05-13 only supports json_object response format\n if (modelName === 'gpt-4o-2024-05-13') {\n responseFormat = { type: AIResponseFormat.JSON };\n }\n\n return responseFormat;\n};\n\nexport async function callToGetJSONObject<T>(\n messages: ChatCompletionMessageParam[],\n AIActionTypeValue: AIActionType,\n modelPreferences: IModelPreferences,\n): Promise<{ content: T; usage?: AIUsageInfo }> {\n const response = await call(messages, AIActionTypeValue, modelPreferences);\n assert(response, 'empty response');\n const jsonContent = safeParseJson(response.content, modelPreferences);\n return { content: jsonContent, usage: response.usage };\n}\n\nexport async function callAiFnWithStringResponse<T>(\n msgs: AIArgs,\n AIActionTypeValue: AIActionType,\n modelPreferences: IModelPreferences,\n): Promise<{ content: string; usage?: AIUsageInfo }> {\n const { content, usage } = await call(\n msgs,\n AIActionTypeValue,\n modelPreferences,\n );\n return { content, usage };\n}\n\nexport function extractJSONFromCodeBlock(response: string) {\n try {\n // First, try to match a JSON object directly in the response\n const jsonMatch = response.match(/^\\s*(\\{[\\s\\S]*\\})\\s*$/);\n if (jsonMatch) {\n return jsonMatch[1];\n }\n\n // If no direct JSON object is found, try to extract JSON from a code block\n const codeBlockMatch = response.match(\n /```(?:json)?\\s*(\\{[\\s\\S]*?\\})\\s*```/,\n );\n if (codeBlockMatch) {\n return codeBlockMatch[1];\n }\n\n // If no code block is found, try to find a JSON-like structure in the text\n const jsonLikeMatch = response.match(/\\{[\\s\\S]*\\}/);\n if (jsonLikeMatch) {\n return jsonLikeMatch[0];\n }\n } catch {}\n // If no JSON-like structure is found, return the original response\n return response;\n}\n\nexport function preprocessDoubaoBboxJson(input: string) {\n if (input.includes('bbox')) {\n // when its values like 940 445 969 490, replace all /\\d+\\s+\\d+/g with /$1,$2/g\n while (/\\d+\\s+\\d+/.test(input)) {\n input = input.replace(/(\\d+)\\s+(\\d+)/g, '$1,$2');\n }\n }\n return input;\n}\n\nexport function safeParseJson(\n input: string,\n modelPreferences: IModelPreferences,\n) {\n const cleanJsonString = extractJSONFromCodeBlock(input);\n // match the point\n if (cleanJsonString?.match(/\\((\\d+),(\\d+)\\)/)) {\n return cleanJsonString\n .match(/\\((\\d+),(\\d+)\\)/)\n ?.slice(1)\n .map(Number);\n }\n try {\n return JSON.parse(cleanJsonString);\n } catch {}\n try {\n return JSON.parse(jsonrepair(cleanJsonString));\n } catch (e) {}\n\n if (\n vlLocateMode(modelPreferences) === 'doubao-vision' ||\n vlLocateMode(modelPreferences) === 'vlm-ui-tars'\n ) {\n const jsonString = preprocessDoubaoBboxJson(cleanJsonString);\n return JSON.parse(jsonrepair(jsonString));\n }\n throw Error(`failed to parse json response: ${input}`);\n}\n"],"names":["createChatClient","AIActionTypeValue","modelPreferences","socksProxy","httpProxy","modelName","openaiBaseURL","openaiApiKey","openaiExtraConfig","openaiUseAzureDeprecated","useAzureOpenai","azureOpenaiScope","azureOpenaiKey","azureOpenaiEndpoint","azureOpenaiApiVersion","azureOpenaiDeployment","azureExtraConfig","useAnthropicSdk","anthropicApiKey","modelDescription","globalConfigManager","openai","proxyAgent","debugProxy","getDebug","HttpsProxyAgent","SocksProxyAgent","AzureOpenAI","tokenProvider","assert","ifInBrowser","credential","DefaultAzureCredential","getBearerTokenProvider","OpenAI","MIDSCENE_API_TYPE","MIDSCENE_LANGSMITH_DEBUG","Error","console","wrapOpenAI","Anthropic","call","messages","options","completion","style","responseFormat","getResponseFormat","maxTokens","OPENAI_MAX_TOKENS","debugCall","debugProfileStats","debugProfileDetail","startTime","Date","isStreaming","content","accumulated","usage","timeCost","commonConfig","vlLocateMode","Number","stream","chunk","_chunk_choices__delta","_chunk_choices__delta1","_chunk_choices_2","reasoning_content","chunkData","undefined","estimatedTokens","Math","finalChunk","_result_usage","_result_usage1","_result_usage2","result","uiTarsModelVersion","JSON","convertImageContent","imgBase64","mimeType","body","parseBase64","m","Array","_chunk_delta","anthropicUsage","e","newError","AIActionType","assertSchema","locatorSchema","planSchema","AIResponseFormat","callToGetJSONObject","response","jsonContent","safeParseJson","callAiFnWithStringResponse","msgs","extractJSONFromCodeBlock","jsonMatch","codeBlockMatch","jsonLikeMatch","preprocessDoubaoBboxJson","input","cleanJsonString","_cleanJsonString_match","jsonrepair","jsonString"],"mappings":"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"}
|
package/dist/es/device/index.mjs
CHANGED
|
@@ -1,20 +1,94 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
return {
|
|
4
|
-
click: async (x, y, options)=>{},
|
|
5
|
-
wheel: async (deltaX, deltaY)=>{},
|
|
6
|
-
move: async (x, y)=>{},
|
|
7
|
-
drag: async (from, to)=>{}
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
get keyboard() {
|
|
11
|
-
return {
|
|
12
|
-
type: async (text)=>{},
|
|
13
|
-
press: async (action)=>{}
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
async clearInput(element) {}
|
|
1
|
+
import { getMidsceneLocationSchema, z } from "../index.mjs";
|
|
2
|
+
class AbstractDevice {
|
|
17
3
|
}
|
|
18
|
-
|
|
4
|
+
const defineAction = (config)=>config;
|
|
5
|
+
const actionTapParamSchema = z.object({
|
|
6
|
+
locate: getMidsceneLocationSchema().describe('The element to be tapped')
|
|
7
|
+
});
|
|
8
|
+
const defineActionTap = (call)=>defineAction({
|
|
9
|
+
name: 'Tap',
|
|
10
|
+
description: 'Tap the element',
|
|
11
|
+
interfaceAlias: 'aiTap',
|
|
12
|
+
paramSchema: actionTapParamSchema,
|
|
13
|
+
call
|
|
14
|
+
});
|
|
15
|
+
const actionRightClickParamSchema = z.object({
|
|
16
|
+
locate: getMidsceneLocationSchema().describe('The element to be right clicked')
|
|
17
|
+
});
|
|
18
|
+
const defineActionRightClick = (call)=>defineAction({
|
|
19
|
+
name: 'RightClick',
|
|
20
|
+
description: 'Right click the element',
|
|
21
|
+
interfaceAlias: 'aiRightClick',
|
|
22
|
+
paramSchema: actionRightClickParamSchema,
|
|
23
|
+
call
|
|
24
|
+
});
|
|
25
|
+
const actionHoverParamSchema = z.object({
|
|
26
|
+
locate: getMidsceneLocationSchema().describe('The element to be hovered')
|
|
27
|
+
});
|
|
28
|
+
const defineActionHover = (call)=>defineAction({
|
|
29
|
+
name: 'Hover',
|
|
30
|
+
description: 'Move the mouse to the element',
|
|
31
|
+
interfaceAlias: 'aiHover',
|
|
32
|
+
paramSchema: actionHoverParamSchema,
|
|
33
|
+
call
|
|
34
|
+
});
|
|
35
|
+
const actionInputParamSchema = z.object({
|
|
36
|
+
value: z.string().describe('The value to be input'),
|
|
37
|
+
locate: getMidsceneLocationSchema().describe('The element to be input')
|
|
38
|
+
});
|
|
39
|
+
const defineActionInput = (call)=>defineAction({
|
|
40
|
+
name: 'Input',
|
|
41
|
+
description: 'Input the value into the element',
|
|
42
|
+
interfaceAlias: 'aiInput',
|
|
43
|
+
paramSchema: actionInputParamSchema,
|
|
44
|
+
call
|
|
45
|
+
});
|
|
46
|
+
const actionKeyboardPressParamSchema = z.object({
|
|
47
|
+
locate: getMidsceneLocationSchema().describe('The element to be clicked before pressing the key').optional(),
|
|
48
|
+
keyName: z.string().describe('The key to be pressed')
|
|
49
|
+
});
|
|
50
|
+
const defineActionKeyboardPress = (call)=>defineAction({
|
|
51
|
+
name: 'KeyboardPress',
|
|
52
|
+
description: 'Press a function key, like "Enter", "Tab", "Escape". Do not use this to type text.',
|
|
53
|
+
interfaceAlias: 'aiKeyboardPress',
|
|
54
|
+
paramSchema: actionKeyboardPressParamSchema,
|
|
55
|
+
call
|
|
56
|
+
});
|
|
57
|
+
const actionScrollParamSchema = z.object({
|
|
58
|
+
direction: z["enum"]([
|
|
59
|
+
'down',
|
|
60
|
+
'up',
|
|
61
|
+
'right',
|
|
62
|
+
'left'
|
|
63
|
+
]).default('down').describe('The direction to scroll'),
|
|
64
|
+
scrollType: z["enum"]([
|
|
65
|
+
'once',
|
|
66
|
+
'untilBottom',
|
|
67
|
+
'untilTop',
|
|
68
|
+
'untilRight',
|
|
69
|
+
'untilLeft'
|
|
70
|
+
]).default('once').describe('The scroll type'),
|
|
71
|
+
distance: z.number().nullable().optional().describe('The distance in pixels to scroll'),
|
|
72
|
+
locate: getMidsceneLocationSchema().optional().describe('The element to be scrolled')
|
|
73
|
+
});
|
|
74
|
+
const defineActionScroll = (call)=>defineAction({
|
|
75
|
+
name: 'Scroll',
|
|
76
|
+
description: 'Scroll the page or an element. The direction to scroll, the scroll type, and the distance to scroll. The distance is the number of pixels to scroll. If not specified, use `down` direction, `once` scroll type, and `null` distance.',
|
|
77
|
+
interfaceAlias: 'aiScroll',
|
|
78
|
+
paramSchema: actionScrollParamSchema,
|
|
79
|
+
call
|
|
80
|
+
});
|
|
81
|
+
const actionDragAndDropParamSchema = z.object({
|
|
82
|
+
from: getMidsceneLocationSchema().describe('The position to be dragged'),
|
|
83
|
+
to: getMidsceneLocationSchema().describe('The position to be dropped')
|
|
84
|
+
});
|
|
85
|
+
const defineActionDragAndDrop = (call)=>defineAction({
|
|
86
|
+
name: 'DragAndDrop',
|
|
87
|
+
description: 'Drag and drop the element',
|
|
88
|
+
interfaceAlias: 'aiDragAndDrop',
|
|
89
|
+
paramSchema: actionDragAndDropParamSchema,
|
|
90
|
+
call
|
|
91
|
+
});
|
|
92
|
+
export { AbstractDevice, actionDragAndDropParamSchema, actionHoverParamSchema, actionInputParamSchema, actionKeyboardPressParamSchema, actionRightClickParamSchema, actionScrollParamSchema, actionTapParamSchema, defineAction, defineActionDragAndDrop, defineActionHover, defineActionInput, defineActionKeyboardPress, defineActionRightClick, defineActionScroll, defineActionTap };
|
|
19
93
|
|
|
20
94
|
//# sourceMappingURL=index.mjs.map
|