Skip to content

Commit 37ae712

Browse files
quanruyuyutaotao
andauthored
feat(web-integration): support logScreenshot api for agent (#813)
* feat(web-integration): support logScreenshot api for agent * docs(core): update api description * docs(site): fix error * feat(web-integration): title is also optional * docs(site): fix --------- Co-authored-by: yutao <[email protected]>
1 parent 297f66a commit 37ae712

File tree

17 files changed

+196
-99
lines changed

17 files changed

+196
-99
lines changed

apps/report/src/components/detail-panel.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use client';
22
import './detail-panel.less';
33
import { useExecutionDump } from '@/components/store';
4-
import { filterBase64Value, timeStr } from '@/utils';
54
import {
65
CameraOutlined,
76
FileTextOutlined,
@@ -12,6 +11,7 @@ import type {
1211
ExecutionTaskInsightLocate,
1312
ExecutionTaskPlanning,
1413
} from '@midscene/core';
14+
import { filterBase64Value, timeStr } from '@midscene/visualizer';
1515
import { Blackboard, Player } from '@midscene/visualizer';
1616
import { ConfigProvider, Segmented } from 'antd';
1717
import { useEffect, useState } from 'react';

apps/report/src/components/detail-side.less

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,19 @@
1010
margin-bottom: 4px;
1111
}
1212

13-
.ant-tag{
13+
.ant-tag {
1414
margin-top: 2px;
1515
}
1616

17+
18+
.log-content {
19+
padding: 20px;
20+
}
21+
1722
.meta-kv {
1823
padding: @side-vertical-spacing @side-horizontal-padding calc(@side-vertical-spacing + 4px);
1924
overflow: hidden;
25+
2026
.meta {
2127
box-sizing: border-box;
2228
padding: 2px 0;
@@ -26,13 +32,13 @@
2632
line-height: 1.5;
2733

2834
.meta-key {
29-
width:100px;
35+
width: 100px;
3036
text-align: right;
3137
padding-right: 16px;
3238
flex-shrink: 0;
3339
// color: #999;
3440
}
35-
41+
3642
.meta-value {
3743
flex: 1;
3844
}
@@ -42,7 +48,7 @@
4248
.item-list {
4349
padding: @side-vertical-spacing @side-horizontal-padding;
4450

45-
cursor:default;
51+
cursor: default;
4652
margin-bottom: 10px;
4753

4854
.item {
@@ -61,11 +67,12 @@
6167

6268
.item-highlight {
6369
color: #FFF;
70+
6471
.subtitle {
6572
color: #CCC;
6673
}
6774
}
68-
75+
6976
.item-extra {
7077
position: absolute;
7178
right: @side-horizontal-padding;
@@ -76,7 +83,7 @@
7683
.title-right-padding {
7784
padding-right: 15px;
7885
}
79-
86+
8087
.title {
8188
font-size: 18px;
8289
font-weight: bold;
@@ -100,7 +107,7 @@
100107
.description {
101108
margin-top: @subSpacing;
102109
}
103-
110+
104111
.description-content {
105112
font-size: 14px;
106113
margin-top: @side-horizontal-padding;
@@ -128,4 +135,4 @@
128135
.item-list-space-up {
129136
margin-top: @side-vertical-spacing;
130137
}
131-
}
138+
}

apps/report/src/components/detail-side.tsx

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* eslint-disable max-lines */
22
'use client';
33
import './detail-side.less';
4-
import { timeStr } from '@/utils';
4+
import { timeStr } from '@midscene/visualizer';
55
import { paramStr, typeStr } from '@midscene/web/ui-utils';
66

77
import { RadiusSettingOutlined } from '@ant-design/icons';
@@ -221,11 +221,11 @@ const DetailSide = (): JSX.Element => {
221221
],
222222
});
223223

224-
let taskParam: JSX.Element | null = null;
224+
let taskInput: JSX.Element | null = null;
225225
if (task?.type === 'Planning') {
226226
const planningTask = task as ExecutionTaskPlanning;
227227
if (planningTask.param?.userInstruction) {
228-
taskParam = MetaKV({
228+
taskInput = MetaKV({
229229
data: [
230230
{ key: 'type', content: (task && typeStr(task)) || '' },
231231
{
@@ -239,7 +239,7 @@ const DetailSide = (): JSX.Element => {
239239
],
240240
});
241241
} else {
242-
taskParam = MetaKV({
242+
taskInput = MetaKV({
243243
data: [
244244
{ key: 'type', content: (task && typeStr(task)) || '' },
245245
{
@@ -250,7 +250,7 @@ const DetailSide = (): JSX.Element => {
250250
});
251251
}
252252
} else if (task?.type === 'Insight') {
253-
taskParam = MetaKV({
253+
taskInput = MetaKV({
254254
data: [
255255
{ key: 'type', content: (task && typeStr(task)) || '' },
256256
...(paramStr(task)
@@ -280,7 +280,7 @@ const DetailSide = (): JSX.Element => {
280280
],
281281
});
282282
} else if (task?.type === 'Action') {
283-
taskParam = MetaKV({
283+
taskInput = MetaKV({
284284
data: [
285285
{ key: 'type', content: (task && typeStr(task)) || '' },
286286
{
@@ -289,6 +289,10 @@ const DetailSide = (): JSX.Element => {
289289
},
290290
],
291291
});
292+
} else if (task?.type === 'Log') {
293+
taskInput = task.param?.content ? (
294+
<pre className="log-content">{task.param.content}</pre>
295+
) : null;
292296
}
293297

294298
let outputDataContent = null;
@@ -467,9 +471,9 @@ const DetailSide = (): JSX.Element => {
467471
{/* Meta */}
468472
<PanelTitle title="Task Meta" />
469473
{metaKVElement}
470-
{/* Param */}
471-
<PanelTitle title="Param" />
472-
{taskParam}
474+
{/* Input: Param/Content */}
475+
<PanelTitle title={task?.type === 'Log' ? 'Content' : 'Param'} />
476+
{taskInput}
473477
{/* Response */}
474478
<PanelTitle title={task?.subType === 'Locate' ? 'Element' : 'Output'} />
475479
<div className="item-list item-list-space-up">{outputDataContent}</div>

apps/report/src/utils.ts

Lines changed: 0 additions & 73 deletions
This file was deleted.

apps/site/docs/en/API.mdx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,32 @@ The `deepThink` feature is a powerful feature that allows Midscene to call AI mo
253253

254254
:::
255255

256+
## Log Screenshot
257+
258+
Log the current screenshot with a description in the report file.
259+
260+
* Type
261+
262+
```typescript
263+
function logScreenshot(title?: string, options?: Object): Promise<void>;
264+
```
265+
266+
* Parameters:
267+
* `title?: string` - Optional, the title of the screenshot, if not provided, the title will be 'untitled'.
268+
* `options?: Object` - Optional, a configuration object containing:
269+
* `content?: string` - The description of the screenshot.
270+
271+
* Return Value:
272+
* Returns a `Promise<void>`
273+
274+
* Examples:
275+
276+
```typescript
277+
await agent.logScreenshot('Login page', {
278+
content: 'User A',
279+
});
280+
```
281+
256282
## Data Extraction
257283

258284
### `agent.aiQuery()`

apps/site/docs/en/automate-with-scripts-in-yaml.mdx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ web:
145145
# boolean, continue on network idle error, true for default
146146
continueOnNetworkIdleError: <boolean>
147147

148-
# string, the path to save the aiQuery result, optional
148+
# string, the path to save the aiQuery/aiAssert result, optional
149149
output: <path-to-output-file>
150150

151151
# boolean, if limit the popup to the current page, true for default in yaml script
@@ -232,6 +232,10 @@ tasks:
232232
deepThink: <boolean> # optional, whether to use deepThink to precisely locate the element
233233
cacheable: <boolean> # optional, whether cacheable when enabling [caching feature](./caching.mdx). True by default.
234234
235+
# log the current screenshot with a description in the report file
236+
- logScreenshot: <title> # optional, the title of the screenshot, if not provided, the title will be 'untitled'
237+
content: <content> # optional, the screenshot description
238+
235239
# Data Extraction
236240
# ----------------
237241

apps/site/docs/zh/API.mdx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,35 @@ await agent.aiRightClick('页面顶部的文件名称', { deepThink: true });
251251

252252
:::
253253

254+
## 记录截图
255+
256+
### `agent.logScreenshot()`
257+
258+
在报告文件中记录当前截图,并添加描述。
259+
260+
* 类型
261+
262+
```typescript
263+
function logScreenshot(title?: string, options?: Object): Promise<void>;
264+
```
265+
266+
* 参数:
267+
* `title?: string` - 可选,截图的标题,如果未提供,则标题为 'untitled'。
268+
* `options?: Object` - 可选,一个配置对象,包含:
269+
* `content?: string` - 截图的描述。
270+
271+
272+
* 返回值:
273+
* `Promise<void>`
274+
275+
* 示例:
276+
277+
```typescript
278+
await agent.logScreenshot('登录页面', {
279+
content: '用户 A',
280+
});
281+
```
282+
254283
## 数据提取
255284

256285
### `agent.aiQuery()`

apps/site/docs/zh/automate-with-scripts-in-yaml.mdx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ web:
145145
# 是否在等待超时后继续,可选,默认 true
146146
continueOnNetworkIdleError: <boolean>
147147

148-
# 输出 aiQuery 结果的 JSON 文件路径,可选
148+
# 输出 aiQuery/aiAssert 结果的 JSON 文件路径,可选
149149
output: <path-to-output-file>
150150

151151
# 是否限制页面在当前 tab 打开,可选,默认 true
@@ -232,6 +232,10 @@ tasks:
232232
deepThink: <boolean> # 可选,是否使用深度思考(deepThink)来精确定位元素
233233
cacheable: <boolean> # 可选,当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True
234234

235+
# 在报告文件中记录当前截图,并添加描述
236+
- logScreenshot: <title> # 可选,截图的标题,如果未提供,则标题为 'untitled'
237+
content: <content> # 可选,截图的描述
238+
235239
# 数据提取
236240
# ----------------
237241

packages/core/src/types.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,12 @@ export interface ExecutionRecorderItem {
361361
timing?: string;
362362
}
363363

364-
export type ExecutionTaskType = 'Planning' | 'Insight' | 'Action' | 'Assertion';
364+
export type ExecutionTaskType =
365+
| 'Planning'
366+
| 'Insight'
367+
| 'Action'
368+
| 'Assertion'
369+
| 'Log';
365370

366371
export interface ExecutorContext {
367372
task: ExecutionTask;
@@ -506,6 +511,18 @@ export type ExecutionTaskActionApply<ActionParam = any> = ExecutionTaskApply<
506511

507512
export type ExecutionTaskAction = ExecutionTask<ExecutionTaskActionApply>;
508513

514+
/*
515+
task - Log
516+
*/
517+
518+
export type ExecutionTaskLogApply<
519+
LogParam = {
520+
content: string;
521+
},
522+
> = ExecutionTaskApply<'Log', LogParam, void, void>;
523+
524+
export type ExecutionTaskLog = ExecutionTask<ExecutionTaskLogApply>;
525+
509526
/*
510527
task - planning
511528
*/

packages/core/src/yaml.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,11 @@ export interface MidsceneYamlFlowItemSleep {
162162
sleep: number;
163163
}
164164

165+
export interface MidsceneYamlFlowItemLogScreenshot {
166+
logScreenshot?: string; // optional, the title of the screenshot
167+
content?: string;
168+
}
169+
165170
export type MidsceneYamlFlowItem =
166171
| MidsceneYamlFlowItemAIAction
167172
| MidsceneYamlFlowItemAIAssert
@@ -173,7 +178,8 @@ export type MidsceneYamlFlowItem =
173178
| MidsceneYamlFlowItemAIInput
174179
| MidsceneYamlFlowItemAIKeyboardPress
175180
| MidsceneYamlFlowItemAIScroll
176-
| MidsceneYamlFlowItemSleep;
181+
| MidsceneYamlFlowItemSleep
182+
| MidsceneYamlFlowItemLogScreenshot;
177183

178184
export interface FreeFn {
179185
name: string;

packages/visualizer/src/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,5 @@ export {
4242
getPlaceholderForType,
4343
blankResult,
4444
} from './component/playground/playground-utils';
45+
46+
export { timeStr, filterBase64Value } from './utils';

0 commit comments

Comments
 (0)