@mcpc-tech/unplugin-dev-inspector-mcp 0.1.30 → 0.1.32
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/client/dist/{PromptParamsDialog-D0TaQM5I.js → PromptParamsDialog-B0YpiWEk.js} +113 -87
- package/client/dist/inspector.js +19 -20
- package/client/dist/sidebar.js +1 -1
- package/dist/config-updater.cjs +160 -14
- package/dist/config-updater.js +160 -14
- package/dist/index.cjs +5 -2
- package/dist/index.d.cts +16 -9
- package/dist/index.d.ts +16 -9
- package/dist/index.js +5 -2
- package/dist/react/react.js +382 -4
- package/package.json +1 -1
package/dist/react/react.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Client } from "@modelcontextprotocol/sdk/client";
|
|
|
2
2
|
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
3
3
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { createClientExecClient } from "@mcpc-tech/cmcp";
|
|
5
|
+
import { toPng } from "html-to-image";
|
|
5
6
|
import { ListPromptsResultSchema, PromptListChangedNotificationSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
6
7
|
|
|
7
8
|
//#region src/tool-schemas.ts
|
|
@@ -102,6 +103,72 @@ Returns: source location, DOM hierarchy, computed styles, dimensions, and user n
|
|
|
102
103
|
} },
|
|
103
104
|
required: ["code"]
|
|
104
105
|
}
|
|
106
|
+
},
|
|
107
|
+
capture_area_context: {
|
|
108
|
+
name: "capture_area_context",
|
|
109
|
+
description: `Capture area context by activating visual area selection mode.
|
|
110
|
+
|
|
111
|
+
User draws a rectangle on the page to select multiple elements at once. After selection, returns context for all elements in the area including source locations, DOM info, and screenshot.
|
|
112
|
+
|
|
113
|
+
**Flow**:
|
|
114
|
+
1. Activates area selection mode (user sees crosshair cursor)
|
|
115
|
+
2. User draws rectangle around target elements
|
|
116
|
+
3. Returns: primary element + related elements with source locations, DOM hierarchy, and screenshot`,
|
|
117
|
+
inputSchema: {
|
|
118
|
+
type: "object",
|
|
119
|
+
properties: {}
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
get_network_requests: {
|
|
123
|
+
name: "get_network_requests",
|
|
124
|
+
description: `Get network requests from browser for debugging.
|
|
125
|
+
|
|
126
|
+
Returns list of HTTP requests with ID, method, URL, and status code. Use reqid parameter to get full details of a specific request including headers, body, and timing.
|
|
127
|
+
|
|
128
|
+
**Usage**:
|
|
129
|
+
- Call without parameters to list all requests
|
|
130
|
+
- Call with reqid to get specific request details`,
|
|
131
|
+
inputSchema: {
|
|
132
|
+
type: "object",
|
|
133
|
+
properties: { reqid: {
|
|
134
|
+
type: "number",
|
|
135
|
+
description: "Optional. Request ID to get full details. If omitted, returns list of all requests."
|
|
136
|
+
} }
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
get_console_messages: {
|
|
140
|
+
name: "get_console_messages",
|
|
141
|
+
description: `Get console messages from browser for debugging.
|
|
142
|
+
|
|
143
|
+
Returns list of console logs with ID, level (log/warn/error/info), and message content. Use msgid parameter to get full details of a specific message.
|
|
144
|
+
|
|
145
|
+
**Usage**:
|
|
146
|
+
- Call without parameters to list all messages
|
|
147
|
+
- Call with msgid to get specific message details`,
|
|
148
|
+
inputSchema: {
|
|
149
|
+
type: "object",
|
|
150
|
+
properties: { msgid: {
|
|
151
|
+
type: "number",
|
|
152
|
+
description: "Optional. Message ID to get full details. If omitted, returns list of all messages."
|
|
153
|
+
} }
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
get_stdio_messages: {
|
|
157
|
+
name: "get_stdio_messages",
|
|
158
|
+
description: `Get stdio (stdout/stderr) terminal messages from dev server process.
|
|
159
|
+
|
|
160
|
+
Returns list of terminal output with ID, stream type (stdout/stderr), and content. Use stdioid parameter to get full details of a specific message.
|
|
161
|
+
|
|
162
|
+
**Usage**:
|
|
163
|
+
- Call without parameters to list all stdio messages
|
|
164
|
+
- Call with stdioid to get specific message details`,
|
|
165
|
+
inputSchema: {
|
|
166
|
+
type: "object",
|
|
167
|
+
properties: { stdioid: {
|
|
168
|
+
type: "number",
|
|
169
|
+
description: "Optional. Stdio message ID to get full details. If omitted, returns list of all messages."
|
|
170
|
+
} }
|
|
171
|
+
}
|
|
105
172
|
}
|
|
106
173
|
};
|
|
107
174
|
|
|
@@ -293,7 +360,7 @@ function getDevServerBaseUrl() {
|
|
|
293
360
|
if (injectedConfig?.baseUrl && typeof injectedConfig.baseUrl === "string") return injectedConfig.baseUrl.replace(/\/$/, "");
|
|
294
361
|
if (injectedConfig?.host && injectedConfig?.port) return `http://${injectedConfig.host}:${injectedConfig.port}${base}`.replace(/\/$/, "");
|
|
295
362
|
if (typeof window !== "undefined" && window.location?.origin) return window.location.origin;
|
|
296
|
-
return `http://localhost:
|
|
363
|
+
return `http://localhost:6137`;
|
|
297
364
|
}
|
|
298
365
|
/**
|
|
299
366
|
* Merge custom agent with default agent properties
|
|
@@ -352,24 +419,257 @@ async function getDefaultAgent() {
|
|
|
352
419
|
//#endregion
|
|
353
420
|
//#region client/utils/format.ts
|
|
354
421
|
/**
|
|
422
|
+
* Format DOM element info only (for Code tab)
|
|
423
|
+
*/
|
|
424
|
+
function formatDomElement(elementInfo) {
|
|
425
|
+
if (!elementInfo) return "";
|
|
426
|
+
const { tagName, textContent, className, id: elemId, domPath, boundingBox } = elementInfo;
|
|
427
|
+
let output = `### DOM Element
|
|
428
|
+
\`\`\`
|
|
429
|
+
Tag: <${tagName}${elemId ? ` id="${elemId}"` : ""}${className ? ` class="${className}"` : ""}>
|
|
430
|
+
Text: ${textContent || "(empty)"}
|
|
431
|
+
Path: ${domPath || "N/A"}
|
|
432
|
+
\`\`\`
|
|
433
|
+
`;
|
|
434
|
+
if (boundingBox) output += `
|
|
435
|
+
### Position & Size
|
|
436
|
+
- **Position**: (${Math.round(boundingBox.x)}, ${Math.round(boundingBox.y)})
|
|
437
|
+
- **Size**: ${Math.round(boundingBox.width)}px × ${Math.round(boundingBox.height)}px
|
|
438
|
+
`;
|
|
439
|
+
return output;
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Format computed styles only (for Styles tab)
|
|
443
|
+
*/
|
|
444
|
+
function formatComputedStyles(elementInfo) {
|
|
445
|
+
if (!elementInfo) return "";
|
|
446
|
+
const { computedStyles, styles } = elementInfo;
|
|
447
|
+
if (computedStyles) return `### Computed Styles
|
|
448
|
+
|
|
449
|
+
**Layout**:
|
|
450
|
+
- display: ${computedStyles.layout.display}
|
|
451
|
+
- position: ${computedStyles.layout.position}
|
|
452
|
+
- z-index: ${computedStyles.layout.zIndex}
|
|
453
|
+
|
|
454
|
+
**Typography**:
|
|
455
|
+
- font: ${computedStyles.typography.fontSize} ${computedStyles.typography.fontFamily}
|
|
456
|
+
- color: ${computedStyles.typography.color}
|
|
457
|
+
- text-align: ${computedStyles.typography.textAlign}
|
|
458
|
+
|
|
459
|
+
**Spacing**:
|
|
460
|
+
- padding: ${computedStyles.spacing.padding}
|
|
461
|
+
- margin: ${computedStyles.spacing.margin}
|
|
462
|
+
|
|
463
|
+
**Background & Border**:
|
|
464
|
+
- background: ${computedStyles.background.backgroundColor}
|
|
465
|
+
- border: ${computedStyles.border.border}
|
|
466
|
+
- border-radius: ${computedStyles.border.borderRadius}
|
|
467
|
+
`;
|
|
468
|
+
else if (styles) return `### Key Styles
|
|
469
|
+
- display: ${styles.display}
|
|
470
|
+
- color: ${styles.color}
|
|
471
|
+
- background: ${styles.backgroundColor}
|
|
472
|
+
- font-size: ${styles.fontSize}
|
|
473
|
+
`;
|
|
474
|
+
return "";
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Format source location
|
|
478
|
+
*/
|
|
479
|
+
function formatSourceInfo(sourceInfo) {
|
|
480
|
+
return `## Source Code
|
|
481
|
+
- **File**: ${sourceInfo.file}
|
|
482
|
+
- **Line**: ${sourceInfo.line}:${sourceInfo.column}
|
|
483
|
+
- **Component**: ${sourceInfo.component}
|
|
484
|
+
`;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Format console messages
|
|
488
|
+
*/
|
|
489
|
+
function formatConsoleMessages(messages) {
|
|
490
|
+
if (messages.length === 0) return "";
|
|
491
|
+
const formatted = messages.map((msg) => {
|
|
492
|
+
return `- ${msg.level === "error" ? "❌" : msg.level === "warn" ? "⚠️" : "📝"} [${msg.level}] ${msg.text}`;
|
|
493
|
+
}).join("\n");
|
|
494
|
+
return `## Console Messages (${messages.length})
|
|
495
|
+
${formatted}
|
|
496
|
+
`;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Format network requests
|
|
500
|
+
*/
|
|
501
|
+
function formatNetworkRequests(requests) {
|
|
502
|
+
if (requests.length === 0) return "";
|
|
503
|
+
const formatted = requests.map((req) => {
|
|
504
|
+
let entry = `### ${req.method} ${req.url}
|
|
505
|
+
- **Status**: ${req.status}
|
|
506
|
+
`;
|
|
507
|
+
if (req.details && req.details !== "(expand request to load details)") entry += `
|
|
508
|
+
#### Details
|
|
509
|
+
\`\`\`
|
|
510
|
+
${req.details}
|
|
511
|
+
\`\`\`
|
|
512
|
+
`;
|
|
513
|
+
return entry;
|
|
514
|
+
}).join("\n");
|
|
515
|
+
return `## Network Requests (${requests.length})
|
|
516
|
+
${formatted}
|
|
517
|
+
`;
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Format stdio messages
|
|
521
|
+
*/
|
|
522
|
+
function formatStdioMessages(messages) {
|
|
523
|
+
if (messages.length === 0) return "";
|
|
524
|
+
const formatted = messages.map((msg) => {
|
|
525
|
+
return `- [${msg.stream}] ${msg.data}`;
|
|
526
|
+
}).join("\n");
|
|
527
|
+
return `## Terminal Logs (${messages.length})
|
|
528
|
+
${formatted}
|
|
529
|
+
`;
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Format page information
|
|
533
|
+
*/
|
|
534
|
+
function formatPageInfo(pageInfo) {
|
|
535
|
+
return `## Page Information
|
|
536
|
+
- **URL**: ${pageInfo.url}
|
|
537
|
+
- **Title**: ${pageInfo.title}
|
|
538
|
+
- **Viewport**: ${pageInfo.viewport.width} × ${pageInfo.viewport.height}
|
|
539
|
+
- **Language**: ${pageInfo.language}
|
|
540
|
+
`;
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
355
543
|
* Format element annotations (notes) from primary and related elements
|
|
356
544
|
*/
|
|
357
545
|
function formatElementAnnotations(options) {
|
|
358
|
-
const { primaryNote, primaryTag, relatedElements } = options;
|
|
546
|
+
const { primaryNote, primaryTag, relatedElements, elementNotes } = options;
|
|
359
547
|
const notes = [];
|
|
360
548
|
if (primaryNote) {
|
|
361
549
|
const tag = primaryTag || "element";
|
|
362
550
|
notes.push(`- **Primary element** (${tag}): ${primaryNote}`);
|
|
363
551
|
}
|
|
364
552
|
if (relatedElements && relatedElements.length > 0) relatedElements.forEach((el, idx) => {
|
|
365
|
-
|
|
553
|
+
const note = el.note || elementNotes?.[idx];
|
|
554
|
+
if (note) {
|
|
366
555
|
const tag = el.elementInfo?.tagName?.toLowerCase() || el.component;
|
|
367
556
|
const location = el.file && el.line ? ` at ${el.file}:${el.line}` : "";
|
|
368
|
-
notes.push(`- **Related element #${idx + 1}** (${tag}${location}): ${
|
|
557
|
+
notes.push(`- **Related element #${idx + 1}** (${tag}${location}): ${note}`);
|
|
369
558
|
}
|
|
370
559
|
});
|
|
371
560
|
return notes.length > 0 ? `\n**Element Annotations**:\n${notes.join("\n")}\n` : "";
|
|
372
561
|
}
|
|
562
|
+
/**
|
|
563
|
+
* Format complete context for Copy & Go (matches ContextPicker tab structure)
|
|
564
|
+
*/
|
|
565
|
+
function formatCopyContext(options) {
|
|
566
|
+
const { sourceInfo, includeElement, includeStyles, includePageInfo, pageInfo, feedback, consoleMessages, networkRequests, stdioMessages, relatedElements, relatedElementIds, elementNotes } = options;
|
|
567
|
+
let output = "# Element Context\n\n";
|
|
568
|
+
const hasRelatedElements = relatedElements && relatedElements.length > 0 && relatedElementIds && relatedElementIds.length > 0;
|
|
569
|
+
if (sourceInfo && includeElement) {
|
|
570
|
+
output += "## Code\n\n";
|
|
571
|
+
if (hasRelatedElements) output += "### Primary Element (Best Match)\n";
|
|
572
|
+
output += formatSourceInfo(sourceInfo);
|
|
573
|
+
output += "\n";
|
|
574
|
+
output += formatDomElement(sourceInfo.elementInfo);
|
|
575
|
+
output += "\n";
|
|
576
|
+
}
|
|
577
|
+
if (relatedElements && relatedElements.length > 0 && relatedElementIds && relatedElementIds.length > 0) {
|
|
578
|
+
const selectedElements = relatedElements.filter((_, idx) => relatedElementIds.includes(idx));
|
|
579
|
+
if (selectedElements.length > 0) {
|
|
580
|
+
output += "## Related Elements\n\n";
|
|
581
|
+
const grouped = selectedElements.reduce((acc, el) => {
|
|
582
|
+
const file = el.file || "unknown";
|
|
583
|
+
if (!acc[file]) acc[file] = [];
|
|
584
|
+
acc[file].push(el);
|
|
585
|
+
return acc;
|
|
586
|
+
}, {});
|
|
587
|
+
Object.entries(grouped).forEach(([file, elements]) => {
|
|
588
|
+
output += `### ${file}\n`;
|
|
589
|
+
elements.forEach((el) => {
|
|
590
|
+
const originalIndex = relatedElements.indexOf(el);
|
|
591
|
+
const note = elementNotes ? elementNotes[originalIndex] : null;
|
|
592
|
+
output += `- **${el.component}** (${el.line}:${el.column})`;
|
|
593
|
+
if (el.elementInfo?.tagName) {
|
|
594
|
+
output += ` - \`<${el.elementInfo.tagName}`;
|
|
595
|
+
if (el.elementInfo.className) output += ` class="${el.elementInfo.className}"`;
|
|
596
|
+
if (el.elementInfo.id) output += ` id="${el.elementInfo.id}"`;
|
|
597
|
+
output += `>`;
|
|
598
|
+
if (el.elementInfo.textContent) {
|
|
599
|
+
const preview = el.elementInfo.textContent.trim().slice(0, 30);
|
|
600
|
+
if (preview) output += ` "${preview}${el.elementInfo.textContent.length > 30 ? "..." : ""}"`;
|
|
601
|
+
}
|
|
602
|
+
output += "`";
|
|
603
|
+
}
|
|
604
|
+
if (note) output += `\n - **USER NOTE**: "${note}"`;
|
|
605
|
+
output += "\n";
|
|
606
|
+
});
|
|
607
|
+
output += "\n";
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
if (sourceInfo?.elementInfo && includeStyles) {
|
|
612
|
+
output += "## Styles\n\n";
|
|
613
|
+
output += formatComputedStyles(sourceInfo.elementInfo);
|
|
614
|
+
output += "\n";
|
|
615
|
+
}
|
|
616
|
+
if (pageInfo && includePageInfo) {
|
|
617
|
+
output += formatPageInfo(pageInfo);
|
|
618
|
+
output += "\n";
|
|
619
|
+
}
|
|
620
|
+
if (feedback) output += `## User Request\n\n${feedback}\n\n`;
|
|
621
|
+
if (consoleMessages && consoleMessages.length > 0) {
|
|
622
|
+
output += formatConsoleMessages(consoleMessages);
|
|
623
|
+
output += "\n";
|
|
624
|
+
}
|
|
625
|
+
if (networkRequests && networkRequests.length > 0) {
|
|
626
|
+
output += formatNetworkRequests(networkRequests);
|
|
627
|
+
output += "\n";
|
|
628
|
+
}
|
|
629
|
+
if (stdioMessages && stdioMessages.length > 0) output += formatStdioMessages(stdioMessages);
|
|
630
|
+
return output.trim();
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
//#endregion
|
|
634
|
+
//#region client/utils/screenshot.ts
|
|
635
|
+
/**
|
|
636
|
+
* Capture screenshot of a DOM element
|
|
637
|
+
* @param element - The DOM element to capture
|
|
638
|
+
* @param options - Screenshot options
|
|
639
|
+
* @returns Promise<string> - Data URL of the screenshot, or empty string on error
|
|
640
|
+
*/
|
|
641
|
+
async function captureElementScreenshot(element, options = {}) {
|
|
642
|
+
const { quality = .95, maxWidth = 1200, maxHeight = 800 } = options;
|
|
643
|
+
try {
|
|
644
|
+
const rect = element.getBoundingClientRect();
|
|
645
|
+
return await toPng(element, {
|
|
646
|
+
quality,
|
|
647
|
+
pixelRatio: Math.min(1, maxWidth / rect.width, maxHeight / rect.height) * (window.devicePixelRatio || 1),
|
|
648
|
+
cacheBust: true,
|
|
649
|
+
width: rect.width,
|
|
650
|
+
height: rect.height,
|
|
651
|
+
style: {
|
|
652
|
+
margin: "0",
|
|
653
|
+
transform: "none"
|
|
654
|
+
},
|
|
655
|
+
filter: (node) => {
|
|
656
|
+
if (node instanceof HTMLElement) {
|
|
657
|
+
const tagName = node.tagName.toLowerCase();
|
|
658
|
+
if (tagName === "iframe" || tagName === "script" || tagName === "link" || tagName === "video" || tagName === "audio" || tagName === "object" || tagName === "embed") return false;
|
|
659
|
+
if (tagName === "img") {
|
|
660
|
+
const img = node;
|
|
661
|
+
if (!img.complete || img.naturalWidth === 0) return false;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
return true;
|
|
665
|
+
},
|
|
666
|
+
fontEmbedCSS: ""
|
|
667
|
+
});
|
|
668
|
+
} catch (error) {
|
|
669
|
+
console.error("[screenshot] Failed to capture element:", error);
|
|
670
|
+
return "";
|
|
671
|
+
}
|
|
672
|
+
}
|
|
373
673
|
|
|
374
674
|
//#endregion
|
|
375
675
|
//#region client/hooks/useMcp.ts
|
|
@@ -552,6 +852,13 @@ ${requests}
|
|
|
552
852
|
|
|
553
853
|
`;
|
|
554
854
|
}
|
|
855
|
+
const notesSection = formatElementAnnotations({
|
|
856
|
+
primaryNote: sourceInfo.note,
|
|
857
|
+
primaryTag: elementInfo?.tagName?.toLowerCase() || component,
|
|
858
|
+
relatedElements: sourceInfo.relatedElements,
|
|
859
|
+
elementNotes: selectedContext?.elementNotes
|
|
860
|
+
});
|
|
861
|
+
if (notesSection) output += notesSection;
|
|
555
862
|
output += `## Your Task
|
|
556
863
|
1. Investigate the issue using 'chrome_devtools' tool (check console logs, network requests, performance)
|
|
557
864
|
2. Use 'execute_page_script' to query element state if needed
|
|
@@ -722,6 +1029,77 @@ After clicking, use \`list_inspections\` to view the captured element with full
|
|
|
722
1029
|
{
|
|
723
1030
|
...TOOL_SCHEMAS.execute_page_script,
|
|
724
1031
|
implementation: patchContext
|
|
1032
|
+
},
|
|
1033
|
+
{
|
|
1034
|
+
...TOOL_SCHEMAS.capture_area_context,
|
|
1035
|
+
implementation: () => {
|
|
1036
|
+
cancelPendingRequest("New area capture request started");
|
|
1037
|
+
window.dispatchEvent(new CustomEvent("activate-area-select"));
|
|
1038
|
+
return new Promise((resolve, reject) => {
|
|
1039
|
+
pendingResolve = resolve;
|
|
1040
|
+
pendingReject = reject;
|
|
1041
|
+
const handleAreaComplete = async (event) => {
|
|
1042
|
+
window.removeEventListener("area-selection-complete", handleAreaComplete);
|
|
1043
|
+
const { sourceInfo } = event.detail || {};
|
|
1044
|
+
if (!sourceInfo) {
|
|
1045
|
+
reject(/* @__PURE__ */ new Error("No elements selected in area"));
|
|
1046
|
+
clearPendingRequest();
|
|
1047
|
+
return;
|
|
1048
|
+
}
|
|
1049
|
+
try {
|
|
1050
|
+
const pageInfo = {
|
|
1051
|
+
url: window.location.href,
|
|
1052
|
+
title: document.title,
|
|
1053
|
+
viewport: {
|
|
1054
|
+
width: window.innerWidth,
|
|
1055
|
+
height: window.innerHeight
|
|
1056
|
+
},
|
|
1057
|
+
language: document.documentElement.lang || navigator.language
|
|
1058
|
+
};
|
|
1059
|
+
let screenshot;
|
|
1060
|
+
if (sourceInfo.element) screenshot = await captureElementScreenshot(sourceInfo.element);
|
|
1061
|
+
const elementNotes = {};
|
|
1062
|
+
sourceInfo.relatedElements?.forEach((el, idx) => {
|
|
1063
|
+
if (el.note) elementNotes[idx] = el.note;
|
|
1064
|
+
});
|
|
1065
|
+
const content = [{
|
|
1066
|
+
type: "text",
|
|
1067
|
+
text: formatCopyContext({
|
|
1068
|
+
sourceInfo,
|
|
1069
|
+
includeElement: true,
|
|
1070
|
+
includeStyles: false,
|
|
1071
|
+
includePageInfo: true,
|
|
1072
|
+
pageInfo,
|
|
1073
|
+
relatedElements: sourceInfo.relatedElements,
|
|
1074
|
+
relatedElementIds: sourceInfo.relatedElements?.map((_, idx) => idx),
|
|
1075
|
+
elementNotes: Object.keys(elementNotes).length > 0 ? elementNotes : void 0
|
|
1076
|
+
})
|
|
1077
|
+
}];
|
|
1078
|
+
if (screenshot) {
|
|
1079
|
+
const base64Data = screenshot.replace(/^data:image\/\w+;base64,/, "");
|
|
1080
|
+
content.push({
|
|
1081
|
+
type: "image",
|
|
1082
|
+
data: base64Data,
|
|
1083
|
+
mimeType: "image/png"
|
|
1084
|
+
});
|
|
1085
|
+
}
|
|
1086
|
+
resolve({ content });
|
|
1087
|
+
} catch (error) {
|
|
1088
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
1089
|
+
reject(/* @__PURE__ */ new Error(`Error processing area selection: ${errorMsg}`));
|
|
1090
|
+
}
|
|
1091
|
+
clearPendingRequest();
|
|
1092
|
+
};
|
|
1093
|
+
window.addEventListener("area-selection-complete", handleAreaComplete);
|
|
1094
|
+
setTimeout(() => {
|
|
1095
|
+
if (pendingReject === reject) {
|
|
1096
|
+
window.removeEventListener("area-selection-complete", handleAreaComplete);
|
|
1097
|
+
clearPendingRequest();
|
|
1098
|
+
reject(/* @__PURE__ */ new Error("Timeout: No area selected"));
|
|
1099
|
+
}
|
|
1100
|
+
}, TIMEOUT_MS);
|
|
1101
|
+
});
|
|
1102
|
+
}
|
|
725
1103
|
}
|
|
726
1104
|
];
|
|
727
1105
|
const getCustomTools = () => {
|
package/package.json
CHANGED