@hypothesi/tauri-mcp-server 0.8.3 → 0.10.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.
@@ -0,0 +1,395 @@
1
+ /**
2
+ * Element picker overlay for MCP Server Tauri.
3
+ *
4
+ * Activated by the agent via webview_select_element. Displays a hover highlight,
5
+ * context tooltip, and cancel bar. On click (desktop) or two-tap (mobile) the
6
+ * selected element's metadata is emitted as a Tauri event so the MCP server can
7
+ * retrieve it asynchronously.
8
+ *
9
+ * @param {Object} params
10
+ * @param {string} params.mode - 'pick' (agent-initiated picker)
11
+ * @param {string} params.pickerId - Unique identifier for this picker session
12
+ */
13
+ (function(params) {
14
+ var mode = params.mode;
15
+ var pickerId = params.pickerId;
16
+
17
+ // Duplicate-activation guard
18
+ if (window.__MCP_PICKER_ACTIVE__) {
19
+ // Cancel the previous picker
20
+ var prevId = window.__MCP_PICKER_ACTIVE__;
21
+ cleanup();
22
+ if (window.__TAURI__ && window.__TAURI__.event && window.__TAURI__.event.emit) {
23
+ window.__TAURI__.event.emit('__element_picked', { pickerId: prevId, cancelled: true });
24
+ }
25
+ }
26
+ window.__MCP_PICKER_ACTIVE__ = pickerId;
27
+
28
+ var isTouch = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0);
29
+ var highlight = null;
30
+ var tooltip = null;
31
+ var cancelBar = null;
32
+ var trackedElement = null; // element currently being highlighted
33
+ var rafId = null; // requestAnimationFrame handle for cyclic repositioning
34
+
35
+ // ── Velocity-based hover throttling state ──────────────────────────────
36
+ var lastMouseX = 0;
37
+ var lastMouseY = 0;
38
+ var lastMouseTime = 0;
39
+ var mouseVelocity = 0;
40
+ var hoverUpdateTimer = null;
41
+
42
+ // ── Cancel bar ─────────────────────────────────────────────────────────
43
+ cancelBar = document.createElement('div');
44
+ cancelBar.setAttribute('data-mcp-picker', 'cancel-bar');
45
+ var cancelBarAtTop = true;
46
+ cancelBar.style.cssText =
47
+ 'position:fixed;top:0;left:0;right:0;z-index:2147483647;height:40px;' +
48
+ 'background:rgba(30,41,59,0.95);display:flex;align-items:center;' +
49
+ 'justify-content:space-between;padding:0 12px;font:13px/1 system-ui,sans-serif;' +
50
+ 'color:#E2E8F0;box-sizing:border-box;' +
51
+ 'transition:top 0.2s ease,bottom 0.2s ease;';
52
+
53
+ var cancelText = document.createElement('span');
54
+ cancelText.textContent = 'MCP Element Picker \u2014 Click to select | ESC or tap X to cancel';
55
+ cancelText.style.cssText = 'overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;';
56
+
57
+ // Move button — toggles bar between top and bottom
58
+ var moveBtn = document.createElement('button');
59
+ moveBtn.setAttribute('data-mcp-picker', 'move-btn');
60
+ moveBtn.textContent = '\u2193'; // ↓
61
+ moveBtn.title = 'Move bar to bottom';
62
+ moveBtn.style.cssText =
63
+ 'background:none;border:none;color:#94A3B8;font-size:16px;cursor:pointer;' +
64
+ 'width:32px;height:40px;display:flex;align-items:center;justify-content:center;' +
65
+ 'flex-shrink:0;';
66
+ function toggleCancelBarPosition(e) {
67
+ e.stopPropagation();
68
+ e.preventDefault();
69
+ cancelBarAtTop = !cancelBarAtTop;
70
+ cancelBar.style.top = cancelBarAtTop ? '0' : 'auto';
71
+ cancelBar.style.bottom = cancelBarAtTop ? 'auto' : '0';
72
+ moveBtn.textContent = cancelBarAtTop ? '\u2193' : '\u2191'; // ↓ or ↑
73
+ moveBtn.title = cancelBarAtTop ? 'Move bar to bottom' : 'Move bar to top';
74
+ }
75
+ moveBtn.addEventListener('click', toggleCancelBarPosition);
76
+ moveBtn.addEventListener('touchend', toggleCancelBarPosition);
77
+
78
+ var cancelBtn = document.createElement('button');
79
+ cancelBtn.setAttribute('data-mcp-picker', 'cancel-btn');
80
+ cancelBtn.textContent = '\u2715';
81
+ cancelBtn.style.cssText =
82
+ 'background:none;border:none;color:#E2E8F0;font-size:20px;cursor:pointer;' +
83
+ 'width:40px;height:40px;display:flex;align-items:center;justify-content:center;' +
84
+ 'flex-shrink:0;';
85
+ cancelBtn.addEventListener('click', function(e) {
86
+ e.stopPropagation();
87
+ cancelPicker();
88
+ });
89
+ cancelBtn.addEventListener('touchend', function(e) {
90
+ e.stopPropagation();
91
+ e.preventDefault();
92
+ cancelPicker();
93
+ });
94
+
95
+ cancelBar.appendChild(cancelText);
96
+ cancelBar.appendChild(moveBtn);
97
+ cancelBar.appendChild(cancelBtn);
98
+ document.body.appendChild(cancelBar);
99
+
100
+ // ── Highlight helpers ──────────────────────────────────────────────────
101
+ function createHighlight() {
102
+ var el = document.createElement('div');
103
+ el.setAttribute('data-mcp-picker', 'highlight');
104
+ el.style.cssText =
105
+ 'position:fixed;z-index:2147483645;pointer-events:none;' +
106
+ 'background:rgba(59,130,246,0.15);border:2px solid #3B82F6;';
107
+ document.body.appendChild(el);
108
+ return el;
109
+ }
110
+
111
+ function positionHighlight(el, target) {
112
+ var rect = target.getBoundingClientRect();
113
+ el.style.top = rect.top + 'px';
114
+ el.style.left = rect.left + 'px';
115
+ el.style.width = rect.width + 'px';
116
+ el.style.height = rect.height + 'px';
117
+ }
118
+
119
+ // ── Cyclic highlight repositioning via rAF ─────────────────────────────
120
+ // Keeps the highlight tracking animated or repositioned elements at ~60fps.
121
+ function startTracking() {
122
+ if (rafId) return;
123
+ function tick() {
124
+ if (trackedElement && highlight) {
125
+ positionHighlight(highlight, trackedElement);
126
+ }
127
+ rafId = requestAnimationFrame(tick);
128
+ }
129
+ rafId = requestAnimationFrame(tick);
130
+ }
131
+
132
+ function stopTracking() {
133
+ if (rafId) {
134
+ cancelAnimationFrame(rafId);
135
+ rafId = null;
136
+ }
137
+ }
138
+
139
+ // ── Tooltip helpers ────────────────────────────────────────────────────
140
+ function showTooltip(target) {
141
+ if (!tooltip) {
142
+ tooltip = document.createElement('div');
143
+ tooltip.setAttribute('data-mcp-picker', 'tooltip');
144
+ tooltip.style.cssText =
145
+ 'position:fixed;z-index:2147483646;pointer-events:none;' +
146
+ 'background:#1E293B;color:#E2E8F0;font:12px/1.4 monospace;' +
147
+ 'padding:4px 8px;border-radius:4px;white-space:nowrap;max-width:300px;' +
148
+ 'overflow:hidden;text-overflow:ellipsis;';
149
+ document.body.appendChild(tooltip);
150
+ }
151
+
152
+ var rect = target.getBoundingClientRect();
153
+ var tag = target.tagName.toLowerCase();
154
+ var id = target.id ? '#' + target.id : '';
155
+ var cls = target.className && typeof target.className === 'string'
156
+ ? '.' + target.className.trim().split(/\s+/).join('.')
157
+ : '';
158
+ var label = (tag + id + cls);
159
+ if (label.length > 60) label = label.substring(0, 57) + '...';
160
+ label += ' (' + Math.round(rect.width) + '\u00d7' + Math.round(rect.height) + ')';
161
+ tooltip.textContent = label;
162
+
163
+ // Position above or below the element
164
+ var tooltipTop = rect.top - 28;
165
+ if (tooltipTop < 44) { // below the cancel bar (40px + 4px padding)
166
+ tooltipTop = rect.bottom + 4;
167
+ }
168
+ tooltip.style.top = tooltipTop + 'px';
169
+ tooltip.style.left = Math.max(4, rect.left) + 'px';
170
+ }
171
+
172
+ function hideTooltip() {
173
+ if (tooltip && tooltip.parentNode) {
174
+ tooltip.parentNode.removeChild(tooltip);
175
+ tooltip = null;
176
+ }
177
+ }
178
+
179
+ // ── Element detection ──────────────────────────────────────────────────
180
+ // Uses the shared elementsFromPoint helper from bridge.js when available,
181
+ // falls back to document.elementFromPoint.
182
+ function findElementAt(x, y) {
183
+ if (window.__MCP_GET_ELEMENT_AT_POINT__) {
184
+ return window.__MCP_GET_ELEMENT_AT_POINT__(x, y);
185
+ }
186
+ // Fallback: hide highlight, use single elementFromPoint
187
+ if (highlight) highlight.style.display = 'none';
188
+ var el = document.elementFromPoint(x, y);
189
+ if (highlight) highlight.style.display = '';
190
+ return el;
191
+ }
192
+
193
+ // ── Picker element detection guard (fallback for findElementAt) ────────
194
+ function isPickerUI(el) {
195
+ while (el) {
196
+ if (el.getAttribute && el.getAttribute('data-mcp-picker')) {
197
+ return true;
198
+ }
199
+ el = el.parentElement;
200
+ }
201
+ return false;
202
+ }
203
+
204
+ // ── Selection ──────────────────────────────────────────────────────────
205
+ function selectElement(target) {
206
+ var metadata;
207
+ if (window.__MCP_COLLECT_ELEMENT_METADATA__) {
208
+ metadata = window.__MCP_COLLECT_ELEMENT_METADATA__(target);
209
+ } else {
210
+ metadata = { tag: target.tagName.toLowerCase(), cssSelector: '' };
211
+ }
212
+
213
+ // Store in window for later retrieval
214
+ window.__MCP_PICKED_ELEMENT__ = metadata;
215
+
216
+ // Remove overlay + tooltip but keep highlight for screenshot
217
+ removeCancelBar();
218
+ hideTooltip();
219
+ stopTracking();
220
+ removeListeners();
221
+
222
+ // Emit Tauri event
223
+ if (window.__TAURI__ && window.__TAURI__.event && window.__TAURI__.event.emit) {
224
+ window.__TAURI__.event.emit('__element_picked', { pickerId: pickerId, element: metadata });
225
+ }
226
+
227
+ window.__MCP_PICKER_ACTIVE__ = null;
228
+ return 'Element selected: ' + metadata.tag + (metadata.id ? '#' + metadata.id : '');
229
+ }
230
+
231
+ // ── Cancellation ──────────────────────────────────────────────────────
232
+ function cancelPicker() {
233
+ cleanup();
234
+ if (window.__TAURI__ && window.__TAURI__.event && window.__TAURI__.event.emit) {
235
+ window.__TAURI__.event.emit('__element_picked', { pickerId: pickerId, cancelled: true });
236
+ }
237
+ window.__MCP_PICKER_ACTIVE__ = null;
238
+ }
239
+
240
+ // ── Cleanup ────────────────────────────────────────────────────────────
241
+ function removeCancelBar() {
242
+ if (cancelBar && cancelBar.parentNode) {
243
+ cancelBar.parentNode.removeChild(cancelBar);
244
+ cancelBar = null;
245
+ }
246
+ }
247
+
248
+ function removeHighlight() {
249
+ if (highlight && highlight.parentNode) {
250
+ highlight.parentNode.removeChild(highlight);
251
+ highlight = null;
252
+ }
253
+ }
254
+
255
+ function cleanup() {
256
+ removeCancelBar();
257
+ removeHighlight();
258
+ hideTooltip();
259
+ stopTracking();
260
+ removeListeners();
261
+ trackedElement = null;
262
+ if (hoverUpdateTimer) {
263
+ clearTimeout(hoverUpdateTimer);
264
+ hoverUpdateTimer = null;
265
+ }
266
+ window.__MCP_PICKER_ACTIVE__ = null;
267
+ }
268
+
269
+ // ── Core hover-update logic (shared by throttled and immediate paths) ──
270
+ function updateHoveredElement() {
271
+ var el = findElementAt(lastMouseX, lastMouseY);
272
+
273
+ if (!el || isPickerUI(el)) return;
274
+
275
+ if (el === trackedElement) return; // no change
276
+ trackedElement = el;
277
+
278
+ if (!highlight) {
279
+ highlight = createHighlight();
280
+ startTracking();
281
+ }
282
+ positionHighlight(highlight, el);
283
+ showTooltip(el);
284
+ }
285
+
286
+ // ── Desktop: hover + click with velocity throttling ────────────────────
287
+ function onMouseMove(e) {
288
+ var now = performance.now();
289
+ var dx = e.clientX - lastMouseX;
290
+ var dy = e.clientY - lastMouseY;
291
+ var dt = now - lastMouseTime;
292
+ var distance = Math.sqrt(dx * dx + dy * dy);
293
+
294
+ lastMouseX = e.clientX;
295
+ lastMouseY = e.clientY;
296
+
297
+ // Calculate velocity in pixels per second
298
+ mouseVelocity = dt > 0 ? (distance / dt) * 1000 : 0;
299
+ lastMouseTime = now;
300
+
301
+ // If moving fast (>600 px/s), throttle updates to ~28fps
302
+ if (mouseVelocity > 600) {
303
+ if (hoverUpdateTimer) {
304
+ clearTimeout(hoverUpdateTimer);
305
+ }
306
+ hoverUpdateTimer = setTimeout(updateHoveredElement, 36); // ~28fps
307
+ } else {
308
+ if (hoverUpdateTimer) {
309
+ clearTimeout(hoverUpdateTimer);
310
+ hoverUpdateTimer = null;
311
+ }
312
+ updateHoveredElement();
313
+ }
314
+ }
315
+
316
+ function onClick(e) {
317
+ // Let clicks on picker UI (cancel, move buttons) pass through to their handlers
318
+ if (isPickerUI(e.target)) return;
319
+
320
+ e.preventDefault();
321
+ e.stopPropagation();
322
+
323
+ var el = findElementAt(e.clientX, e.clientY);
324
+
325
+ if (!el || isPickerUI(el)) return;
326
+
327
+ selectElement(el);
328
+ }
329
+
330
+ // ── Mobile: two-tap ────────────────────────────────────────────────────
331
+ var lastTapTarget = null;
332
+
333
+ function onTouchEnd(e) {
334
+ var touch = e.changedTouches[0];
335
+ if (!touch) return;
336
+
337
+ var el = findElementAt(touch.clientX, touch.clientY);
338
+
339
+ // Let taps on picker UI (cancel, move buttons) pass through to their handlers
340
+ if (!el || isPickerUI(el)) return;
341
+
342
+ e.preventDefault();
343
+ e.stopPropagation();
344
+
345
+ if (lastTapTarget === el) {
346
+ // Second tap on same element -> confirm
347
+ selectElement(el);
348
+ } else {
349
+ // First tap (or different element) -> highlight
350
+ lastTapTarget = el;
351
+ trackedElement = el;
352
+
353
+ if (!highlight) {
354
+ highlight = createHighlight();
355
+ startTracking();
356
+ }
357
+ positionHighlight(highlight, el);
358
+ showTooltip(el);
359
+
360
+ if (cancelText) {
361
+ cancelText.textContent = 'Tap element again to send | X Cancel';
362
+ }
363
+ }
364
+ }
365
+
366
+ // ── Keyboard escape ────────────────────────────────────────────────────
367
+ function onKeyDown(e) {
368
+ if (e.key === 'Escape') {
369
+ e.preventDefault();
370
+ e.stopPropagation();
371
+ cancelPicker();
372
+ }
373
+ }
374
+
375
+ // ── Listener management ────────────────────────────────────────────────
376
+ function removeListeners() {
377
+ document.removeEventListener('mousemove', onMouseMove, true);
378
+ document.removeEventListener('click', onClick, true);
379
+ document.removeEventListener('touchend', onTouchEnd, true);
380
+ document.removeEventListener('keydown', onKeyDown, true);
381
+ }
382
+
383
+ // Attach appropriate listeners based on device
384
+ document.addEventListener('keydown', onKeyDown, true);
385
+
386
+ if (isTouch) {
387
+ document.addEventListener('touchend', onTouchEnd, true);
388
+ }
389
+
390
+ // Always attach mouse listeners (hybrid devices like touch laptops)
391
+ document.addEventListener('mousemove', onMouseMove, true);
392
+ document.addEventListener('click', onClick, true);
393
+
394
+ return 'Picker activated (id: ' + pickerId + ')';
395
+ })
@@ -0,0 +1,25 @@
1
+ /**
2
+ * html2canvas-pro library loader
3
+ *
4
+ * Loads the html2canvas-pro library from node_modules and provides it as a string
5
+ * that can be injected into the webview. html2canvas-pro is a fork of html2canvas
6
+ * that adds support for modern CSS color functions like oklch(), oklab(), lab(),
7
+ * lch(), and color().
8
+ */
9
+ /** Script ID used for the html2canvas library in the script registry. */
10
+ export declare const HTML2CANVAS_SCRIPT_ID = "__mcp_html2canvas__";
11
+ /**
12
+ * Get the html2canvas-pro library source code.
13
+ * Loaded lazily and cached.
14
+ */
15
+ export declare function getHtml2CanvasSource(): string;
16
+ /**
17
+ * Build a script that captures a screenshot using html2canvas.
18
+ * Assumes html2canvas is already loaded (either via script manager or inline).
19
+ */
20
+ export declare function buildScreenshotCaptureScript(format: 'png' | 'jpeg', quality: number): string;
21
+ /**
22
+ * Build a script that injects html2canvas and captures a screenshot.
23
+ * This is the legacy function that inlines the library - kept for fallback.
24
+ */
25
+ export declare function buildScreenshotScript(format: 'png' | 'jpeg', quality: number): string;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Script loader for webview injection scripts
3
+ *
4
+ * These scripts are loaded at build time and injected into the webview at runtime.
5
+ * Each script is an IIFE that accepts a params object.
6
+ */
7
+ export declare const SCRIPTS: {
8
+ readonly resolveRef: string;
9
+ readonly interact: string;
10
+ readonly swipe: string;
11
+ readonly keyboard: string;
12
+ readonly waitFor: string;
13
+ readonly getStyles: string;
14
+ readonly focus: string;
15
+ readonly findElement: string;
16
+ readonly domSnapshot: string;
17
+ readonly elementPicker: string;
18
+ };
19
+ /** Script ID used for resolve-ref in the script registry. */
20
+ export declare const RESOLVE_REF_SCRIPT_ID = "__mcp_resolve_ref__";
21
+ /**
22
+ * Get the resolve-ref script source code.
23
+ */
24
+ export declare function getResolveRefSource(): string;
25
+ /**
26
+ * Build a script invocation with parameters
27
+ * The script should be an IIFE that accepts a params object
28
+ */
29
+ export declare function buildScript(script: string, params: Record<string, unknown>): string;
30
+ /**
31
+ * Build a script for typing text (uses the keyboard script's typeText function)
32
+ */
33
+ export declare function buildTypeScript(selector: string, text: string, strategy?: string): string;
34
+ /**
35
+ * Build a script for key events (press, down, up)
36
+ */
37
+ export declare function buildKeyEventScript(action: string, key: string, modifiers?: string[]): string;
@@ -22,6 +22,7 @@ export const SCRIPTS = {
22
22
  focus: loadScript('focus'),
23
23
  findElement: loadScript('find-element'),
24
24
  domSnapshot: loadScript('dom-snapshot'),
25
+ elementPicker: loadScript('element-picker'),
25
26
  };
