Path: blob/main/src/vs/workbench/contrib/browserView/electron-browser/tools/dragElementTool.ts
13405 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import type { CancellationToken } from '../../../../../base/common/cancellation.js';6import { Codicon } from '../../../../../base/common/codicons.js';7import { escapeMarkdownSyntaxTokens, MarkdownString } from '../../../../../base/common/htmlContent.js';8import { localize } from '../../../../../nls.js';9import { IPlaywrightService } from '../../../../../platform/browserView/common/playwrightService.js';10import { ToolDataSource, type CountTokensCallback, type IPreparedToolInvocation, type IToolData, type IToolImpl, type IToolInvocation, type IToolInvocationPreparationContext, type IToolResult, type ToolProgress } from '../../../chat/common/tools/languageModelToolsService.js';11import { createBrowserPageLink, DEFAULT_ELEMENT_LABEL, errorResult, playwrightInvoke } from './browserToolHelpers.js';12import { BrowserChatToolReferenceName } from '../../common/browserChatToolReferenceNames.js';13import { OpenPageToolId } from './openBrowserTool.js';1415export const DragElementToolData: IToolData = {16id: 'drag_element',17toolReferenceName: BrowserChatToolReferenceName.DragElement,18displayName: localize('dragElementTool.displayName', 'Drag Element'),19userDescription: localize('dragElementTool.userDescription', 'Drag an element over another element'),20modelDescription: 'Drag an element over another element in a browser page.',21icon: Codicon.move,22source: ToolDataSource.Internal,23inputSchema: {24type: 'object',25properties: {26pageId: {27type: 'string',28description: `The browser page ID, acquired from context or the open tool.`29},30fromRef: {31type: 'string',32description: 'Element reference of the element to drag.'33},34fromSelector: {35type: 'string',36description: 'Playwright selector of the element to drag when "fromRef" is not available.'37},38fromElement: {39type: 'string',40description: 'Human-readable description of the element to drag (e.g., "file item", "draggable card").'41},42toRef: {43type: 'string',44description: 'Element reference of the element to drop onto.'45},46toSelector: {47type: 'string',48description: 'Playwright selector of the element to drop onto when "toRef" is not available.'49},50toElement: {51type: 'string',52description: 'Human-readable description of the element to drop onto (e.g., "drop zone", "target folder").'53},54},55required: ['pageId', 'fromElement', 'toElement'],56$comment: 'One of "fromRef" or "fromSelector" is required, and one of "toRef" or "toSelector" is required.',57},58};5960interface IDragElementToolParams {61pageId: string;62fromRef?: string;63fromSelector?: string;64fromElement?: string;65toRef?: string;66toSelector?: string;67toElement?: string;68}6970export class DragElementTool implements IToolImpl {71constructor(72@IPlaywrightService private readonly playwrightService: IPlaywrightService,73) { }7475async prepareToolInvocation(_context: IToolInvocationPreparationContext, _token: CancellationToken): Promise<IPreparedToolInvocation | undefined> {76const params = _context.parameters as IDragElementToolParams;77const link = createBrowserPageLink(params.pageId);78const fromElement = escapeMarkdownSyntaxTokens(params.fromElement ?? DEFAULT_ELEMENT_LABEL);79const toElement = escapeMarkdownSyntaxTokens(params.toElement ?? DEFAULT_ELEMENT_LABEL);80return {81invocationMessage: new MarkdownString(localize('browser.drag.invocation', "Dragging {0} to {1} in {2}", fromElement, toElement, link)),82pastTenseMessage: new MarkdownString(localize('browser.drag.past', "Dragged {0} to {1} in {2}", fromElement, toElement, link)),83};84}8586async invoke(invocation: IToolInvocation, _countTokens: CountTokensCallback, _progress: ToolProgress, _token: CancellationToken): Promise<IToolResult> {87const params = invocation.parameters as IDragElementToolParams;8889if (!params.pageId) {90return errorResult(`No page ID provided. Use '${OpenPageToolId}' first.`);91}9293let fromSelector = params.fromSelector;94if (params.fromRef) {95fromSelector = `aria-ref=${params.fromRef}`;96}97if (!fromSelector) {98return errorResult('Either a "fromRef" or "fromSelector" parameter is required for the source element.');99}100101let toSelector = params.toSelector;102if (params.toRef) {103toSelector = `aria-ref=${params.toRef}`;104}105if (!toSelector) {106return errorResult('Either a "toRef" or "toSelector" parameter is required for the target element.');107}108109return playwrightInvoke(this.playwrightService, params.pageId, (page, from, to) => page.dragAndDrop(from, to), fromSelector, toSelector);110}111}112113114