60 lines
2.2 KiB
TypeScript
60 lines
2.2 KiB
TypeScript
import { z } from "zod";
|
|
import { getCanvasCapability, parseCanvasCapabilityArgs } from "./registry";
|
|
import {
|
|
CANVAS_CAPABILITY_IDS,
|
|
type CanvasCapabilityCommandSource,
|
|
type CanvasCapabilityId,
|
|
} from "./types";
|
|
|
|
export const canvasCapabilityClientCommandSchema = z.object({
|
|
version: z.literal(1),
|
|
requestId: z.string().trim().min(1).max(180),
|
|
capabilityId: z.enum(CANVAS_CAPABILITY_IDS),
|
|
projectId: z.string().trim().min(1).max(180).optional(),
|
|
nodeIds: z.array(z.string().trim().min(1).max(180)).min(1).max(50),
|
|
args: z.record(z.unknown()).default({}),
|
|
source: z.enum(["toolbar", "agent", "mcp", "system"]),
|
|
confirmed: z.boolean().optional(),
|
|
createdAt: z.string().datetime(),
|
|
});
|
|
|
|
export type CanvasCapabilityClientCommand = z.infer<
|
|
typeof canvasCapabilityClientCommandSchema
|
|
>;
|
|
|
|
export function createCanvasCapabilityClientCommand(params: {
|
|
capabilityId: CanvasCapabilityId;
|
|
nodeIds: string[];
|
|
projectId?: string;
|
|
requestId?: string;
|
|
args?: unknown;
|
|
source: CanvasCapabilityCommandSource;
|
|
confirmed?: boolean;
|
|
createdAt?: string;
|
|
}): CanvasCapabilityClientCommand {
|
|
const capability = getCanvasCapability(params.capabilityId);
|
|
if (!capability) throw new Error(`Unknown canvas capability: ${params.capabilityId}`);
|
|
const nodeIds = Array.from(new Set(params.nodeIds.map((id) => id.trim()).filter(Boolean)));
|
|
if (nodeIds.length < capability.selection.min) {
|
|
throw new Error(`${capability.title} requires at least ${capability.selection.min} selected node(s)`);
|
|
}
|
|
if (capability.selection.max && nodeIds.length > capability.selection.max) {
|
|
throw new Error(`${capability.title} supports at most ${capability.selection.max} selected node(s)`);
|
|
}
|
|
if (capability.confirmation === "always" && params.confirmed !== true) {
|
|
throw new Error(`${capability.title} requires explicit confirmation`);
|
|
}
|
|
|
|
return canvasCapabilityClientCommandSchema.parse({
|
|
version: 1,
|
|
requestId: params.requestId || crypto.randomUUID(),
|
|
capabilityId: params.capabilityId,
|
|
projectId: params.projectId,
|
|
nodeIds,
|
|
args: parseCanvasCapabilityArgs(params.capabilityId, params.args),
|
|
source: params.source,
|
|
confirmed: params.confirmed,
|
|
createdAt: params.createdAt || new Date().toISOString(),
|
|
});
|
|
}
|