This commit is contained in:
alonso.torres 2026-01-08 10:33:35 +01:00
parent c931e6978b
commit 9233b8e548
2 changed files with 56 additions and 19 deletions

View File

@ -19,12 +19,19 @@ const statusElement = document.getElementById("connection-status");
* @param isConnectedState - whether the connection is in a connected state (affects color) * @param isConnectedState - whether the connection is in a connected state (affects color)
* @param message - optional additional message to append to the status * @param message - optional additional message to append to the status
*/ */
function updateConnectionStatus(status: string, isConnectedState: boolean, message?: string): void { function updateConnectionStatus(code: string, status: string, isConnectedState: boolean, message?: string): void {
if (statusElement) { if (statusElement) {
const displayText = message ? `${status}: ${message}` : status; const displayText = message ? `${status}: ${message}` : status;
statusElement.textContent = displayText; statusElement.textContent = displayText;
statusElement.style.color = isConnectedState ? "var(--accent-primary)" : "var(--error-700)"; statusElement.style.color = isConnectedState ? "var(--accent-primary)" : "var(--error-700)";
} }
parent.postMessage(
{
type: "update-connection-status",
status: code,
},
"*"
);
} }
/** /**
@ -44,25 +51,23 @@ function sendTaskResponse(response: any): void {
/** /**
* Establishes a WebSocket connection to the MCP server. * Establishes a WebSocket connection to the MCP server.
*/ */
function connectToMcpServer(): void { function connectToMcpServer(url: string, token: string): void {
if (ws?.readyState === WebSocket.OPEN) { if (ws?.readyState === WebSocket.OPEN) {
updateConnectionStatus("Already connected", true); updateConnectionStatus("connected", "Already connected", true);
return; return;
} }
try { try {
let wsUrl = PENPOT_MCP_WEBSOCKET_URL;
if (isMultiUserMode) { if (isMultiUserMode) {
// TODO obtain proper userToken from penpot url += `?userToken=${encodeURIComponent(token)}`;
const userToken = "dummyToken";
wsUrl += `?userToken=${encodeURIComponent(userToken)}`;
} }
ws = new WebSocket(wsUrl);
updateConnectionStatus("Connecting...", false); ws = new WebSocket(url);
updateConnectionStatus("connecting", "Connecting...", false);
ws.onopen = () => { ws.onopen = () => {
console.log("Connected to MCP server"); console.log("Connected to MCP server");
updateConnectionStatus("Connected to MCP server", true); updateConnectionStatus("connected", "Connected to MCP server", true);
}; };
ws.onmessage = (event) => { ws.onmessage = (event) => {
@ -79,32 +84,37 @@ function connectToMcpServer(): void {
ws.onclose = (event: CloseEvent) => { ws.onclose = (event: CloseEvent) => {
console.log("Disconnected from MCP server"); console.log("Disconnected from MCP server");
const message = event.reason || undefined; const message = event.reason || undefined;
updateConnectionStatus("Disconnected", false, message); updateConnectionStatus("disconnected", "Disconnected", false, message);
ws = null; ws = null;
}; };
ws.onerror = (error) => { ws.onerror = (error) => {
console.error("WebSocket error:", error); console.error("WebSocket error:", error);
// note: WebSocket error events typically don't contain detailed error messages // note: WebSocket error events typically don't contain detailed error messages
updateConnectionStatus("Connection error", false); updateConnectionStatus("error", "Connection error", false);
}; };
} catch (error) { } catch (error) {
console.error("Failed to connect to MCP server:", error); console.error("Failed to connect to MCP server:", error);
const message = error instanceof Error ? error.message : undefined; const message = error instanceof Error ? error.message : undefined;
updateConnectionStatus("Connection failed", false, message); updateConnectionStatus("error", "Connection failed", false, message);
} }
} }
document.querySelector("[data-handler='connect-mcp']")?.addEventListener("click", () => { // document.querySelector("[data-handler='connect-mcp']")?.addEventListener("click", () => {
connectToMcpServer(); // connectToMcpServer();
}); // });
// Listen plugin.ts messages // Listen plugin.ts messages
window.addEventListener("message", (event) => { window.addEventListener("message", (event) => {
if (event.data.source === "penpot") { console.log("event", event.data);
if (event.data.type === "init-server") {
connectToMcpServer(event.data.url, event.data.token);
} else if (event.data.source === "penpot") {
document.body.dataset.theme = event.data.theme; document.body.dataset.theme = event.data.theme;
} else if (event.data.type === "task-response") { } else if (event.data.type === "task-response") {
// Forward task response back to MCP server // Forward task response back to MCP server
sendTaskResponse(event.data.response); sendTaskResponse(event.data.response);
} }
}); });
parent.postMessage({ type: "ui-initialized" }, "*");

View File

@ -1,6 +1,11 @@
import { ExecuteCodeTaskHandler } from "./task-handlers/ExecuteCodeTaskHandler"; import { ExecuteCodeTaskHandler } from "./task-handlers/ExecuteCodeTaskHandler";
import { Task, TaskHandler } from "./TaskHandler"; import { Task, TaskHandler } from "./TaskHandler";
console.log("TOKEN", mcp.getToken());
console.log("SERVER", mcp.getServerUrl());
mcp.setMcpStatus("connecting");
/** /**
* Registry of all available task handlers. * Registry of all available task handlers.
*/ */
@ -11,12 +16,26 @@ declare const IS_MULTI_USER_MODE: boolean;
const isMultiUserMode = typeof IS_MULTI_USER_MODE !== "undefined" ? IS_MULTI_USER_MODE : false; const isMultiUserMode = typeof IS_MULTI_USER_MODE !== "undefined" ? IS_MULTI_USER_MODE : false;
// Open the plugin UI (main.ts) // Open the plugin UI (main.ts)
penpot.ui.open("Penpot MCP Plugin", `?theme=${penpot.theme}&multiUser=${isMultiUserMode}`, { width: 158, height: 200 }); penpot.ui.open("Penpot MCP Plugin", `?theme=${penpot.theme}&multiUser=${isMultiUserMode}`, {
width: 158,
height: 200,
hidden: true,
});
// Handle messages // Handle messages
penpot.ui.onMessage<string | { id: string; task: string; params: any }>((message) => { penpot.ui.onMessage<string | { id: string; task: string; params: any }>((message) => {
// Handle plugin task requests // Handle plugin task requests
if (typeof message === "object" && message.task && message.id) { console.log(message);
if (message.type === "ui-initialized") {
console.log("send message");
penpot.ui.sendMessage({
type: "init-server",
url: mcp.getServerUrl(),
token: mcp.getToken(),
});
} else if (message.type === "update-connection-status") {
mcp.setMcpStatus(message.status);
} else if (typeof message === "object" && message.task && message.id) {
handlePluginTaskRequest(message).catch((error) => { handlePluginTaskRequest(message).catch((error) => {
console.error("Error in handlePluginTaskRequest:", error); console.error("Error in handlePluginTaskRequest:", error);
}); });
@ -67,3 +86,11 @@ penpot.on("themechange", (theme) => {
theme, theme,
}); });
}); });
// console.log("send message");
// penpot.ui.sendMessage({
// source: "penpot",
// type: "init-server",
// url: mcp.getServerUrl(),
// token: mcp.getToken(),
// })