-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Expand file tree
/
Copy pathscreenshot.ts
More file actions
112 lines (104 loc) · 3.44 KB
/
screenshot.ts
File metadata and controls
112 lines (104 loc) · 3.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {zod} from '../third_party/index.js';
import type {ElementHandle, Page} from '../third_party/index.js';
import {ToolCategory} from './categories.js';
import {definePageTool} from './ToolDefinition.js';
export const screenshot = definePageTool({
name: 'take_screenshot',
description: `Take a screenshot of the page or element.`,
annotations: {
category: ToolCategory.DEBUGGING,
// Not read-only due to filePath param.
readOnlyHint: false,
},
schema: {
format: zod
.enum(['png', 'jpeg', 'webp'])
.default('png')
.describe('Type of format to save the screenshot as. Default is "png"'),
quality: zod
.number()
.min(0)
.max(100)
.optional()
.describe(
'Compression quality for JPEG and WebP formats (0-100). Higher values mean better quality but larger file sizes. Ignored for PNG format.',
),
uid: zod
.string()
.optional()
.describe(
'The uid of an element on the page from the page content snapshot. If omitted, takes a page screenshot.',
),
fullPage: zod
.boolean()
.optional()
.describe(
'If set to true takes a screenshot of the full page instead of the currently visible viewport. Incompatible with uid.',
),
filePath: zod
.string()
.optional()
.describe(
'The absolute path, or a path relative to the current working directory, to save the screenshot to instead of attaching it to the response.',
),
},
handler: async (request, response, context) => {
if (request.params.filePath) {
context.validatePath(request.params.filePath);
}
if (request.params.uid && request.params.fullPage) {
throw new Error('Providing both "uid" and "fullPage" is not allowed.');
}
let pageOrHandle: Page | ElementHandle;
if (request.params.uid) {
pageOrHandle = await request.page.getElementByUid(request.params.uid);
} else {
pageOrHandle = request.page.pptrPage;
}
const format = request.params.format;
const quality = format === 'png' ? undefined : request.params.quality;
const screenshot = await pageOrHandle.screenshot({
type: format,
fullPage: request.params.fullPage,
quality,
optimizeForSpeed: true, // Bonus: optimize encoding for speed
});
if (request.params.uid) {
response.appendResponseLine(
`Took a screenshot of node with uid "${request.params.uid}".`,
);
} else if (request.params.fullPage) {
response.appendResponseLine(
'Took a screenshot of the full current page.',
);
} else {
response.appendResponseLine(
"Took a screenshot of the current page's viewport.",
);
}
if (request.params.filePath) {
const result = await context.saveFile(
screenshot,
request.params.filePath,
`.${format}`,
);
response.appendResponseLine(`Saved screenshot to ${result.filename}.`);
} else if (screenshot.length >= 2_000_000) {
const {filepath} = await context.saveTemporaryFile(
screenshot,
`screenshot.${request.params.format}`,
);
response.appendResponseLine(`Saved screenshot to ${filepath}.`);
} else {
response.attachImage({
mimeType: `image/${request.params.format}`,
data: Buffer.from(screenshot).toString('base64'),
});
}
},
});