@midscene/core 1.0.1-beta-20251024064637.0 → 1.0.1-beta-20251027034431.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/ui-utils.mjs +4 -1
- package/dist/es/agent/ui-utils.mjs.map +1 -1
- package/dist/es/agent/utils.mjs +1 -1
- package/dist/es/ai-model/prompt/llm-planning.mjs +111 -7
- package/dist/es/ai-model/prompt/llm-planning.mjs.map +1 -1
- package/dist/es/ai-model/service-caller/index.mjs +23 -31
- package/dist/es/ai-model/service-caller/index.mjs.map +1 -1
- package/dist/es/device/device-options.mjs +0 -0
- 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/ui-utils.js +4 -1
- package/dist/lib/agent/ui-utils.js.map +1 -1
- package/dist/lib/agent/utils.js +1 -1
- package/dist/lib/ai-model/prompt/llm-planning.js +111 -7
- package/dist/lib/ai-model/prompt/llm-planning.js.map +1 -1
- package/dist/lib/ai-model/service-caller/index.js +23 -31
- package/dist/lib/ai-model/service-caller/index.js.map +1 -1
- package/dist/lib/device/device-options.js +20 -0
- package/dist/lib/device/device-options.js.map +1 -0
- 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 +1 -1
- package/dist/types/device/device-options.d.ts +57 -0
- package/dist/types/device/index.d.ts +5 -4
- package/dist/types/types.d.ts +2 -7
- package/dist/types/yaml.d.ts +3 -5
- package/package.json +3 -3
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
function typeStr(task) {
|
|
2
|
-
|
|
2
|
+
if ('Insight' === task.type && ('Query' === task.subType || 'Assert' === task.subType)) return task.type;
|
|
3
|
+
if ('Action' === task.type && task.subType) return `Action Space / ${task.subType}`;
|
|
4
|
+
if (task.subType) return `${task.type} / ${task.subType}`;
|
|
5
|
+
return task.type;
|
|
3
6
|
}
|
|
4
7
|
function locateParamStr(locate) {
|
|
5
8
|
if (!locate) return '';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent/ui-utils.mjs","sources":["webpack://@midscene/core/./src/agent/ui-utils.ts"],"sourcesContent":["import type {\n DetailedLocateParam,\n ExecutionTask,\n ExecutionTaskAction,\n ExecutionTaskInsightAssertion,\n ExecutionTaskInsightLocate,\n ExecutionTaskInsightQuery,\n ExecutionTaskPlanning,\n PullParam,\n ScrollParam,\n} from '@/types';\n\nexport function typeStr(task: ExecutionTask) {\n
|
|
1
|
+
{"version":3,"file":"agent/ui-utils.mjs","sources":["webpack://@midscene/core/./src/agent/ui-utils.ts"],"sourcesContent":["import type {\n DetailedLocateParam,\n ExecutionTask,\n ExecutionTaskAction,\n ExecutionTaskInsightAssertion,\n ExecutionTaskInsightLocate,\n ExecutionTaskInsightQuery,\n ExecutionTaskPlanning,\n PullParam,\n ScrollParam,\n} from '@/types';\n\nexport function typeStr(task: ExecutionTask) {\n // For Insight tasks with Query or Assert subtypes, show just \"Insight\"\n if (\n task.type === 'Insight' &&\n (task.subType === 'Query' || task.subType === 'Assert')\n ) {\n return task.type;\n }\n\n // For Action tasks with subType, show \"Action Space / subType\"\n if (task.type === 'Action' && task.subType) {\n return `Action Space / ${task.subType}`;\n }\n\n // For all other cases with subType, show \"type / subType\"\n if (task.subType) {\n return `${task.type} / ${task.subType}`;\n }\n\n // No subType, just show type\n return task.type;\n}\n\nexport function locateParamStr(locate?: DetailedLocateParam | string): string {\n if (!locate) {\n return '';\n }\n\n if (typeof locate === 'string') {\n return locate;\n }\n\n if (typeof locate === 'object') {\n if (typeof locate.prompt === 'string') {\n return locate.prompt;\n }\n\n if (typeof locate.prompt === 'object' && locate.prompt.prompt) {\n const prompt = locate.prompt.prompt;\n const images = locate.prompt.images || [];\n\n if (images.length === 0) return prompt;\n\n const imagesStr = images\n .map((image) => {\n let url = image.url;\n if (\n url.startsWith('data:image/') ||\n (url.startsWith('data:') && url.includes('base64'))\n ) {\n url = `${url.substring(0, 15)}...`;\n }\n return `[${image.name}](${url})`;\n })\n .join(', ');\n\n return `${prompt}, ${imagesStr}`;\n }\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?: PullParam) {\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 locateParamStr((task as ExecutionTaskInsightLocate)?.param) ||\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\n if (typeof value === 'string') return value;\n\n if (typeof value === 'object' && locateParamStr(value as any)) {\n return locateParamStr(value as any);\n }\n\n return JSON.stringify(value, undefined, 2);\n}\n"],"names":["typeStr","task","locateParamStr","locate","prompt","images","imagesStr","image","url","scrollParamStr","scrollParam","pullParamStr","pullParam","parts","taskTitleStr","type","paramStr","value","_task_param","_task_param1","_task_param2","_task_param3","_task_param4","_task_param5","_task_param6","locateStr","_task_param7","_task_param8","JSON","undefined"],"mappings":"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"}
|
package/dist/es/agent/utils.mjs
CHANGED
|
@@ -99,7 +99,7 @@ async function matchElementFromCache(context, cacheEntry, cachePrompt, cacheable
|
|
|
99
99
|
return;
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
|
-
const getMidsceneVersion = ()=>"1.0.1-beta-
|
|
102
|
+
const getMidsceneVersion = ()=>"1.0.1-beta-20251027034431.0";
|
|
103
103
|
const parsePrompt = (prompt)=>{
|
|
104
104
|
if ('string' == typeof prompt) return {
|
|
105
105
|
textPrompt: prompt,
|
|
@@ -23,37 +23,126 @@ const descriptionForAction = (action, locatorSchemaTypeDescription)=>{
|
|
|
23
23
|
if ('ZodEffects' === typeName) {
|
|
24
24
|
if (f._def.schema) return unwrapField(f._def.schema);
|
|
25
25
|
}
|
|
26
|
+
if ('ZodPipeline' === typeName) {
|
|
27
|
+
if (f._def.out) return unwrapField(f._def.out);
|
|
28
|
+
}
|
|
29
|
+
if ('ZodCatch' === typeName) {
|
|
30
|
+
if (f._def.innerType) return unwrapField(f._def.innerType);
|
|
31
|
+
}
|
|
32
|
+
if ('ZodBranded' === typeName) {
|
|
33
|
+
if (f._def.type) return unwrapField(f._def.type);
|
|
34
|
+
}
|
|
35
|
+
if ('ZodReadonly' === typeName) {
|
|
36
|
+
if (f._def.innerType) return unwrapField(f._def.innerType);
|
|
37
|
+
}
|
|
26
38
|
return f;
|
|
27
39
|
};
|
|
28
40
|
const actualField = unwrapField(field);
|
|
29
41
|
const fieldTypeName = null == (_actualField__def = actualField._def) ? void 0 : _actualField__def.typeName;
|
|
42
|
+
if ('ZodEffects' === fieldTypeName) {
|
|
43
|
+
var _actualField__def1;
|
|
44
|
+
if (null == (_actualField__def1 = actualField._def) ? void 0 : _actualField__def1.schema) return getTypeName(actualField._def.schema);
|
|
45
|
+
}
|
|
30
46
|
if ('ZodString' === fieldTypeName) return 'string';
|
|
31
47
|
if ('ZodNumber' === fieldTypeName) return 'number';
|
|
32
48
|
if ('ZodBoolean' === fieldTypeName) return 'boolean';
|
|
33
|
-
if ('
|
|
49
|
+
if ('ZodDate' === fieldTypeName) return 'Date';
|
|
50
|
+
if ('ZodBigInt' === fieldTypeName) return 'bigint';
|
|
51
|
+
if ('ZodNull' === fieldTypeName) return 'null';
|
|
52
|
+
if ('ZodUndefined' === fieldTypeName) return 'undefined';
|
|
53
|
+
if ('ZodAny' === fieldTypeName) return 'any';
|
|
54
|
+
if ('ZodUnknown' === fieldTypeName) return 'unknown';
|
|
55
|
+
if ('ZodVoid' === fieldTypeName) return 'void';
|
|
56
|
+
if ('ZodArray' === fieldTypeName) {
|
|
57
|
+
var _actualField__def2;
|
|
58
|
+
const itemType = null == (_actualField__def2 = actualField._def) ? void 0 : _actualField__def2.type;
|
|
59
|
+
if (itemType) return `${getTypeName(itemType)}[]`;
|
|
60
|
+
return 'array';
|
|
61
|
+
}
|
|
34
62
|
if ('ZodObject' === fieldTypeName) {
|
|
35
63
|
if (ifMidsceneLocatorField(actualField)) return locatorSchemaTypeDescription;
|
|
36
64
|
return 'object';
|
|
37
65
|
}
|
|
66
|
+
if ('ZodTuple' === fieldTypeName) {
|
|
67
|
+
var _actualField__def3;
|
|
68
|
+
const items = null == (_actualField__def3 = actualField._def) ? void 0 : _actualField__def3.items;
|
|
69
|
+
if (items && items.length > 0) {
|
|
70
|
+
const itemTypes = items.map((item)=>getTypeName(item));
|
|
71
|
+
return `[${itemTypes.join(', ')}]`;
|
|
72
|
+
}
|
|
73
|
+
return 'tuple';
|
|
74
|
+
}
|
|
75
|
+
if ('ZodRecord' === fieldTypeName) {
|
|
76
|
+
var _actualField__def4;
|
|
77
|
+
const valueType = null == (_actualField__def4 = actualField._def) ? void 0 : _actualField__def4.valueType;
|
|
78
|
+
if (valueType) return `Record<string, ${getTypeName(valueType)}>`;
|
|
79
|
+
return 'Record';
|
|
80
|
+
}
|
|
81
|
+
if ('ZodLiteral' === fieldTypeName) {
|
|
82
|
+
var _actualField__def5;
|
|
83
|
+
const value = null == (_actualField__def5 = actualField._def) ? void 0 : _actualField__def5.value;
|
|
84
|
+
if (void 0 !== value) return 'string' == typeof value ? `'${value}'` : String(value);
|
|
85
|
+
return 'literal';
|
|
86
|
+
}
|
|
38
87
|
if ('ZodEnum' === fieldTypeName) {
|
|
39
|
-
var _actualField__def_values,
|
|
40
|
-
const values = (null == (
|
|
88
|
+
var _actualField__def_values, _actualField__def6;
|
|
89
|
+
const values = (null == (_actualField__def6 = actualField._def) ? void 0 : null == (_actualField__def_values = _actualField__def6.values) ? void 0 : _actualField__def_values.map((option)=>String(`'${option}'`)).join(', ')) ?? 'enum';
|
|
41
90
|
return `enum(${values})`;
|
|
42
91
|
}
|
|
92
|
+
if ('ZodNativeEnum' === fieldTypeName) return 'nativeEnum';
|
|
43
93
|
if ('ZodUnion' === fieldTypeName) {
|
|
44
|
-
var
|
|
45
|
-
const options = null == (
|
|
94
|
+
var _actualField__def7;
|
|
95
|
+
const options = null == (_actualField__def7 = actualField._def) ? void 0 : _actualField__def7.options;
|
|
46
96
|
if (options && options.length > 0) {
|
|
47
97
|
const types = options.map((opt)=>getTypeName(opt));
|
|
48
98
|
return types.join(' | ');
|
|
49
99
|
}
|
|
50
100
|
return 'union';
|
|
51
101
|
}
|
|
102
|
+
if ('ZodDiscriminatedUnion' === fieldTypeName) return 'discriminatedUnion';
|
|
103
|
+
if ('ZodIntersection' === fieldTypeName) {
|
|
104
|
+
var _actualField__def8, _actualField__def9;
|
|
105
|
+
const left = null == (_actualField__def8 = actualField._def) ? void 0 : _actualField__def8.left;
|
|
106
|
+
const right = null == (_actualField__def9 = actualField._def) ? void 0 : _actualField__def9.right;
|
|
107
|
+
if (left && right) return `${getTypeName(left)} & ${getTypeName(right)}`;
|
|
108
|
+
return 'intersection';
|
|
109
|
+
}
|
|
110
|
+
if ('ZodPromise' === fieldTypeName) {
|
|
111
|
+
var _actualField__def10;
|
|
112
|
+
const innerType = null == (_actualField__def10 = actualField._def) ? void 0 : _actualField__def10.type;
|
|
113
|
+
if (innerType) return `Promise<${getTypeName(innerType)}>`;
|
|
114
|
+
return 'Promise';
|
|
115
|
+
}
|
|
116
|
+
if ('ZodLazy' === fieldTypeName) return 'lazy';
|
|
117
|
+
if ('ZodPipeline' === fieldTypeName) {
|
|
118
|
+
var _actualField__def11;
|
|
119
|
+
const out = null == (_actualField__def11 = actualField._def) ? void 0 : _actualField__def11.out;
|
|
120
|
+
if (out) return getTypeName(out);
|
|
121
|
+
return 'pipeline';
|
|
122
|
+
}
|
|
123
|
+
if ('ZodCatch' === fieldTypeName) {
|
|
124
|
+
var _actualField__def12;
|
|
125
|
+
const innerType = null == (_actualField__def12 = actualField._def) ? void 0 : _actualField__def12.innerType;
|
|
126
|
+
if (innerType) return getTypeName(innerType);
|
|
127
|
+
return 'catch';
|
|
128
|
+
}
|
|
129
|
+
if ('ZodBranded' === fieldTypeName) {
|
|
130
|
+
var _actualField__def13;
|
|
131
|
+
const innerType = null == (_actualField__def13 = actualField._def) ? void 0 : _actualField__def13.type;
|
|
132
|
+
if (innerType) return getTypeName(innerType);
|
|
133
|
+
return 'branded';
|
|
134
|
+
}
|
|
135
|
+
if ('ZodReadonly' === fieldTypeName) {
|
|
136
|
+
var _actualField__def14;
|
|
137
|
+
const innerType = null == (_actualField__def14 = actualField._def) ? void 0 : _actualField__def14.innerType;
|
|
138
|
+
if (innerType) return `Readonly<${getTypeName(innerType)}>`;
|
|
139
|
+
return 'readonly';
|
|
140
|
+
}
|
|
52
141
|
console.warn('failed to parse Zod type. This may lead to wrong params from the LLM.\n', actualField._def);
|
|
53
142
|
return actualField.toString();
|
|
54
143
|
};
|
|
55
144
|
const getDescription = (field)=>{
|
|
56
|
-
var _actualField__def;
|
|
145
|
+
var _actualField__def, _actualField__def1, _actualField__def2;
|
|
57
146
|
const unwrapField = (f)=>{
|
|
58
147
|
if (!f._def) return f;
|
|
59
148
|
const typeName = f._def.typeName;
|
|
@@ -61,12 +150,27 @@ const descriptionForAction = (action, locatorSchemaTypeDescription)=>{
|
|
|
61
150
|
if ('ZodEffects' === typeName) {
|
|
62
151
|
if (f._def.schema) return unwrapField(f._def.schema);
|
|
63
152
|
}
|
|
153
|
+
if ('ZodPipeline' === typeName) {
|
|
154
|
+
if (f._def.out) return unwrapField(f._def.out);
|
|
155
|
+
}
|
|
156
|
+
if ('ZodCatch' === typeName) {
|
|
157
|
+
if (f._def.innerType) return unwrapField(f._def.innerType);
|
|
158
|
+
}
|
|
159
|
+
if ('ZodBranded' === typeName) {
|
|
160
|
+
if (f._def.type) return unwrapField(f._def.type);
|
|
161
|
+
}
|
|
162
|
+
if ('ZodReadonly' === typeName) {
|
|
163
|
+
if (f._def.innerType) return unwrapField(f._def.innerType);
|
|
164
|
+
}
|
|
64
165
|
return f;
|
|
65
166
|
};
|
|
66
167
|
if ("description" in field) return field.description || null;
|
|
67
168
|
const actualField = unwrapField(field);
|
|
68
169
|
if ("description" in actualField) return actualField.description || null;
|
|
69
|
-
if ((null == (_actualField__def = actualField._def) ? void 0 : _actualField__def.typeName) === '
|
|
170
|
+
if ((null == (_actualField__def = actualField._def) ? void 0 : _actualField__def.typeName) === 'ZodEffects' && (null == (_actualField__def1 = actualField._def) ? void 0 : _actualField__def1.schema)) {
|
|
171
|
+
if ("description" in actualField._def.schema) return actualField._def.schema.description || null;
|
|
172
|
+
}
|
|
173
|
+
if ((null == (_actualField__def2 = actualField._def) ? void 0 : _actualField__def2.typeName) === 'ZodObject') {
|
|
70
174
|
if ('midscene_location_field_flag' in actualField._def.shape()) return 'Location information for the target element';
|
|
71
175
|
}
|
|
72
176
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-model/prompt/llm-planning.mjs","sources":["webpack://@midscene/core/./src/ai-model/prompt/llm-planning.ts"],"sourcesContent":["import type { DeviceAction } from '@/types';\nimport type { TVlModeTypes } from '@midscene/shared/env';\nimport type { ResponseFormatJSONSchema } from 'openai/resources/index';\nimport type { ZodObject, z } from 'zod';\nimport { ifMidsceneLocatorField } from '../common';\nimport { bboxDescription } from './common';\n\n// Note: put the log field first to trigger the CoT\n\nconst vlCurrentLog = `\"log\": string, // Log your thoughts and what the next one action (ONLY ONE!) you can do according to the screenshot and the instruction. The log should contain the following information: \"The user wants to do ... . According to the instruction and the previous logs, next step is to .... Now i am going to compose an action '{ action-type }' to do ....\". If no action should be done, log the reason. Use the same language as the user's instruction.`;\nconst llmCurrentLog = `\"log\": string, // Log what the next actions you can do according to the screenshot and the instruction. The typical log looks like \"Now i want to use action '{ action-type }' to do ..\". If no action should be done, log the reason. \". Use the same language as the user's instruction.`;\n\nconst commonOutputFields = `\"error\"?: string, // Error messages about unexpected situations, if any. Only think it is an error when the situation is not foreseeable according to the instruction. Use the same language as the user's instruction.\n \"more_actions_needed_by_instruction\": boolean, // Consider if there is still more action(s) to do after the action in \"Log\" is done, according to the instruction. If so, set this field to true. Otherwise, set it to false.`;\nconst vlLocateParam = () =>\n '{bbox: [number, number, number, number], prompt: string }';\nconst llmLocateParam = () => '{\"id\": string, \"prompt\": string}';\n\nexport const descriptionForAction = (\n action: DeviceAction<any>,\n locatorSchemaTypeDescription: string,\n) => {\n const tab = ' ';\n const fields: string[] = [];\n\n // Add the action type field\n fields.push(`- type: \"${action.name}\"`);\n\n // Handle paramSchema if it exists\n if (action.paramSchema) {\n // Try to extract parameter information from the zod schema\n // For zod object schemas, extract type information and descriptions\n const shape = (action.paramSchema as ZodObject<any>).shape;\n\n if (!shape) {\n console.warn(\n `action.paramSchema is not a ZodObject, may lead to unexpected behavior, action name: ${action.name}`,\n );\n }\n\n const paramLines: string[] = [];\n\n // Helper function to get type name from zod schema\n const getTypeName = (field: any): string => {\n // Recursively unwrap optional, nullable, and other wrapper types to get the actual inner type\n const unwrapField = (f: any): any => {\n if (!f._def) return f;\n\n const typeName = f._def.typeName;\n\n // Handle wrapper types that have innerType\n if (\n typeName === 'ZodOptional' ||\n typeName === 'ZodNullable' ||\n typeName === 'ZodDefault'\n ) {\n return unwrapField(f._def.innerType);\n }\n\n // Handle ZodEffects (transformations, refinements, preprocessors)\n if (typeName === 'ZodEffects') {\n // For ZodEffects, unwrap the schema field which contains the underlying type\n if (f._def.schema) {\n return unwrapField(f._def.schema);\n }\n }\n\n return f;\n };\n\n const actualField = unwrapField(field);\n const fieldTypeName = actualField._def?.typeName;\n\n if (fieldTypeName === 'ZodString') return 'string';\n if (fieldTypeName === 'ZodNumber') return 'number';\n if (fieldTypeName === 'ZodBoolean') return 'boolean';\n if (fieldTypeName === 'ZodArray') return 'array';\n if (fieldTypeName === 'ZodObject') {\n // Check if this is a passthrough object (like MidsceneLocation)\n if (ifMidsceneLocatorField(actualField)) {\n return locatorSchemaTypeDescription;\n }\n return 'object';\n }\n if (fieldTypeName === 'ZodEnum') {\n const values =\n (actualField._def?.values as unknown[] | undefined)\n ?.map((option: unknown) => String(`'${option}'`))\n .join(', ') ?? 'enum';\n\n return `enum(${values})`;\n }\n // Handle ZodUnion by taking the first option (for display purposes)\n if (fieldTypeName === 'ZodUnion') {\n const options = actualField._def?.options as any[] | undefined;\n if (options && options.length > 0) {\n // For unions, list all types\n const types = options.map((opt: any) => getTypeName(opt));\n return types.join(' | ');\n }\n return 'union';\n }\n\n console.warn(\n 'failed to parse Zod type. This may lead to wrong params from the LLM.\\n',\n actualField._def,\n );\n return actualField.toString();\n };\n\n // Helper function to get description from zod schema\n const getDescription = (field: z.ZodTypeAny): string | null => {\n // Recursively unwrap optional, nullable, and other wrapper types to get the actual inner type\n const unwrapField = (f: any): any => {\n if (!f._def) return f;\n\n const typeName = f._def.typeName;\n\n // Handle wrapper types that have innerType\n if (\n typeName === 'ZodOptional' ||\n typeName === 'ZodNullable' ||\n typeName === 'ZodDefault'\n ) {\n return unwrapField(f._def.innerType);\n }\n\n // Handle ZodEffects (transformations, refinements, preprocessors)\n if (typeName === 'ZodEffects') {\n // For ZodEffects, unwrap the schema field which contains the underlying type\n if (f._def.schema) {\n return unwrapField(f._def.schema);\n }\n }\n\n return f;\n };\n\n // Check for direct description on the original field (wrapper may have description)\n if ('description' in field) {\n return field.description || null;\n }\n\n const actualField = unwrapField(field);\n\n // Check for description on the unwrapped field\n if ('description' in actualField) {\n return actualField.description || null;\n }\n\n // Check for MidsceneLocation fields and add description\n if (actualField._def?.typeName === 'ZodObject') {\n if ('midscene_location_field_flag' in actualField._def.shape()) {\n return 'Location information for the target element';\n }\n }\n\n return null;\n };\n\n for (const [key, field] of Object.entries(shape)) {\n if (field && typeof field === 'object') {\n // Check if field is optional\n const isOptional =\n typeof (field as any).isOptional === 'function' &&\n (field as any).isOptional();\n const keyWithOptional = isOptional ? `${key}?` : key;\n\n // Get the type name\n const typeName = getTypeName(field);\n\n // Get description\n const description = getDescription(field as z.ZodTypeAny);\n\n // Build param line for this field\n let paramLine = `${keyWithOptional}: ${typeName}`;\n if (description) {\n paramLine += ` // ${description}`;\n }\n\n paramLines.push(paramLine);\n }\n }\n\n if (paramLines.length > 0) {\n fields.push('- param:');\n for (const paramLine of paramLines) {\n fields.push(` - ${paramLine}`);\n }\n }\n }\n\n return `- ${action.name}, ${action.description || 'No description provided'}\n${tab}${fields.join(`\\n${tab}`)}\n`.trim();\n};\n\nconst systemTemplateOfVLPlanning = ({\n actionSpace,\n vlMode,\n}: {\n actionSpace: DeviceAction<any>[];\n vlMode: TVlModeTypes | undefined;\n}) => {\n const actionNameList = actionSpace.map((action) => action.name).join(', ');\n const actionDescriptionList = actionSpace.map((action) => {\n return descriptionForAction(action, vlLocateParam());\n });\n const actionList = actionDescriptionList.join('\\n');\n\n return `\nTarget: User will give you a latest screenshot, an instruction and some previous logs indicating what have been done. Please tell what the next one action is (or null if no action should be done) to do the tasks the instruction requires. \n\nRestriction:\n- Don't give extra actions or plans beyond the instruction. ONLY plan for what the instruction requires. For example, don't try to submit the form if the instruction is only to fill something.\n- Always give ONLY ONE action in \\`log\\` field (or null if no action should be done), instead of multiple actions. Supported actions are ${actionNameList}.\n- Don't repeat actions in the previous logs.\n- Bbox is the bounding box of the element to be located. It's an array of 4 numbers, representing ${bboxDescription(vlMode)}.\n\nSupporting actions:\n${actionList}\n\nField description:\n* The \\`prompt\\` field inside the \\`locate\\` field is a short description that could be used to locate the element.\n\nReturn in JSON format:\n{\n ${vlCurrentLog}\n ${commonOutputFields}\n \"action\": \n {\n // one of the supporting actions\n } | null,\n ,\n \"sleep\"?: number, // The sleep time after the action, in milliseconds.\n}\n\nFor example, when the instruction is \"click 'Confirm' button, and click 'Yes' in popup\" and the previous log shows \"The 'Confirm' button has been clicked\", by viewing the screenshot and previous logs, you should consider: We have already clicked the 'Confirm' button, so next we should find and click 'Yes' in popup.\n\nthis and output the JSON:\n\n{\n \"log\": \"The user wants to do click 'Confirm' button, and click 'Yes' in popup. According to the instruction and the previous logs, next step is to tap the 'Yes' button in the popup. Now i am going to compose an action 'Tap' to click 'Yes' in popup.\",\n \"action\": {\n \"type\": \"Tap\",\n \"param\": {\n \"locate\": {\n \"bbox\": [100, 100, 200, 200],\n \"prompt\": \"The 'Yes' button in popup\"\n }\n }\n },\n \"more_actions_needed_by_instruction\": false,\n}\n`;\n};\n\nconst systemTemplateOfLLM = ({\n actionSpace,\n}: { actionSpace: DeviceAction<any>[] }) => {\n const actionNameList = actionSpace.map((action) => action.name).join(' / ');\n const actionDescriptionList = actionSpace.map((action) => {\n return descriptionForAction(action, llmLocateParam());\n });\n const actionList = actionDescriptionList.join('\\n');\n\n return `\n## Role\n\nYou are a versatile professional in software UI automation. Your outstanding contributions will impact the user experience of billions of users.\n\n## Objective\n\n- Decompose the instruction user asked into a series of actions\n- Locate the target element if possible\n- If the instruction cannot be accomplished, give a further plan.\n\n## Workflow\n\n1. Receive the screenshot, element description of screenshot(if any), user's instruction and previous logs.\n2. Decompose the user's task into a sequence of feasible actions, and place it in the \\`actions\\` field. There are different types of actions (${actionNameList}). The \"About the action\" section below will give you more details.\n3. Consider whether the user's instruction will be accomplished after the actions you composed.\n- If the instruction is accomplished, set \\`more_actions_needed_by_instruction\\` to false.\n- If more actions are needed, set \\`more_actions_needed_by_instruction\\` to true. Get ready to hand over to the next talent people like you. Carefully log what have been done in the \\`log\\` field, he or she will continue the task according to your logs.\n4. If the task is not feasible on this page, set \\`error\\` field to the reason.\n\n## Constraints\n\n- All the actions you composed MUST be feasible, which means all the action fields can be filled with the page context information you get. If not, don't plan this action.\n- Trust the \"What have been done\" field about the task (if any), don't repeat actions in it.\n- Respond only with valid JSON. Do not write an introduction or summary or markdown prefix like \\`\\`\\`json\\`\\`\\`.\n- If the screenshot and the instruction are totally irrelevant, set reason in the \\`error\\` field.\n\n## About the \\`actions\\` field\n\nThe \\`locate\\` param is commonly used in the \\`param\\` field of the action, means to locate the target element to perform the action, it conforms to the following scheme:\n\ntype LocateParam = {\n \"id\": string, // the id of the element found. It should either be the id marked with a rectangle in the screenshot or the id described in the description.\n \"prompt\"?: string // the description of the element to find. It can only be omitted when locate is null.\n} | null // If it's not on the page, the LocateParam should be null\n\n## Supported actions\n\nEach action has a \\`type\\` and corresponding \\`param\\`. To be detailed:\n${actionList}\n\n`.trim();\n};\n\nconst outputTemplate = `\n## Output JSON Format:\n\nThe JSON format is as follows:\n\n{\n \"actions\": [\n // ... some actions\n ],\n ${llmCurrentLog}\n ${commonOutputFields}\n}\n\n## Examples\n\n### Example: Decompose a task\n\nWhen you received the following information:\n\n* Instruction: 'Click the language switch button, wait 1s, click \"English\"'\n* Logs: null\n* Page Context (screenshot and description) shows: There is a language switch button, and the \"English\" option is not shown in the screenshot now.\n\nBy viewing the page screenshot and description, you should consider this and output the JSON:\n\n* The user intent is: tap the switch button, sleep, and tap the 'English' option\n* The language switch button is shown in the screenshot, and can be located by the page description or the id marked with a rectangle. So we can plan a Tap action to do this.\n* Plan a Sleep action to wait for 1 second to ensure the language options are displayed.\n* The \"English\" option button is not shown in the screenshot now, it means it may only show after the previous actions are finished. So don't plan any action to do this.\n* Compose the log: The user wants to do click the language switch button, wait 1s, click \"English\". According to the instruction and the previous logs, next step is to tap the language switch button to open the language options. Now i am going to compose an action 'Tap' to click the language switch button.\n* The task cannot be accomplished (because the last tapping action is not finished yet), so the \\`more_actions_needed_by_instruction\\` field is true. The \\`error\\` field is null.\n\n{\n \"actions\":[\n {\n \"thought\": \"Click the language switch button to open the language options.\",\n \"type\": \"Tap\", \n \"param\": {\n \"locate\": { id: \"c81c4e9a33\", prompt: \"The language switch button\" }\n }\n },\n {\n \"thought\": \"Wait for 1 second to ensure the language options are displayed.\",\n \"type\": \"Sleep\",\n \"param\": { \"timeMs\": 1000 },\n }\n ],\n \"error\": null,\n \"more_actions_needed_by_instruction\": true,\n \"log\": \"The user wants to do click the language switch button, wait 1s, click \\\"English\\\". According to the instruction and the previous logs, next step is to tap the language switch button to open the language options. Now i am going to compose an action 'Tap' to click the language switch button.\",\n}\n\n### Example: What NOT to do\nWrong output:\n{\n \"actions\":[\n {\n \"thought\": \"Click the language switch button to open the language options.\",\n \"type\": \"Tap\",\n \"param\": {\n \"locate\": { \"id\": \"c81c4e9a33\" } // WRONG: prompt is missing, this is not a valid LocateParam\n }\n },\n {\n \"thought\": \"Click the English option\",\n \"type\": \"Tap\", \n \"param\": {\n \"locate\": null // WRONG: if the element is not on the page, you should not plan this action\n }\n }\n ],\n \"more_actions_needed_by_instruction\": false, // WRONG: should be true\n \"log\": \"The user wants to do click the language switch button, wait 1s, click \\\"English\\\". According to the instruction and the previous logs, next step is to tap the language switch button to open the language options. Now i am going to compose an action 'Tap' to click the language switch button.\",\n}\n`;\n\nexport async function systemPromptToTaskPlanning({\n actionSpace,\n vlMode,\n}: {\n actionSpace: DeviceAction<any>[];\n vlMode: TVlModeTypes | undefined;\n}) {\n if (vlMode) {\n return systemTemplateOfVLPlanning({ actionSpace, vlMode });\n }\n\n return `${systemTemplateOfLLM({ actionSpace })}\\n\\n${outputTemplate}`;\n}\n\nexport const planSchema: ResponseFormatJSONSchema = {\n type: 'json_schema',\n json_schema: {\n name: 'action_items',\n strict: false,\n schema: {\n type: 'object',\n strict: false,\n properties: {\n actions: {\n type: 'array',\n items: {\n type: 'object',\n strict: false,\n properties: {\n thought: {\n type: 'string',\n description:\n 'Reasons for generating this task, and why this task is feasible on this page',\n },\n type: {\n type: 'string',\n description: 'Type of action',\n },\n param: {\n anyOf: [\n { type: 'null' },\n {\n type: 'object',\n additionalProperties: true,\n },\n ],\n description: 'Parameter of the action',\n },\n locate: {\n type: ['object', 'null'],\n properties: {\n id: { type: 'string' },\n prompt: { type: 'string' },\n },\n required: ['id', 'prompt'],\n additionalProperties: false,\n description: 'Location information for the target element',\n },\n },\n required: ['thought', 'type', 'param', 'locate'],\n additionalProperties: false,\n },\n description: 'List of actions to be performed',\n },\n more_actions_needed_by_instruction: {\n type: 'boolean',\n description:\n 'If all the actions described in the instruction have been covered by this action and logs, set this field to false.',\n },\n log: {\n type: 'string',\n description:\n 'Log what these planned actions do. Do not include further actions that have not been planned.',\n },\n error: {\n type: ['string', 'null'],\n description: 'Error messages about unexpected situations',\n },\n },\n required: [\n 'actions',\n 'more_actions_needed_by_instruction',\n 'log',\n 'error',\n ],\n additionalProperties: false,\n },\n },\n};\n"],"names":["vlCurrentLog","llmCurrentLog","commonOutputFields","vlLocateParam","llmLocateParam","descriptionForAction","action","locatorSchemaTypeDescription","tab","fields","shape","console","paramLines","getTypeName","field","_actualField__def","unwrapField","f","typeName","actualField","fieldTypeName","ifMidsceneLocatorField","_actualField__def_values","values","option","String","_actualField__def2","options","types","opt","getDescription","key","Object","isOptional","keyWithOptional","description","paramLine","systemTemplateOfVLPlanning","actionSpace","vlMode","actionNameList","actionDescriptionList","actionList","bboxDescription","systemTemplateOfLLM","outputTemplate","systemPromptToTaskPlanning","planSchema"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ai-model/prompt/llm-planning.mjs","sources":["webpack://@midscene/core/./src/ai-model/prompt/llm-planning.ts"],"sourcesContent":["import type { DeviceAction } from '@/types';\nimport type { TVlModeTypes } from '@midscene/shared/env';\nimport type { ResponseFormatJSONSchema } from 'openai/resources/index';\nimport type { ZodObject, z } from 'zod';\nimport { ifMidsceneLocatorField } from '../common';\nimport { bboxDescription } from './common';\n\n// Note: put the log field first to trigger the CoT\n\nconst vlCurrentLog = `\"log\": string, // Log your thoughts and what the next one action (ONLY ONE!) you can do according to the screenshot and the instruction. The log should contain the following information: \"The user wants to do ... . According to the instruction and the previous logs, next step is to .... Now i am going to compose an action '{ action-type }' to do ....\". If no action should be done, log the reason. Use the same language as the user's instruction.`;\nconst llmCurrentLog = `\"log\": string, // Log what the next actions you can do according to the screenshot and the instruction. The typical log looks like \"Now i want to use action '{ action-type }' to do ..\". If no action should be done, log the reason. \". Use the same language as the user's instruction.`;\n\nconst commonOutputFields = `\"error\"?: string, // Error messages about unexpected situations, if any. Only think it is an error when the situation is not foreseeable according to the instruction. Use the same language as the user's instruction.\n \"more_actions_needed_by_instruction\": boolean, // Consider if there is still more action(s) to do after the action in \"Log\" is done, according to the instruction. If so, set this field to true. Otherwise, set it to false.`;\nconst vlLocateParam = () =>\n '{bbox: [number, number, number, number], prompt: string }';\nconst llmLocateParam = () => '{\"id\": string, \"prompt\": string}';\n\nexport const descriptionForAction = (\n action: DeviceAction<any>,\n locatorSchemaTypeDescription: string,\n) => {\n const tab = ' ';\n const fields: string[] = [];\n\n // Add the action type field\n fields.push(`- type: \"${action.name}\"`);\n\n // Handle paramSchema if it exists\n if (action.paramSchema) {\n // Try to extract parameter information from the zod schema\n // For zod object schemas, extract type information and descriptions\n const shape = (action.paramSchema as ZodObject<any>).shape;\n\n if (!shape) {\n console.warn(\n `action.paramSchema is not a ZodObject, may lead to unexpected behavior, action name: ${action.name}`,\n );\n }\n\n const paramLines: string[] = [];\n\n // Helper function to get type name from zod schema\n const getTypeName = (field: any): string => {\n // Recursively unwrap optional, nullable, and other wrapper types to get the actual inner type\n const unwrapField = (f: any): any => {\n if (!f._def) return f;\n\n const typeName = f._def.typeName;\n\n // Handle wrapper types that have innerType\n if (\n typeName === 'ZodOptional' ||\n typeName === 'ZodNullable' ||\n typeName === 'ZodDefault'\n ) {\n return unwrapField(f._def.innerType);\n }\n\n // Handle ZodEffects (transformations, refinements, preprocessors)\n if (typeName === 'ZodEffects') {\n // For ZodEffects, unwrap the schema field which contains the underlying type\n if (f._def.schema) {\n return unwrapField(f._def.schema);\n }\n }\n\n // Handle additional wrapper types\n if (typeName === 'ZodPipeline') {\n // For pipeline, unwrap the output type\n if (f._def.out) {\n return unwrapField(f._def.out);\n }\n }\n\n if (typeName === 'ZodCatch') {\n // For catch, unwrap the inner type\n if (f._def.innerType) {\n return unwrapField(f._def.innerType);\n }\n }\n\n if (typeName === 'ZodBranded') {\n // For branded, unwrap the base type\n if (f._def.type) {\n return unwrapField(f._def.type);\n }\n }\n\n if (typeName === 'ZodReadonly') {\n // For readonly, unwrap the inner type\n if (f._def.innerType) {\n return unwrapField(f._def.innerType);\n }\n }\n\n return f;\n };\n\n const actualField = unwrapField(field);\n const fieldTypeName = actualField._def?.typeName;\n\n // Handle ZodEffects explicitly before other types\n // This ensures transform/refine/preprocess wrappers are properly unwrapped\n if (fieldTypeName === 'ZodEffects') {\n if (actualField._def?.schema) {\n return getTypeName(actualField._def.schema);\n }\n }\n\n // Basic types\n if (fieldTypeName === 'ZodString') return 'string';\n if (fieldTypeName === 'ZodNumber') return 'number';\n if (fieldTypeName === 'ZodBoolean') return 'boolean';\n if (fieldTypeName === 'ZodDate') return 'Date';\n if (fieldTypeName === 'ZodBigInt') return 'bigint';\n if (fieldTypeName === 'ZodNull') return 'null';\n if (fieldTypeName === 'ZodUndefined') return 'undefined';\n if (fieldTypeName === 'ZodAny') return 'any';\n if (fieldTypeName === 'ZodUnknown') return 'unknown';\n if (fieldTypeName === 'ZodVoid') return 'void';\n\n // Complex types\n if (fieldTypeName === 'ZodArray') {\n const itemType = actualField._def?.type;\n if (itemType) {\n return `${getTypeName(itemType)}[]`;\n }\n return 'array';\n }\n if (fieldTypeName === 'ZodObject') {\n // Check if this is a passthrough object (like MidsceneLocation)\n if (ifMidsceneLocatorField(actualField)) {\n return locatorSchemaTypeDescription;\n }\n return 'object';\n }\n if (fieldTypeName === 'ZodTuple') {\n const items = actualField._def?.items as any[] | undefined;\n if (items && items.length > 0) {\n const itemTypes = items.map((item: any) => getTypeName(item));\n return `[${itemTypes.join(', ')}]`;\n }\n return 'tuple';\n }\n if (fieldTypeName === 'ZodRecord') {\n const valueType = actualField._def?.valueType;\n if (valueType) {\n return `Record<string, ${getTypeName(valueType)}>`;\n }\n return 'Record';\n }\n if (fieldTypeName === 'ZodLiteral') {\n const value = actualField._def?.value;\n if (value !== undefined) {\n return typeof value === 'string' ? `'${value}'` : String(value);\n }\n return 'literal';\n }\n if (fieldTypeName === 'ZodEnum') {\n const values =\n (actualField._def?.values as unknown[] | undefined)\n ?.map((option: unknown) => String(`'${option}'`))\n .join(', ') ?? 'enum';\n\n return `enum(${values})`;\n }\n if (fieldTypeName === 'ZodNativeEnum') {\n return 'nativeEnum';\n }\n if (fieldTypeName === 'ZodUnion') {\n const options = actualField._def?.options as any[] | undefined;\n if (options && options.length > 0) {\n // For unions, list all types\n const types = options.map((opt: any) => getTypeName(opt));\n return types.join(' | ');\n }\n return 'union';\n }\n if (fieldTypeName === 'ZodDiscriminatedUnion') {\n return 'discriminatedUnion';\n }\n if (fieldTypeName === 'ZodIntersection') {\n const left = actualField._def?.left;\n const right = actualField._def?.right;\n if (left && right) {\n return `${getTypeName(left)} & ${getTypeName(right)}`;\n }\n return 'intersection';\n }\n if (fieldTypeName === 'ZodPromise') {\n const innerType = actualField._def?.type;\n if (innerType) {\n return `Promise<${getTypeName(innerType)}>`;\n }\n return 'Promise';\n }\n if (fieldTypeName === 'ZodLazy') {\n // For lazy types, we can't resolve the type without evaluating the getter\n return 'lazy';\n }\n // Additional wrapper types\n if (fieldTypeName === 'ZodPipeline') {\n const out = actualField._def?.out;\n if (out) {\n return getTypeName(out);\n }\n return 'pipeline';\n }\n if (fieldTypeName === 'ZodCatch') {\n const innerType = actualField._def?.innerType;\n if (innerType) {\n return getTypeName(innerType);\n }\n return 'catch';\n }\n if (fieldTypeName === 'ZodBranded') {\n const innerType = actualField._def?.type;\n if (innerType) {\n return getTypeName(innerType);\n }\n return 'branded';\n }\n if (fieldTypeName === 'ZodReadonly') {\n const innerType = actualField._def?.innerType;\n if (innerType) {\n return `Readonly<${getTypeName(innerType)}>`;\n }\n return 'readonly';\n }\n\n console.warn(\n 'failed to parse Zod type. This may lead to wrong params from the LLM.\\n',\n actualField._def,\n );\n return actualField.toString();\n };\n\n // Helper function to get description from zod schema\n const getDescription = (field: z.ZodTypeAny): string | null => {\n // Recursively unwrap optional, nullable, and other wrapper types to get the actual inner type\n const unwrapField = (f: any): any => {\n if (!f._def) return f;\n\n const typeName = f._def.typeName;\n\n // Handle wrapper types that have innerType\n if (\n typeName === 'ZodOptional' ||\n typeName === 'ZodNullable' ||\n typeName === 'ZodDefault'\n ) {\n return unwrapField(f._def.innerType);\n }\n\n // Handle ZodEffects (transformations, refinements, preprocessors)\n if (typeName === 'ZodEffects') {\n // For ZodEffects, unwrap the schema field which contains the underlying type\n if (f._def.schema) {\n return unwrapField(f._def.schema);\n }\n }\n\n // Handle additional wrapper types\n if (typeName === 'ZodPipeline') {\n if (f._def.out) {\n return unwrapField(f._def.out);\n }\n }\n\n if (typeName === 'ZodCatch') {\n if (f._def.innerType) {\n return unwrapField(f._def.innerType);\n }\n }\n\n if (typeName === 'ZodBranded') {\n if (f._def.type) {\n return unwrapField(f._def.type);\n }\n }\n\n if (typeName === 'ZodReadonly') {\n if (f._def.innerType) {\n return unwrapField(f._def.innerType);\n }\n }\n\n return f;\n };\n\n // Check for direct description on the original field (wrapper may have description)\n if ('description' in field) {\n return field.description || null;\n }\n\n const actualField = unwrapField(field);\n\n // Check for description on the unwrapped field\n if ('description' in actualField) {\n return actualField.description || null;\n }\n\n // Handle ZodEffects explicitly - check inner schema for description\n if (\n actualField._def?.typeName === 'ZodEffects' &&\n actualField._def?.schema\n ) {\n if ('description' in actualField._def.schema) {\n return actualField._def.schema.description || null;\n }\n }\n\n // Check for MidsceneLocation fields and add description\n if (actualField._def?.typeName === 'ZodObject') {\n if ('midscene_location_field_flag' in actualField._def.shape()) {\n return 'Location information for the target element';\n }\n }\n\n return null;\n };\n\n for (const [key, field] of Object.entries(shape)) {\n if (field && typeof field === 'object') {\n // Check if field is optional\n const isOptional =\n typeof (field as any).isOptional === 'function' &&\n (field as any).isOptional();\n const keyWithOptional = isOptional ? `${key}?` : key;\n\n // Get the type name\n const typeName = getTypeName(field);\n\n // Get description\n const description = getDescription(field as z.ZodTypeAny);\n\n // Build param line for this field\n let paramLine = `${keyWithOptional}: ${typeName}`;\n if (description) {\n paramLine += ` // ${description}`;\n }\n\n paramLines.push(paramLine);\n }\n }\n\n if (paramLines.length > 0) {\n fields.push('- param:');\n for (const paramLine of paramLines) {\n fields.push(` - ${paramLine}`);\n }\n }\n }\n\n return `- ${action.name}, ${action.description || 'No description provided'}\n${tab}${fields.join(`\\n${tab}`)}\n`.trim();\n};\n\nconst systemTemplateOfVLPlanning = ({\n actionSpace,\n vlMode,\n}: {\n actionSpace: DeviceAction<any>[];\n vlMode: TVlModeTypes | undefined;\n}) => {\n const actionNameList = actionSpace.map((action) => action.name).join(', ');\n const actionDescriptionList = actionSpace.map((action) => {\n return descriptionForAction(action, vlLocateParam());\n });\n const actionList = actionDescriptionList.join('\\n');\n\n return `\nTarget: User will give you a latest screenshot, an instruction and some previous logs indicating what have been done. Please tell what the next one action is (or null if no action should be done) to do the tasks the instruction requires. \n\nRestriction:\n- Don't give extra actions or plans beyond the instruction. ONLY plan for what the instruction requires. For example, don't try to submit the form if the instruction is only to fill something.\n- Always give ONLY ONE action in \\`log\\` field (or null if no action should be done), instead of multiple actions. Supported actions are ${actionNameList}.\n- Don't repeat actions in the previous logs.\n- Bbox is the bounding box of the element to be located. It's an array of 4 numbers, representing ${bboxDescription(vlMode)}.\n\nSupporting actions:\n${actionList}\n\nField description:\n* The \\`prompt\\` field inside the \\`locate\\` field is a short description that could be used to locate the element.\n\nReturn in JSON format:\n{\n ${vlCurrentLog}\n ${commonOutputFields}\n \"action\": \n {\n // one of the supporting actions\n } | null,\n ,\n \"sleep\"?: number, // The sleep time after the action, in milliseconds.\n}\n\nFor example, when the instruction is \"click 'Confirm' button, and click 'Yes' in popup\" and the previous log shows \"The 'Confirm' button has been clicked\", by viewing the screenshot and previous logs, you should consider: We have already clicked the 'Confirm' button, so next we should find and click 'Yes' in popup.\n\nthis and output the JSON:\n\n{\n \"log\": \"The user wants to do click 'Confirm' button, and click 'Yes' in popup. According to the instruction and the previous logs, next step is to tap the 'Yes' button in the popup. Now i am going to compose an action 'Tap' to click 'Yes' in popup.\",\n \"action\": {\n \"type\": \"Tap\",\n \"param\": {\n \"locate\": {\n \"bbox\": [100, 100, 200, 200],\n \"prompt\": \"The 'Yes' button in popup\"\n }\n }\n },\n \"more_actions_needed_by_instruction\": false,\n}\n`;\n};\n\nconst systemTemplateOfLLM = ({\n actionSpace,\n}: { actionSpace: DeviceAction<any>[] }) => {\n const actionNameList = actionSpace.map((action) => action.name).join(' / ');\n const actionDescriptionList = actionSpace.map((action) => {\n return descriptionForAction(action, llmLocateParam());\n });\n const actionList = actionDescriptionList.join('\\n');\n\n return `\n## Role\n\nYou are a versatile professional in software UI automation. Your outstanding contributions will impact the user experience of billions of users.\n\n## Objective\n\n- Decompose the instruction user asked into a series of actions\n- Locate the target element if possible\n- If the instruction cannot be accomplished, give a further plan.\n\n## Workflow\n\n1. Receive the screenshot, element description of screenshot(if any), user's instruction and previous logs.\n2. Decompose the user's task into a sequence of feasible actions, and place it in the \\`actions\\` field. There are different types of actions (${actionNameList}). The \"About the action\" section below will give you more details.\n3. Consider whether the user's instruction will be accomplished after the actions you composed.\n- If the instruction is accomplished, set \\`more_actions_needed_by_instruction\\` to false.\n- If more actions are needed, set \\`more_actions_needed_by_instruction\\` to true. Get ready to hand over to the next talent people like you. Carefully log what have been done in the \\`log\\` field, he or she will continue the task according to your logs.\n4. If the task is not feasible on this page, set \\`error\\` field to the reason.\n\n## Constraints\n\n- All the actions you composed MUST be feasible, which means all the action fields can be filled with the page context information you get. If not, don't plan this action.\n- Trust the \"What have been done\" field about the task (if any), don't repeat actions in it.\n- Respond only with valid JSON. Do not write an introduction or summary or markdown prefix like \\`\\`\\`json\\`\\`\\`.\n- If the screenshot and the instruction are totally irrelevant, set reason in the \\`error\\` field.\n\n## About the \\`actions\\` field\n\nThe \\`locate\\` param is commonly used in the \\`param\\` field of the action, means to locate the target element to perform the action, it conforms to the following scheme:\n\ntype LocateParam = {\n \"id\": string, // the id of the element found. It should either be the id marked with a rectangle in the screenshot or the id described in the description.\n \"prompt\"?: string // the description of the element to find. It can only be omitted when locate is null.\n} | null // If it's not on the page, the LocateParam should be null\n\n## Supported actions\n\nEach action has a \\`type\\` and corresponding \\`param\\`. To be detailed:\n${actionList}\n\n`.trim();\n};\n\nconst outputTemplate = `\n## Output JSON Format:\n\nThe JSON format is as follows:\n\n{\n \"actions\": [\n // ... some actions\n ],\n ${llmCurrentLog}\n ${commonOutputFields}\n}\n\n## Examples\n\n### Example: Decompose a task\n\nWhen you received the following information:\n\n* Instruction: 'Click the language switch button, wait 1s, click \"English\"'\n* Logs: null\n* Page Context (screenshot and description) shows: There is a language switch button, and the \"English\" option is not shown in the screenshot now.\n\nBy viewing the page screenshot and description, you should consider this and output the JSON:\n\n* The user intent is: tap the switch button, sleep, and tap the 'English' option\n* The language switch button is shown in the screenshot, and can be located by the page description or the id marked with a rectangle. So we can plan a Tap action to do this.\n* Plan a Sleep action to wait for 1 second to ensure the language options are displayed.\n* The \"English\" option button is not shown in the screenshot now, it means it may only show after the previous actions are finished. So don't plan any action to do this.\n* Compose the log: The user wants to do click the language switch button, wait 1s, click \"English\". According to the instruction and the previous logs, next step is to tap the language switch button to open the language options. Now i am going to compose an action 'Tap' to click the language switch button.\n* The task cannot be accomplished (because the last tapping action is not finished yet), so the \\`more_actions_needed_by_instruction\\` field is true. The \\`error\\` field is null.\n\n{\n \"actions\":[\n {\n \"thought\": \"Click the language switch button to open the language options.\",\n \"type\": \"Tap\", \n \"param\": {\n \"locate\": { id: \"c81c4e9a33\", prompt: \"The language switch button\" }\n }\n },\n {\n \"thought\": \"Wait for 1 second to ensure the language options are displayed.\",\n \"type\": \"Sleep\",\n \"param\": { \"timeMs\": 1000 },\n }\n ],\n \"error\": null,\n \"more_actions_needed_by_instruction\": true,\n \"log\": \"The user wants to do click the language switch button, wait 1s, click \\\"English\\\". According to the instruction and the previous logs, next step is to tap the language switch button to open the language options. Now i am going to compose an action 'Tap' to click the language switch button.\",\n}\n\n### Example: What NOT to do\nWrong output:\n{\n \"actions\":[\n {\n \"thought\": \"Click the language switch button to open the language options.\",\n \"type\": \"Tap\",\n \"param\": {\n \"locate\": { \"id\": \"c81c4e9a33\" } // WRONG: prompt is missing, this is not a valid LocateParam\n }\n },\n {\n \"thought\": \"Click the English option\",\n \"type\": \"Tap\", \n \"param\": {\n \"locate\": null // WRONG: if the element is not on the page, you should not plan this action\n }\n }\n ],\n \"more_actions_needed_by_instruction\": false, // WRONG: should be true\n \"log\": \"The user wants to do click the language switch button, wait 1s, click \\\"English\\\". According to the instruction and the previous logs, next step is to tap the language switch button to open the language options. Now i am going to compose an action 'Tap' to click the language switch button.\",\n}\n`;\n\nexport async function systemPromptToTaskPlanning({\n actionSpace,\n vlMode,\n}: {\n actionSpace: DeviceAction<any>[];\n vlMode: TVlModeTypes | undefined;\n}) {\n if (vlMode) {\n return systemTemplateOfVLPlanning({ actionSpace, vlMode });\n }\n\n return `${systemTemplateOfLLM({ actionSpace })}\\n\\n${outputTemplate}`;\n}\n\nexport const planSchema: ResponseFormatJSONSchema = {\n type: 'json_schema',\n json_schema: {\n name: 'action_items',\n strict: false,\n schema: {\n type: 'object',\n strict: false,\n properties: {\n actions: {\n type: 'array',\n items: {\n type: 'object',\n strict: false,\n properties: {\n thought: {\n type: 'string',\n description:\n 'Reasons for generating this task, and why this task is feasible on this page',\n },\n type: {\n type: 'string',\n description: 'Type of action',\n },\n param: {\n anyOf: [\n { type: 'null' },\n {\n type: 'object',\n additionalProperties: true,\n },\n ],\n description: 'Parameter of the action',\n },\n locate: {\n type: ['object', 'null'],\n properties: {\n id: { type: 'string' },\n prompt: { type: 'string' },\n },\n required: ['id', 'prompt'],\n additionalProperties: false,\n description: 'Location information for the target element',\n },\n },\n required: ['thought', 'type', 'param', 'locate'],\n additionalProperties: false,\n },\n description: 'List of actions to be performed',\n },\n more_actions_needed_by_instruction: {\n type: 'boolean',\n description:\n 'If all the actions described in the instruction have been covered by this action and logs, set this field to false.',\n },\n log: {\n type: 'string',\n description:\n 'Log what these planned actions do. Do not include further actions that have not been planned.',\n },\n error: {\n type: ['string', 'null'],\n description: 'Error messages about unexpected situations',\n },\n },\n required: [\n 'actions',\n 'more_actions_needed_by_instruction',\n 'log',\n 'error',\n ],\n additionalProperties: false,\n },\n },\n};\n"],"names":["vlCurrentLog","llmCurrentLog","commonOutputFields","vlLocateParam","llmLocateParam","descriptionForAction","action","locatorSchemaTypeDescription","tab","fields","shape","console","paramLines","getTypeName","field","_actualField__def","unwrapField","f","typeName","actualField","fieldTypeName","_actualField__def1","_actualField__def2","itemType","ifMidsceneLocatorField","_actualField__def3","items","itemTypes","item","_actualField__def4","valueType","_actualField__def5","value","undefined","String","_actualField__def_values","values","option","_actualField__def7","options","types","opt","_actualField__def8","_actualField__def9","left","right","_actualField__def10","innerType","_actualField__def11","out","_actualField__def12","_actualField__def13","_actualField__def14","getDescription","key","Object","isOptional","keyWithOptional","description","paramLine","systemTemplateOfVLPlanning","actionSpace","vlMode","actionNameList","actionDescriptionList","actionList","bboxDescription","systemTemplateOfLLM","outputTemplate","systemPromptToTaskPlanning","planSchema"],"mappings":"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"}
|
|
@@ -11,37 +11,29 @@ import { assertSchema } from "../prompt/assertion.mjs";
|
|
|
11
11
|
import { planSchema } from "../prompt/llm-planning.mjs";
|
|
12
12
|
async function createChatClient({ AIActionTypeValue, modelConfig }) {
|
|
13
13
|
const { socksProxy, httpProxy, modelName, openaiBaseURL, openaiApiKey, openaiExtraConfig, modelDescription, uiTarsModelVersion: uiTarsVersion, vlMode, createOpenAIClient } = modelConfig;
|
|
14
|
-
let
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
openai =
|
|
37
|
-
baseURL: openaiBaseURL,
|
|
38
|
-
apiKey: openaiApiKey,
|
|
39
|
-
...proxyAgent ? {
|
|
40
|
-
httpAgent: proxyAgent
|
|
41
|
-
} : {},
|
|
42
|
-
...openaiExtraConfig,
|
|
43
|
-
dangerouslyAllowBrowser: true
|
|
44
|
-
});
|
|
14
|
+
let proxyAgent;
|
|
15
|
+
const debugProxy = getDebug('ai:call:proxy');
|
|
16
|
+
if (httpProxy) {
|
|
17
|
+
debugProxy('using http proxy', httpProxy);
|
|
18
|
+
proxyAgent = new HttpsProxyAgent(httpProxy);
|
|
19
|
+
} else if (socksProxy) {
|
|
20
|
+
debugProxy('using socks proxy', socksProxy);
|
|
21
|
+
proxyAgent = new SocksProxyAgent(socksProxy);
|
|
22
|
+
}
|
|
23
|
+
const openAIOptions = {
|
|
24
|
+
baseURL: openaiBaseURL,
|
|
25
|
+
apiKey: openaiApiKey,
|
|
26
|
+
...proxyAgent ? {
|
|
27
|
+
httpAgent: proxyAgent
|
|
28
|
+
} : {},
|
|
29
|
+
...openaiExtraConfig,
|
|
30
|
+
dangerouslyAllowBrowser: true
|
|
31
|
+
};
|
|
32
|
+
const baseOpenAI = new openai_0(openAIOptions);
|
|
33
|
+
let openai = baseOpenAI;
|
|
34
|
+
if (createOpenAIClient) {
|
|
35
|
+
const wrappedClient = await createOpenAIClient(baseOpenAI, openAIOptions);
|
|
36
|
+
if (wrappedClient) openai = wrappedClient;
|
|
45
37
|
}
|
|
46
38
|
return {
|
|
47
39
|
completion: openai.chat.completions,
|
|
@@ -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 {\n type IModelConfig,\n OPENAI_MAX_TOKENS,\n type TVlModeTypes,\n type UITarsModelVersion,\n globalConfigManager,\n} from '@midscene/shared/env';\n\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport { HttpsProxyAgent } from 'https-proxy-agent';\nimport { jsonrepair } from 'jsonrepair';\nimport OpenAI 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 { planSchema } from '../prompt/llm-planning';\n\nasync function createChatClient({\n AIActionTypeValue,\n modelConfig,\n}: {\n AIActionTypeValue: AIActionType;\n modelConfig: IModelConfig;\n}): Promise<{\n completion: OpenAI.Chat.Completions;\n modelName: string;\n modelDescription: string;\n uiTarsVersion?: UITarsModelVersion;\n vlMode: TVlModeTypes | undefined;\n}> {\n const {\n socksProxy,\n httpProxy,\n modelName,\n openaiBaseURL,\n openaiApiKey,\n openaiExtraConfig,\n modelDescription,\n uiTarsModelVersion: uiTarsVersion,\n vlMode,\n createOpenAIClient,\n } = modelConfig;\n\n let openai: OpenAI;\n\n // Use custom client factory if provided\n if (createOpenAIClient) {\n openai = createOpenAIClient({\n modelName,\n openaiApiKey,\n openaiBaseURL,\n socksProxy,\n httpProxy,\n openaiExtraConfig,\n vlMode,\n intent: modelConfig.intent,\n modelDescription,\n });\n } else {\n // Default OpenAI client creation\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 openai = new OpenAI({\n baseURL: openaiBaseURL,\n apiKey: openaiApiKey,\n ...(proxyAgent ? { httpAgent: proxyAgent as any } : {}),\n ...openaiExtraConfig,\n dangerouslyAllowBrowser: true,\n });\n }\n\n return {\n completion: openai.chat.completions,\n modelName,\n modelDescription,\n uiTarsVersion,\n vlMode,\n };\n}\n\nexport async function callAI(\n messages: ChatCompletionMessageParam[],\n AIActionTypeValue: AIActionType,\n modelConfig: IModelConfig,\n options?: {\n stream?: boolean;\n onChunk?: StreamingCallback;\n },\n): Promise<{ content: string; usage?: AIUsageInfo; isStreamed: boolean }> {\n const { completion, modelName, modelDescription, uiTarsVersion, vlMode } =\n await createChatClient({\n AIActionTypeValue,\n modelConfig,\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: vlMode === '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 ...(vlMode === 'qwen-vl' // qwen vl v2 specific config\n ? {\n vl_high_resolution_images: true,\n }\n : {}),\n };\n\n try {\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: modelConfig.intent,\n },\n };\n options.onChunk!(finalChunk);\n break;\n }\n }\n content = accumulated;\n debugProfileStats(\n `streaming model, ${modelName}, mode, ${vlMode || '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, ${vlMode || 'default'}, ui-tars-version, ${uiTarsVersion}, 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(`model usage detail: ${JSON.stringify(result.usage)}`);\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\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: modelConfig.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.PLAN:\n responseFormat = planSchema;\n break;\n case AIActionType.EXTRACT_DATA:\n case AIActionType.DESCRIBE_ELEMENT:\n responseFormat = { type: AIResponseFormat.JSON };\n break;\n case AIActionType.TEXT:\n // No response format for plain text - return as-is\n responseFormat = undefined;\n break;\n }\n }\n\n // gpt-4o-2024-05-13 only supports json_object response format\n // Skip for plain text to allow string output\n if (\n modelName === 'gpt-4o-2024-05-13' &&\n AIActionTypeValue !== AIActionType.TEXT\n ) {\n responseFormat = { type: AIResponseFormat.JSON };\n }\n\n return responseFormat;\n};\n\nexport async function callAIWithObjectResponse<T>(\n messages: ChatCompletionMessageParam[],\n AIActionTypeValue: AIActionType,\n modelConfig: IModelConfig,\n): Promise<{ content: T; usage?: AIUsageInfo }> {\n const response = await callAI(messages, AIActionTypeValue, modelConfig);\n assert(response, 'empty response');\n const vlMode = modelConfig.vlMode;\n const jsonContent = safeParseJson(response.content, vlMode);\n return { content: jsonContent, usage: response.usage };\n}\n\nexport async function callAIWithStringResponse(\n msgs: AIArgs,\n AIActionTypeValue: AIActionType,\n modelConfig: IModelConfig,\n): Promise<{ content: string; usage?: AIUsageInfo }> {\n const { content, usage } = await callAI(msgs, AIActionTypeValue, modelConfig);\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(input: string, vlMode: TVlModeTypes | undefined) {\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 (vlMode === 'doubao-vision' || vlMode === 'vlm-ui-tars') {\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","modelConfig","socksProxy","httpProxy","modelName","openaiBaseURL","openaiApiKey","openaiExtraConfig","modelDescription","uiTarsVersion","vlMode","createOpenAIClient","openai","proxyAgent","debugProxy","getDebug","HttpsProxyAgent","SocksProxyAgent","OpenAI","callAI","messages","options","completion","responseFormat","getResponseFormat","maxTokens","globalConfigManager","OPENAI_MAX_TOKENS","debugCall","debugProfileStats","debugProfileDetail","startTime","Date","isStreaming","content","accumulated","usage","timeCost","commonConfig","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","JSON","assert","e","console","newError","Error","AIActionType","assertSchema","planSchema","AIResponseFormat","callAIWithObjectResponse","response","jsonContent","safeParseJson","callAIWithStringResponse","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 {\n type IModelConfig,\n OPENAI_MAX_TOKENS,\n type TVlModeTypes,\n type UITarsModelVersion,\n globalConfigManager,\n} from '@midscene/shared/env';\n\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert } from '@midscene/shared/utils';\nimport { HttpsProxyAgent } from 'https-proxy-agent';\nimport { jsonrepair } from 'jsonrepair';\nimport OpenAI 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 { planSchema } from '../prompt/llm-planning';\n\nasync function createChatClient({\n AIActionTypeValue,\n modelConfig,\n}: {\n AIActionTypeValue: AIActionType;\n modelConfig: IModelConfig;\n}): Promise<{\n completion: OpenAI.Chat.Completions;\n modelName: string;\n modelDescription: string;\n uiTarsVersion?: UITarsModelVersion;\n vlMode: TVlModeTypes | undefined;\n}> {\n const {\n socksProxy,\n httpProxy,\n modelName,\n openaiBaseURL,\n openaiApiKey,\n openaiExtraConfig,\n modelDescription,\n uiTarsModelVersion: uiTarsVersion,\n vlMode,\n createOpenAIClient,\n } = modelConfig;\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 const openAIOptions = {\n baseURL: openaiBaseURL,\n apiKey: openaiApiKey,\n ...(proxyAgent ? { httpAgent: proxyAgent as any } : {}),\n ...openaiExtraConfig,\n dangerouslyAllowBrowser: true,\n };\n\n const baseOpenAI = new OpenAI(openAIOptions);\n\n let openai: OpenAI = baseOpenAI;\n\n if (createOpenAIClient) {\n const wrappedClient = await createOpenAIClient(baseOpenAI, openAIOptions);\n\n if (wrappedClient) {\n openai = wrappedClient as OpenAI;\n }\n }\n\n return {\n completion: openai.chat.completions,\n modelName,\n modelDescription,\n uiTarsVersion,\n vlMode,\n };\n}\n\nexport async function callAI(\n messages: ChatCompletionMessageParam[],\n AIActionTypeValue: AIActionType,\n modelConfig: IModelConfig,\n options?: {\n stream?: boolean;\n onChunk?: StreamingCallback;\n },\n): Promise<{ content: string; usage?: AIUsageInfo; isStreamed: boolean }> {\n const { completion, modelName, modelDescription, uiTarsVersion, vlMode } =\n await createChatClient({\n AIActionTypeValue,\n modelConfig,\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: vlMode === '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 ...(vlMode === 'qwen-vl' // qwen vl v2 specific config\n ? {\n vl_high_resolution_images: true,\n }\n : {}),\n };\n\n try {\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: modelConfig.intent,\n },\n };\n options.onChunk!(finalChunk);\n break;\n }\n }\n content = accumulated;\n debugProfileStats(\n `streaming model, ${modelName}, mode, ${vlMode || '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, ${vlMode || 'default'}, ui-tars-version, ${uiTarsVersion}, 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(`model usage detail: ${JSON.stringify(result.usage)}`);\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\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: modelConfig.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.PLAN:\n responseFormat = planSchema;\n break;\n case AIActionType.EXTRACT_DATA:\n case AIActionType.DESCRIBE_ELEMENT:\n responseFormat = { type: AIResponseFormat.JSON };\n break;\n case AIActionType.TEXT:\n // No response format for plain text - return as-is\n responseFormat = undefined;\n break;\n }\n }\n\n // gpt-4o-2024-05-13 only supports json_object response format\n // Skip for plain text to allow string output\n if (\n modelName === 'gpt-4o-2024-05-13' &&\n AIActionTypeValue !== AIActionType.TEXT\n ) {\n responseFormat = { type: AIResponseFormat.JSON };\n }\n\n return responseFormat;\n};\n\nexport async function callAIWithObjectResponse<T>(\n messages: ChatCompletionMessageParam[],\n AIActionTypeValue: AIActionType,\n modelConfig: IModelConfig,\n): Promise<{ content: T; usage?: AIUsageInfo }> {\n const response = await callAI(messages, AIActionTypeValue, modelConfig);\n assert(response, 'empty response');\n const vlMode = modelConfig.vlMode;\n const jsonContent = safeParseJson(response.content, vlMode);\n return { content: jsonContent, usage: response.usage };\n}\n\nexport async function callAIWithStringResponse(\n msgs: AIArgs,\n AIActionTypeValue: AIActionType,\n modelConfig: IModelConfig,\n): Promise<{ content: string; usage?: AIUsageInfo }> {\n const { content, usage } = await callAI(msgs, AIActionTypeValue, modelConfig);\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(input: string, vlMode: TVlModeTypes | undefined) {\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 (vlMode === 'doubao-vision' || vlMode === 'vlm-ui-tars') {\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","modelConfig","socksProxy","httpProxy","modelName","openaiBaseURL","openaiApiKey","openaiExtraConfig","modelDescription","uiTarsVersion","vlMode","createOpenAIClient","proxyAgent","debugProxy","getDebug","HttpsProxyAgent","SocksProxyAgent","openAIOptions","baseOpenAI","OpenAI","openai","wrappedClient","callAI","messages","options","completion","responseFormat","getResponseFormat","maxTokens","globalConfigManager","OPENAI_MAX_TOKENS","debugCall","debugProfileStats","debugProfileDetail","startTime","Date","isStreaming","content","accumulated","usage","timeCost","commonConfig","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","JSON","assert","e","console","newError","Error","AIActionType","assertSchema","planSchema","AIResponseFormat","callAIWithObjectResponse","response","jsonContent","safeParseJson","callAIWithStringResponse","msgs","extractJSONFromCodeBlock","jsonMatch","codeBlockMatch","jsonLikeMatch","preprocessDoubaoBboxJson","input","cleanJsonString","_cleanJsonString_match","jsonrepair","jsonString"],"mappings":"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"}
|
|
File without changes
|