mirror of
https://github.com/penpot/penpot-mcp.git
synced 2026-07-28 17:05:58 +00:00
Refactor task handling (adding Task abstraction)
This commit is contained in:
parent
8275735999
commit
93e98f5e08
@ -1,6 +1,6 @@
|
||||
import { WebSocket, WebSocketServer } from "ws";
|
||||
import { PluginTask } from "./PluginTask";
|
||||
import { PluginTaskResponse, PluginTaskResult } from "@penpot-mcp/common";
|
||||
import {WebSocket, WebSocketServer} from "ws";
|
||||
import {PluginTask} from "./PluginTask";
|
||||
import {PluginTaskResponse} from "@penpot-mcp/common";
|
||||
|
||||
/**
|
||||
* Provides the connection to the Penpot MCP Plugin via WebSocket
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
*
|
||||
* @template TParams - The strongly-typed parameters for this task
|
||||
*/
|
||||
import { PluginTaskRequest, PluginTaskResult } from "@penpot-mcp/common";
|
||||
import { PluginTaskRequest, PluginTaskResult } from '@penpot-mcp/common';
|
||||
import { randomUUID } from "crypto";
|
||||
|
||||
/**
|
||||
|
||||
@ -1,31 +1,22 @@
|
||||
|
||||
/**
|
||||
* Abstract base class for task handlers in the Penpot MCP plugin.
|
||||
*
|
||||
* @template TParams - The type of parameters this handler expects
|
||||
* Represents a task received from the MCP server in the Penpot MCP plugin
|
||||
*/
|
||||
export abstract class TaskHandler<TParams = any> {
|
||||
/** The task identifier this handler is responsible for */
|
||||
abstract readonly task: string;
|
||||
|
||||
export class Task<TParams = any> {
|
||||
/**
|
||||
* Checks if this handler can process the given task.
|
||||
*
|
||||
* @param task - The task identifier to check
|
||||
* @returns True if this handler applies to the given task
|
||||
* @param requestId Unique identifier for the task request
|
||||
* @param taskType The type of the task to execute
|
||||
* @param params Task parameters/arguments
|
||||
*/
|
||||
applies(task: string): boolean {
|
||||
return this.task === task;
|
||||
}
|
||||
constructor(public requestId: string, public taskType: string, public params: TParams) {}
|
||||
|
||||
/**
|
||||
* Sends a task response back to the MCP server.
|
||||
*/
|
||||
public static sendTaskResponse(taskId: string, success: boolean, data: any = undefined, error: any = undefined): void {
|
||||
protected sendResponse(success: boolean, data: any = undefined, error: any = undefined): void {
|
||||
const response = {
|
||||
type: "task-response",
|
||||
response: {
|
||||
id: taskId,
|
||||
id: this.requestId,
|
||||
success: success,
|
||||
data: data,
|
||||
error: error,
|
||||
@ -37,19 +28,38 @@ export abstract class TaskHandler<TParams = any> {
|
||||
console.log("Sent task response:", response);
|
||||
}
|
||||
|
||||
public static sendTaskSuccess(taskId: string, data: any = undefined): void {
|
||||
this.sendTaskResponse(taskId, true, data);
|
||||
public sendSuccess(data: any = undefined): void {
|
||||
this.sendResponse(true, data);
|
||||
}
|
||||
|
||||
public static sendTaskError(taskId: string, error: string): void {
|
||||
this.sendTaskResponse(taskId, false, undefined, error);
|
||||
public sendError(error: string): void {
|
||||
this.sendResponse(false, undefined, error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract base class for task handlers in the Penpot MCP plugin.
|
||||
*
|
||||
* @template TParams - The type of parameters this handler expects
|
||||
*/
|
||||
export abstract class TaskHandler<TParams = any> {
|
||||
/** The task type this handler is responsible for */
|
||||
abstract readonly taskType: string;
|
||||
|
||||
/**
|
||||
* Checks if this handler can process the given task.
|
||||
*
|
||||
* @param task - The task identifier to check
|
||||
* @returns True if this handler applies to the given task
|
||||
*/
|
||||
isApplicableTo(task: Task): boolean {
|
||||
return this.taskType === task.taskType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the task with the provided parameters.
|
||||
*
|
||||
* @param taskId - The unique ID of the task request
|
||||
* @param params - The parameters for the task
|
||||
* @param task - The task to be handled
|
||||
*/
|
||||
abstract handle(taskId: string, params: TParams): void;
|
||||
abstract handle(task: Task<TParams>): void;
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
import {PrintTextTaskHandler} from "./task-handlers/PrintTextTaskHandler";
|
||||
import {TaskHandler} from "./TaskHandler";
|
||||
import {Task, TaskHandler} from "./TaskHandler";
|
||||
|
||||
/**
|
||||
* Registry of all available task handlers.
|
||||
@ -40,22 +40,25 @@ penpot.ui.onMessage<string | { id: string; task: string; params: any }>((message
|
||||
*/
|
||||
function handlePluginTaskRequest(request: { id: string; task: string; params: any }): void {
|
||||
console.log("Executing plugin task:", request.task, request.params);
|
||||
const task = new Task(request.id, request.task, request.params);
|
||||
|
||||
// Find the appropriate handler
|
||||
const handler = taskHandlers.find(h => h.applies(request.task));
|
||||
const handler = taskHandlers.find(h => h.isApplicableTo(task));
|
||||
|
||||
if (handler) {
|
||||
try {
|
||||
// Cast the params to the expected type and handle the task
|
||||
handler.handle(request.id, request.params);
|
||||
console.log("Processing task with handler:", handler);
|
||||
handler.handle(task);
|
||||
console.log("Task handled successfully:", task);
|
||||
} catch (error) {
|
||||
console.error(`Error handling task '${request.task}':`, error);
|
||||
console.error("Error creating text:", error);
|
||||
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
||||
TaskHandler.sendTaskError(request.id, `Error handling task: ${errorMessage}`);
|
||||
task.sendError(`Error handling task: ${errorMessage}`);
|
||||
}
|
||||
} else {
|
||||
console.warn("Unknown plugin task:", request.task);
|
||||
TaskHandler.sendTaskError(request.id, `Unknown task type: ${request.task}`);
|
||||
task.sendError(`Unknown task type: ${request.task}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,46 +1,31 @@
|
||||
import {TaskHandler} from "../TaskHandler";
|
||||
import {Task, TaskHandler} from "../TaskHandler";
|
||||
import {PrintTextTaskParams} from "../../../common/src";
|
||||
|
||||
/**
|
||||
* Task handler for printing text to Penpot.
|
||||
*/
|
||||
export class PrintTextTaskHandler extends TaskHandler<PrintTextTaskParams> {
|
||||
readonly task = "printText";
|
||||
readonly taskType = "printText";
|
||||
|
||||
/**
|
||||
* Handles the printText task by creating text in Penpot.
|
||||
*
|
||||
* @param taskId - The unique ID of the task request
|
||||
* @param params - The parameters containing the text to create
|
||||
*/
|
||||
handle(taskId: string, params: PrintTextTaskParams): void {
|
||||
if (!params.text) {
|
||||
console.error("printText task requires 'text' parameter");
|
||||
TaskHandler.sendTaskError(taskId, "printText task requires 'text' parameter");
|
||||
return;
|
||||
handle(task: Task<PrintTextTaskParams>): void {
|
||||
if (!task.params.text) {
|
||||
throw new Error("printText task requires 'text' parameter");
|
||||
}
|
||||
|
||||
try {
|
||||
const text = penpot.createText(params.text);
|
||||
const text = penpot.createText(task.params.text);
|
||||
|
||||
if (text) {
|
||||
// Center the text in the viewport
|
||||
text.x = penpot.viewport.center.x;
|
||||
text.y = penpot.viewport.center.y;
|
||||
if (text) {
|
||||
// Center the text in the viewport
|
||||
text.x = penpot.viewport.center.x;
|
||||
text.y = penpot.viewport.center.y;
|
||||
|
||||
// Select the newly created text
|
||||
penpot.selection = [text];
|
||||
// Select the newly created text
|
||||
penpot.selection = [text];
|
||||
|
||||
console.log("Successfully created text:", params.text);
|
||||
TaskHandler.sendTaskSuccess(taskId, { textId: text.id });
|
||||
} else {
|
||||
console.error("Failed to create text element");
|
||||
TaskHandler.sendTaskError(taskId, "Failed to create text element");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error creating text:", error);
|
||||
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
||||
TaskHandler.sendTaskError(taskId, `Error creating text: ${errorMessage}`);
|
||||
console.log("Successfully created text:", task.params.text);
|
||||
task.sendSuccess({ textId: text.id });
|
||||
} else {
|
||||
throw new Error("Failed to create text element");
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user