- Strip tools/schema.ts from 1831 to 65 lines (remove duplicate tool defs) - Fix tools/index.ts to export ALL_TOOLS from registry instead of schema - Fix renderJsx → renderJSX typo in tools/create.ts and structure.ts - Add geometry.ts with shared rotation/coordinate math utilities - Add isArrayMixed() helper to use-multi-props.ts, deduplicate FillSection/StrokeSection/EffectsSection - Fix broken test imports: use @open-pencil/core instead of relative paths into packages/core/src/ - Merge duplicate import statements across all test files - Export profiler internals and style-run helpers from core index.ts - Add 6 new test files: color, undo, snap, vector, style-runs, text-editor (98 new tests) - Update renderer-effects test for renderer/ directory split
66 lines
1.7 KiB
TypeScript
66 lines
1.7 KiB
TypeScript
/**
|
|
* Tool definition schema.
|
|
*
|
|
* Each tool is defined once with typed params and an execute function
|
|
* that operates on FigmaAPI. Adapters for AI chat (valibot), CLI (citty),
|
|
* and MCP (JSON Schema) are generated from these definitions.
|
|
*/
|
|
|
|
import type { FigmaAPI, FigmaNodeProxy } from '../figma-api'
|
|
|
|
export type ParamType = 'string' | 'number' | 'boolean' | 'color' | 'string[]'
|
|
|
|
export interface ParamDef {
|
|
type: ParamType
|
|
description: string
|
|
required?: boolean
|
|
default?: unknown
|
|
enum?: string[]
|
|
min?: number
|
|
max?: number
|
|
}
|
|
|
|
export interface ToolDef {
|
|
name: string
|
|
description: string
|
|
mutates?: boolean
|
|
params: Record<string, ParamDef>
|
|
execute: (figma: FigmaAPI, args: Record<string, any>) => unknown
|
|
}
|
|
|
|
type ResolvedType<T extends ParamType> = T extends 'string'
|
|
? string
|
|
: T extends 'number'
|
|
? number
|
|
: T extends 'boolean'
|
|
? boolean
|
|
: T extends 'color'
|
|
? string
|
|
: T extends 'string[]'
|
|
? string[]
|
|
: never
|
|
|
|
type ResolvedParams<P extends Record<string, ParamDef>> = {
|
|
[K in keyof P as P[K]['required'] extends true ? K : never]: ResolvedType<P[K]['type']>
|
|
} & {
|
|
[K in keyof P as P[K]['required'] extends true ? never : K]?: ResolvedType<P[K]['type']>
|
|
}
|
|
|
|
export function defineTool<P extends Record<string, ParamDef>>(def: {
|
|
name: string
|
|
description: string
|
|
mutates?: boolean
|
|
params: P
|
|
execute: (figma: FigmaAPI, args: ResolvedParams<P>) => unknown
|
|
}): ToolDef {
|
|
return def as unknown as ToolDef
|
|
}
|
|
|
|
export function nodeToResult(node: FigmaNodeProxy): Record<string, unknown> {
|
|
return node.toJSON()
|
|
}
|
|
|
|
export function nodeSummary(node: FigmaNodeProxy): { id: string; name: string; type: string } {
|
|
return { id: node.id, name: node.name, type: node.type }
|
|
}
|