import type { ZodType, input as ZodInput, output as ZodOutput } from "zod"; export interface PluginRpcContract< InputSchema extends ZodType = ZodType, OutputSchema extends ZodType = ZodType, > { name: string; input: InputSchema; output: OutputSchema; } interface RpcDefinition { name: string; input: InputSchema; output: OutputSchema; } const RPC_NAME = /^[a-z][a-z0-9._-]*$/; export function defineRpc( definition: RpcDefinition, ): PluginRpcContract { const name = definition.name.trim(); if (!RPC_NAME.test(name)) throw new Error(`Invalid plugin RPC method: ${definition.name}`); return { ...definition, name }; } export async function callPluginRpc( contract: PluginRpcContract, invoke: (method: string, input: unknown) => Promise, input: ZodInput, ): Promise> { const parsedInput = await contract.input.parseAsync(input); const output = await invoke(contract.name, parsedInput); return contract.output.parseAsync(output); }