* feat: name the call and list every problem in validation errors Tool arguments were checked with v.parse, whose error names only the first problem and neither the tool nor the argument, so a model that sent a wrong create_shape call read 'Expected string but received 42'. Tool arguments in Core, which AI chat, MCP, the CLI, and WebMCP all reach, the automation bridge's file commands, design JSX component properties, and gradient stops now throw a heading that names the call followed by v.summarize, which lists each issue with its path. parseToolArgs is exported for the app's own parses of tool arguments. * test(design-jsx): pass a deliberately wrong property value through the types The test checks what a script sees for a non-string instance property, which the Instance types reject at compile time. * docs: say that MCP clients get the MCP SDK's validation report The MCP SDK validates tool arguments against the registered schema before OpenPencil's handler runs, so an MCP client already received every problem with its path and does not see parseToolArgs' message.
39 lines
1.2 KiB
TypeScript
39 lines
1.2 KiB
TypeScript
import { describe, expect, test } from 'bun:test'
|
||
|
||
import * as v from 'valibot'
|
||
|
||
import { FigmaAPI } from '@open-pencil/core/figma-api'
|
||
import { defineTool } from '@open-pencil/core/tools'
|
||
import { SceneGraph } from '@open-pencil/scene-graph'
|
||
|
||
const tool = defineTool({
|
||
name: 'place_box',
|
||
description: 'Places a box',
|
||
execution: { kind: 'sync', mutation: 'none' },
|
||
input: v.object({
|
||
kind: v.picklist(['FRAME', 'RECTANGLE']),
|
||
width: v.pipe(v.number(), v.minValue(1))
|
||
}),
|
||
execute: (_figma, args) => args
|
||
})
|
||
|
||
describe('tool arguments', () => {
|
||
test('name the tool and list every problem with its argument', () => {
|
||
const figma = new FigmaAPI(new SceneGraph())
|
||
expect(() => tool.execute(figma, { kind: 'CIRCLE', width: 0 })).toThrow(
|
||
[
|
||
'Invalid arguments for place_box:',
|
||
'× Invalid type: Expected ("FRAME" | "RECTANGLE") but received "CIRCLE"',
|
||
' → at kind',
|
||
'× Invalid value: Expected >=1 but received 0',
|
||
' → at width'
|
||
].join('\n')
|
||
)
|
||
})
|
||
|
||
test('pass valid arguments through', () => {
|
||
const figma = new FigmaAPI(new SceneGraph())
|
||
expect(tool.execute(figma, { kind: 'FRAME', width: 10 })).toEqual({ kind: 'FRAME', width: 10 })
|
||
})
|
||
})
|