26
27
  /** Script ID used for resolve-ref in the script registry. */
27
28
  export const RESOLVE_REF_SCRIPT_ID = '__mcp_resolve_ref__';
@@ -0,0 +1,76 @@
1
+ import { z } from 'zod';
2
+ import { PluginClient } from './plugin-client.js';
3
+ /**
4
+ * Session Manager - Native IPC-based session management
5
+ *
6
+ * This module provides lightweight native session management using Tauri IPC.
7
+ * The "session" concept is maintained for API compatibility.
8
+ *
9
+ * Connection Strategy:
10
+ * 1. Try localhost first (most reliable for simulators/emulators/desktop)
11
+ * 2. If localhost fails and a remote host is configured, try that host
12
+ * 3. Return error if all connection attempts fail
13
+ */
14
+ export declare const ManageDriverSessionSchema: z.ZodObject<{
15
+ action: z.ZodEnum<["start", "stop", "status"]>;
16
+ host: z.ZodOptional<z.ZodString>;
17
+ port: z.ZodOptional<z.ZodNumber>;
18
+ appIdentifier: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
19
+ }, "strip", z.ZodTypeAny, {
20
+ action: "status" | "start" | "stop";
21
+ host?: string | undefined;
22
+ port?: number | undefined;
23
+ appIdentifier?: string | number | undefined;
24
+ }, {
25
+ action: "status" | "start" | "stop";
26
+ host?: string | undefined;
27
+ port?: number | undefined;
28
+ appIdentifier?: string | number | undefined;
29
+ }>;
30
+ export interface SessionInfo {
31
+ name: string;
32
+ identifier: string | null;
33
+ host: string;
34
+ port: number;
35
+ client: PluginClient;
36
+ connected: boolean;
37
+ }
38
+ /**
39
+ * Check if any session is currently active.
40
+ * @returns true if at least one session exists
41
+ */
42
+ export declare function hasActiveSession(): boolean;
43
+ /**
44
+ * Get a specific session by port.
45
+ */
46
+ export declare function getSession(port: number): SessionInfo | null;
47
+ /**
48
+ * Get the default session (most recently connected).
49
+ */
50
+ export declare function getDefaultSession(): SessionInfo | null;
51
+ /**
52
+ * Get all active sessions.
53
+ */
54
+ export declare function getAllSessions(): SessionInfo[];
55
+ /**
56
+ * Resolve target app from port or identifier.
57
+ * Returns the appropriate session based on the routing logic.
58
+ */
59
+ export declare function resolveTargetApp(portOrIdentifier?: string | number): SessionInfo;
60
+ /**
61
+ * Manage session lifecycle (start, stop, or status).
62
+ *
63
+ * Connection strategy for 'start':
64
+ * 1. Try localhost:{port} first (most reliable for simulators/emulators/desktop)
65
+ * 2. If localhost fails AND a different host is configured, try {host}:{port}
66
+ * 3. If both fail, try auto-discovery on localhost
67
+ * 4. Return error if all attempts fail
68
+ *
69
+ * @param action - 'start', 'stop', or 'status'
70
+ * @param host - Optional host address (defaults to env var or localhost)
71
+ * @param port - Optional port number (defaults to 9223)
72
+ * @param appIdentifier - Optional app identifier for 'stop' action (port or bundle ID)
73
+ * @returns For 'start'/'stop': A message string describing the result.
74
+ * For 'status': A JSON string with connection details
75
+ */
76
+ export declare function manageDriverSession(action: 'start' | 'stop' | 'status', host?: string, port?: number, appIdentifier?: string | number): Promise<string>;
@@ -0,0 +1,122 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Ensures the MCP server is fully initialized and ready to use.
4
+ * This is called automatically by all tool functions.
5
+ *
6
+ * Initialization includes:
7
+ * - Verifying an active session exists (via driver_session)
8
+ * - Connecting to the plugin WebSocket using session config
9
+ * - Console capture is already initialized by bridge.js in the Tauri app
10
+ *
11
+ * This function is idempotent - calling it multiple times is safe.
12
+ *
13
+ * @throws Error if no session is active (driver_session must be called first)
14
+ */
15
+ export declare function ensureReady(): Promise<void>;
16
+ /**
17
+ * Reset initialization state (useful for testing or reconnecting).
18
+ */
19
+ export declare function resetInitialization(): void;
20
+ export interface ExecuteInWebviewResult {
21
+ result: string;
22
+ windowLabel: string;
23
+ warning?: string;
24
+ }
25
+ /**
26
+ * Execute JavaScript in the Tauri webview using native IPC via WebSocket.
27
+ *
28
+ * @param script - JavaScript code to execute in the webview context
29
+ * @param windowId - Optional window label to target (defaults to "main")
30
+ * @param appIdentifier - Optional app identifier to target specific app
31
+ * @returns Result of the script execution with window context
32
+ */
33
+ export declare function executeInWebview(script: string, windowId?: string, appIdentifier?: string | number): Promise<string>;
34
+ /**
35
+ * Execute JavaScript in the Tauri webview and return window context.
36
+ *
37
+ * @param script - JavaScript code to execute in the webview context
38
+ * @param windowId - Optional window label to target (defaults to "main")
39
+ * @param appIdentifier - Optional app identifier to target specific app
40
+ * @returns Result of the script execution with window context
41
+ */
42
+ export declare function executeInWebviewWithContext(script: string, windowId?: string, appIdentifier?: string | number): Promise<ExecuteInWebviewResult>;
43
+ /**
44
+ * Execute async JavaScript in the webview with timeout support.
45
+ *
46
+ * @param script - JavaScript code to execute (can use await)
47
+ * @param windowId - Optional window label to target (defaults to "main")
48
+ * @param timeout - Timeout in milliseconds (default: 5000)
49
+ * @returns Result of the script execution
50
+ */
51
+ export declare function executeAsyncInWebview(script: string, windowId?: string, timeout?: number): Promise<string>;
52
+ /**
53
+ * Initialize console log capture in the webview.
54
+ * This intercepts console methods and stores logs in memory.
55
+ *
56
+ * NOTE: Console capture is now automatically initialized by bridge.js when the
57
+ * Tauri app starts. This function is kept for backwards compatibility and will
58
+ * simply return early if capture is already initialized.
59
+ */
60
+ export declare function initializeConsoleCapture(): Promise<string>;
61
+ /**
62
+ * Retrieve captured console logs with optional filtering.
63
+ *
64
+ * @param filter - Optional regex pattern to filter log messages
65
+ * @param since - Optional ISO timestamp to filter logs after this time
66
+ * @param windowId - Optional window label to target (defaults to "main")
67
+ * @param appIdentifier - Optional app identifier to target specific app
68
+ * @returns Formatted console logs as string
69
+ */
70
+ export declare function getConsoleLogs(filter?: string, since?: string, windowId?: string, appIdentifier?: string | number): Promise<string>;
71
+ /**
72
+ * Clear all captured console logs.
73
+ */
74
+ export declare function clearConsoleLogs(): Promise<string>;
75
+ import type { ToolContent } from '../tools-registry.js';
76
+ /**
77
+ * Result of a screenshot capture, containing both image data and optional context.
78
+ */
79
+ export interface ScreenshotResult {
80
+ content: ToolContent[];
81
+ }
82
+ export interface CaptureScreenshotOptions {
83
+ format?: 'png' | 'jpeg';
84
+ quality?: number;
85
+ windowId?: string;
86
+ appIdentifier?: string | number;
87
+ maxWidth?: number;
88
+ }
89
+ /**
90
+ * Capture a screenshot of the entire webview.
91
+ *
92
+ * @param options - Screenshot options (format, quality, windowId, appIdentifier, etc.)
93
+ * @returns Screenshot result with image content
94
+ */
95
+ export declare function captureScreenshot(options?: CaptureScreenshotOptions): Promise<ScreenshotResult>;
96
+ export declare const ExecuteScriptSchema: z.ZodObject<{
97
+ script: z.ZodString;
98
+ }, "strip", z.ZodTypeAny, {
99
+ script: string;
100
+ }, {
101
+ script: string;
102
+ }>;
103
+ export declare const GetConsoleLogsSchema: z.ZodObject<{
104
+ filter: z.ZodOptional<z.ZodString>;
105
+ since: z.ZodOptional<z.ZodString>;
106
+ }, "strip", z.ZodTypeAny, {
107
+ filter?: string | undefined;
108
+ since?: string | undefined;
109
+ }, {
110
+ filter?: string | undefined;
111
+ since?: string | undefined;
112
+ }>;
113
+ export declare const CaptureScreenshotSchema: z.ZodObject<{
114
+ format: z.ZodDefault<z.ZodOptional<z.ZodEnum<["png", "jpeg"]>>>;
115
+ quality: z.ZodOptional<z.ZodNumber>;
116
+ }, "strip", z.ZodTypeAny, {
117
+ format: "png" | "jpeg";
118
+ quality?: number | undefined;
119
+ }, {
120
+ format?: "png" | "jpeg" | undefined;
121
+ quality?: number | undefined;
122
+ }>;