validpilot-oss 1.1.1 → 1.2.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/CHANGELOG.md +11 -0
- package/package.json +1 -1
- package/server.js +75 -0
- package/tools/browser_navigate.json +26 -0
- package/tools/browser_screenshot_element.json +22 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.2.0] - 2026-06-28
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- 新增 `browser_screenshot_element` 工具 - 对指定页面元素进行截图,支持padding参数扩展截图区域
|
|
10
|
+
- 新增 `browser_navigate` 工具 - 浏览器导航操作,支持前进(forward)、后退(back)、刷新(refresh)、重新加载(reload)
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- 完整实现文档承诺的所有72个工具,能力匹配度100%
|
|
15
|
+
|
|
5
16
|
## [1.1.1] - 2026-06-28
|
|
6
17
|
|
|
7
18
|
### Fixed
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -3949,6 +3949,81 @@ async function callTool(name, args = {}) {
|
|
|
3949
3949
|
|
|
3950
3950
|
return text(JSON.stringify({ image: filePath, success: true, error_analysis: { has_errors: false } }, null, 2));
|
|
3951
3951
|
}
|
|
3952
|
+
case 'browser_screenshot_element': {
|
|
3953
|
+
const { target } = await ensurePage();
|
|
3954
|
+
ensureArtifactsDir();
|
|
3955
|
+
const selector = args.selector;
|
|
3956
|
+
if (!selector) {
|
|
3957
|
+
return { isError: true, content: [{ type: 'text', text: 'browser_screenshot_element 需要提供 selector 参数' }] };
|
|
3958
|
+
}
|
|
3959
|
+
const padding = args.padding || 0;
|
|
3960
|
+
const safeName = (args.name || `element-screenshot-${Date.now()}`).replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
3961
|
+
const filePath = path.join(SCREENSHOT_DIR, `${safeName}.png`);
|
|
3962
|
+
|
|
3963
|
+
try {
|
|
3964
|
+
const element = await target.$(selector);
|
|
3965
|
+
if (!element) {
|
|
3966
|
+
return { isError: true, content: [{ type: 'text', text: `未找到选择器 "${selector}" 对应的元素` }] };
|
|
3967
|
+
}
|
|
3968
|
+
|
|
3969
|
+
const box = await element.boundingBox();
|
|
3970
|
+
if (!box) {
|
|
3971
|
+
return { isError: true, content: [{ type: 'text', text: `元素 "${selector}" 不可见或尺寸为0` }] };
|
|
3972
|
+
}
|
|
3973
|
+
|
|
3974
|
+
const clip = {
|
|
3975
|
+
x: Math.max(0, box.x - padding),
|
|
3976
|
+
y: Math.max(0, box.y - padding),
|
|
3977
|
+
width: box.width + padding * 2,
|
|
3978
|
+
height: box.height + padding * 2
|
|
3979
|
+
};
|
|
3980
|
+
|
|
3981
|
+
await target.screenshot({ path: filePath, clip, omitBackground: false });
|
|
3982
|
+
|
|
3983
|
+
return text(JSON.stringify({
|
|
3984
|
+
image: filePath,
|
|
3985
|
+
success: true,
|
|
3986
|
+
selector,
|
|
3987
|
+
elementSize: { width: box.width, height: box.height },
|
|
3988
|
+
screenshotSize: { width: clip.width, height: clip.height },
|
|
3989
|
+
padding
|
|
3990
|
+
}, null, 2));
|
|
3991
|
+
} catch (e) {
|
|
3992
|
+
return { isError: true, content: [{ type: 'text', text: `元素截图失败: ${e.message}` }] };
|
|
3993
|
+
}
|
|
3994
|
+
}
|
|
3995
|
+
case 'browser_navigate': {
|
|
3996
|
+
const { target } = await ensurePage();
|
|
3997
|
+
const action = args.action || 'refresh';
|
|
3998
|
+
const waitUntil = args.waitUntil || 'domcontentloaded';
|
|
3999
|
+
const timeout = args.timeout || 30000;
|
|
4000
|
+
|
|
4001
|
+
try {
|
|
4002
|
+
switch (action) {
|
|
4003
|
+
case 'forward':
|
|
4004
|
+
await target.goForward({ timeout });
|
|
4005
|
+
break;
|
|
4006
|
+
case 'back':
|
|
4007
|
+
await target.goBack({ timeout });
|
|
4008
|
+
break;
|
|
4009
|
+
case 'refresh':
|
|
4010
|
+
case 'reload':
|
|
4011
|
+
await target.reload({ waitUntil, timeout });
|
|
4012
|
+
break;
|
|
4013
|
+
default:
|
|
4014
|
+
return { isError: true, content: [{ type: 'text', text: `不支持的导航操作: ${action},支持 forward/back/refresh/reload` }] };
|
|
4015
|
+
}
|
|
4016
|
+
|
|
4017
|
+
return text(JSON.stringify({
|
|
4018
|
+
action,
|
|
4019
|
+
success: true,
|
|
4020
|
+
currentUrl: target.url(),
|
|
4021
|
+
waitUntil
|
|
4022
|
+
}, null, 2));
|
|
4023
|
+
} catch (e) {
|
|
4024
|
+
return { isError: true, content: [{ type: 'text', text: `导航失败: ${e.message}` }] };
|
|
4025
|
+
}
|
|
4026
|
+
}
|
|
3952
4027
|
case 'browser_step': {
|
|
3953
4028
|
const { target } = await ensurePage();
|
|
3954
4029
|
return text(JSON.stringify(await captureStepEvidence(target, args.label || 'manual-step', args), null, 2));
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "browser_navigate",
|
|
3
|
+
"description": "浏览器导航操作。支持前进(forward)、后退(back)、刷新(refresh)、重新加载(reload)操作。",
|
|
4
|
+
"inputSchema": {
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"action": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "导航操作:forward(前进)、back(后退)、refresh(刷新)、reload(重新加载)",
|
|
10
|
+
"enum": ["forward", "back", "refresh", "reload"],
|
|
11
|
+
"default": "refresh"
|
|
12
|
+
},
|
|
13
|
+
"waitUntil": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "等待条件:domcontentloaded(DOM加载完成)、load(页面完全加载)、networkidle(网络空闲)",
|
|
16
|
+
"enum": ["domcontentloaded", "load", "networkidle"],
|
|
17
|
+
"default": "domcontentloaded"
|
|
18
|
+
},
|
|
19
|
+
"timeout": {
|
|
20
|
+
"type": "number",
|
|
21
|
+
"description": "超时时间,单位毫秒,默认30000"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"required": ["action"]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "browser_screenshot_element",
|
|
3
|
+
"description": "对指定页面元素进行截图。使用CSS选择器定位元素,截取该元素的可见区域,返回截图路径和尺寸信息。支持padding参数扩展截图区域。",
|
|
4
|
+
"inputSchema": {
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"selector": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "目标元素的CSS选择器"
|
|
10
|
+
},
|
|
11
|
+
"padding": {
|
|
12
|
+
"type": "number",
|
|
13
|
+
"description": "截图区域周围的padding,单位像素,默认0"
|
|
14
|
+
},
|
|
15
|
+
"name": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "截图文件名(不含扩展名),默认自动生成"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"required": ["selector"]
|
|
21
|
+
}
|
|
22
|
+
}
|