ai-chatbot/lib/canvas/capabilities/client-command.ts

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(),
});
}