appium-mcp 1.24.2 → 1.25.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 +6 -0
- package/README.md +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +2 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/interactions/pinch.d.ts +3 -0
- package/dist/tools/interactions/pinch.d.ts.map +1 -0
- package/dist/tools/interactions/pinch.js +152 -0
- package/dist/tools/interactions/pinch.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
- package/src/tools/index.ts +2 -0
- package/src/tools/interactions/pinch.ts +172 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [1.25.0](https://github.com/appium/appium-mcp/compare/v1.24.2...v1.25.0) (2026-03-11)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* add `appium_pinch` gesture tool for iOS and Android ([#203](https://github.com/appium/appium-mcp/issues/203)) ([ee0896e](https://github.com/appium/appium-mcp/commit/ee0896eb0d9a5dac6002c59683bee1aeee9d2b82))
|
|
6
|
+
|
|
1
7
|
## [1.24.2](https://github.com/appium/appium-mcp/compare/v1.24.1...v1.24.2) (2026-03-10)
|
|
2
8
|
|
|
3
9
|
### Bug Fixes
|
package/README.md
CHANGED
|
@@ -263,6 +263,7 @@ MCP Appium provides a comprehensive set of tools organized into the following ca
|
|
|
263
263
|
| `appium_double_tap` | Perform double tap on an element |
|
|
264
264
|
| `appium_long_press` | Perform a long press (press and hold) gesture on an element |
|
|
265
265
|
| `appium_drag_and_drop` | Perform a drag and drop gesture from a source location to a target location (supports element-to-element, element-to-coordinates, coordinates-to-element, and coordinates-to-coordinates) |
|
|
266
|
+
| `appium_pinch` | Perform a pinch gesture to zoom in (scale > 1) or zoom out (scale < 1) on an element or the whole screen. Works on both iOS and Android. |
|
|
266
267
|
| `appium_set_value` | Enter text into an input field |
|
|
267
268
|
| `appium_get_text` | Get text content from an element |
|
|
268
269
|
| `appium_handle_alert` | Accept or dismiss system/permission alerts, or click a dialog button by label |
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAyClC,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAgI3D"}
|
package/dist/tools/index.js
CHANGED
|
@@ -19,6 +19,7 @@ import clickElement from './interactions/click.js';
|
|
|
19
19
|
import doubleTap from './interactions/double-tap.js';
|
|
20
20
|
import longPress from './interactions/long-press.js';
|
|
21
21
|
import dragAndDrop from './interactions/drag-and-drop.js';
|
|
22
|
+
import pinch from './interactions/pinch.js';
|
|
22
23
|
import pressKey from './interactions/press-key.js';
|
|
23
24
|
import setValue from './interactions/set-value.js';
|
|
24
25
|
import getText from './interactions/get-text.js';
|
|
@@ -124,6 +125,7 @@ export default function registerTools(server) {
|
|
|
124
125
|
doubleTap(server);
|
|
125
126
|
longPress(server);
|
|
126
127
|
dragAndDrop(server);
|
|
128
|
+
pinch(server);
|
|
127
129
|
pressKey(server);
|
|
128
130
|
setValue(server);
|
|
129
131
|
getText(server);
|
package/dist/tools/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pinch.d.ts","sourceRoot":"","sources":["../../../src/tools/interactions/pinch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;AAWtD,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAgKnD"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { getDriver, getPlatformName, PLATFORM } from '../../session-store.js';
|
|
3
|
+
import { elementUUIDScheme } from '../../schema.js';
|
|
4
|
+
import { execute, getElementRect, getWindowRect, performActions, } from '../../command.js';
|
|
5
|
+
export default function pinch(server) {
|
|
6
|
+
const pinchSchema = z.object({
|
|
7
|
+
scale: z
|
|
8
|
+
.number()
|
|
9
|
+
.min(0.01)
|
|
10
|
+
.max(10)
|
|
11
|
+
.describe('Pinch scale. Use a value between 0 and 1 to zoom out (pinch close), and a value greater than 1 to zoom in (pinch open). Example: 0.5 = zoom out 50%, 2.0 = zoom in 2x.'),
|
|
12
|
+
elementUUID: elementUUIDScheme
|
|
13
|
+
.trim()
|
|
14
|
+
.min(1)
|
|
15
|
+
.optional()
|
|
16
|
+
.describe('Optional UUID of the element to pinch on. If not provided, the pinch gesture is applied to the whole screen.'),
|
|
17
|
+
velocity: z
|
|
18
|
+
.number()
|
|
19
|
+
.min(0.1)
|
|
20
|
+
.max(20)
|
|
21
|
+
.default(2.2)
|
|
22
|
+
.optional()
|
|
23
|
+
.describe('The velocity of the pinch in scale factor per second. Used natively by iOS for zoom in, and controls gesture speed for zoom out on both platforms. Default is 2.2.'),
|
|
24
|
+
});
|
|
25
|
+
server.addTool({
|
|
26
|
+
name: 'appium_pinch',
|
|
27
|
+
description: 'Perform a pinch gesture to zoom in or zoom out. Use scale < 1 to zoom out (pinch close) and scale > 1 to zoom in (pinch open). Works on both iOS and Android. Optionally target a specific element, otherwise the gesture applies to the whole screen.',
|
|
28
|
+
parameters: pinchSchema,
|
|
29
|
+
annotations: {
|
|
30
|
+
readOnlyHint: false,
|
|
31
|
+
openWorldHint: false,
|
|
32
|
+
},
|
|
33
|
+
execute: async (args, _context) => {
|
|
34
|
+
const driver = getDriver();
|
|
35
|
+
if (!driver) {
|
|
36
|
+
throw new Error('No driver found');
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const platform = getPlatformName(driver);
|
|
40
|
+
const { scale, elementUUID, velocity = 2.2 } = args;
|
|
41
|
+
const direction = scale < 1 ? 'close (zoom out)' : 'open (zoom in)';
|
|
42
|
+
// Compute center and spread from element or full screen
|
|
43
|
+
let cx, cy, spread;
|
|
44
|
+
let windowRect = null;
|
|
45
|
+
if (elementUUID) {
|
|
46
|
+
const rect = await getElementRect(driver, elementUUID);
|
|
47
|
+
cx = Math.floor(rect.x + rect.width / 2);
|
|
48
|
+
cy = Math.floor(rect.y + rect.height / 2);
|
|
49
|
+
spread = Math.floor(Math.min(rect.width, rect.height) * 0.3);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
windowRect = await getWindowRect(driver);
|
|
53
|
+
cx = Math.floor(windowRect.width / 2);
|
|
54
|
+
cy = Math.floor(windowRect.height / 2);
|
|
55
|
+
spread = Math.floor(Math.min(windowRect.width, windowRect.height) * 0.3);
|
|
56
|
+
}
|
|
57
|
+
if (scale < 1) {
|
|
58
|
+
// Zoom out on both platforms: W3C Actions, fingers start far, move close
|
|
59
|
+
const startSpread = spread;
|
|
60
|
+
const endSpread = Math.max(1, Math.floor(spread * scale));
|
|
61
|
+
const duration = Math.floor((1 / Math.abs(velocity)) * 1000);
|
|
62
|
+
await performActions(driver, [
|
|
63
|
+
{
|
|
64
|
+
type: 'pointer',
|
|
65
|
+
id: 'finger1',
|
|
66
|
+
parameters: { pointerType: 'touch' },
|
|
67
|
+
actions: [
|
|
68
|
+
{
|
|
69
|
+
type: 'pointerMove',
|
|
70
|
+
duration: 0,
|
|
71
|
+
x: cx - startSpread,
|
|
72
|
+
y: cy,
|
|
73
|
+
},
|
|
74
|
+
{ type: 'pointerDown', button: 0 },
|
|
75
|
+
{ type: 'pointerMove', duration, x: cx - endSpread, y: cy },
|
|
76
|
+
{ type: 'pointerUp', button: 0 },
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
type: 'pointer',
|
|
81
|
+
id: 'finger2',
|
|
82
|
+
parameters: { pointerType: 'touch' },
|
|
83
|
+
actions: [
|
|
84
|
+
{
|
|
85
|
+
type: 'pointerMove',
|
|
86
|
+
duration: 0,
|
|
87
|
+
x: cx + startSpread,
|
|
88
|
+
y: cy,
|
|
89
|
+
},
|
|
90
|
+
{ type: 'pointerDown', button: 0 },
|
|
91
|
+
{ type: 'pointerMove', duration, x: cx + endSpread, y: cy },
|
|
92
|
+
{ type: 'pointerUp', button: 0 },
|
|
93
|
+
],
|
|
94
|
+
},
|
|
95
|
+
]);
|
|
96
|
+
}
|
|
97
|
+
else if (platform === PLATFORM.ios) {
|
|
98
|
+
// Zoom in on iOS: mobile: pinch
|
|
99
|
+
const params = {
|
|
100
|
+
scale,
|
|
101
|
+
velocity: Math.abs(velocity),
|
|
102
|
+
};
|
|
103
|
+
if (elementUUID) {
|
|
104
|
+
params.elementId = elementUUID;
|
|
105
|
+
}
|
|
106
|
+
await execute(driver, 'mobile: pinch', params);
|
|
107
|
+
}
|
|
108
|
+
else if (platform === PLATFORM.android) {
|
|
109
|
+
// Zoom in on Android: mobile: pinchOpenGesture
|
|
110
|
+
// Convert scale factor to percent (0–1) for pinchOpenGesture:
|
|
111
|
+
// scale=2 → 0.5, scale=4 → 0.75, scale=10 → 0.9. Capped at 0.99 to avoid edge collisions.
|
|
112
|
+
const percent = Math.min(0.99, 1 - 1 / scale);
|
|
113
|
+
const params = { percent };
|
|
114
|
+
if (elementUUID) {
|
|
115
|
+
params.elementId = elementUUID;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
const rect = windowRect;
|
|
119
|
+
params.left = rect.x ?? 0;
|
|
120
|
+
params.top = rect.y ?? 0;
|
|
121
|
+
params.width = rect.width;
|
|
122
|
+
params.height = rect.height;
|
|
123
|
+
}
|
|
124
|
+
await execute(driver, 'mobile: pinchOpenGesture', params);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
throw new Error(`Unsupported platform: ${platform}. Only Android and iOS are supported.`);
|
|
128
|
+
}
|
|
129
|
+
const target = elementUUID ? `element ${elementUUID}` : 'screen';
|
|
130
|
+
return {
|
|
131
|
+
content: [
|
|
132
|
+
{
|
|
133
|
+
type: 'text',
|
|
134
|
+
text: `Successfully performed pinch ${direction} (scale=${scale}) on ${target}.`,
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
return {
|
|
141
|
+
content: [
|
|
142
|
+
{
|
|
143
|
+
type: 'text',
|
|
144
|
+
text: `Failed to perform pinch gesture. err: ${err.toString()}`,
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=pinch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pinch.js","sourceRoot":"","sources":["../../../src/tools/interactions/pinch.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/server.json
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
"name": "io.github.appium/appium-mcp",
|
|
4
4
|
"title": "MCP Appium - Mobile Development and Automation Server",
|
|
5
5
|
"description": "MCP server for Appium mobile automation on iOS and Android devices with test creation tools.",
|
|
6
|
-
"version": "1.
|
|
6
|
+
"version": "1.25.0",
|
|
7
7
|
"packages": [
|
|
8
8
|
{
|
|
9
9
|
"registryType": "npm",
|
|
10
10
|
"identifier": "appium-mcp",
|
|
11
|
-
"version": "1.
|
|
11
|
+
"version": "1.25.0",
|
|
12
12
|
"transport": {
|
|
13
13
|
"type": "stdio"
|
|
14
14
|
}
|
package/src/tools/index.ts
CHANGED
|
@@ -34,6 +34,7 @@ import clickElement from './interactions/click.js';
|
|
|
34
34
|
import doubleTap from './interactions/double-tap.js';
|
|
35
35
|
import longPress from './interactions/long-press.js';
|
|
36
36
|
import dragAndDrop from './interactions/drag-and-drop.js';
|
|
37
|
+
import pinch from './interactions/pinch.js';
|
|
37
38
|
import pressKey from './interactions/press-key.js';
|
|
38
39
|
import setValue from './interactions/set-value.js';
|
|
39
40
|
import getText from './interactions/get-text.js';
|
|
@@ -148,6 +149,7 @@ export default function registerTools(server: FastMCP): void {
|
|
|
148
149
|
doubleTap(server);
|
|
149
150
|
longPress(server);
|
|
150
151
|
dragAndDrop(server);
|
|
152
|
+
pinch(server);
|
|
151
153
|
pressKey(server);
|
|
152
154
|
setValue(server);
|
|
153
155
|
getText(server);
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import type { ContentResult, FastMCP } from 'fastmcp';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { getDriver, getPlatformName, PLATFORM } from '../../session-store.js';
|
|
4
|
+
import { elementUUIDScheme } from '../../schema.js';
|
|
5
|
+
import {
|
|
6
|
+
execute,
|
|
7
|
+
getElementRect,
|
|
8
|
+
getWindowRect,
|
|
9
|
+
performActions,
|
|
10
|
+
} from '../../command.js';
|
|
11
|
+
|
|
12
|
+
export default function pinch(server: FastMCP): void {
|
|
13
|
+
const pinchSchema = z.object({
|
|
14
|
+
scale: z
|
|
15
|
+
.number()
|
|
16
|
+
.min(0.01)
|
|
17
|
+
.max(10)
|
|
18
|
+
.describe(
|
|
19
|
+
'Pinch scale. Use a value between 0 and 1 to zoom out (pinch close), and a value greater than 1 to zoom in (pinch open). Example: 0.5 = zoom out 50%, 2.0 = zoom in 2x.'
|
|
20
|
+
),
|
|
21
|
+
elementUUID: elementUUIDScheme
|
|
22
|
+
.trim()
|
|
23
|
+
.min(1)
|
|
24
|
+
.optional()
|
|
25
|
+
.describe(
|
|
26
|
+
'Optional UUID of the element to pinch on. If not provided, the pinch gesture is applied to the whole screen.'
|
|
27
|
+
),
|
|
28
|
+
velocity: z
|
|
29
|
+
.number()
|
|
30
|
+
.min(0.1)
|
|
31
|
+
.max(20)
|
|
32
|
+
.default(2.2)
|
|
33
|
+
.optional()
|
|
34
|
+
.describe(
|
|
35
|
+
'The velocity of the pinch in scale factor per second. Used natively by iOS for zoom in, and controls gesture speed for zoom out on both platforms. Default is 2.2.'
|
|
36
|
+
),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
server.addTool({
|
|
40
|
+
name: 'appium_pinch',
|
|
41
|
+
description:
|
|
42
|
+
'Perform a pinch gesture to zoom in or zoom out. Use scale < 1 to zoom out (pinch close) and scale > 1 to zoom in (pinch open). Works on both iOS and Android. Optionally target a specific element, otherwise the gesture applies to the whole screen.',
|
|
43
|
+
parameters: pinchSchema,
|
|
44
|
+
annotations: {
|
|
45
|
+
readOnlyHint: false,
|
|
46
|
+
openWorldHint: false,
|
|
47
|
+
},
|
|
48
|
+
execute: async (
|
|
49
|
+
args: z.infer<typeof pinchSchema>,
|
|
50
|
+
_context: Record<string, unknown> | undefined
|
|
51
|
+
): Promise<ContentResult> => {
|
|
52
|
+
const driver = getDriver();
|
|
53
|
+
if (!driver) {
|
|
54
|
+
throw new Error('No driver found');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
const platform = getPlatformName(driver);
|
|
59
|
+
const { scale, elementUUID, velocity = 2.2 } = args;
|
|
60
|
+
const direction = scale < 1 ? 'close (zoom out)' : 'open (zoom in)';
|
|
61
|
+
|
|
62
|
+
// Compute center and spread from element or full screen
|
|
63
|
+
let cx: number, cy: number, spread: number;
|
|
64
|
+
let windowRect: Awaited<ReturnType<typeof getWindowRect>> | null = null;
|
|
65
|
+
if (elementUUID) {
|
|
66
|
+
const rect = await getElementRect(driver, elementUUID);
|
|
67
|
+
cx = Math.floor(rect.x + rect.width / 2);
|
|
68
|
+
cy = Math.floor(rect.y + rect.height / 2);
|
|
69
|
+
spread = Math.floor(Math.min(rect.width, rect.height) * 0.3);
|
|
70
|
+
} else {
|
|
71
|
+
windowRect = await getWindowRect(driver);
|
|
72
|
+
cx = Math.floor(windowRect.width / 2);
|
|
73
|
+
cy = Math.floor(windowRect.height / 2);
|
|
74
|
+
spread = Math.floor(
|
|
75
|
+
Math.min(windowRect.width, windowRect.height) * 0.3
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (scale < 1) {
|
|
80
|
+
// Zoom out on both platforms: W3C Actions, fingers start far, move close
|
|
81
|
+
const startSpread = spread;
|
|
82
|
+
const endSpread = Math.max(1, Math.floor(spread * scale));
|
|
83
|
+
const duration = Math.floor((1 / Math.abs(velocity)) * 1000);
|
|
84
|
+
|
|
85
|
+
await performActions(driver, [
|
|
86
|
+
{
|
|
87
|
+
type: 'pointer',
|
|
88
|
+
id: 'finger1',
|
|
89
|
+
parameters: { pointerType: 'touch' },
|
|
90
|
+
actions: [
|
|
91
|
+
{
|
|
92
|
+
type: 'pointerMove',
|
|
93
|
+
duration: 0,
|
|
94
|
+
x: cx - startSpread,
|
|
95
|
+
y: cy,
|
|
96
|
+
},
|
|
97
|
+
{ type: 'pointerDown', button: 0 },
|
|
98
|
+
{ type: 'pointerMove', duration, x: cx - endSpread, y: cy },
|
|
99
|
+
{ type: 'pointerUp', button: 0 },
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
type: 'pointer',
|
|
104
|
+
id: 'finger2',
|
|
105
|
+
parameters: { pointerType: 'touch' },
|
|
106
|
+
actions: [
|
|
107
|
+
{
|
|
108
|
+
type: 'pointerMove',
|
|
109
|
+
duration: 0,
|
|
110
|
+
x: cx + startSpread,
|
|
111
|
+
y: cy,
|
|
112
|
+
},
|
|
113
|
+
{ type: 'pointerDown', button: 0 },
|
|
114
|
+
{ type: 'pointerMove', duration, x: cx + endSpread, y: cy },
|
|
115
|
+
{ type: 'pointerUp', button: 0 },
|
|
116
|
+
],
|
|
117
|
+
},
|
|
118
|
+
]);
|
|
119
|
+
} else if (platform === PLATFORM.ios) {
|
|
120
|
+
// Zoom in on iOS: mobile: pinch
|
|
121
|
+
const params: Record<string, any> = {
|
|
122
|
+
scale,
|
|
123
|
+
velocity: Math.abs(velocity),
|
|
124
|
+
};
|
|
125
|
+
if (elementUUID) {
|
|
126
|
+
params.elementId = elementUUID;
|
|
127
|
+
}
|
|
128
|
+
await execute(driver, 'mobile: pinch', params);
|
|
129
|
+
} else if (platform === PLATFORM.android) {
|
|
130
|
+
// Zoom in on Android: mobile: pinchOpenGesture
|
|
131
|
+
// Convert scale factor to percent (0–1) for pinchOpenGesture:
|
|
132
|
+
// scale=2 → 0.5, scale=4 → 0.75, scale=10 → 0.9. Capped at 0.99 to avoid edge collisions.
|
|
133
|
+
const percent = Math.min(0.99, 1 - 1 / scale);
|
|
134
|
+
const params: Record<string, any> = { percent };
|
|
135
|
+
if (elementUUID) {
|
|
136
|
+
params.elementId = elementUUID;
|
|
137
|
+
} else {
|
|
138
|
+
const rect = windowRect!;
|
|
139
|
+
params.left = rect.x ?? 0;
|
|
140
|
+
params.top = rect.y ?? 0;
|
|
141
|
+
params.width = rect.width;
|
|
142
|
+
params.height = rect.height;
|
|
143
|
+
}
|
|
144
|
+
await execute(driver, 'mobile: pinchOpenGesture', params);
|
|
145
|
+
} else {
|
|
146
|
+
throw new Error(
|
|
147
|
+
`Unsupported platform: ${platform}. Only Android and iOS are supported.`
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const target = elementUUID ? `element ${elementUUID}` : 'screen';
|
|
152
|
+
return {
|
|
153
|
+
content: [
|
|
154
|
+
{
|
|
155
|
+
type: 'text',
|
|
156
|
+
text: `Successfully performed pinch ${direction} (scale=${scale}) on ${target}.`,
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
};
|
|
160
|
+
} catch (err: any) {
|
|
161
|
+
return {
|
|
162
|
+
content: [
|
|
163
|
+
{
|
|
164
|
+
type: 'text',
|
|
165
|
+
text: `Failed to perform pinch gesture. err: ${err.toString()}`,
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
}
|