@atomixstudio/mcp 1.0.34 → 1.0.35
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 +10 -2
- package/dist/chunk-426RNS3G.js +1782 -0
- package/dist/chunk-426RNS3G.js.map +1 -0
- package/dist/figma-bridge-protocol.d.ts +4 -3
- package/dist/figma-bridge-protocol.js +1 -1
- package/dist/index.js +534 -742
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-CE6J5MJX.js +0 -49
- package/dist/chunk-CE6J5MJX.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../figma-tools/src/build-payloads.ts","../../figma-tools/src/design-catalog.ts","../../figma-tools/src/resolve-names.ts","../../figma-tools/src/design-skills.ts","../src/figma-bridge-protocol.ts"],"sourcesContent":["/**\n * Build Figma variable + paint + text + effect style payloads from design system tokens.\n * Single source for sync-to-Figma (MCP and in-plugin).\n */\n\nimport type {\n FigmaSyncDSInput,\n FigmaSyncPayloads,\n FigmaTextStylePayload,\n FigmaDropShadow,\n FigmaSyncStep,\n StoredColorsForFigmaRefs,\n FigmaColorVariable,\n} from \"./types.js\";\n\n/** Fallback prefix map for DS that don't provide _groupPrefix (e.g. legacy). Group names can be removed/renamed in DS. */\nconst LEGACY_GROUP_PREFIX: Record<string, string> = {\n background: \"bg\",\n text: \"text\",\n icon: \"icon\",\n border: \"border\",\n brand: \"brand\",\n action: \"action\",\n feedback: \"feedback\",\n};\n\nconst RESERVED_COLOR_KEYS = new Set<string>([\"customScales\", \"neutral\"]);\n\n/** Group order from stored colors: use _groupOrder when set, otherwise derive from object keys (so DS can remove/rename groups). */\nfunction getColorGroupOrder(storedColors: StoredColorsForFigmaRefs): string[] {\n if (Array.isArray(storedColors._groupOrder) && storedColors._groupOrder.length > 0) {\n return storedColors._groupOrder;\n }\n return Object.keys(storedColors).filter(\n (k) => !k.startsWith(\"_\") && !RESERVED_COLOR_KEYS.has(k) && typeof storedColors[k] === \"object\"\n );\n}\n\n/** Prefix for export key (e.g. \"bg\" for \"bg-page\"). Prefer DS _groupPrefix; else legacy map; else groupName. */\nfunction getGroupPrefix(storedColors: StoredColorsForFigmaRefs, groupName: string): string {\n const custom = (storedColors as { _groupPrefix?: Record<string, string> })._groupPrefix;\n if (custom && typeof custom[groupName] === \"string\") return custom[groupName];\n return LEGACY_GROUP_PREFIX[groupName] ?? groupName;\n}\n\n/**\n * Use exact scale name from API/DB; only capitalize first letter for Figma display. No mapping or invented names.\n */\nfunction refScaleToFigmaDisplayName(scaleFromRef: string): string {\n const s = scaleFromRef.trim();\n if (!s) return s;\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\n/**\n * Convert stored reference (e.g. \"brand.600\", \"radix.gray.50\", \"new.coral\") to Figma primitive variable name.\n * Returns null if the result is not in the primitives set (e.g. radix scale not synced as a scale).\n * Red vs redDark stay distinct: red.900 -> \"Red / 900\", redDark.900 -> \"RedDark / 900\" (schema names).\n */\nfunction referenceToFigmaPrimitiveName(\n ref: string,\n primitiveNames: Set<string>\n): string | null {\n if (!ref || typeof ref !== \"string\") return null;\n const r = ref.trim();\n // Use exact names from DB: e.g. \"Brand / 600\", \"Neutral / 50\", \"Red / 900\", \"RedDark / 900\"\n const scaleStep = /^([a-zA-Z]+)\\.(\\d+|[a-z]+)$/.exec(r);\n if (scaleStep) {\n const [, scale, step] = scaleStep;\n const scaleDisplay = refScaleToFigmaDisplayName(scale);\n const name = `${scaleDisplay} / ${step}`;\n return primitiveNames.has(name) ? name : null;\n }\n // radix.*: use family name as-is (e.g. \"Gray / 50\", \"GrayDark / 950\", \"RedDark / 800\")\n const radixMatch = /^radix\\.([a-zA-Z]+)\\.(\\d+)$/.exec(r);\n if (radixMatch) {\n const [, family, step] = radixMatch;\n const scaleName = refScaleToFigmaDisplayName(family);\n const name = `${scaleName} / ${step}`;\n return primitiveNames.has(name) ? name : null;\n }\n // new.coral, oneOff.coral -> \"One-off / coral\"\n const oneOffMatch = /^(?:new|oneOff)\\.(.+)$/.exec(r);\n if (oneOffMatch) {\n const name = `One-off / ${oneOffMatch[1]}`;\n return primitiveNames.has(name) ? name : null;\n }\n // whiteAlpha.200, blackAlpha.300\n const whiteAlpha = /^whiteAlpha\\.(.+)$/.exec(r);\n if (whiteAlpha) {\n const name = `WhiteAlpha / ${whiteAlpha[1]}`;\n return primitiveNames.has(name) ? name : null;\n }\n const blackAlpha = /^blackAlpha\\.(.+)$/.exec(r);\n if (blackAlpha) {\n const name = `BlackAlpha / ${blackAlpha[1]}`;\n return primitiveNames.has(name) ? name : null;\n }\n return null;\n}\n\n/**\n * Parse reference string to Figma scale name (e.g. \"gray.50\" -> \"Gray\", \"redDark.900\" -> \"RedDark\").\n * Uses schema scale names; dark refs stay distinct so we create both \"Red\" and \"RedDark\" primitives.\n */\nfunction referenceToScaleName(ref: string): string | null {\n if (!ref || typeof ref !== \"string\") return null;\n const r = ref.trim();\n const scaleStep = /^([a-zA-Z]+)\\.(\\d+|[a-z]+)$/.exec(r);\n if (scaleStep) return refScaleToFigmaDisplayName(scaleStep[1]);\n const radixMatch = /^radix\\.([a-zA-Z]+)\\.(\\d+)$/.exec(r);\n if (radixMatch) return refScaleToFigmaDisplayName(radixMatch[1]);\n return null;\n}\n\n/**\n * Collect scale names referenced by any semantic (so we can ensure full scale is in primitives).\n */\nexport function getReferencedScaleNames(storedColors: StoredColorsForFigmaRefs): Set<string> {\n const names = new Set<string>();\n const groupOrder = getColorGroupOrder(storedColors);\n for (const groupName of groupOrder) {\n const group = storedColors[groupName];\n if (!group || typeof group !== \"object\") continue;\n const keys = Object.keys(group).filter((k) => !k.startsWith(\"_\") && k !== \"governance\");\n for (const key of keys) {\n const value = (group as Record<string, unknown>)[key];\n if (value === undefined || typeof value !== \"object\" || value === null) continue;\n const theme = value as { light?: { reference?: string }; dark?: { reference?: string } };\n const lightScale = theme.light?.reference ? referenceToScaleName(theme.light.reference) : null;\n const darkScale = theme.dark?.reference ? referenceToScaleName(theme.dark.reference) : null;\n if (lightScale) names.add(lightScale);\n if (darkScale) names.add(darkScale);\n }\n }\n return names;\n}\n\n/**\n * Get full scale steps (step -> hex) from stored colors only. No Radix/API fallback.\n * Neutral from storedColors.neutral.steps; others from customScales (exact name match from DB).\n */\nfunction getFullScaleFromStored(\n storedColors: StoredColorsForFigmaRefs,\n scaleName: string\n): Record<string, string> | null {\n const key = scaleName.toLowerCase();\n if (key === \"neutral\" || key === \"gray\") {\n const neutral = storedColors.neutral as { steps?: Record<string, { hex?: string }> } | undefined;\n if (!neutral?.steps || typeof neutral.steps !== \"object\") return null;\n const out: Record<string, string> = {};\n for (const [step, stepValue] of Object.entries(neutral.steps)) {\n const hex = stepValue?.hex;\n if (typeof hex === \"string\" && /^#?[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$/i.test(hex)) {\n out[step] = hex.startsWith(\"#\") ? hex : `#${hex}`;\n }\n }\n return Object.keys(out).length > 0 ? out : null;\n }\n const customScales = storedColors.customScales as Array<{ name?: string; steps?: Record<string, { hex?: string }> }> | undefined;\n if (Array.isArray(customScales)) {\n const keyNorm = key.replace(/\\s+/g, \"\");\n const scale = customScales.find(\n (s) => s.name?.toLowerCase() === key || s.name?.toLowerCase().replace(/\\s+/g, \"\") === keyNorm\n );\n if (scale?.steps && typeof scale.steps === \"object\") {\n const out: Record<string, string> = {};\n for (const [step, stepValue] of Object.entries(scale.steps)) {\n const hex = stepValue?.hex;\n if (typeof hex === \"string\" && /^#?[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$/i.test(hex)) {\n out[step] = hex.startsWith(\"#\") ? hex : `#${hex}`;\n }\n }\n if (Object.keys(out).length > 0) return out;\n }\n }\n return null;\n}\n\n/**\n * Build map: export key -> { Light?, Dark? } primitive names from stored refs (exact names from DB).\n */\nfunction buildSemanticRefMap(\n storedColors: StoredColorsForFigmaRefs,\n primitiveNames: Set<string>\n): Record<string, { Light?: string; Dark?: string }> {\n const out: Record<string, { Light?: string; Dark?: string }> = {};\n const groupOrder = getColorGroupOrder(storedColors);\n for (const groupName of groupOrder) {\n const group = storedColors[groupName];\n if (!group || typeof group !== \"object\") continue;\n const prefix = getGroupPrefix(storedColors, groupName);\n const rowOrder = Array.isArray((group as { _rowOrder?: string[] })._rowOrder)\n ? (group as { _rowOrder: string[] })._rowOrder\n : undefined;\n const keys = Array.isArray(rowOrder)\n ? rowOrder\n : Object.keys(group).filter((k) => !k.startsWith(\"_\") && k !== \"governance\");\n const toKebab = prefix === \"action\" || prefix === \"brand\" || prefix === \"feedback\";\n for (const key of keys) {\n const value = (group as Record<string, unknown>)[key];\n if (value === undefined || typeof value !== \"object\" || value === null) continue;\n const theme = value as { light?: { reference?: string }; dark?: { reference?: string } };\n let cssKey: string = key === \"app\" ? \"page\" : key;\n if (toKebab) {\n cssKey = String(key).replace(/([a-z])([A-Z])/g, \"$1-$2\").toLowerCase();\n }\n const fullKey = `${prefix}-${cssKey}`;\n const lightRef = theme.light?.reference ? referenceToFigmaPrimitiveName(theme.light.reference, primitiveNames) : null;\n const darkRef = theme.dark?.reference ? referenceToFigmaPrimitiveName(theme.dark.reference, primitiveNames) : null;\n if (lightRef || darkRef) {\n out[fullKey] = {};\n if (lightRef) out[fullKey].Light = lightRef;\n if (darkRef) out[fullKey].Dark = darkRef;\n }\n }\n }\n return out;\n}\n\n/** Derive Figma variable/style name with grouping from any export key. */\nexport function figmaColorNameWithGroup(key: string): string {\n if (key.includes(\"/\")) {\n const [group, ...rest] = key.split(\"/\");\n const name = rest.join(\"/\").trim();\n if (!name) return key;\n const groupDisplay = group.charAt(0).toUpperCase() + group.slice(1).toLowerCase();\n return `${groupDisplay} / ${name}`;\n }\n const firstDash = key.indexOf(\"-\");\n if (firstDash <= 0) return key;\n const group = key.slice(0, firstDash);\n const name = key.slice(firstDash + 1);\n const groupDisplay = group.charAt(0).toUpperCase() + group.slice(1).toLowerCase();\n return `${groupDisplay} / ${name}`;\n}\n\nconst FIGMA_SHADOW_ORDER: Record<string, number> = {\n none: 0,\n xs: 1,\n sm: 2,\n md: 3,\n lg: 4,\n xl: 5,\n \"2xl\": 6,\n focus: 7,\n};\n\nfunction tokenValueToNumber(s: string): number {\n if (typeof s !== \"string\" || !s.trim()) return 0;\n const t = s.trim();\n if (t.endsWith(\"rem\")) {\n const n = parseFloat(t.replace(/rem$/, \"\"));\n return Number.isFinite(n) ? Math.round(n * 16) : 0;\n }\n if (t.endsWith(\"px\")) {\n const n = parseFloat(t.replace(/px$/, \"\"));\n return Number.isFinite(n) ? Math.round(n) : 0;\n }\n const n = parseFloat(t);\n return Number.isFinite(n) ? n : 0;\n}\n\nfunction parseBoxShadowToFigmaEffect(shadowStr: string): FigmaDropShadow | null {\n const s = shadowStr.trim();\n if (!s || s.toLowerCase() === \"none\") return null;\n const parsePx = (x: string): number => (typeof x === \"string\" ? parseFloat(x.replace(/px$/i, \"\")) : NaN);\n const colorMatch = s.match(/(rgba?\\s*\\([^)]+\\)|#[0-9A-Fa-f]{3,8})\\s*$/i);\n const colorStr = colorMatch ? colorMatch[1].trim() : undefined;\n const rest = (colorMatch ? s.slice(0, colorMatch.index) : s).trim();\n const parts = rest ? rest.split(/\\s+/) : [];\n if (parts.length < 3) return null;\n const offsetX = parsePx(parts[0]);\n const offsetY = parsePx(parts[1]);\n const blur = parsePx(parts[2]);\n let spread = 0;\n if (parts.length >= 4) spread = parsePx(parts[3]);\n let r = 0,\n g = 0,\n b = 0,\n a = 0.1;\n if (colorStr) {\n const rgbaMatch = colorStr.match(/rgba?\\s*\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*(?:,\\s*([\\d.]+)\\s*)?\\)/i);\n if (rgbaMatch) {\n r = Number(rgbaMatch[1]) / 255;\n g = Number(rgbaMatch[2]) / 255;\n b = Number(rgbaMatch[3]) / 255;\n a = rgbaMatch[4] != null ? parseFloat(rgbaMatch[4]) : 1;\n } else {\n const hexMatch = colorStr.match(/^#?([0-9A-Fa-f]{6})([0-9A-Fa-f]{2})?$/);\n if (hexMatch) {\n r = parseInt(hexMatch[1].slice(0, 2), 16) / 255;\n g = parseInt(hexMatch[1].slice(2, 4), 16) / 255;\n b = parseInt(hexMatch[1].slice(4, 6), 16) / 255;\n a = hexMatch[2] ? parseInt(hexMatch[2], 16) / 255 : 0.1;\n }\n }\n }\n if (!Number.isFinite(offsetX) || !Number.isFinite(offsetY) || !Number.isFinite(blur)) return null;\n return {\n type: \"DROP_SHADOW\",\n offset: { x: offsetX, y: offsetY },\n radius: Math.max(0, blur),\n spread: Number.isFinite(spread) ? spread : 0,\n color: { r, g, b, a },\n visible: true,\n blendMode: \"NORMAL\",\n };\n}\n\nfunction parseBoxShadowToFigmaEffects(shadowStr: string): FigmaDropShadow[] {\n const s = (shadowStr || \"\").trim();\n if (!s || s.toLowerCase() === \"none\") return [];\n const out: FigmaDropShadow[] = [];\n const segments = s.split(/\\s*,\\s*/);\n for (const seg of segments) {\n const effect = parseBoxShadowToFigmaEffect(seg.trim());\n if (effect) out.push(effect);\n }\n return out;\n}\n\nexport function colorTo8DigitHex(color: string): string | null {\n if (!color || typeof color !== \"string\") return null;\n const s = color.trim();\n const rgbaMatch = s.match(/rgba?\\s*\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*(?:,\\s*([\\d.]+)\\s*)?\\)/i);\n if (rgbaMatch) {\n const r = Math.max(0, Math.min(255, parseInt(rgbaMatch[1], 10)));\n const g = Math.max(0, Math.min(255, parseInt(rgbaMatch[2], 10)));\n const b = Math.max(0, Math.min(255, parseInt(rgbaMatch[3], 10)));\n const a = rgbaMatch[4] != null ? Math.max(0, Math.min(1, parseFloat(rgbaMatch[4]))) : 1;\n const aByte = Math.round(a * 255);\n const hex = \"#\" + [r, g, b, aByte].map((n) => n.toString(16).padStart(2, \"0\")).join(\"\").toUpperCase();\n return hex;\n }\n const hexMatch = s.match(/^#?([0-9A-Fa-f]{6})([0-9A-Fa-f]{2})?$/i);\n if (hexMatch) {\n const rgb = hexMatch[1];\n const aa = hexMatch[2] ?? \"FF\";\n return `#${rgb}${aa}`.toUpperCase();\n }\n return null;\n}\n\nfunction typesetKeyToFontFamilyRole(key: string): \"display\" | \"heading\" | \"body\" | \"mono\" {\n const prefix = (key.split(\"-\")[0] ?? key).toLowerCase();\n if (prefix === \"display\" || prefix.startsWith(\"display\")) return \"display\";\n if (prefix === \"heading\" || prefix.startsWith(\"heading\")) return \"heading\";\n if (prefix === \"mono\" || prefix.startsWith(\"mono\")) return \"mono\";\n if (prefix.startsWith(\"body\")) return \"body\";\n return \"body\";\n}\n\n/**\n * Build Figma variable + paint + text style payloads from design system data.\n * Input shape: { tokens, meta } (e.g. from ExportedTokens or sync-core DesignSystemData).\n */\nexport function buildFigmaPayloadsFromDS(data: FigmaSyncDSInput): FigmaSyncPayloads {\n const tokens = data.tokens as Record<string, unknown>;\n const colors = tokens?.colors as {\n static?: { brand?: Record<string, string> };\n modes?: { light?: Record<string, string>; dark?: Record<string, string> };\n alphaScales?: { whiteAlpha?: Record<string, string>; blackAlpha?: Record<string, string> };\n scales?: Record<string, Record<string, string>>;\n oneOffs?: Array<{ id: string; name: string; hex: string }>;\n } | undefined;\n const typography = tokens?.typography as Record<string, unknown> | undefined;\n\n const hexRe = /^#?[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$/;\n const modes: string[] = [];\n if (colors?.modes) {\n const light = colors.modes.light ?? {};\n const dark = colors.modes.dark ?? {};\n if (Object.keys(light).length > 0) modes.push(\"Light\");\n if (Object.keys(dark).length > 0 && !modes.includes(\"Dark\")) modes.push(\"Dark\");\n }\n if (modes.length === 0) modes.push(\"Light\");\n\n /** Primitives collection uses a single mode named \"Value\" (column header in Figma); Radix and semantics use full modes. */\n const primitiveModes = [\"Value\"];\n\n const dsName = data.meta?.name;\n const collectionPrefix = dsName ? `${dsName} ` : \"\";\n\n const referencedScaleNames =\n data.storedColors ? getReferencedScaleNames(data.storedColors) : new Set<string>();\n // ----- Primitives: \"[DS name] Colors Primitives\" (no scopes, variables only) -----\n const primitiveVariables: Array<{ name: string; values: Record<string, string> }> = [];\n const primitiveNames = new Set<string>();\n /** Hex (normalized 8-char) -> \"One-off / name\" for linking semantics that use one-off hex but lack ref. */\n const oneOffHexToFigmaName = new Map<string, string>();\n\n const alphaScales = colors?.alphaScales;\n if (alphaScales?.whiteAlpha && typeof alphaScales.whiteAlpha === \"object\") {\n for (const [step, value] of Object.entries(alphaScales.whiteAlpha)) {\n if (typeof value !== \"string\") continue;\n const hex = colorTo8DigitHex(value);\n if (!hex || !hexRe.test(hex)) continue;\n const figmaName = `WhiteAlpha / ${step}`;\n if (primitiveNames.has(figmaName)) continue;\n primitiveNames.add(figmaName);\n const values: Record<string, string> = {};\n for (const m of primitiveModes) values[m] = hex;\n primitiveVariables.push({ name: figmaName, values });\n }\n }\n if (alphaScales?.blackAlpha && typeof alphaScales.blackAlpha === \"object\") {\n for (const [step, value] of Object.entries(alphaScales.blackAlpha)) {\n if (typeof value !== \"string\") continue;\n const hex = colorTo8DigitHex(value);\n if (!hex || !hexRe.test(hex)) continue;\n const figmaName = `BlackAlpha / ${step}`;\n if (primitiveNames.has(figmaName)) continue;\n primitiveNames.add(figmaName);\n const values: Record<string, string> = {};\n for (const m of primitiveModes) values[m] = hex;\n primitiveVariables.push({ name: figmaName, values });\n }\n }\n // Custom scales (brand, neutral, accent, etc.) — include all steps from export\n if (colors?.scales && typeof colors.scales === \"object\") {\n for (const [scaleName, steps] of Object.entries(colors.scales)) {\n if (!steps || typeof steps !== \"object\") continue;\n let groupDisplay = scaleName.charAt(0).toUpperCase() + scaleName.slice(1);\n if (scaleName.toLowerCase() === \"neutral\" && data.storedColors) {\n const neutral = data.storedColors.neutral as { baseHueFamily?: string } | undefined;\n if (neutral?.baseHueFamily) {\n groupDisplay = refScaleToFigmaDisplayName(neutral.baseHueFamily);\n }\n }\n for (const [step, hexVal] of Object.entries(steps)) {\n if (typeof hexVal !== \"string\") continue;\n const hex = colorTo8DigitHex(hexVal) ?? (hexRe.test(hexVal) ? hexVal : null);\n if (!hex || !hexRe.test(hex)) continue;\n const figmaName = `${groupDisplay} / ${step}`;\n if (primitiveNames.has(figmaName)) continue;\n primitiveNames.add(figmaName);\n const values: Record<string, string> = {};\n for (const m of primitiveModes) values[m] = hex;\n primitiveVariables.push({ name: figmaName, values });\n }\n }\n }\n // Referenced scales: from stored data first, then getRadixScale for scales the DB refs point to\n // (e.g. refs say \"radix.grayDark.50\" — grayDark isn't in stored/customScales, so we need getRadixScale for hex data)\n const radixVariables: Array<{ name: string; values: Record<string, string> }> = [];\n const radixCollectionName = `${collectionPrefix}Colors Radix`;\n\n for (const scaleName of referencedScaleNames) {\n if (primitiveNames.has(`${scaleName} / 50`) || primitiveNames.has(`${scaleName} / 100`)) continue;\n const fromStored = data.storedColors\n ? getFullScaleFromStored(data.storedColors, scaleName)\n : null;\n const scaleData = fromStored\n ?? data.getRadixScale?.(scaleName)\n ?? data.resolvedRadixScales?.[scaleName]\n ?? null;\n if (!scaleData) continue;\n for (const [step, hexVal] of Object.entries(scaleData)) {\n const figmaName = `${scaleName} / ${step}`;\n if (primitiveNames.has(figmaName)) continue;\n const hex = colorTo8DigitHex(hexVal) ?? (hexRe.test(hexVal) ? hexVal : null);\n if (!hex || !hexRe.test(hex)) continue;\n primitiveNames.add(figmaName);\n const values: Record<string, string> = {};\n for (const m of primitiveModes) values[m] = hex;\n primitiveVariables.push({ name: figmaName, values });\n }\n }\n // One-off colors; track hex -> Figma name so semantics can alias when value matches\n if (colors?.oneOffs && Array.isArray(colors.oneOffs)) {\n for (const oneOff of colors.oneOffs) {\n if (!oneOff || typeof oneOff !== \"object\" || typeof oneOff.hex !== \"string\") continue;\n const hex = colorTo8DigitHex(oneOff.hex) ?? (hexRe.test(oneOff.hex) ? oneOff.hex : null);\n if (!hex || !hexRe.test(hex)) continue;\n const name = typeof oneOff.name === \"string\" && oneOff.name ? oneOff.name : oneOff.id ?? \"unnamed\";\n const figmaName = `One-off / ${name}`;\n if (primitiveNames.has(figmaName)) continue;\n primitiveNames.add(figmaName);\n const values: Record<string, string> = {};\n for (const m of primitiveModes) values[m] = hex;\n primitiveVariables.push({ name: figmaName, values });\n const normalizedHex = hex.replace(/^#/, \"\").toUpperCase();\n const key8 = normalizedHex.length === 6 ? normalizedHex + \"FF\" : normalizedHex;\n oneOffHexToFigmaName.set(key8, figmaName);\n }\n }\n\n // ----- Semantic -> primitive ref map (from stored colors) -----\n const semanticRefMap =\n data.storedColors && primitiveNames.size > 0\n ? buildSemanticRefMap(data.storedColors, primitiveNames)\n : {};\n\n // ----- Semantics: \"[DS name] Colors\" (with scopes; link to primitives via alias when ref available) -----\n const semanticVariables: FigmaColorVariable[] = [];\n const semanticNames = new Set<string>();\n const primitivesCollectionName = `${collectionPrefix}Colors Primitives`;\n\n if (colors?.modes) {\n const light = colors.modes.light ?? {};\n const dark = colors.modes.dark ?? {};\n const orderedKeys = [...Object.keys(light)];\n for (const k of Object.keys(dark)) {\n if (!orderedKeys.includes(k)) orderedKeys.push(k);\n }\n for (const key of orderedKeys) {\n const lightVal = light[key];\n const darkVal = dark[key];\n const lightHex =\n typeof lightVal === \"string\" ? colorTo8DigitHex(lightVal) ?? (hexRe.test(lightVal) ? lightVal : null) : null;\n if (lightHex && hexRe.test(lightHex)) {\n const figmaName = figmaColorNameWithGroup(key);\n if (semanticNames.has(figmaName)) continue;\n semanticNames.add(figmaName);\n const darkHex =\n typeof darkVal === \"string\" ? colorTo8DigitHex(darkVal) ?? (hexRe.test(darkVal) ? darkVal : null) : null;\n const refs = semanticRefMap[key];\n const values: Record<string, string> = {\n ...(modes.includes(\"Light\") && { Light: lightHex }),\n ...(modes.includes(\"Dark\") && { Dark: darkHex && hexRe.test(darkHex) ? darkHex : lightHex }),\n };\n const aliasByMode: Record<string, string> = {};\n for (const m of modes) {\n const aliasFromRef = m === \"Light\" ? refs?.Light : refs?.Dark;\n if (aliasFromRef && primitiveNames.has(aliasFromRef)) {\n aliasByMode[m] = aliasFromRef;\n continue;\n }\n const hexForMode = m === \"Light\" ? lightHex : (darkHex && hexRe.test(darkHex) ? darkHex : lightHex);\n const norm = hexForMode.replace(/^#/, \"\").toUpperCase();\n const key8 = norm.length === 6 ? norm + \"FF\" : norm;\n const oneOffAlias = oneOffHexToFigmaName.get(key8);\n if (oneOffAlias) {\n aliasByMode[m] = oneOffAlias;\n }\n }\n semanticVariables.push({\n name: figmaName,\n values,\n ...(Object.keys(aliasByMode).length > 0 ? { aliasByMode } : {}),\n });\n }\n }\n }\n if (colors?.static?.brand && typeof colors.static.brand === \"object\") {\n for (const [key, hex] of Object.entries(colors.static.brand)) {\n if (typeof hex !== \"string\" || !hexRe.test(hex)) continue;\n const figmaName = figmaColorNameWithGroup(`brand/${key}`);\n if (semanticNames.has(figmaName)) continue;\n semanticNames.add(figmaName);\n const values: Record<string, string> = {};\n for (const m of modes) values[m] = hex;\n semanticVariables.push({ name: figmaName, values });\n }\n }\n\n const colorVariableCollections: FigmaSyncPayloads[\"colorVariableCollections\"] = [];\n if (primitiveVariables.length > 0) {\n colorVariableCollections.push({\n collectionName: primitivesCollectionName,\n modes: primitiveModes,\n variables: primitiveVariables,\n applyScopes: false,\n });\n }\n if (radixVariables.length > 0) {\n colorVariableCollections.push({\n collectionName: radixCollectionName,\n modes,\n variables: radixVariables,\n applyScopes: false,\n });\n }\n if (semanticVariables.length > 0) {\n const primitiveCollections: string[] = [];\n if (primitiveVariables.length > 0) primitiveCollections.push(primitivesCollectionName);\n if (radixVariables.length > 0) primitiveCollections.push(radixCollectionName);\n colorVariableCollections.push({\n collectionName: `${collectionPrefix}Colors Semantic`,\n modes,\n variables: semanticVariables,\n applyScopes: true,\n ...(primitiveCollections.length > 1\n ? { primitiveCollectionNames: primitiveCollections }\n : primitiveCollections.length === 1\n ? { primitiveCollectionName: primitiveCollections[0] }\n : {}),\n });\n }\n\n const paintStyles: Array<{ name: string; color: string }> = [];\n\n const textStyles: FigmaTextStylePayload[] = [];\n const sizeToPx = (val: string | number, basePx = 16): number => {\n if (typeof val === \"number\") return Math.round(val);\n const s = String(val).trim();\n const pxMatch = s.match(/^([\\d.]+)\\s*px$/i);\n if (pxMatch) return Math.round(parseFloat(pxMatch[1]));\n const remMatch = s.match(/^([\\d.]+)\\s*rem$/i);\n if (remMatch) return Math.round(parseFloat(remMatch[1]) * basePx);\n const n = parseFloat(s);\n if (Number.isFinite(n)) return n <= 0 ? basePx : n < 50 ? Math.round(n * basePx) : Math.round(n);\n return basePx;\n };\n const letterSpacingToPx = (val: string | number | undefined, fontSizePx: number): number | undefined => {\n if (val === undefined || val === null) return undefined;\n if (typeof val === \"number\") return Math.round(val);\n const s = String(val).trim();\n const pxMatch = s.match(/^([-\\d.]+)\\s*px$/i);\n if (pxMatch) return Math.round(parseFloat(pxMatch[1]));\n const emMatch = s.match(/^([-\\d.]+)\\s*em$/i);\n if (emMatch) return Math.round(parseFloat(emMatch[1]) * fontSizePx);\n const n = parseFloat(s);\n return Number.isFinite(n) ? Math.round(n) : undefined;\n };\n const firstFont = (obj: unknown): string => {\n if (typeof obj === \"string\") {\n const primary = obj.split(\",\")[0].trim().replace(/^['\"]|['\"]$/g, \"\");\n return primary || \"Inter\";\n }\n if (obj && typeof obj === \"object\" && !Array.isArray(obj)) {\n const v =\n (obj as Record<string, unknown>).body ??\n (obj as Record<string, unknown>).heading ??\n (obj as Record<string, unknown>).display ??\n Object.values(obj as object)[0];\n return firstFont(v);\n }\n return \"Inter\";\n };\n const toFontFamilyString = (val: unknown): string => {\n if (typeof val === \"string\") {\n const s = val.trim().replace(/^[\"']|[\"']$/g, \"\");\n return s || \"Inter\";\n }\n return firstFont(val);\n };\n\n const fontFamilyMap = (typography?.fontFamily as Record<string, string> | undefined) ?? {};\n const defaultFontFamily = typography ? firstFont(typography.fontFamily ?? \"Inter\") : \"Inter\";\n const fontSizeMap = typography?.fontSize as Record<string, string> | undefined;\n const fontWeightMap = typography?.fontWeight as Record<string, number | string> | undefined;\n const lineHeightMap = typography?.lineHeight as Record<string, number> | undefined;\n const letterSpacingMap = typography?.letterSpacing as Record<string, string> | undefined;\n const textTransformMap = typography?.textTransform as Record<string, \"uppercase\" | \"lowercase\" | \"capitalize\" | \"none\"> | undefined;\n const textDecorationMap = typography?.textDecoration as Record<string, \"underline\" | \"none\"> | undefined;\n\n if (fontSizeMap && typeof fontSizeMap === \"object\" && Object.keys(fontSizeMap).length > 0) {\n for (const [key, sizeVal] of Object.entries(fontSizeMap)) {\n const fontSize = sizeToPx(sizeVal);\n if (fontSize <= 0) continue;\n const role = typesetKeyToFontFamilyRole(key);\n const fontFamily = toFontFamilyString(\n fontFamilyMap[role] ?? fontFamilyMap.body ?? fontFamilyMap.heading ?? fontFamilyMap.display ?? defaultFontFamily\n );\n const lh = lineHeightMap && typeof lineHeightMap === \"object\" ? lineHeightMap[key] : undefined;\n const weight = fontWeightMap && typeof fontWeightMap === \"object\" ? fontWeightMap[key] : undefined;\n const fontWeight = weight != null ? String(weight) : \"400\";\n const letterSpacingPx = letterSpacingToPx(\n letterSpacingMap && typeof letterSpacingMap === \"object\" ? letterSpacingMap[key] : undefined,\n fontSize\n );\n const textTransform = textTransformMap && typeof textTransformMap === \"object\" ? textTransformMap[key] : undefined;\n const textDecoration = textDecorationMap && typeof textDecorationMap === \"object\" ? textDecorationMap[key] : undefined;\n const namePart = key.replace(/-/g, \" / \");\n const style: FigmaTextStylePayload = {\n name: namePart.startsWith(\"Typography\") ? namePart : `Typography / ${namePart}`,\n fontFamily,\n fontWeight,\n fontSize,\n lineHeightUnit: \"PERCENT\",\n letterSpacingUnit: \"PIXELS\",\n ...(letterSpacingPx !== undefined && letterSpacingPx !== 0 ? { letterSpacingValue: letterSpacingPx } : {}),\n };\n if (lh != null && typeof lh === \"number\" && lh > 0) {\n style.lineHeightValue = lh >= 10 ? Math.round((lh / fontSize) * 100) : Math.round(lh * 100);\n } else {\n style.lineHeightValue = 150;\n }\n if (textTransform === \"uppercase\") style.textCase = \"UPPER\";\n else if (textTransform === \"lowercase\") style.textCase = \"LOWER\";\n else if (textTransform === \"capitalize\") style.textCase = \"TITLE\";\n else style.textCase = \"ORIGINAL\";\n if (textDecoration === \"underline\") style.textDecoration = \"UNDERLINE\";\n else style.textDecoration = \"NONE\";\n textStyles.push(style);\n }\n }\n const textStylesMap = typography?.textStyles as Record<\n string,\n { fontSize?: string; lineHeight?: string; fontWeight?: string }\n > | undefined;\n if (textStyles.length === 0 && textStylesMap && typeof textStylesMap === \"object\") {\n for (const [styleName, style] of Object.entries(textStylesMap)) {\n if (!style || typeof style !== \"object\") continue;\n const fontSize = sizeToPx(style.fontSize ?? \"1rem\");\n const lhStr = style.lineHeight;\n const lineHeightUnitless =\n lhStr != null ? (lhStr.endsWith(\"%\") ? parseFloat(lhStr) / 100 : sizeToPx(lhStr) / fontSize) : 1.5;\n const payload: FigmaTextStylePayload = {\n name: styleName.startsWith(\"Typography\") ? styleName : `Typography / ${styleName.replace(/\\//g, \" / \")}`,\n fontFamily: defaultFontFamily,\n fontWeight: String(style.fontWeight ?? \"400\"),\n fontSize,\n lineHeightUnit: \"PERCENT\",\n lineHeightValue: Math.round((Number.isFinite(lineHeightUnitless) ? lineHeightUnitless : 1.5) * 100),\n letterSpacingUnit: \"PIXELS\",\n textCase: \"ORIGINAL\",\n textDecoration: \"NONE\",\n };\n textStyles.push(payload);\n }\n }\n textStyles.sort((a, b) => {\n if (a.fontSize !== b.fontSize) return a.fontSize - b.fontSize;\n return (a.name || \"\").localeCompare(b.name || \"\");\n });\n\n const numberVariableCollections: Array<{\n collectionName: string;\n categoryKey: string;\n variables: Array<{ name: string; value: number }>;\n scopes: string[];\n }> = [];\n\n const spacing = tokens?.spacing as { scale?: Record<string, string> } | undefined;\n if (spacing?.scale && typeof spacing.scale === \"object\") {\n const vars: Array<{ name: string; value: number }> = [];\n for (const [key, val] of Object.entries(spacing.scale)) {\n const n = tokenValueToNumber(val);\n if (n >= 0) vars.push({ name: `Spacing / ${key}`, value: n });\n }\n vars.sort((a, b) => a.value - b.value);\n if (vars.length > 0)\n numberVariableCollections.push({\n collectionName: `${collectionPrefix}Spacing`,\n categoryKey: \"Spacing\",\n variables: vars,\n scopes: [\"GAP\"],\n });\n }\n const radius = tokens?.radius as { scale?: Record<string, string> } | undefined;\n if (radius?.scale && typeof radius.scale === \"object\") {\n const vars: Array<{ name: string; value: number }> = [];\n for (const [key, val] of Object.entries(radius.scale)) {\n const n = tokenValueToNumber(val);\n if (n >= 0) vars.push({ name: `Radius / ${key}`, value: n });\n }\n vars.sort((a, b) => a.value - b.value);\n if (vars.length > 0)\n numberVariableCollections.push({\n collectionName: `${collectionPrefix}Radius`,\n categoryKey: \"Radius\",\n variables: vars,\n scopes: [\"CORNER_RADIUS\"],\n });\n }\n const borders = tokens?.borders as { width?: Record<string, string> } | undefined;\n if (borders?.width && typeof borders.width === \"object\") {\n const vars: Array<{ name: string; value: number }> = [];\n for (const [key, val] of Object.entries(borders.width)) {\n const n = tokenValueToNumber(val);\n if (n >= 0) vars.push({ name: `Borders / ${key}`, value: n });\n }\n vars.sort((a, b) => a.value - b.value);\n if (vars.length > 0)\n numberVariableCollections.push({\n collectionName: `${collectionPrefix}Borders`,\n categoryKey: \"Borders\",\n variables: vars,\n scopes: [\"STROKE_FLOAT\"],\n });\n }\n const sizing = tokens?.sizing as { height?: Record<string, string>; icon?: Record<string, string> } | undefined;\n const sizingVariables: Array<{ name: string; value: number }> = [];\n if (sizing?.height && typeof sizing.height === \"object\") {\n for (const [key, val] of Object.entries(sizing.height)) {\n const n = tokenValueToNumber(val);\n if (n >= 0) sizingVariables.push({ name: `Height / ${key}`, value: n });\n }\n }\n if (sizing?.icon && typeof sizing.icon === \"object\") {\n for (const [key, val] of Object.entries(sizing.icon)) {\n const n = tokenValueToNumber(val);\n if (n >= 0) sizingVariables.push({ name: `Icon / ${key}`, value: n });\n }\n }\n sizingVariables.sort((a, b) => a.value - b.value);\n if (sizingVariables.length > 0) {\n numberVariableCollections.push({\n collectionName: `${collectionPrefix}Sizing`,\n categoryKey: \"Sizing\",\n variables: sizingVariables,\n scopes: [\"WIDTH_HEIGHT\"],\n });\n }\n const layout = tokens?.layout as { breakpoint?: Record<string, string> } | undefined;\n if (layout?.breakpoint && typeof layout.breakpoint === \"object\") {\n const vars: Array<{ name: string; value: number }> = [];\n for (const [key, val] of Object.entries(layout.breakpoint)) {\n const n = tokenValueToNumber(val);\n if (n >= 0) vars.push({ name: `Breakpoint / ${key}`, value: n });\n }\n vars.sort((a, b) => a.value - b.value);\n if (vars.length > 0)\n numberVariableCollections.push({\n collectionName: `${collectionPrefix}Layout`,\n categoryKey: \"Layout\",\n variables: vars,\n scopes: [\"WIDTH_HEIGHT\"],\n });\n }\n\n const effectStyles: Array<{ name: string; effects: FigmaDropShadow[] }> = [];\n const shadows = tokens?.shadows as { elevation?: Record<string, string>; focus?: string } | undefined;\n if (shadows?.elevation && typeof shadows.elevation === \"object\") {\n for (const [key, val] of Object.entries(shadows.elevation)) {\n if (typeof val !== \"string\") continue;\n const effects = parseBoxShadowToFigmaEffects(val);\n if (effects.length > 0) effectStyles.push({ name: `Shadow / ${key}`, effects });\n }\n }\n if (shadows?.focus && typeof shadows.focus === \"string\") {\n const effects = parseBoxShadowToFigmaEffects(shadows.focus);\n if (effects.length > 0) effectStyles.push({ name: \"Shadow / focus\", effects });\n }\n effectStyles.sort((a, b) => {\n const nameA = a.name.startsWith(\"Shadow / \") ? a.name.slice(9) : a.name;\n const nameB = b.name.startsWith(\"Shadow / \") ? b.name.slice(9) : b.name;\n const orderA = FIGMA_SHADOW_ORDER[nameA] ?? 100;\n const orderB = FIGMA_SHADOW_ORDER[nameB] ?? 100;\n if (orderA !== orderB) return orderA - orderB;\n return nameA.localeCompare(nameB);\n });\n\n return {\n colorVariableCollections,\n paintStyles,\n textStyles,\n numberVariableCollections,\n effectStyles,\n };\n}\n\n/**\n * Expected Figma variable/style names from DS (same naming as sync).\n * Used for readiness checks and resolveFigmaIdsForTokens.\n */\nexport function getExpectedFigmaNamesFromDS(data: FigmaSyncDSInput): {\n colorVariableNames: string[];\n paintStyleNames: string[];\n textStyleNames: string[];\n effectStyleNames: string[];\n numberVariableNames: string[];\n} {\n const payloads = buildFigmaPayloadsFromDS(data);\n const numberVariableNames = payloads.numberVariableCollections.flatMap((c) =>\n c.variables.map((v) => v.name)\n );\n const colorVariableNames = payloads.colorVariableCollections.flatMap((c) =>\n c.variables.map((v) => v.name)\n );\n return {\n colorVariableNames,\n paintStyleNames: payloads.paintStyles.map((s) => s.name),\n textStyleNames: payloads.textStyles.map((s) => s.name),\n effectStyleNames: payloads.effectStyles.map((s) => s.name),\n numberVariableNames,\n };\n}\n\n/**\n * Convert payloads to a flat list of bridge steps for the plugin.\n * Order: create_color_variables (primitives then semantics), create_paint_styles (if any), create_number_variables (per collection), create_text_styles, create_effect_styles.\n */\nexport function buildSyncSteps(payloads: FigmaSyncPayloads): FigmaSyncStep[] {\n const steps: FigmaSyncStep[] = [];\n for (const coll of payloads.colorVariableCollections) {\n if (coll.variables.length > 0) {\n steps.push({\n method: \"create_color_variables\",\n params: {\n collectionName: coll.collectionName,\n modes: coll.modes,\n variables: coll.variables,\n removeVariablesNotInPayload: true,\n applyScopes: coll.applyScopes,\n ...(coll.primitiveCollectionNames?.length\n ? { primitiveCollectionNames: coll.primitiveCollectionNames }\n : coll.primitiveCollectionName\n ? { primitiveCollectionName: coll.primitiveCollectionName }\n : {}),\n },\n });\n }\n }\n if (payloads.paintStyles.length > 0) {\n steps.push({\n method: \"create_paint_styles\",\n params: {\n styles: payloads.paintStyles,\n removePaintStylesNotInPayload: true,\n },\n });\n }\n for (const coll of payloads.numberVariableCollections) {\n steps.push({\n method: \"create_number_variables\",\n params: {\n collectionName: coll.collectionName,\n variables: coll.variables.map((v) => ({ name: v.name, value: v.value })),\n scopes: coll.scopes,\n removeVariablesNotInPayload: true,\n },\n });\n }\n if (payloads.textStyles.length > 0) {\n steps.push({\n method: \"create_text_styles\",\n params: {\n styles: payloads.textStyles,\n removeTextStylesNotInPayload: true,\n },\n });\n }\n if (payloads.effectStyles.length > 0) {\n steps.push({\n method: \"create_effect_styles\",\n params: {\n styles: payloads.effectStyles,\n removeShadowStylesNotInPayload: true,\n },\n });\n }\n return steps;\n}\n","/**\n * Shared Figma design method catalog — THE single source of truth for all bridge methods.\n * Consumed by: MCP (designInFigma tool), Design tab (design-generate prompt),\n * Figma plugin (bridge-types), and MCP bridge protocol.\n * To add/remove a bridge method, edit ONLY this file — all consumers derive from it at build time.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface FigmaMethodParam {\n name: string;\n type: \"string\" | \"number\" | \"boolean\" | \"array\" | \"object\";\n required: boolean;\n description: string;\n enum?: string[];\n}\n\nexport interface FigmaDesignMethod {\n method: string;\n category:\n | \"query\"\n | \"sync\"\n | \"create\"\n | \"component\"\n | \"layout\"\n | \"styling\"\n | \"mode\"\n | \"finalize\";\n description: string;\n params: FigmaMethodParam[];\n}\n\nexport interface PlaceholderSize {\n width: number;\n height: number;\n description: string;\n}\n\nexport interface FigmaDesignCatalog {\n methods: FigmaDesignMethod[];\n outputRules: string[];\n idResolutionRules: string[];\n compositionGuidelines: string[];\n placeholderSizes: Record<string, PlaceholderSize>;\n examples: Array<{\n prompt: string;\n reply: string;\n steps: Array<{ method: string; params: Record<string, unknown> }>;\n note?: string;\n }>;\n}\n\n// ---------------------------------------------------------------------------\n// Catalog\n// ---------------------------------------------------------------------------\n\nexport const FIGMA_DESIGN_CATALOG: FigmaDesignCatalog = {\n // ---- Methods ----------------------------------------------------------\n\n methods: [\n // Query\n {\n method: \"get_document_info\",\n category: \"query\",\n description: \"Returns basic document information (name, pages).\",\n params: [],\n },\n {\n method: \"get_selection\",\n category: \"query\",\n description: \"Returns the current selection in the Figma file.\",\n params: [],\n },\n {\n method: \"get_node_info\",\n category: \"query\",\n description: \"Returns detailed info about a specific node.\",\n params: [\n { name: \"nodeId\", type: \"string\", required: true, description: \"Figma node ID\" },\n ],\n },\n {\n method: \"get_figma_variables_and_styles\",\n category: \"query\",\n description: \"Returns all local variable collections, text styles, effect styles, and paint styles in the file.\",\n params: [],\n },\n {\n method: \"get_figma_library_variables\",\n category: \"query\",\n description: \"Returns library (team/external) variable collections available to the file.\",\n params: [],\n },\n {\n method: \"get_design_screenshot\",\n category: \"query\",\n description: \"Returns a base64 PNG screenshot of a frame.\",\n params: [\n { name: \"frameId\", type: \"string\", required: true, description: \"Frame node ID\" },\n { name: \"scale\", type: \"number\", required: false, description: \"Export scale 1-4 (default 1)\" },\n ],\n },\n {\n method: \"list_local_components\",\n category: \"query\",\n description:\n \"Lists all local components in the current file page. Returns componentId, name, and description. \" +\n \"Use the returned componentId with design_create_component_instance.\",\n params: [],\n },\n {\n method: \"get_component_catalog\",\n category: \"query\",\n description:\n \"Returns the curated design assets catalog: library components, library styles, library variables, \" +\n \"local components, local styles, and local variables. Only enabled (non-excluded) items are returned. \" +\n \"Use component keys with design_create_component_instance's componentKey param. \" +\n \"Optionally filter by name with the query param.\",\n params: [\n { name: \"query\", type: \"string\", required: false, description: \"Filter components by name (case-insensitive substring match)\" },\n ],\n },\n {\n method: \"get_component_text_layers\",\n category: \"query\",\n description:\n \"Scans a component (library or local) and returns all visible text layers inside it. \" +\n \"Returns an array of { name, characters } for each text node. Use this to discover \" +\n \"the exact text node names before calling design_create_component_instance with textOverrides. \" +\n \"Provide componentKey (library) or componentId (local) or nodeId (existing instance on canvas).\",\n params: [\n { name: \"componentKey\", type: \"string\", required: false, description: \"Library component key to scan\" },\n { name: \"componentId\", type: \"string\", required: false, description: \"Local component ID to scan\" },\n { name: \"nodeId\", type: \"string\", required: false, description: \"Existing instance or component node ID on canvas\" },\n ],\n },\n {\n method: \"get_variable_collection_modes\",\n category: \"query\",\n description: \"Returns available modes for a variable collection.\",\n params: [\n { name: \"collectionId\", type: \"string\", required: true, description: \"Variable collection ID\" },\n ],\n },\n {\n method: \"get_frame_variable_mode\",\n category: \"query\",\n description: \"Returns the current variable mode set on a frame for a collection.\",\n params: [\n { name: \"frameId\", type: \"string\", required: true, description: \"Frame node ID\" },\n { name: \"collectionId\", type: \"string\", required: true, description: \"Variable collection ID\" },\n ],\n },\n\n // Sync (token push)\n {\n method: \"create_color_variables\",\n category: \"sync\",\n description: \"Create or update a color variable collection (primitives or semantics with light/dark modes).\",\n params: [\n { name: \"collectionName\", type: \"string\", required: true, description: \"Collection name\" },\n { name: \"modes\", type: \"array\", required: true, description: \"Mode names (e.g. ['Light','Dark'])\" },\n { name: \"variables\", type: \"array\", required: true, description: \"Array of color variables\" },\n { name: \"applyScopes\", type: \"boolean\", required: false, description: \"Apply scopes to variables (true for semantics)\" },\n { name: \"primitiveCollectionName\", type: \"string\", required: false, description: \"Primitives collection for alias resolution\" },\n { name: \"primitiveCollectionNames\", type: \"array\", required: false, description: \"Multiple primitives collections for alias resolution\" },\n ],\n },\n {\n method: \"create_paint_styles\",\n category: \"sync\",\n description: \"Create or update paint styles.\",\n params: [\n { name: \"styles\", type: \"array\", required: true, description: \"Array of { name, color } paint styles\" },\n ],\n },\n {\n method: \"create_text_styles\",\n category: \"sync\",\n description: \"Create or update text styles from typography tokens.\",\n params: [\n { name: \"styles\", type: \"array\", required: true, description: \"Array of text style payloads\" },\n ],\n },\n {\n method: \"create_number_variables\",\n category: \"sync\",\n description: \"Create or update a number variable collection (spacing, radius, borders, sizing, breakpoints).\",\n params: [\n { name: \"collectionName\", type: \"string\", required: true, description: \"Collection name\" },\n { name: \"categoryKey\", type: \"string\", required: true, description: \"Token category key\" },\n { name: \"variables\", type: \"array\", required: true, description: \"Array of { name, value } number variables\" },\n { name: \"scopes\", type: \"array\", required: true, description: \"Figma variable scopes\" },\n ],\n },\n {\n method: \"create_effect_styles\",\n category: \"sync\",\n description: \"Create or update effect styles (shadows).\",\n params: [\n { name: \"styles\", type: \"array\", required: true, description: \"Array of { name, effects } effect styles\" },\n ],\n },\n {\n method: \"apply_fill_to_selection\",\n category: \"sync\",\n description: \"Apply a fill color to the current Figma selection.\",\n params: [\n { name: \"variableId\", type: \"string\", required: false, description: \"Variable ID to apply\" },\n { name: \"paintStyleId\", type: \"string\", required: false, description: \"Paint style ID to apply\" },\n ],\n },\n {\n method: \"apply_matching_styles_to_selection\",\n category: \"styling\",\n description: \"Apply matching or closest variables and styles to the current Figma selection by color distance.\",\n params: [\n { name: \"strategy\", type: \"string\", required: false, description: \"Match strategy\", enum: [\"closest\", \"variable\"] },\n { name: \"applyFills\", type: \"boolean\", required: false, description: \"Apply matching to fill colors (default true)\" },\n { name: \"applyStrokes\", type: \"boolean\", required: false, description: \"Apply matching to stroke colors (default true)\" },\n { name: \"applyTextStyles\", type: \"boolean\", required: false, description: \"Apply closest text style (default true)\" },\n { name: \"applyEffects\", type: \"boolean\", required: false, description: \"Apply closest effect style (default true)\" },\n { name: \"applyCornerRadius\", type: \"boolean\", required: false, description: \"Bind closest corner radius variable (default true)\" },\n ],\n },\n\n // Create (design)\n {\n method: \"design_create_frame\",\n category: \"create\",\n description:\n \"Creates a frame. When parentId is omitted, creates a top-level ROOT frame on the canvas with vertical auto-layout \" +\n \"(FIXED size, clipped, auto-positioned next to existing content, selected and scrolled into view). \" +\n \"When parentId is provided, creates a child frame inside that parent. \" +\n \"USE FRAMES for all containers, sections, columns, cards, buttons, inputs — \" +\n \"anything that holds children or needs auto-layout.\",\n params: [\n { name: \"parentId\", type: \"string\", required: false, description: \"Parent node name or ID. Omit to create a top-level root frame.\" },\n { name: \"name\", type: \"string\", required: false, description: \"Node name (used for ID resolution in later steps)\" },\n { name: \"width\", type: \"number\", required: false, description: \"Optional fixed width\" },\n { name: \"height\", type: \"number\", required: false, description: \"Optional fixed height\" },\n { name: \"fillVariableName\", type: \"string\", required: false, description: \"Background fill variable name\" },\n { name: \"cornerRadiusVariableName\", type: \"string\", required: false, description: \"Corner radius variable name\" },\n { name: \"cornerRadius\", type: \"number\", required: false, description: \"Corner radius literal (prefer variable when available)\" },\n ],\n },\n {\n method: \"design_create_text\",\n category: \"create\",\n description: \"Creates a text node with visible content.\",\n params: [\n { name: \"parentId\", type: \"string\", required: false, description: \"Parent node name or ID\" },\n { name: \"characters\", type: \"string\", required: true, description: 'The visible text label (e.g. \"Button\", \"Submit\"). NEVER just \"Text\".' },\n { name: \"textStyleName\", type: \"string\", required: false, description: \"Text style name from the file\" },\n { name: \"fillVariableName\", type: \"string\", required: false, description: \"Text color variable name\" },\n { name: \"name\", type: \"string\", required: false, description: \"Node name\" },\n ],\n },\n {\n method: \"design_create_rectangle\",\n category: \"create\",\n description:\n \"Creates a rectangle. Use ONLY for decorative shapes, dividers, or image placeholders — NOT for layout containers.\",\n params: [\n { name: \"parentId\", type: \"string\", required: false, description: \"Parent node name or ID\" },\n { name: \"width\", type: \"number\", required: true, description: \"Width in pixels\" },\n { name: \"height\", type: \"number\", required: true, description: \"Height in pixels\" },\n { name: \"fillVariableName\", type: \"string\", required: false, description: \"Fill variable name\" },\n { name: \"cornerRadiusVariableName\", type: \"string\", required: false, description: \"Corner radius variable name\" },\n { name: \"cornerRadius\", type: \"number\", required: false, description: \"Corner radius literal\" },\n { name: \"name\", type: \"string\", required: false, description: \"Node name\" },\n ],\n },\n {\n method: \"design_create_ellipse\",\n category: \"create\",\n description: \"Creates an ellipse shape.\",\n params: [\n { name: \"parentId\", type: \"string\", required: false, description: \"Parent node name or ID\" },\n { name: \"width\", type: \"number\", required: true, description: \"Width in pixels\" },\n { name: \"height\", type: \"number\", required: true, description: \"Height in pixels\" },\n { name: \"fillVariableName\", type: \"string\", required: false, description: \"Fill variable name\" },\n { name: \"name\", type: \"string\", required: false, description: \"Node name\" },\n ],\n },\n {\n method: \"design_create_line\",\n category: \"create\",\n description: \"Creates a line.\",\n params: [\n { name: \"parentId\", type: \"string\", required: false, description: \"Parent node name or ID\" },\n { name: \"length\", type: \"number\", required: false, description: \"Line length in pixels\" },\n { name: \"strokeVariableName\", type: \"string\", required: false, description: \"Stroke color variable name\" },\n { name: \"strokeWeight\", type: \"number\", required: false, description: \"Stroke weight in pixels\" },\n { name: \"name\", type: \"string\", required: false, description: \"Node name\" },\n ],\n },\n {\n method: \"design_create_vector\",\n category: \"create\",\n description:\n \"Creates a vector node with optional SVG path data. Use for custom icons or shapes when no library component exists.\",\n params: [\n { name: \"parentId\", type: \"string\", required: false, description: \"Parent node name or ID\" },\n { name: \"name\", type: \"string\", required: false, description: \"Node name\" },\n { name: \"vectorPaths\", type: \"array\", required: false, description: 'Array of SVG path objects: [{\"windingRule\":\"NONZERO\"|\"EVENODD\",\"data\":\"M0 0 L10 10...\"}]' },\n { name: \"width\", type: \"number\", required: false, description: \"Vector width in pixels\" },\n { name: \"height\", type: \"number\", required: false, description: \"Vector height in pixels\" },\n { name: \"fillVariableName\", type: \"string\", required: false, description: \"Fill color variable name\" },\n ],\n },\n {\n method: \"design_create_image\",\n category: \"create\",\n description: \"Creates an image node from base64 data.\",\n params: [\n { name: \"parentId\", type: \"string\", required: false, description: \"Parent node name or ID\" },\n { name: \"imageBytesBase64\", type: \"string\", required: true, description: \"Base64-encoded PNG or JPEG\" },\n { name: \"width\", type: \"number\", required: false, description: \"Width in pixels\" },\n { name: \"height\", type: \"number\", required: false, description: \"Height in pixels\" },\n { name: \"scaleMode\", type: \"string\", required: false, description: \"Image scale mode\", enum: [\"FILL\", \"FIT\", \"CROP\", \"TILE\"] },\n { name: \"name\", type: \"string\", required: false, description: \"Node name\" },\n ],\n },\n {\n method: \"design_create_frame_from_preset\",\n category: \"create\",\n description: \"Creates a frame from a device preset.\",\n params: [\n {\n name: \"preset\",\n type: \"string\",\n required: true,\n description: \"Device preset name\",\n enum: [\n \"iphone_14\", \"iphone_14_plus\", \"iphone_se\",\n \"android_360\", \"android_412\",\n \"tablet_768\",\n \"desktop_1440\", \"desktop_1920\",\n ],\n },\n { name: \"parentId\", type: \"string\", required: false, description: \"Parent node name or ID\" },\n ],\n },\n\n // Components\n {\n method: \"design_create_component_instance\",\n category: \"component\",\n description:\n \"Creates an instance of a library or local component. For library components with variants, \" +\n \"pass the componentKey (works for both component keys and component set keys). \" +\n \"Select a variant with variantKey (exact key) or variantProperties (property map like {\\\"Size\\\":\\\"sm\\\",\\\"State\\\":\\\"default\\\"}). \" +\n \"Use textOverrides to set text inside the instance (e.g. button label, input placeholder) — keys are text node names, values are the text. \" +\n \"After creation, hardcoded fills/strokes are automatically rebound to the closest matching \" +\n \"DS color variable so imported components use semantic colors. Set rebindColors to false to skip.\",\n params: [\n { name: \"parentId\", type: \"string\", required: false, description: \"Parent node name or ID\" },\n { name: \"componentKey\", type: \"string\", required: false, description: \"Library component key or component set key\" },\n { name: \"variantKey\", type: \"string\", required: false, description: \"Specific variant key (from children list) to import a particular variant instead of the default\" },\n { name: \"variantProperties\", type: \"object\", required: false, description: \"Variant properties map to select a variant by property values (e.g. {\\\"Size\\\":\\\"sm\\\",\\\"State\\\":\\\"default\\\"}). Alternative to variantKey.\" },\n { name: \"componentId\", type: \"string\", required: false, description: \"Local component ID\" },\n { name: \"name\", type: \"string\", required: false, description: \"Node name\" },\n { name: \"textOverrides\", type: \"object\", required: false, description: \"Text overrides for text nodes inside the instance. Keys are text node names, values are the replacement text (e.g. {\\\"Label\\\":\\\"Submit\\\",\\\"Placeholder\\\":\\\"Enter email\\\"}). The first text node can also be targeted with key \\\"_primary\\\".\" },\n { name: \"fillVariableId\", type: \"string\", required: false, description: \"Color variable ID to apply as the root fill (overrides automatic rebind for the instance root)\" },\n { name: \"rebindColors\", type: \"boolean\", required: false, description: \"Auto-rebind hardcoded fills/strokes to closest DS color variable (default: true)\" },\n ],\n },\n {\n method: \"design_create_component\",\n category: \"component\",\n description: \"Creates an empty master component.\",\n params: [\n { name: \"parentId\", type: \"string\", required: false, description: \"Parent node name or ID\" },\n { name: \"name\", type: \"string\", required: false, description: \"Component name\" },\n { name: \"width\", type: \"number\", required: false, description: \"Width in pixels\" },\n { name: \"height\", type: \"number\", required: false, description: \"Height in pixels\" },\n ],\n },\n {\n method: \"design_convert_to_component\",\n category: \"component\",\n description: \"Converts an existing frame to a component.\",\n params: [\n { name: \"nodeId\", type: \"string\", required: true, description: \"Frame node ID to convert\" },\n { name: \"name\", type: \"string\", required: false, description: \"Component name\" },\n ],\n },\n {\n method: \"design_combine_as_variants\",\n category: \"component\",\n description: \"Combines 2+ components into a variant set.\",\n params: [\n { name: \"parentId\", type: \"string\", required: true, description: \"Parent node name or ID\" },\n { name: \"nodeIds\", type: \"array\", required: true, description: \"Array of 2+ component node IDs\" },\n { name: \"index\", type: \"number\", required: false, description: \"Insert index\" },\n ],\n },\n\n // Layout\n {\n method: \"design_set_auto_layout\",\n category: \"layout\",\n description: \"Sets auto-layout on a frame. Use layoutWrap WRAP for horizontal layouts that wrap children to multiple rows.\",\n params: [\n { name: \"nodeId\", type: \"string\", required: false, description: \"Target node name or ID (defaults to last created frame)\" },\n { name: \"direction\", type: \"string\", required: true, description: \"Layout direction\", enum: [\"VERTICAL\", \"HORIZONTAL\"] },\n { name: \"layoutWrap\", type: \"string\", required: false, description: \"Only for HORIZONTAL: NO_WRAP (default) or WRAP to allow children to wrap to next row\", enum: [\"NO_WRAP\", \"WRAP\"] },\n { name: \"counterAxisSpacingVariableName\", type: \"string\", required: false, description: \"When layoutWrap WRAP: spacing between wrapped rows (variable name)\" },\n { name: \"counterAxisAlignContent\", type: \"string\", required: false, description: \"When layoutWrap WRAP: alignment of wrapped rows\", enum: [\"AUTO\", \"SPACE_BETWEEN\"] },\n { name: \"paddingVariableName\", type: \"string\", required: false, description: \"Padding variable name (all sides). Overridden by per-side params if provided.\" },\n { name: \"paddingTopVariableName\", type: \"string\", required: false, description: \"Top padding variable name (overrides paddingVariableName for top)\" },\n { name: \"paddingRightVariableName\", type: \"string\", required: false, description: \"Right padding variable name (overrides paddingVariableName for right)\" },\n { name: \"paddingBottomVariableName\", type: \"string\", required: false, description: \"Bottom padding variable name (overrides paddingVariableName for bottom)\" },\n { name: \"paddingLeftVariableName\", type: \"string\", required: false, description: \"Left padding variable name (overrides paddingVariableName for left)\" },\n { name: \"itemSpacingVariableName\", type: \"string\", required: false, description: \"Item spacing variable name\" },\n { name: \"primaryAxisAlignItems\", type: \"string\", required: false, description: \"Primary axis alignment\", enum: [\"MIN\", \"CENTER\", \"MAX\", \"SPACE_BETWEEN\"] },\n { name: \"counterAxisAlignItems\", type: \"string\", required: false, description: \"Counter axis alignment\", enum: [\"MIN\", \"CENTER\", \"MAX\", \"BASELINE\"] },\n { name: \"layoutSizingHorizontal\", type: \"string\", required: false, description: \"Horizontal sizing\", enum: [\"HUG\", \"FILL\"] },\n { name: \"layoutSizingVertical\", type: \"string\", required: false, description: \"Vertical sizing\", enum: [\"HUG\", \"FILL\"] },\n ],\n },\n {\n method: \"design_set_layout_sizing\",\n category: \"layout\",\n description: \"Sets sizing behavior and optional per-child alignment override on a node within auto-layout.\",\n params: [\n { name: \"nodeId\", type: \"string\", required: false, description: \"Target node name or ID\" },\n { name: \"layoutSizingHorizontal\", type: \"string\", required: false, description: \"Horizontal sizing\", enum: [\"FIXED\", \"HUG\", \"FILL\"] },\n { name: \"layoutSizingVertical\", type: \"string\", required: false, description: \"Vertical sizing\", enum: [\"FIXED\", \"HUG\", \"FILL\"] },\n { name: \"layoutAlign\", type: \"string\", required: false, description: \"Whether this child stretches on the counter axis. Use STRETCH to fill; INHERIT (default) to not stretch. Counter-axis alignment is set on the parent via counterAxisAlignItems.\", enum: [\"STRETCH\", \"INHERIT\"] },\n ],\n },\n {\n method: \"design_set_layout_constraints\",\n category: \"layout\",\n description: \"Sets min/max width/height constraints on a node. Use variable names for token-bound values, or raw numbers as fallback.\",\n params: [\n { name: \"nodeId\", type: \"string\", required: true, description: \"Target node name or ID\" },\n { name: \"minWidthVariableName\", type: \"string\", required: false, description: \"Min width variable name\" },\n { name: \"maxWidthVariableName\", type: \"string\", required: false, description: \"Max width variable name\" },\n { name: \"minHeightVariableName\", type: \"string\", required: false, description: \"Min height variable name\" },\n { name: \"maxHeightVariableName\", type: \"string\", required: false, description: \"Max height variable name\" },\n { name: \"minWidth\", type: \"number\", required: false, description: \"Min width in pixels (fallback if no variable)\" },\n { name: \"maxWidth\", type: \"number\", required: false, description: \"Max width in pixels (fallback if no variable)\" },\n { name: \"minHeight\", type: \"number\", required: false, description: \"Min height in pixels (fallback if no variable)\" },\n { name: \"maxHeight\", type: \"number\", required: false, description: \"Max height in pixels (fallback if no variable)\" },\n ],\n },\n {\n method: \"design_set_resize_constraints\",\n category: \"layout\",\n description:\n \"Sets resize constraints (how the node responds to parent resize). Use for absolutely positioned/floating elements so they float correctly on resize. Horizontal: MIN=Left, CENTER=Center, MAX=Right, STRETCH=Left+Right (pin both, width stretches), SCALE=scale with parent. Vertical: MIN=Top, CENTER=Center, MAX=Bottom, STRETCH=Top+Bottom, SCALE=scale.\",\n params: [\n { name: \"nodeId\", type: \"string\", required: true, description: \"Target node name or ID\" },\n { name: \"constraintsHorizontal\", type: \"string\", required: false, description: \"Horizontal: MIN (left), CENTER, MAX (right), STRETCH (left+right), SCALE\", enum: [\"MIN\", \"MAX\", \"CENTER\", \"STRETCH\", \"SCALE\"] },\n { name: \"constraintsVertical\", type: \"string\", required: false, description: \"Vertical: MIN (top), CENTER, MAX (bottom), STRETCH (top+bottom), SCALE\", enum: [\"MIN\", \"MAX\", \"CENTER\", \"STRETCH\", \"SCALE\"] },\n ],\n },\n {\n method: \"design_set_node_position\",\n category: \"layout\",\n description:\n \"Sets x/y position of a node. For floating elements inside an auto-layout frame (badges, FABs, overlays), set absolute: true so the node ignores auto-layout and is positioned by x/y; then use design_set_resize_constraints so it floats correctly on parent resize.\",\n params: [\n { name: \"nodeId\", type: \"string\", required: true, description: \"Target node name or ID\" },\n { name: \"x\", type: \"number\", required: true, description: \"X position\" },\n { name: \"y\", type: \"number\", required: true, description: \"Y position\" },\n { name: \"absolute\", type: \"boolean\", required: false, description: \"If true, set layoutPositioning to ABSOLUTE so the node is taken out of auto-layout flow (use for floating UI elements)\" },\n ],\n },\n {\n method: \"design_resize_node\",\n category: \"layout\",\n description: \"Resizes a node and optionally updates corner radius.\",\n params: [\n { name: \"nodeId\", type: \"string\", required: false, description: \"Target node name or ID\" },\n { name: \"width\", type: \"number\", required: false, description: \"New width\" },\n { name: \"height\", type: \"number\", required: false, description: \"New height\" },\n { name: \"cornerRadiusVariableName\", type: \"string\", required: false, description: \"Corner radius variable name\" },\n { name: \"cornerRadius\", type: \"number\", required: false, description: \"Corner radius literal\" },\n ],\n },\n {\n method: \"design_append_child\",\n category: \"layout\",\n description: \"Reparents a node into a new parent.\",\n params: [\n { name: \"parentId\", type: \"string\", required: true, description: \"New parent node name or ID\" },\n { name: \"childId\", type: \"string\", required: true, description: \"Child node name or ID to reparent\" },\n ],\n },\n {\n method: \"design_group_nodes\",\n category: \"layout\",\n description: \"Groups multiple nodes together.\",\n params: [\n { name: \"parentId\", type: \"string\", required: true, description: \"Parent node name or ID\" },\n { name: \"nodeIds\", type: \"array\", required: true, description: \"Array of node names or IDs to group\" },\n ],\n },\n\n // Styling\n {\n method: \"design_set_effects\",\n category: \"styling\",\n description: \"Applies an effect style to a node.\",\n params: [\n { name: \"nodeId\", type: \"string\", required: true, description: \"Target node name or ID\" },\n { name: \"effectStyleName\", type: \"string\", required: true, description: \"Effect style name from the file\" },\n ],\n },\n {\n method: \"design_set_strokes\",\n category: \"styling\",\n description:\n \"Sets stroke color, weight, and alignment on a node. Supports uniform weight or per-side weights (top/right/bottom/left).\",\n params: [\n { name: \"nodeId\", type: \"string\", required: true, description: \"Target node name or ID\" },\n { name: \"strokeVariableName\", type: \"string\", required: true, description: \"Stroke color variable name\" },\n { name: \"strokeWeight\", type: \"number\", required: false, description: \"Uniform stroke weight in pixels (overridden by per-side values)\" },\n { name: \"strokeWeightVariableName\", type: \"string\", required: false, description: \"Stroke weight variable name\" },\n { name: \"strokeAlign\", type: \"string\", required: false, description: \"Stroke alignment\", enum: [\"INSIDE\", \"OUTSIDE\", \"CENTER\"] },\n { name: \"strokeTopWeight\", type: \"number\", required: false, description: \"Top stroke weight (enables individual strokes)\" },\n { name: \"strokeRightWeight\", type: \"number\", required: false, description: \"Right stroke weight\" },\n { name: \"strokeBottomWeight\", type: \"number\", required: false, description: \"Bottom stroke weight\" },\n { name: \"strokeLeftWeight\", type: \"number\", required: false, description: \"Left stroke weight\" },\n ],\n },\n {\n method: \"design_set_text_properties\",\n category: \"styling\",\n description: \"Sets text alignment, truncation, max lines, and auto-sizing mode on a text node.\",\n params: [\n { name: \"nodeId\", type: \"string\", required: true, description: \"Target text node name or ID\" },\n { name: \"textAlignHorizontal\", type: \"string\", required: false, description: \"Horizontal alignment\", enum: [\"LEFT\", \"CENTER\", \"RIGHT\", \"JUSTIFIED\"] },\n { name: \"textAlignVertical\", type: \"string\", required: false, description: \"Vertical alignment\", enum: [\"TOP\", \"CENTER\", \"BOTTOM\"] },\n { name: \"textAutoResize\", type: \"string\", required: false, description: \"Text auto-sizing mode: WIDTH_AND_HEIGHT (auto width), HEIGHT (fixed width, auto height), NONE (fixed size), TRUNCATE (fixed + clip)\", enum: [\"NONE\", \"WIDTH_AND_HEIGHT\", \"HEIGHT\", \"TRUNCATE\"] },\n { name: \"textTruncation\", type: \"string\", required: false, description: \"Truncation mode\", enum: [\"DISABLED\", \"ENDING\"] },\n { name: \"maxLines\", type: \"number\", required: false, description: \"Max lines before truncation\" },\n ],\n },\n\n // Mode\n {\n method: \"design_set_frame_variable_mode\",\n category: \"mode\",\n description: \"Sets light/dark mode override on a frame. The root frame defaults to Light automatically — child frames inherit from root (AUTO). Only use this to switch the root frame's mode or to override a specific non-root parent frame.\",\n params: [\n { name: \"frameId\", type: \"string\", required: true, description: \"Frame node ID\" },\n { name: \"collectionId\", type: \"string\", required: true, description: \"Variable collection ID\" },\n { name: \"modeId\", type: \"string\", required: true, description: \"Mode ID\" },\n ],\n },\n\n // Finalize\n {\n method: \"finalize_design_frame\",\n category: \"finalize\",\n description: \"Renames the root frame and optionally sets its background fill. Should be the last step.\",\n params: [\n { name: \"frameId\", type: \"string\", required: false, description: \"Frame ID (auto-targets root frame if omitted)\" },\n { name: \"name\", type: \"string\", required: true, description: \"Final descriptive name for the frame\" },\n { name: \"fillVariableName\", type: \"string\", required: false, description: \"Background fill variable name\" },\n ],\n },\n ],\n\n // ---- Output rules (AI instructions, not mandatory for all callers) ------\n\n outputRules: [\n \"If the user is asking a question and NOT requesting UI on canvas, answer with a helpful reply and output steps: [].\",\n \"For multi-element designs, the first step should be design_create_frame with NO parentId and width/height from standard sizes. This creates the root frame.\",\n \"The root frame IS the design canvas. Add sections/columns/children directly to it — do NOT create a wrapper frame inside.\",\n \"Last step is ALWAYS finalize_design_frame with a descriptive name and optional fillVariableName for the root background.\",\n \"Every design_create_text MUST include actual characters content, NEVER just \\\"Text\\\".\",\n \"Every design_create_frame for a visible component MUST include fillVariableName for its background.\",\n \"Every frame with children MUST have design_set_auto_layout applied.\",\n \"parentId must be a frame or group, NEVER a component instance. When using design_create_component_instance, create a wrapper frame first, add the instance to it, then use the wrapper frame as parentId for text or other children.\",\n \"When using design_create_component_instance for UI components (buttons, inputs, cards, alerts), ALWAYS pass textOverrides to set the visible text INSIDE the component. Do NOT create separate design_create_text steps for text that belongs inside a component — use textOverrides instead.\",\n \"Use design_set_layout_sizing with layoutSizingHorizontal:\\\"FILL\\\" on section/column frames (direct children of root) so they stretch to fill root width. Plugin auto-applies FILL width for 2nd-level children.\",\n \"Use EXACT variable/style names from the file context — do not invent names.\",\n \"All params MUST be included in each step — method names alone are useless without their params.\",\n ],\n\n // ---- ID resolution rules -----------------------------------------------\n\n idResolutionRules: [\n \"After the first design_create_frame (root frame, no parentId), any create step missing parentId defaults to the root frame.\",\n 'Use the \"name\" param from a previous create step as parentId/nodeId to reference that node. Example: if you create a frame with name:\"Card\", then parentId:\"Card\" in a later step targets that frame.',\n \"For design_set_auto_layout/design_resize_node/design_set_layout_sizing: use nodeId:\\\"FrameName\\\" to target a named frame. If nodeId is omitted, it targets the last created frame (or the root).\",\n \"finalize_design_frame auto-targets the root frame if frameId is omitted.\",\n ],\n\n // ---- Composition guidelines --------------------------------------------\n\n compositionGuidelines: [\n // --- Sizing hierarchy (enforced by plugin, but model should follow) ---\n \"SIZING HIERARCHY (critical):\",\n \" Level 1 — Root frame: width is ALWAYS FIXED (never FILL/HUG). Height is HUG for pages/screens (>=500px) so content grows, FIXED for small components (<500px like navbars, cards).\",\n \" Level 2 — Sections/columns (direct children of root): ALWAYS layoutSizingHorizontal FILL so they stretch to root width. The plugin auto-applies FILL width, but you should still call design_set_layout_sizing for clarity.\",\n \" Level 3 — Content frames (cards, rows, inputs, buttons): FILL width to stretch within their section, or HUG for inline elements (badges, icons). Use design_set_layout_sizing explicitly.\",\n \" Text nodes: FILL width + textAutoResize HEIGHT for body/paragraph text (auto-applied by plugin). HUG for short labels.\",\n // --- General composition ---\n \"The root frame already has VERTICAL auto-layout. Add sections directly as children.\",\n \"Use design_create_frame for all containers (sections, columns, cards, inputs, buttons). Rectangles do NOT support children.\",\n \"For a 2-column layout: create left + right column frames directly in the root frame, set layout_sizing FILL on columns, change root auto-layout to HORIZONTAL.\",\n \"For a page with sections: create section frames directly in the root frame, set layout_sizing FILL on each section.\",\n \"For a card: root frame (small size) with card frame (fill + radius) as direct child, children inside card, auto-layout card VERTICAL, finalize.\",\n \"When a card or row uses an icon/component: create a wrapper frame (e.g. name:\\\"Card\\\"), add design_create_component_instance as child of that frame, then add text/other children with parentId:\\\"Card\\\" — never use the instance name as parentId.\",\n \"For grouped elements (button = frame + text, input = frame + text): create inner frames with their own auto-layout.\",\n \"Apply auto-layout to INNER frames first, then OUTER frames (bottom-up order).\",\n \"For text that should wrap (body, paragraph, card/feed content): ensure the text's parent frame has auto-layout, then use design_set_layout_sizing on the text node with layoutSizingHorizontal FILL and design_set_text_properties with textAutoResize HEIGHT so text wraps to the frame width.\",\n \"For horizontal layouts that should wrap children to multiple rows (e.g. tag lists, card grids): use design_set_auto_layout with direction HORIZONTAL and layoutWrap WRAP; optionally set counterAxisSpacingVariableName and counterAxisAlignContent (AUTO or SPACE_BETWEEN).\",\n \"Floating elements (badge, FAB, overlay, close button): create the node as child of the relevant frame, then design_set_node_position with absolute: true and x, y; then design_set_resize_constraints (e.g. STRETCH+MAX for a bottom bar that stretches width and sticks to bottom).\",\n ],\n\n // ---- Placeholder sizes -------------------------------------------------\n\n placeholderSizes: {\n desktop: { width: 1440, height: 900, description: '\"desktop\" / \"page\" / \"landing\" / \"dashboard\" / \"screen\"' },\n mobile: { width: 390, height: 844, description: '\"mobile\" / \"phone\" / \"app\"' },\n tablet: { width: 768, height: 1024, description: '\"tablet\" / \"iPad\"' },\n card: { width: 400, height: 500, description: '\"card\" / \"dialog\" / \"modal\"' },\n sidebar: { width: 320, height: 600, description: '\"sidebar\"' },\n navbar: { width: 1440, height: 64, description: '\"navbar\" / \"header\"' },\n component: { width: 400, height: 200, description: '\"button\" / \"input\" / \"badge\" / small component' },\n },\n\n // ---- Examples ----------------------------------------------------------\n\n examples: [\n {\n prompt: \"Create a primary button\",\n reply: \"Primary button with `Action / primary` fill.\",\n steps: [\n { method: \"design_create_frame\", params: { width: 400, height: 200 } },\n { method: \"design_create_frame\", params: { name: \"Button\", fillVariableName: \"Action / primary\", cornerRadiusVariableName: \"Radius / md\" } },\n { method: \"design_create_text\", params: { parentId: \"Button\", characters: \"Button\", textStyleName: \"bodySm\", fillVariableName: \"Action / primary-foreground\" } },\n { method: \"design_set_auto_layout\", params: { nodeId: \"Button\", direction: \"HORIZONTAL\", paddingVariableName: \"Spacing / md\", itemSpacingVariableName: \"Spacing / sm\", primaryAxisAlignItems: \"CENTER\", counterAxisAlignItems: \"CENTER\", layoutSizingHorizontal: \"HUG\", layoutSizingVertical: \"HUG\" } },\n { method: \"finalize_design_frame\", params: { name: \"Primary Button\" } },\n ],\n },\n {\n prompt: \"Design a login screen\",\n reply: \"Desktop login screen with image column and form column.\",\n steps: [\n { method: \"design_create_frame\", params: { width: 1440, height: 900 } },\n { method: \"design_create_frame\", params: { name: \"ImageColumn\", fillVariableName: \"Surface / muted\" } },\n { method: \"design_set_layout_sizing\", params: { nodeId: \"ImageColumn\", layoutSizingHorizontal: \"FILL\", layoutSizingVertical: \"FILL\" } },\n { method: \"design_create_frame\", params: { name: \"FormColumn\", fillVariableName: \"Surface / primary\" } },\n { method: \"design_set_layout_sizing\", params: { nodeId: \"FormColumn\", layoutSizingHorizontal: \"FILL\", layoutSizingVertical: \"FILL\" } },\n { method: \"design_create_text\", params: { parentId: \"FormColumn\", characters: \"Welcome back\", textStyleName: \"heading\", fillVariableName: \"Text / primary\", name: \"Title\" } },\n { method: \"design_create_frame\", params: { parentId: \"FormColumn\", name: \"EmailInput\", fillVariableName: \"Surface / secondary\", cornerRadiusVariableName: \"Radius / md\" } },\n { method: \"design_create_text\", params: { parentId: \"EmailInput\", characters: \"Email address\", textStyleName: \"bodySm\", fillVariableName: \"Text / secondary\" } },\n { method: \"design_set_auto_layout\", params: { nodeId: \"EmailInput\", direction: \"HORIZONTAL\", paddingVariableName: \"Spacing / sm\", counterAxisAlignItems: \"CENTER\", layoutSizingHorizontal: \"FILL\", layoutSizingVertical: \"HUG\" } },\n { method: \"design_create_frame\", params: { parentId: \"FormColumn\", name: \"PasswordInput\", fillVariableName: \"Surface / secondary\", cornerRadiusVariableName: \"Radius / md\" } },\n { method: \"design_create_text\", params: { parentId: \"PasswordInput\", characters: \"Password\", textStyleName: \"bodySm\", fillVariableName: \"Text / secondary\" } },\n { method: \"design_set_auto_layout\", params: { nodeId: \"PasswordInput\", direction: \"HORIZONTAL\", paddingVariableName: \"Spacing / sm\", counterAxisAlignItems: \"CENTER\", layoutSizingHorizontal: \"FILL\", layoutSizingVertical: \"HUG\" } },\n { method: \"design_create_frame\", params: { parentId: \"FormColumn\", name: \"LoginBtn\", fillVariableName: \"Action / primary\", cornerRadiusVariableName: \"Radius / md\" } },\n { method: \"design_create_text\", params: { parentId: \"LoginBtn\", characters: \"Sign in\", textStyleName: \"bodySm\", fillVariableName: \"Action / primary-foreground\" } },\n { method: \"design_set_auto_layout\", params: { nodeId: \"LoginBtn\", direction: \"HORIZONTAL\", paddingVariableName: \"Spacing / md\", primaryAxisAlignItems: \"CENTER\", counterAxisAlignItems: \"CENTER\", layoutSizingHorizontal: \"FILL\", layoutSizingVertical: \"HUG\" } },\n { method: \"design_set_auto_layout\", params: { nodeId: \"FormColumn\", direction: \"VERTICAL\", paddingVariableName: \"Spacing / xl\", itemSpacingVariableName: \"Spacing / md\", primaryAxisAlignItems: \"CENTER\", counterAxisAlignItems: \"MIN\", layoutSizingHorizontal: \"FILL\", layoutSizingVertical: \"FILL\" } },\n { method: \"design_set_auto_layout\", params: { direction: \"HORIZONTAL\", itemSpacingVariableName: \"Spacing / none\", primaryAxisAlignItems: \"MIN\", counterAxisAlignItems: \"MIN\" } },\n { method: \"finalize_design_frame\", params: { name: \"Desktop Login Screen\", fillVariableName: \"Surface / primary\" } },\n ],\n note: \"The last design_set_auto_layout without nodeId targets the root frame (overrides its default VERTICAL layout to HORIZONTAL for the 2-column split).\",\n },\n ],\n};\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** All method names from the catalog (flat array). */\nexport function getCatalogMethodNames(): string[] {\n return FIGMA_DESIGN_CATALOG.methods.map((m) => m.method);\n}\n\n/** Only design-oriented method names (excludes query and sync categories). */\nexport function getDesignMethodNames(): string[] {\n return FIGMA_DESIGN_CATALOG.methods\n .filter((m) => m.category !== \"query\" && m.category !== \"sync\")\n .map((m) => m.method);\n}\n\n/** Query-only method names (get_selection, get_node_info, get_design_screenshot, etc.). Safe to expose for read-only MCP actions. */\nexport function getQueryMethodNames(): string[] {\n return FIGMA_DESIGN_CATALOG.methods\n .filter((m) => m.category === \"query\")\n .map((m) => m.method);\n}\n\n/**\n * Detect the intended root frame size from a user prompt.\n * Uses keyword matching against placeholderSizes descriptions.\n * Returns the matched size or desktop as fallback.\n */\nexport function detectFrameSize(userMessage: string): PlaceholderSize & { key: string } {\n const msg = userMessage.toLowerCase();\n const sizePatterns: Array<{ key: string; pattern: RegExp }> = [\n { key: \"mobile\", pattern: /\\b(mobile|phone|app|iphone|android|ios)\\b/ },\n { key: \"tablet\", pattern: /\\b(tablet|ipad)\\b/ },\n { key: \"navbar\", pattern: /\\b(navbar|nav\\s*bar|header)\\b/ },\n { key: \"sidebar\", pattern: /\\b(sidebar|side\\s*bar|side\\s*nav)\\b/ },\n { key: \"card\", pattern: /\\b(card|dialog|modal|popup|sheet|drawer)\\b/ },\n { key: \"component\", pattern: /\\b(button|input|badge|chip|tag|toggle|switch|checkbox|radio)\\b/ },\n { key: \"desktop\", pattern: /\\b(desktop|page|landing|dashboard|web|website|screen)\\b/ },\n ];\n for (const { key, pattern } of sizePatterns) {\n if (pattern.test(msg)) {\n const size = FIGMA_DESIGN_CATALOG.placeholderSizes[key];\n return { ...size, key };\n }\n }\n const fallback = FIGMA_DESIGN_CATALOG.placeholderSizes.desktop;\n return { ...fallback, key: \"desktop\" };\n}\n\n/**\n * Format the catalog for an AI system prompt (text block).\n * Produces the same format currently used in design-generate route.\n */\nexport function formatCatalogForPrompt(catalog: FigmaDesignCatalog): string {\n const lines: string[] = [];\n\n const categoryOrder: Array<FigmaDesignMethod[\"category\"]> = [\n \"create\", \"component\", \"layout\", \"styling\", \"mode\", \"finalize\",\n ];\n const categoryLabels: Record<string, string> = {\n create: \"Create\",\n component: \"Components\",\n layout: \"Layout\",\n styling: \"Styling\",\n mode: \"Mode / screenshot\",\n finalize: \"Finalize\",\n };\n\n const queryMethods = catalog.methods.filter((m) => m.category === \"query\");\n const screenshotMethod = queryMethods.find((m) => m.method === \"get_design_screenshot\");\n const collectionModesMethod = queryMethods.find((m) => m.method === \"get_variable_collection_modes\");\n const frameVarModeMethod = queryMethods.find((m) => m.method === \"get_frame_variable_mode\");\n\n lines.push(\"BRIDGE METHODS (one per step):\\n\");\n\n for (const cat of categoryOrder) {\n let methods = catalog.methods.filter((m) => m.category === cat);\n if (cat === \"mode\") {\n const extras = [screenshotMethod, collectionModesMethod, frameVarModeMethod].filter(Boolean) as FigmaDesignMethod[];\n methods = [...methods, ...extras];\n }\n if (methods.length === 0) continue;\n lines.push(`${categoryLabels[cat] ?? cat}:`);\n for (const m of methods) {\n const paramDescs = m.params\n .map((p) => {\n const req = p.required ? \" (REQUIRED)\" : \"\";\n const enumStr = p.enum ? ` (${p.enum.join(\"/\")})` : \"\";\n return `${p.name}${req}${enumStr}`;\n })\n .join(\", \");\n lines.push(`- ${m.method}: Params: ${paramDescs || \"none\"}. ${m.description}`);\n }\n lines.push(\"\");\n }\n\n lines.push(\"STANDARD SIZES — pass width and height to the first design_create_frame (root frame, no parentId) based on what user asks for:\");\n for (const [, size] of Object.entries(catalog.placeholderSizes)) {\n lines.push(`- ${size.description} → width:${size.width}, height:${size.height}`);\n }\n lines.push(\"If ambiguous, default to desktop.\\n\");\n\n lines.push('OUTPUT FORMAT — return JSON: {\"reply\":\"...\",\"steps\":[{\"method\":\"...\",\"params\":{...}}, ...]}\\n');\n\n lines.push(\"OUTPUT RULES — follow strictly:\");\n catalog.outputRules.forEach((rule, i) => {\n lines.push(`${i}. ${rule}`);\n });\n lines.push(\"\");\n\n lines.push(\"ID RESOLUTION — the system auto-wires IDs between steps:\");\n for (const rule of catalog.idResolutionRules) {\n lines.push(`- ${rule}`);\n }\n lines.push(\"\");\n\n lines.push(\"BUILDING COMPLEX UIs — nest frames inside the root frame:\");\n for (const guideline of catalog.compositionGuidelines) {\n lines.push(`- ${guideline}`);\n }\n lines.push(\"\");\n\n for (let i = 0; i < catalog.examples.length; i++) {\n const ex = catalog.examples[i];\n lines.push(`EXAMPLE ${i + 1} — ${ex.prompt}:`);\n lines.push(JSON.stringify({ reply: ex.reply, steps: ex.steps }));\n if (ex.note) lines.push(`Note: ${ex.note}`);\n lines.push(\"\");\n }\n\n lines.push(\"CRITICAL: The variable names in the examples above are illustrative. You MUST use the EXACT variable and style names listed in the \\\"Available in this Figma file\\\" section. Match the closest available name for each purpose (fill color, text style, spacing, radius).\");\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Format the catalog for MCP tool response (structured JSON).\n * Includes only design-relevant methods (excludes sync/query internals).\n */\nexport function formatCatalogForMCP(\n catalog: FigmaDesignCatalog,\n fileContext?: {\n localVariables: string[];\n libraryVariables: string[];\n textStyles: string[];\n effectStyles: string[];\n },\n): {\n methods: Array<{ method: string; category: string; description: string; params: FigmaMethodParam[] }>;\n outputRules: string[];\n idResolutionRules: string[];\n compositionGuidelines: string[];\n placeholderSizes: Record<string, PlaceholderSize>;\n examples: FigmaDesignCatalog[\"examples\"];\n fileContext?: typeof fileContext;\n} {\n const designMethods = catalog.methods.filter(\n (m) => m.category !== \"sync\",\n );\n return {\n methods: designMethods.map((m) => ({\n method: m.method,\n category: m.category,\n description: m.description,\n params: m.params,\n })),\n outputRules: catalog.outputRules,\n idResolutionRules: catalog.idResolutionRules,\n compositionGuidelines: catalog.compositionGuidelines,\n placeholderSizes: catalog.placeholderSizes,\n examples: catalog.examples,\n ...(fileContext ? { fileContext } : {}),\n };\n}\n","/**\n * Name-to-ID resolution for Figma design steps.\n * Shared between design-generate API route and MCP designInFigma tool.\n * Pure functions — no Next.js or DB dependencies.\n */\n\n// ---------------------------------------------------------------------------\n// File context shape (minimal interface matching plugin output)\n// ---------------------------------------------------------------------------\n\nexport interface FileContextPayload {\n textStyles?: Array<{ name: string; id: string }>;\n effectStyles?: Array<{ name: string; id: string }>;\n paintStyles?: Array<{ name: string; id: string }>;\n variableCollections?: Array<{\n name: string;\n id: string;\n variables: Array<{ name: string; id: string; [k: string]: unknown }>;\n [k: string]: unknown;\n }>;\n /** Library variable collections use `key` instead of `id`. */\n variableCollectionsLibrary?: Array<{\n name: string;\n key?: string;\n id?: string;\n variables: Array<{ name: string; key?: string; id?: string; [k: string]: unknown }>;\n [k: string]: unknown;\n }>;\n}\n\n// ---------------------------------------------------------------------------\n// Normalize\n// ---------------------------------------------------------------------------\n\n/** Normalize for fuzzy match: lowercase, collapse \" / \" and spaces to \"/\", trim. */\nexport function normalizeTokenName(name: string): string {\n return name\n .toLowerCase()\n .trim()\n .replace(/\\s*\\/\\s*/g, \"/\")\n .replace(/\\s+/g, \"/\")\n .replace(/\\/+/g, \"/\")\n .replace(/^\\//, \"\")\n .replace(/\\/$/, \"\");\n}\n\n// ---------------------------------------------------------------------------\n// Resolvers\n// ---------------------------------------------------------------------------\n\nexport interface NameResolvers {\n textStyleIdByName: Map<string, string>;\n textStyleIdByNormalized: Map<string, string>;\n effectStyleIdByName: Map<string, string>;\n effectStyleIdByNormalized: Map<string, string>;\n variableIdByName: Map<string, string>;\n variableIdByNormalized: Map<string, string>;\n firstTextStyleId: string | undefined;\n firstEffectStyleId: string | undefined;\n}\n\n/** Build name→id maps from fileContext for resolving step params. Includes normalized keys for fuzzy match. */\nexport function buildResolvers(fileContext: FileContextPayload): NameResolvers {\n const textStyleIdByName = new Map<string, string>();\n const textStyleIdByNormalized = new Map<string, string>();\n for (const s of fileContext.textStyles ?? []) {\n textStyleIdByName.set(s.name, s.id);\n textStyleIdByNormalized.set(normalizeTokenName(s.name), s.id);\n }\n\n const effectStyleIdByName = new Map<string, string>();\n const effectStyleIdByNormalized = new Map<string, string>();\n for (const s of fileContext.effectStyles ?? []) {\n effectStyleIdByName.set(s.name, s.id);\n effectStyleIdByNormalized.set(normalizeTokenName(s.name), s.id);\n }\n\n const variableIdByName = new Map<string, string>();\n const variableIdByNormalized = new Map<string, string>();\n for (const coll of fileContext.variableCollections ?? []) {\n for (const v of coll.variables) {\n variableIdByName.set(v.name, v.id);\n variableIdByNormalized.set(normalizeTokenName(v.name), v.id);\n }\n }\n for (const coll of fileContext.variableCollectionsLibrary ?? []) {\n for (const v of coll.variables) {\n const identifier = v.key ? `libkey:${v.key}` : v.id ?? \"\";\n if (!identifier) continue;\n if (!variableIdByName.has(v.name)) {\n variableIdByName.set(v.name, identifier);\n variableIdByNormalized.set(normalizeTokenName(v.name), identifier);\n }\n }\n }\n\n const firstTextStyleId = (fileContext.textStyles ?? [])[0]?.id;\n const firstEffectStyleId = (fileContext.effectStyles ?? [])[0]?.id;\n\n return {\n textStyleIdByName,\n textStyleIdByNormalized,\n effectStyleIdByName,\n effectStyleIdByNormalized,\n variableIdByName,\n variableIdByNormalized,\n firstTextStyleId,\n firstEffectStyleId,\n };\n}\n\n/** Exact match first, then normalized match. */\nexport function resolveByNameOrNormalized(\n name: string,\n exact: Map<string, string>,\n normalized: Map<string, string>,\n): string | undefined {\n return exact.get(name) ?? normalized.get(normalizeTokenName(name));\n}\n\n/** Try to resolve a variable name to its id: exact, normalized, then last segment after \" / \". */\nexport function resolveVariableName(\n name: string,\n variableIdByName: Map<string, string>,\n variableIdByNormalized: Map<string, string>,\n): string | undefined {\n return (\n variableIdByName.get(name) ??\n variableIdByNormalized.get(normalizeTokenName(name)) ??\n (name.includes(\" / \") ? variableIdByName.get(name.split(\" / \").slice(-1)[0]?.trim() ?? \"\") : undefined) ??\n (name.includes(\"/\") ? variableIdByNormalized.get(normalizeTokenName(name.split(\"/\").pop() ?? \"\")) : undefined)\n );\n}\n\n/**\n * Resolve step params: replace *Name keys with *Id using fileContext.\n * Uses exact + normalized match; fallbacks for text/effect when missing.\n */\nexport function resolveStepParams(\n params: Record<string, unknown>,\n resolvers: NameResolvers,\n): Record<string, unknown> {\n const out = { ...params };\n const {\n textStyleIdByName,\n textStyleIdByNormalized,\n effectStyleIdByName,\n effectStyleIdByNormalized,\n variableIdByName,\n variableIdByNormalized,\n firstTextStyleId,\n firstEffectStyleId,\n } = resolvers;\n\n if (typeof out.textStyleName === \"string\") {\n const id =\n resolveByNameOrNormalized(out.textStyleName as string, textStyleIdByName, textStyleIdByNormalized) ??\n firstTextStyleId;\n if (id) {\n out.textStyleId = id;\n delete out.textStyleName;\n }\n }\n if (typeof out.fillVariableName === \"string\") {\n const id = resolveVariableName(out.fillVariableName as string, variableIdByName, variableIdByNormalized);\n if (id) {\n out.fillVariableId = id;\n delete out.fillVariableName;\n }\n }\n if (typeof out.effectStyleName === \"string\") {\n const id =\n resolveByNameOrNormalized(out.effectStyleName as string, effectStyleIdByName, effectStyleIdByNormalized) ??\n firstEffectStyleId;\n if (id) {\n out.effectStyleId = id;\n delete out.effectStyleName;\n }\n }\n if (typeof out.strokeVariableName === \"string\") {\n const id = resolveVariableName(out.strokeVariableName as string, variableIdByName, variableIdByNormalized);\n if (id) {\n out.strokeVariableId = id;\n delete out.strokeVariableName;\n }\n }\n if (typeof out.cornerRadiusVariableName === \"string\") {\n const id = resolveVariableName(out.cornerRadiusVariableName as string, variableIdByName, variableIdByNormalized);\n if (id) {\n out.cornerRadiusVariableId = id;\n delete out.cornerRadiusVariableName;\n }\n }\n if (typeof out.strokeWeightVariableName === \"string\") {\n const id = resolveVariableName(out.strokeWeightVariableName as string, variableIdByName, variableIdByNormalized);\n if (id) {\n out.strokeWeightVariableId = id;\n delete out.strokeWeightVariableName;\n }\n }\n if (typeof out.paddingVariableName === \"string\") {\n const id = resolveVariableName(out.paddingVariableName as string, variableIdByName, variableIdByNormalized);\n if (id) {\n out.paddingVariableId = id;\n delete out.paddingVariableName;\n }\n }\n if (typeof out.paddingTopVariableName === \"string\") {\n const id = resolveVariableName(out.paddingTopVariableName as string, variableIdByName, variableIdByNormalized);\n if (id) {\n out.paddingTopVariableId = id;\n delete out.paddingTopVariableName;\n }\n }\n if (typeof out.paddingRightVariableName === \"string\") {\n const id = resolveVariableName(out.paddingRightVariableName as string, variableIdByName, variableIdByNormalized);\n if (id) {\n out.paddingRightVariableId = id;\n delete out.paddingRightVariableName;\n }\n }\n if (typeof out.paddingBottomVariableName === \"string\") {\n const id = resolveVariableName(out.paddingBottomVariableName as string, variableIdByName, variableIdByNormalized);\n if (id) {\n out.paddingBottomVariableId = id;\n delete out.paddingBottomVariableName;\n }\n }\n if (typeof out.paddingLeftVariableName === \"string\") {\n const id = resolveVariableName(out.paddingLeftVariableName as string, variableIdByName, variableIdByNormalized);\n if (id) {\n out.paddingLeftVariableId = id;\n delete out.paddingLeftVariableName;\n }\n }\n if (typeof out.itemSpacingVariableName === \"string\") {\n const id = resolveVariableName(out.itemSpacingVariableName as string, variableIdByName, variableIdByNormalized);\n if (id) {\n out.itemSpacingVariableId = id;\n delete out.itemSpacingVariableName;\n }\n }\n if (typeof out.counterAxisSpacingVariableName === \"string\") {\n const id = resolveVariableName(out.counterAxisSpacingVariableName as string, variableIdByName, variableIdByNormalized);\n if (id) {\n out.counterAxisSpacingVariableId = id;\n delete out.counterAxisSpacingVariableName;\n }\n }\n if (typeof out.minWidthVariableName === \"string\") {\n const id = resolveVariableName(out.minWidthVariableName as string, variableIdByName, variableIdByNormalized);\n if (id) {\n out.minWidthVariableId = id;\n delete out.minWidthVariableName;\n }\n }\n if (typeof out.maxWidthVariableName === \"string\") {\n const id = resolveVariableName(out.maxWidthVariableName as string, variableIdByName, variableIdByNormalized);\n if (id) {\n out.maxWidthVariableId = id;\n delete out.maxWidthVariableName;\n }\n }\n if (typeof out.minHeightVariableName === \"string\") {\n const id = resolveVariableName(out.minHeightVariableName as string, variableIdByName, variableIdByNormalized);\n if (id) {\n out.minHeightVariableId = id;\n delete out.minHeightVariableName;\n }\n }\n if (typeof out.maxHeightVariableName === \"string\") {\n const id = resolveVariableName(out.maxHeightVariableName as string, variableIdByName, variableIdByNormalized);\n if (id) {\n out.maxHeightVariableId = id;\n delete out.maxHeightVariableName;\n }\n }\n\n return out;\n}\n","/**\n * Canonical Figma Design Skills — single source of truth.\n *\n * Consumed by:\n * - Lab API (design-chat, design-generate, skill-context routes) via builder helpers\n * - MCP (syncAll / getDependencies) for the Figma design SKILL.md\n * - Figma plugin Design tab indirectly (via Lab API)\n *\n * Architecture:\n * PERSONA constants — Lola identity + mode-switching UX (Design tab only, never MCP)\n * KNOWLEDGE_ASK_* consts — advisory skill content (Design tab Ask mode only, never MCP)\n * KNOWLEDGE_CREATE_* consts — generative design knowledge (shared by Design tab Create AND MCP)\n * FIGMA_SKILL_EXTRAS_* — composed persona + knowledge (Design tab)\n * FIGMA_DESIGN_SKILL_MD — persona-free, generative-only markdown (MCP)\n */\n\nconst SCHEMA_VERSION = 1;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type SkillExtrasBlock = {\n prerequisites: string;\n best_practices: string;\n dos_donts: string;\n};\n\nexport type SkillContextPayload = {\n schema_version: number;\n ai_rules: string;\n prerequisites: string;\n best_practices: string;\n dos_donts: string;\n};\n\nexport type SkillContextDualPayload = {\n schema_version: number;\n ai_rules: string;\n ask: SkillExtrasBlock;\n create: SkillExtrasBlock;\n};\n\n// ---------------------------------------------------------------------------\n// PERSONA — Lola identity & Design tab UX steering (NEVER exposed via MCP)\n// ---------------------------------------------------------------------------\n\n/**\n * Lola identity paragraph for Design tab system prompts (Ask and Create).\n * Parameterized by design system name. Not used by MCP.\n */\nexport function getFigmaPersonaIdentity(dsName: string): string {\n return `Identity and steering: You are Lola, the user's creative assistant for ${dsName}. Important: ONLY IF asked who you are, your role, or your expertise: say you're Lola, their creative assistant for ${dsName} otherwise focus on the task at hand; in Ask mode you help with brand, copy, UX, and brainstorming; in Create mode you help with designing on the canvas using their design system. Always steer unrelated conversation back to what they'd like to do in Figma with ${dsName}.`;\n}\n\n/** Ask mode persona: Lola identity + mode-switching guard. */\nexport const FIGMA_PERSONA_ASK = `- When asked who you are or about your role, use the persona defined in the system prompt (Lola, creative assistant for their design system; Ask vs Create help). Steer off-topic conversation back to what they'd like to do in Figma with their design system.\n- If the user asks you to create, design, or generate UI components or screens on the Figma canvas (e.g. \"create a button\", \"design a login form\", \"make a card\", \"add a navbar\"), do not attempt to do it. Tell them that to create on the canvas they need to switch to Create mode, then repeat their request there.`;\n\n/** Create mode persona: Lola identity + expertise framing. */\nexport const FIGMA_PERSONA_CREATE = `- When asked who you are or about your role, use the persona defined in the system prompt (Lola, creative assistant for their design system; Ask vs Create help). Steer off-topic conversation back to what they'd like to do in Figma with their design system.\n- You are the design system expert for Create mode. Expertise: token-based UI (variables, text/effect styles), auto-layout and structure, naming and semantics, consistency with design system tokens, step-by-step Figma bridge commands. Same personality: direct, precise, no fluff; every step and name must earn its place.`;\n\n// ---------------------------------------------------------------------------\n// KNOWLEDGE — Advisory (Design tab Ask mode ONLY, never MCP)\n// ---------------------------------------------------------------------------\n\nconst KNOWLEDGE_ASK_PREREQUISITES = `- You support the design system owner and their team with questions about their brand, design direction, content, and UX. You are brand-agnostic: advise only from their design system's rules (tone of voice, design direction, component and copy guidance). Never impose a different brand.\n- Use only the \"Design system rules\" and any tone or direction stated there. If the user has not defined tone or direction, say so and suggest they add it in their design system.`;\n\nconst KNOWLEDGE_ASK_BEST_PRACTICES = `- Lead with benefit and clarity; avoid corporate fluff and feature-first answers.\n- For copy or naming: give a concrete before/after when improving something.\n- For visual or brand questions: tie recommendations to their tokens and rules (e.g. \"Given your primary and surface tokens...\").\n- Brainstorm as a partner: offer 2\\u20133 clear options when relevant, then narrow with them.\n- UX and product design: When the question touches flows, layout, or controls, apply UX heuristics (e.g. visibility of system status, match to real world, user control, consistency, error prevention, recognition over recall, flexibility, minimalism, error recovery, help) and interaction design (clear affordances, feedback, mapping, constraints). Recommend in plain language and, when useful, name the principle (e.g. \"This improves visibility of system status\" or \"Recognition over recall: show the option instead of making them remember it\").`;\n\nconst KNOWLEDGE_ASK_DOS_DONTS = `Do:\n- Ground every recommendation in their design system rules; speak to them as experts; use short, active phrasing; suggest specific wording when discussing copy.\n- Use UX and interaction design principles to justify design recommendations (e.g. feedback, consistency, clarity of next steps).\n\nDO NOT:\n- DO NOT invent tone or direction they have not defined; talk at them; over-explain; use hedging (\"we think\", \"might help\") or passive, weak copy.\n- DO NOT give purely subjective design opinions without tying them to a principle (heuristic, interaction design, or the user's design system rules).`;\n\n// ---------------------------------------------------------------------------\n// KNOWLEDGE — Generative (shared by Design tab Create mode AND MCP)\n// ---------------------------------------------------------------------------\n\nconst KNOWLEDGE_CREATE_PREREQUISITES = `- Must use either linked variables/style library (primary) or local variables/styles (secondary) for binding. Use only token names that appear in the \"Available in this Figma file\" asset list; do not invent names.\n- IMPORTANT: If neither linked nor local variables/styles are available, halt the design process and ask the user to run syncToFigma (MCP tool) or /--sync-to-figma (slash prompt) first to set up variables and styles. Do not proceed without them.\n- Always refer to the user's DS foundation AI guide for design direction and token usage.`;\n\nconst KNOWLEDGE_CREATE_BEST_PRACTICES = `- When the Design assets catalog lists components (Button, Input, Card, Alert, etc.): you MUST use design_create_component_instance for those elements. Do NOT build buttons, inputs, or cards from design_create_frame + design_create_text. Search the catalog by name and use the componentKey (or componentId for local). Pass textOverrides to set text inside the component (e.g. button labels, input placeholders) and variantProperties to select the correct variant. Only use frame+text when the catalog has no matching component.\n- For all colors (fills, strokes, text color), use ONLY variable names (fillVariableName, strokeVariableName). NEVER use paint style names for colors \\u2014 variables support mode switching (light/dark).\n- Last step is finalize_design_frame to name and optionally set the background fill on the root frame.\n- parentId can be omitted on the first child \\u2014 it defaults to the root frame. For deeper children, use the \"name\" from the parent design_create_frame step as parentId.\n- nodeId in design_set_auto_layout / design_set_layout_sizing / design_set_strokes / design_set_effects is the \"name\" of the target node (resolved to Figma id at runtime).\n- After design_create_frame, call design_set_auto_layout, then add children (text/rectangle/ellipse or design_create_component_instance), then design_set_layout_sizing on each child.\n- Apply cornerRadius via cornerRadiusVariableName; use design_set_strokes for borders; design_set_effects for shadows.`;\n\nconst KNOWLEDGE_CREATE_DOS_DONTS = `Do:\n- ALWAYS use SEMANTIC COLOR VARIABLE NAMES (fillVariableName, strokeVariableName) for all colors.\n- Apply SEMANTIC COLOR VARIABLE NAMES for frames, shapes, and text, change the original color if not compliant.\n- Give every created frame a clear \"name\" so later steps can reference it by nodeId.\n- Output a full sequence of steps for the requested component (e.g. button = frame + auto-layout + text + layout sizing + finalize).\n- For design_create_text, ALWAYS set \"characters\" to the real visible label (e.g. \"Button\", \"Submit\", \"Sign in\"). Never use a placeholder like \"Text\" or leave it empty.\n- For frames that are buttons, cards, or have a visible background, ALWAYS set fillVariableName to a color variable from the assets list.\n- For button label text on a colored background, set fillVariableName on design_create_text to a contrasting color variable (e.g. onPrimary).\n- ALWAYS use design_create_component_instance for icons, logos, illustrations, AND UI components (buttons, inputs, cards, alerts, etc.) when matching components exist in the catalog. Search the catalog by name and use the componentKey (or componentId for local).\n- For component instances with text (buttons, inputs, cards, alerts, etc.), ALWAYS pass textOverrides to set the visible text INSIDE the component. Use exact text node names from the catalog's textLayers list (e.g. {\"Label\": \"Submit\", \"Description\": \"Click here\"}). If the catalog shows textLayers for a component, use those exact names as keys. If textLayers are not listed, use get_component_text_layers to discover them, or use {\"_primary\": \"Submit\"} to target the first text node. NEVER create separate design_create_text nodes for text that belongs inside a component instance.\n- For component sets with variants, prefer variantProperties (e.g. {\"Size\": \"sm\", \"State\": \"default\", \"Type\": \"outline\"}) to select the right variant by property values. Use variantKey only when you have the exact key from the catalog children list.\n- When a card or row contains an icon/component: create a wrapper frame first (design_create_frame with name e.g. \"Card\"), add design_create_component_instance as child of that frame, then add text/other children with parentId the wrapper frame name — never use the instance as parentId (Figma cannot append to component instances).\n- For icons and logo instances, ALWAYS pass fillVariableName with a semantic color (e.g. \"Icon / primary\", \"Text / primary\"). You choose the token; the plugin applies it to the glyph only. If you omit fillVariableName, the plugin resolves existing hex fills to the closest variable (prefers semantic) — so either way icons get semantic color.\n\nDO NOT:\n- DO NOT invent variable or style names not in the assets list.\n- DO NOT use primitive color variables, raw hex, or paint style or raw PX values.\n- DO NOT set fill or background on the icon frame; fillVariableName on design_create_component_instance applies to the glyph only.\n- DO NOT use primitive variable names for colors (e.g. \"GrayDark / 300\", \"Gray / 50\", \"Red / 800\") — use ONLY variables from collections whose name does not include \"Primitives\" and does not start with \"Radix \" (e.g. \"Text / primary\", \"Action / primary\", \"Surface / primary\" from semantic collections).\n- DO NOT output only one or two steps for a component request; include all steps needed to build the UI.\n- DO NOT use arbitrary frame sizes like 100x100 or 200x200; use standard device sizes (see catalog) or hug content.\n- DO NOT use design_create_vector for icons when a matching icon component exists in the catalog — always prefer design_create_component_instance.\n- DO NOT create separate design_create_text nodes for text that should be inside a component instance (e.g. button labels, input placeholders, alert messages). Use textOverrides on design_create_component_instance instead.\n- DO NOT build UI components (buttons, inputs, cards, alerts) from scratch with design_create_frame + design_create_text when matching components exist in the catalog. Always use design_create_component_instance with textOverrides and variantProperties.\n- DO NOT guess text node names for textOverrides. Check the catalog's textLayers data first. If unavailable, call get_component_text_layers before creating the instance to discover the exact text node names.`;\n\n// ---------------------------------------------------------------------------\n// KNOWLEDGE — Quality Protocol (shared by Design tab Create AND MCP)\n// ---------------------------------------------------------------------------\n\nconst KNOWLEDGE_QUALITY_PROTOCOL = `## Quality Verification\n\n1. After finalize_design_frame, ALWAYS call get_design_screenshot to visually inspect the result.\n2. If a source reference was provided (screenshot, image, code snippet, URL), compare the output against it.\n3. Identify structural mismatches: missing elements, wrong hierarchy, incorrect spacing, misaligned sections.\n4. Iterate: add or modify steps to fix issues, then screenshot again.\n5. Maximum 3 iteration rounds before asking the user for guidance on remaining discrepancies.\n6. Do not declare the design complete until the screenshot confirms it matches the intent.`;\n\n// ---------------------------------------------------------------------------\n// KNOWLEDGE — Auto-Layout & Sizing Discipline (shared)\n// ---------------------------------------------------------------------------\n\nconst KNOWLEDGE_LAYOUT_DISCIPLINE = `## Auto-Layout & Sizing\n\n- Auto-layout everything. Every frame with children MUST have design_set_auto_layout applied.\n- Floating elements (badges, close buttons, FABs, overlays, tooltips): (1) design_set_node_position with absolute: true and x, y; (2) design_set_resize_constraints so they float on parent resize (e.g. STRETCH horizontal + MAX vertical for a bottom bar that sticks to bottom and stretches width).\n- Use design_set_node_position with absolute: true ONLY for floating elements; it takes the node out of auto-layout so x/y apply.\n- Root frame width: fixed width, all child frames stretch to fill the root frame width.\n- Root frame height: Dont fix height, all child frames HUG to fill the root frame height.\n- Content Width: FILL for content that stretches to parent, HUG for content-sized elements (buttons, tags, chips).\n- Content Height: Content determines height, but set it to FILL for columns and sidebars that stretch vertically.\n- Wrapping text: For any body or paragraph text that should wrap within its container (e.g. feed content, card copy, descriptions), (1) set the frame that directly contains the text to layoutSizingHorizontal \"FILL\" via design_set_layout_sizing so it uses full width, and (2) call design_set_text_properties on that text node with textAutoResize \"HEIGHT\" so the text wraps to the frame width instead of hugging. Without both, text will hug and leave empty space.\n- Never leave sizing as default FIXED unless the element has a deliberate fixed dimension.\n- For icons use icon sizing variables and spacing. Keep icon frames square.\n- Set elements to hug or fill — never leave them unconstrained.`;\n\n// ---------------------------------------------------------------------------\n// KNOWLEDGE — Use-case best practices (shared by Design tab Create AND MCP)\n// ---------------------------------------------------------------------------\n\nconst KNOWLEDGE_MOBILE_DESIGN = `## Designing for Mobile\n\n### Best Practices\n1. Avoid fixed width or height. Add padding and set height and width to hug contents or fill width. See spacing and sizing rules! \n2. Text width should always set to \"FILL\" to ensure text wraps within frame's width.\n3. Add system status bar UI and home indicator UI if no components for this is available in the catalog. Use spacing variables to set the padding.\n4. Use device preset frames for correct dimensions. iPhone 14: 390\\u00d7844, Android: 412\\u00d7915 (or 360\\u00d7800 for compact). Use design_create_frame_from_preset when available.\n5. All interactive elements must follow sizing and spacing rules. Use sizing / height variables to enforce this consistently.\n6. Design for the thumb zone: place primary actions in the bottom 60% of the screen. Bottom navigation with 4\\u20135 items is the standard pattern.\n7. Mobile is single-column. Stack sections vertically. Avoid horizontal scrolling for primary content.\n\n### Figma-Specific Tips\n1. Use design_create_frame_from_preset (iphone_14, android_412) instead of manual dimensions.\n2. Set text nodes to textAutoResize: \"HEIGHT\" for fixed-width, auto-height text (mobile text wraps within screen width).\n3. Content frames: layoutSizingHorizontal \"FILL\", layoutSizingVertical \"HUG\" — fills width, hugs content height.\n4. Bottom navigation: horizontal auto-layout frame, FILL width, items spaced with SPACE_BETWEEN, each item is a vertical frame (icon + label).\n5. Cards in scrollable lists: create a container frame with VERTICAL auto-layout, each card FILL width and HUG height.\n6. Set the ROOT frame's height to \"HUG\" content to ensure it stretches to the content height.`;\n\n\nconst KNOWLEDGE_WEB_DESIGN = `## Designing for Web\n\n### Best Practices\n1. Use 1440\\u00d7900 desktop frame if size not specified. Design content within a max-width container (see breakpoint tokens) centered in the viewport using counterAxisAlignItems: \"CENTER\".\n2. Detect how many sections are needed and create them as children of the root frame. \n3. Root frame by default is a vertical auto-layout frame with FILL horizontal layout sizing. Create a constrained content frame inside with max-width via design_set_layout_constraints.\n4. Navigation: horizontal auto-layout, logo on the left, nav links centered or right-aligned, use SPACE_BETWEEN for even distribution.\n5. All interactive elements must follow sizing and spacing rules. Use sizing / height variables to enforce this consistently.\n6. Responsive thinking: use min/max width constraints on content containers. Cards and grid items benefit from min-width to prevent collapsing.\n\n### Figma-Specific Tips\n1. The root frame IS the viewport. Add full-width sections directly as children (VERTICAL auto-layout by default).\n2. For multi-column layouts: switch the appropriate parent frame to auto-layout.\n3. Use layoutSizingHorizontal \"FILL\" on column frames so they stretch proportionally.\n4. Apply counterAxisAlignItems \"STRETCH\" on horizontal parents for equal-height columns.\n5. Hero sections: VERTICAL auto-layout, CENTER both axes, generous padding tokens (xl or 2xl). Use itemSpacing for vertical rhythm.`;\n\nconst KNOWLEDGE_TOKEN_APPLICATION = `## Applying Tokens to Designs\n\n### Best Practices\n1. ALWAYS use SEMANTIC COLOR VARIABLES (fillVariableName, strokeVariableName) \\u2014 never use PRIMITIVE colors, hex, rgb, or paint style names. Variables enable light/dark mode switching.\n2. If components are using NON-SEMANTIC color fills for any shapes or text, replace them with SEMANTIC color fills.\n3. For icons and logos: pass fillVariableName on design_create_component_instance. The plugin applies the color to the glyph (vector/shape) only, not the icon frame, and rebinds any existing fill to a semantic variable when possible.\n4. Use semantic token names over primitive names when both exist: prefer \"Surface / primary\" over \"Neutral / 10\", prefer \"Action / primary\" over \"Green / 600\".\n5. Bind spacing via paddingVariableName (uniform or per-side) and itemSpacingVariableName on auto-layout frames. Never hardcode pixel spacing.\n6. Bind corner radius via cornerRadiusVariableName on frames and rectangles. Reserve raw cornerRadius only when no variable exists.\n7. Apply text styles via textStyleName for consistent typography. Text styles bundle font family, size, weight, and line height.\n\n### Figma-Specific Tips\n1. The asset list (\"Available in this Figma file\") is the source of truth. Match exact names including slashes and casing.\n2. Use apply_matching_styles_to_selection for batch token application to existing, unbound designs. It matches by color distance.\n3. The root frame is automatically set to Light mode. Child frames inherit from root (AUTO). Do NOT call design_set_frame_variable_mode on child frames unless the user explicitly asks for a mode override on a specific section. Only use it on the root frame to switch the entire design's mode, or on a non-root parent frame as an explicit override.\n4. Per-side padding variables (paddingTopVariableName, etc.) override uniform paddingVariableName \\u2014 use for asymmetric layouts like cards with more bottom padding.\n5. For Icons apply SEMANTIC color to the vector shapes. DO NOT set bg color to the ICON frame background.`;\n\n// ---------------------------------------------------------------------------\n// KNOWLEDGE — Image-to-Figma Recreation (shared by Design tab Create AND MCP)\n// ---------------------------------------------------------------------------\n\nconst KNOWLEDGE_IMAGE_TO_FIGMA = `## Image-to-Figma Recreation\n\nACTIVATION: Apply this knowledge ONLY when the user has selected a reference image and asks to recreate, reproduce, replicate, or redesign it. A reference image is a selected IMAGE node, RECTANGLE, or FRAME containing a single child. If the selection contains multiple elements, REJECT: reply that you can only recreate from a single reference image and ask the user to flatten or select just one image.\n\n### Step 1: Determine Device Type from Image Dimensions\n\nThe selection context includes the image dimensions (width, height). Use these to determine the root frame size:\n- Portrait orientation (height > width × 1.2) → MOBILE. Use 390×844 root frame. Follow mobile design rules.\n- Width ≥ 1200 → DESKTOP. Use 1440×900 root frame. Follow web design rules.\n- Width 600–1199 AND landscape/square → TABLET. Use 768×1024 root frame. Follow web design rules with single-column bias.\n- If dimensions are unavailable, infer from image content (phone chrome = mobile, browser chrome = desktop).\nUse the matching standard size from the catalog. Do NOT use the image's raw pixel dimensions as the frame size.\n\n### Step 2: Systematic Top-Down Decomposition\n\nScan the reference image from top to bottom. Identify each distinct horizontal band:\n1. Status bar / system UI (mobile only)\n2. Navigation / header\n3. Content sections (hero, features, lists, grids, forms)\n4. Footer / bottom navigation (mobile: tab bar)\n\nEach band becomes a FRAME with auto-layout. Name each frame descriptively (e.g., \"Header\", \"Hero Section\", \"Destination Cards Grid\", \"App Download Section\").\n\n### Step 3: Element Identification Within Sections\n\nFor each section, identify every visible element:\n- **Text**: Read the EXACT text from the image. Use the precise wording — do not paraphrase or summarize. Match the apparent hierarchy (heading vs body vs caption) to available text styles.\n- **Buttons / CTAs**: Frame + text with action color variables. Match the visual style (filled = primary, outlined = secondary).\n- **Input fields**: Frame + placeholder text with surface/muted fills.\n- **Cards**: Frame with fill + corner radius, containing image placeholder + text + metadata.\n- **Content images** (photos, illustrations, avatars): Create a RECTANGLE placeholder with a muted/secondary fill. Set dimensions proportional to what appears in the reference. Name descriptively (e.g., \"New York Photo\", \"Hero Illustration\", \"User Avatar\").\n- **Icons**: Use design_create_component_instance if a matching icon exists in the catalog. Otherwise use a small rectangle placeholder.\n- **Dividers / separators**: design_create_line or a thin frame with border fill.\n- **Badges / chips / tags**: Small frames with HUG sizing, rounded corners, and appropriate fill.\n\n### Step 4: Proportional Sizing and Spacing\n\nEstimate proportions from the reference image relative to the root frame, not pixel-exact:\n- If a hero section takes roughly 40% of the viewport height, size accordingly.\n- If cards are arranged in a 2×4 or 3×2 grid, use horizontal auto-layout with FILL children.\n- Match the visual density: tight spacing vs generous whitespace. Use spacing variables (sm for tight, md for normal, lg for generous, xl for spacious).\n- For text sizing: large headings → largest available text style, body → mid-range style, captions → smallest style.\n\n### Step 5: Color Mapping Strategy\n\nMap visual colors from the image to the CLOSEST SEMANTIC variable — do not try to match exact hex values:\n- Dark backgrounds → use the darkest available surface/background variable\n- Light backgrounds → Surface / primary or Surface / muted\n- Brand-colored elements (buttons, highlights) → Action / primary or brand variables\n- Text on dark → light text variable; text on light → dark text variable\n- Subtle borders → Border / primary or Border / secondary\n- Muted/disabled elements → Text / muted or Surface / muted\n\n### Content Images and Photos\n\nPhotos, illustrations, screenshots, and complex graphics CANNOT be recreated. For each:\n- Look for image library or image components. \n- If none, create a rectangle placeholder with muted or any semantic surface / background color fill. Do not use primitive colors or hex values.\n- Size proportionally to the reference.\n- Name descriptively: \"Hero Banner Image\", \"Product Photo\", \"Map Preview\".\n- DO NOT attempt to describe or recreate photo content as vector shapes`;\n\nconst KNOWLEDGE_COMPONENTS_VARIANTS = `## Creating Components & Variants\n\n### Best Practices\n1. Build the base component fully first: frame + auto-layout + children + token bindings + sizing. Finalize structure before converting.\n2. If components are using NON-SEMANTIC color fills for any shapes or text, replace them with SEMANTIC color fills.\n3. Avoid fixed width or height. Add padding and set height and width to hug content. See spacing and sizing rules! \n4. Name with slash convention for organization: \"Button/Primary\", \"Input/Default\", \"Card/Outlined\". Figma groups these in the assets panel.\n5. Every variant must be a unique combination of properties (e.g., Size=sm + State=default vs Size=sm + State=hover). Do not duplicate property combinations.\n6. Use variable binding on all variants so they inherit mode switching (light/dark) automatically. Do NOT set explicit variable mode on variant frames — they inherit from the root frame.\n7. NEVER use primitive colors or hardcoded colors for UI components.\n\n### Figma-Specific Tips\n1. Use design_create_component for the master, build its internals (auto-layout, children, tokens), then create variant frames and use design_combine_as_variants.\n2. Alternative: build all variant frames first, use design_convert_to_component on each, then design_combine_as_variants to merge into a variant set.\n3. Set auto-layout and layout sizing BEFORE converting to component. Changing structure after conversion can break variant overrides.\n4. Use list_local_components before creating to avoid duplicating existing components in the file.\n5. Variant property naming must be consistent across all variants in the set (e.g., always \"Size\", never mixing \"Size\" and \"size\").`;\n\n// ---------------------------------------------------------------------------\n// Composed Design tab exports (persona + knowledge)\n// ---------------------------------------------------------------------------\n\n/** Ask mode: persona + knowledge. Used by Design tab only. */\nexport const FIGMA_SKILL_EXTRAS_ASK = {\n schema_version: SCHEMA_VERSION,\n prerequisites: `${FIGMA_PERSONA_ASK}\\n${KNOWLEDGE_ASK_PREREQUISITES}`,\n best_practices: KNOWLEDGE_ASK_BEST_PRACTICES,\n dos_donts: KNOWLEDGE_ASK_DOS_DONTS,\n} as const;\n\n/** Create mode: persona + knowledge (including use-case guides). Used by Design tab only. */\nexport const FIGMA_SKILL_EXTRAS_CREATE = {\n schema_version: SCHEMA_VERSION,\n prerequisites: `${FIGMA_PERSONA_CREATE}\\n${KNOWLEDGE_CREATE_PREREQUISITES}`,\n best_practices: [\n KNOWLEDGE_CREATE_BEST_PRACTICES,\n KNOWLEDGE_LAYOUT_DISCIPLINE,\n KNOWLEDGE_QUALITY_PROTOCOL,\n KNOWLEDGE_MOBILE_DESIGN,\n KNOWLEDGE_WEB_DESIGN,\n KNOWLEDGE_TOKEN_APPLICATION,\n KNOWLEDGE_COMPONENTS_VARIANTS,\n KNOWLEDGE_IMAGE_TO_FIGMA,\n ].join(\"\\n\\n\"),\n dos_donts: KNOWLEDGE_CREATE_DOS_DONTS,\n} as const;\n\n/** @deprecated Use FIGMA_SKILL_EXTRAS_CREATE for Create mode. */\nexport const FIGMA_SKILL_EXTRAS = FIGMA_SKILL_EXTRAS_CREATE;\n\nexport type FigmaSkillExtras = typeof FIGMA_SKILL_EXTRAS_CREATE;\nexport type FigmaSkillExtrasAsk = typeof FIGMA_SKILL_EXTRAS_ASK;\n\n// ---------------------------------------------------------------------------\n// MCP export — persona-free, generative-only design skill as markdown\n// ---------------------------------------------------------------------------\n\n/**\n * Persona-free Figma design skill for MCP consumers (SKILL.md).\n * Focused entirely on creating high-quality, token-bound designs in Figma\n * from any reference (screenshots, images, code snippets, URLs).\n * No advisory/brand/copy content — that lives only in the Design tab Ask mode.\n */\nexport const FIGMA_DESIGN_SKILL_MD = `# Figma Design Skill\n\nCreate high-quality, token-bound designs in Figma from any reference: screenshots, images, code snippets, or URLs. Every element uses the user's design system variables and styles.\n\n## Prerequisites\n\n${KNOWLEDGE_CREATE_PREREQUISITES}\n\n## Core Workflow\n\n${KNOWLEDGE_CREATE_BEST_PRACTICES}\n\n${KNOWLEDGE_LAYOUT_DISCIPLINE}\n\n${KNOWLEDGE_QUALITY_PROTOCOL}\n\n${KNOWLEDGE_MOBILE_DESIGN}\n\n${KNOWLEDGE_WEB_DESIGN}\n\n${KNOWLEDGE_TOKEN_APPLICATION}\n\n${KNOWLEDGE_COMPONENTS_VARIANTS}\n\n${KNOWLEDGE_IMAGE_TO_FIGMA}\n\n## Do's and Don'ts\n\n${KNOWLEDGE_CREATE_DOS_DONTS}\n`;\n\n// ---------------------------------------------------------------------------\n// Builder helpers (used by Lab skill-context API route)\n// ---------------------------------------------------------------------------\n\n/**\n * Build the skill context object to inject into Gemini (single-mode).\n * @param rulesContent - Output of generateUserRules for the user's DS.\n * @param extras - Optional override; defaults to FIGMA_SKILL_EXTRAS_CREATE.\n */\nexport function buildSkillContextPayload(\n rulesContent: string,\n extras?: { prerequisites?: string; best_practices?: string; dos_donts?: string },\n): SkillContextPayload {\n const pr = extras?.prerequisites ?? FIGMA_SKILL_EXTRAS_CREATE.prerequisites;\n const bp = extras?.best_practices ?? FIGMA_SKILL_EXTRAS_CREATE.best_practices;\n const dd = extras?.dos_donts ?? FIGMA_SKILL_EXTRAS_CREATE.dos_donts;\n return {\n schema_version: FIGMA_SKILL_EXTRAS_CREATE.schema_version,\n ai_rules: rulesContent,\n prerequisites: pr,\n best_practices: bp,\n dos_donts: dd,\n };\n}\n\n/**\n * Build dual skill context (Ask + Create) for the skill-context API.\n * Client uses skillContext.ask for design-chat and skillContext.create for design-generate.\n */\nexport function buildDualSkillContextPayload(rulesContent: string): SkillContextDualPayload {\n return {\n schema_version: FIGMA_SKILL_EXTRAS_CREATE.schema_version,\n ai_rules: rulesContent,\n ask: {\n prerequisites: FIGMA_SKILL_EXTRAS_ASK.prerequisites,\n best_practices: FIGMA_SKILL_EXTRAS_ASK.best_practices,\n dos_donts: FIGMA_SKILL_EXTRAS_ASK.dos_donts,\n },\n create: {\n prerequisites: FIGMA_SKILL_EXTRAS_CREATE.prerequisites,\n best_practices: FIGMA_SKILL_EXTRAS_CREATE.best_practices,\n dos_donts: FIGMA_SKILL_EXTRAS_CREATE.dos_donts,\n },\n };\n}\n","/**\n * Bridge wire protocol (merged from figma-bridge).\n * All messages are JSON. Only whitelisted methods are allowed.\n * Used by the in-process Figma bridge (WebSocket server in mcp-user).\n * Method list derived from the shared catalog in @atomix/figma-tools.\n */\n\nimport { getCatalogMethodNames } from \"@atomix/figma-tools\";\n\n// Single source of truth: design-catalog.ts in @atomix/figma-tools. Do NOT duplicate method lists here.\nexport const BRIDGE_METHODS = getCatalogMethodNames();\n\nexport type BridgeMethod = string;\n\nexport interface BridgeRequest {\n id: string;\n method: string;\n params?: Record<string, unknown>;\n}\n\nexport interface BridgeSuccessResponse {\n id: string;\n result: unknown;\n}\n\nexport interface BridgeErrorResponse {\n id: string;\n error: string;\n}\n\nexport type BridgeResponse = BridgeSuccessResponse | BridgeErrorResponse;\n\nexport function isBridgeRequest(msg: unknown): msg is BridgeRequest {\n if (!msg || typeof msg !== \"object\") return false;\n const m = msg as Record<string, unknown>;\n return (\n typeof m.id === \"string\" &&\n m.id.length > 0 &&\n typeof m.method === \"string\" &&\n m.method.length > 0\n );\n}\n\n/** Convert camelCase to snake_case for bridge (e.g. getFigmaVariablesAndStyles -> get_figma_variables_and_styles). */\nexport function normalizeBridgeMethod(method: string): string {\n if (typeof method !== \"string\" || !method) return method;\n return method.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);\n}\n\nexport function isAllowedMethod(method: string): boolean {\n const normalized = normalizeBridgeMethod(method);\n return BRIDGE_METHODS.includes(normalized);\n}\n"],"mappings":"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","names":["group","name","groupDisplay","n"]}
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* Bridge wire protocol (merged from figma-bridge).
|
|
3
3
|
* All messages are JSON. Only whitelisted methods are allowed.
|
|
4
4
|
* Used by the in-process Figma bridge (WebSocket server in mcp-user).
|
|
5
|
+
* Method list derived from the shared catalog in @atomix/figma-tools.
|
|
5
6
|
*/
|
|
6
|
-
declare const BRIDGE_METHODS:
|
|
7
|
-
type BridgeMethod =
|
|
7
|
+
declare const BRIDGE_METHODS: string[];
|
|
8
|
+
type BridgeMethod = string;
|
|
8
9
|
interface BridgeRequest {
|
|
9
10
|
id: string;
|
|
10
11
|
method: string;
|
|
@@ -22,6 +23,6 @@ type BridgeResponse = BridgeSuccessResponse | BridgeErrorResponse;
|
|
|
22
23
|
declare function isBridgeRequest(msg: unknown): msg is BridgeRequest;
|
|
23
24
|
/** Convert camelCase to snake_case for bridge (e.g. getFigmaVariablesAndStyles -> get_figma_variables_and_styles). */
|
|
24
25
|
declare function normalizeBridgeMethod(method: string): string;
|
|
25
|
-
declare function isAllowedMethod(method: string):
|
|
26
|
+
declare function isAllowedMethod(method: string): boolean;
|
|
26
27
|
|
|
27
28
|
export { BRIDGE_METHODS, type BridgeErrorResponse, type BridgeMethod, type BridgeRequest, type BridgeResponse, type BridgeSuccessResponse, isAllowedMethod, isBridgeRequest, normalizeBridgeMethod };
|