@midscene/core 1.5.6 → 1.5.7-beta-20260317083700.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.
@@ -152,7 +152,7 @@ async function matchElementFromCache(context, cacheEntry, cachePrompt, cacheable
152
152
  return;
153
153
  }
154
154
  }
155
- const getMidsceneVersion = ()=>"1.5.6";
155
+ const getMidsceneVersion = ()=>"1.5.7-beta-20260317083700.0";
156
156
  const parsePrompt = (prompt)=>{
157
157
  if ('string' == typeof prompt) return {
158
158
  textPrompt: prompt,
@@ -2,10 +2,11 @@ import { AIResponseParseError, callAI, callAIWithObjectResponse, callAIWithStrin
2
2
  import { systemPromptToLocateElement } from "./prompt/llm-locator.mjs";
3
3
  import { generatePlaywrightTest, generatePlaywrightTestStream } from "./prompt/playwright-generator.mjs";
4
4
  import { generateYamlTest, generateYamlTestStream } from "./prompt/yaml-generator.mjs";
5
+ import { generatePlaywrightFromVideoFrames, generateYamlFromVideoFrames } from "./prompt/video-to-yaml.mjs";
5
6
  import { AiExtractElementInfo, AiJudgeOrderSensitive, AiLocateElement, AiLocateSection } from "./inspect.mjs";
6
7
  import { plan } from "./llm-planning.mjs";
7
8
  import { autoGLMPlanning } from "./auto-glm/planning.mjs";
8
9
  import { PointSchema, RectSchema, SizeSchema, TMultimodalPromptSchema, TUserPromptSchema, adaptBboxToRect, dumpActionParam, findAllMidsceneLocatorField, getMidsceneLocationSchema, parseActionParam } from "../common.mjs";
9
10
  import { uiTarsPlanning } from "./ui-tars-planning.mjs";
10
11
  import { ConversationHistory } from "./conversation-history.mjs";
11
- export { AIResponseParseError, AiExtractElementInfo, AiJudgeOrderSensitive, AiLocateElement, AiLocateSection, ConversationHistory, PointSchema, RectSchema, SizeSchema, TMultimodalPromptSchema, TUserPromptSchema, adaptBboxToRect, autoGLMPlanning, callAI, callAIWithObjectResponse, callAIWithStringResponse, dumpActionParam, findAllMidsceneLocatorField, generatePlaywrightTest, generatePlaywrightTestStream, generateYamlTest, generateYamlTestStream, getMidsceneLocationSchema, parseActionParam, plan, systemPromptToLocateElement, uiTarsPlanning };
12
+ export { AIResponseParseError, AiExtractElementInfo, AiJudgeOrderSensitive, AiLocateElement, AiLocateSection, ConversationHistory, PointSchema, RectSchema, SizeSchema, TMultimodalPromptSchema, TUserPromptSchema, adaptBboxToRect, autoGLMPlanning, callAI, callAIWithObjectResponse, callAIWithStringResponse, dumpActionParam, findAllMidsceneLocatorField, generatePlaywrightFromVideoFrames, generatePlaywrightTest, generatePlaywrightTestStream, generateYamlFromVideoFrames, generateYamlTest, generateYamlTestStream, getMidsceneLocationSchema, parseActionParam, plan, systemPromptToLocateElement, uiTarsPlanning };
@@ -0,0 +1,156 @@
1
+ import { PLAYWRIGHT_EXAMPLE_CODE, YAML_EXAMPLE_CODE } from "@midscene/shared/constants";
2
+ import { callAIWithStringResponse } from "../index.mjs";
3
+ function ensureDataUri(base64) {
4
+ if (base64.startsWith('data:')) return base64;
5
+ return `data:image/jpeg;base64,${base64}`;
6
+ }
7
+ const MIDSCENE_CONSTRAINTS = `
8
+ ## CRITICAL — Midscene Constraints (You MUST follow these)
9
+
10
+ Midscene automates the **web page content area** only. It CANNOT interact with:
11
+ - Browser chrome (address bar, bookmarks bar, tab bar, back/forward buttons)
12
+ - OS-level UI (taskbar, dock, system dialogs, file picker)
13
+ - Developer tools
14
+
15
+ Therefore:
16
+ 1. **URL navigation** must be handled via the \`web.url\` field (for the starting URL) or \`javascript: window.location.href = '...'\` (for mid-flow navigation). NEVER generate actions that type into the address bar or click browser navigation buttons.
17
+ 2. If the video shows the user typing a URL in the address bar and pressing Enter, convert that into the appropriate \`web.url\` or \`javascript\` navigation — NOT aiTap/aiInput on the address bar.
18
+ 3. Only target elements **inside the web page content**.
19
+ 4. If you see the browser address bar showing a URL, extract it and use it as \`web.url\`.
20
+ `;
21
+ const ACTION_DETECTION_GUIDE = `
22
+ ## Action Detection Guide
23
+
24
+ - **Click/Tap**: An element becomes focused, pressed, or a new page/modal appears after a frame.
25
+ - **Text Input**: Text appears in an input field that was empty or had different text before.
26
+ - **Scroll**: The page content shifts up/down/left/right between frames.
27
+ - **Navigation**: The URL changes or page content changes dramatically — use \`web.url\` or \`javascript\` for this.
28
+ - **Keyboard Press**: A specific key action occurs (Enter to submit, Tab to move focus, Escape to close).
29
+ - **Hover**: A tooltip or dropdown appears when the cursor is over an element.
30
+ `;
31
+ function buildYamlSystemPrompt() {
32
+ return `You are an expert in UI test automation with Midscene.js. Your task is to analyze a sequence of screenshots extracted from a screen recording video and generate a **runnable** Midscene YAML test script that reproduces the user's actions.
33
+
34
+ ## Your Analysis Process
35
+
36
+ 1. **Observe each frame carefully** — note what changed between consecutive frames.
37
+ 2. **Identify user actions** — clicks, typing, scrolling, navigation, keyboard shortcuts.
38
+ 3. **Determine action targets** — describe UI elements in natural language (e.g., "the search input box", "the Login button", "the first product card").
39
+ 4. **Identify the sequence** — order actions chronologically.
40
+ 5. **Group into logical tasks** — group related actions into named tasks.
41
+ 6. **Extract URLs** — read the address bar in screenshots to determine the actual URL.
42
+ ${MIDSCENE_CONSTRAINTS}
43
+ ${ACTION_DETECTION_GUIDE}
44
+ ## Output Rules
45
+
46
+ - Output ONLY valid Midscene YAML — no markdown code fences, no explanation.
47
+ - The \`web.url\` field MUST be set to the actual page URL visible in the video (read it from the address bar in the frames).
48
+ - Use natural language descriptions for element targeting (Midscene uses AI to locate elements).
49
+ - Prefer specific, unambiguous element descriptions.
50
+ - Use aiTap for clicks, aiInput for text entry, aiScroll for scrolling, aiAssert for verifying important state changes.
51
+ - Add aiWaitFor when the page needs time to load after navigation or actions.
52
+ - If the user navigates to a different URL mid-flow, use \`javascript: window.location.href = 'new_url'\`.
53
+
54
+ ## YAML Format Reference
55
+ ${YAML_EXAMPLE_CODE}`;
56
+ }
57
+ function buildPlaywrightSystemPrompt() {
58
+ return `You are an expert test automation engineer specializing in Playwright and Midscene.js. Your task is to analyze a sequence of screenshots extracted from a screen recording video and generate a **runnable** Playwright test using @midscene/web/playwright that reproduces the user's actions.
59
+ ${MIDSCENE_CONSTRAINTS}
60
+
61
+ For Playwright tests, navigation is handled by \`page.goto(url)\` in beforeEach — NEVER generate aiTap/aiInput actions targeting the browser address bar.
62
+ ${ACTION_DETECTION_GUIDE}
63
+ ## Output Rules
64
+
65
+ - Output ONLY the raw TypeScript test code — no markdown code fences, no explanation.
66
+ - The test MUST be immediately executable without modification.
67
+ - Extract the actual page URL from the address bar visible in the video frames.
68
+ - Use \`page.goto(url)\` for the initial navigation in beforeEach.
69
+ - Use \`page.goto(url)\` for mid-flow navigation if the URL changes.
70
+ - Use natural language descriptions for element targeting.
71
+
72
+ ## Playwright + Midscene Code Reference
73
+ ${PLAYWRIGHT_EXAMPLE_CODE}`;
74
+ }
75
+ function buildUserPrompt(frames, options, format) {
76
+ const parts = [];
77
+ parts.push('I recorded a screen video of a user interacting with a web application. Below are key frames extracted from the video in chronological order.');
78
+ if (options.url) parts.push(`\nThe starting URL is: ${options.url}`);
79
+ else parts.push('\nIMPORTANT: Look at the browser address bar in the frames to determine the actual URL of the page. Use that URL in the output.');
80
+ if (options.description) parts.push(`\nDescription of what the video shows: ${options.description}`);
81
+ parts.push(`\nThere are ${frames.length} frames in total. Each frame is labeled with its timestamp.`);
82
+ const formatLabel = 'yaml' === format ? 'Midscene YAML' : 'Playwright test';
83
+ parts.push(`\nAnalyze the frames to identify all user actions, then generate a complete, runnable ${formatLabel} script that reproduces the workflow.`);
84
+ parts.push('\nREMINDER: Do NOT generate actions that interact with the browser address bar or browser chrome. Convert URL typing into web.url / page.goto().');
85
+ parts.push('\nIMPORTANT: Return ONLY the raw code content. Do NOT wrap the response in markdown code blocks.');
86
+ return parts.join('');
87
+ }
88
+ function buildMultimodalMessages(frames, options, format) {
89
+ const systemPrompt = 'yaml' === format ? buildYamlSystemPrompt() : buildPlaywrightSystemPrompt();
90
+ const userText = buildUserPrompt(frames, options, format);
91
+ const userContent = [];
92
+ userContent.push({
93
+ type: 'text',
94
+ text: userText
95
+ });
96
+ for (const frame of frames){
97
+ userContent.push({
98
+ type: 'text',
99
+ text: `\n[Frame at ${frame.timestamp.toFixed(1)}s]:`
100
+ });
101
+ userContent.push({
102
+ type: 'image_url',
103
+ image_url: {
104
+ url: ensureDataUri(frame.base64),
105
+ detail: 'high'
106
+ }
107
+ });
108
+ }
109
+ return [
110
+ {
111
+ role: 'system',
112
+ content: systemPrompt
113
+ },
114
+ {
115
+ role: 'user',
116
+ content: userContent
117
+ }
118
+ ];
119
+ }
120
+ function stripCodeFences(content, format) {
121
+ let result = content;
122
+ result = 'yaml' === format ? result.replace(/^```(?:ya?ml)?\s*\n?/i, '') : result.replace(/^```(?:typescript|javascript|ts|js)?\s*\n?/i, '');
123
+ result = result.replace(/\n?```\s*$/i, '');
124
+ return result.trim();
125
+ }
126
+ async function generateYamlFromVideoFrames(frames, options, modelConfig) {
127
+ if (0 === frames.length) throw new Error('No frames provided for video-to-YAML generation');
128
+ const messages = buildMultimodalMessages(frames, options, 'yaml');
129
+ const response = await callAIWithStringResponse(messages, modelConfig);
130
+ let content = stripCodeFences(response.content, 'yaml');
131
+ if (options.url && !content.includes('url:')) {
132
+ const webConfig = [
133
+ 'web:',
134
+ ` url: "${options.url}"`,
135
+ options.viewportWidth ? ` viewportWidth: ${options.viewportWidth}` : null,
136
+ options.viewportHeight ? ` viewportHeight: ${options.viewportHeight}` : null,
137
+ ''
138
+ ].filter(Boolean).join('\n');
139
+ content = `${webConfig}\n${content}`;
140
+ }
141
+ return {
142
+ content
143
+ };
144
+ }
145
+ async function generatePlaywrightFromVideoFrames(frames, options, modelConfig) {
146
+ if (0 === frames.length) throw new Error('No frames provided for video-to-Playwright generation');
147
+ const messages = buildMultimodalMessages(frames, options, 'playwright');
148
+ const response = await callAIWithStringResponse(messages, modelConfig);
149
+ const content = stripCodeFences(response.content, 'playwright');
150
+ return {
151
+ content
152
+ };
153
+ }
154
+ export { generatePlaywrightFromVideoFrames, generateYamlFromVideoFrames };
155
+
156
+ //# sourceMappingURL=video-to-yaml.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-model/prompt/video-to-yaml.mjs","sources":["../../../../src/ai-model/prompt/video-to-yaml.ts"],"sourcesContent":["import {\n PLAYWRIGHT_EXAMPLE_CODE,\n YAML_EXAMPLE_CODE,\n} from '@midscene/shared/constants';\nimport type { IModelConfig } from '@midscene/shared/env';\nimport type { ChatCompletionMessageParam } from 'openai/resources/index';\nimport { callAIWithStringResponse } from '../index';\n\nexport interface VideoFrame {\n /** base64-encoded image data (with or without data URI prefix) */\n base64: string;\n /** timestamp in seconds */\n timestamp: number;\n}\n\nexport interface VideoToScriptOptions {\n /** The starting URL of the web page shown in the video */\n url?: string;\n /** A brief description of what the video demonstrates */\n description?: string;\n /** Viewport width observed in the video */\n viewportWidth?: number;\n /** Viewport height observed in the video */\n viewportHeight?: number;\n}\n\nexport type VideoScriptFormat = 'yaml' | 'playwright';\n\nfunction ensureDataUri(base64: string): string {\n if (base64.startsWith('data:')) {\n return base64;\n }\n return `data:image/jpeg;base64,${base64}`;\n}\n\nconst MIDSCENE_CONSTRAINTS = `\n## CRITICAL — Midscene Constraints (You MUST follow these)\n\nMidscene automates the **web page content area** only. It CANNOT interact with:\n- Browser chrome (address bar, bookmarks bar, tab bar, back/forward buttons)\n- OS-level UI (taskbar, dock, system dialogs, file picker)\n- Developer tools\n\nTherefore:\n1. **URL navigation** must be handled via the \\`web.url\\` field (for the starting URL) or \\`javascript: window.location.href = '...'\\` (for mid-flow navigation). NEVER generate actions that type into the address bar or click browser navigation buttons.\n2. If the video shows the user typing a URL in the address bar and pressing Enter, convert that into the appropriate \\`web.url\\` or \\`javascript\\` navigation — NOT aiTap/aiInput on the address bar.\n3. Only target elements **inside the web page content**.\n4. If you see the browser address bar showing a URL, extract it and use it as \\`web.url\\`.\n`;\n\nconst ACTION_DETECTION_GUIDE = `\n## Action Detection Guide\n\n- **Click/Tap**: An element becomes focused, pressed, or a new page/modal appears after a frame.\n- **Text Input**: Text appears in an input field that was empty or had different text before.\n- **Scroll**: The page content shifts up/down/left/right between frames.\n- **Navigation**: The URL changes or page content changes dramatically — use \\`web.url\\` or \\`javascript\\` for this.\n- **Keyboard Press**: A specific key action occurs (Enter to submit, Tab to move focus, Escape to close).\n- **Hover**: A tooltip or dropdown appears when the cursor is over an element.\n`;\n\nfunction buildYamlSystemPrompt(): string {\n return `You are an expert in UI test automation with Midscene.js. Your task is to analyze a sequence of screenshots extracted from a screen recording video and generate a **runnable** Midscene YAML test script that reproduces the user's actions.\n\n## Your Analysis Process\n\n1. **Observe each frame carefully** — note what changed between consecutive frames.\n2. **Identify user actions** — clicks, typing, scrolling, navigation, keyboard shortcuts.\n3. **Determine action targets** — describe UI elements in natural language (e.g., \"the search input box\", \"the Login button\", \"the first product card\").\n4. **Identify the sequence** — order actions chronologically.\n5. **Group into logical tasks** — group related actions into named tasks.\n6. **Extract URLs** — read the address bar in screenshots to determine the actual URL.\n${MIDSCENE_CONSTRAINTS}\n${ACTION_DETECTION_GUIDE}\n## Output Rules\n\n- Output ONLY valid Midscene YAML — no markdown code fences, no explanation.\n- The \\`web.url\\` field MUST be set to the actual page URL visible in the video (read it from the address bar in the frames).\n- Use natural language descriptions for element targeting (Midscene uses AI to locate elements).\n- Prefer specific, unambiguous element descriptions.\n- Use aiTap for clicks, aiInput for text entry, aiScroll for scrolling, aiAssert for verifying important state changes.\n- Add aiWaitFor when the page needs time to load after navigation or actions.\n- If the user navigates to a different URL mid-flow, use \\`javascript: window.location.href = 'new_url'\\`.\n\n## YAML Format Reference\n${YAML_EXAMPLE_CODE}`;\n}\n\nfunction buildPlaywrightSystemPrompt(): string {\n return `You are an expert test automation engineer specializing in Playwright and Midscene.js. Your task is to analyze a sequence of screenshots extracted from a screen recording video and generate a **runnable** Playwright test using @midscene/web/playwright that reproduces the user's actions.\n${MIDSCENE_CONSTRAINTS}\n\nFor Playwright tests, navigation is handled by \\`page.goto(url)\\` in beforeEach — NEVER generate aiTap/aiInput actions targeting the browser address bar.\n${ACTION_DETECTION_GUIDE}\n## Output Rules\n\n- Output ONLY the raw TypeScript test code — no markdown code fences, no explanation.\n- The test MUST be immediately executable without modification.\n- Extract the actual page URL from the address bar visible in the video frames.\n- Use \\`page.goto(url)\\` for the initial navigation in beforeEach.\n- Use \\`page.goto(url)\\` for mid-flow navigation if the URL changes.\n- Use natural language descriptions for element targeting.\n\n## Playwright + Midscene Code Reference\n${PLAYWRIGHT_EXAMPLE_CODE}`;\n}\n\nfunction buildUserPrompt(\n frames: VideoFrame[],\n options: VideoToScriptOptions,\n format: VideoScriptFormat,\n): string {\n const parts: string[] = [];\n\n parts.push(\n 'I recorded a screen video of a user interacting with a web application. Below are key frames extracted from the video in chronological order.',\n );\n\n if (options.url) {\n parts.push(`\\nThe starting URL is: ${options.url}`);\n } else {\n parts.push(\n '\\nIMPORTANT: Look at the browser address bar in the frames to determine the actual URL of the page. Use that URL in the output.',\n );\n }\n\n if (options.description) {\n parts.push(`\\nDescription of what the video shows: ${options.description}`);\n }\n\n parts.push(\n `\\nThere are ${frames.length} frames in total. Each frame is labeled with its timestamp.`,\n );\n\n const formatLabel = format === 'yaml' ? 'Midscene YAML' : 'Playwright test';\n parts.push(\n `\\nAnalyze the frames to identify all user actions, then generate a complete, runnable ${formatLabel} script that reproduces the workflow.`,\n );\n\n parts.push(\n '\\nREMINDER: Do NOT generate actions that interact with the browser address bar or browser chrome. Convert URL typing into web.url / page.goto().',\n );\n\n parts.push(\n '\\nIMPORTANT: Return ONLY the raw code content. Do NOT wrap the response in markdown code blocks.',\n );\n\n return parts.join('');\n}\n\nfunction buildMultimodalMessages(\n frames: VideoFrame[],\n options: VideoToScriptOptions,\n format: VideoScriptFormat,\n): ChatCompletionMessageParam[] {\n const systemPrompt =\n format === 'yaml' ? buildYamlSystemPrompt() : buildPlaywrightSystemPrompt();\n\n const userText = buildUserPrompt(frames, options, format);\n\n const userContent: Array<\n | { type: 'text'; text: string }\n | { type: 'image_url'; image_url: { url: string; detail?: string } }\n > = [];\n\n userContent.push({ type: 'text', text: userText });\n\n for (const frame of frames) {\n userContent.push({\n type: 'text',\n text: `\\n[Frame at ${frame.timestamp.toFixed(1)}s]:`,\n });\n userContent.push({\n type: 'image_url',\n image_url: {\n url: ensureDataUri(frame.base64),\n detail: 'high',\n },\n });\n }\n\n return [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userContent as any },\n ];\n}\n\nfunction stripCodeFences(content: string, format: VideoScriptFormat): string {\n let result = content;\n if (format === 'yaml') {\n result = result.replace(/^```(?:ya?ml)?\\s*\\n?/i, '');\n } else {\n result = result.replace(/^```(?:typescript|javascript|ts|js)?\\s*\\n?/i, '');\n }\n result = result.replace(/\\n?```\\s*$/i, '');\n return result.trim();\n}\n\n/**\n * Generate a Midscene YAML test script from video frames using a VLM.\n */\nexport async function generateYamlFromVideoFrames(\n frames: VideoFrame[],\n options: VideoToScriptOptions,\n modelConfig: IModelConfig,\n): Promise<{ content: string }> {\n if (frames.length === 0) {\n throw new Error('No frames provided for video-to-YAML generation');\n }\n\n const messages = buildMultimodalMessages(frames, options, 'yaml');\n const response = await callAIWithStringResponse(messages, modelConfig);\n\n let content = stripCodeFences(response.content, 'yaml');\n\n // If a URL was provided but not in the generated YAML, prepend web config\n if (options.url && !content.includes('url:')) {\n const webConfig = [\n 'web:',\n ` url: \"${options.url}\"`,\n options.viewportWidth\n ? ` viewportWidth: ${options.viewportWidth}`\n : null,\n options.viewportHeight\n ? ` viewportHeight: ${options.viewportHeight}`\n : null,\n '',\n ]\n .filter(Boolean)\n .join('\\n');\n content = `${webConfig}\\n${content}`;\n }\n\n return { content };\n}\n\n/**\n * Generate a Playwright + Midscene test script from video frames using a VLM.\n */\nexport async function generatePlaywrightFromVideoFrames(\n frames: VideoFrame[],\n options: VideoToScriptOptions,\n modelConfig: IModelConfig,\n): Promise<{ content: string }> {\n if (frames.length === 0) {\n throw new Error('No frames provided for video-to-Playwright generation');\n }\n\n const messages = buildMultimodalMessages(frames, options, 'playwright');\n const response = await callAIWithStringResponse(messages, modelConfig);\n const content = stripCodeFences(response.content, 'playwright');\n\n return { content };\n}\n"],"names":["ensureDataUri","base64","MIDSCENE_CONSTRAINTS","ACTION_DETECTION_GUIDE","buildYamlSystemPrompt","YAML_EXAMPLE_CODE","buildPlaywrightSystemPrompt","PLAYWRIGHT_EXAMPLE_CODE","buildUserPrompt","frames","options","format","parts","formatLabel","buildMultimodalMessages","systemPrompt","userText","userContent","frame","stripCodeFences","content","result","generateYamlFromVideoFrames","modelConfig","Error","messages","response","callAIWithStringResponse","webConfig","Boolean","generatePlaywrightFromVideoFrames"],"mappings":"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"}