mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-15 06:16:03 +00:00
fix(browser): 加固 browser_click 激活语义并修复相关验证阻塞
- 将 browser_click 调整为 mousedown/mouseup 后走 native click - 在取消激活和中途 detached 场景下避免强制触发 native activation - 补齐 browser_click 的回归测试与取消激活场景覆盖 - 修复 cliproxy 本地代理、Droid 环境隔离、图像分析 hook 与 proxy 集成测试的验证阻塞 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
eb8149e8fa
commit
74f028168d
7 files changed
+400
-15
No files matched your search
@@ -133,7 +133,7 @@ function getTools() {
|
||||
{
|
||||
name: TOOL_CLICK,
|
||||
description:
|
||||
'Click the first element matching a CSS selector in the selected page using synthetic element.click(). Optionally choose a page by index.',
|
||||
'Click the first element matching a CSS selector in the selected page using a minimal mouse event chain with click fallback. Optionally choose a page by index.',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
@@ -516,11 +516,54 @@ async function handleClick(toolArgs) {
|
||||
if (!element) {
|
||||
throw new Error('element not found for selector: ' + selector);
|
||||
}
|
||||
if (!element.isConnected) {
|
||||
throw new Error('element is detached for selector: ' + selector);
|
||||
}
|
||||
if ('disabled' in element && element.disabled) {
|
||||
throw new Error('element is disabled for selector: ' + selector);
|
||||
}
|
||||
const style = window.getComputedStyle(element);
|
||||
const rect = element.getBoundingClientRect();
|
||||
if (
|
||||
style.display === 'none' ||
|
||||
style.visibility === 'hidden' ||
|
||||
rect.width <= 0 ||
|
||||
rect.height <= 0
|
||||
) {
|
||||
throw new Error('element is hidden or not interactable for selector: ' + selector);
|
||||
}
|
||||
element.scrollIntoView({ block: 'center', inline: 'center' });
|
||||
|
||||
const dispatchMouseEvent = (type, init) => {
|
||||
const event = new MouseEvent(type, {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
composed: true,
|
||||
view: window,
|
||||
detail: 1,
|
||||
...init,
|
||||
});
|
||||
return element.dispatchEvent(event);
|
||||
};
|
||||
|
||||
try {
|
||||
const dispatchResult = {
|
||||
shouldActivate:
|
||||
dispatchMouseEvent('mousedown', { button: 0, buttons: 1 }) &&
|
||||
dispatchMouseEvent('mouseup', { button: 0, buttons: 0 }),
|
||||
};
|
||||
if (!dispatchResult.shouldActivate) {
|
||||
return 'ok';
|
||||
}
|
||||
if (!element.isConnected) {
|
||||
return 'ok';
|
||||
}
|
||||
} catch (mouseError) {
|
||||
// Fall through to the native activation path below.
|
||||
}
|
||||
|
||||
element.click();
|
||||
|
||||
return 'ok';
|
||||
})()`;
|
||||
|
||||
|
||||
Reference in new issue
Block a user