@elixpo/lixsketch 5.6.1 → 5.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -6
- package/dist/mcp/index.js +585 -0
- package/dist/mcp/index.js.map +7 -0
- package/dist/mcp/node.js +184 -0
- package/dist/mcp/node.js.map +7 -0
- package/dist/mcp/stdio.js +723 -0
- package/dist/mcp/stdio.js.map +7 -0
- package/package.json +7 -1
- package/src/mcp/fileStore.js +70 -0
- package/src/mcp/index.js +5 -0
- package/src/mcp/node.js +2 -0
- package/src/mcp/preview.js +39 -0
- package/src/mcp/scene.js +275 -0
- package/src/mcp/server.js +195 -0
- package/src/mcp/stdio.js +41 -0
- package/src/mcp/stdioTransport.js +46 -0
- package/src/mcp/store.js +23 -0
- package/src/mcp/templates.js +51 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/mcp/scene.js", "../../src/mcp/templates.js", "../../src/mcp/preview.js", "../../src/mcp/server.js", "../../src/mcp/store.js"],
|
|
4
|
+
"sourcesContent": ["const FORMAT = 'lixsketch';\nconst VERSION = 1;\nconst MAX_SHAPES = 5000;\nconst MAX_OPERATIONS = 500;\nconst SCENE_TYPES = new Set(['rectangle', 'circle', 'line', 'arrow', 'freehandStroke', 'frame', 'text', 'code', 'image', 'icon']);\nconst WRITABLE_TYPES = new Set(['rectangle', 'circle', 'line', 'arrow', 'freehandStroke', 'frame', 'text']);\n\nconst clone = (value) => JSON.parse(JSON.stringify(value));\nconst finite = (value, fallback = 0) => Number.isFinite(Number(value)) ? Number(value) : fallback;\nconst positive = (value, fallback = 1) => Math.max(1, finite(value, fallback));\n\nexport function createEmptyScene(name = 'MCP Canvas') {\n return {\n format: FORMAT,\n version: VERSION,\n sessionID: `mcp-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`,\n name: String(name || 'MCP Canvas').trim().slice(0, 72),\n createdAt: new Date().toISOString(),\n viewport: { x: 0, y: 0, width: 1280, height: 720 },\n zoom: 1,\n mcpRevision: 0,\n shapes: [],\n };\n}\n\nexport function validateScene(scene) {\n const errors = [];\n if (!scene || typeof scene !== 'object') return { valid: false, errors: ['Scene must be an object'] };\n if (scene.format !== FORMAT) errors.push(`Scene format must be \"${FORMAT}\"`);\n if (scene.version !== VERSION) errors.push(`Scene version must be ${VERSION}`);\n if (!Array.isArray(scene.shapes)) errors.push('Scene shapes must be an array');\n if (Array.isArray(scene.shapes) && scene.shapes.length > MAX_SHAPES) errors.push(`Scene exceeds ${MAX_SHAPES} shapes`);\n const ids = new Set();\n for (const [index, shape] of (scene.shapes || []).entries()) {\n if (!shape || typeof shape !== 'object') { errors.push(`Shape ${index} must be an object`); continue; }\n if (!SCENE_TYPES.has(shape.type)) errors.push(`Shape ${index} has unsupported type \"${shape.type}\"`);\n if (!shape.shapeID || typeof shape.shapeID !== 'string') errors.push(`Shape ${index} is missing shapeID`);\n else if (ids.has(shape.shapeID)) errors.push(`Duplicate shapeID \"${shape.shapeID}\"`);\n else ids.add(shape.shapeID);\n validateShapeGeometry(shape, index, errors);\n }\n return { valid: errors.length === 0, errors };\n}\n\nfunction escapeXml(value) {\n return String(value).replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('\"', '"').replaceAll(\"'\", ''');\n}\n\nfunction normalizeOptions(value = {}) {\n return {\n roughness: Math.max(0, Math.min(3, finite(value.roughness, 1.2))),\n stroke: typeof value.stroke === 'string' ? value.stroke : '#8b76d6',\n strokeWidth: Math.max(0.5, Math.min(20, finite(value.strokeWidth, 2))),\n fill: typeof value.fill === 'string' ? value.fill : 'transparent',\n fillStyle: typeof value.fillStyle === 'string' ? value.fillStyle : 'solid',\n opacity: Math.max(0, Math.min(1, finite(value.opacity, 1))),\n };\n}\n\nfunction createTextShape(input, shapeID) {\n const x = finite(input.x), y = finite(input.y), rotation = finite(input.rotation);\n const text = String(input.text || '').slice(0, 10000);\n const fontSize = Math.max(8, Math.min(160, finite(input.fontSize, 20)));\n const color = typeof input.color === 'string' ? input.color : '#e8e3f3';\n const family = typeof input.fontFamily === 'string' ? input.fontFamily.slice(0, 80) : 'lixFont';\n const transform = `translate(${x}, ${y})${rotation ? ` rotate(${rotation}, 0, 0)` : ''}`;\n const lines = text.split('\\n').map((line, index) => `<tspan x=\"0\" dy=\"${index === 0 ? 0 : '1.2em'}\">${escapeXml(line || ' ')}</tspan>`).join('');\n return {\n shapeID, type: 'text', x, y, rotation,\n mcpText: text, mcpFontSize: fontSize, mcpColor: color, mcpFontFamily: family,\n groupHTML: `<g id=\"${escapeXml(shapeID)}\" data-type=\"text-group\" data-x=\"${x}\" data-y=\"${y}\" transform=\"${transform}\"><text id=\"${escapeXml(shapeID)}-text\" x=\"0\" y=\"0\" fill=\"${escapeXml(color)}\" font-size=\"${fontSize}\" font-family=\"${escapeXml(family)}\" dominant-baseline=\"hanging\" white-space=\"pre\" pointer-events=\"painted\" data-type=\"text\" data-initial-size=\"${fontSize}\" data-initial-font=\"${escapeXml(family)}\" data-initial-color=\"${escapeXml(color)}\">${lines}</text></g>`,\n };\n}\n\nexport function normalizeShape(input, existingIds = new Set()) {\n if (!input || typeof input !== 'object') throw new Error('Shape must be an object');\n if (!WRITABLE_TYPES.has(input.type)) throw new Error(`Shape type \"${input.type}\" is read-only through MCP`);\n let shapeID = String(input.shapeID || `${input.type}-${crypto.randomUUID()}`).slice(0, 120);\n while (existingIds.has(shapeID)) shapeID = `${input.type}-${crypto.randomUUID()}`;\n const base = { shapeID, type: input.type, rotation: finite(input.rotation), options: normalizeOptions(input.options), groupId: input.groupId || null, parentFrame: input.parentFrame || null, docBlockIds: [] };\n switch (input.type) {\n case 'rectangle': return { ...base, x: finite(input.x), y: finite(input.y), width: positive(input.width, 160), height: positive(input.height, 90) };\n case 'circle': return { ...base, x: finite(input.x), y: finite(input.y), rx: positive(input.rx, 60), ry: positive(input.ry, 60) };\n case 'line': return { ...base, startPoint: point(input.startPoint), endPoint: point(input.endPoint, 120), isCurved: Boolean(input.isCurved), controlPoint: input.controlPoint ? point(input.controlPoint) : null };\n case 'arrow': return { ...base, startPoint: point(input.startPoint), endPoint: point(input.endPoint, 120), arrowHeadStyle: input.arrowHeadStyle || 'triangle', arrowOutlineStyle: input.arrowOutlineStyle || 'solid', arrowCurved: Boolean(input.arrowCurved), arrowCurveAmount: finite(input.arrowCurveAmount, 0.2) };\n case 'freehandStroke': {\n const points = (Array.isArray(input.points) ? input.points : []).slice(0, 4096).map((entry) => [finite(entry?.[0]), finite(entry?.[1]), finite(entry?.[2], 0.5)]);\n if (points.length < 2) throw new Error('freehandStroke requires at least two points');\n return { ...base, points };\n }\n case 'frame': return { ...base, x: finite(input.x), y: finite(input.y), width: positive(input.width, 640), height: positive(input.height, 360), frameName: String(input.frameName || 'Frame').slice(0, 80), fillStyle: input.fillStyle || 'transparent', fillColor: input.fillColor || '#1e1e28', gridSize: positive(input.gridSize, 20), containedShapeIDs: [] };\n case 'text': return { ...base, ...createTextShape(input, shapeID) };\n default: throw new Error(`Unsupported shape type \"${input.type}\"`);\n }\n}\n\nfunction point(value, fallbackX = 0) {\n return { x: finite(value?.x, fallbackX), y: finite(value?.y) };\n}\n\nfunction translateShape(shape, dx, dy) {\n const moved = clone(shape);\n if (moved.startPoint) { moved.startPoint.x += dx; moved.startPoint.y += dy; }\n if (moved.endPoint) { moved.endPoint.x += dx; moved.endPoint.y += dy; }\n if (moved.controlPoint) { moved.controlPoint.x += dx; moved.controlPoint.y += dy; }\n if (moved.controlPoint1) { moved.controlPoint1.x += dx; moved.controlPoint1.y += dy; }\n if (moved.controlPoint2) { moved.controlPoint2.x += dx; moved.controlPoint2.y += dy; }\n if (Array.isArray(moved.points)) moved.points = moved.points.map((p) => [p[0] + dx, p[1] + dy, ...p.slice(2)]);\n if (Number.isFinite(moved.x)) moved.x += dx;\n if (Number.isFinite(moved.y)) moved.y += dy;\n if (moved.type === 'text' && moved.groupHTML) {\n moved.groupHTML = moved.groupHTML\n .replace(/data-x=\"[^\"]*\"/, `data-x=\"${moved.x}\"`)\n .replace(/data-y=\"[^\"]*\"/, `data-y=\"${moved.y}\"`)\n .replace(/transform=\"translate\\([^)]*\\)/, `transform=\"translate(${moved.x}, ${moved.y})`);\n }\n if (moved.type === 'code' && moved.groupHTML) {\n moved.groupHTML = moved.groupHTML\n .replace(/data-x=\"[^\"]*\"/, `data-x=\"${moved.x}\"`)\n .replace(/data-y=\"[^\"]*\"/, `data-y=\"${moved.y}\"`)\n .replace(/transform=\"translate\\([^)]*\\)/, `transform=\"translate(${moved.x}, ${moved.y})`);\n }\n if (moved.type === 'icon' && moved.elementHTML) {\n moved.elementHTML = moved.elementHTML\n .replace(/\\bx=\"[^\"]*\"/, `x=\"${moved.x}\"`)\n .replace(/\\by=\"[^\"]*\"/, `y=\"${moved.y}\"`);\n }\n return moved;\n}\n\nexport function applyScenePatch(sceneInput, operations, { expectedRevision, dryRun = false } = {}) {\n const scene = clone(sceneInput);\n const check = validateScene(scene);\n if (!check.valid) throw new Error(`Invalid scene: ${check.errors.join('; ')}`);\n if (!Array.isArray(operations) || operations.length === 0) throw new Error('At least one operation is required');\n if (operations.length > MAX_OPERATIONS) throw new Error(`Patch exceeds ${MAX_OPERATIONS} operations`);\n const revision = Number(scene.mcpRevision || 0);\n if (expectedRevision !== undefined && Number(expectedRevision) !== revision) throw new Error(`Revision conflict: expected ${expectedRevision}, current ${revision}`);\n const changedIds = new Set();\n for (const operation of operations) {\n if (!operation || typeof operation !== 'object') throw new Error('Each operation must be an object');\n if (operation.op === 'add') {\n if (scene.shapes.length >= MAX_SHAPES) throw new Error(`Scene exceeds ${MAX_SHAPES} shapes`);\n const ids = new Set(scene.shapes.map((shape) => shape.shapeID));\n const shape = normalizeShape(operation.shape, ids);\n scene.shapes.push(shape); changedIds.add(shape.shapeID);\n } else if (operation.op === 'update') {\n const index = scene.shapes.findIndex((shape) => shape.shapeID === operation.shapeID);\n if (index < 0) throw new Error(`Shape \"${operation.shapeID}\" was not found`);\n const immutable = scene.shapes[index];\n scene.shapes[index] = applyShapeChanges(immutable, operation.changes || {}); changedIds.add(immutable.shapeID);\n } else if (operation.op === 'delete') {\n const ids = new Set(Array.isArray(operation.shapeIDs) ? operation.shapeIDs : [operation.shapeID]);\n const before = scene.shapes.length;\n scene.shapes = scene.shapes.filter((shape) => !ids.has(shape.shapeID));\n if (scene.shapes.length === before) throw new Error('No requested shapes were found');\n scene.shapes.forEach((shape) => {\n if (ids.has(shape.parentFrame)) shape.parentFrame = null;\n if (Array.isArray(shape.containedShapeIDs)) shape.containedShapeIDs = shape.containedShapeIDs.filter((id) => !ids.has(id));\n });\n ids.forEach((id) => changedIds.add(id));\n } else if (operation.op === 'translate') {\n const ids = new Set(operation.shapeIDs || []), dx = finite(operation.dx), dy = finite(operation.dy);\n if (!ids.size) throw new Error('translate requires shapeIDs');\n scene.shapes = scene.shapes.map((shape) => ids.has(shape.shapeID) ? translateShape(shape, dx, dy) : shape);\n ids.forEach((id) => changedIds.add(id));\n } else if (operation.op === 'rename_canvas') {\n scene.name = String(operation.name || '').trim().slice(0, 72) || scene.name;\n } else throw new Error(`Unsupported operation \"${operation.op}\"`);\n }\n scene.mcpRevision = revision + 1;\n scene.updatedAt = new Date().toISOString();\n const result = validateScene(scene);\n if (!result.valid) throw new Error(`Patch produced an invalid scene: ${result.errors.join('; ')}`);\n return { scene, revision: scene.mcpRevision, dryRun: Boolean(dryRun), changedShapeIDs: [...changedIds] };\n}\n\nfunction applyShapeChanges(shape, changes) {\n if (!changes || typeof changes !== 'object' || Array.isArray(changes)) throw new Error('Shape changes must be an object');\n const allowed = {\n rectangle: ['x', 'y', 'width', 'height', 'rotation', 'options', 'groupId', 'parentFrame'],\n circle: ['x', 'y', 'rx', 'ry', 'rotation', 'options', 'groupId', 'parentFrame'],\n line: ['startPoint', 'endPoint', 'controlPoint', 'isCurved', 'options', 'groupId', 'parentFrame'],\n arrow: ['startPoint', 'endPoint', 'controlPoint1', 'controlPoint2', 'arrowHeadStyle', 'arrowOutlineStyle', 'arrowCurved', 'arrowCurveAmount', 'options', 'groupId', 'parentFrame'],\n freehandStroke: ['points', 'rotation', 'options', 'groupId', 'parentFrame'],\n frame: ['x', 'y', 'width', 'height', 'rotation', 'frameName', 'fillStyle', 'fillColor', 'gridSize', 'options', 'groupId', 'parentFrame'],\n text: ['x', 'y', 'rotation', 'text', 'fontSize', 'color', 'fontFamily', 'groupId', 'parentFrame'],\n }[shape.type] || [];\n const rejected = Object.keys(changes).filter((key) => !allowed.includes(key));\n if (rejected.length) throw new Error(`Cannot update ${shape.type} fields: ${rejected.join(', ')}`);\n if (shape.type === 'text') {\n const text = changes.text ?? shape.mcpText ?? extractText(shape.groupHTML);\n return { ...shape, ...createTextShape({ x: changes.x ?? shape.x, y: changes.y ?? shape.y, rotation: changes.rotation ?? shape.rotation, text, fontSize: changes.fontSize ?? shape.mcpFontSize, color: changes.color ?? shape.mcpColor, fontFamily: changes.fontFamily ?? shape.mcpFontFamily }, shape.shapeID), groupId: changes.groupId ?? shape.groupId, parentFrame: changes.parentFrame ?? shape.parentFrame };\n }\n const copy = { ...clone(shape), ...clone(changes), shapeID: shape.shapeID, type: shape.type };\n if (changes.options) copy.options = { ...(shape.options || {}), ...normalizeOptions({ ...(shape.options || {}), ...changes.options }) };\n return copy;\n}\n\nfunction extractText(groupHTML = '') {\n return String(groupHTML).replace(/<[^>]+>/g, ' ').replace(/\\s+/g, ' ').trim();\n}\n\nfunction validateShapeGeometry(shape, index, errors) {\n const numbers = [];\n if (['rectangle', 'frame', 'text', 'code', 'image', 'icon'].includes(shape.type)) numbers.push(['x', shape.x], ['y', shape.y]);\n if (['rectangle', 'frame', 'image', 'icon'].includes(shape.type)) numbers.push(['width', shape.width], ['height', shape.height]);\n if (shape.type === 'circle') numbers.push(['x', shape.x], ['y', shape.y], ['rx', shape.rx], ['ry', shape.ry]);\n if (shape.startPoint) numbers.push(['startPoint.x', shape.startPoint.x], ['startPoint.y', shape.startPoint.y]);\n if (shape.endPoint) numbers.push(['endPoint.x', shape.endPoint.x], ['endPoint.y', shape.endPoint.y]);\n for (const [field, value] of numbers) if (!Number.isFinite(Number(value))) errors.push(`Shape ${index} has invalid ${field}`);\n if (['rectangle', 'frame', 'image', 'icon'].includes(shape.type) && (Number(shape.width) <= 0 || Number(shape.height) <= 0)) errors.push(`Shape ${index} must have positive dimensions`);\n if (shape.type === 'circle' && (Number(shape.rx) <= 0 || Number(shape.ry) <= 0)) errors.push(`Shape ${index} must have positive radii`);\n if (shape.type === 'freehandStroke' && (!Array.isArray(shape.points) || shape.points.length < 2 || shape.points.length > 4096)) errors.push(`Shape ${index} has invalid freehand points`);\n if (shape.type === 'text' && typeof shape.groupHTML !== 'string') errors.push(`Shape ${index} is missing text markup`);\n if (shape.type === 'code' && typeof shape.groupHTML !== 'string') errors.push(`Shape ${index} is missing code markup`);\n if (shape.type === 'image' && typeof shape.href !== 'string') errors.push(`Shape ${index} is missing image href`);\n if (shape.type === 'icon' && typeof shape.elementHTML !== 'string') errors.push(`Shape ${index} is missing icon markup`);\n}\n\nexport function getSceneSummary(scene) {\n const counts = {};\n for (const shape of scene.shapes || []) counts[shape.type] = (counts[shape.type] || 0) + 1;\n return { name: scene.name, format: scene.format, version: scene.version, revision: Number(scene.mcpRevision || 0), shapeCount: scene.shapes?.length || 0, counts, bounds: getSceneBounds(scene) };\n}\n\nexport function getSceneBounds(scene) {\n const boxes = (scene.shapes || []).map(shapeBounds).filter(Boolean);\n if (!boxes.length) return null;\n const minX = Math.min(...boxes.map((b) => b.x)), minY = Math.min(...boxes.map((b) => b.y));\n const maxX = Math.max(...boxes.map((b) => b.x + b.width)), maxY = Math.max(...boxes.map((b) => b.y + b.height));\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\nexport function shapeBounds(shape) {\n if (shape.type === 'circle') return { x: shape.x - shape.rx, y: shape.y - shape.ry, width: shape.rx * 2, height: shape.ry * 2 };\n if (shape.startPoint && shape.endPoint) {\n const x = Math.min(shape.startPoint.x, shape.endPoint.x), y = Math.min(shape.startPoint.y, shape.endPoint.y);\n return { x, y, width: Math.abs(shape.endPoint.x - shape.startPoint.x), height: Math.abs(shape.endPoint.y - shape.startPoint.y) };\n }\n if (Array.isArray(shape.points) && shape.points.length) {\n const xs = shape.points.map((p) => p[0]), ys = shape.points.map((p) => p[1]);\n return { x: Math.min(...xs), y: Math.min(...ys), width: Math.max(...xs) - Math.min(...xs), height: Math.max(...ys) - Math.min(...ys) };\n }\n if (shape.type === 'text') return { x: finite(shape.x), y: finite(shape.y), width: 160, height: 32 };\n return { x: finite(shape.x), y: finite(shape.y), width: positive(shape.width), height: positive(shape.height) };\n}\n\nexport function mergeTemplateScene(sceneInput, templateInput, { x, y } = {}) {\n const scene = clone(sceneInput), template = clone(templateInput);\n const validation = validateScene(template);\n if (!validation.valid) throw new Error(`Template scene is invalid: ${validation.errors.join('; ')}`);\n if (scene.shapes.length + template.shapes.length > MAX_SHAPES) throw new Error(`Imported template would exceed ${MAX_SHAPES} shapes`);\n const bounds = getSceneBounds(template) || { x: 0, y: 0 };\n const targetX = finite(x, scene.viewport?.x || 0), targetY = finite(y, scene.viewport?.y || 0);\n const dx = targetX - bounds.x, dy = targetY - bounds.y;\n const idMap = new Map(template.shapes.map((shape) => [shape.shapeID, `${shape.type}-${crypto.randomUUID()}`]));\n const imported = template.shapes.map((shape) => {\n const moved = translateShape(shape, dx, dy);\n moved.shapeID = idMap.get(shape.shapeID);\n if (moved.parentFrame) moved.parentFrame = idMap.get(moved.parentFrame) || null;\n if (Array.isArray(moved.containedShapeIDs)) moved.containedShapeIDs = moved.containedShapeIDs.map((id) => idMap.get(id)).filter(Boolean);\n if (moved.startAttachmentID) moved.startAttachmentID = idMap.get(moved.startAttachmentID) || null;\n if (moved.endAttachmentID) moved.endAttachmentID = idMap.get(moved.endAttachmentID) || null;\n if (moved.groupHTML) moved.groupHTML = moved.groupHTML.split(shape.shapeID).join(moved.shapeID);\n if (moved.elementHTML) moved.elementHTML = moved.elementHTML.split(shape.shapeID).join(moved.shapeID);\n return moved;\n });\n scene.shapes.push(...imported);\n scene.mcpRevision = Number(scene.mcpRevision || 0) + 1;\n scene.updatedAt = new Date().toISOString();\n return { scene, revision: scene.mcpRevision, importedShapeIDs: imported.map((shape) => shape.shapeID) };\n}\n\nexport const MCP_LIMITS = Object.freeze({ maxShapes: MAX_SHAPES, maxOperations: MAX_OPERATIONS });\n", "const DEFAULT_MARKETPLACE_URL = 'https://sketch.elixpo.com';\n\nfunction decodeBase64Url(value) {\n const base64 = String(value).replaceAll('-', '+').replaceAll('_', '/');\n const padded = base64 + '='.repeat((4 - base64.length % 4) % 4);\n const binary = atob(padded);\n return Uint8Array.from(binary, (character) => character.charCodeAt(0));\n}\n\nexport async function decryptPublicTemplate(ciphertext, keyValue) {\n const keyBytes = decodeBase64Url(keyValue);\n if (keyBytes.byteLength !== 32) throw new Error('Template key is not AES-256');\n const combined = decodeBase64Url(ciphertext);\n if (combined.byteLength < 28) throw new Error('Template ciphertext is invalid');\n const key = await crypto.subtle.importKey('raw', keyBytes, { name: 'AES-GCM', length: 256 }, false, ['decrypt']);\n const plaintext = await crypto.subtle.decrypt({ name: 'AES-GCM', iv: combined.slice(0, 12) }, key, combined.slice(12));\n return JSON.parse(new TextDecoder().decode(plaintext));\n}\n\nexport class MarketplaceTemplateProvider {\n constructor({ baseUrl = DEFAULT_MARKETPLACE_URL, fetchImpl = globalThis.fetch } = {}) {\n if (typeof fetchImpl !== 'function') throw new Error('MarketplaceTemplateProvider requires fetch');\n this.baseUrl = String(baseUrl).replace(/\\/$/, '');\n this.fetch = fetchImpl;\n }\n\n async search({ query = '', tag = '', limit = 12 } = {}) {\n const url = new URL('/api/templates', this.baseUrl);\n if (query) url.searchParams.set('q', String(query).slice(0, 80));\n if (tag) url.searchParams.set('tag', String(tag).slice(0, 24));\n url.searchParams.set('limit', String(Math.min(24, Math.max(1, Number(limit) || 12))));\n const response = await this.fetch(url, { headers: { accept: 'application/json' } });\n const body = await response.json();\n if (!response.ok) throw new Error(body.error || `Marketplace request failed (${response.status})`);\n return body.templates || [];\n }\n\n async load(slug) {\n const safeSlug = String(slug || '').trim();\n if (!/^[a-z0-9-]{1,80}$/.test(safeSlug)) throw new Error('Template slug is invalid');\n const url = new URL(`/api/templates/${encodeURIComponent(safeSlug)}`, this.baseUrl);\n url.searchParams.set('snapshot', '1');\n const response = await this.fetch(url, { headers: { accept: 'application/json' } });\n const body = await response.json();\n if (!response.ok) throw new Error(body.error || `Template request failed (${response.status})`);\n const template = body.template;\n if (!template?.encryptedData || !template?.publicKey) throw new Error('Template snapshot is unavailable');\n return { metadata: { ...template, encryptedData: undefined, publicKey: undefined, encryptedDocData: undefined }, scene: await decryptPublicTemplate(template.encryptedData, template.publicKey) };\n }\n}\n\n", "import { getSceneBounds } from './scene.js';\n\nconst MAX_PREVIEW_BYTES = 5 * 1024 * 1024;\n\nconst esc = (value) => String(value ?? '').replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('\"', '"');\nconst color = (value, fallback) => typeof value === 'string' && /^#[0-9a-f]{3,8}$/i.test(value) ? value : fallback;\n\nfunction options(shape) {\n return {\n stroke: color(shape.options?.stroke, '#8b76d6'),\n fill: shape.options?.fill === 'transparent' ? 'none' : color(shape.options?.fill, 'none'),\n width: Math.max(0.5, Math.min(20, Number(shape.options?.strokeWidth) || 2)),\n opacity: Math.max(0, Math.min(1, Number(shape.options?.opacity) || 1)),\n };\n}\n\nfunction renderShape(shape) {\n const style = options(shape);\n const attrs = `stroke=\"${style.stroke}\" stroke-width=\"${style.width}\" fill=\"${style.fill}\" opacity=\"${style.opacity}\"`;\n if (shape.type === 'rectangle') return `<rect x=\"${shape.x}\" y=\"${shape.y}\" width=\"${shape.width}\" height=\"${shape.height}\" rx=\"6\" ${attrs}/>`;\n if (shape.type === 'circle') return `<ellipse cx=\"${shape.x}\" cy=\"${shape.y}\" rx=\"${shape.rx}\" ry=\"${shape.ry}\" ${attrs}/>`;\n if (shape.type === 'line') return `<line x1=\"${shape.startPoint.x}\" y1=\"${shape.startPoint.y}\" x2=\"${shape.endPoint.x}\" y2=\"${shape.endPoint.y}\" ${attrs}/>`;\n if (shape.type === 'arrow') return `<line x1=\"${shape.startPoint.x}\" y1=\"${shape.startPoint.y}\" x2=\"${shape.endPoint.x}\" y2=\"${shape.endPoint.y}\" ${attrs} marker-end=\"url(#arrowhead)\"/>`;\n if (shape.type === 'freehandStroke') return `<polyline points=\"${shape.points.map((p) => `${p[0]},${p[1]}`).join(' ')}\" ${attrs} fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>`;\n if (shape.type === 'frame') return `<g><rect x=\"${shape.x}\" y=\"${shape.y}\" width=\"${shape.width}\" height=\"${shape.height}\" ${attrs} stroke-dasharray=\"6 5\"/><text x=\"${shape.x + 8}\" y=\"${shape.y - 8}\" fill=\"#9f94b5\" font-size=\"14\">${esc(shape.frameName || 'Frame')}</text></g>`;\n if (shape.type === 'text') return `<text x=\"${shape.x}\" y=\"${shape.y}\" fill=\"${color(shape.mcpColor, '#e8e3f3')}\" font-size=\"${Number(shape.mcpFontSize) || 20}\" font-family=\"sans-serif\">${esc(shape.mcpText || String(shape.groupHTML || '').replace(/<[^>]+>/g, ' ').trim())}</text>`;\n return '';\n}\n\nexport function renderSceneSvg(scene, { background = '#15111f', padding = 40 } = {}) {\n const bounds = getSceneBounds(scene) || { x: 0, y: 0, width: 1280, height: 720 };\n const pad = Math.max(0, Math.min(200, Number(padding) || 0));\n const viewBox = { x: bounds.x - pad, y: bounds.y - pad, width: Math.max(1, bounds.width + pad * 2), height: Math.max(1, bounds.height + pad * 2) };\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}\" width=\"${Math.ceil(viewBox.width)}\" height=\"${Math.ceil(viewBox.height)}\"><defs><marker id=\"arrowhead\" markerWidth=\"10\" markerHeight=\"7\" refX=\"9\" refY=\"3.5\" orient=\"auto\"><polygon points=\"0 0,10 3.5,0 7\" fill=\"#8b76d6\"/></marker></defs><rect x=\"${viewBox.x}\" y=\"${viewBox.y}\" width=\"${viewBox.width}\" height=\"${viewBox.height}\" fill=\"${color(background, '#15111f')}\"/>${(scene.shapes || []).map(renderShape).join('')}</svg>`;\n if (new TextEncoder().encode(svg).byteLength > MAX_PREVIEW_BYTES) {\n throw new Error('Canvas preview exceeds the 5 MB output limit');\n }\n return svg;\n}\n", "import { applyScenePatch, createEmptyScene, getSceneSummary, mergeTemplateScene, validateScene, MCP_LIMITS } from './scene.js';\nimport { MarketplaceTemplateProvider } from './templates.js';\nimport { renderSceneSvg } from './preview.js';\n\nconst SERVER_NAME = 'lixsketch';\nconst SERVER_VERSION = '1.0.0';\nconst PROTOCOL_VERSION = '2025-11-25';\nconst SUPPORTED_PROTOCOL_VERSIONS = new Set([PROTOCOL_VERSION, '2025-06-18', '2024-11-05']);\n\nconst PATCH_OPERATION_SCHEMA = {\n oneOf: [\n { type: 'object', required: ['op', 'shape'], properties: { op: { const: 'add' }, shape: { type: 'object', description: 'A rectangle, circle, line, arrow, frame, freehandStroke, or text shape.' } } },\n { type: 'object', required: ['op', 'shapeID', 'changes'], properties: { op: { const: 'update' }, shapeID: { type: 'string' }, changes: { type: 'object' } } },\n { type: 'object', required: ['op'], properties: { op: { const: 'delete' }, shapeID: { type: 'string' }, shapeIDs: { type: 'array', items: { type: 'string' } } } },\n { type: 'object', required: ['op', 'shapeIDs', 'dx', 'dy'], properties: { op: { const: 'translate' }, shapeIDs: { type: 'array', items: { type: 'string' } }, dx: { type: 'number' }, dy: { type: 'number' } } },\n { type: 'object', required: ['op', 'name'], properties: { op: { const: 'rename_canvas' }, name: { type: 'string', maxLength: 72 } } },\n ],\n};\n\nexport const LIXSKETCH_MCP_TOOLS = Object.freeze([\n {\n name: 'canvas_get',\n title: 'Read LixSketch canvas',\n description: 'Return the canvas summary and optionally its editable scene shapes. Read this before mutation to obtain the current revision.',\n inputSchema: { type: 'object', properties: { includeShapes: { type: 'boolean', default: false }, shapeIDs: { type: 'array', maxItems: 500, items: { type: 'string' } } }, additionalProperties: false },\n annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },\n },\n {\n name: 'canvas_apply_patch',\n title: 'Apply atomic canvas patch',\n description: `Atomically add, update, translate, or delete shapes. Supports ${MCP_LIMITS.maxOperations} operations per call, optimistic revision checks, and dry runs.`,\n inputSchema: { type: 'object', required: ['operations'], properties: { expectedRevision: { type: 'integer', minimum: 0 }, dryRun: { type: 'boolean', default: false }, operations: { type: 'array', minItems: 1, maxItems: MCP_LIMITS.maxOperations, items: PATCH_OPERATION_SCHEMA } }, additionalProperties: false },\n annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false },\n },\n {\n name: 'canvas_validate',\n title: 'Validate LixSketch canvas',\n description: 'Validate the current scene format, supported shapes, unique IDs, and package limits.',\n inputSchema: { type: 'object', properties: {}, additionalProperties: false },\n annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },\n },\n {\n name: 'canvas_preview',\n title: 'Render canvas preview',\n description: 'Render a lightweight SVG preview of the current scene for visual inspection before or after edits.',\n inputSchema: { type: 'object', properties: { background: { type: 'string', pattern: '^#[0-9a-fA-F]{3,8}$' }, padding: { type: 'number', minimum: 0, maximum: 200, default: 40 } }, additionalProperties: false },\n annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },\n },\n {\n name: 'canvas_new',\n title: 'Create blank LixSketch canvas',\n description: 'Replace the current scene with a blank canvas. Requires explicit confirmation.',\n inputSchema: { type: 'object', required: ['confirm'], properties: { name: { type: 'string', maxLength: 72 }, confirm: { const: true } }, additionalProperties: false },\n annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false },\n },\n {\n name: 'templates_search',\n title: 'Search LixSketch templates',\n description: 'Search published workspace and component templates in the LixSketch marketplace.',\n inputSchema: { type: 'object', properties: { query: { type: 'string', maxLength: 80 }, tag: { type: 'string', maxLength: 24 }, limit: { type: 'integer', minimum: 1, maximum: 24, default: 12 } }, additionalProperties: false },\n annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },\n },\n {\n name: 'template_insert',\n title: 'Insert LixSketch template',\n description: 'Insert a published template into the current canvas, remapping every shape and relationship ID. The operation is atomic and supports a dry run.',\n inputSchema: { type: 'object', required: ['slug'], properties: { slug: { type: 'string', pattern: '^[a-z0-9-]{1,80}$' }, x: { type: 'number' }, y: { type: 'number' }, expectedRevision: { type: 'integer', minimum: 0 }, dryRun: { type: 'boolean', default: false } }, additionalProperties: false },\n annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },\n },\n]);\n\nfunction toolResult(value, message) {\n return {\n content: [{ type: 'text', text: message || JSON.stringify(value, null, 2) }],\n structuredContent: value,\n };\n}\n\nfunction toolError(error) {\n const message = error instanceof Error ? error.message : String(error);\n return { isError: true, content: [{ type: 'text', text: message }], structuredContent: { error: message } };\n}\n\nexport class LixSketchMcpServer {\n constructor({ store, templateProvider = new MarketplaceTemplateProvider(), serverInfo = {} } = {}) {\n if (!store?.read || !store?.write) throw new Error('createLixSketchMcpServer requires a scene store with read() and write()');\n this.store = store;\n this.templateProvider = templateProvider;\n this.serverInfo = { name: SERVER_NAME, version: SERVER_VERSION, ...serverInfo };\n this.mutationChain = Promise.resolve();\n }\n\n listTools() {\n return LIXSKETCH_MCP_TOOLS;\n }\n\n async callTool(name, args = {}) {\n try {\n switch (name) {\n case 'canvas_get': {\n const scene = await this.store.read();\n let shapes;\n if (args.includeShapes) {\n const ids = new Set(args.shapeIDs || []);\n shapes = ids.size ? scene.shapes.filter((shape) => ids.has(shape.shapeID)) : scene.shapes;\n }\n return toolResult({ summary: getSceneSummary(scene), ...(shapes ? { shapes } : {}) });\n }\n case 'canvas_validate': {\n const scene = await this.store.read();\n const validation = validateScene(scene);\n return toolResult({ ...validation, summary: getSceneSummary(scene), limits: MCP_LIMITS });\n }\n case 'canvas_preview': {\n const scene = await this.store.read();\n const svg = renderSceneSvg(scene, args);\n return toolResult({ svg, dataUrl: `data:image/svg+xml;base64,${encodeBase64(svg)}`, summary: getSceneSummary(scene) }, svg);\n }\n case 'templates_search': {\n const templates = await this.templateProvider.search(args);\n return toolResult({ templates: templates.map(safeTemplateMetadata) });\n }\n case 'canvas_apply_patch':\n return await this.enqueueMutation(async () => {\n const scene = await this.store.read();\n const result = applyScenePatch(scene, args.operations, args);\n if (!args.dryRun) await this.store.write(result.scene);\n return toolResult({ revision: result.revision, dryRun: result.dryRun, changedShapeIDs: result.changedShapeIDs, summary: getSceneSummary(result.scene) }, args.dryRun ? 'Canvas patch is valid. No changes were saved.' : `Canvas patch saved at revision ${result.revision}.`);\n });\n case 'canvas_new':\n if (args.confirm !== true) throw new Error('canvas_new requires confirm=true');\n return await this.enqueueMutation(async () => {\n const scene = createEmptyScene(args.name);\n await this.store.write(scene);\n return toolResult({ summary: getSceneSummary(scene) }, 'Blank canvas created.');\n });\n case 'template_insert':\n return await this.enqueueMutation(async () => {\n const scene = await this.store.read();\n const revision = Number(scene.mcpRevision || 0);\n if (args.expectedRevision !== undefined && Number(args.expectedRevision) !== revision) throw new Error(`Revision conflict: expected ${args.expectedRevision}, current ${revision}`);\n const template = await this.templateProvider.load(args.slug);\n const result = mergeTemplateScene(scene, template.scene, args);\n if (!args.dryRun) await this.store.write(result.scene);\n return toolResult({ template: safeTemplateMetadata(template.metadata), revision: result.revision, dryRun: Boolean(args.dryRun), importedShapeIDs: result.importedShapeIDs, summary: getSceneSummary(result.scene) }, args.dryRun ? 'Template import is valid. No changes were saved.' : `Template inserted with ${result.importedShapeIDs.length} shapes.`);\n });\n default: throw new Error(`Unknown tool \"${name}\"`);\n }\n } catch (error) {\n return toolError(error);\n }\n }\n\n enqueueMutation(operation) {\n const pending = this.mutationChain.then(operation, operation);\n this.mutationChain = pending.catch(() => {});\n return pending;\n }\n\n async handleRequest(request) {\n const method = request?.method;\n if (method === 'initialize') {\n const requested = request.params?.protocolVersion;\n const protocolVersion = SUPPORTED_PROTOCOL_VERSIONS.has(requested) ? requested : PROTOCOL_VERSION;\n return { protocolVersion, capabilities: { tools: { listChanged: false }, resources: { subscribe: false, listChanged: false } }, serverInfo: this.serverInfo, instructions: 'Read canvas_get before mutations. Use expectedRevision and dryRun for safe edits. Prefer template_insert for reusable component packs.' };\n }\n if (method === 'ping') return {};\n if (method === 'tools/list') return { tools: this.listTools() };\n if (method === 'tools/call') return this.callTool(request.params?.name, request.params?.arguments || {});\n if (method === 'resources/list') return { resources: [{ uri: 'lixsketch://canvas', name: 'Current LixSketch canvas', description: 'The active editable .lixjson scene', mimeType: 'application/vnd.lixsketch+json' }, { uri: 'lixsketch://canvas/preview.svg', name: 'Current canvas preview', description: 'A lightweight SVG preview of the current scene', mimeType: 'image/svg+xml' }] };\n if (method === 'resources/read') {\n const scene = await this.store.read();\n if (request.params?.uri === 'lixsketch://canvas') return { contents: [{ uri: 'lixsketch://canvas', mimeType: 'application/vnd.lixsketch+json', text: JSON.stringify(scene) }] };\n if (request.params?.uri === 'lixsketch://canvas/preview.svg') return { contents: [{ uri: 'lixsketch://canvas/preview.svg', mimeType: 'image/svg+xml', text: renderSceneSvg(scene) }] };\n throw Object.assign(new Error('Resource not found'), { code: -32002 });\n }\n if (method?.startsWith('notifications/')) return undefined;\n throw Object.assign(new Error(`Method not found: ${method}`), { code: -32601 });\n }\n}\n\nfunction safeTemplateMetadata(template = {}) {\n return { id: template.id, slug: template.slug, title: template.title, description: template.description || '', tags: template.tags || [], publisher: template.publisher, views: template.views, forks: template.forks, clones: template.clones, publishedAt: template.publishedAt, updatedAt: template.updatedAt };\n}\n\nfunction encodeBase64(value) {\n if (typeof btoa === 'function') return btoa(unescape(encodeURIComponent(value)));\n return Buffer.from(value, 'utf8').toString('base64');\n}\n\nexport function createLixSketchMcpServer(options) {\n return new LixSketchMcpServer(options);\n}\n\nexport { PROTOCOL_VERSION as LIXSKETCH_MCP_PROTOCOL_VERSION };\n", "import { createEmptyScene, validateScene } from './scene.js';\n\nexport class MemorySceneStore {\n #scene;\n\n constructor(scene = createEmptyScene()) {\n const validation = validateScene(scene);\n if (!validation.valid) throw new Error(`Invalid initial scene: ${validation.errors.join('; ')}`);\n this.#scene = structuredClone(scene);\n }\n\n async read() {\n return structuredClone(this.#scene);\n }\n\n async write(scene) {\n const validation = validateScene(scene);\n if (!validation.valid) throw new Error(`Refusing to store invalid scene: ${validation.errors.join('; ')}`);\n this.#scene = structuredClone(scene);\n return this.read();\n }\n}\n\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["color", "shape", "options"]
|
|
7
|
+
}
|
package/dist/mcp/node.js
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// src/mcp/fileStore.js
|
|
2
|
+
import { mkdir, open, readFile, rename, stat, unlink } from "node:fs/promises";
|
|
3
|
+
import { dirname, resolve } from "node:path";
|
|
4
|
+
|
|
5
|
+
// src/mcp/scene.js
|
|
6
|
+
var FORMAT = "lixsketch";
|
|
7
|
+
var VERSION = 1;
|
|
8
|
+
var MAX_SHAPES = 5e3;
|
|
9
|
+
var MAX_OPERATIONS = 500;
|
|
10
|
+
var SCENE_TYPES = /* @__PURE__ */ new Set(["rectangle", "circle", "line", "arrow", "freehandStroke", "frame", "text", "code", "image", "icon"]);
|
|
11
|
+
function createEmptyScene(name = "MCP Canvas") {
|
|
12
|
+
return {
|
|
13
|
+
format: FORMAT,
|
|
14
|
+
version: VERSION,
|
|
15
|
+
sessionID: `mcp-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`,
|
|
16
|
+
name: String(name || "MCP Canvas").trim().slice(0, 72),
|
|
17
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
18
|
+
viewport: { x: 0, y: 0, width: 1280, height: 720 },
|
|
19
|
+
zoom: 1,
|
|
20
|
+
mcpRevision: 0,
|
|
21
|
+
shapes: []
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function validateScene(scene) {
|
|
25
|
+
const errors = [];
|
|
26
|
+
if (!scene || typeof scene !== "object") return { valid: false, errors: ["Scene must be an object"] };
|
|
27
|
+
if (scene.format !== FORMAT) errors.push(`Scene format must be "${FORMAT}"`);
|
|
28
|
+
if (scene.version !== VERSION) errors.push(`Scene version must be ${VERSION}`);
|
|
29
|
+
if (!Array.isArray(scene.shapes)) errors.push("Scene shapes must be an array");
|
|
30
|
+
if (Array.isArray(scene.shapes) && scene.shapes.length > MAX_SHAPES) errors.push(`Scene exceeds ${MAX_SHAPES} shapes`);
|
|
31
|
+
const ids = /* @__PURE__ */ new Set();
|
|
32
|
+
for (const [index, shape] of (scene.shapes || []).entries()) {
|
|
33
|
+
if (!shape || typeof shape !== "object") {
|
|
34
|
+
errors.push(`Shape ${index} must be an object`);
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (!SCENE_TYPES.has(shape.type)) errors.push(`Shape ${index} has unsupported type "${shape.type}"`);
|
|
38
|
+
if (!shape.shapeID || typeof shape.shapeID !== "string") errors.push(`Shape ${index} is missing shapeID`);
|
|
39
|
+
else if (ids.has(shape.shapeID)) errors.push(`Duplicate shapeID "${shape.shapeID}"`);
|
|
40
|
+
else ids.add(shape.shapeID);
|
|
41
|
+
validateShapeGeometry(shape, index, errors);
|
|
42
|
+
}
|
|
43
|
+
return { valid: errors.length === 0, errors };
|
|
44
|
+
}
|
|
45
|
+
function validateShapeGeometry(shape, index, errors) {
|
|
46
|
+
const numbers = [];
|
|
47
|
+
if (["rectangle", "frame", "text", "code", "image", "icon"].includes(shape.type)) numbers.push(["x", shape.x], ["y", shape.y]);
|
|
48
|
+
if (["rectangle", "frame", "image", "icon"].includes(shape.type)) numbers.push(["width", shape.width], ["height", shape.height]);
|
|
49
|
+
if (shape.type === "circle") numbers.push(["x", shape.x], ["y", shape.y], ["rx", shape.rx], ["ry", shape.ry]);
|
|
50
|
+
if (shape.startPoint) numbers.push(["startPoint.x", shape.startPoint.x], ["startPoint.y", shape.startPoint.y]);
|
|
51
|
+
if (shape.endPoint) numbers.push(["endPoint.x", shape.endPoint.x], ["endPoint.y", shape.endPoint.y]);
|
|
52
|
+
for (const [field, value] of numbers) if (!Number.isFinite(Number(value))) errors.push(`Shape ${index} has invalid ${field}`);
|
|
53
|
+
if (["rectangle", "frame", "image", "icon"].includes(shape.type) && (Number(shape.width) <= 0 || Number(shape.height) <= 0)) errors.push(`Shape ${index} must have positive dimensions`);
|
|
54
|
+
if (shape.type === "circle" && (Number(shape.rx) <= 0 || Number(shape.ry) <= 0)) errors.push(`Shape ${index} must have positive radii`);
|
|
55
|
+
if (shape.type === "freehandStroke" && (!Array.isArray(shape.points) || shape.points.length < 2 || shape.points.length > 4096)) errors.push(`Shape ${index} has invalid freehand points`);
|
|
56
|
+
if (shape.type === "text" && typeof shape.groupHTML !== "string") errors.push(`Shape ${index} is missing text markup`);
|
|
57
|
+
if (shape.type === "code" && typeof shape.groupHTML !== "string") errors.push(`Shape ${index} is missing code markup`);
|
|
58
|
+
if (shape.type === "image" && typeof shape.href !== "string") errors.push(`Shape ${index} is missing image href`);
|
|
59
|
+
if (shape.type === "icon" && typeof shape.elementHTML !== "string") errors.push(`Shape ${index} is missing icon markup`);
|
|
60
|
+
}
|
|
61
|
+
var MCP_LIMITS = Object.freeze({ maxShapes: MAX_SHAPES, maxOperations: MAX_OPERATIONS });
|
|
62
|
+
|
|
63
|
+
// src/mcp/fileStore.js
|
|
64
|
+
var MAX_SCENE_FILE_BYTES = 20 * 1024 * 1024;
|
|
65
|
+
var FileSceneStore = class {
|
|
66
|
+
constructor(filePath) {
|
|
67
|
+
if (!filePath) throw new Error("A scene file path is required");
|
|
68
|
+
this.filePath = resolve(filePath);
|
|
69
|
+
this.writeChain = Promise.resolve();
|
|
70
|
+
}
|
|
71
|
+
async read() {
|
|
72
|
+
try {
|
|
73
|
+
const details = await stat(this.filePath);
|
|
74
|
+
if (details.size > MAX_SCENE_FILE_BYTES) {
|
|
75
|
+
throw new Error(`Scene file exceeds the ${MAX_SCENE_FILE_BYTES / 1024 / 1024} MB MCP limit`);
|
|
76
|
+
}
|
|
77
|
+
const source = await readFile(this.filePath, "utf8");
|
|
78
|
+
const scene = JSON.parse(source);
|
|
79
|
+
const validation = validateScene(scene);
|
|
80
|
+
if (!validation.valid) throw new Error(`Invalid scene file: ${validation.errors.join("; ")}`);
|
|
81
|
+
return scene;
|
|
82
|
+
} catch (error) {
|
|
83
|
+
if (error?.code !== "ENOENT") throw error;
|
|
84
|
+
const scene = createEmptyScene();
|
|
85
|
+
await this.write(scene);
|
|
86
|
+
return scene;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async write(scene) {
|
|
90
|
+
const validation = validateScene(scene);
|
|
91
|
+
if (!validation.valid) throw new Error(`Refusing to store invalid scene: ${validation.errors.join("; ")}`);
|
|
92
|
+
this.writeChain = this.writeChain.then(async () => {
|
|
93
|
+
await mkdir(dirname(this.filePath), { recursive: true });
|
|
94
|
+
const temporary = `${this.filePath}.${process.pid}.${crypto.randomUUID()}.tmp`;
|
|
95
|
+
try {
|
|
96
|
+
const serialized = `${JSON.stringify(scene, null, 2)}
|
|
97
|
+
`;
|
|
98
|
+
if (Buffer.byteLength(serialized, "utf8") > MAX_SCENE_FILE_BYTES) {
|
|
99
|
+
throw new Error(`Scene file exceeds the ${MAX_SCENE_FILE_BYTES / 1024 / 1024} MB MCP limit`);
|
|
100
|
+
}
|
|
101
|
+
const handle = await open(temporary, "wx", 384);
|
|
102
|
+
try {
|
|
103
|
+
await handle.writeFile(serialized, "utf8");
|
|
104
|
+
await handle.sync();
|
|
105
|
+
} finally {
|
|
106
|
+
await handle.close();
|
|
107
|
+
}
|
|
108
|
+
await rename(temporary, this.filePath);
|
|
109
|
+
} catch (error) {
|
|
110
|
+
await unlink(temporary).catch(() => {
|
|
111
|
+
});
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
await this.writeChain;
|
|
116
|
+
return structuredClone(scene);
|
|
117
|
+
}
|
|
118
|
+
async info() {
|
|
119
|
+
try {
|
|
120
|
+
const details = await stat(this.filePath);
|
|
121
|
+
return { path: this.filePath, sizeBytes: details.size, updatedAt: details.mtime.toISOString() };
|
|
122
|
+
} catch (error) {
|
|
123
|
+
if (error?.code === "ENOENT") return { path: this.filePath, sizeBytes: 0, updatedAt: null };
|
|
124
|
+
throw error;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// src/mcp/stdioTransport.js
|
|
130
|
+
import { createInterface } from "node:readline";
|
|
131
|
+
var MAX_MESSAGE_BYTES = 10 * 1024 * 1024;
|
|
132
|
+
function serveLixSketchStdio(server, { input = process.stdin, output = process.stdout } = {}) {
|
|
133
|
+
if (!server?.handleRequest) throw new Error("A LixSketch MCP server is required");
|
|
134
|
+
const lines = createInterface({ input, crlfDelay: Infinity, terminal: false });
|
|
135
|
+
let processing = Promise.resolve();
|
|
136
|
+
let resolveClosed;
|
|
137
|
+
const closed = new Promise((resolve2) => {
|
|
138
|
+
resolveClosed = resolve2;
|
|
139
|
+
});
|
|
140
|
+
const send = (message) => output.write(`${JSON.stringify(message)}
|
|
141
|
+
`);
|
|
142
|
+
lines.on("line", (line) => {
|
|
143
|
+
processing = processing.then(async () => {
|
|
144
|
+
if (!line.trim()) return;
|
|
145
|
+
if (Buffer.byteLength(line, "utf8") > MAX_MESSAGE_BYTES) {
|
|
146
|
+
send({ jsonrpc: "2.0", id: null, error: { code: -32600, message: "MCP request exceeds the 10 MB limit" } });
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
let request;
|
|
150
|
+
try {
|
|
151
|
+
request = JSON.parse(line);
|
|
152
|
+
} catch {
|
|
153
|
+
send({ jsonrpc: "2.0", id: null, error: { code: -32700, message: "Parse error" } });
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (request.jsonrpc !== "2.0" || typeof request.method !== "string") {
|
|
157
|
+
if (request.id !== void 0) send({ jsonrpc: "2.0", id: request.id ?? null, error: { code: -32600, message: "Invalid Request" } });
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
try {
|
|
161
|
+
const result = await server.handleRequest(request);
|
|
162
|
+
if (request.id !== void 0 && result !== void 0) send({ jsonrpc: "2.0", id: request.id, result });
|
|
163
|
+
} catch (error) {
|
|
164
|
+
if (request.id !== void 0) send({ jsonrpc: "2.0", id: request.id, error: { code: Number(error?.code) || -32603, message: error?.message || "Internal error" } });
|
|
165
|
+
}
|
|
166
|
+
}).catch((error) => {
|
|
167
|
+
process.stderr.write(`LixSketch MCP transport error: ${error?.message || error}
|
|
168
|
+
`);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
lines.once("close", () => processing.finally(resolveClosed));
|
|
172
|
+
return {
|
|
173
|
+
closed,
|
|
174
|
+
close: async () => {
|
|
175
|
+
lines.close();
|
|
176
|
+
await processing;
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
export {
|
|
181
|
+
FileSceneStore,
|
|
182
|
+
serveLixSketchStdio
|
|
183
|
+
};
|
|
184
|
+
//# sourceMappingURL=node.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/mcp/fileStore.js", "../../src/mcp/scene.js", "../../src/mcp/stdioTransport.js"],
|
|
4
|
+
"sourcesContent": ["import { mkdir, open, readFile, rename, stat, unlink } from 'node:fs/promises';\nimport { dirname, resolve } from 'node:path';\nimport { createEmptyScene, validateScene } from './scene.js';\n\nconst MAX_SCENE_FILE_BYTES = 20 * 1024 * 1024;\n\nexport class FileSceneStore {\n constructor(filePath) {\n if (!filePath) throw new Error('A scene file path is required');\n this.filePath = resolve(filePath);\n this.writeChain = Promise.resolve();\n }\n\n async read() {\n try {\n const details = await stat(this.filePath);\n if (details.size > MAX_SCENE_FILE_BYTES) {\n throw new Error(`Scene file exceeds the ${MAX_SCENE_FILE_BYTES / 1024 / 1024} MB MCP limit`);\n }\n const source = await readFile(this.filePath, 'utf8');\n const scene = JSON.parse(source);\n const validation = validateScene(scene);\n if (!validation.valid) throw new Error(`Invalid scene file: ${validation.errors.join('; ')}`);\n return scene;\n } catch (error) {\n if (error?.code !== 'ENOENT') throw error;\n const scene = createEmptyScene();\n await this.write(scene);\n return scene;\n }\n }\n\n async write(scene) {\n const validation = validateScene(scene);\n if (!validation.valid) throw new Error(`Refusing to store invalid scene: ${validation.errors.join('; ')}`);\n this.writeChain = this.writeChain.then(async () => {\n await mkdir(dirname(this.filePath), { recursive: true });\n const temporary = `${this.filePath}.${process.pid}.${crypto.randomUUID()}.tmp`;\n try {\n const serialized = `${JSON.stringify(scene, null, 2)}\\n`;\n if (Buffer.byteLength(serialized, 'utf8') > MAX_SCENE_FILE_BYTES) {\n throw new Error(`Scene file exceeds the ${MAX_SCENE_FILE_BYTES / 1024 / 1024} MB MCP limit`);\n }\n const handle = await open(temporary, 'wx', 0o600);\n try {\n await handle.writeFile(serialized, 'utf8');\n await handle.sync();\n } finally {\n await handle.close();\n }\n await rename(temporary, this.filePath);\n } catch (error) {\n await unlink(temporary).catch(() => {});\n throw error;\n }\n });\n await this.writeChain;\n return structuredClone(scene);\n }\n\n async info() {\n try {\n const details = await stat(this.filePath);\n return { path: this.filePath, sizeBytes: details.size, updatedAt: details.mtime.toISOString() };\n } catch (error) {\n if (error?.code === 'ENOENT') return { path: this.filePath, sizeBytes: 0, updatedAt: null };\n throw error;\n }\n }\n}\n", "const FORMAT = 'lixsketch';\nconst VERSION = 1;\nconst MAX_SHAPES = 5000;\nconst MAX_OPERATIONS = 500;\nconst SCENE_TYPES = new Set(['rectangle', 'circle', 'line', 'arrow', 'freehandStroke', 'frame', 'text', 'code', 'image', 'icon']);\nconst WRITABLE_TYPES = new Set(['rectangle', 'circle', 'line', 'arrow', 'freehandStroke', 'frame', 'text']);\n\nconst clone = (value) => JSON.parse(JSON.stringify(value));\nconst finite = (value, fallback = 0) => Number.isFinite(Number(value)) ? Number(value) : fallback;\nconst positive = (value, fallback = 1) => Math.max(1, finite(value, fallback));\n\nexport function createEmptyScene(name = 'MCP Canvas') {\n return {\n format: FORMAT,\n version: VERSION,\n sessionID: `mcp-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`,\n name: String(name || 'MCP Canvas').trim().slice(0, 72),\n createdAt: new Date().toISOString(),\n viewport: { x: 0, y: 0, width: 1280, height: 720 },\n zoom: 1,\n mcpRevision: 0,\n shapes: [],\n };\n}\n\nexport function validateScene(scene) {\n const errors = [];\n if (!scene || typeof scene !== 'object') return { valid: false, errors: ['Scene must be an object'] };\n if (scene.format !== FORMAT) errors.push(`Scene format must be \"${FORMAT}\"`);\n if (scene.version !== VERSION) errors.push(`Scene version must be ${VERSION}`);\n if (!Array.isArray(scene.shapes)) errors.push('Scene shapes must be an array');\n if (Array.isArray(scene.shapes) && scene.shapes.length > MAX_SHAPES) errors.push(`Scene exceeds ${MAX_SHAPES} shapes`);\n const ids = new Set();\n for (const [index, shape] of (scene.shapes || []).entries()) {\n if (!shape || typeof shape !== 'object') { errors.push(`Shape ${index} must be an object`); continue; }\n if (!SCENE_TYPES.has(shape.type)) errors.push(`Shape ${index} has unsupported type \"${shape.type}\"`);\n if (!shape.shapeID || typeof shape.shapeID !== 'string') errors.push(`Shape ${index} is missing shapeID`);\n else if (ids.has(shape.shapeID)) errors.push(`Duplicate shapeID \"${shape.shapeID}\"`);\n else ids.add(shape.shapeID);\n validateShapeGeometry(shape, index, errors);\n }\n return { valid: errors.length === 0, errors };\n}\n\nfunction escapeXml(value) {\n return String(value).replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('\"', '"').replaceAll(\"'\", ''');\n}\n\nfunction normalizeOptions(value = {}) {\n return {\n roughness: Math.max(0, Math.min(3, finite(value.roughness, 1.2))),\n stroke: typeof value.stroke === 'string' ? value.stroke : '#8b76d6',\n strokeWidth: Math.max(0.5, Math.min(20, finite(value.strokeWidth, 2))),\n fill: typeof value.fill === 'string' ? value.fill : 'transparent',\n fillStyle: typeof value.fillStyle === 'string' ? value.fillStyle : 'solid',\n opacity: Math.max(0, Math.min(1, finite(value.opacity, 1))),\n };\n}\n\nfunction createTextShape(input, shapeID) {\n const x = finite(input.x), y = finite(input.y), rotation = finite(input.rotation);\n const text = String(input.text || '').slice(0, 10000);\n const fontSize = Math.max(8, Math.min(160, finite(input.fontSize, 20)));\n const color = typeof input.color === 'string' ? input.color : '#e8e3f3';\n const family = typeof input.fontFamily === 'string' ? input.fontFamily.slice(0, 80) : 'lixFont';\n const transform = `translate(${x}, ${y})${rotation ? ` rotate(${rotation}, 0, 0)` : ''}`;\n const lines = text.split('\\n').map((line, index) => `<tspan x=\"0\" dy=\"${index === 0 ? 0 : '1.2em'}\">${escapeXml(line || ' ')}</tspan>`).join('');\n return {\n shapeID, type: 'text', x, y, rotation,\n mcpText: text, mcpFontSize: fontSize, mcpColor: color, mcpFontFamily: family,\n groupHTML: `<g id=\"${escapeXml(shapeID)}\" data-type=\"text-group\" data-x=\"${x}\" data-y=\"${y}\" transform=\"${transform}\"><text id=\"${escapeXml(shapeID)}-text\" x=\"0\" y=\"0\" fill=\"${escapeXml(color)}\" font-size=\"${fontSize}\" font-family=\"${escapeXml(family)}\" dominant-baseline=\"hanging\" white-space=\"pre\" pointer-events=\"painted\" data-type=\"text\" data-initial-size=\"${fontSize}\" data-initial-font=\"${escapeXml(family)}\" data-initial-color=\"${escapeXml(color)}\">${lines}</text></g>`,\n };\n}\n\nexport function normalizeShape(input, existingIds = new Set()) {\n if (!input || typeof input !== 'object') throw new Error('Shape must be an object');\n if (!WRITABLE_TYPES.has(input.type)) throw new Error(`Shape type \"${input.type}\" is read-only through MCP`);\n let shapeID = String(input.shapeID || `${input.type}-${crypto.randomUUID()}`).slice(0, 120);\n while (existingIds.has(shapeID)) shapeID = `${input.type}-${crypto.randomUUID()}`;\n const base = { shapeID, type: input.type, rotation: finite(input.rotation), options: normalizeOptions(input.options), groupId: input.groupId || null, parentFrame: input.parentFrame || null, docBlockIds: [] };\n switch (input.type) {\n case 'rectangle': return { ...base, x: finite(input.x), y: finite(input.y), width: positive(input.width, 160), height: positive(input.height, 90) };\n case 'circle': return { ...base, x: finite(input.x), y: finite(input.y), rx: positive(input.rx, 60), ry: positive(input.ry, 60) };\n case 'line': return { ...base, startPoint: point(input.startPoint), endPoint: point(input.endPoint, 120), isCurved: Boolean(input.isCurved), controlPoint: input.controlPoint ? point(input.controlPoint) : null };\n case 'arrow': return { ...base, startPoint: point(input.startPoint), endPoint: point(input.endPoint, 120), arrowHeadStyle: input.arrowHeadStyle || 'triangle', arrowOutlineStyle: input.arrowOutlineStyle || 'solid', arrowCurved: Boolean(input.arrowCurved), arrowCurveAmount: finite(input.arrowCurveAmount, 0.2) };\n case 'freehandStroke': {\n const points = (Array.isArray(input.points) ? input.points : []).slice(0, 4096).map((entry) => [finite(entry?.[0]), finite(entry?.[1]), finite(entry?.[2], 0.5)]);\n if (points.length < 2) throw new Error('freehandStroke requires at least two points');\n return { ...base, points };\n }\n case 'frame': return { ...base, x: finite(input.x), y: finite(input.y), width: positive(input.width, 640), height: positive(input.height, 360), frameName: String(input.frameName || 'Frame').slice(0, 80), fillStyle: input.fillStyle || 'transparent', fillColor: input.fillColor || '#1e1e28', gridSize: positive(input.gridSize, 20), containedShapeIDs: [] };\n case 'text': return { ...base, ...createTextShape(input, shapeID) };\n default: throw new Error(`Unsupported shape type \"${input.type}\"`);\n }\n}\n\nfunction point(value, fallbackX = 0) {\n return { x: finite(value?.x, fallbackX), y: finite(value?.y) };\n}\n\nfunction translateShape(shape, dx, dy) {\n const moved = clone(shape);\n if (moved.startPoint) { moved.startPoint.x += dx; moved.startPoint.y += dy; }\n if (moved.endPoint) { moved.endPoint.x += dx; moved.endPoint.y += dy; }\n if (moved.controlPoint) { moved.controlPoint.x += dx; moved.controlPoint.y += dy; }\n if (moved.controlPoint1) { moved.controlPoint1.x += dx; moved.controlPoint1.y += dy; }\n if (moved.controlPoint2) { moved.controlPoint2.x += dx; moved.controlPoint2.y += dy; }\n if (Array.isArray(moved.points)) moved.points = moved.points.map((p) => [p[0] + dx, p[1] + dy, ...p.slice(2)]);\n if (Number.isFinite(moved.x)) moved.x += dx;\n if (Number.isFinite(moved.y)) moved.y += dy;\n if (moved.type === 'text' && moved.groupHTML) {\n moved.groupHTML = moved.groupHTML\n .replace(/data-x=\"[^\"]*\"/, `data-x=\"${moved.x}\"`)\n .replace(/data-y=\"[^\"]*\"/, `data-y=\"${moved.y}\"`)\n .replace(/transform=\"translate\\([^)]*\\)/, `transform=\"translate(${moved.x}, ${moved.y})`);\n }\n if (moved.type === 'code' && moved.groupHTML) {\n moved.groupHTML = moved.groupHTML\n .replace(/data-x=\"[^\"]*\"/, `data-x=\"${moved.x}\"`)\n .replace(/data-y=\"[^\"]*\"/, `data-y=\"${moved.y}\"`)\n .replace(/transform=\"translate\\([^)]*\\)/, `transform=\"translate(${moved.x}, ${moved.y})`);\n }\n if (moved.type === 'icon' && moved.elementHTML) {\n moved.elementHTML = moved.elementHTML\n .replace(/\\bx=\"[^\"]*\"/, `x=\"${moved.x}\"`)\n .replace(/\\by=\"[^\"]*\"/, `y=\"${moved.y}\"`);\n }\n return moved;\n}\n\nexport function applyScenePatch(sceneInput, operations, { expectedRevision, dryRun = false } = {}) {\n const scene = clone(sceneInput);\n const check = validateScene(scene);\n if (!check.valid) throw new Error(`Invalid scene: ${check.errors.join('; ')}`);\n if (!Array.isArray(operations) || operations.length === 0) throw new Error('At least one operation is required');\n if (operations.length > MAX_OPERATIONS) throw new Error(`Patch exceeds ${MAX_OPERATIONS} operations`);\n const revision = Number(scene.mcpRevision || 0);\n if (expectedRevision !== undefined && Number(expectedRevision) !== revision) throw new Error(`Revision conflict: expected ${expectedRevision}, current ${revision}`);\n const changedIds = new Set();\n for (const operation of operations) {\n if (!operation || typeof operation !== 'object') throw new Error('Each operation must be an object');\n if (operation.op === 'add') {\n if (scene.shapes.length >= MAX_SHAPES) throw new Error(`Scene exceeds ${MAX_SHAPES} shapes`);\n const ids = new Set(scene.shapes.map((shape) => shape.shapeID));\n const shape = normalizeShape(operation.shape, ids);\n scene.shapes.push(shape); changedIds.add(shape.shapeID);\n } else if (operation.op === 'update') {\n const index = scene.shapes.findIndex((shape) => shape.shapeID === operation.shapeID);\n if (index < 0) throw new Error(`Shape \"${operation.shapeID}\" was not found`);\n const immutable = scene.shapes[index];\n scene.shapes[index] = applyShapeChanges(immutable, operation.changes || {}); changedIds.add(immutable.shapeID);\n } else if (operation.op === 'delete') {\n const ids = new Set(Array.isArray(operation.shapeIDs) ? operation.shapeIDs : [operation.shapeID]);\n const before = scene.shapes.length;\n scene.shapes = scene.shapes.filter((shape) => !ids.has(shape.shapeID));\n if (scene.shapes.length === before) throw new Error('No requested shapes were found');\n scene.shapes.forEach((shape) => {\n if (ids.has(shape.parentFrame)) shape.parentFrame = null;\n if (Array.isArray(shape.containedShapeIDs)) shape.containedShapeIDs = shape.containedShapeIDs.filter((id) => !ids.has(id));\n });\n ids.forEach((id) => changedIds.add(id));\n } else if (operation.op === 'translate') {\n const ids = new Set(operation.shapeIDs || []), dx = finite(operation.dx), dy = finite(operation.dy);\n if (!ids.size) throw new Error('translate requires shapeIDs');\n scene.shapes = scene.shapes.map((shape) => ids.has(shape.shapeID) ? translateShape(shape, dx, dy) : shape);\n ids.forEach((id) => changedIds.add(id));\n } else if (operation.op === 'rename_canvas') {\n scene.name = String(operation.name || '').trim().slice(0, 72) || scene.name;\n } else throw new Error(`Unsupported operation \"${operation.op}\"`);\n }\n scene.mcpRevision = revision + 1;\n scene.updatedAt = new Date().toISOString();\n const result = validateScene(scene);\n if (!result.valid) throw new Error(`Patch produced an invalid scene: ${result.errors.join('; ')}`);\n return { scene, revision: scene.mcpRevision, dryRun: Boolean(dryRun), changedShapeIDs: [...changedIds] };\n}\n\nfunction applyShapeChanges(shape, changes) {\n if (!changes || typeof changes !== 'object' || Array.isArray(changes)) throw new Error('Shape changes must be an object');\n const allowed = {\n rectangle: ['x', 'y', 'width', 'height', 'rotation', 'options', 'groupId', 'parentFrame'],\n circle: ['x', 'y', 'rx', 'ry', 'rotation', 'options', 'groupId', 'parentFrame'],\n line: ['startPoint', 'endPoint', 'controlPoint', 'isCurved', 'options', 'groupId', 'parentFrame'],\n arrow: ['startPoint', 'endPoint', 'controlPoint1', 'controlPoint2', 'arrowHeadStyle', 'arrowOutlineStyle', 'arrowCurved', 'arrowCurveAmount', 'options', 'groupId', 'parentFrame'],\n freehandStroke: ['points', 'rotation', 'options', 'groupId', 'parentFrame'],\n frame: ['x', 'y', 'width', 'height', 'rotation', 'frameName', 'fillStyle', 'fillColor', 'gridSize', 'options', 'groupId', 'parentFrame'],\n text: ['x', 'y', 'rotation', 'text', 'fontSize', 'color', 'fontFamily', 'groupId', 'parentFrame'],\n }[shape.type] || [];\n const rejected = Object.keys(changes).filter((key) => !allowed.includes(key));\n if (rejected.length) throw new Error(`Cannot update ${shape.type} fields: ${rejected.join(', ')}`);\n if (shape.type === 'text') {\n const text = changes.text ?? shape.mcpText ?? extractText(shape.groupHTML);\n return { ...shape, ...createTextShape({ x: changes.x ?? shape.x, y: changes.y ?? shape.y, rotation: changes.rotation ?? shape.rotation, text, fontSize: changes.fontSize ?? shape.mcpFontSize, color: changes.color ?? shape.mcpColor, fontFamily: changes.fontFamily ?? shape.mcpFontFamily }, shape.shapeID), groupId: changes.groupId ?? shape.groupId, parentFrame: changes.parentFrame ?? shape.parentFrame };\n }\n const copy = { ...clone(shape), ...clone(changes), shapeID: shape.shapeID, type: shape.type };\n if (changes.options) copy.options = { ...(shape.options || {}), ...normalizeOptions({ ...(shape.options || {}), ...changes.options }) };\n return copy;\n}\n\nfunction extractText(groupHTML = '') {\n return String(groupHTML).replace(/<[^>]+>/g, ' ').replace(/\\s+/g, ' ').trim();\n}\n\nfunction validateShapeGeometry(shape, index, errors) {\n const numbers = [];\n if (['rectangle', 'frame', 'text', 'code', 'image', 'icon'].includes(shape.type)) numbers.push(['x', shape.x], ['y', shape.y]);\n if (['rectangle', 'frame', 'image', 'icon'].includes(shape.type)) numbers.push(['width', shape.width], ['height', shape.height]);\n if (shape.type === 'circle') numbers.push(['x', shape.x], ['y', shape.y], ['rx', shape.rx], ['ry', shape.ry]);\n if (shape.startPoint) numbers.push(['startPoint.x', shape.startPoint.x], ['startPoint.y', shape.startPoint.y]);\n if (shape.endPoint) numbers.push(['endPoint.x', shape.endPoint.x], ['endPoint.y', shape.endPoint.y]);\n for (const [field, value] of numbers) if (!Number.isFinite(Number(value))) errors.push(`Shape ${index} has invalid ${field}`);\n if (['rectangle', 'frame', 'image', 'icon'].includes(shape.type) && (Number(shape.width) <= 0 || Number(shape.height) <= 0)) errors.push(`Shape ${index} must have positive dimensions`);\n if (shape.type === 'circle' && (Number(shape.rx) <= 0 || Number(shape.ry) <= 0)) errors.push(`Shape ${index} must have positive radii`);\n if (shape.type === 'freehandStroke' && (!Array.isArray(shape.points) || shape.points.length < 2 || shape.points.length > 4096)) errors.push(`Shape ${index} has invalid freehand points`);\n if (shape.type === 'text' && typeof shape.groupHTML !== 'string') errors.push(`Shape ${index} is missing text markup`);\n if (shape.type === 'code' && typeof shape.groupHTML !== 'string') errors.push(`Shape ${index} is missing code markup`);\n if (shape.type === 'image' && typeof shape.href !== 'string') errors.push(`Shape ${index} is missing image href`);\n if (shape.type === 'icon' && typeof shape.elementHTML !== 'string') errors.push(`Shape ${index} is missing icon markup`);\n}\n\nexport function getSceneSummary(scene) {\n const counts = {};\n for (const shape of scene.shapes || []) counts[shape.type] = (counts[shape.type] || 0) + 1;\n return { name: scene.name, format: scene.format, version: scene.version, revision: Number(scene.mcpRevision || 0), shapeCount: scene.shapes?.length || 0, counts, bounds: getSceneBounds(scene) };\n}\n\nexport function getSceneBounds(scene) {\n const boxes = (scene.shapes || []).map(shapeBounds).filter(Boolean);\n if (!boxes.length) return null;\n const minX = Math.min(...boxes.map((b) => b.x)), minY = Math.min(...boxes.map((b) => b.y));\n const maxX = Math.max(...boxes.map((b) => b.x + b.width)), maxY = Math.max(...boxes.map((b) => b.y + b.height));\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\nexport function shapeBounds(shape) {\n if (shape.type === 'circle') return { x: shape.x - shape.rx, y: shape.y - shape.ry, width: shape.rx * 2, height: shape.ry * 2 };\n if (shape.startPoint && shape.endPoint) {\n const x = Math.min(shape.startPoint.x, shape.endPoint.x), y = Math.min(shape.startPoint.y, shape.endPoint.y);\n return { x, y, width: Math.abs(shape.endPoint.x - shape.startPoint.x), height: Math.abs(shape.endPoint.y - shape.startPoint.y) };\n }\n if (Array.isArray(shape.points) && shape.points.length) {\n const xs = shape.points.map((p) => p[0]), ys = shape.points.map((p) => p[1]);\n return { x: Math.min(...xs), y: Math.min(...ys), width: Math.max(...xs) - Math.min(...xs), height: Math.max(...ys) - Math.min(...ys) };\n }\n if (shape.type === 'text') return { x: finite(shape.x), y: finite(shape.y), width: 160, height: 32 };\n return { x: finite(shape.x), y: finite(shape.y), width: positive(shape.width), height: positive(shape.height) };\n}\n\nexport function mergeTemplateScene(sceneInput, templateInput, { x, y } = {}) {\n const scene = clone(sceneInput), template = clone(templateInput);\n const validation = validateScene(template);\n if (!validation.valid) throw new Error(`Template scene is invalid: ${validation.errors.join('; ')}`);\n if (scene.shapes.length + template.shapes.length > MAX_SHAPES) throw new Error(`Imported template would exceed ${MAX_SHAPES} shapes`);\n const bounds = getSceneBounds(template) || { x: 0, y: 0 };\n const targetX = finite(x, scene.viewport?.x || 0), targetY = finite(y, scene.viewport?.y || 0);\n const dx = targetX - bounds.x, dy = targetY - bounds.y;\n const idMap = new Map(template.shapes.map((shape) => [shape.shapeID, `${shape.type}-${crypto.randomUUID()}`]));\n const imported = template.shapes.map((shape) => {\n const moved = translateShape(shape, dx, dy);\n moved.shapeID = idMap.get(shape.shapeID);\n if (moved.parentFrame) moved.parentFrame = idMap.get(moved.parentFrame) || null;\n if (Array.isArray(moved.containedShapeIDs)) moved.containedShapeIDs = moved.containedShapeIDs.map((id) => idMap.get(id)).filter(Boolean);\n if (moved.startAttachmentID) moved.startAttachmentID = idMap.get(moved.startAttachmentID) || null;\n if (moved.endAttachmentID) moved.endAttachmentID = idMap.get(moved.endAttachmentID) || null;\n if (moved.groupHTML) moved.groupHTML = moved.groupHTML.split(shape.shapeID).join(moved.shapeID);\n if (moved.elementHTML) moved.elementHTML = moved.elementHTML.split(shape.shapeID).join(moved.shapeID);\n return moved;\n });\n scene.shapes.push(...imported);\n scene.mcpRevision = Number(scene.mcpRevision || 0) + 1;\n scene.updatedAt = new Date().toISOString();\n return { scene, revision: scene.mcpRevision, importedShapeIDs: imported.map((shape) => shape.shapeID) };\n}\n\nexport const MCP_LIMITS = Object.freeze({ maxShapes: MAX_SHAPES, maxOperations: MAX_OPERATIONS });\n", "import { createInterface } from 'node:readline';\n\nconst MAX_MESSAGE_BYTES = 10 * 1024 * 1024;\n\nexport function serveLixSketchStdio(server, { input = process.stdin, output = process.stdout } = {}) {\n if (!server?.handleRequest) throw new Error('A LixSketch MCP server is required');\n const lines = createInterface({ input, crlfDelay: Infinity, terminal: false });\n let processing = Promise.resolve();\n let resolveClosed;\n const closed = new Promise((resolve) => { resolveClosed = resolve; });\n const send = (message) => output.write(`${JSON.stringify(message)}\\n`);\n\n lines.on('line', (line) => {\n processing = processing.then(async () => {\n if (!line.trim()) return;\n if (Buffer.byteLength(line, 'utf8') > MAX_MESSAGE_BYTES) {\n send({ jsonrpc: '2.0', id: null, error: { code: -32600, message: 'MCP request exceeds the 10 MB limit' } });\n return;\n }\n let request;\n try { request = JSON.parse(line); }\n catch { send({ jsonrpc: '2.0', id: null, error: { code: -32700, message: 'Parse error' } }); return; }\n if (request.jsonrpc !== '2.0' || typeof request.method !== 'string') {\n if (request.id !== undefined) send({ jsonrpc: '2.0', id: request.id ?? null, error: { code: -32600, message: 'Invalid Request' } });\n return;\n }\n try {\n const result = await server.handleRequest(request);\n if (request.id !== undefined && result !== undefined) send({ jsonrpc: '2.0', id: request.id, result });\n } catch (error) {\n if (request.id !== undefined) send({ jsonrpc: '2.0', id: request.id, error: { code: Number(error?.code) || -32603, message: error?.message || 'Internal error' } });\n }\n }).catch((error) => {\n process.stderr.write(`LixSketch MCP transport error: ${error?.message || error}\\n`);\n });\n });\n lines.once('close', () => processing.finally(resolveClosed));\n\n return {\n closed,\n close: async () => {\n lines.close();\n await processing;\n },\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["resolve"]
|
|
7
|
+
}
|