Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/browserView/electron-browser/tools/clickBrowserTool.ts
13405 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import type { CancellationToken } from '../../../../../base/common/cancellation.js';
7
import { Codicon } from '../../../../../base/common/codicons.js';
8
import { escapeMarkdownSyntaxTokens, MarkdownString } from '../../../../../base/common/htmlContent.js';
9
import { localize } from '../../../../../nls.js';
10
import { IPlaywrightService } from '../../../../../platform/browserView/common/playwrightService.js';
11
import { ToolDataSource, type CountTokensCallback, type IPreparedToolInvocation, type IToolData, type IToolImpl, type IToolInvocation, type IToolInvocationPreparationContext, type IToolResult, type ToolProgress } from '../../../chat/common/tools/languageModelToolsService.js';
12
import { createBrowserPageLink, DEFAULT_ELEMENT_LABEL, errorResult, playwrightInvoke } from './browserToolHelpers.js';
13
import { BrowserChatToolReferenceName } from '../../common/browserChatToolReferenceNames.js';
14
import { OpenPageToolId } from './openBrowserTool.js';
15
16
export const ClickBrowserToolData: IToolData = {
17
id: 'click_element',
18
toolReferenceName: BrowserChatToolReferenceName.ClickElement,
19
displayName: localize('clickBrowserTool.displayName', 'Click Element'),
20
userDescription: localize('clickBrowserTool.userDescription', 'Click an element in a browser page'),
21
modelDescription: 'Click on an element in a browser page.',
22
icon: Codicon.cursor,
23
source: ToolDataSource.Internal,
24
inputSchema: {
25
type: 'object',
26
properties: {
27
pageId: {
28
type: 'string',
29
description: `The browser page ID, acquired from context or the open tool.`
30
},
31
ref: {
32
type: 'string',
33
description: 'Element reference to click.'
34
},
35
selector: {
36
type: 'string',
37
description: 'Playwright selector of the element to click when "ref" is not available.'
38
},
39
element: {
40
type: 'string',
41
description: 'Human-readable description of the element to click (e.g., "submit button", "search icon").'
42
},
43
dblClick: {
44
type: 'boolean',
45
description: 'Set to true for double clicks. Default is false.'
46
},
47
button: {
48
type: 'string',
49
enum: ['left', 'right', 'middle'],
50
description: 'Mouse button to click with. Default is "left".'
51
},
52
},
53
required: ['pageId', 'element'],
54
$comment: 'One of "ref" or "selector" is required.',
55
},
56
};
57
58
interface IClickBrowserToolParams {
59
pageId: string;
60
ref?: string;
61
selector?: string;
62
element?: string;
63
dblClick?: boolean;
64
button?: 'left' | 'right' | 'middle';
65
}
66
67
export class ClickBrowserTool implements IToolImpl {
68
constructor(
69
@IPlaywrightService private readonly playwrightService: IPlaywrightService,
70
) { }
71
72
async prepareToolInvocation(_context: IToolInvocationPreparationContext, _token: CancellationToken): Promise<IPreparedToolInvocation | undefined> {
73
const params = _context.parameters as IClickBrowserToolParams;
74
const link = createBrowserPageLink(params.pageId);
75
const element = escapeMarkdownSyntaxTokens(params.element ?? DEFAULT_ELEMENT_LABEL);
76
return {
77
invocationMessage: params.button === 'right'
78
? new MarkdownString(localize('browser.click.invocation.right', "Right-clicking {0} in {1}", element, link))
79
: params.button === 'middle'
80
? new MarkdownString(localize('browser.click.invocation.middle', "Middle-clicking {0} in {1}", element, link))
81
: params.dblClick
82
? new MarkdownString(localize('browser.dblClick.invocation', "Double-clicking {0} in {1}", element, link))
83
: new MarkdownString(localize('browser.click.invocation', "Clicking {0} in {1}", element, link)),
84
pastTenseMessage: params.button === 'right'
85
? new MarkdownString(localize('browser.click.past.right', "Right-clicked {0} in {1}", element, link))
86
: params.button === 'middle'
87
? new MarkdownString(localize('browser.click.past.middle', "Middle-clicked {0} in {1}", element, link))
88
: params.dblClick
89
? new MarkdownString(localize('browser.dblClick.past', "Double-clicked {0} in {1}", element, link))
90
: new MarkdownString(localize('browser.click.past', "Clicked {0} in {1}", element, link)),
91
};
92
}
93
94
async invoke(invocation: IToolInvocation, _countTokens: CountTokensCallback, _progress: ToolProgress, _token: CancellationToken): Promise<IToolResult> {
95
const params = invocation.parameters as IClickBrowserToolParams;
96
97
if (!params.pageId) {
98
return errorResult(`No page ID provided. Use '${OpenPageToolId}' first.`);
99
}
100
101
let selector = params.selector;
102
if (params.ref) {
103
selector = `aria-ref=${params.ref}`;
104
}
105
106
if (!selector) {
107
return errorResult('Either a "ref" or "selector" parameter is required.');
108
}
109
110
const button = params.button ?? 'left';
111
112
if (params.dblClick) {
113
return playwrightInvoke(this.playwrightService, params.pageId, (page, sel, btn) => page.locator(sel).dblclick({ button: btn }), selector, button);
114
}
115
116
return playwrightInvoke(this.playwrightService, params.pageId, (page, sel, btn) => page.locator(sel).click({ button: btn }), selector, button);
117
}
118
}
119
120