coderio 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -48
- package/dist/cli.js +27 -12
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +12 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/logger.ts","../src/nodes/process/structure/prompt.ts","../src/tools/position-tool/utils/fetch-thumbnail-dimensions.ts","../src/cli/index.ts","../src/constants/index.ts","../src/cli/init.ts","../src/tools/figma-tool/index.ts","../src/utils/axios.ts","../src/utils/config.ts","../src/utils/file.ts","../src/utils/workspace.ts","../src/tools/figma-tool/figma.ts","../src/tools/figma-tool/images.ts","../src/utils/promise-pool.ts","../src/tools/figma-tool/constants.ts","../src/tools/style-tool/index.ts","../src/tools/style-tool/color.ts","../src/tools/style-tool/utils.ts","../src/nodes/process/index.ts","../src/utils/call-model.ts","../src/nodes/process/structure/index.ts","../src/nodes/process/structure/utils.ts","../src/utils/naming.ts","../src/utils/parser.ts","../src/utils/url-parser.ts","../src/cli/d2p.ts","../src/cli/d2c.ts","../src/graph.ts","../src/state.ts","../src/agents/initial-agent/index.ts","../src/agents/initial-agent/prompt.ts","../src/nodes/initial/index.ts","../src/agents/initial-agent/instruction.ts","../src/nodes/validation/index.ts","../src/nodes/validation/constants.ts","../src/nodes/validation/core/validation-loop.ts","../src/agents/commit-agent/index.ts","../src/agents/commit-agent/prompt.ts","../src/agents/commit-agent/instruction.ts","../src/nodes/validation/commit/index.ts","../src/agents/judger-agent/index.ts","../src/tools/history-tool/index.ts","../src/tools/hierarchy-tool/index.ts","../src/nodes/validation/utils/tree/tree-traversal.ts","../src/agents/judger-agent/prompt.ts","../src/agents/judger-agent/utils.ts","../src/agents/judger-agent/instruction.ts","../src/agents/refiner-agent/index.ts","../src/agents/refiner-agent/prompt.ts","../src/agents/refiner-agent/utils.ts","../src/agents/refiner-agent/instruction.ts","../src/agents/launch-agent/index.ts","../src/agents/launch-agent/prompt.ts","../src/agents/launch-agent/utils.ts","../src/agents/launch-agent/instruction.ts","../src/nodes/validation/launch/index.ts","../src/nodes/validation/utils/extraction/extract-layout-metadata.ts","../src/nodes/validation/report/index.ts","../src/tools/report-tool/index.ts","../src/tools/visualization-tool/index.ts","../src/tools/visualization-tool/utils/annotation-styles.ts","../src/tools/visualization-tool/utils/annotate-render.ts","../src/tools/visualization-tool/utils/image-converter.ts","../src/tools/visualization-tool/utils/annotate-target.ts","../src/nodes/validation/utils/playwright/launcher.ts","../src/tools/visualization-tool/utils/browser-management.ts","../src/tools/visualization-tool/utils/combine.ts","../src/tools/visualization-tool/utils/pixel-diff-heatmap.ts","../src/tools/launch-tool/index.ts","../src/tools/launch-tool/utils/dev-server-manager.ts","../src/nodes/validation/utils/extraction/extract-protocol-context.ts","../src/nodes/validation/core/validate-position.ts","../src/tools/position-tool/index.ts","../src/tools/position-tool/utils/capture-position.ts","../src/tools/position-tool/utils/position-metrics.ts","../src/tools/position-tool/utils/aggregate-elements.ts","../src/utils/dependency-installer.ts","../src/nodes/code/index.ts","../src/nodes/code/utils.ts","../src/nodes/code/prompt.ts","../src/nodes/code/constants.ts","../src/utils/code-cache.ts","../src/utils/checkpoint.ts","../src/cli/prompts.ts","../src/cli/images.ts","../src/cli/p2c.ts","../src/cli/val.ts"],"sourcesContent":["import chalk from 'chalk';\n\n/**\n * Get current timestamp in YYYY-MM-DD HH:mm:ss format\n */\nfunction getTimestamp(): string {\n const now = new Date();\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const day = String(now.getDate()).padStart(2, '0');\n const hours = String(now.getHours()).padStart(2, '0');\n const minutes = String(now.getMinutes()).padStart(2, '0');\n const seconds = String(now.getSeconds()).padStart(2, '0');\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;\n}\n\n/**\n * Logger utility for consistent console output with colors\n */\nexport const logger = {\n /**\n * Print standard log (alias for info logs).\n *\n * Many subsystems (e.g. validation) use `printLog()` as the default logging method.\n */\n printLog(message: string): void {\n console.log(message);\n },\n\n /**\n * Print info log in blue\n */\n printInfoLog(message: string): void {\n console.log(chalk.blue(`[${getTimestamp()}] [INFO] ${message}`));\n },\n\n /**\n * Print warning log in yellow\n */\n printWarnLog(message: string): void {\n console.warn(chalk.yellow(`[${getTimestamp()}] [WARNING] ${message}`));\n },\n\n /**\n * Print error log in red\n */\n printErrorLog(message: string): void {\n console.error(chalk.red(`[${getTimestamp()}] [ERROR] ✖ ${message}`));\n },\n\n /**\n * Print test/debug log in gray\n * Only logs in development/test environments\n */\n printTestLog(message: string): void {\n if (process.env.NODE_ENV === 'development') {\n console.log(chalk.gray(`[${getTimestamp()}] [DEBUG] ${message}`));\n }\n },\n\n /**\n * Print success log in green\n */\n printSuccessLog(message: string): void {\n console.log(chalk.green(`[${getTimestamp()}] [SUCCESS] ✔ ${message}`));\n },\n};\n","/**\n * Prompt template for structure generation.\n * Matches the style used in agents/initial-agent/prompt.ts.\n */\nexport const generateStructurePrompt = (options: { positions: string; width?: string }) => {\n const { positions, width } = options;\n const imageWidth = width ?? '1440';\n return `\n<system_instructions>\n <task>Generate a semantic React component structure from Figma design data.</task>\n\n <input_context>\n <positions_json>${positions}</positions_json>\n <image_width>${imageWidth}px</image_width>\n <visual_reference>Refer to the attached image for hierarchy and grouping.</visual_reference>\n </input_context>\n\n <rules>\n <rule name=\"Hierarchy Strategy\">\n 1. Compare 'positions_json' nesting with visual grouping.\n 2. If data contradicts visual layout, IGNORE data nesting and restructure based on VISUAL proximity.\n </rule>\n\n <rule name=\"Pattern Recognition (CRITICAL)\">\n 1. **Semantic Grouping**: Group by function (e.g., \"PricingCard\", \"UserProfile\").\n 2. **Grid/List Detection**:\n - Detect repeating identical siblings (e.g., 6 Cards).\n - Create a SINGLE container (e.g., \"CardGrid\") instead of \"Card1\", \"Card2\".\n - **MERGE IDs**: The container's \\`elementIds\\` MUST include ALL children IDs of all items in the grid to ensure complete style extraction.\n - **Reusable Instances with \\`data.componentName\\`**:\n - For each visually repeated item, keep a unique \\`id\\` / \\`data.name\\` (e.g., \"TaskCard1\", \"TaskCard2\", ...).\n - Set the SAME \\`data.componentName\\` for all these items (e.g., \"TaskCard\") to mark them as instances of one reusable component.\n - Example: 12 task cards → each child has different \\`id\\` / \\`data.name\\` (\"TaskCard1\"... \"TaskCard12\"), but the SAME \\`data.componentName\\`: \"TaskCard\".\n 3. **Fragmentation**: Avoid creating components for single atoms (Text/Icon) unless reusable (Button/Chip).\n 4. **Monoliths**: Split sections >1000px height.\n </rule>\n\n <rule name=\"Component Granularity (CRITICAL - Prevent Over-Fragmentation)\">\n 1. **Maximum Depth = 2**:\n - Component tree should NOT exceed 2 levels deep (root -> children -> grandchildren is the MAX).\n - If you find yourself creating a 3rd level, STOP and merge it into the parent instead.\n\n 2. **Minimum Element Threshold**:\n - Each component MUST contain at least 5+ elements in its \\`elementIds\\`.\n - If a potential component has fewer than 5 elements, MERGE it into its parent or sibling.\n - This prevents creating tiny components like \"LegalLinks\" (3 links) or \"CommunityLinks\" (2 links).\n\n 3. **Component Count Limit**:\n - For a single section, create at most 2-3 child components.\n - Example: Footer → FooterTop, FooterBottom (2 children, NOT 4-5 like \"Logos\", \"Links\", \"QRCode\", etc.)\n\n 4. **DO NOT Create Separate Components For**:\n - A group of links (merge into parent section's elementIds)\n - A group of logos or icons (merge into parent section's elementIds)\n - Single text, image, icon, divider, link\n - Any group with < 5 elements\n These should ALL be included in parent's \\`elementIds\\`.\n\n 5. **Merge by Visual Region, NOT by Function**:\n - Divide by visual position (Top/Bottom, Left/Right), NOT by element type (Links/Logos/QRCode).\n - Example: FooterTop contains logos + links + icons together (all elements in that visual area).\n </rule>\n\n <rule name=\"Naming & ID\">\n - \\`id\\` MUST match \\`data.name\\` (PascalCase, Unique).\n - **Containers**: \\`elementIds\\` = container background/frame IDs only.\n - **Leaves**: \\`elementIds\\` = component's direct IDs + ALL nested children IDs.\n - **Integrity**: Every input ID must be assigned to exactly one component.\n </rule>\n\n <rule name=\"Layout Data\">\n For EACH node, calculate:\n - \\`boundingBox\\`: {top, left, width, height} (Absolute)\n - \\`relativeBoundingBox\\`: {top, left, width, height} (Relative to parent)\n - \\`spacing\\`: {next: number} (Distance to next sibling)\n - \\`layoutDirection\\`: \"VERTICAL\" | \"HORIZONTAL\" | \"NONE\"\n **HOW TO DETERMINE layoutDirection (ESPECIALLY FOR ROOT NODE)**:\n 1. Look at ALL direct children's \\`boundingBox.left\\` values\n 2. **If children have 2+ DIFFERENT \\`left\\` values** (difference > 50px):\n → Set \\`layoutDirection = \"HORIZONTAL\"\\`\n → Example: Sidebar at left=0, Content at left=240 → HORIZONTAL\n 3. **If ALL children have SAME \\`left\\` value** (within ±50px tolerance):\n → Set \\`layoutDirection = \"VERTICAL\"\\`\n → Example: Header at left=0, Content at left=0, Footer at left=0 → VERTICAL\n 4. Common patterns:\n - **Sidebar Layout**: Sidebar (left=0) + Main Content (left=240+) → ROOT is HORIZONTAL\n - **Stacked Layout**: All sections at same left position → ROOT is VERTICAL\n </rule>\n </rules>\n\n <output_format>\n Return ONLY a single valid JSON object (no markdown code blocks).\n Output MUST be COMPACT (no pretty-printing): avoid indentation/newlines as much as possible.\n Follow this schema exactly:\n {\n \"id\": \"ComponentName\",\n \"data\": {\n \"name\": \"ComponentName\",\n \"componentName\": \"OptionalReusableComponentName\",\n \"purpose\": \"string\",\n \"elementIds\": [\"id1\", \"...\"],\n \"layout\": {\n \"boundingBox\": { \"top\": 0, \"left\": 0, \"width\": 0, \"height\": 0 },\n \"relativeBoundingBox\": { \"top\": 0, \"left\": 0, \"width\": 0, \"height\": 0 },\n \"spacing\": { \"next\": 0 },\n \"layoutDirection\": \"VERTICAL\"\n }\n },\n \"children\": []\n }\n\n layoutDirection MUST be one of: \"VERTICAL\" | \"HORIZONTAL\" | \"NONE\"\n \n **Layout Groups**:\n - Do NOT generate \\`layoutGroups\\` field in your output\n - This field will be automatically added by post-processing if needed\n\n **CRITICAL: 2-Level Maximum Structure**\n\n Your output MUST follow a maximum 2-level structure. Level 2 nodes should have \\`children: []\\`.\n All primitive elements (single text, links, logos, icons, dividers) go into \\`elementIds\\`, NOT as child components.\n\n Example for ANY section:\n {\n \"id\": \"SectionName\",\n \"data\": {\n \"name\": \"SectionName\",\n \"purpose\": \"Main section description\",\n \"elementIds\": [\"container-id\"],\n \"layout\": {...}\n },\n \"children\": [\n {\n \"id\": \"SubSectionA\",\n \"data\": {\n \"name\": \"SubSectionA\",\n \"purpose\": \"Visual area with links, logos, text\",\n \"elementIds\": [\"all\", \"element\", \"ids\", \"including\", \"links\", \"logos\", \"text\"],\n \"layout\": {...}\n },\n \"children\": [] // MUST be empty - all elements via elementIds\n },\n {\n \"id\": \"SubSectionB\",\n \"data\": {\n \"name\": \"SubSectionB\",\n \"purpose\": \"Another visual area\",\n \"elementIds\": [\"all\", \"element\", \"ids\", \"in\", \"this\", \"area\"],\n \"layout\": {...}\n },\n \"children\": [] // MUST be empty\n }\n ]\n }\n\n For reusable component instances that share the same \\`data.componentName\\` but have different \\`id\\` and \\`data.name\\`, an additional expected example is:\n {\n \"id\": \"TaskCardGrid\",\n \"data\": {\n \"name\": \"TaskCardGrid\",\n \"purpose\": \"Grid container for task cards\",\n \"elementIds\": [\"...\"],\n \"layout\": {\n \"boundingBox\": { \"top\": 0, \"left\": 0, \"width\": 0, \"height\": 0 },\n \"relativeBoundingBox\": { \"top\": 0, \"left\": 0, \"width\": 0, \"height\": 0 },\n \"spacing\": { \"next\": 0 },\n \"layoutDirection\": \"VERTICAL\"\n }\n },\n \"children\": [\n {\n \"id\": \"TaskCard1\",\n \"data\": {\n \"name\": \"TaskCard1\",\n \"componentName\": \"TaskCard\",\n \"purpose\": \"Single task card\",\n \"elementIds\": [\"id1\", \"...\"],\n \"layout\": {\n \"boundingBox\": { \"top\": 0, \"left\": 0, \"width\": 0, \"height\": 0 },\n \"relativeBoundingBox\": { \"top\": 0, \"left\": 0, \"width\": 0, \"height\": 0 },\n \"spacing\": { \"next\": 0 },\n \"layoutDirection\": \"VERTICAL\"\n }\n },\n \"children\": []\n }\n ]\n }\n </output_format>\n</system_instructions>\n`.trim();\n};\n\n/**\n * Prompt template for extracting data list and props schema.\n */\nexport const extractDataListPrompt = (options: { containerName: string; childComponentName: string; figmaData: string }) => {\n const { containerName, childComponentName, figmaData } = options;\n return `\nYou are an expert Frontend Developer.\nYou are analyzing a container component \"${containerName}\" which contains a list of \"${childComponentName}\" components.\n\nYour task is to:\n1. Generate a **props schema** (formal parameter definitions) based on the first component instance\n2. Extract the **data array** (actual parameter values) for all component instances from the provided Figma structure data\n\nContext:\n- Container: ${containerName}\n- Child Component: ${childComponentName}\n- Figma Data:\n${figmaData}\n\nInstructions:\n1. Analyze the \"children\" in the Figma Data. Identify those that are instances of \"${childComponentName}\".\n2. For each instance, extract ALL differing content, including:\n - **Text**: Extract the **EXACT** text content found in the \"characters\" fields. Do NOT summarize or generate placeholders.\n - **Images/Icons**: Identify nodes where \\`type\\` is \"IMAGE\". These nodes will have a \\`url\\` field.\n - If a node has \\`isIcon: true\\` field, or the node name contains \"icon\", or the url ends with \".svg\", use \\`iconSrc\\` as the key.\n - Otherwise, use \\`imageSrc\\` or \\`avatarSrc\\` based on context (e.g., avatar for profile pictures).\n - **Layout/Variants**: \n - If the component has \\`layoutDirection: \"HORIZONTAL\"\\` in the layoutInfo, and contains both text and image content, determine the image position:\n - Check the \\`absoluteBoundingBox\\` positions: if image's x position is less than text's x position, image is on the **left**; otherwise on the **right**.\n - Extract as \\`imagePosition: \"left\"\\` or \\`imagePosition: \"right\"\\` prop.\n - Any other component properties or visual variants (e.g. \"variant\": \"filled\", \"active\": true).\n3. **Normalize the data keys (CRITICAL)**:\n - For text content: use \\`title\\`, \\`description\\`, \\`label\\`, etc.\n - For images/icons: ALWAYS use \\`iconSrc\\`, \\`imageSrc\\`, \\`avatarSrc\\` (with \"Src\" suffix)\n - **DO NOT** use ambiguous keys like \\`icon\\`, \\`image\\`, \\`avatar\\` alone\n - This ensures compatibility with standard React component prop naming conventions.\n - Example:\n \\`\\`\\`json\n {\n \"title\": \"Example Title\",\n \"description\": \"Example description\",\n \"imageSrc\": \"@/assets/actual-filename-from-figma.png\"\n }\n \\`\\`\\`\n4. **Generate Props Schema (CRITICAL)**:\n - Based on the first component instance, infer the prop definitions\n - For each extracted field (e.g., \"title\", \"description\", \"imageSrc\"), determine:\n * **key**: The property name (e.g., \"title\")\n * **type**: The TypeScript type - must be one of: \"string\", \"number\", \"boolean\", \"string[]\", \"number[]\"\n * **description**: A clear description of what this prop represents\n - Return as \"props\" array with objects containing { key, type, description }\n - Example:\n \\`\\`\\`json\n {\n \"key\": \"title\",\n \"type\": \"string\",\n \"description\": \"Card title text\"\n }\n \\`\\`\\`\n5. **CRITICAL Rules**:\n - **USE ACTUAL DATA ONLY**: The example above uses placeholder names. You MUST use the actual \"characters\" and \"url\" values from the Figma Data provided.\n - **NO FIGMA IDs**: Do NOT include Figma node IDs (like \"1:2859\") in the output. Only extract actual content data.\n - **NO PLACEHOLDERS**: Do NOT generate fake text or copy paths from examples. If a node does not have a \"url\" field, do not include an \"imageSrc\" property.\n - **Deep Search**: Text nodes might be nested deeply inside Frames/Groups. Look recursively for \"characters\" fields.\n - **Layout Information**: The Figma Data includes \\`layoutInfo\\` array with \\`layoutDirection\\` and \\`absoluteBoundingBox\\` for each component instance. Use this to determine layout-related props like image position (left/right) in horizontal layouts.\n - **Asset Paths - CRITICAL**: \n - Images are represented by nodes with \\`type: \"IMAGE\"\\`. These nodes MUST have a \\`url\\` field.\n - You MUST use the EXACT value from the \\`url\\` field as the value for \"imageSrc\", \"iconSrc\", or \"avatarSrc\" without any modifications.\n - The \\`url\\` field value MUST be a file path (e.g., \"@/assets/icon-name.svg\").\n - **DO NOT hallucinate or copy paths from the example above.** Every image MUST correspond to a node in the provided Figma Data.\n - CORRECT: If a node has \\`type: \"IMAGE\"\\` and \\`url: \"@/assets/real-image-123.png\"\\`, use exactly that.\n - WRONG: Using \"@/assets/start-2.svg\" if it's not in the input data.\n - If the \\`url\\` field does not exist or does not contain a valid path starting with \"@/assets/\", omit the iconSrc/imageSrc/avatarSrc field entirely.\n6. Return a JSON object with two keys:\n - \"props\": Array of prop definitions with { key, type, description }\n - \"state\": Array of data objects for each component instance\n7. Return ONLY the JSON object. Do not explain.\n\nExample Output JSON Structure (for reference only):\n{\n \"props\": [\n {\n \"key\": \"title\",\n \"type\": \"string\",\n \"description\": \"Card title text\"\n },\n {\n \"key\": \"description\",\n \"type\": \"string\",\n \"description\": \"Card description text\"\n },\n {\n \"key\": \"imageSrc\",\n \"type\": \"string\",\n \"description\": \"Path to card image\"\n }\n ],\n \"state\": [\n {\n \"title\": \"Actual Title 1\",\n \"description\": \"Actual Description 1\",\n \"imageSrc\": \"@/assets/actual-file-1.png\"\n },\n {\n \"title\": \"Actual Title 2\",\n \"description\": \"Actual Description 2\",\n \"imageSrc\": \"@/assets/actual-file-2.png\"\n }\n ]\n}\n`.trim();\n};\n","/**\n * Utility to fetch Figma thumbnail and extract its dimensions\n * Matches the Python reference implementation from evolt\n */\n\nimport axios from 'axios';\nimport { logger } from '../../../utils/logger';\n\nexport interface ThumbnailDimensions {\n width: number;\n height: number;\n}\n\n/**\n * Fetches Figma thumbnail and extracts its dimensions.\n * This ensures the browser viewport matches the Figma thumbnail dimensions,\n * preventing screenshot dimension mismatches.\n *\n * Based on evolt Python implementation: _fetch_figma_thumbnail_with_dimensions()\n *\n * @param figmaThumbnailUrl - Figma thumbnail CDN URL\n * @returns Promise resolving to thumbnail dimensions, or undefined if fetch fails\n *\n * @example\n * ```typescript\n * const dimensions = await fetchThumbnailDimensions(figmaThumbnailUrl);\n * if (dimensions) {\n * const viewport = { width: dimensions.width, height: dimensions.height };\n * // Use viewport for browser launch\n * }\n * ```\n */\nexport async function fetchThumbnailDimensions(figmaThumbnailUrl: string): Promise<ThumbnailDimensions | undefined> {\n if (!figmaThumbnailUrl) {\n return undefined;\n }\n\n try {\n const sharp = (await import('sharp')).default;\n // Fetch the image from Figma CDN\n const response = await axios.get(figmaThumbnailUrl, {\n responseType: 'arraybuffer',\n timeout: 30000,\n });\n\n // Extract dimensions using Sharp\n const imageBuffer = Buffer.from(response.data);\n const metadata = await sharp(imageBuffer).metadata();\n\n if (!metadata.width || !metadata.height) {\n return undefined;\n }\n\n return {\n width: metadata.width,\n height: metadata.height,\n };\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.printWarnLog(`Failed to fetch Figma thumbnail: ${errorMsg}`);\n return undefined;\n }\n}\n","#!/usr/bin/env node\n\n/**\n * CLI Entry Point for Coderio.\n * This file handles command registration, argument parsing, and global error handling for the CLI.\n */\n\n// Save the user's current working directory before any operations\nprocess.env.CODERIO_CLI_USER_CWD = process.cwd();\n\nimport { Command } from 'commander';\nimport { registerCommands } from './init';\nimport { logger } from '../utils/logger';\nimport { registerD2PCommand } from './d2p';\nimport { registerD2CCommand } from './d2c';\nimport { registerImagesCommand } from './images';\nimport { registerP2CCommand } from './p2c';\nimport { registerValidateCommand } from './val';\n\nasync function main(argv: string[]): Promise<void> {\n const program = new Command();\n\n // Register all commands\n registerCommands(program);\n registerD2CCommand(program);\n registerD2PCommand(program);\n registerP2CCommand(program);\n registerImagesCommand(program);\n registerValidateCommand(program);\n\n if (argv.length <= 2) {\n program.help({ error: false });\n return;\n }\n\n // Parse arguments and execute actions\n await program.parseAsync(argv);\n}\n\nmain(process.argv).catch(err => {\n const error = err as Error;\n logger.printErrorLog(`${error.message || String(error)}`);\n process.exit(1);\n});\n","/* Application constants */\n\nexport const CLI_NAME = 'coderio'; // CLI name\nexport const MAX_OUTPUT_TOKENS = 20480; // Max output tokens\n\n/* Unified agent context window token limit */\nexport const AGENT_CONTEXT_WINDOW_TOKENS = 128000;\n","import { Command } from 'commander';\nimport { CLI_NAME } from '../constants';\n\n/* Register all commands to the program */\nexport function registerCommands(program: Command): void {\n const version = typeof __VERSION__ === 'undefined' ? '0.0.1' : __VERSION__;\n program\n .name(CLI_NAME)\n .description(`${CLI_NAME} - Convert Figma designs to code`)\n .version(version, '-v, -V, --version', 'Output the version number')\n .showHelpAfterError();\n}\n","import { tools } from 'evoltagent';\nimport { checkBorder } from './figma';\nimport { FigmaFrameInfo } from '../../types/figma-types';\nimport { ImageNode } from './types';\nimport { executeDownloadImages, fetchImages, findImageNodes } from './images';\nimport { cleanFigma, fetchFigmaNode, fetchFigmaImages } from './figma';\nimport { styleTool } from '../style-tool';\n\n@tools({\n fetchAndClean: {\n description: 'Fetch and clean Figma document from URL',\n params: [\n { name: 'fileId', type: 'string', description: 'Figma file ID' },\n { name: 'nodeId', type: 'string', description: 'Figma node ID' },\n { name: 'token', type: 'string', description: 'Figma API token' },\n ],\n returns: {\n type: 'FigmaFrameInfo',\n description: 'Original Figma document fetched from the URL via official Figma API and cleaned by removing invisible nodes',\n },\n },\n downloadImages: {\n description: 'Detect and download image nodes from figma document',\n params: [\n { name: 'fileId', type: 'string', description: 'Figma file ID' },\n { name: 'token', type: 'string', description: 'Figma API token' },\n { name: 'imageDir', type: 'string', description: 'Output directory path' },\n {\n name: 'document',\n optional: true,\n type: 'FigmaFrameInfo',\n description: 'Figma document which is fetched and cleaned from the URL',\n },\n ],\n returns: {\n type: '{ successCount: number; failCount: number; imageNodesMap: Map<string, ImageNode> }',\n description: 'Download results of images from the Figma document with Map structure',\n },\n },\n simplifyImageNodes: {\n description: 'Simplify image nodes in figma document by replacing redundant properties with url',\n params: [\n { name: 'node', type: 'FigmaFrameInfo', description: 'Figma node' },\n { name: 'imageNodes', type: 'Map<string, ImageNode>', description: 'Image nodes map with id as key' },\n ],\n returns: {\n type: 'FigmaFrameInfo',\n description: 'Figma node with image nodes simplified and replaced with url',\n },\n },\n processedStyle: {\n description: 'Process styles in Figma document',\n params: [{ name: 'node', type: 'FigmaFrameInfo', description: 'Figma node' }],\n returns: {\n type: 'FigmaFrameInfo',\n description: 'Figma node with styles processed',\n },\n },\n})\nclass FigmaTool {\n async fetchAndClean(fileId: string, nodeId: string, token: string): Promise<FigmaFrameInfo | undefined> {\n if (!fileId || !nodeId || !token) {\n return undefined;\n }\n\n const document = await fetchFigmaNode(fileId, nodeId, token);\n if (!document || !document?.children?.length) {\n return undefined;\n }\n\n const images = await fetchFigmaImages(fileId, nodeId, token);\n const thumbnail = images?.[nodeId] || '';\n document.thumbnailUrl = thumbnail;\n\n const cleanedDocument = cleanFigma(document);\n\n return cleanedDocument;\n }\n\n async downloadImages(\n fileId: string,\n token: string,\n imageDir: string,\n document?: FigmaFrameInfo\n ): Promise<{ successCount: number; failCount: number; imageNodesMap: Map<string, ImageNode> }> {\n if (!fileId) {\n return { successCount: 0, failCount: 0, imageNodesMap: new Map() };\n }\n\n /* Detect images from the document */\n const imageNodes = findImageNodes(document?.children || [], document?.absoluteBoundingBox);\n const fetchedImages = await fetchImages(imageNodes, fileId, token);\n if (!fetchedImages.length) {\n return { successCount: 0, failCount: 0, imageNodesMap: new Map() };\n }\n\n return await executeDownloadImages(fetchedImages, imageDir);\n }\n\n simplifyImageNodes(node: FigmaFrameInfo, imageNodes: Map<string, ImageNode>): FigmaFrameInfo {\n const imageTarget = imageNodes.get(node.id);\n\n if (imageTarget) {\n const basicInfo: FigmaFrameInfo = {\n id: node.id,\n name: node.name,\n type: 'IMAGE',\n url: imageTarget.url,\n absoluteBoundingBox: node.absoluteBoundingBox,\n absoluteRenderBounds: node.absoluteRenderBounds,\n };\n\n if (node.cornerRadius) {\n basicInfo.cornerRadius = node.cornerRadius;\n }\n\n if (checkBorder(node)) {\n basicInfo.strokes = node.strokes;\n basicInfo.strokeWeight = node.strokeWeight;\n basicInfo.strokeAlign = node.strokeAlign;\n }\n return basicInfo;\n }\n\n const result: FigmaFrameInfo = { ...node };\n if (node.children && Array.isArray(node.children)) {\n result.children = node.children.map(child => this.simplifyImageNodes(child, imageNodes));\n }\n\n return result;\n }\n\n processedStyle(node: FigmaFrameInfo): FigmaFrameInfo {\n // Convert current node's styles using style-tool\n const processedNode = styleTool.convert(node);\n\n // Recursively process children\n if (processedNode.children && Array.isArray(processedNode.children)) {\n processedNode.children = processedNode.children.map(child => this.processedStyle(child));\n }\n\n return processedNode;\n }\n}\n\nexport const figmaTool = new FigmaTool();\n","import axios, { AxiosRequestConfig } from 'axios';\nimport { getDebugConfig } from './config';\nimport { writeFile } from './file';\nimport { workspaceManager } from './workspace';\n\n/**\n * Save debug log\n */\nfunction saveDebugLog(\n requestInfo: { url: string; config: AxiosRequestConfig },\n responseInfo: { status: number; statusText: string; data: unknown }\n): void {\n const debugConfig = getDebugConfig();\n if (!debugConfig.enabled) {\n return;\n }\n const debugContent = [\n '------------request------------',\n JSON.stringify(requestInfo, null, 2),\n '------------response------------',\n JSON.stringify(responseInfo, null, 2),\n ].join('\\n');\n writeFile(workspaceManager.path?.debug ?? '', `fetch_${new Date().toISOString()}.md`, debugContent);\n}\n\n/**\n * Axios get request with debug logging\n */\nexport async function get<T>(url: string, config?: AxiosRequestConfig<T>): Promise<T> {\n const response = await axios.get<T>(url, config);\n\n saveDebugLog(\n {\n url,\n config: config ?? {},\n },\n {\n status: response.status,\n statusText: response.statusText,\n data: response.data,\n }\n );\n\n return response.data;\n}\n","import { readFileSync, existsSync } from 'fs';\nimport { resolve } from 'path';\nimport { homedir } from 'os';\nimport yaml from 'js-yaml';\n\n// Configuration directory in user's home\nexport const CONFIG_DIR = resolve(homedir(), '.coderio');\nconst CONFIG_FILE = resolve(CONFIG_DIR, 'config.yaml');\n\n/**\n * Model configuration interface\n */\nexport interface ModelConfig {\n provider: string;\n model: string;\n baseUrl: string;\n apiKey: string;\n}\n\n/**\n * Figma configuration interface\n */\nexport interface FigmaConfig {\n token: string;\n}\n\n/**\n * Debug configuration interface\n */\nexport interface DebugConfig {\n enabled: boolean;\n outputDir?: string;\n}\n\n/**\n * Configuration file structure\n */\ninterface Config {\n model: ModelConfig;\n figma: FigmaConfig;\n debug?: DebugConfig;\n}\n\n// Cache for loaded configuration\nlet cachedConfig: Config | null = null;\n\n/**\n * Load configuration from user's config directory\n * The configuration is cached after first load\n * @returns Full configuration object\n */\nexport function loadConfig(): Config {\n if (cachedConfig) {\n return cachedConfig;\n }\n\n if (!existsSync(CONFIG_FILE)) {\n throw new Error(`Configuration file not found at: ${CONFIG_FILE}\\n` + `Please create the configuration file.`);\n }\n\n try {\n const fileContent = readFileSync(CONFIG_FILE, 'utf8');\n const rawConfig = yaml.load(fileContent) as Config;\n\n if (!rawConfig) {\n throw new Error('Invalid config.yaml structure: configuration is empty');\n }\n\n cachedConfig = rawConfig;\n return cachedConfig;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Failed to load config.yaml: ${error.message}`);\n }\n throw error;\n }\n}\n\n/**\n * Get model configuration from config.yaml\n * @returns Model configuration\n * @throws Error if configuration is invalid\n */\nexport function getModelConfig(): ModelConfig {\n const config = loadConfig();\n if (!config.model) {\n throw new Error('Model configuration not found in config.yaml');\n }\n return config.model;\n}\n\n/**\n * Get Figma configuration from config.yaml\n * @returns Figma configuration\n * @throws Error if configuration is invalid\n */\nexport function getFigmaConfig(): FigmaConfig {\n const config = loadConfig();\n if (!config.figma) {\n throw new Error('Figma configuration not found in config.yaml');\n }\n return config.figma;\n}\n\n/**\n * Get debug configuration from config.yaml\n * @returns Debug configuration (defaults to disabled if not specified)\n */\nexport function getDebugConfig(): DebugConfig {\n const config = loadConfig();\n return config.debug || { enabled: false };\n}\n\n/**\n * Get the path to the configuration file\n */\nexport function getConfigPath(): string {\n return CONFIG_FILE;\n}\n\n/**\n * Check if configuration file exists\n */\nexport function configExists(): boolean {\n return existsSync(CONFIG_FILE);\n}\n/**\n * Clear the configuration cache\n * Useful for testing or when configuration needs to be reloaded\n */\nexport function clearConfigCache(): void {\n cachedConfig = null;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { logger } from './logger';\nimport { FileInfo } from '../types/file-types';\n\n/**\n * Write file to the specified path\n * @param filePath - The path to the file\n * @param content - The content to write to the file\n */\nexport const writeFile = (folderPath: string, filePath: string, content: string) => {\n if (!folderPath || !filePath || !content) {\n return;\n }\n if (!fs.existsSync(folderPath)) {\n fs.mkdirSync(folderPath, { recursive: true });\n }\n fs.writeFileSync(path.join(folderPath, filePath), content);\n};\n\n/**\n * Create multiple files from parsed data\n */\nexport function createFiles({ files, filePath }: { files: FileInfo[]; filePath: string }): void {\n try {\n for (const file of files) {\n const dirPath = path.dirname(filePath);\n writeFile(dirPath, file.filename, file.content);\n }\n } catch (error) {\n logger.printErrorLog(`Failed to create files in ${filePath}: ${(error as Error).message}`);\n throw error;\n }\n}\n","import path from 'node:path';\nimport fs from 'node:fs';\nimport { WorkspaceStructure } from '../types/workspace-types';\nimport { logger } from './logger';\n\n/**\n * Defines the logical structure of the output workspace.\n * output directory structure\n coderio/\n └── figmaName/ # Project root directory generated from a Figma URL\n ├── my-app/ # Generated project source code\n ├── process/ # Intermediate data and cache during generation\n │ ├── validation/ # Validation reports, screenshots, and processed.json\n │ └── ... # Other process artifacts\n ├── reports.html # Validation reports summary\n └── checkpoint/ # Cache\n ├── coderio-cli.db \n └── checkpoint.json \n*/\nclass Workspace {\n path: WorkspaceStructure | null = null;\n\n initWorkspace(subPath: string, rootPath?: string, appName?: string): WorkspaceStructure {\n if (this.path) {\n return this.path;\n }\n\n const root = rootPath || (process.env.CODERIO_CLI_USER_CWD ?? process.cwd());\n const coderioRoot = path.join(root, 'coderio');\n const finalRoot = path.resolve(coderioRoot, subPath);\n const app = appName || 'my-app';\n\n const absoluteRoot = path.resolve(finalRoot);\n const processDir = path.join(absoluteRoot, 'process');\n const checkpointDir = path.join(absoluteRoot, 'checkpoint');\n const debugDir = path.join(absoluteRoot, 'debug');\n\n this.path = {\n root: absoluteRoot,\n app: path.join(absoluteRoot, app),\n process: processDir,\n debug: debugDir,\n reports: path.join(absoluteRoot, 'reports.html'),\n db: path.join(checkpointDir, 'coderio-cli.db'),\n checkpoint: path.join(checkpointDir, 'checkpoint.json'),\n };\n return this.path;\n }\n\n /**\n * Delete all files and directories inside the workspace\n */\n deleteWorkspace(workspace: WorkspaceStructure): void {\n try {\n if (fs.existsSync(workspace.root)) {\n // Read all entries in the workspace root\n const entries = fs.readdirSync(workspace.root);\n\n // Delete each entry\n for (const entry of entries) {\n const fullPath = path.join(workspace.root, entry);\n fs.rmSync(fullPath, { recursive: true, force: true });\n }\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.printWarnLog(`Failed to delete workspace: ${errorMessage}`);\n }\n }\n\n /**\n * Resolve the absolute path to the source code directory\n * @param paths - The workspace structure\n * @param srcSubPath - The subpath to the source code directory\n * @returns The absolute path to the source code directory\n */\n resolveAppSrc(paths: WorkspaceStructure, srcSubPath: string): string {\n return path.join(paths.app, 'src', srcSubPath);\n }\n\n /**\n * Resolve component alias path to absolute filesystem path.\n *\n * Handles various path formats:\n * - @/components/Button → /workspace/my-app/src/components/Button/index.tsx\n * - @/src/components/Button → /workspace/my-app/src/components/Button/index.tsx\n * - components/Button → /workspace/my-app/src/components/Button/index.tsx\n *\n */\n resolveComponentPath(aliasPath: string): string {\n // Normalize path separators for robustness across platforms.\n const normalizedAlias = aliasPath.replace(/\\\\/g, '/');\n\n // Step 1: Strip @/ prefix if present\n let relativePath = normalizedAlias.startsWith('@/')\n ? normalizedAlias.substring(2) // '@/components/Button' → 'components/Button'\n : normalizedAlias;\n\n // Step 2: Strip 'src/' prefix if present (resolveAppSrc adds it)\n // '@/src/components/Button' → 'components/Button'\n if (relativePath.startsWith('src/')) {\n relativePath = relativePath.substring(4);\n }\n\n // Step 3: Ensure path ends with /index.tsx (all components follow this convention)\n if (!relativePath.endsWith('.tsx') && !relativePath.endsWith('.ts')) {\n relativePath = `${relativePath}/index.tsx`;\n }\n\n return relativePath;\n }\n}\nexport const workspaceManager = new Workspace();\n","import { FigmaFrameInfo, FigmaImageFormat, FigmaColorObject } from '../../types/figma-types';\nimport { get } from '../../utils/axios';\nimport { logger } from '../../utils/logger';\n\n/**\n * Fetch Figma nodes by fileId and nodeId\n * @param fileId - Figma file ID\n * @param nodeId - Figma node ID\n * @param token - Figma API token\n * @returns Figma frame information\n */\nexport const fetchFigmaNode = async (fileId: string, nodeId: string, token: string): Promise<FigmaFrameInfo | undefined> => {\n const url = `https://api.figma.com/v1/files/${fileId}/nodes?ids=${nodeId}`;\n try {\n const data = await get<{ nodes: Record<string, { document: FigmaFrameInfo }> }>(url, {\n headers: {\n 'X-Figma-Token': token,\n },\n });\n // format node id to match the format in the response\n const resData = data.nodes?.[nodeId];\n return resData?.document;\n } catch (error) {\n logger.printErrorLog(`Failed to fetch Figma node: ${error instanceof Error ? error.message : 'Unknown error'}`);\n return undefined;\n }\n};\n\n/**\n * Fetch Figma image by fileId and nodeId\n * @param fileId - Figma file ID\n * @param nodeIds - Figma node ID, multiple node ids can be passed separated by commas\n * @param token - Figma API token\n * @param format - Figma image format\n * @returns Figma image\n */\nexport const fetchFigmaImages = async (\n fileId: string,\n nodeIds: string,\n token: string,\n format?: FigmaImageFormat\n): Promise<Record<string, string>> => {\n const url = `https://api.figma.com/v1/images/${fileId}`;\n try {\n const data = await get<{ images: Record<string, string> }>(url, {\n headers: {\n 'X-Figma-Token': token,\n },\n params: {\n ids: nodeIds,\n format: format || 'png',\n },\n });\n const images = data.images || {};\n // format node id to match the format from response to request\n return Object.fromEntries(Object.entries(images));\n } catch (error) {\n logger.printErrorLog(`Failed to fetch Figma images: ${error instanceof Error ? error.message : 'Unknown error'}`);\n return {};\n }\n};\n\n/**\n * Clean Figma node and children. Remove invisible nodes and children.\n * @param node - Figma node or children\n * @returns Cleaned Figma node or children. If the node is invisible, return null.\n */\nexport const cleanFigma = (node: FigmaFrameInfo): FigmaFrameInfo | undefined => {\n // if node is invisible, return undefined\n if (node.visible === false) {\n return undefined;\n }\n\n // if node has children, recursively clean each child\n if (node.children && Array.isArray(node.children)) {\n node.children = node.children\n .map(child => cleanFigma(child)) // recursively clean each child\n .filter(child => child !== undefined); // filter out invisible nodes\n }\n\n return node;\n};\n\n/**\n * Check if node has border\n * @param node - Figma node\n * @returns True if node has border, false otherwise\n */\nexport const checkBorder = (node: FigmaFrameInfo): boolean => {\n const strokes = node.strokes;\n const strokeWeight = node.strokeWeight;\n\n if (!strokes || !strokes.length || !strokeWeight) return false;\n\n const visibleStrokes = strokes.filter((s: FigmaColorObject) => s.visible !== false);\n if (visibleStrokes.length === 0) return false;\n\n return true;\n};\n","import { FigmaColorObject, FigmaFrameInfo, FigmaImageFormat, FigmaPositionAndSize } from '../../types/figma-types';\nimport { ImageNode } from './types';\nimport fs from 'fs';\nimport path from 'path';\nimport axios from 'axios';\nimport { promisePool } from '../../utils/promise-pool';\nimport { fetchFigmaImages } from './figma';\nimport { DEFAULT_DOWNLOAD_CONCURRENCY, DOWNLOAD_TIMEOUT_MS, MAX_DOWNLOAD_RETRIES, BASE_RETRY_DELAY_MS } from './constants';\nimport { logger } from '../../utils/logger';\n\n/**\n * Fetch images from figma document\n * @param nodes - Image nodes\n * @param fileId - Figma file ID\n * @param token - Figma API token\n * @returns Image nodes\n */\nexport const fetchImages = async (nodes: ImageNode[], fileId: string, token: string): Promise<ImageNode[]> => {\n if (!fileId || !nodes?.length) {\n return [];\n }\n\n const svgs = nodes.filter(node => node.format === FigmaImageFormat.SVG);\n const pngs = nodes.filter(node => node.format === FigmaImageFormat.PNG);\n const getImagePromises: Promise<{ [key: string]: string } | undefined>[] = [];\n\n if (svgs.length > 0) {\n getImagePromises.push(fetchFigmaImages(fileId, svgs.map(node => node.id).join(','), token, FigmaImageFormat.SVG));\n }\n if (pngs.length > 0) {\n getImagePromises.push(fetchFigmaImages(fileId, pngs.map(node => node.id).join(','), token, FigmaImageFormat.PNG));\n }\n\n const images: ImageNode[] = [];\n const results = await Promise.all(getImagePromises);\n results.forEach((res: { [key: string]: string } | undefined) => {\n if (res) {\n for (const [key, value] of Object.entries(res)) {\n images.push({\n id: key,\n name: '',\n format: FigmaImageFormat.PNG,\n ...(nodes.find(n => n.id === key) || {}),\n url: value || '',\n });\n }\n }\n });\n\n return images;\n};\n\n/**\n * Download images from figma document\n * @param images - Image nodes\n * @param imageDir - Output directory path\n * @param concurrency - Concurrency level\n * @returns Download results\n */\nexport const executeDownloadImages = async (\n images: ImageNode[],\n imageDir?: string,\n concurrency: number = DEFAULT_DOWNLOAD_CONCURRENCY\n): Promise<{ successCount: number; failCount: number; imageNodesMap: Map<string, ImageNode> }> => {\n if (!images || !images.length || !imageDir) {\n return {\n successCount: 0,\n failCount: 0,\n imageNodesMap: new Map(),\n };\n }\n\n // Process all images with dynamic concurrency control using promisePool\n const results = await promisePool(images, image => createDownloadTask(image, imageDir), concurrency);\n\n // Aggregate log after completion\n const successCount = results.filter(r => r.success).length;\n const failCount = results.length - successCount;\n\n // Convert results array to Map with id as key\n const imageNodesMap = new Map<string, ImageNode>(results.map(img => [img.id, img]));\n\n return {\n successCount,\n failCount,\n imageNodesMap,\n };\n};\n\n/**\n * Find image nodes in figma document\n * @param nodes - Figma nodes\n * @param absoluteBoundingBox - Absolute bounding box of the document\n * @returns Image nodes\n */\nexport const findImageNodes = (nodes: FigmaFrameInfo[], absoluteBoundingBox?: FigmaPositionAndSize): ImageNode[] => {\n const imageNodes: ImageNode[] = [];\n if (!nodes || !Array.isArray(nodes)) {\n return imageNodes;\n }\n\n for (const node of nodes) {\n if (node.visible === false) {\n continue;\n }\n // Rule 1: If node type is VECTOR, directly add to imageNodeIds\n else if (node.type === 'VECTOR') {\n imageNodes.push(assignImageObject(node, exportSvgIfNeeded(node, absoluteBoundingBox)));\n }\n // Rule 2: If node type is IMAGE or has imageRef, directly add to imageNodeIds\n else if (isImageNode(node) || isImageNodeViaName(node)) {\n if (isImageNode(node) || hasAnyImageNodeInDescendants(node)) {\n imageNodes.push(assignImageObject(node, FigmaImageFormat.PNG));\n } else {\n imageNodes.push(assignImageObject(node, exportSvgIfNeeded(node, absoluteBoundingBox)));\n }\n } else if (isMaskNode(node)) {\n imageNodes.push(assignImageObject(node, FigmaImageFormat.PNG));\n }\n // Rule 3: For nodes with children, check if any leaf descendant is a TEXT node with characters\n else if (node.children && node.children.length > 0) {\n const hasAnyTextNode = hasAnyTextNodeWithCharacters(node);\n\n if (hasAnyTextNode) {\n const firstLevelChildrenHasImageNode = node.children.some((child: FigmaFrameInfo) => isImageNode(child));\n const firstLevelChildrenHasTextNode = node.children.some((child: FigmaFrameInfo) => isTextNode(child));\n if (firstLevelChildrenHasImageNode && !firstLevelChildrenHasTextNode) {\n imageNodes.push(assignImageObject(node, FigmaImageFormat.PNG));\n } else {\n const childImageIds = findImageNodes(node.children, absoluteBoundingBox);\n imageNodes.push(...childImageIds);\n }\n } else if (hasAnyImageNodeInDescendants(node)) {\n imageNodes.push(assignImageObject(node, FigmaImageFormat.PNG));\n } else {\n imageNodes.push(assignImageObject(node, exportSvgIfNeeded(node, absoluteBoundingBox)));\n }\n }\n }\n\n return imageNodes;\n};\n\n/**\n * Determine whether a node should be exported as SVG or PNG\n * @param node - Figma node\n * @param absoluteBoundingBox - Absolute bounding box of the document\n * @returns Figma image format\n */\nexport const exportSvgIfNeeded = (node: FigmaFrameInfo, absoluteBoundingBox?: FigmaPositionAndSize) => {\n // Rule 1: Check if node is very large (likely a background) -> PNG\n if (node.absoluteBoundingBox && absoluteBoundingBox) {\n const { width, height } = node.absoluteBoundingBox;\n const { width: pageWidth, height: pageHeight } = absoluteBoundingBox;\n if (width >= pageWidth && height >= pageHeight) {\n return FigmaImageFormat.PNG;\n }\n }\n\n // Rule 2: Check exportSettings for explicit format specification\n if (node.exportSettings && node.exportSettings.length > 0) {\n const format = node.exportSettings[0].format;\n if (format === FigmaImageFormat.PNG) {\n return FigmaImageFormat.PNG;\n }\n if (format === FigmaImageFormat.SVG) {\n return FigmaImageFormat.SVG;\n }\n }\n\n // Rule 3: Check node name for background keywords -> PNG\n if (node.name.includes('背景') || node.name.toLowerCase().includes('background')) {\n return FigmaImageFormat.PNG;\n }\n\n // Default: Export as SVG\n return FigmaImageFormat.SVG;\n};\n\n/** Assign image object from figma node and format **/\nexport const assignImageObject = (node: { id: string; name: string }, format: FigmaImageFormat) => {\n return {\n id: node.id,\n name: node.name,\n format,\n };\n};\n\n/** Check if node has image ref in fills **/\nexport const hasImageRefInFills = (node: FigmaFrameInfo): boolean => {\n if (!node || !node.fills || node.fills.length === 0) {\n return false;\n }\n return node.fills.some((fill: FigmaColorObject) => {\n const fillWithImageRef = fill;\n return (fillWithImageRef.imageRef && fillWithImageRef.imageRef !== '') || fillWithImageRef.type === 'IMAGE';\n });\n};\n\n/** Check if node is image node **/\nexport const isImageNode = (node: FigmaFrameInfo): boolean => {\n if (!node) {\n return false;\n }\n\n if (node.type === 'IMAGE') {\n return true;\n }\n\n if (node.fills && node.fills.length > 0) {\n return hasImageRefInFills(node);\n }\n\n return false;\n};\n\n/** Check if node is image node via name **/\nexport const isImageNodeViaName = (node: FigmaFrameInfo): boolean => {\n return (node && node.name.toLowerCase().includes('img')) || node.name.toLowerCase().includes('image');\n};\n\n/** Check if node is mask node **/\nexport const isMaskNode = (node: FigmaFrameInfo): boolean => {\n return node && node.name.toLowerCase().includes('mask');\n};\n\n/** Check if node is text node **/\nexport const isTextNode = (node: FigmaFrameInfo): boolean => {\n return node && node.type === 'TEXT' && node.characters !== undefined && node.characters.trim() !== '';\n};\n\n/** Check if node has any image node in descendants **/\nexport const hasAnyImageNodeInDescendants = (node: FigmaFrameInfo): boolean => {\n if (!node) return false;\n\n if (!node.children || node.children.length === 0) {\n return isImageNode(node);\n }\n return node.children.some((child: FigmaFrameInfo) => hasAnyImageNodeInDescendants(child));\n};\n\n/** Check if node has any text node in descendants **/\nexport const hasAnyTextNodeWithCharacters = (node: FigmaFrameInfo): boolean => {\n if (!node) return false;\n\n if (!node.children || node.children.length === 0) {\n return isTextNode(node);\n }\n return node.children.some((child: FigmaFrameInfo) => hasAnyTextNodeWithCharacters(child));\n};\n\n/**\n * Download an image from URL and save to local directory\n * @param url - Image URL to download\n * @param filename - Local filename (with extension)\n * @param outputDir - Output directory path\n * @returns Local file path\n */\nexport async function downloadImage(url: string, filename?: string, imageDir?: string, base64?: boolean): Promise<string> {\n if (!url || (!base64 && (!filename || !imageDir))) {\n return '';\n }\n\n const maxRetries = MAX_DOWNLOAD_RETRIES;\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const response = await axios.get(url, {\n responseType: 'arraybuffer',\n timeout: DOWNLOAD_TIMEOUT_MS,\n });\n\n if (base64) {\n return Buffer.from(response.data).toString('base64');\n } else {\n if (!imageDir || !filename) {\n return '';\n }\n // Create directory if it doesn't exist\n if (!fs.existsSync(imageDir)) {\n fs.mkdirSync(imageDir, { recursive: true });\n }\n const filepath = path.join(imageDir, filename);\n fs.writeFileSync(filepath, Buffer.from(response.data));\n return filepath;\n }\n } catch (error) {\n lastError = error;\n // Don't wait on the last attempt\n if (attempt < maxRetries) {\n // Wait 1s, 2s, 3s, 4s, 5s\n const delay = BASE_RETRY_DELAY_MS * (attempt + 1);\n await new Promise(resolve => setTimeout(resolve, delay));\n }\n }\n }\n\n const errorMessage = lastError instanceof Error ? lastError.message : String(lastError);\n throw new Error(`Failed to download image from ${url} after ${maxRetries} retries: ${errorMessage}`);\n}\n\n/**\n * Create download task for image\n * @param image - Image object\n * @param outputDir - Output directory path\n * @returns Download task object\n */\nexport const createDownloadTask = async (image: ImageNode, imageDir?: string): Promise<ImageNode> => {\n if (!image.url) {\n return {\n id: image.id,\n name: image.name,\n format: image.format,\n url: image.url,\n remote: image.url,\n success: false,\n };\n }\n\n const ext = image.format || FigmaImageFormat.PNG;\n // Sanitize filename: remove special characters, replace spaces with dashes\n const sanitizedName = (image.name || image.id).replace(/[^a-zA-Z0-9-_]/g, '-').toLowerCase();\n const filename = `${sanitizedName}-${image.id.replace(/:/g, '-')}.${ext}`;\n\n try {\n const localPath = await downloadImage(image.url, filename, imageDir);\n const normalizedImageDir = imageDir ? path.normalize(imageDir) : '';\n const dirParts = normalizedImageDir.split(path.sep).filter(Boolean);\n const srcIndex = dirParts.lastIndexOf('src');\n const srcDir =\n srcIndex >= 0 ? (normalizedImageDir.startsWith(path.sep) ? path.sep : '') + path.join(...dirParts.slice(0, srcIndex + 1)) : '';\n\n const relativeFromSrc = srcDir ? path.relative(srcDir, localPath) : '';\n const normalizedRelative = relativeFromSrc.split(path.sep).join('/');\n const aliasPath = `@/${normalizedRelative}`;\n\n return {\n id: image.id,\n name: image.name,\n format: image.format,\n url: aliasPath,\n remote: image.url,\n success: true,\n };\n } catch {\n logger.printErrorLog(`Failed to download image: ${image.url}`);\n return {\n id: image.id,\n name: image.name,\n format: image.format,\n url: image.url,\n remote: image.url,\n success: false,\n };\n }\n};\n","/**\n * Run multiple asynchronous tasks with a concurrency limit.\n *\n * @param items - Array of items to process\n * @param taskGenerator - Function that creates a promise for a single item\n * @param concurrency - Maximum number of concurrent tasks\n * @returns Array of results\n */\nexport async function promisePool<T, R>(items: T[], taskGenerator: (item: T) => Promise<R>, concurrency: number = 5): Promise<R[]> {\n if (!items || !items.length) {\n return [];\n }\n const results: R[] = [];\n let nextIndex = 0;\n const executing = new Set<Promise<void>>();\n\n const processTask = async (index: number) => {\n const item = items[index];\n if (!item) {\n results[index] = undefined as unknown as R;\n return;\n }\n const result = await taskGenerator(item);\n results[index] = result;\n };\n\n while (nextIndex < items.length || executing.size > 0) {\n while (nextIndex < items.length && executing.size < concurrency) {\n const index = nextIndex++;\n const promise = processTask(index).finally(() => {\n executing.delete(promise);\n });\n executing.add(promise);\n }\n\n if (executing.size > 0) {\n await Promise.race(executing);\n }\n }\n\n return results;\n}\n","export const MAX_DOWNLOAD_RETRIES = 5; // Maximum number of download retries\nexport const DOWNLOAD_TIMEOUT_MS = 60000; // Download timeout in milliseconds\nexport const BASE_RETRY_DELAY_MS = 1000; // Base retry delay in milliseconds\nexport const DEFAULT_DOWNLOAD_CONCURRENCY = 5; // Default download concurrency\n","import { tools } from 'evoltagent';\nimport { CSSStyles, FigmaFrameInfo } from '../../types/figma-types';\nimport { convertBorderRadius, convertEffects, convertFills, convertStrokes, convertClipContent } from './utils';\n\n@tools({\n convert: {\n description: 'Convert Figma properties to CSS styles, remove redundant properties, and return the processed Figma node',\n params: [{ name: 'node', type: 'FigmaFrameInfo', description: 'Figma node' }],\n returns: {\n type: 'CSSStyles',\n description: 'CSS styles converted from Figma properties',\n },\n },\n})\nclass StyleTool {\n convert(node: FigmaFrameInfo): FigmaFrameInfo {\n const inlineStyles: CSSStyles = {};\n\n if (node.type !== 'TEXT') {\n convertBorderRadius(node, inlineStyles);\n convertEffects(node, inlineStyles);\n convertFills(node, inlineStyles);\n convertStrokes(node, inlineStyles);\n convertClipContent(node, inlineStyles);\n }\n\n // Create processed node with styles\n const processedNode: FigmaFrameInfo = {\n ...node,\n inlineStyles,\n };\n\n // Remove converted fields to reduce data size\n if (node.type !== 'TEXT') {\n const nodeWithOptionalStyles = processedNode as Partial<FigmaFrameInfo> & Record<string, unknown>;\n delete nodeWithOptionalStyles.fills;\n delete nodeWithOptionalStyles.background;\n delete nodeWithOptionalStyles.strokes;\n delete nodeWithOptionalStyles.strokeAlign;\n delete nodeWithOptionalStyles.backgroundColor;\n delete nodeWithOptionalStyles.cornerRadius;\n delete nodeWithOptionalStyles.rectangleCornerRadii;\n delete nodeWithOptionalStyles.effects;\n // delete nodeWithOptionalStyles.absoluteRenderBounds;\n delete nodeWithOptionalStyles.style;\n }\n return processedNode;\n }\n}\n\nexport const styleTool = new StyleTool();\n","/**\n * Color Converter\n * Convert Figma color objects (SOLID, GRADIENT_LINEAR, GRADIENT_RADIAL) to CSS color strings\n */\nimport { FigmaColorObject, FigmaColor, FigmaGradientStop } from '../../types/figma-types';\n\nexport class ColorConverter {\n // Main conversion entry point\n static convert(colorObject: FigmaColorObject): string {\n if (!colorObject) return 'transparent';\n\n const type = colorObject.type;\n\n switch (type) {\n case 'SOLID':\n return this.convertSolid(colorObject);\n case 'GRADIENT_LINEAR':\n return this.convertLinearGradient(colorObject);\n case 'GRADIENT_RADIAL':\n return this.convertRadialGradient(colorObject);\n default:\n return 'transparent';\n }\n }\n\n // Convert SOLID fill to rgba/rgb string\n private static convertSolid(fill: FigmaColorObject): string {\n if (!fill.color) return 'transparent';\n\n const opacity = this.getOpacity(fill.opacity);\n return this.rgbaToString(fill.color, opacity);\n }\n\n // Convert linear gradient to CSS linear-gradient\n private static convertLinearGradient(fill: FigmaColorObject): string {\n const stops = fill.gradientStops || [];\n const handles = fill.gradientHandlePositions || [];\n const fillOpacity = this.getOpacity(fill.opacity);\n\n if (stops.length === 0) return 'transparent';\n\n // Calculate gradient angle\n const angle = handles.length >= 2 ? this.calculateLinearGradientAngle(handles) : 180;\n\n // Calculate gradient stops with positions\n const stopsWithPositions = this.calculateLinearGradientStops(stops, handles, fillOpacity);\n\n return `linear-gradient(${angle}deg, ${stopsWithPositions})`;\n }\n\n // Convert radial gradient to CSS radial-gradient\n private static convertRadialGradient(fill: FigmaColorObject): string {\n const stops = fill.gradientStops || [];\n const handles = fill.gradientHandlePositions || [];\n const fillOpacity = this.getOpacity(fill.opacity);\n\n if (stops.length === 0) return 'transparent';\n\n // Calculate radial gradient parameters\n const { size, position } = this.calculateRadialGradientParams(handles);\n\n // Convert stops\n const stopsStr = stops\n .map(stop => {\n const color = this.rgbaToString(stop.color, fillOpacity);\n const pos = Math.round(stop.position * 100);\n return `${color} ${pos}%`;\n })\n .join(', ');\n\n return `radial-gradient(${size} at ${position}, ${stopsStr})`;\n }\n\n private static getOpacity(opacity?: number): number {\n return opacity !== undefined ? opacity : 1;\n }\n\n // Helper: Convert Figma color to CSS rgba/rgb/hex string\n static rgbaToString(color: FigmaColor, opacity: number = 1): string {\n if (!color) return 'transparent';\n\n const r = Math.round((color.r || 0) * 255);\n const g = Math.round((color.g || 0) * 255);\n const b = Math.round((color.b || 0) * 255);\n const a = (color.a !== undefined ? color.a : 1) * (opacity !== undefined ? opacity : 1);\n\n // Use hex format when fully opaque, rgba when transparent\n if (Math.abs(a - 1) < 0.001) {\n // Fully opaque - use hex format\n if (r === 255 && g === 255 && b === 255) return '#FFF';\n if (r === 0 && g === 0 && b === 0) return '#000';\n // Convert to hex\n const toHex = (n: number) => n.toString(16).toUpperCase().padStart(2, '0');\n return `#${toHex(r)}${toHex(g)}${toHex(b)}`;\n }\n\n // Transparent - use rgba with proper formatting\n const alphaStr = a !== undefined ? a.toFixed(2) : '1';\n return `rgba(${r}, ${g}, ${b}, ${alphaStr})`;\n }\n\n /**\n * Calculate CSS gradient angle from Figma gradient handle positions\n * Figma uses a transform matrix system with 3 points:\n * - p0: gradient origin\n * - p1: gradient direction endpoint (color changes from p0 to p1)\n * - p2: perpendicular direction endpoint\n *\n * Formula: CSS angle = atan2(v1) + angleBetween(v1, v2)\n * where v1 = p1-p0, v2 = p2-p0\n */\n private static calculateLinearGradientAngle(positions: { x: number; y: number }[]): number {\n if (positions.length < 2) return 180;\n\n const [p0, p1, p2] = positions;\n\n if (!p0 || !p1) return 180;\n\n // Vector v1: gradient direction (p0 → p1)\n const v1x = p1.x - p0.x;\n const v1y = p1.y - p0.y;\n const len1 = Math.sqrt(v1x * v1x + v1y * v1y);\n\n // Calculate angle of v1\n const angle1Rad = Math.atan2(v1y, v1x);\n const angle1Deg = angle1Rad * (180 / Math.PI);\n\n // If we don't have p2, use simple formula\n if (!p2 || positions.length < 3) {\n let cssAngle = angle1Deg + 90;\n while (cssAngle < 0) cssAngle += 360;\n while (cssAngle >= 360) cssAngle -= 360;\n return Math.round(cssAngle);\n }\n\n // Vector v2: perpendicular reference (p0 → p2)\n const v2x = p2.x - p0.x;\n const v2y = p2.y - p0.y;\n const len2 = Math.sqrt(v2x * v2x + v2y * v2y);\n\n // Calculate angle between v1 and v2\n const dot = v1x * v2x + v1y * v2y;\n const cosAngle = Math.max(-1, Math.min(1, dot / (len1 * len2)));\n const angleBetweenRad = Math.acos(cosAngle);\n const angleBetweenDeg = angleBetweenRad * (180 / Math.PI);\n\n // CSS angle = angle1 + angleBetween\n let cssAngle = angle1Deg + angleBetweenDeg;\n\n // Normalize to 0-360 range\n while (cssAngle < 0) {\n cssAngle += 360;\n }\n while (cssAngle >= 360) {\n cssAngle -= 360;\n }\n\n return Math.round(cssAngle);\n }\n\n /**\n * Calculate gradient stops with correct positions\n * Based on Figma's gradient handle positions and transform matrix\n */\n private static calculateLinearGradientStops(\n stops: FigmaGradientStop[],\n handles: { x: number; y: number }[],\n fillOpacity: number\n ): string {\n if (handles.length < 2) {\n // Fallback: simple position mapping\n return stops\n .map(stop => {\n const color = this.rgbaToString(stop.color, fillOpacity);\n const position = Math.round(stop.position * 100);\n // Format: remove .00 for whole numbers\n const posStr = position === 0 ? '0%' : `${position}%`;\n return `${color} ${posStr}`;\n })\n .join(', ');\n }\n\n const [p0, p1] = handles;\n\n if (!p0 || !p1) {\n return stops\n .map(stop => {\n const color = this.rgbaToString(stop.color, fillOpacity);\n const position = Math.round(stop.position * 100);\n const posStr = position === 0 ? '0%' : `${position}%`;\n return `${color} ${posStr}`;\n })\n .join(', ');\n }\n\n // Transform matrix vectors\n const m1x = p1.x - p0.x;\n const m1y = p1.y - p0.y;\n\n // Gradient length\n const gradientLength = Math.sqrt(m1x * m1x + m1y * m1y);\n\n if (gradientLength === 0) {\n return stops\n .map(stop => {\n const color = this.rgbaToString(stop.color, fillOpacity);\n const position = Math.round(stop.position * 100);\n const posStr = position === 0 ? '0%' : `${position}%`;\n return `${color} ${posStr}`;\n })\n .join(', ');\n }\n\n // Get CSS angle\n const cssAngle = this.calculateLinearGradientAngle(handles);\n const cssAngleRad = (cssAngle * Math.PI) / 180;\n\n // CSS gradient direction vector\n const gradDirX = Math.sin(cssAngleRad);\n const gradDirY = -Math.cos(cssAngleRad);\n\n // Project box corners onto gradient direction\n const corners = [\n { x: 0, y: 0 },\n { x: 1, y: 0 },\n { x: 0, y: 1 },\n { x: 1, y: 1 },\n ];\n\n const projections = corners.map(c => c.x * gradDirX + c.y * gradDirY);\n const minProj = Math.min(...projections);\n const maxProj = Math.max(...projections);\n const projRange = maxProj - minProj;\n\n // Calculate stop positions\n return stops\n .map(stop => {\n const color = this.rgbaToString(stop.color, fillOpacity);\n\n // Point on gradient line at this stop\n const pointX = p0.x + stop.position * m1x;\n const pointY = p0.y + stop.position * m1y;\n\n // Project onto CSS gradient direction\n const projection = pointX * gradDirX + pointY * gradDirY;\n\n // Convert to percentage\n let cssPosition = ((projection - minProj) / projRange) * 100;\n\n // Round to 2 decimal places then format\n cssPosition = cssPosition !== undefined ? Math.round(cssPosition * 100) / 100 : 0;\n\n // Format position string\n let posStr: string;\n if (cssPosition === 0) {\n posStr = '0%';\n } else if (Number.isInteger(cssPosition)) {\n posStr = `${cssPosition}%`;\n } else {\n posStr = `${cssPosition.toFixed(2)}%`;\n }\n\n return `${color} ${posStr}`;\n })\n .join(', ');\n }\n\n // Calculate radial gradient parameters from handle positions\n private static calculateRadialGradientParams(handles: { x: number; y: number }[]): {\n size: string;\n position: string;\n } {\n if (handles.length < 2) {\n return { size: 'circle', position: '50% 50%' };\n }\n\n const [center, edge, perpendicular] = handles;\n\n if (!center || !edge || !perpendicular) {\n return { size: 'circle', position: '50% 50%' };\n }\n\n // Calculate radius as distance from center to edge\n const dx = edge.x - center.x;\n const dy = edge.y - center.y;\n const radiusX = Math.sqrt(dx * dx + dy * dy);\n\n // Calculate perpendicular radius if third handle exists\n let radiusY = radiusX;\n if (perpendicular) {\n const pdx = perpendicular.x - center.x;\n const pdy = perpendicular.y - center.y;\n radiusY = Math.sqrt(pdx * pdx + pdy * pdy);\n }\n\n // Convert center position to percentage\n const centerX = center.x !== undefined ? (center.x * 100).toFixed(2) : '0';\n const centerY = center.y !== undefined ? (center.y * 100).toFixed(2) : '0';\n\n // Calculate size\n const sizeX = radiusX !== undefined ? (radiusX * 100).toFixed(2) : '0';\n const sizeY = radiusY !== undefined ? (radiusY * 100).toFixed(2) : '0';\n\n return {\n size: `${sizeY}% ${sizeX}%`,\n position: `${centerX}% ${centerY}%`,\n };\n }\n\n // Convert SOLID fill to linear-gradient format (for layering multiple fills)\n static solidToGradient(fill: FigmaColorObject): string {\n const color = this.convertSolid(fill);\n return `linear-gradient(0deg, ${color} 0%, ${color} 100%)`;\n }\n}\n","import { CSSStyles, FigmaColorObject, FigmaFrameInfo } from '../../types/figma-types';\nimport { ColorConverter } from './color';\n\n// Convert border radius\nexport const convertBorderRadius = (node: FigmaFrameInfo, inlineStyles: CSSStyles): void => {\n if (node.cornerRadius !== undefined) {\n inlineStyles.borderRadius = `${node.cornerRadius}px`;\n }\n\n // Individual corner radius\n if (node.rectangleCornerRadii) {\n const [tl, tr, br, bl] = node.rectangleCornerRadii;\n inlineStyles.borderRadius = `${tl}px ${tr}px ${br}px ${bl}px`;\n }\n};\n\n// Convert effects (shadow, filter,backdrop-filter)\nexport const convertEffects = (node: FigmaFrameInfo, inlineStyles: CSSStyles): void => {\n const effects = node.effects;\n\n if (!effects || effects.length === 0) return;\n\n const shadows: string[] = [];\n const filters: string[] = [];\n const backdropFilters: string[] = [];\n\n for (const effect of effects) {\n if (effect.visible === false) continue;\n\n if (effect.type === 'DROP_SHADOW') {\n const x = effect.offset?.x || 0;\n const y = effect.offset?.y || 0;\n const blur = effect.radius || 0;\n const spread = effect.spread || 0;\n // Use ColorConverter for shadow color\n const color = effect.color ? ColorConverter.convert({ type: 'SOLID', color: effect.color }) : 'rgba(0, 0, 0, 0.25)';\n\n shadows.push(`${x.toFixed(0)}px ${y.toFixed(0)}px ${(blur / 2).toFixed(0)}px ${spread.toFixed(0)}px ${color}`);\n } else if (effect.type === 'INNER_SHADOW') {\n const x = effect.offset?.x || 0;\n const y = effect.offset?.y || 0;\n const blur = effect.radius || 0;\n const spread = effect.spread || 0;\n const color = effect.color ? ColorConverter.convert({ type: 'SOLID', color: effect.color }) : 'rgba(0, 0, 0, 0.25)';\n\n shadows.push(`inset ${x.toFixed(0)}px ${y.toFixed(0)}px ${(blur / 2).toFixed(0)}px ${spread.toFixed(0)}px ${color}`);\n } else if (effect.type === 'LAYER_BLUR') {\n const blur = effect.radius || 0;\n filters.push(`blur(${(blur / 2).toFixed(0)}px)`);\n } else if (effect.type === 'BACKGROUND_BLUR') {\n const blur = effect.radius || 0;\n backdropFilters.push(`blur(${(blur / 2).toFixed(0)}px)`);\n }\n }\n\n if (shadows.length > 0) {\n inlineStyles.boxShadow = shadows.join(', ');\n }\n\n if (filters.length > 0) {\n inlineStyles.filter = filters.join(' ');\n }\n\n if (backdropFilters.length > 0) {\n inlineStyles.backdropFilter = backdropFilters.join(', ');\n }\n};\n\n// Convert fills to background\n// Handles multiple fills and creates layered backgrounds\nexport const convertFills = (node: FigmaFrameInfo, inlineStyles: CSSStyles): void => {\n const fills = node.fills || node.background;\n\n if (!fills || fills.length === 0) return;\n\n // Filter visible fills\n const visibleFills = fills.filter((fill: FigmaColorObject) => fill.visible !== false);\n if (visibleFills.length === 0) return;\n\n // Convert all fills to CSS\n // For multiple fills, convert SOLID to gradient format for proper layering\n const backgrounds: string[] = visibleFills.map((fill: FigmaColorObject) => {\n if (fill.type === 'SOLID' && visibleFills.length > 1) {\n return ColorConverter.solidToGradient(fill);\n }\n return ColorConverter.convert(fill);\n });\n\n // IMPORTANT: Reverse the array!\n // Figma fills: index 0 = top layer\n // CSS background: first declared = top layer\n // But Figma's rendering order is bottom-to-top in the fills array\n // So we need to reverse to match CSS rendering order\n backgrounds.reverse();\n\n // Set background with all layers\n inlineStyles.background = backgrounds.join(', ');\n};\n\n// Convert strokes to border\nexport const convertStrokes = (node: FigmaFrameInfo, inlineStyles: CSSStyles): void => {\n const strokes = node.strokes;\n\n if (!strokes || strokes.length === 0 || !node.strokeWeight) return;\n\n const visibleStrokes = strokes.filter((s: FigmaColorObject) => s.visible !== false);\n if (visibleStrokes.length === 0) return;\n\n const width = node.strokeWeight || 1;\n let strokeColor = '';\n const isGradientStroke = visibleStrokes.some((s: FigmaColorObject) => s.type.includes('GRADIENT'));\n if (isGradientStroke) {\n const gradient = visibleStrokes.find((s: FigmaColorObject) => s.type.includes('GRADIENT'));\n if (gradient) {\n strokeColor = ColorConverter.convert(gradient);\n }\n inlineStyles.strokeColor = strokeColor;\n inlineStyles.borderRadius = `${node.cornerRadius !== undefined ? node.cornerRadius.toFixed(0) : '0'}px`;\n inlineStyles.strokeWidth = `${width}px`;\n } else {\n const solid = visibleStrokes.find((s: FigmaColorObject) => s.type === 'SOLID');\n if (solid) {\n strokeColor = ColorConverter.convert(solid);\n }\n inlineStyles.border = `${width}px solid ${strokeColor}`;\n }\n};\n\n// Convert clip content\nexport const convertClipContent = (node: FigmaFrameInfo, inlineStyles: CSSStyles): void => {\n if (node.clipsContent) {\n inlineStyles.overflow = 'hidden';\n }\n};\n","import { GraphState } from '../../state';\nimport { figmaTool } from '../../tools/figma-tool';\nimport { FigmaFrameInfo, FigmaUrlInfo } from '../../types/figma-types';\nimport { getFigmaConfig } from '../../utils/config';\nimport { writeFile } from '../../utils/file';\nimport { logger } from '../../utils/logger';\nimport { generateStructure } from './structure';\nimport { ImageNode } from '../../tools/figma-tool/types';\nimport { workspaceManager } from '../../utils/workspace';\n\n/**\n * 'process' node, responsible for generating the protocol for frontend code generation.\n *\n * This function serves as a unified workflow that can be consumed by:\n * 1. LangGraph Node: As part of the design2code graph workflow\n * 2. CLI Command: `f2p` (figma2protocol) - full protocol generation\n * 3. CLI Command: `images` (get-images) - partial workflow (fetch + download only)\n * 4. Script Execution: Direct execution via tsx/node\n *\n * Workflow Steps:\n * - Step 1: Fetch and clean Figma document from API\n * - Step 2: Detect and download images from Figma document\n * - Step 3: Simplify image nodes by replacing properties with URLs\n * - Step 4: Process styles (convert Figma styles to CSS)\n * - Step 5: Write protocol.json and images.json to workspace\n * @param state - The state of the graph.\n * @returns The state of the graph.\n */\nexport const generateProtocol = async (state: GraphState) => {\n const assetsDir = workspaceManager.resolveAppSrc(state.workspace, 'assets');\n const processDir = state.workspace.process;\n const { document, imageNodesMap } = await executeFigmaAndImagesActions(state.urlInfo, assetsDir, processDir);\n\n /* Simplify image nodes in Figma document by replacing redundant properties with url */\n const simplifiedDocument = figmaTool.simplifyImageNodes(document, imageNodesMap);\n /* Process styles (convert Figma styles to CSS) */\n const processedStyleDocument = figmaTool.processedStyle(simplifiedDocument);\n /* Generate structure */\n const protocol = await generateStructure(processedStyleDocument);\n\n // Write protocol.json (contains all Figma data in data.elements)\n writeFile(state.workspace.process, 'protocol.json', JSON.stringify(protocol, null, 2));\n logger.printInfoLog(`Please check the output in the workspace: ${state.workspace.process}`);\n\n return {\n protocol,\n figmaInfo: {\n thumbnail: processedStyleDocument?.thumbnailUrl || document?.thumbnailUrl || '',\n },\n };\n};\n\n/**\n * Executes the Figma and images actions.\n * @param state - The state of the graph.\n * @returns The state of the graph with imageNodesMap as Map<string, ImageNode>.\n */\nexport const executeFigmaAndImagesActions = async (\n urlInfo: FigmaUrlInfo,\n assetsDir: string,\n processDir: string\n): Promise<{ document: FigmaFrameInfo; imageNodesMap: Map<string, ImageNode> }> => {\n const { fileId, nodeId } = urlInfo;\n if (!fileId || !nodeId) {\n throw new Error('Invalid Figma URL');\n }\n\n const token = getFigmaConfig().token;\n if (!token) {\n throw new Error('Figma API token is required');\n }\n\n /* Fetch and clean Figma document */\n const document = await figmaTool.fetchAndClean(fileId, nodeId, token);\n if (!document) {\n throw new Error('Failed to fetch and clean Figma document');\n }\n writeFile(processDir, 'figma.json', JSON.stringify(document, null, 2));\n logger.printSuccessLog(`Figma document fetched and cleaned successfully`);\n\n /* Detect and download images from Figma document */\n const downloadResult: { successCount: number; failCount: number; imageNodesMap: Map<string, ImageNode> } =\n await figmaTool.downloadImages(fileId, token, assetsDir, document);\n const { successCount, failCount, imageNodesMap } = downloadResult;\n\n if (successCount) {\n logger.printSuccessLog(`Downloaded ${successCount} images`);\n }\n if (failCount) {\n logger.printWarnLog(`Failed to download ${failCount} images`);\n }\n\n /* Write images.json with array format for JSON compatibility */\n const resultsArray = Array.from(imageNodesMap.values());\n writeFile(processDir, 'images.json', JSON.stringify(resultsArray, null, 2));\n\n return {\n document,\n imageNodesMap,\n };\n};\n","import { HumanMessage } from '@langchain/core/messages';\nimport { ChatOpenAI } from '@langchain/openai';\nimport { logger } from './logger';\nimport { getDebugConfig, getModelConfig, type ModelConfig } from './config';\nimport { writeFile } from './file';\nimport { workspaceManager } from './workspace';\n\n/**\n * Content part types for multimodal messages\n */\ntype ContentPart = { type: 'text'; text: string } | { type: 'image_url'; image_url: { url: string } };\n\n/**\n * Options for calling the model\n */\nexport interface CallModelOptions {\n question: string;\n imageUrls?: string | string[];\n streaming?: boolean;\n responseFormat?: { type: 'json_object' | 'text' };\n maxTokens?: number;\n}\n\n/**\n * Validate model configuration\n * @param config - Model configuration to validate\n * @throws Error if required fields are missing\n */\nfunction validateModelConfig(config: ModelConfig | null | undefined): asserts config is ModelConfig {\n if (!config || !config.provider || !config.model || !config.baseUrl || !config.apiKey) {\n throw new Error(\n `Invalid model configuration. Required fields: provider, model, baseUrl, apiKey. Please check your config.yaml file.`\n );\n }\n}\n\n/**\n * Call an LLM model with the given options\n * @param options - Configuration options for the model call\n * @returns The model's text response\n */\nexport async function callModel(options: CallModelOptions): Promise<string> {\n const { question, imageUrls, streaming = false, responseFormat, maxTokens } = options;\n\n // Validate input\n if (!question || !question.trim()) {\n throw new Error('Question must be a non-empty string');\n }\n\n // Get and validate config separately\n let config: ModelConfig;\n try {\n config = getModelConfig();\n validateModelConfig(config);\n } catch (error) {\n if (error instanceof Error) {\n logger.printErrorLog(`Configuration error: ${error.message}`);\n }\n throw error;\n }\n\n try {\n const requestConfig = {\n modelName: config.model,\n apiKey: config.apiKey,\n configuration: {\n baseURL: config.baseUrl,\n },\n ...(maxTokens && { maxTokens }),\n temperature: 0.1,\n streaming,\n ...(streaming && {\n streamingOptions: {\n includeUsage: true,\n },\n }),\n ...(!streaming && { streamUsage: true }),\n ...(responseFormat && { modelKwargs: { response_format: responseFormat } }),\n };\n const agentModel = new ChatOpenAI(requestConfig);\n\n // Build multimodal content parts: text + image_url\n const contentParts: ContentPart[] = [];\n contentParts.push({ type: 'text', text: question });\n\n // Add images if provided\n if (imageUrls) {\n const urls = Array.isArray(imageUrls) ? imageUrls : [imageUrls];\n for (const url of urls) {\n if (url && typeof url === 'string' && url.trim()) {\n contentParts.push({ type: 'image_url', image_url: { url: url.trim() } });\n }\n }\n }\n\n // Create user message - use array if multimodal, string if text-only\n const userMessage = new HumanMessage({\n content: contentParts.length > 1 ? contentParts : question,\n });\n\n const message = await agentModel.invoke([userMessage]);\n\n if (!message.text) {\n throw new Error('Model returned empty response');\n }\n\n const debugConfig = getDebugConfig();\n const isDebugEnabled = debugConfig.enabled;\n if (isDebugEnabled) {\n const debugContent = [\n '------------config------------',\n JSON.stringify(requestConfig, null, 2),\n '------------request------------',\n JSON.stringify(contentParts, null, 2),\n '------------response------------',\n JSON.stringify(message.text, null, 2),\n ].join('\\n');\n writeFile(workspaceManager.path?.debug ?? '', `model_${new Date().toISOString()}.md`, debugContent);\n }\n\n return message.text;\n } catch (error) {\n if (error instanceof Error) {\n logger.printErrorLog(`[${config.model}] Error details: ${error.message}`);\n if (error.stack) {\n logger.printTestLog(`[${config.model}] Stack trace: ${error.stack}`);\n }\n }\n throw new Error(`${config.model} model request failed: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n}\n","import type { FigmaFrameInfo } from '../../../types/figma-types';\nimport type { Protocol } from '../../../types';\nimport { callModel } from '../../../utils/call-model';\nimport { logger } from '../../../utils/logger';\nimport { generateStructurePrompt } from './prompt';\nimport { extractNodePositionsHierarchical, postProcessStructure, populateComponentProps } from './utils';\nimport { extractJSON } from '../../../utils/parser';\n\n/**\n * Structure node - generates component hierarchy from Figma design\n *\n * Responsibilities:\n * 1. Analyzes Figma frame structure using AI model\n * 2. Extracts component relationships and data\n * 3. Generates file paths and naming conventions\n * 4. Populates component props and states for code generation\n *\n * @param state - Current graph state\n * @returns Updated state with protocol\n */\nexport const generateStructure = async (figma: FigmaFrameInfo) => {\n const frames = figma.frames || figma.children;\n const imageWidth = figma.absoluteBoundingBox?.width;\n const thumbnailUrl = figma.thumbnailUrl;\n\n if (!frames || frames.length === 0) {\n logger.printErrorLog('No processed frames found in state');\n throw new Error('No processed frames found');\n }\n\n logger.printInfoLog('Starting structure analysis...');\n\n try {\n // Extract hierarchical position data from Figma frames\n const positions = extractNodePositionsHierarchical(frames);\n const positionsJson = JSON.stringify(positions);\n\n // Generate structure using AI\n const prompt = generateStructurePrompt({\n positions: positionsJson,\n width: imageWidth ? String(imageWidth) : '1440',\n });\n\n logger.printInfoLog('Calling AI model to generate component structure...');\n\n const structureResult = await callModel({\n question: prompt,\n imageUrls: thumbnailUrl,\n responseFormat: { type: 'json_object' },\n maxTokens: 20240,\n });\n\n // Parse AI response\n const jsonContent = extractJSON(structureResult);\n const parsedStructure = JSON.parse(jsonContent) as Protocol | Protocol[];\n\n // Post-process structure: normalize names, populate elements, annotate paths\n logger.printInfoLog('Processing structure tree...');\n postProcessStructure(parsedStructure, frames);\n\n const protocol = (Array.isArray(parsedStructure) ? parsedStructure[0] : parsedStructure) as Protocol;\n\n // Extract component props and states for reusable components\n if (frames && protocol) {\n logger.printInfoLog('Extracting component properties and states...');\n await populateComponentProps(protocol, frames, thumbnailUrl);\n }\n\n logger.printSuccessLog('Component structure generated successfully');\n\n return protocol;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.printErrorLog(`Error generating component structure: ${errorMessage}`);\n throw new Error(`Failed to parse component structure: ${errorMessage}`);\n }\n};\n","import type { FigmaFrameInfo, Protocol, FrameData } from '../../../types';\nimport type { SimplifiedFigmaNode, ExtendedFrameStructNode, ParsedDataListResponse } from './types';\nimport path from 'node:path';\nimport { toKebabCase } from '../../../utils/naming';\nimport { extractJSON } from '../../../utils/parser';\nimport { callModel } from '../../../utils/call-model';\nimport { logger } from '../../../utils/logger';\n\n// ============= Figma Node Utilities =============\n/**\n * Simplifies Figma nodes for content extraction, retaining essential fields for AI processing\n * Removes heavy vector data while keeping text content, images, and layout information\n *\n * @param node - The Figma frame node to simplify\n * @returns Simplified node with only essential fields\n */\nexport function simplifyFigmaNodeForContent(node: FigmaFrameInfo): SimplifiedFigmaNode {\n const simple: SimplifiedFigmaNode = {\n id: node.id,\n name: node.name,\n type: node.type,\n };\n\n // Check both url (set by Asset node) and thumbnailUrl (original Figma field)\n const imageUrl = (node as FigmaFrameInfo & { url?: string }).url || node.thumbnailUrl;\n if (imageUrl) {\n simple.url = imageUrl;\n }\n\n if (node.cornerRadius !== undefined) {\n simple.cornerRadius = node.cornerRadius;\n }\n\n if (node.characters !== undefined && node.characters !== null) {\n simple.characters = node.characters;\n }\n\n if (node.visible !== undefined) simple.visible = node.visible;\n\n if (node.absoluteBoundingBox) simple.absoluteBoundingBox = node.absoluteBoundingBox;\n\n if (node.children && Array.isArray(node.children)) {\n simple.children = node.children.map(simplifyFigmaNodeForContent);\n }\n\n if (node.inlineStyles) {\n simple.inlineStyles = node.inlineStyles as Record<string, unknown>;\n }\n\n if (node.style) {\n simple.style = node.style as unknown as Record<string, unknown>;\n }\n\n if (node.strokes && Array.isArray(node.strokes) && node.strokes.length > 0) {\n simple.hasStrokes = true;\n }\n\n return simple;\n}\n\n/**\n * Extract node positions with hierarchical structure preserved\n * Returns nested position data maintaining parent-child relationships\n *\n * @param data - Figma frame data (single frame or array of frames)\n * @returns Hierarchical position data with node information\n */\nexport function extractNodePositionsHierarchical(data: FigmaFrameInfo[] | FigmaFrameInfo | undefined): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n if (!data) {\n return result;\n }\n\n const list = Array.isArray(data) ? data : [data];\n\n for (const item of list) {\n if (item && typeof item === 'object' && item.id) {\n const nodeData: Record<string, unknown> = {};\n\n // Extract position information\n const bounds = item.absoluteBoundingBox || item.absoluteRenderBounds;\n if (bounds) {\n nodeData.x = bounds.x;\n nodeData.y = bounds.y;\n nodeData.w = bounds.width;\n nodeData.h = bounds.height;\n }\n\n // Recursively process children\n if (item.children && Array.isArray(item.children) && item.children.length > 0) {\n nodeData.children = extractNodePositionsHierarchical(item.children);\n }\n\n result[item.id] = nodeData;\n }\n }\n\n return result;\n}\n\n/**\n * Extract nodes by IDs, including their full subtrees (all children)\n * This allows inspecting the full content of specific component instances\n */\nfunction extractNodesWithSubtreeByIds(tree: FigmaFrameInfo | FigmaFrameInfo[], idList: string[]): FigmaFrameInfo[] {\n const idSet = new Set(idList);\n const result: FigmaFrameInfo[] = [];\n\n const findNodes = (nodes: FigmaFrameInfo[]) => {\n for (const node of nodes) {\n if (idSet.has(node.id)) {\n // Deep clone the node to ensure all fields (including url) are preserved\n const clonedNode = JSON.parse(JSON.stringify(node)) as FigmaFrameInfo;\n result.push(clonedNode);\n // Do not recurse into children of a match, because the match already contains them.\n } else if (node.children && Array.isArray(node.children)) {\n findNodes(node.children);\n }\n }\n };\n\n const nodeArray = Array.isArray(tree) ? tree : [tree];\n findNodes(nodeArray);\n return result;\n}\n\n/**\n * Extract nodes by IDs while preserving hierarchical structure\n * Nodes in idList are kept; if a deep child is in idList but parent isn't, the child is still extracted\n *\n * @param tree - The Figma frame tree to search\n * @param idList - Array of node IDs to extract\n * @param options - Optional settings\n * @param options.includeSubtree - If true, includes all descendants of matched nodes\n * @returns Array of extracted nodes with hierarchy preserved\n */\nexport function extractHierarchicalNodesByIds(\n tree: FigmaFrameInfo | FigmaFrameInfo[],\n idList: string[],\n options?: { includeSubtree?: boolean }\n): FigmaFrameInfo[] {\n if (options?.includeSubtree) {\n return extractNodesWithSubtreeByIds(tree, idList);\n }\n\n const idSet = new Set(idList);\n const result: FigmaFrameInfo[] = [];\n\n // Helper function to check if a node or any of its descendants are in idList\n const hasDescendantInList = (node: FigmaFrameInfo): boolean => {\n if (idSet.has(node.id)) return true;\n\n if (node.children && Array.isArray(node.children)) {\n for (const child of node.children) {\n if (typeof child === 'object' && child !== null && 'id' in child) {\n if (hasDescendantInList(child)) {\n return true;\n }\n }\n }\n }\n\n return false;\n };\n\n // Helper function to recursively process a single node\n const processNode = (node: FigmaFrameInfo): FigmaFrameInfo[] => {\n // First check if this node or any descendant is in the list\n if (!hasDescendantInList(node)) {\n return [];\n }\n\n // If current node is in the list, keep it with filtered children\n if (idSet.has(node.id)) {\n const clonedNode: FigmaFrameInfo = { ...node };\n\n // Process children if they exist\n if (node.children && Array.isArray(node.children)) {\n const filteredChildren: FigmaFrameInfo[] = [];\n\n for (const child of node.children) {\n if (typeof child === 'object' && child !== null && 'id' in child) {\n const processedChildren = processNode(child);\n filteredChildren.push(...processedChildren);\n }\n }\n\n clonedNode.children = filteredChildren.length > 0 ? filteredChildren : [];\n } else {\n clonedNode.children = [];\n }\n\n return [clonedNode];\n } else {\n // Current node is not in the list, but some descendants are\n // Collect all matching descendants and return them (flattened)\n const matchingDescendants: FigmaFrameInfo[] = [];\n\n if (node.children && Array.isArray(node.children)) {\n for (const child of node.children) {\n if (typeof child === 'object' && child !== null && 'id' in child) {\n const processedChildren = processNode(child);\n matchingDescendants.push(...processedChildren);\n }\n }\n }\n\n return matchingDescendants;\n }\n };\n\n // Process tree (handle both single node and array)\n const nodeArray = Array.isArray(tree) ? tree : [tree];\n\n for (const node of nodeArray) {\n const processedNodes = processNode(node);\n result.push(...processedNodes);\n }\n\n return result;\n}\n\n// ============= Structure Processing Utilities =============\n\n/**\n * Post-processes the structure tree in a single traversal\n * Performs three operations simultaneously:\n * 1. Normalizes componentName (moves from top-level to data field)\n * 2. Populates elements data from elementIds\n * 3. Annotates with file system paths (path, componentPath, kebabName)\n *\n * @param structure - The parsed structure from AI model\n * @param frames - The Figma frames tree for element extraction\n */\nexport function postProcessStructure(structure?: Protocol | Protocol[] | null, frames?: FigmaFrameInfo[]): void {\n if (!structure) {\n return;\n }\n\n // Utility to join alias path segments (always POSIX '/')\n const joinSegments = (...segments: (string | undefined)[]): string =>\n path.posix.join(...segments.filter((segment): segment is string => Boolean(segment && segment.length)));\n\n const nodes = Array.isArray(structure) ? structure : [structure];\n let rootPath = '@/components';\n\n // Convert component name to kebab-case for file naming\n const toKebabName = (node: Protocol): string => {\n const source = node.data.kebabName || node.data.name || node.id || 'component';\n const kebabName = toKebabCase(source);\n if (!node.data.kebabName) {\n node.data.kebabName = kebabName;\n }\n return kebabName;\n };\n\n const traverse = (node?: Protocol | null, parentPath?: string, level = 0): void => {\n if (!node || !node.data) {\n return;\n }\n\n // 1. Normalize componentName (from top-level to data field)\n const extendedNode = node as ExtendedFrameStructNode;\n const topLevelComponentName = extendedNode.componentName;\n if (topLevelComponentName && !node.data.componentName) {\n node.data.componentName = topLevelComponentName;\n delete extendedNode.componentName;\n }\n\n // 2. Populate elements data from elementIds\n if (frames) {\n const nodeData = node.data as FrameData & { elementIds?: string[] };\n const elementIds = nodeData.elementIds;\n if (elementIds && Array.isArray(elementIds)) {\n if (elementIds.length > 0) {\n node.data.elements = extractHierarchicalNodesByIds(frames, elementIds, { includeSubtree: true });\n } else {\n node.data.elements = [];\n }\n delete nodeData.elementIds;\n } else {\n node.data.elements = node.data.elements || [];\n }\n }\n\n // 3. Annotate with file system paths\n const segment = toKebabName(node);\n let currentPath: string;\n\n if (level === 0) {\n // Root node always uses base path\n currentPath = rootPath;\n rootPath = currentPath;\n } else {\n const ancestorPath = parentPath || rootPath;\n currentPath = joinSegments(ancestorPath, segment);\n }\n\n // For reusable components, generate flat componentPath (non-hierarchical)\n if (node.data.componentName) {\n const componentKebabName = toKebabCase(node.data.componentName);\n node.data.componentPath = joinSegments(rootPath, componentKebabName);\n node.data.path = node.data.componentPath;\n }\n\n node.data.path = currentPath;\n\n // Recursively process children\n if (Array.isArray(node.children) && node.children.length > 0) {\n node.children.forEach(child => traverse(child, node.data.path, level + 1));\n }\n };\n\n nodes.forEach(node => {\n if (!node || !node.data) {\n return;\n }\n traverse(node, undefined, 0);\n });\n}\n\n/**\n * Extract component groups from protocol children\n * Groups components by their componentName for batch processing\n *\n * @param protocol - The protocol node to analyze\n * @returns Map of componentName to array of instances\n */\nexport function extractComponentGroups(node: Protocol): Map<string, Protocol[]> {\n if (!node || !node.children || node.children.length === 0) return new Map();\n const componentGroups = new Map<string, Protocol[]>();\n const validChildren = node.children.filter(c => c && c.data);\n\n validChildren.forEach(child => {\n const name = child.data.componentName;\n if (name) {\n if (!componentGroups.has(name)) {\n componentGroups.set(name, []);\n }\n componentGroups.get(name)!.push(child);\n }\n });\n\n return componentGroups;\n}\n\n/**\n * Applies props and state to the protocol node\n * @param parsed - The parsed data list response\n * @param node - The protocol node to apply the props and state to\n * @param compName - The name of the component\n * @param group - The group of components\n * @param isList - Whether the component is a list\n */\nexport function applyPropsAndStateToProtocol(\n parsed: ParsedDataListResponse,\n node: Protocol,\n compName: string,\n group: Protocol[],\n isList: boolean\n): void {\n if (parsed && parsed.state && Array.isArray(parsed.state)) {\n if (isList) {\n if (!node.data.states) {\n node.data.states = [];\n }\n\n node.data.states.push({\n state: parsed.state,\n componentName: compName,\n componentPath: group[0]?.data.componentPath || '',\n });\n\n const originalChildren: Protocol[] = node.children || [];\n const newChildren: Protocol[] = [];\n const processedComponentNames = new Set<string>();\n\n for (const child of originalChildren) {\n const childName = child.data.componentName;\n if (childName === compName) {\n if (!processedComponentNames.has(childName)) {\n child.data.name = childName;\n child.id = childName;\n const cleanKebabName = toKebabCase(childName);\n child.data.kebabName = cleanKebabName;\n delete child.data.path;\n\n if (parsed.props && Array.isArray(parsed.props)) {\n child.data.props = parsed.props;\n }\n\n newChildren.push(child);\n processedComponentNames.add(childName);\n }\n } else {\n newChildren.push(child);\n }\n }\n\n node.children = newChildren;\n }\n }\n}\n\n/**\n * Extracts component properties and states from repeated component instances\n * For components that appear multiple times (e.g., cards in a grid), this function:\n * 1. Groups instances by componentName\n * 2. Uses AI to extract data variations (text, images, etc.)\n * 3. Generates props schema for the component\n * 4. Collapses duplicate instances into a single template + state array\n *\n * @param node - Current structure node to process\n * @param frames - Figma frames for reference\n * @param thumbnailUrl - Design thumbnail URL for AI visual context\n */\nexport async function populateComponentProps(node: Protocol, frames: FigmaFrameInfo[], thumbnailUrl?: string): Promise<void> {\n if (!node || !node.children || node.children.length === 0) return;\n\n const componentGroups = extractComponentGroups(node);\n\n // Process each component group to extract props and data\n for (const [compName, group] of componentGroups) {\n if (group.length === 0) continue;\n\n const isList = group.length > 1;\n const allElements = group.flatMap(g => g.data.elements || []);\n const simplifiedNodes = allElements\n .filter((n): n is FigmaFrameInfo => typeof n === 'object' && n !== null)\n .map(n => simplifyFigmaNodeForContent(n));\n const figmaDataJson = JSON.stringify(simplifiedNodes);\n const containerName = node.data.name || 'Container';\n\n try {\n const { extractDataListPrompt } = await import('./prompt');\n const prompt = extractDataListPrompt({\n containerName,\n childComponentName: compName,\n figmaData: figmaDataJson,\n });\n\n const result = await callModel({\n question: prompt,\n imageUrls: thumbnailUrl,\n responseFormat: { type: 'json_object' },\n });\n\n const json = extractJSON(result);\n const parsed = JSON.parse(json) as ParsedDataListResponse;\n applyPropsAndStateToProtocol(parsed, node, compName, group, isList);\n } catch (e) {\n logger.printErrorLog(\n `Failed to extract data list for ${compName} in ${containerName}: ${e instanceof Error ? e.message : String(e)}`\n );\n }\n }\n\n // Recursively process children\n for (const child of node.children) {\n await populateComponentProps(child, frames, thumbnailUrl);\n }\n}\n","/**\n * Standard naming utilities for the project.\n * Ensures consistency between kebab-case file paths and PascalCase component names.\n */\n\n/**\n * Converts a string to PascalCase (e.g. \"my-component\" -> \"MyComponent\")\n * Used for Component Names and imports.\n */\nexport function toPascalCase(str: string): string {\n // 1. Replace special chars with space\n // 2. Split by space or capital letters\n // 3. Capitalize first letter of each part\n return str\n .replace(/[^a-zA-Z0-9]+/g, ' ')\n .trim()\n .split(/\\s+/)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('');\n}\n\n/**\n * Converts a string to kebab-case (e.g. \"MyComponent\" -> \"my-component\")\n * Used for file paths and directories.\n */\nexport function toKebabCase(str: string): string {\n return str\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2') // Split camelCase\n .replace(/[^a-zA-Z0-9]+/g, '-') // Replace non-alphanumeric with hyphen\n .toLowerCase()\n .replace(/^-+|-+$/g, ''); // Trim leading/trailing hyphens\n}\n","/**\n * Response parsing utilities for AI model outputs.\n * Handles extraction of structured content from markdown-formatted responses.\n */\n\nimport { FileInfo } from '../types/file-types';\n\n/**\n * Extract JSON content from markdown code blocks\n * Handles cases where AI models wrap JSON in ```json ... ``` or ``` ... ```\n * If no code block markers are found, returns the original content\n *\n * @param response - Model response that may contain markdown code blocks\n * @returns Extracted JSON string without markdown formatting\n *\n * @example\n * // Input: \"```json\\n{\\\"key\\\": \\\"value\\\"}\\n```\"\n * // Output: \"{\\\"key\\\": \\\"value\\\"}\"\n */\nexport function extractJSON(response: string): string {\n // Try to match ```json ... ``` format first\n const jsonBlockMatch = response.match(/```json\\s*\\n([\\s\\S]*?)\\n```/);\n if (jsonBlockMatch && jsonBlockMatch[1]) {\n return jsonBlockMatch[1].trim();\n }\n\n // Try to match generic ``` ... ``` format (with newlines around content)\n const codeBlockMatch = response.match(/```\\s*\\n([\\s\\S]*?)\\n```/);\n if (codeBlockMatch && codeBlockMatch[1]) {\n return codeBlockMatch[1].trim();\n }\n\n // Fallback: no proper code block; use full content but strip loose markdown fences.\n // Some models return raw JSON with trailing \"```\" (e.g. ...]```) or leading ```\\n.\n let cleaned = response.trim();\n cleaned = cleaned.replace(/^\\s*```(?:json)?\\s*\\n?/g, '').replace(/\\s*```+\\s*$/g, '');\n return cleaned;\n}\n\n/**\n * Extract code content from markdown code blocks\n * Handles cases where AI models wrap code in ```tsx ... ``` or ``` ... ```\n * If no code block markers are found, returns the original content\n */\nexport function extractCode(response: string): string {\n // 1. Try to extract content strictly within ``` fences\n // Regex captures content between ```language and ```\n const codeBlockMatch = response.match(/```(?:tsx|typescript|react|js|javascript|json|css|less|scss)?\\s*\\n([\\s\\S]*?)```/);\n\n if (codeBlockMatch && codeBlockMatch[1]) {\n return codeBlockMatch[1].trim();\n }\n\n // 2. Fallback: If no clear block structure is found (or fences are missing/malformed),\n // try to strip loose fences just in case, but usually method 1 catches the block.\n // If the model returned JUST code without fences, this preserves it.\n // If the model returned \"Here is code: code\", this returns the whole string (which might be bad, but safest fallback).\n\n // Removing loose fences if any remain (unlikely if method 1 failed but good for cleanup)\n const cleaned = response\n .replace(/```(tsx|typescript|react|js|javascript|json|css|less|scss)?/g, '')\n .replace(/```/g, '')\n .trim();\n\n return cleaned;\n}\n\n/**\n * Extract multiple files from content with file headers\n * Format:\n * ## filename.tsx\n * ```tsx\n * code...\n * ```\n *\n * ## filename.css\n * ```css\n * styles...\n * ```\n */\nexport function extractFiles(content: string): FileInfo[] {\n const files: FileInfo[] = [];\n\n // Match file sections: ## filename\\n```language\\ncode\\n```\n // Allow optional whitespace around newlines for flexibility\n const fileRegex = /##\\s+([^\\n]+)\\s*\\n\\s*```(?:\\w+)?\\s*\\n([\\s\\S]*?)\\n\\s*```/g;\n let match;\n\n while ((match = fileRegex.exec(content)) !== null) {\n if (match[1] && match[2]) {\n const filename = match[1].trim();\n const code = match[2].trim();\n files.push({ filename, content: code });\n }\n }\n\n return files;\n}\n","import { FigmaUrlInfo } from '../types/figma-types';\n\n/**\n * Parse Figma URL and extract fileId, name, and nodeId in one pass\n * @param url - Figma URL to parse\n * @returns Object containing fileId, name, and nodeId\n * @example\n * parseFigmaUrl('https://www.figma.com/design/aONcu8L82l1PdcT304Q8Za/Intern?node-id=0-495')\n * // Returns: { fileId: 'aONcu8L82l1PdcT304Q8Za', name: 'intern', nodeId: '0-495' }\n */\nexport const parseFigmaUrl = (url: string): FigmaUrlInfo => {\n let fileId: string | null = null;\n let name = 'untitled';\n let nodeId: string | null = null;\n\n try {\n const urlObj = new URL(decodeURIComponent(url));\n const pathParts = urlObj.pathname.split('/').filter(Boolean);\n if (pathParts.length >= 3) {\n fileId = pathParts[pathParts.length - 2] || null;\n const fileName = pathParts[pathParts.length - 1];\n name = fileName ? encodeURI(fileName).toLowerCase() : 'untitled';\n name = name.length > 20 ? name.substring(0, 20) : name;\n }\n\n nodeId = urlObj.searchParams.get('node-id') || null;\n nodeId = nodeId ? nodeId.replace(/-/g, ':') : null;\n } catch {}\n\n if (!fileId || !nodeId) {\n throw new Error('Invalid Figma URL');\n }\n\n return { fileId, name, nodeId, projectName: `${name}_${nodeId}` };\n};\n","import { Command } from 'commander';\nimport { generateProtocol } from '../nodes/process';\nimport { parseFigmaUrl } from '../utils/url-parser';\nimport { workspaceManager } from '../utils/workspace';\nimport { logger } from '../utils/logger';\n\n// f2p command: Figma to Protocol\nexport const registerD2PCommand = (program: Command) => {\n program\n .command('design2protocol')\n .alias('d2p')\n .description('Convert Figma design to protocol (fetch and process Figma document)')\n .option('-s, --source <url>', 'Figma Link')\n .action(async (opts: { source: string }) => {\n try {\n const { source } = opts;\n const urlInfo = parseFigmaUrl(source);\n const workspace = workspaceManager.initWorkspace(urlInfo.name);\n\n await generateProtocol({\n urlInfo,\n workspace,\n figmaInfo: { thumbnail: '' },\n protocol: undefined,\n messages: [],\n config: {},\n });\n\n logger.printSuccessLog('Successfully completed Design to Protocol conversion!');\n } catch (error) {\n logger.printErrorLog(`Error during d2p execution: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n};\n","import { Command } from 'commander';\nimport { logger } from '../utils/logger';\nimport { design2code } from '../graph';\nimport { ValidationMode } from '../types/graph-types';\n\n/**\n * Validate and map CLI mode parameter to internal validationMode.\n * @param mode - The mode string from CLI\n * @returns The mapped ValidationMode, or null if invalid\n */\nfunction getValidationMode(mode: string): ValidationMode | null {\n const validModes = ['code', 'with-report', 'full'] as const;\n type ValidMode = (typeof validModes)[number];\n const isValidMode = (m: string): m is ValidMode => {\n return validModes.includes(m as ValidMode);\n };\n\n if (!isValidMode(mode)) {\n return null;\n }\n\n // Map CLI mode to internal validationMode\n const modeMap: Record<ValidMode, ValidationMode> = {\n code: ValidationMode.CodeOnly,\n 'with-report': ValidationMode.ReportOnly,\n full: ValidationMode.Full,\n };\n\n return modeMap[mode];\n}\n\n// d2c command: Design to Code\nexport const registerD2CCommand = (program: Command) => {\n program\n .command('design2code')\n .alias('d2c')\n .description('Generate frontend code from design')\n .option('-s, --source <url>', 'Figma Link')\n .option(\n '-m, --mode [type]',\n 'Execution mode: code (generate component code only), with-report (single validation and generate report), full (iterative validation)',\n 'code'\n )\n .action(async (opts: { source: string; mode?: string }) => {\n try {\n const { source, mode = 'code' } = opts;\n\n const validationMode = getValidationMode(mode);\n if (!validationMode) {\n logger.printErrorLog(`Invalid mode: ${mode}. Must be one of: code, with-report, full`);\n process.exit(1);\n }\n\n await design2code(source, validationMode);\n\n logger.printSuccessLog('Successfully completed code generation from design! Happy coding!');\n } catch (error) {\n logger.printErrorLog(`Error during d2c execution: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n};\n","import { StateGraph, START, END } from '@langchain/langgraph';\nimport { GraphNode, ValidationMode } from './types/graph-types';\nimport { GraphStateAnnotation } from './state';\nimport { initialProject } from './nodes/initial';\nimport { generateProtocol } from './nodes/process';\nimport { runValidation } from './nodes/validation';\nimport { parseFigmaUrl } from './utils/url-parser';\nimport { workspaceManager } from './utils/workspace';\nimport { generateCode } from './nodes/code';\nimport { initializeSqliteSaver, promptCheckpointChoice } from './utils/checkpoint';\nimport { logger } from './utils/logger';\nimport { callModel } from './utils/call-model';\n\nexport async function design2code(url: string, mode?: ValidationMode): Promise<void> {\n const urlInfo = parseFigmaUrl(url);\n const threadId = urlInfo.projectName!;\n const workspace = workspaceManager.initWorkspace(threadId);\n\n // Initialize SqliteSaver with the database path\n let checkpointer = initializeSqliteSaver(workspace.db);\n const resume = await promptCheckpointChoice(checkpointer, threadId);\n\n logger.printInfoLog(`Starting design-to-code process for: ${urlInfo.projectName}`);\n\n // If not resuming, delete workspace and reinitialize checkpointer\n if (resume !== true) {\n workspaceManager.deleteWorkspace(workspace);\n logger.printInfoLog('Starting fresh...');\n // Reinitialize checkpointer after deleting workspace\n checkpointer = initializeSqliteSaver(workspace.db);\n } else {\n logger.printInfoLog('Resuming from cache...');\n }\n\n await callModel({\n question: '请介绍你自己,你是什么模型',\n streaming: false,\n });\n\n // Compile graph with checkpointer (after potential reinitialization)\n const graph = new StateGraph(GraphStateAnnotation)\n .addNode(GraphNode.INITIAL, initialProject)\n .addNode(GraphNode.PROCESS, generateProtocol)\n .addNode(GraphNode.CODE, generateCode)\n .addNode(GraphNode.VALIDATION, runValidation)\n .addEdge(START, GraphNode.INITIAL)\n .addEdge(GraphNode.INITIAL, GraphNode.PROCESS)\n .addEdge(GraphNode.PROCESS, GraphNode.CODE)\n .addEdge(GraphNode.CODE, GraphNode.VALIDATION)\n .addEdge(GraphNode.VALIDATION, END)\n .compile({ checkpointer });\n\n const config = { configurable: { thread_id: threadId } };\n\n // If resuming from checkpoint, pass null to let LangGraph resume from saved state\n // Otherwise, pass initial state to start fresh\n const validationMode: ValidationMode = mode ?? ValidationMode.Full;\n const state =\n resume === true\n ? null\n : {\n messages: [],\n urlInfo,\n workspace,\n config: {\n validationMode,\n },\n };\n await graph.invoke(state, config);\n\n logger.printSuccessLog('Design-to-code process completed!');\n}\n","import { Annotation, MessagesAnnotation } from '@langchain/langgraph';\nimport type { FigmaUrlInfo } from './types/figma-types';\nimport type { Protocol, GlobalFigmaInfo, ValidationConfig } from './types';\nimport { WorkspaceStructure } from './types/workspace-types';\n\nexport const GraphStateAnnotation = Annotation.Root({\n ...MessagesAnnotation.spec,\n urlInfo: Annotation<FigmaUrlInfo>(),\n workspace: Annotation<WorkspaceStructure>(),\n figmaInfo: Annotation<GlobalFigmaInfo>(),\n protocol: Annotation<Protocol | undefined>(),\n config: Annotation<ValidationConfig>(),\n});\n\nexport type GraphState = typeof GraphStateAnnotation.State;\n","import { Agent, type ModelConfig } from 'evoltagent';\nimport { INITIAL_AGENT_SYSTEM_PROMPT } from './prompt';\n\n/**\n * Creates an initial agent for scaffolding a project.\n * @param options - The options for creating the agent.\n * @param options.modelConfig - The model configuration.\n * @param options.appPath - The path to the app.\n * @returns The initial agent.\n */\nexport function createInitialAgent(modelConfig: ModelConfig): Agent {\n const systemTools = ['ThinkTool.execute', 'FileEditor.read', 'FileEditor.write'];\n\n return new Agent({\n name: 'InitialAgent',\n profile: 'Expert Frontend Engineer specialized in project scaffolding with React, TypeScript, and Tailwind CSS V4.',\n system: INITIAL_AGENT_SYSTEM_PROMPT,\n tools: systemTools,\n modelConfig,\n verbose: true,\n });\n}\n","/**\n * Generates the system prompt for the InitialAgent.\n * Defines project requirements, tech stack (React + Tailwind V4), and safety constraints.\n *\n * @param options - Configuration options for the prompt generation.\n * @param options.appPath - The target directory path where the project will be scaffolded.\n */\nexport const INITIAL_AGENT_SYSTEM_PROMPT = `\n<system_instructions>\n <task>Scaffold a clean React V18 + TS + Vite + TailwindCSS V4 + Less project.</task>\n\n <input_context>\n - appPath: /absolute/path/to/app\n - appName: document title name\n </input_context>\n\n <requirements>\n <tech_stack>React V18, TypeScript, Vite, TailwindCSS V4, Less</tech_stack>\n\n <directory_constraint>\n CRITICAL: All file operations MUST be performed within the directory specified by appPath.\n When using 'FileEditor.write' or other file tools, you MUST use the full path format: {appPath}/filename.\n </directory_constraint>\n\n <file_specs>\n - \\`.gitignore\\`: Standard gitignore file. MUST include:\n * node_modules/\n * dist/ and build/ directories\n * .env file\n * Editor files (.vscode/*, .DS_Store, etc.)\n * Log files and cache directories\n * Lock files (package-lock.json, yarn.lock, pnpm-lock.yaml)\n - \\`package.json\\`: Basic scripts and dependencies. MUST include \\`tailwindcss\\` (v4) and \\`@tailwindcss/vite\\`.\n * Scripts MUST use \"pnpm exec\" prefix to ensure project dependencies are prioritized:\n - \"dev\": \"pnpm exec vite\"\n - \"build\": \"pnpm exec tsc && pnpm exec vite build\"\n - \"preview\": \"pnpm exec vite preview\"\n * IMPORTANT: Do NOT add \"coderio\" as a dependency - it's only a build tool, not a runtime dependency.\n - \\`vite.config.ts\\`: Configure React and TailwindCSS V4 plugins. MUST include path alias configuration:\n * Add \\`resolve.alias\\` with \\`@\\` pointing to \\`path.resolve(__dirname, './src')\\`\n * Import \\`path\\` from 'node:path'\n - \\`tsconfig.json\\`: Standard React-Vite TS config. MUST include path alias configuration:\n * Add \\`compilerOptions.baseUrl\\` set to \".\"\n * Add \\`compilerOptions.paths\\` with \\`\"@/*\": [\"src/*\"]\\`\n - \\`index.html\\`: Basic template with #root and entry script. set document title to appName.\n - \\`src/main.tsx\\`: Entry point rendering App.\n - \\`src/vite-env.d.ts\\`: MUST include \\`/// <reference types=\"vite/client\" />\\` to support CSS/Less module imports.\n - \\`src/App.tsx\\`: MUST be an empty component (returns null or empty div), NO React import if unused.\n - \\`src/App.less\\`: MUST be an empty file.\n - \\`src/globals.css\\`: ONLY include \\`@import \"tailwindcss\";\\`.\n </file_specs>\n </requirements>\n\n <workflow>\n 1. Use 'FileEditor.write' to create each file listed in <file_specs>, using the format {appPath}/filename for all paths.\n 2. Ensure the directory structure is correct and all files are contained within the appPath directory.\n </workflow>\n\n <final_instruction>\n Create a fully working but MINIMAL project skeleton using Tailwind CSS V4. Use 'FileEditor.write' for all file creations. Use the full path format {appPath}/filename for every file. Do not provide code blocks in chat.\n </final_instruction>\n</system_instructions>\n`.trim();\n","import { createInitialAgent } from '../../agents/initial-agent';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { logger } from '../../utils/logger';\nimport { getModelConfig } from '../../utils/config';\nimport { GraphState } from '../../state';\nimport { MAX_OUTPUT_TOKENS, AGENT_CONTEXT_WINDOW_TOKENS } from '../../constants';\nimport { initialAgentInstruction } from '../../agents/initial-agent/instruction';\n\n/**\n * 'initial' node, responsible for initializing the empty project scaffold.\n * It uses an LLM-based agent to create the basic project structure and files.\n */\nexport const initialProject = async (state: GraphState) => {\n logger.printInfoLog('Initializing project...');\n\n const envConfig = getModelConfig();\n const modelConfig = {\n ...envConfig,\n contextWindowTokens: AGENT_CONTEXT_WINDOW_TOKENS,\n maxOutputTokens: MAX_OUTPUT_TOKENS,\n };\n\n const appPath = state.workspace.app;\n const appName = state.urlInfo.name || '';\n if (!appPath) {\n throw new Error('Workspace application path is not defined.');\n }\n\n const initialAgent = createInitialAgent(modelConfig);\n const result: unknown = await initialAgent.run(initialAgentInstruction({ appPath, appName }));\n\n // Validate if essential files were created\n const essentialFiles = ['package.json', 'src', 'vite.config.ts', 'tsconfig.json', 'index.html', 'src/main.tsx', 'src/App.tsx'];\n for (const file of essentialFiles) {\n const fullPath = path.join(appPath, file);\n if (!fs.existsSync(fullPath)) {\n throw new Error(`Critical file/directory missing: \"${file}\". The project scaffolding may have failed.`);\n }\n }\n\n logger.printSuccessLog(result as string);\n\n return {};\n};\n","export function initialAgentInstruction(params: { appPath: string; appName: string }): string {\n return `\nappPath: ${params.appPath}\nappName: ${params.appName}\n\nTASK:\nScaffold a clean React V18 + TS + Vite + TailwindCSS V4 + Less project.\n`.trim();\n}\n","/**\n * Validation module.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { GraphState } from '../../state';\nimport { METRIC_DECIMAL_PLACES } from './constants';\nimport { logger } from '../../utils/logger';\nimport { validationLoop } from './core/validation-loop';\nimport { commit } from './commit/index';\nimport { ValidationMode } from '../../types/graph-types';\n\n/**\n * LangGraph node: run validation on the generated app and write a report into the workspace.\n * Reads validation mode from state.config.validationMode (defaults to 'full').\n * Throws error if validation fails (MAE threshold not reached) or execution errors occur.\n */\nexport const runValidation = async (state: GraphState): Promise<void> => {\n if (!state.protocol) {\n throw new Error('No protocol found for validation (state.protocol is missing).');\n }\n if (!state.figmaInfo?.thumbnail) {\n throw new Error('Missing Figma thumbnail URL (state.figmaInfo.thumbnail is missing).');\n }\n\n const mode = state.config?.validationMode ?? ValidationMode.Full;\n // Code-only mode: skip validation, only commit and exit\n if (mode === ValidationMode.CodeOnly) {\n logger.printInfoLog('Code-only mode: skipping validation, committing generated code...');\n const commitResult = await commit({ appPath: state.workspace.app });\n if (!commitResult.success) {\n logger.printWarnLog(`Git commit failed: ${commitResult.message}`);\n } else {\n logger.printSuccessLog('Git commit completed successfully!');\n }\n return;\n }\n\n const outputDir = path.join(state.workspace.process, 'validation');\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n logger.printInfoLog(`Starting validation loop (mode: ${mode})...`);\n\n const result = await validationLoop({\n protocol: state.protocol,\n figmaThumbnailUrl: state.figmaInfo.thumbnail,\n outputDir,\n workspace: state.workspace,\n config: { mode },\n });\n\n if (result.error) {\n throw new Error(result.error);\n }\n\n const reportHtmlPath = path.join(outputDir, 'index.html');\n if (result.validationPassed) {\n logger.printSuccessLog(`Validation PASSED (MAE: ${result.finalMae.toFixed(METRIC_DECIMAL_PLACES)}px)`);\n } else {\n logger.printWarnLog(`Validation FAILED (MAE: ${result.finalMae.toFixed(METRIC_DECIMAL_PLACES)}px)`);\n }\n logger.printInfoLog(`Validation report: ${reportHtmlPath}`);\n};\n","/**\n * Validation node-specific configuration constants.\n * These are static values specific to the validation orchestration logic.\n * Not global - scoped to validation node only.\n */\n\n/**\n * Target MAE (Mean Absolute Error) in pixels.\n *\n * Maximum acceptable average position error across all elements.\n */\nexport const TARGET_MAE = 3;\n\n/**\n * Position error threshold in pixels.\n *\n * - Elements with error <= this value are classified as \"accurate\"\n * - Elements with error > this value are classified as \"misaligned\"\n */\nexport const POSITION_THRESHOLD = 1.0;\n\n/**\n * Default timeout for browser operations in milliseconds.\n *\n * Used by Playwright for page navigation and rendering.\n */\nexport const DEFAULT_TIMEOUT = 30000;\n\n/**\n * Number of decimal places for rounding metric values.\n */\nexport const METRIC_DECIMAL_PLACES = 2;\n\n/**\n * Default viewport size for browser rendering.\n */\nexport const DEFAULT_VIEWPORT = { width: 1440, height: 900 };\n\n/**\n * Maximum number of validation-correction iterations for the judger-refiner loop.\n */\nexport const MAX_ITERATIONS = 3;\n\n/**\n * Run browser in headless mode.\n */\nexport const HEADLESS = true;\n\n/**\n * Timeout for optional selector waiting in milliseconds (5 seconds)\n */\nexport const SELECTOR_WAIT_TIMEOUT = 5000;\n\n/**\n * Default validation loop configuration.\n *\n * Used when no custom config is provided to validationLoop().\n */\nexport const DEFAULT_VALIDATION_LOOP_CONFIG = {\n maxIterations: MAX_ITERATIONS,\n targetMae: TARGET_MAE,\n positionThreshold: POSITION_THRESHOLD,\n browserTimeout: DEFAULT_TIMEOUT,\n defaultViewportWidth: DEFAULT_VIEWPORT.width,\n defaultViewportHeight: DEFAULT_VIEWPORT.height,\n headless: HEADLESS,\n};\n\n/**\n * Dev server constants used by validation/launch tooling.\n */\nexport const DEFAULT_PORT = 5173;\n\n/**\n * Builds the default dev server URL from a port number.\n */\nexport function buildDevServerUrl(port: number): string {\n return `http://localhost:${port}`;\n}\n","/**\n * Main validation loop orchestration.\n *\n * Simplified actor-critic pattern with in-memory data passing.\n * Iteratively validates positions, diagnoses errors, applies fixes until\n * MAE threshold is met or max iterations reached.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport { DEFAULT_VALIDATION_LOOP_CONFIG } from '../constants';\nimport { logger } from '../../../utils/logger';\nimport { commit } from '../commit/index';\nimport { createJudgerAgent } from '../../../agents/judger-agent';\nimport { formatJudgerInstruction } from '../../../agents/judger-agent/instruction';\nimport { createRefinerAgent, formatRefinerInstruction } from '../../../agents/refiner-agent';\nimport { launch } from '../launch/index';\nimport type { ComponentHistory, MisalignedComponent, Dict } from '../../../types/validation-types';\nimport type { JudgerDiagnosis } from '../../../agents/judger-agent/types';\nimport type { RefinerResult } from '../../../agents/refiner-agent/types';\nimport type {\n ComponentCorrectionLog,\n IterationLog,\n ProcessedOutput,\n RefinementContext,\n ValidationIterationResult,\n ValidationLoopConfig,\n ValidationLoopParams,\n ValidationLoopResult,\n SkippedElement,\n} from '../types';\nimport { extractLayoutFromContext } from '../utils/extraction/extract-layout-metadata';\nimport { report } from '../report/index';\nimport { LaunchTool } from '../../../tools/launch-tool';\nimport { VisualizationTool } from '../../../tools/visualization-tool';\nimport { extractValidationContext, extractComponentPaths, toElementMetadataRegistry } from '../utils/extraction/extract-protocol-context';\nimport { validatePositions } from './validate-position';\nimport { downloadImage } from '../../../tools/figma-tool/images';\nimport { ensureValidationDependencies } from '../../../utils/dependency-installer';\nimport { ValidationMode } from '../../../types/graph-types';\n\nfunction filterComponentsToFix(misaligned: MisalignedComponent[], positionThreshold: number): MisalignedComponent[] {\n return misaligned.filter(comp => {\n const [errorX, errorY] = comp.validationReport.absoluteError;\n return errorX > positionThreshold || errorY > positionThreshold;\n });\n}\n\nfunction recordComponentPosition(comp: MisalignedComponent, iteration: number, componentHistory: ComponentHistory): void {\n const history = componentHistory[comp.componentId] ?? [];\n history.push({\n iteration,\n position: comp.validationReport.currentPosition,\n error: comp.validationReport.absoluteError,\n fixApplied: null,\n });\n componentHistory[comp.componentId] = history;\n}\n\nasync function refineComponent(comp: MisalignedComponent, context: RefinementContext): Promise<ComponentCorrectionLog> {\n const { workspace, structureTree, componentPaths, componentHistory, validationContext, previousScreenshotPath } = context;\n\n try {\n // Extract element IDs from context for this component\n const elementIds = Array.from(validationContext.elements.values())\n .filter((e): e is NonNullable<typeof e> => e.parentComponentId === comp.componentId)\n .map(e => e.id);\n\n const figmaMetadata = extractLayoutFromContext(validationContext, elementIds);\n\n logger.printLog(` Analyzing ${comp.name}...`);\n const judger = createJudgerAgent({\n workspaceDir: workspace.app,\n structureTree,\n componentPaths,\n history: componentHistory,\n });\n const judgerInstruction = formatJudgerInstruction(comp, figmaMetadata as unknown as Record<string, unknown>, componentPaths);\n const judgerImages = previousScreenshotPath ? [previousScreenshotPath] : undefined;\n const diagnosis = (await judger.run(judgerInstruction, judgerImages)) as JudgerDiagnosis;\n\n logger.printLog(` Error type: ${diagnosis.errorType}`);\n logger.printLog(` Fix instructions: ${diagnosis.refineInstructions?.length || 0}`);\n\n // Skip refiner if no instructions (judger failed to analyze)\n if (!diagnosis.refineInstructions || diagnosis.refineInstructions.length === 0) {\n const history = componentHistory[comp.componentId];\n return {\n componentId: comp.componentId,\n componentPath: comp.path,\n elementIds: comp.elementIds,\n validationReport: comp.validationReport,\n diagnosis,\n refinerResult: {\n success: false,\n summary: ['Skipped - no instructions from judger'],\n editsApplied: 0,\n },\n positionHistory: history ? [...history] : undefined,\n };\n }\n\n logger.printLog(` Applying fixes to ${comp.name}...`);\n const refiner = createRefinerAgent(workspace.app);\n const refinerInstruction = formatRefinerInstruction(comp, diagnosis, componentPaths);\n const refinerResult = (await refiner.run(refinerInstruction)) as RefinerResult;\n\n if (refinerResult.success) {\n logger.printSuccessLog(`${comp.name}: ${refinerResult.editsApplied} edits applied`);\n } else {\n logger.printWarnLog(`${comp.name}: ${refinerResult.editsApplied} edits applied`);\n }\n\n const history = componentHistory[comp.componentId];\n const last = history?.at(-1);\n if (last) {\n last.fixApplied = refinerResult.summary;\n }\n\n return {\n componentId: comp.componentId,\n componentPath: comp.path,\n elementIds: comp.elementIds,\n validationReport: comp.validationReport,\n diagnosis,\n refinerResult,\n positionHistory: history ? [...history] : undefined,\n };\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.printInfoLog(`${comp.name}: ${errorMsg}`);\n\n const history = componentHistory[comp.componentId];\n return {\n componentId: comp.componentId,\n componentPath: comp.path,\n elementIds: comp.elementIds,\n validationReport: comp.validationReport,\n diagnosis: undefined,\n refinerResult: undefined,\n positionHistory: history ? [...history] : undefined,\n };\n }\n}\n\nfunction saveProcessedJson(outputDir: string, processedOutput: ProcessedOutput): void {\n const processedJsonPath = path.join(outputDir, 'processed.json');\n fs.writeFileSync(processedJsonPath, JSON.stringify(processedOutput, null, 2));\n logger.printInfoLog('Saved processed.json');\n}\n\n// Helper functions for reducing code duplication\nasync function performCommit(appPath: string, iteration: number | undefined, stage: string): Promise<void> {\n const commitResult = await commit({ appPath, iteration });\n if (!commitResult.success) {\n logger.printWarnLog(`Git commit (${stage}) failed: ${commitResult.message}`);\n } else if (iteration === undefined) {\n logger.printSuccessLog(`Initial project committed successfully, starting validation loop...`);\n }\n}\n\nfunction saveIterationAndProcessedJson(\n iterations: IterationLog[],\n iteration: number,\n currentMae: number,\n currentSae: number,\n misalignedCount: number,\n components: ComponentCorrectionLog[],\n screenshotPath: string,\n skippedElements: SkippedElement[] | undefined,\n outputDir: string,\n targetMae: number\n): void {\n // Add current iteration to log\n iterations.push({\n iteration,\n metrics: { mae: currentMae, sae: currentSae, misalignedCount },\n components,\n screenshotPath,\n skippedElements: skippedElements && skippedElements.length > 0 ? skippedElements : undefined,\n });\n\n // Save processed.json with updated iterations\n const processedOutput: ProcessedOutput = {\n iterations,\n finalResult: {\n success: currentMae <= targetMae,\n finalMae: currentMae,\n finalSae: currentSae,\n totalIterations: iterations.length,\n misalignedCount,\n },\n };\n saveProcessedJson(outputDir, processedOutput);\n}\n\nexport async function validationLoop(params: ValidationLoopParams): Promise<ValidationLoopResult> {\n // Ensure dependencies are installed before starting validation loop\n ensureValidationDependencies();\n\n const { protocol, figmaThumbnailUrl, outputDir, workspace } = params;\n\n if (!protocol || !figmaThumbnailUrl || !outputDir || !workspace) {\n throw new Error('Something wrong in validation loop, missing required parameters...');\n }\n\n const config: ValidationLoopConfig = {\n ...DEFAULT_VALIDATION_LOOP_CONFIG,\n ...params.config,\n };\n const mode: ValidationMode.ReportOnly | ValidationMode.Full = config.mode ?? ValidationMode.Full;\n const maxIterations = mode === ValidationMode.ReportOnly ? 1 : config.maxIterations;\n const visualizationTool = new VisualizationTool();\n\n // Variables to track server state (will be initialized in iteration 1)\n let currentServerUrl: string | undefined;\n let serverKey: string | undefined;\n\n try {\n // Extract unified validation context from protocol (single traversal)\n const validationContext = extractValidationContext(protocol);\n const designOffset: [number, number] = [validationContext.offset.x, validationContext.offset.y];\n if (Math.abs(designOffset[0]) >= 1 || Math.abs(designOffset[1]) >= 1) {\n logger.printInfoLog(`Design offset: (${designOffset[0].toFixed(0)}, ${designOffset[1].toFixed(0)} px)`);\n }\n\n // Extract component paths from context (already resolved to absolute filesystem paths)\n const resolvedComponentPaths = extractComponentPaths(validationContext, workspace);\n\n // Build element registry for compatibility with existing APIs\n const elementRegistry = toElementMetadataRegistry(validationContext);\n\n // Download and cache Figma thumbnail once to avoid redundant downloads in each iteration\n logger.printInfoLog('Downloading Figma thumbnail (will be cached for all iterations)...');\n const cachedFigmaThumbnailBase64 = await downloadImage(figmaThumbnailUrl, undefined, undefined, true);\n logger.printSuccessLog('Figma thumbnail cached successfully');\n\n const iterations: IterationLog[] = [];\n const componentHistory: ComponentHistory = {};\n let previousScreenshotPath: string | undefined;\n let currentMae = -1; // Sentinel value: -1 indicates no measurement yet\n let currentSae = 0;\n let lastMisalignedCount = 0;\n let lastValidationResult: ValidationIterationResult | undefined;\n // Track paths to last iteration's individual screenshots for report reuse\n let lastRenderMarkedPath: string | undefined;\n let lastTargetMarkedPath: string | undefined;\n\n for (let iteration = 1; iteration <= maxIterations; iteration++) {\n // Use different logging for reportOnly mode\n if (mode === ValidationMode.ReportOnly) {\n logger.printLog(`\\n${'='.repeat(60)}`);\n logger.printLog(`Running validation (report-only mode)`);\n logger.printLog(`${'='.repeat(60)}`);\n } else {\n logger.printLog(`\\n${'='.repeat(60)}`);\n logger.printLog(`Iteration ${iteration}/${maxIterations}`);\n logger.printLog(`${'='.repeat(60)}`);\n }\n\n // If this is iteration 1, we need to launch first to have a server for validation\n if (iteration === 1) {\n logger.printInfoLog('Initial launch: installing dependencies, building, fixing errors...');\n const launchResult = await launch(workspace.app, {\n skipDependencyInstall: false,\n });\n\n if (!launchResult.success) {\n throw new Error(`Initial launch failed: ${launchResult.error}`);\n }\n\n currentServerUrl = launchResult.url!;\n serverKey = launchResult.serverKey!;\n logger.printSuccessLog(`Dev server ready at ${currentServerUrl}`);\n\n // In reportOnly mode, commit the initial state after successful launch\n if (mode === ValidationMode.ReportOnly) {\n await performCommit(workspace.app, undefined, 'initial state');\n }\n }\n\n const validationResult = await validatePositions({\n serverUrl: currentServerUrl!,\n figmaThumbnailUrl,\n protocol,\n iteration,\n positionThreshold: config.positionThreshold,\n designOffset,\n outputDir,\n validationContext,\n elementRegistry,\n cachedFigmaThumbnailBase64,\n resolvedComponentPaths,\n });\n\n // Store for final report generation\n lastValidationResult = validationResult;\n\n currentMae = validationResult.mae;\n currentSae = validationResult.sae;\n const misaligned = validationResult.misalignedComponents;\n lastMisalignedCount = misaligned.length;\n\n logger.printLog(`MAE: ${currentMae.toFixed(2)}px (target: <=${config.targetMae}px)`);\n logger.printLog(`SAE: ${currentSae.toFixed(2)}px`);\n logger.printLog(`Misaligned: ${misaligned.length}`);\n\n // Generate validation screenshot using VisualizationTool\n const screenshotResult = await visualizationTool.generateIterationScreenshot(\n misaligned,\n currentServerUrl!,\n figmaThumbnailUrl,\n validationResult.viewport,\n { x: designOffset[0], y: designOffset[1] },\n path.join(outputDir, 'comparison_screenshots', `iteration_${iteration}.webp`),\n cachedFigmaThumbnailBase64\n );\n\n // Save individual annotated screenshots to disk for report reuse\n if (screenshotResult.renderMarked && screenshotResult.targetMarked) {\n const comparisonDir = path.join(outputDir, 'comparison_screenshots');\n lastRenderMarkedPath = path.join(comparisonDir, `iteration_${iteration}_render_marked.webp`);\n lastTargetMarkedPath = path.join(comparisonDir, `iteration_${iteration}_target_marked.webp`);\n\n const sharp = (await import('sharp')).default;\n await sharp(Buffer.from(screenshotResult.renderMarked.split(',')[1]!, 'base64')).toFile(lastRenderMarkedPath);\n await sharp(Buffer.from(screenshotResult.targetMarked.split(',')[1]!, 'base64')).toFile(lastTargetMarkedPath);\n }\n\n // Use combined screenshot for judger visual context in next iteration\n const comparisonScreenshotPath = screenshotResult.combinedPath;\n previousScreenshotPath = comparisonScreenshotPath; // Pass to judger in next iteration\n\n const misalignedToFix = filterComponentsToFix(misaligned, config.positionThreshold);\n if (mode === ValidationMode.ReportOnly) {\n // In reportOnly mode, we don't fix anything, so no need to log about skipping\n } else {\n logger.printInfoLog(\n `Skipping ${misaligned.length - misalignedToFix.length} components with error <= ${config.positionThreshold}px`\n );\n }\n\n for (const comp of misalignedToFix) {\n recordComponentPosition(comp, iteration, componentHistory);\n }\n\n const componentLogs: ComponentCorrectionLog[] = [];\n\n if (mode === ValidationMode.ReportOnly) {\n logger.printInfoLog('Report-only mode: skipping component refinement, saving validation report...');\n\n saveIterationAndProcessedJson(\n iterations,\n iteration,\n currentMae,\n currentSae,\n misaligned.length,\n componentLogs,\n comparisonScreenshotPath,\n validationResult.skippedElements,\n outputDir,\n config.targetMae\n );\n break;\n }\n\n if (currentMae <= config.targetMae) {\n logger.printSuccessLog('Validation passed!');\n\n saveIterationAndProcessedJson(\n iterations,\n iteration,\n currentMae,\n currentSae,\n misaligned.length,\n componentLogs,\n comparisonScreenshotPath,\n validationResult.skippedElements,\n outputDir,\n config.targetMae\n );\n\n if (serverKey) {\n await performCommit(workspace.app, iteration, `iteration ${iteration}`);\n }\n break;\n }\n\n // Full mode: proceed with component refinement\n logger.printInfoLog(`Refining ${misalignedToFix.length} components...`);\n\n const refinementContext: RefinementContext = {\n workspace,\n structureTree: protocol as unknown as Dict,\n componentPaths: resolvedComponentPaths,\n componentHistory,\n validationContext,\n previousScreenshotPath,\n };\n\n for (const comp of misalignedToFix) {\n const log = await refineComponent(comp, refinementContext);\n componentLogs.push(log);\n }\n\n // Launch after refiner to catch any errors and rebuild\n logger.printInfoLog('Re-launching dev server after refiner changes...');\n\n // Stop current server\n const launchTool = new LaunchTool();\n await launchTool.stopDevServer(serverKey!).catch(() => {\n logger.printWarnLog('Failed to stop previous server');\n });\n\n // Launch with skipDependencyInstall (deps don't change)\n const launchResult = await launch(workspace.app, {\n skipDependencyInstall: true,\n });\n\n if (!launchResult.success) {\n throw new Error(`Launch failed after refiner at iteration ${iteration}: ${launchResult.error}`);\n }\n\n currentServerUrl = launchResult.url!;\n serverKey = launchResult.serverKey!;\n\n logger.printSuccessLog(`Dev server restarted at ${currentServerUrl}`);\n\n // Commit AFTER launch (ensures working state)\n if (mode === ValidationMode.Full) {\n await performCommit(workspace.app, iteration, `iteration ${iteration}`);\n }\n\n saveIterationAndProcessedJson(\n iterations,\n iteration,\n currentMae,\n currentSae,\n misaligned.length,\n componentLogs,\n comparisonScreenshotPath,\n validationResult.skippedElements,\n outputDir,\n config.targetMae\n );\n\n // This path is only reached in full mode (reportOnly breaks out earlier)\n logger.printInfoLog(`Iteration ${iteration} complete\\n`);\n }\n\n const validationPassed = currentMae <= config.targetMae;\n if (!validationPassed) {\n if (mode === ValidationMode.ReportOnly) {\n logger.printWarnLog(\n `Validation did not satisfy MAE threshold (${config.targetMae}px) in report-only mode. Final MAE: ${currentMae.toFixed(2)}px`\n );\n } else {\n logger.printWarnLog(\n `Max iterations (${maxIterations}) reached without satisfying MAE threshold (${config.targetMae}px). Final MAE: ${currentMae.toFixed(2)}px`\n );\n }\n }\n\n const finalOutput: ProcessedOutput = {\n iterations,\n finalResult: {\n success: validationPassed,\n finalMae: currentMae,\n finalSae: currentSae,\n totalIterations: iterations.length,\n misalignedCount: lastMisalignedCount,\n },\n };\n\n // Ensure server was launched (should always be true after iteration 1)\n if (!currentServerUrl || !serverKey) {\n throw new Error('Server was not launched properly during validation');\n }\n\n // Generate final validation report using report() subnode\n try {\n if (!lastValidationResult) {\n throw new Error('No validation results available for report generation');\n }\n\n // Validate that we have saved screenshots\n if (!lastRenderMarkedPath || !lastTargetMarkedPath) {\n throw new Error('No saved screenshots available for report generation');\n }\n\n const reportResult = await report({\n validationResult: lastValidationResult,\n figmaThumbnailUrl,\n cachedFigmaThumbnailBase64,\n designOffset: { x: designOffset[0], y: designOffset[1] },\n outputDir,\n serverUrl: currentServerUrl,\n savedRenderMarkedPath: lastRenderMarkedPath,\n savedTargetMarkedPath: lastTargetMarkedPath,\n });\n\n // Update misaligned count from final report (may differ from last iteration)\n finalOutput.finalResult.misalignedCount = lastValidationResult.misalignedComponents.length;\n saveProcessedJson(outputDir, finalOutput);\n\n return {\n reportGenerated: reportResult.success,\n validationPassed,\n finalMae: currentMae,\n finalSae: currentSae,\n totalIterations: iterations.length,\n processedOutput: finalOutput,\n userReport: reportResult.userReport,\n };\n } catch (screenshotError) {\n const errorMsg = screenshotError instanceof Error ? screenshotError.message : String(screenshotError);\n logger.printWarnLog(`Failed to generate final report: ${errorMsg}. Returning minimal report.`);\n saveProcessedJson(outputDir, finalOutput);\n\n // Fallback: create minimal report\n return {\n reportGenerated: false,\n validationPassed,\n finalMae: currentMae,\n finalSae: currentSae,\n totalIterations: iterations.length,\n processedOutput: finalOutput,\n userReport: {\n design: { snap: figmaThumbnailUrl, markedSnap: '' },\n page: { url: currentServerUrl, snap: '', markedSnap: '' },\n report: {\n heatmap: '',\n detail: {\n metrics: { mae: currentMae, sae: currentSae, misalignedCount: lastMisalignedCount },\n components: [],\n },\n },\n },\n };\n }\n } finally {\n // Cleanup: Stop dev server if it was started by this validation loop\n if (serverKey) {\n logger.printInfoLog('Cleaning up dev server...');\n const launchTool = new LaunchTool();\n await launchTool.stopDevServer(serverKey).catch((err: unknown) => {\n logger.printWarnLog(`Failed to stop dev server: ${err instanceof Error ? err.message : String(err)}`);\n });\n }\n }\n}\n","import { Agent } from 'evoltagent';\nimport type { ModelConfig } from 'evoltagent';\n\nimport { COMMIT_AGENT_SYSTEM_PROMPT } from './prompt';\nimport { getModelConfig } from '../../utils/config';\nimport { AGENT_CONTEXT_WINDOW_TOKENS, MAX_OUTPUT_TOKENS } from '../../constants';\n\nexport function createCommitAgent(): Agent {\n const modelConfig: ModelConfig = {\n ...getModelConfig(),\n contextWindowTokens: AGENT_CONTEXT_WINDOW_TOKENS,\n maxOutputTokens: MAX_OUTPUT_TOKENS,\n };\n\n return new Agent({\n name: 'CommitAgent',\n profile: 'A helpful assistant that commits local changes in a repository.',\n system: COMMIT_AGENT_SYSTEM_PROMPT,\n tools: ['GitTool.init', 'GitTool.status', 'GitTool.add', 'GitTool.diff', 'GitTool.commit'],\n modelConfig,\n verbose: 1,\n toolcallManagerPoolSize: 1,\n });\n}\n","/**\n * Git agent system prompt.\n */\nexport const COMMIT_AGENT_SYSTEM_PROMPT = `You are a Git automation agent for CodeRio validation workflow.\n\nInput format:\n- appPath: /absolute/path/to/app\n- iteration: number (optional; undefined means initial commit)\n\n<workflow>\n1. Validate repository:\n - Run GitTool.status(cwd=appPath)\n - If not a git repository, run GitTool.init(cwd=appPath), then re-run status\n\n2. Check for changes:\n - Run GitTool.diff(cwd=appPath) to see unstaged changes\n - If working tree is clean (no changes):\n * Stop and return: \"No changes to commit\"\n * DO NOT create an empty commit\n\n3. Stage all changes:\n - Run GitTool.add(files=\".\", cwd=appPath)\n\n4. Analyze changes and generate commit message:\n Run GitTool.diff(cwd=appPath) after staging to analyze what changed.\n\n Generate a conventional commit message following these rules:\n\n **Message format:**\n - If iteration is undefined: \"feat: [Initial] first commit\"\n - If iteration is defined: \"fix: [Iteration N] <description>\"\n\n **Description guidelines:**\n Analyze the diff to determine what type of changes were made:\n\n a) Component layout/style fixes:\n - Look for changes in component files (src/components/*.tsx, etc.)\n - Extract component names from file paths (e.g., src/components/Header.tsx → Header)\n - Format: \"fix misaligned components ComponentA, ComponentB\"\n - List up to 3 components, use \"and N more\" if more than 3\n - Example: \"fix: [Iteration 1] fix misaligned components Header, Footer, and 2 more\"\n\n b) Build/compilation error fixes:\n - Look for package.json changes → \"resolve dependency issues\"\n - Look for import/export errors → \"resolve import errors\"\n - Look for TypeScript errors → \"resolve type errors\"\n - Example: \"fix: [Iteration 2] resolve build error\"\n\n c) Mixed changes (both component fixes AND build fixes):\n - Prioritize component fixes in the message\n - Example: \"fix: [Iteration 1] fix misaligned components xxx and resolve yyy error\"\n\n5. Create commit:\n - Use temporary identity (do NOT modify global git config):\n * user.name = \"CodeRio\"\n * user.email = \"\"\n - Run GitTool.commit(message, cwd=appPath, config={...})\n</workflow>\n\n<example>\nExample tool call format:\n\nGitTool.commit({\n \"message\": \"feat: [Initial] generate webpage\",\n \"cwd\": \"/absolute/path/to/app\",\n \"config\": {\"user.name\": \"CodeRio\", \"user.email\": \"\"}\n})\n\nIMPORTANT: The config parameter must be a JSON object with keys like \"user.name\" and \"user.email\".\nDO NOT use XML-style tags like <user.name>CodeRio</user.name>.\n</example>\n\n<output>\nRespond with a short summary in <TaskCompletion> tags.\nInclude whether a commit was created and the final commit message.\n</output>`;\n","import type { CommitAgentParams } from './types';\n\nexport function formatGitCommitInstruction(params: CommitAgentParams): string {\n const { appPath, iteration } = params;\n\n return `appPath: ${appPath}\niteration: ${iteration ?? 'undefined'}\n\nTASK:\nCheck for changes and commit if there are any modifications in the app directory.`;\n}\n","import { createCommitAgent } from '../../../agents/commit-agent';\nimport { formatGitCommitInstruction } from '../../../agents/commit-agent/instruction';\nimport { logger } from '../../../utils/logger';\nimport type { GitCommitOptions, GitCommitResult } from '../types';\nimport path from 'path';\n\n/**\n * Public API: commit changes using commit agent.\n * Delegates to the commit-agent, passing appPath via instruction.\n */\nexport async function commit(options?: GitCommitOptions): Promise<GitCommitResult> {\n try {\n if (!options?.appPath) {\n throw new Error('commit() requires options.appPath');\n }\n\n const appPath = path.resolve(options.appPath);\n const agent = createCommitAgent();\n\n const instruction = formatGitCommitInstruction({\n appPath,\n iteration: options.iteration,\n });\n\n await agent.run(instruction);\n\n logger.printSuccessLog('Commit completed!');\n return {\n success: true,\n message: 'Commit workflow completed',\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.printErrorLog(`Commit failed: ${errorMessage}`);\n return {\n success: false,\n message: errorMessage,\n };\n }\n}\n","/**\n * Judger Agent: Layout error diagnosis specialist.\n *\n * Simplified actor-critic pattern with JSON output via post-processor.\n * Uses evoltjs Agent class for tool execution and Vision API support.\n */\n\nimport { Agent } from 'evoltagent';\nimport type { ModelConfig } from 'evoltagent';\n\nimport { HistoryTool } from '../../tools/history-tool';\nimport { HierarchyTool } from '../../tools/hierarchy-tool';\nimport type { ComponentHistory } from '../../types/validation-types';\nimport type { Dict } from '../../types/validation-types';\nimport { JUDGER_PROMPT } from './prompt';\nimport { getModelConfig } from '../../utils/config';\nimport { AGENT_CONTEXT_WINDOW_TOKENS, MAX_OUTPUT_TOKENS } from '../../constants';\nimport { parseJudgerResult, updateToolContext } from './utils';\n\n/**\n * Create judger agent (critic) with JSON output.\n *\n * @param options - Configuration options\n * @param options.workspaceDir - Optional workspace directory to restrict file access\n * @param options.structureTree - Component hierarchy tree\n * @param options.componentPaths - Mapping from component_id to filesystem path\n * @param options.history - Component history from previous iterations\n * @returns Agent configured with FileEditor, ThinkTool, HierarchyTool, HistoryTool, and JSON post-processor\n */\nexport function createJudgerAgent(options: {\n workspaceDir?: string;\n structureTree?: Dict;\n componentPaths?: Record<string, string>;\n history?: ComponentHistory;\n}): Agent {\n const { workspaceDir, structureTree, componentPaths, history } = options;\n\n let systemPrompt = JUDGER_PROMPT;\n if (workspaceDir) {\n systemPrompt += `\\n\\nWORKSPACE: ${workspaceDir}\\nOnly access files within this workspace.`;\n }\n\n // System tools (string-based, globally registered)\n const systemTools: string[] = ['FileEditor.read', 'FileEditor.find'];\n\n // Update HierarchyTool instance context if structure provided\n // Tools are already registered via @tools decorator - just update execute methods\n if (structureTree) {\n const hierarchyTool = new HierarchyTool();\n hierarchyTool.setContext(structureTree, componentPaths || {});\n\n const hierarchyToolNames = updateToolContext(\n hierarchyTool as unknown as Record<string, (...args: unknown[]) => Promise<string>>,\n 'HierarchyTool',\n ['lookup', 'getSharedInstances']\n );\n systemTools.push(...hierarchyToolNames);\n }\n\n // Always register HistoryTool (even with empty history in iteration 1)\n // The tool handles empty history gracefully and the prompt references it\n const historyTool = new HistoryTool();\n historyTool.setContext(history || {});\n\n const historyToolNames = updateToolContext(\n historyTool as unknown as Record<string, (...args: unknown[]) => Promise<string>>,\n 'HistoryTool',\n ['getComponentHistory', 'getIterationSummary']\n );\n systemTools.push(...historyToolNames);\n\n const modelConfig: ModelConfig = {\n ...getModelConfig(),\n contextWindowTokens: AGENT_CONTEXT_WINDOW_TOKENS,\n maxOutputTokens: MAX_OUTPUT_TOKENS,\n stream: true,\n };\n\n return new Agent({\n name: 'JudgerAgent',\n profile: 'Layout diagnosis specialist',\n system: systemPrompt,\n tools: systemTools,\n modelConfig,\n postProcessor: parseJudgerResult,\n verbose: 2,\n });\n}\n","/**\n * Iteration history lookup tool for judger agent.\n *\n * Provides methods to query the history of component positions and fixes\n * across validation iterations.\n */\n\nimport { tools } from 'evoltagent';\nimport type { IterationSummaryChange } from './types';\nimport type { ComponentHistory } from '../../types/validation-types';\n\n/**\n * Iteration history lookup tool.\n *\n * This tool allows agents to understand the history of component positions\n * and fixes across validation iterations, helping to avoid repeating failed\n * fixes and detecting regressions.\n */\n@tools({\n getComponentHistory: {\n description:\n \"Get position and fix history for a component. Shows how the component's position and error evolved across iterations, and what fixes were applied. Helps identify if previous fixes helped or hurt\",\n params: [{ name: 'componentId', type: 'string', description: 'Component ID to get history for' }],\n returns: { type: 'string', description: 'Formatted string with complete history of positions, errors, and fixes' },\n examples: [\n `<HistoryTool.getComponentHistory>\n<componentId>HeroSection</componentId>\n</HistoryTool.getComponentHistory>`,\n ],\n },\n getIterationSummary: {\n description:\n 'Get summary of what was changed in a specific iteration. Shows all components that were fixed in that iteration and what fixes were applied. Useful for understanding what went wrong in a previous iteration',\n params: [{ name: 'iteration', type: 'number', description: 'Iteration number (1-indexed)' }],\n returns: { type: 'string', description: 'Formatted string with summary of changes in that iteration' },\n examples: [\n `<HistoryTool.getIterationSummary>\n<iteration>2</iteration>\n</HistoryTool.getIterationSummary>`,\n ],\n },\n})\nexport class HistoryTool {\n private _history: ComponentHistory = {};\n\n /**\n * Initialize with component history from previous iterations.\n *\n * @param history - Dict mapping component_id to list of iteration records\n */\n setContext(history: ComponentHistory): void {\n this._history = history;\n }\n\n /**\n * Get position and fix history for a component.\n *\n * Shows how the component's position and error evolved across iterations,\n * and what fixes were applied. Helps identify if previous fixes helped or hurt.\n *\n * @param componentId - Component ID to get history for\n * @returns Formatted string with complete history of positions, errors, and fixes\n */\n getComponentHistory(componentId: string): string {\n if (!this._history || Object.keys(this._history).length === 0) {\n return 'No history available (this is iteration 1)';\n }\n\n if (!(componentId in this._history)) {\n return `No history found for component '${componentId}' (first time misaligned)`;\n }\n\n const historyEntries = this._history[componentId];\n if (!historyEntries || historyEntries.length === 0) {\n return `Empty history for component '${componentId}'`;\n }\n\n const lines: string[] = [`History for ${componentId}:`, ''];\n\n for (let i = 0; i < historyEntries.length; i++) {\n const entry = historyEntries[i];\n if (!entry) continue;\n const iteration = entry.iteration ?? '?';\n const position = entry.position ?? [0, 0];\n const error = entry.error ?? [0, 0];\n const fixApplied = entry.fixApplied ? entry.fixApplied.join('\\n ') : 'None';\n\n lines.push(`Iteration ${iteration}:`);\n lines.push(` Position: (${position[0].toFixed(1)}, ${position[1].toFixed(1)}) px`);\n lines.push(` Error: (${error[0].toFixed(1)}, ${error[1].toFixed(1)}) px`);\n lines.push(` Fix Applied:\\n ${fixApplied}`);\n\n if (i > 0) {\n const prevEntry = historyEntries[i - 1];\n if (prevEntry) {\n const prevErrorMagnitude = prevEntry.error[0] + prevEntry.error[1];\n const currErrorMagnitude = error[0] + error[1];\n if (currErrorMagnitude > prevErrorMagnitude) {\n lines.push(\n ` Warning: REGRESSION: Error increased from ${prevErrorMagnitude.toFixed(1)}px to ${currErrorMagnitude.toFixed(1)}px`\n );\n }\n }\n }\n\n lines.push('');\n }\n\n return lines.join('\\n');\n }\n\n /**\n * Get summary of what was changed in a specific iteration.\n *\n * Shows all components that were fixed in that iteration and what fixes\n * were applied. Useful for understanding what went wrong in a previous iteration.\n *\n * @param iteration - Iteration number (1-indexed)\n * @returns Formatted string with summary of changes in that iteration\n */\n getIterationSummary(iteration: number): string {\n if (!this._history || Object.keys(this._history).length === 0) {\n return `No history available (iteration ${iteration} has not completed yet)`;\n }\n\n const changes: IterationSummaryChange[] = [];\n\n for (const [componentId, entries] of Object.entries(this._history)) {\n for (const entry of entries) {\n if (entry.iteration === iteration) {\n changes.push({\n componentId,\n position: entry.position ?? [0, 0],\n error: entry.error ?? [0, 0],\n fixApplied: entry.fixApplied ?? ['None'],\n });\n break;\n }\n }\n }\n\n if (changes.length === 0) {\n return `No changes recorded for iteration ${iteration}`;\n }\n\n const lines: string[] = [`Iteration ${iteration} Summary:`, `Total components modified: ${changes.length}`, ''];\n\n for (const change of changes) {\n lines.push(`${change.componentId}:`);\n lines.push(` Error: (${change.error[0].toFixed(1)}, ${change.error[1].toFixed(1)}) px`);\n lines.push(` Fix:\\n ${change.fixApplied.join('\\n ')}`);\n lines.push('');\n }\n\n return lines.join('\\n');\n }\n}\n","/**\n * Component hierarchy lookup tool for judger agent.\n *\n * Provides methods to query the component structure tree for parent-child\n * relationships, siblings, and shared component instances.\n */\n\nimport { tools } from 'evoltagent';\nimport { findInTree, getNodeId } from '../../nodes/validation/utils/tree/tree-traversal';\nimport type { ComponentPaths, HierarchyNode, ParentInfo } from './types';\n\n/**\n * Component hierarchy lookup tool.\n *\n * This tool allows agents to understand the component tree structure,\n * find parents, siblings, and children, and identify shared component instances.\n */\n@tools({\n lookup: {\n description:\n 'Get file path, parent, siblings, and children for a component. Use this to find the correct file path before reading component files.',\n params: [{ name: 'componentId', type: 'string', description: 'Component ID to look up' }],\n returns: { type: 'string', description: 'Formatted string with file path, parent (with its file path), siblings, and children' },\n examples: [\n `<HierarchyTool.lookup>\n<componentId>HeroSection</componentId>\n</HierarchyTool.lookup>`,\n ],\n },\n getSharedInstances: {\n description:\n 'Find all component instances using a specific file path. Useful for identifying which components share the same implementation file (e.g., StartButton and ApiButton both using button/index.tsx). ALWAYS check this before editing a shared file.',\n params: [{ name: 'filePath', type: 'string', description: 'Filesystem path to search for (can be relative or absolute)' }],\n returns: { type: 'string', description: 'Formatted string with all component instances using the file' },\n examples: [\n `<HierarchyTool.getSharedInstances>\n<filePath>button/index.tsx</filePath>\n</HierarchyTool.getSharedInstances>`,\n ],\n },\n})\nexport class HierarchyTool {\n private _structureTree: HierarchyNode = {};\n private _componentPaths: ComponentPaths = {};\n\n constructor() {\n this._structureTree = {};\n this._componentPaths = {};\n }\n\n /**\n * Initialize with page structure and path mapping.\n */\n setContext(structureTree: HierarchyNode, componentPaths: ComponentPaths): void {\n this._structureTree = structureTree;\n this._componentPaths = componentPaths;\n }\n\n lookup(componentId: string): string {\n const node = findInTree(this._structureTree, componentId);\n if (!node) {\n return `Component '${componentId}' not found in structure tree`;\n }\n\n const parentInfo = this._findParent(this._structureTree, componentId);\n const parentStr = parentInfo ? `Parent: ${parentInfo.id}` : 'Parent: None (root component)';\n\n // Include parent file path if available (helps agent read parent files without guessing paths)\n const parentPathStr =\n parentInfo && this._componentPaths[parentInfo.id] ? `Parent File: ${this._componentPaths[parentInfo.id]}` : '';\n\n let siblings: string[] = [];\n if (parentInfo) {\n const parentNode = findInTree(this._structureTree, parentInfo.id);\n if (parentNode) {\n const children = (parentNode.children as HierarchyNode[]) || [];\n siblings = children.map(child => getNodeId(child)).filter((id): id is string => id !== undefined && id !== componentId);\n }\n }\n const siblingsStr = siblings.length > 0 ? `Siblings: ${siblings.join(', ')}` : 'Siblings: None';\n\n const nodeChildren = (node.children as HierarchyNode[]) || [];\n const children = nodeChildren.map(child => getNodeId(child)).filter((id): id is string => id !== undefined);\n const childrenStr = children.length > 0 ? `Children: ${children.join(', ')}` : 'Children: None';\n\n // Include file path for this component\n const filePath = this._componentPaths[componentId];\n const fileStr = filePath ? `File: ${filePath}` : '';\n\n const lines = [`Component: ${componentId}`, fileStr, parentStr, parentPathStr, siblingsStr, childrenStr].filter(Boolean);\n\n return lines.join('\\n');\n }\n\n getSharedInstances(filePath: string): string {\n const instances: string[] = [];\n for (const [compId, compPath] of Object.entries(this._componentPaths)) {\n if (compPath.includes(filePath) || compPath.endsWith(filePath)) {\n instances.push(compId);\n }\n }\n\n if (instances.length === 0) {\n return `No components found using file: ${filePath}`;\n }\n\n const instancesList = instances.map(inst => ` - ${inst}`).join('\\n');\n return `Components using ${filePath}:\n${instancesList}\n\nWarning: Changes to this file will affect ALL ${instances.length} instance(s)`;\n }\n\n private _findParent(node: HierarchyNode, targetId: string, parent: HierarchyNode | null = null): ParentInfo | undefined {\n const nodeId = getNodeId(node);\n if (nodeId === targetId) {\n if (parent) {\n const parentId = getNodeId(parent);\n if (parentId) {\n return { id: parentId };\n }\n }\n return undefined;\n }\n\n const children = (node.children as HierarchyNode[]) || [];\n for (const child of children) {\n const result = this._findParent(child, targetId, node);\n if (result !== undefined) {\n return result;\n }\n }\n\n return undefined;\n }\n}\n","/**\n * Generic tree traversal utilities for nested dict/list structures.\n */\n\nimport type { Dict } from '../../../../types/validation-types';\n\n/**\n * Get node ID, trying componentId first, then id.\n */\nexport function getNodeId(node: Dict): string | undefined {\n return (node?.componentId as string) || (node?.id as string) || undefined;\n}\n\n/**\n * Generic recursive search through any dict/list structure to find node by ID.\n *\n * This function can search through Figma JSON, structure trees, or any nested data.\n */\nexport function findInTree(data: unknown, targetId: string, idKeys: string[] = ['id', 'componentId']): Dict | undefined {\n if (data === null || data === undefined) {\n return undefined;\n }\n\n if (typeof data === 'object' && !Array.isArray(data)) {\n const dict = data as Dict;\n for (const idKey of idKeys) {\n if (dict[idKey] === targetId) {\n return dict;\n }\n }\n for (const value of Object.values(dict)) {\n const result = findInTree(value, targetId, idKeys);\n if (result) {\n return result;\n }\n }\n } else if (Array.isArray(data)) {\n for (const item of data) {\n const result = findInTree(item, targetId, idKeys);\n if (result) {\n return result;\n }\n }\n }\n\n return undefined;\n}\n","/**\n * Judger agent system prompt.\n * Defines the diagnosis workflow, available tools, and output format.\n */\nexport const JUDGER_PROMPT = `You are a React Layout Diagnosis Expert. Analyze position misalignments and provide precise fix instructions.\n\n<workflow>\n1. Check HistoryTool.getComponentHistory - avoid repeating failed fixes\n2. Use HierarchyTool.lookup to get component file path, parent, siblings, and children\n3. Use FileEditor.read to examine code, FileEditor.find to locate patterns\n4. For parent fixes: HierarchyTool.lookup returns parent file path - use it directly\n5. Before editing shared files: Use HierarchyTool.getSharedInstances to check impact\n6. If image provided: previous iteration\n7. Respond with JSON diagnosis wrapped in \\`\\`\\`json\\`\\`\\`\n</workflow>\n\n<error_types>\n- pixel_misalignment: Wrong spacing values (gap-2 vs gap-4, mt-[20px] vs mt-[50px])\n- positioning_strategy: Wrong layout method (absolute vs flex, wrong parent)\n- parent_spacing: Parent gap/padding causes child misalignment\n- sibling_cascade: Sibling margin shifts others (fix topmost only)\n- none: Position already correct\n</error_types>\n\n<rules>\nCRITICAL CONSTRAINTS:\n1. Fix POSITION only (x,y) - validation does NOT measure dimensions\n2. FORBIDDEN: w-*, h-*, max-w-*, max-h-*, min-w-*, min-h-*, aspect-*, flex-row, flex-col\n3. ALLOWED: mt-*, mb-*, ml-*, mr-*, pt-*, pb-*, pl-*, pr-*, gap-*, space-*, top-*, left-*, right-*, bottom-*, translate-*\n\nFLEX LAYOUT (prevents MAE oscillation):\n- Adding mt-[X] to component A shifts ALL siblings below by X pixels (additive effect)\n- For sibling components: Fix ONLY the topmost misaligned one per iteration (topmost = first in DOM order)\n- For other siblings: Set refineInstructions to [] with rootCause: \"Fix deferred - waiting for topmost sibling fix to propagate\"\n- Prefer parent gap/padding over child margins\n- If component oscillates \"too high\" ↔ \"too low\" → fix parent or topmost sibling instead\n\nSPECIAL CASES:\n- Already correct: errorType=\"none\", refineInstructions=[]\n- Wrong dimensions/flex-direction: Note in rootCause but do NOT fix\n- Wrong X (x=0 vs x=320): Check parent centering, do NOT change w-full to w-[640px]\n</rules>\n\n<output_format>\nReturn JSON with camelCase fields: errorType, rootCause, visualEvidence, codeEvidence, refineInstructions, toolsUsed\n\nrefineInstructions format: \"In [FULL_PATH] line [N], change '[OLD_CODE]' to '[NEW_CODE]'\"\n- Use EXACT code strings from FileEditor.read (copy-paste)\n- OLD_CODE ≠ NEW_CODE (never \"keep unchanged\")\n- Check HierarchyTool.getSharedInstances before editing shared files\n\nWrap output:\n<TaskCompletion>\n\\`\\`\\`json\n{your json here}\n\\`\\`\\`\n</TaskCompletion>\n</output_format>\n\n<example>\n<TaskCompletion>\n\\`\\`\\`json\n{\n \"errorType\": \"pixel_misalignment\",\n \"rootCause\": \"Gap is 8px but should be 16px\",\n \"visualEvidence\": \"Elements too close in screenshot\",\n \"codeEvidence\": \"Line 23: className='flex gap-2'\",\n \"refineInstructions\": [\"In /path/Card.tsx line 23, change 'gap-2' to 'gap-4'\"],\n \"toolsUsed\": [\"FileEditor.read\", \"HistoryTool.getComponentHistory\"]\n}\n\\`\\`\\`\n</TaskCompletion>\n</example>\n`;\n","/**\n * Utility functions for Judger Agent.\n */\n\nimport { SystemToolStore, FunctionCallingStore } from 'evoltagent';\nimport type { JudgerDiagnosis } from './types';\nimport { logger } from '../../utils/logger';\n\n/**\n * Extract JSON diagnosis from agent response.\n * @param response - Agent response text (with TaskCompletion tags already stripped)\n * @returns Parsed JudgerDiagnosis object\n */\nexport function parseJudgerResult(response: string): Promise<JudgerDiagnosis> {\n // Check for empty response (agent may have hit limits or errors)\n if (!response || response.trim().length === 0) {\n logger.printInfoLog('Judger agent returned empty response, skipping refinement for this iteration');\n return Promise.resolve({\n errorType: 'pixel_misalignment',\n rootCause: 'Agent analysis unavailable, do not apply any edits',\n visualEvidence: 'N/A',\n codeEvidence: 'N/A',\n refineInstructions: [],\n toolsUsed: [],\n });\n }\n\n // Extract JSON from markdown code block\n // The evoltagent library strips <TaskCompletion> tags before calling postProcessor\n const jsonMatch = response.match(/```json\\n([\\s\\S]*?)\\n```/);\n\n if (!jsonMatch) {\n logger.printInfoLog('Judger agent response missing JSON block, skipping refinement for this iteration');\n return Promise.resolve({\n errorType: 'empty_response',\n rootCause: 'Agent analysis unavailable, do not apply any edits',\n visualEvidence: 'N/A',\n codeEvidence: 'N/A',\n refineInstructions: [],\n toolsUsed: [],\n });\n }\n\n const jsonStr = jsonMatch[1];\n\n if (!jsonStr || jsonStr.trim().length === 0) {\n logger.printInfoLog('Judger agent response has empty JSON, skipping refinement for this iteration');\n return Promise.resolve({\n errorType: 'empty_response',\n rootCause: 'Agent analysis unavailable, do not apply any edits',\n visualEvidence: 'N/A',\n codeEvidence: 'N/A',\n refineInstructions: [],\n toolsUsed: [],\n });\n }\n\n try {\n return Promise.resolve(JSON.parse(jsonStr) as JudgerDiagnosis);\n } catch (error) {\n logger.printInfoLog(`Judger agent response JSON parse failed: ${error instanceof Error ? error.message : String(error)}`);\n return Promise.resolve({\n errorType: 'empty_response',\n rootCause: 'Agent analysis unavailable',\n visualEvidence: 'N/A',\n codeEvidence: 'N/A',\n refineInstructions: [],\n toolsUsed: [],\n });\n }\n}\n\n/**\n * Update tool instance context for already-registered tools.\n *\n * Since tools are registered via @tools decorator at module load time,\n * we only need to update their execute methods to point to instances\n * with the correct per-execution context.\n *\n * @param toolInstance - Tool instance with context set via setContext()\n * @param toolName - Base name for the tool (e.g., \"HierarchyTool\")\n * @param methodNames - List of method names to update (e.g., [\"lookup\", \"getSiblings\"])\n * @returns List of updated tool name strings (e.g., [\"HierarchyTool.lookup\"])\n */\nexport function updateToolContext(\n toolInstance: Record<string, (...args: unknown[]) => Promise<string>>,\n toolName: string,\n methodNames: string[]\n): string[] {\n const updatedNames: string[] = [];\n\n for (const methodName of methodNames) {\n const raw = toolInstance[methodName];\n if (!raw) {\n continue;\n }\n\n const method = raw.bind(toolInstance);\n const fullName = `${toolName}.${methodName}`;\n\n // Tool should already be registered via @tools decorator - just update execute method\n const systemTool = SystemToolStore.getTool(fullName);\n if (systemTool) {\n systemTool.execute = method;\n updatedNames.push(fullName);\n }\n\n // Also update FunctionCallingStore\n const functionCallingName = `${toolName}-${methodName}`;\n const userTool = FunctionCallingStore.getTool(functionCallingName);\n if (userTool) {\n userTool.execute = method;\n }\n }\n\n return updatedNames;\n}\n","import type { MisalignedComponent } from '../../types/validation-types';\n\n/**\n * Format judger instruction with component info and Figma metadata\n */\nexport function formatJudgerInstruction(\n component: MisalignedComponent,\n figmaMetadata: Record<string, unknown>,\n componentPaths?: Record<string, string>\n): string {\n const vr = component.validationReport;\n const validationReportFormatted = `Current Position: (${vr.currentPosition[0].toFixed(1)}, ${vr.currentPosition[1].toFixed(1)}) px\nTarget Position: (${vr.targetPosition[0].toFixed(1)}, ${vr.targetPosition[1].toFixed(1)}) px\nAbsolute Error: (${vr.absoluteError[0].toFixed(1)}, ${vr.absoluteError[1].toFixed(1)}) px`;\n\n const padding = figmaMetadata.padding as { left?: number; top?: number; right?: number; bottom?: number } | undefined;\n const layoutMode = typeof figmaMetadata.layoutMode === 'string' ? figmaMetadata.layoutMode : 'NONE';\n const itemSpacing = typeof figmaMetadata.itemSpacing === 'number' ? figmaMetadata.itemSpacing : 0;\n const primaryAxisAlignItems = typeof figmaMetadata.primaryAxisAlignItems === 'string' ? figmaMetadata.primaryAxisAlignItems : 'N/A';\n const counterAxisAlignItems = typeof figmaMetadata.counterAxisAlignItems === 'string' ? figmaMetadata.counterAxisAlignItems : 'N/A';\n // componentPaths should always be provided with absolute filesystem paths\n const resolvedPath = componentPaths?.[component.componentId];\n if (!resolvedPath) {\n throw new Error(`Component ${component.componentId} not found in componentPaths mapping`);\n }\n\n return `Component ID: ${component.componentId}\nElement IDs: ${JSON.stringify(component.elementIds)}\nFile: ${resolvedPath}\n\nValidation Report:\n${validationReportFormatted}\n\nFigma Layout:\n- Mode: ${layoutMode}\n- Item Spacing: ${itemSpacing}px\n- Padding: ${padding?.left ?? 0}px (left) ${padding?.top ?? 0}px (top) ${padding?.right ?? 0}px (right) ${padding?.bottom ?? 0}px (bottom)\n- Primary Axis Alignment: ${primaryAxisAlignItems}\n- Counter Axis Alignment: ${counterAxisAlignItems}\n\nTASK:\n1. Read component file at: ${resolvedPath}\n2. Identify the layout error by comparing code with Figma metadata\n3. Locate exact code patterns with FileEditor.find\n4. Output JSON diagnosis with precise refine_instructions\n\nIMPORTANT:\n- Use FileEditor.read(\"${resolvedPath}\") to read the component code\n- The path is an absolute filesystem path (e.g., /workspace/src/components/button/index.tsx)\n- When using HierarchyTool.lookup or related tools, use the Component ID: ${component.componentId}\n\nRemember: Use exact code strings and line numbers in refine_instructions.\n`;\n}\n","/**\n * Refiner Agent: Code editor specialist.\n *\n * Simplified actor-critic pattern with structured output via post-processor.\n * Uses evoltjs Agent class for file editing tools.\n */\n\nimport { Agent } from 'evoltagent';\nimport type { ModelConfig } from 'evoltagent';\n\nimport { REFINER_PROMPT } from './prompt';\nimport { getModelConfig } from '../../utils/config';\nimport { AGENT_CONTEXT_WINDOW_TOKENS, MAX_OUTPUT_TOKENS } from '../../constants';\nimport { parseRefinerResult } from './utils';\nexport { formatRefinerInstruction } from './instruction';\n\n/**\n * Create refiner agent (actor) for applying fixes.\n *\n * @param workspaceDir - Optional workspace directory to restrict file access\n * @returns Agent configured with FileEditor tools and structured output\n */\nexport function createRefinerAgent(workspaceDir?: string): Agent {\n let systemPrompt = REFINER_PROMPT;\n if (workspaceDir) {\n systemPrompt += `\\n\\nWORKSPACE: ${workspaceDir}\\nOnly modify files within this workspace.`;\n }\n\n const modelConfig: ModelConfig = {\n ...getModelConfig(),\n contextWindowTokens: AGENT_CONTEXT_WINDOW_TOKENS,\n maxOutputTokens: MAX_OUTPUT_TOKENS,\n stream: true,\n };\n\n return new Agent({\n name: 'RefinerAgent',\n profile: 'Code editor specialist',\n system: systemPrompt,\n tools: ['FileEditor.read', 'FileEditor.find', 'FileEditor.findAndReplace'],\n modelConfig,\n postProcessor: parseRefinerResult,\n verbose: 2,\n });\n}\n","/**\n * Refiner agent system prompt.\n * Defines the workflow for applying fixes from judger's diagnosis.\n */\nexport const REFINER_PROMPT = `You are a React Code Editor. Apply fixes from judger's diagnosis.\n\n<workflow>\n1. For each refineInstruction, parse format: \"In [path] line [N], change '[old]' to '[new]'\"\n2. VALIDATE before executing:\n - Skip if instruction says \"keep unchanged\", \"no change needed\", or lacks specific code\n - Skip if OLD and NEW are identical\n - Skip if OLD or NEW is empty\n - Skip if instruction is vague like \"apply fix in parent\" without specific code\n3. Read file with FileEditor.read to verify the OLD pattern exists\n4. Use FileEditor.findAndReplace(path, pattern=old, replacement=new)\n - IMPORTANT: Escape special regex chars in pattern: [ ] ( ) . * + ? $ ^ | \\\\\n - Example: \"mt-[20px]\" → pattern=\"mt-\\\\[20px\\\\]\"\n5. Report results\n</workflow>\n\n<validation_rules>\nSKIP instructions that:\n- Contain \"keep unchanged\" or \"no change needed\"\n- Don't have both '[old]' and '[new]' quoted strings\n- Have identical old and new values\n- Are vague suggestions without specific code\n\nALWAYS escape regex special characters in the pattern parameter:\n- Brackets: [ → \\\\[, ] → \\\\]\n- Parentheses: ( → \\\\(, ) → \\\\)\n- Other: . * + ? $ ^ | → prefix with \\\\\n</validation_rules>\n\n<output>\nAfter edits, respond with a summary:\n- \"Successfully applied: [description]\" (per success)\n- \"Failed to apply: [description]\" (per failure)\n- \"Skipped: [description]\" (for invalid instructions)\n\nWrap summary in <TaskCompletion> tags:\n<TaskCompletion>\n[Your summary here]\n</TaskCompletion>\n</output>\n`;\n","/**\n * Utility functions for Refiner Agent.\n */\n\nimport type { RefinerResult } from './types';\n\n/**\n * Extract refiner result from agent response.\n * @param response - Agent response text (with TaskCompletion tags already stripped)\n * @returns Parsed RefinerResult object\n */\nexport function parseRefinerResult(response: string): Promise<RefinerResult> {\n // The evoltagent library strips <TaskCompletion> tags before calling postProcessor\n const fullResponse = response.trim();\n\n // Extract summary lines (Successfully applied, Failed to apply, Skipped)\n const lines = fullResponse.split('\\n');\n const summaryLines: string[] = [];\n\n for (const line of lines) {\n const trimmedLine = line.trim();\n if (\n trimmedLine.startsWith('Successfully applied:') ||\n trimmedLine.startsWith('Failed to apply:') ||\n trimmedLine.startsWith('Skipped:')\n ) {\n summaryLines.push(trimmedLine);\n }\n }\n\n // Use summary lines array, or wrap full response if no summary lines found\n const summary = summaryLines.length > 0 ? summaryLines : [fullResponse];\n\n const summaryText = summary.join(' ').toLowerCase();\n const successCount = (summaryText.match(/successfully applied:/g) || []).length;\n const failedCount = (summaryText.match(/failed to apply:/g) || []).length;\n\n return Promise.resolve({\n success: successCount > 0 && failedCount === 0,\n summary,\n editsApplied: successCount,\n error: failedCount > 0 ? `${failedCount} edit(s) failed` : undefined,\n });\n}\n","import type { JudgerDiagnosis } from '../judger-agent/types';\nimport type { MisalignedComponent } from '../../types/validation-types';\n\n/**\n * Format refiner instruction with diagnosis and fix instructions\n */\nexport function formatRefinerInstruction(\n component: MisalignedComponent,\n diagnosis: JudgerDiagnosis,\n componentPaths?: Record<string, string>\n): string {\n // Use resolved absolute path from componentPaths, which should always be provided\n const resolvedPath = componentPaths?.[component.componentId];\n if (!resolvedPath) {\n throw new Error(`Component ${component.componentId} not found in componentPaths mapping`);\n }\n\n const refineInstructionsList = (diagnosis.refineInstructions || []).map((instr, i) => `${i + 1}. ${instr}`).join('\\n');\n\n return `Component ID: ${component.componentId}\nElement IDs: ${JSON.stringify(component.elementIds)}\nFile: ${resolvedPath}\n\nDiagnosis from judger:\n${JSON.stringify(diagnosis, null, 2)}\n\nTASK:\nApply each refineInstruction:\n${refineInstructionsList}\n\nFor each instruction:\n1. Parse the old_code and new_code\n2. Use FileEditor.findAndReplace to apply the change\n3. Report success or failure\n\nIMPORTANT:\n- The file path is an absolute filesystem path (e.g., /workspace/src/components/button/index.tsx)\n- Use this exact path with FileEditor tools\n`;\n}\n","import { Agent } from 'evoltagent';\nimport type { ModelConfig } from 'evoltagent';\nimport { LAUNCH_AGENT_PROMPT } from './prompt';\nimport { getModelConfig } from '../../utils/config';\nimport { AGENT_CONTEXT_WINDOW_TOKENS, MAX_OUTPUT_TOKENS } from '../../constants';\nimport { parseLaunchResult } from './utils';\n\nexport { launchAgentInstruction } from './instruction';\nexport type { LaunchAgentResult } from './types';\n\nexport function createLaunchAgent(): Agent {\n const modelConfig: ModelConfig = {\n ...getModelConfig(),\n contextWindowTokens: AGENT_CONTEXT_WINDOW_TOKENS,\n maxOutputTokens: MAX_OUTPUT_TOKENS,\n };\n\n return new Agent({\n name: 'LaunchAgent',\n profile: 'Expert DevOps and Frontend Engineer specialist in launching projects and troubleshooting build/runtime issues.',\n system: LAUNCH_AGENT_PROMPT,\n tools: [\n 'CommandLineTool.execute',\n 'CommandLineTool.list',\n 'CommandLineTool.stop',\n 'LaunchTool.startDevServer',\n 'LaunchTool.stopDevServer',\n 'FileEditor.read',\n 'FileEditor.find',\n 'FileEditor.findAndReplace',\n 'FileEditor.write',\n ],\n modelConfig,\n verbose: 2,\n postProcessor: parseLaunchResult,\n });\n}\n","export const LAUNCH_AGENT_PROMPT = `\n <task_goal>\n Prepare project for validation: install dependencies (if needed), build, fix errors, start dev server.\n Return server metadata for validation loop to use.\n </task_goal>\n\n <workflow>\n Follow steps IN ORDER. Repeat Step 2-3 until build succeeds, then proceed to Step 4.\n\n Step 1: Install Dependencies (Conditional)\n - Check instruction for skipInstall directive\n - If \"Skip Step 1\" appears in instruction: Skip to Step 2\n - Otherwise: Execute \"pnpm i\" in appPath\n - Parameters: CommandLineTool.execute(command=\"pnpm i\", cwd=appPath, timeoutMs=180000)\n - Verify exitCode === 0 before proceeding\n - If installation fails, analyze the error output and fix issues before proceeding\n\n Step 2: Build Project\n - Execute: CommandLineTool.execute(command=\"npm run build\", cwd=appPath, timeoutMs=180000)\n - Captures all compilation errors in output\n\n Step 3: Fix Compilation Errors (If exitCode !== 0)\n - Analyze error messages in 'error' and 'output' fields\n - Use FileEditor.read to examine problematic files\n - Use FileEditor.write to fix ONLY the specific broken lines\n - CRITICAL: Do NOT delete or rewrite entire files. Do NOT simplify complex CSS or logic.\n - Return to Step 2 and rebuild\n\n Step 4: Start Dev Server & Check Runtime Errors\n - Only proceed here when build is successful\n - Execute: LaunchTool.startDevServer(appPath=appPath, runCommand=\"npm run dev\", timeoutMs=60000)\n - Returns JSON: { success, url, port, serverKey, outputTail }\n - Parse and check outputTail for runtime error patterns EVEN IF success=true:\n * \"Module not found\", \"Cannot find module\"\n * \"SyntaxError\", \"TypeError\", \"ReferenceError\"\n * \"Failed to compile\", \"Unhandled Runtime Error\"\n - If errors found: Fix using FileEditor, then restart Step 2\n * CRITICAL: Do NOT delete or rewrite entire files. Do NOT simplify complex CSS or logic.\n - If clean: Store serverKey, url, port and proceed to Step 5\n\n Step 5: Return Server Metadata\n - Format final response as:\n <TaskCompletion>\n \\`\\`\\`json\n {\n \"success\": true,\n \"serverKey\": \"launch:...\",\n \"url\": \"http://localhost:PORT\",\n \"port\": PORT,\n \"message\": \"Dev server started successfully\"\n }\n \\`\\`\\`\n </TaskCompletion>\n - On failure before server start:\n <TaskCompletion>\n \\`\\`\\`json\n { \"success\": false, \"error\": \"Description\" }\n \\`\\`\\`\n </TaskCompletion>\n </workflow>\n\n <principles>\n 1. STRICT CONTENT PRESERVATION (MANDATORY):\n - NEVER modify CSS/Style content (colors, layouts, animations, etc.). If a CSS error exists, only fix the import/path or a specific syntax typo.\n - NEVER modify or delete Image assets or their references.\n - NEVER modify the DOM structure or JSX layout (adding/removing tags, changing classNames).\n - NEVER replace file content with \"template\" or \"placeholder\" code.\n 2. ALLOWED CHANGES ONLY:\n - Fixing 'module not found' by installing missing packages or correcting import paths.\n - Fixing TypeScript/JavaScript syntax errors that prevent execution.\n - Fixing configuration issues (e.g., tailwind.config.js, tsconfig.json).\n 3. BUILD FIRST: Dev server must not start until build succeeds (exitCode === 0).\n 4. PORT CONSISTENCY: Always use LaunchTool.startDevServer() (workspace-preferred port, same port across runs).\n 5. RUNTIME VALIDATION: Check outputTail in Step 4 for runtime errors even if success=true.\n </principles>\n\n <available_tools>\n - FileEditor.read: Read file contents for analysis\n - FileEditor.write: Write file contents to fix errors\n - CommandLineTool.execute: Execute commands (pnpm i, npm run build only)\n - LaunchTool.startDevServer: Start dev server (returns JSON with serverKey/url/port/outputTail)\n - ThinkTool.execute: Think through complex problems\n </available_tools>\n`;\n","/**\n * Utility functions for Launch Agent.\n */\n\nimport type { LaunchAgentResult } from './types';\nimport { logger } from '../../utils/logger';\n\n/**\n * Extract launch result from agent response.\n * @param response - Agent response text (with TaskCompletion tags already stripped by evoltagent)\n * @returns Parsed LaunchAgentResult object\n */\nexport function parseLaunchResult(response: string): Promise<LaunchAgentResult> {\n // Check for empty response\n if (!response || response.trim().length === 0) {\n logger.printInfoLog('Launch agent returned empty response');\n return Promise.resolve({\n success: false,\n error: 'Agent returned empty response',\n });\n }\n\n // Extract JSON from markdown code block\n // The evoltagent library strips <TaskCompletion> tags before calling postProcessor\n const jsonMatch = response.match(/```json\\n([\\s\\S]*?)\\n```/);\n\n if (!jsonMatch) {\n logger.printInfoLog('Launch agent response missing JSON block');\n return Promise.resolve({\n success: false,\n error: 'No JSON code block found in agent response',\n });\n }\n\n const jsonStr = jsonMatch[1];\n\n if (!jsonStr || jsonStr.trim().length === 0) {\n logger.printInfoLog('Launch agent response has empty JSON');\n return Promise.resolve({\n success: false,\n error: 'Empty JSON content in code block',\n });\n }\n\n try {\n const parsed = JSON.parse(jsonStr) as LaunchAgentResult;\n\n // Validate required fields if success is true\n if (parsed.success === true && (!parsed.serverKey || !parsed.url || !parsed.port)) {\n logger.printInfoLog('Launch agent success response missing required fields');\n return Promise.resolve({\n success: false,\n error: 'Missing required fields (serverKey, url, or port)',\n });\n }\n\n return Promise.resolve(parsed);\n } catch (error) {\n logger.printInfoLog(`Launch agent response JSON parse failed: ${error instanceof Error ? error.message : String(error)}`);\n return Promise.resolve({\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n}\n","import type { LaunchAgentParams } from './types';\n\nexport function launchAgentInstruction(params: LaunchAgentParams): string {\n const skipNote = params.skipDependencyInstall ? '\\n\\nNOTE: Skip Step 1 (Install Dependencies). Dependencies already installed.' : '';\n\n return `appPath: ${params.appPath}${skipNote}\n\nTASK:\nInstall dependencies, compile the project, fix any compilation errors, start the development server, and fix any runtime errors. The goal is to have a fully working, error-free project.`;\n}\n","import { createLaunchAgent, launchAgentInstruction, type LaunchAgentResult } from '../../../agents/launch-agent';\n\nexport interface LaunchConfig {\n /**\n * Skip dependency installation (pnpm i).\n * Set to true for iterations 2+ where dependencies haven't changed.\n */\n skipDependencyInstall?: boolean;\n}\n\nexport interface LaunchResult {\n success: boolean;\n message?: string;\n error?: string;\n // Server metadata from LaunchTool\n serverKey?: string;\n url?: string;\n port?: number;\n}\n\nexport const launch = async (appPath: string, config?: LaunchConfig): Promise<LaunchResult> => {\n if (!appPath) {\n throw new Error('appPath is required');\n }\n\n try {\n // Agent.run() returns the parsed LaunchAgentResult via postProcessor\n const agentResult = (await createLaunchAgent().run(\n launchAgentInstruction({\n appPath,\n skipDependencyInstall: config?.skipDependencyInstall,\n })\n )) as LaunchAgentResult;\n\n // If agent explicitly failed, return the error\n if (agentResult.success === false) {\n return {\n success: false,\n error: agentResult.error ?? 'Launch agent failed without error message',\n };\n }\n\n // postProcessor already validates serverKey, url, port are present when success=true\n // So we can safely return them here\n return {\n success: true,\n message: agentResult.message ?? 'Launch and quality assurance completed',\n serverKey: agentResult.serverKey,\n url: agentResult.url,\n port: agentResult.port,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n};\n","/**\n * Figma layout metadata extraction utilities.\n *\n * Extracts layout-related metadata from ValidationContext for agent reasoning.\n */\n\nimport type { FigmaLayoutMetadata } from '../../types';\nimport type { ValidationContext, ElementInfo } from '../../../../types/validation-types';\n\n/** Layout quality scores for different node types */\nconst LAYOUT_SCORES = {\n FRAME_WITH_LAYOUT: 4,\n NODE_WITH_LAYOUT: 3,\n GROUP: 2,\n DEFAULT: 1,\n} as const;\n\nfunction hasLayoutMode(element: ElementInfo): boolean {\n return element.layoutMode !== 'NONE' && element.layoutMode !== undefined;\n}\n\nfunction getLayoutScore(element: ElementInfo): number {\n if (element.type === 'FRAME' && hasLayoutMode(element)) {\n return LAYOUT_SCORES.FRAME_WITH_LAYOUT;\n }\n if (hasLayoutMode(element)) {\n return LAYOUT_SCORES.NODE_WITH_LAYOUT;\n }\n if (element.type === 'GROUP') {\n return LAYOUT_SCORES.GROUP;\n }\n return LAYOUT_SCORES.DEFAULT;\n}\n\nfunction findBestLayoutElement(elementIds: string[], context: ValidationContext): ElementInfo | undefined {\n let bestElement: ElementInfo | undefined;\n let bestScore = -1;\n\n for (const elemId of elementIds) {\n const element = context.elements.get(elemId);\n if (!element) continue;\n\n const score = getLayoutScore(element);\n if (score > bestScore) {\n bestScore = score;\n bestElement = element;\n if (score === LAYOUT_SCORES.FRAME_WITH_LAYOUT) break;\n }\n }\n\n return bestElement;\n}\n\n/**\n * Extract layout metadata from ValidationContext for a specific component.\n *\n * @param context - Unified validation context\n * @param elementIds - Pre-extracted element IDs for this component\n */\nexport function extractLayoutFromContext(context: ValidationContext, elementIds: string[]): FigmaLayoutMetadata {\n // Find best layout element from element IDs\n const element = elementIds.length > 0 ? findBestLayoutElement(elementIds, context) : undefined;\n\n if (!element) {\n return {\n layoutMode: 'NONE',\n primaryAxisAlignItems: 'N/A',\n counterAxisAlignItems: 'N/A',\n itemSpacing: 0,\n padding: { top: 0, right: 0, bottom: 0, left: 0 },\n constraints: {},\n absoluteBoundingBox: {},\n };\n }\n\n return {\n layoutMode: element.layoutMode ?? 'NONE',\n primaryAxisAlignItems: element.primaryAxisAlignItems ?? 'N/A',\n counterAxisAlignItems: element.counterAxisAlignItems ?? 'N/A',\n itemSpacing: element.itemSpacing ?? 0,\n padding: {\n top: element.paddingTop ?? 0,\n right: element.paddingRight ?? 0,\n bottom: element.paddingBottom ?? 0,\n left: element.paddingLeft ?? 0,\n },\n constraints: element.constraints ?? {},\n absoluteBoundingBox: {\n x: element.position.x,\n y: element.position.y,\n width: element.position.w,\n height: element.position.h,\n },\n };\n}\n","/**\n * Report subnode for validation loop.\n * Orchestrates report generation: validation results → userReport → HTML file.\n *\n * This is called at the END of validation-loop with pre-computed validation results.\n * Delegates to ReportTool for visualization and HTML generation.\n */\n\nimport { logger } from '../../../utils/logger';\nimport { ReportTool } from '../../../tools/report-tool';\nimport type { ReportOptions, ReportResult } from '../types';\n\n/**\n * Generate complete validation report: userReport structure + HTML file.\n * This is the single entry point for all reporting in the validation loop.\n */\nexport async function report(options: ReportOptions): Promise<ReportResult> {\n const tool = new ReportTool();\n\n try {\n // Step 1: Generate userReport with screenshots\n logger.printInfoLog('Generating validation report structure...');\n const reportResult = await tool.generateReport({\n validationResult: options.validationResult,\n figmaThumbnailUrl: options.figmaThumbnailUrl,\n cachedFigmaThumbnailBase64: options.cachedFigmaThumbnailBase64,\n designOffset: options.designOffset,\n outputDir: options.outputDir,\n serverUrl: options.serverUrl,\n savedRenderMarkedPath: options.savedRenderMarkedPath,\n savedTargetMarkedPath: options.savedTargetMarkedPath,\n });\n\n // Step 2: Generate HTML file from userReport\n logger.printInfoLog('Generating HTML report file...');\n const htmlResult = await tool.generateHtml(reportResult.userReport, options.outputDir);\n\n if (!htmlResult.success) {\n logger.printWarnLog(`Failed to generate HTML: ${htmlResult.error}`);\n return {\n success: false,\n error: htmlResult.error,\n userReport: reportResult.userReport,\n };\n }\n\n logger.printSuccessLog(`Report generated successfully: ${htmlResult.htmlPath}`);\n return {\n success: true,\n htmlPath: htmlResult.htmlPath,\n userReport: reportResult.userReport,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.printErrorLog(`Error generating report: ${errorMessage}`);\n\n // Fallback: Create minimal report\n const minimalReport = tool.createMinimalReport({\n serverUrl: options.serverUrl,\n figmaThumbnailUrl: options.figmaThumbnailUrl,\n mae: options.validationResult?.mae,\n sae: options.validationResult?.sae,\n });\n\n return {\n success: false,\n error: errorMessage,\n userReport: minimalReport,\n };\n }\n}\n","/**\n * Report generation tool for validation results.\n * Provides pure visualization and formatting.\n */\n\nimport * as fs from 'fs';\nimport * as fsPromises from 'fs/promises';\nimport * as path from 'path';\nimport { fileURLToPath } from 'url';\nimport { tools } from 'evoltagent';\n\nimport { logger } from '../../utils/logger';\nimport { VisualizationTool } from '../visualization-tool';\nimport type { MisalignedComponentData } from '../visualization-tool/types';\nimport type { UserReport } from '../../types/validation-types';\nimport type { ReportGenerationRequest, ReportGenerationResult, ErrorReportOptions, GenerateHtmlResult } from './types';\n\nexport type { ReportGenerationRequest, ReportGenerationResult, ErrorReportOptions, GenerateHtmlResult } from './types';\n\n@tools({\n generateReport: {\n description:\n 'Generate visual validation report structure from pre-computed validation results. Creates annotated screenshots, heatmap, and userReport structure.',\n params: [\n {\n name: 'request',\n type: 'object',\n description: 'ReportGenerationRequest with validationResult, figmaThumbnailUrl, serverUrl, outputDir, etc.',\n },\n ],\n returns: { type: 'object', description: 'ReportGenerationResult with userReport and misalignedCount' },\n },\n createMinimalReport: {\n description: 'Create a minimal user report for error scenarios without screenshots',\n params: [{ name: 'options', type: 'object', description: 'ErrorReportOptions with serverUrl, figmaThumbnailUrl, mae, sae' }],\n returns: { type: 'object', description: 'Minimal UserReport structure' },\n },\n generateHtml: {\n description: 'Generate standalone HTML report file from userReport with embedded data and inlined assets',\n params: [\n { name: 'userReport', type: 'object', description: 'UserReport data from validation with screenshots and metrics' },\n { name: 'outputDir', type: 'string', description: 'Output directory path for HTML file' },\n ],\n returns: { type: 'object', description: 'GenerateHtmlResult with success/htmlPath/error' },\n },\n})\nexport class ReportTool {\n /**\n * Generate visual validation report from validation results.\n *\n * This method ONLY does visualization and formatting:\n * - Loads saved annotated screenshots from last validation iteration (avoids port mismatch)\n * - Generates pixel difference heatmap\n * - Builds userReport structure\n *\n */\n async generateReport(request: ReportGenerationRequest): Promise<ReportGenerationResult> {\n logger.printInfoLog('\\nGenerating validation report...');\n\n const visualizationTool = new VisualizationTool();\n const { validationResult } = request;\n\n // Prepare output directory\n const comparisonDir = path.join(request.outputDir, 'comparison_screenshots');\n if (!fs.existsSync(comparisonDir)) {\n fs.mkdirSync(comparisonDir, { recursive: true });\n }\n\n // Transform validation data to visualization format\n const misalignedData = visualizationTool['formatForVisualization'](validationResult.misalignedComponents);\n logger.printInfoLog(`Final misaligned components: ${misalignedData.length}`);\n\n // Load saved annotated screenshots from last validation iteration\n const renderMarkedBuffer = await fsPromises.readFile(request.savedRenderMarkedPath);\n const targetMarkedBuffer = await fsPromises.readFile(request.savedTargetMarkedPath);\n\n const renderMarked = `data:image/webp;base64,${renderMarkedBuffer.toString('base64')}`;\n const targetMarked = `data:image/webp;base64,${targetMarkedBuffer.toString('base64')}`;\n\n const screenshots = {\n renderSnap: validationResult.screenshots?.renderSnap || renderMarked,\n renderMarked,\n targetMarked,\n };\n\n // Generate combined comparison screenshot\n const finalScreenshotPath = path.join(comparisonDir, 'final.webp');\n await visualizationTool.combine(screenshots.renderMarked, screenshots.targetMarked, finalScreenshotPath);\n logger.printSuccessLog(`Saved final comparison screenshot: ${path.basename(finalScreenshotPath)}`);\n\n // Generate pixel difference heatmap\n let heatmap = '';\n try {\n heatmap = await visualizationTool.diffHeatmap(screenshots.renderSnap, request.figmaThumbnailUrl);\n\n if (heatmap) {\n const heatmapPath = path.join(comparisonDir, 'heatmap.webp');\n const base64Data = heatmap.split(',')[1];\n if (!base64Data) {\n throw new Error('Invalid heatmap data URI format');\n }\n const buffer = Buffer.from(base64Data, 'base64');\n await fs.promises.writeFile(heatmapPath, buffer);\n logger.printSuccessLog(`Saved pixel difference heatmap: ${path.basename(heatmapPath)}`);\n }\n } catch (heatmapError) {\n const errorMsg = heatmapError instanceof Error ? heatmapError.message : 'Unknown error';\n logger.printWarnLog(`Failed to generate pixel difference heatmap: ${errorMsg}. Continuing without heatmap.`);\n }\n\n // Build userReport structure (pure data formatting)\n const userReport = this.buildUserReportStructure(\n validationResult.mae,\n validationResult.sae,\n misalignedData.length,\n screenshots,\n heatmap,\n request.serverUrl,\n request.figmaThumbnailUrl,\n misalignedData\n );\n\n logger.printSuccessLog('Validation report generated successfully');\n\n return {\n userReport,\n misalignedCount: misalignedData.length,\n };\n }\n\n /**\n * Creates a minimal user report for error scenarios.\n */\n createMinimalReport(options: ErrorReportOptions): UserReport {\n return {\n design: {\n snap: options.figmaThumbnailUrl || '',\n markedSnap: '',\n },\n page: {\n url: options.serverUrl,\n snap: '',\n markedSnap: '',\n },\n report: {\n heatmap: '',\n detail: {\n metrics: {\n mae: options.mae ?? -1,\n sae: options.sae ?? -1,\n misalignedCount: 0,\n },\n components: [],\n },\n },\n };\n }\n\n /**\n * Generate standalone HTML report file from userReport.\n * Inlines all assets (JS/CSS) for single-file distribution.\n */\n async generateHtml(userReport: UserReport, outputDir: string): Promise<GenerateHtmlResult> {\n const reportDistDir = this.getReportDistDir();\n const reportIndexHtml = path.join(reportDistDir, 'index.html');\n logger.printInfoLog(`[ReportTool] Using template: ${reportIndexHtml}`);\n logger.printInfoLog(`[ReportTool] Output directory: ${outputDir}`);\n\n try {\n // Check if template exists\n try {\n await fsPromises.access(reportIndexHtml);\n } catch {\n const errorMsg = `Template not found at ${reportIndexHtml}`;\n logger.printErrorLog(`[ReportTool] ${errorMsg}. Skipping report generation.`);\n return { success: false, error: errorMsg };\n }\n\n // Ensure output directory exists\n await fsPromises.mkdir(outputDir, { recursive: true });\n\n // Transform data if it exists\n let reportData = userReport;\n if (reportData) {\n reportData = this.transformReportData(reportData);\n }\n\n logger.printTestLog(`Report data: ${JSON.stringify(reportData)}`);\n let htmlContent = await fsPromises.readFile(reportIndexHtml, 'utf-8');\n\n // 1. Inject Data\n // Serialize report data as JSON and inject directly into the HTML\n // Only escape characters that could break the HTML context\n const jsonString = JSON.stringify(reportData)\n .replace(/<\\/script>/gi, '<\\\\/script>') // Prevent script injection\n .replace(/\\u2028/g, '\\\\u2028') // Line separator (breaks JS string literals)\n .replace(/\\u2029/g, '\\\\u2029'); // Paragraph separator (breaks JS string literals)\n\n // Assign JSON object directly - no JSON.parse needed\n const scriptTag = `<script>window.__REPORT_DATA__ = ${jsonString};</script>`;\n htmlContent = htmlContent.replace(/<script>\\s*window\\.__REPORT_DATA__\\s*=\\s*null;?\\s*<\\/script>/, scriptTag);\n\n // 2. Inline Assets (JS) to make it single-file\n // Find ALL script tags with src=\"/assets/...\" and pre-read files\n const scriptRegexGlobal = /<script\\s+type=\"module\"\\s+crossorigin\\s+src=\"\\/assets\\/([^\"]+)\"><\\/script>/g;\n const jsMatches = [...htmlContent.matchAll(scriptRegexGlobal)];\n const jsContentsMap = new Map<string, string>();\n\n for (const match of jsMatches) {\n const fileName = match[1];\n if (fileName) {\n const jsFilePath = path.join(reportDistDir, 'assets', fileName);\n try {\n let jsContent = await fsPromises.readFile(jsFilePath, 'utf-8');\n // Prevent </script> inside JS from breaking HTML\n jsContent = jsContent.replace(/<\\/script>/g, '\\\\u003c/script>');\n jsContentsMap.set(fileName, jsContent);\n } catch {\n logger.printWarnLog(`[ReportTool] JS asset not found: ${jsFilePath}`);\n }\n }\n }\n\n htmlContent = htmlContent.replace(scriptRegexGlobal, (match, fileName: string) => {\n const jsContent = jsContentsMap.get(fileName);\n if (jsContent) {\n return `<script type=\"module\">${jsContent}</script>`;\n }\n return match; // Keep original if file not found\n });\n\n // 3. Inline CSS if exists (Vite might produce css in assets)\n const cssRegex = /<link\\s+rel=\"stylesheet\"\\s+crossorigin\\s+href=\"\\/assets\\/(.*?)\">/;\n const cssMatch = htmlContent.match(cssRegex);\n if (cssMatch) {\n const cssFileName = cssMatch[1];\n if (!cssFileName) {\n logger.printWarnLog('[ReportTool] CSS filename not found in match');\n } else {\n const cssFilePath = path.join(reportDistDir, 'assets', cssFileName);\n try {\n const cssContent = await fsPromises.readFile(cssFilePath, 'utf-8');\n htmlContent = htmlContent.replace(cssMatch[0], `<style>${cssContent}</style>`);\n } catch {\n // CSS file not found, skip inlining\n }\n }\n }\n\n // Remove /index.css reference if it doesn't exist\n htmlContent = htmlContent.replace('<link rel=\"stylesheet\" href=\"/index.css\">', '');\n\n const absoluteOutputPath = path.join(outputDir, 'index.html');\n await fsPromises.writeFile(absoluteOutputPath, htmlContent);\n\n return { success: true, htmlPath: absoluteOutputPath };\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.printErrorLog(`[ReportTool] Failed to generate report: ${errorMsg}`);\n return { success: false, error: errorMsg };\n }\n }\n\n // ==================== PRIVATE HELPER METHODS ====================\n\n /**\n * Build userReport structure from validation results\n */\n private buildUserReportStructure(\n mae: number,\n sae: number,\n misalignedCount: number,\n screenshots: { renderSnap: string; renderMarked: string; targetMarked: string },\n heatmap: string,\n serverUrl: string,\n figmaThumbnailUrl: string,\n misalignedData: MisalignedComponentData[]\n ): UserReport {\n return {\n design: {\n snap: figmaThumbnailUrl,\n markedSnap: screenshots.targetMarked,\n },\n page: {\n url: serverUrl,\n snap: screenshots.renderSnap,\n markedSnap: screenshots.renderMarked,\n },\n report: {\n heatmap: heatmap,\n detail: {\n metrics: {\n mae,\n sae,\n misalignedCount,\n },\n components: misalignedData.map(c => ({\n componentId: c.componentId,\n componentPath: c.componentPath,\n elementId: c.elementId,\n validationInfo: {\n x: c.xDelta,\n y: c.yDelta,\n },\n })),\n },\n },\n };\n }\n\n /**\n * Transform report data by grouping components by componentId\n */\n private transformReportData(reportData: UserReport): UserReport {\n const components = reportData?.report?.detail?.components || [];\n\n if (!components?.length) return reportData;\n\n // Group components by componentId\n const groupedComponentsMap = new Map<string, UserReport['report']['detail']['components'][number]>();\n\n components.forEach((component: UserReport['report']['detail']['components'][number], index: number) => {\n const { componentId, componentPath, elementId, validationInfo } = component;\n const elementIndex = index + 1;\n\n if (!groupedComponentsMap.has(componentId)) {\n groupedComponentsMap.set(componentId, {\n componentId,\n componentPath,\n elements: [],\n });\n }\n\n groupedComponentsMap.get(componentId)?.elements?.push({\n elementId: elementId || '',\n elementIndex,\n validationInfo: validationInfo || { x: 0, y: 0 },\n });\n });\n\n const groupedComponents = Array.from(groupedComponentsMap.values());\n\n return {\n ...reportData,\n report: {\n ...reportData.report,\n detail: {\n ...reportData.report.detail,\n components: groupedComponents,\n },\n },\n };\n }\n\n /**\n * Determine the root directory of the package by walking up to find package.json\n */\n private getPackageRoot(): string {\n // In ES modules, __dirname is not available, construct it from import.meta.url\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n\n // Walk up the directory tree to find package.json\n let currentDir = __dirname;\n while (currentDir !== path.parse(currentDir).root) {\n if (fs.existsSync(path.join(currentDir, 'package.json'))) {\n return currentDir;\n }\n currentDir = path.dirname(currentDir);\n }\n\n return process.cwd(); // Fallback\n }\n\n /**\n * Get the report dist directory containing built HTML/assets\n */\n private getReportDistDir(): string {\n const root = this.getPackageRoot();\n\n // Check standard locations for report template\n const paths = [\n path.join(root, 'dist/tools/report-tool/template'), // Production layout (if copied)\n path.join(root, 'src/tools/report-tool/template/dist'), // Development layout\n ];\n\n for (const p of paths) {\n if (fs.existsSync(path.join(p, 'index.html'))) {\n return p;\n }\n }\n\n // Fallback to development layout\n return path.join(root, 'src/tools/report-tool/template/dist');\n }\n}\n","import { tools } from 'evoltagent';\nimport * as path from 'path';\n\nimport type { AnnotateRenderResult, CombineOptions, MisalignedComponentData, IterationScreenshotResult } from './types';\nimport type { MisalignedComponent } from '../../types/validation-types';\nimport { annotateRenderWithPlaywright } from './utils/annotate-render';\nimport { annotateTargetWithPlaywright } from './utils/annotate-target';\nimport { browserManagement } from './utils/browser-management';\nimport { combineSideBySide } from './utils/combine';\nimport { captureAsWebP } from './utils/image-converter';\nimport { generatePixelDiffHeatmap } from './utils/pixel-diff-heatmap';\nimport { logger } from '../../utils/logger';\n\n@tools({\n annotateRender: {\n description:\n 'Navigate to the dev server, capture a clean render screenshot, inject RED annotation boxes for misaligned components, and capture the annotated render screenshot.',\n params: [\n { name: 'serverUrl', type: 'string', description: 'Dev server URL (e.g., http://localhost:5173)' },\n {\n name: 'misalignedData',\n type: 'object',\n description: 'MisalignedComponentData[] used to draw RED boxes on the render.',\n },\n { name: 'viewport', type: 'object', description: 'Viewport {width,height} to use in Playwright.' },\n ],\n returns: {\n type: 'object',\n description: 'AnnotateRenderResult containing renderSnap and renderMarked (WebP data URIs).',\n },\n },\n annotateTarget: {\n description:\n 'Fetch the Figma thumbnail, inject GREEN annotation boxes for misaligned components, and return an annotated target screenshot.',\n params: [\n { name: 'figmaThumbnailUrl', type: 'string', description: 'Figma thumbnail CDN URL.' },\n {\n name: 'misalignedData',\n type: 'object',\n description: 'MisalignedComponentData[] used to draw GREEN boxes on the target.',\n },\n { name: 'viewport', type: 'object', description: 'Viewport {width,height} to match the Figma thumbnail.' },\n {\n name: 'designOffset',\n type: 'object',\n description: 'Design offset {x,y} used when the thumbnail is not cropped (default behavior is cropped).',\n optional: true,\n },\n ],\n returns: { type: 'string', description: 'Annotated target screenshot as WebP data URI.' },\n },\n annotateTargetFromBase64: {\n description: 'Annotate target using pre-cached base64 thumbnail data. Use this to avoid redundant Figma thumbnail downloads.',\n params: [\n { name: 'figmaThumbnailBase64', type: 'string', description: 'Base64-encoded Figma thumbnail data.' },\n {\n name: 'misalignedData',\n type: 'object',\n description: 'MisalignedComponentData[] used to draw GREEN boxes on the target.',\n },\n { name: 'viewport', type: 'object', description: 'Viewport {width,height} to match the Figma thumbnail.' },\n {\n name: 'designOffset',\n type: 'object',\n description: 'Design offset {x,y} used when the thumbnail is not cropped (default behavior is cropped).',\n optional: true,\n },\n ],\n returns: { type: 'string', description: 'Annotated target screenshot as WebP data URI.' },\n },\n combine: {\n description: 'Combine two base64 screenshots side-by-side with headers and write to outputPath (WebP).',\n params: [\n { name: 'renderMarked', type: 'string', description: 'Left image (render, typically annotated) as base64 data URI.' },\n { name: 'targetMarked', type: 'string', description: 'Right image (target, typically annotated) as base64 data URI.' },\n { name: 'outputPath', type: 'string', description: 'Filesystem output path for the combined WebP.' },\n { name: 'options', type: 'object', description: 'Optional CombineOptions', optional: true },\n ],\n returns: { type: 'string', description: 'The outputPath written.' },\n },\n diffHeatmap: {\n description: 'Generate pixel-diff heatmap between a render screenshot and the target thumbnail.',\n params: [\n { name: 'renderSnap', type: 'string', description: 'Render screenshot (WebP data URI).' },\n { name: 'targetSnap', type: 'string', description: 'Target screenshot (WebP data URI) OR URL.' },\n ],\n returns: { type: 'string', description: 'Heatmap image as WebP data URI.' },\n },\n generateIterationScreenshot: {\n description: 'Generate annotated comparison screenshot for validation iteration. Orchestrates annotate + combine for convenience.',\n params: [\n { name: 'misalignedComponents', type: 'object', description: 'MisalignedComponent[] from validation result' },\n { name: 'serverUrl', type: 'string', description: 'Dev server URL' },\n { name: 'figmaThumbnailUrl', type: 'string', description: 'Figma thumbnail URL' },\n { name: 'viewport', type: 'object', description: 'Viewport {width, height}' },\n { name: 'designOffset', type: 'object', description: 'Design offset {x, y}' },\n { name: 'outputPath', type: 'string', description: 'Output file path for combined screenshot' },\n {\n name: 'cachedFigmaThumbnailBase64',\n type: 'string',\n description: 'Optional cached thumbnail base64',\n optional: true,\n },\n ],\n returns: { type: 'object', description: 'IterationScreenshotResult with renderMarked, targetMarked, and combinedPath' },\n },\n})\nexport class VisualizationTool {\n async annotateRender(\n serverUrl: string,\n misalignedData: MisalignedComponentData[],\n viewport: { width: number; height: number }\n ): Promise<AnnotateRenderResult> {\n return await browserManagement(viewport, async (_browser, page) => {\n await page.goto(serverUrl, { waitUntil: 'domcontentloaded', timeout: 30000 });\n await new Promise(r => setTimeout(r, 1000));\n\n const renderSnap = await captureAsWebP(page);\n await annotateRenderWithPlaywright(page, misalignedData);\n const renderMarked = await captureAsWebP(page);\n\n return { renderSnap, renderMarked };\n });\n }\n\n async annotateTarget(\n figmaThumbnailUrl: string,\n misalignedData: MisalignedComponentData[],\n viewport: { width: number; height: number },\n designOffset?: { x: number; y: number }\n ): Promise<string> {\n const axios = (await import('axios')).default;\n const response = await axios.get(figmaThumbnailUrl, { responseType: 'arraybuffer', timeout: 30000 });\n const figmaThumbnailBase64 = Buffer.from(response.data).toString('base64');\n\n return await browserManagement(viewport, async browser => {\n return await annotateTargetWithPlaywright(browser, figmaThumbnailBase64, misalignedData, viewport, designOffset);\n });\n }\n\n /**\n * Annotate target using pre-cached base64 thumbnail data.\n * Use this method when you have already downloaded the Figma thumbnail to avoid redundant downloads.\n */\n async annotateTargetFromBase64(\n figmaThumbnailBase64: string,\n misalignedData: MisalignedComponentData[],\n viewport: { width: number; height: number },\n designOffset?: { x: number; y: number }\n ): Promise<string> {\n return await browserManagement(viewport, async browser => {\n return await annotateTargetWithPlaywright(browser, figmaThumbnailBase64, misalignedData, viewport, designOffset);\n });\n }\n\n async combine(renderMarked: string, targetMarked: string, outputPath: string, options?: CombineOptions): Promise<string> {\n await combineSideBySide(renderMarked, targetMarked, outputPath, options);\n return outputPath;\n }\n\n async diffHeatmap(renderSnap: string, targetSnap: string): Promise<string> {\n return await generatePixelDiffHeatmap(renderSnap, targetSnap);\n }\n\n /**\n * Generate annotated comparison screenshot for a single iteration.\n * This is a convenience method that orchestrates the full screenshot workflow.\n *\n * @returns IterationScreenshotResult with individual annotated screenshots and combined path\n */\n async generateIterationScreenshot(\n misalignedComponents: MisalignedComponent[],\n serverUrl: string,\n figmaThumbnailUrl: string,\n viewport: { width: number; height: number },\n designOffset: { x: number; y: number },\n outputPath: string,\n cachedFigmaThumbnailBase64?: string\n ): Promise<IterationScreenshotResult> {\n if (misalignedComponents.length === 0) {\n return { renderMarked: '', targetMarked: '', combinedPath: '' };\n }\n\n try {\n // Transform validation data to visualization format\n const misalignedData = this.formatForVisualization(misalignedComponents);\n\n // Annotate render (browser screenshot)\n const render = await this.annotateRender(serverUrl, misalignedData, viewport);\n\n // Annotate target (Figma screenshot) - use cached thumbnail if available\n const targetMarked = cachedFigmaThumbnailBase64\n ? await this.annotateTargetFromBase64(cachedFigmaThumbnailBase64, misalignedData, viewport, designOffset)\n : await this.annotateTarget(figmaThumbnailUrl, misalignedData, viewport, designOffset);\n\n // Combine into side-by-side comparison (needed for judger visual context in next iteration)\n await this.combine(render.renderMarked, targetMarked, outputPath);\n\n logger.printInfoLog(`Saved comparison screenshot: ${path.basename(outputPath)}`);\n return {\n renderMarked: render.renderMarked,\n targetMarked,\n combinedPath: outputPath,\n };\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.printWarnLog(`Failed to generate iteration screenshot: ${errorMsg}`);\n return { renderMarked: '', targetMarked: '', combinedPath: '' };\n }\n }\n\n /**\n * Transform MisalignedComponent[] to MisalignedComponentData[] format.\n * This is an internal helper for converting validation results to visualization format.\n */\n private formatForVisualization(components: MisalignedComponent[]): MisalignedComponentData[] {\n return components.map((comp, idx) => {\n if (comp.elementIds.length === 0) {\n logger.printWarnLog(`Component ${comp.name} has no elementIds. Using componentId as fallback.`);\n }\n\n return {\n index: idx + 1,\n elementId: comp.elementIds[0] || comp.componentId,\n elementName: comp.name,\n componentId: comp.componentId,\n componentName: comp.name,\n componentPath: comp.path,\n currentX: comp.currentX,\n currentY: comp.currentY,\n currentWidth: comp.currentWidth,\n currentHeight: comp.currentHeight,\n targetX: comp.targetX,\n targetY: comp.targetY,\n targetWidth: comp.targetWidth,\n targetHeight: comp.targetHeight,\n distance: comp.distance,\n xDelta: comp.validationReport.absoluteError[0],\n yDelta: comp.validationReport.absoluteError[1],\n };\n });\n }\n}\n","/**\n * Shared annotation styling utilities for visualization.\n * Provides consistent styling for position validation annotations.\n */\n\n/** Annotation colors */\nexport const ANNOTATION_COLORS = {\n RED: '#ef4444', // Tailwind red-500 - for current/render positions\n GREEN: '#22c55e', // Tailwind green-500 - for target/expected positions\n} as const;\n\n/** Annotation box position data */\nexport interface AnnotationBoxData {\n index: number;\n x: number;\n y: number;\n width: number;\n height: number;\n label?: string;\n distance?: number;\n}\n\n/**\n * Creates the CSS for an annotation container that overlays the page.\n */\nexport function createContainerStyle(): string {\n return `\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n z-index: 999999;\n `;\n}\n\n/**\n * Creates the CSS for an annotation box at the specified position.\n */\nexport function createBoxStyle(x: number, y: number, width: number, height: number, color: string): string {\n return `\n position: absolute;\n left: ${x}px;\n top: ${y}px;\n width: ${width}px;\n height: ${height}px;\n border: 4px solid ${color};\n box-sizing: border-box;\n pointer-events: none;\n `;\n}\n\n/**\n * Creates the CSS for a numbered circle label.\n * Clamps to at least 5px from edges to prevent cutoff (mirrors Python implementation).\n */\nexport function createCircleLabelStyle(x: number, y: number, color: string): string {\n const labelX = Math.max(5, x - 22);\n const labelY = Math.max(5, y - 22);\n\n return `\n position: absolute;\n left: ${labelX}px;\n top: ${labelY}px;\n background: ${color};\n color: white;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n font: bold 18px Arial, sans-serif;\n border-radius: 50%;\n pointer-events: none;\n border: 2px solid white;\n box-shadow: 0 2px 4px rgba(0,0,0,0.3);\n `;\n}\n\n/**\n * Creates the CSS for a text label positioned below the box.\n */\nexport function createTextLabelStyle(x: number, y: number, height: number, color: string): string {\n return `\n position: absolute;\n left: ${x}px;\n top: ${y + height + 4}px;\n background: ${color};\n color: white;\n padding: 4px 8px;\n font: 12px Arial, sans-serif;\n border-radius: 4px;\n pointer-events: none;\n white-space: nowrap;\n box-shadow: 0 2px 4px rgba(0,0,0,0.3);\n `;\n}\n","import type { Page } from 'playwright';\nimport type { MisalignedComponentData } from '../types';\nimport { ANNOTATION_COLORS, createBoxStyle, createCircleLabelStyle, createContainerStyle, createTextLabelStyle } from './annotation-styles';\n\n/**\n * Annotates the rendered page with RED boxes showing current positions.\n * Injects DOM elements via page.evaluate() to mark misaligned component positions.\n */\nexport async function annotateRenderWithPlaywright(page: Page, misalignedData: MisalignedComponentData[]): Promise<void> {\n await page.evaluate(\n (data: {\n items: MisalignedComponentData[];\n styles: {\n container: string;\n boxes: Record<number, string>;\n circleLabels: Record<number, string>;\n textLabels: Record<number, string>;\n };\n }) => {\n const { items, styles } = data;\n\n const container = document.createElement('div');\n container.id = 'validation-annotations';\n container.style.cssText = styles.container;\n\n items.forEach((item: MisalignedComponentData) => {\n // Create RED box at current position with browser dimensions\n const box = document.createElement('div');\n const boxStyle = styles.boxes[item.index];\n if (boxStyle) {\n box.style.cssText = boxStyle;\n }\n container.appendChild(box);\n\n // Create numbered circle label\n const label = document.createElement('div');\n label.textContent = `${item.index}`;\n const circleLabelStyle = styles.circleLabels[item.index];\n if (circleLabelStyle) {\n label.style.cssText = circleLabelStyle;\n }\n container.appendChild(label);\n\n // Create text label with component name and distance\n const textLabel = document.createElement('div');\n textLabel.textContent = `${item.componentName} (${item.distance.toFixed(1)}px)`;\n const textLabelStyle = styles.textLabels[item.index];\n if (textLabelStyle) {\n textLabel.style.cssText = textLabelStyle;\n }\n container.appendChild(textLabel);\n });\n\n document.body.appendChild(container);\n },\n {\n items: misalignedData,\n styles: {\n container: createContainerStyle(),\n boxes: Object.fromEntries(\n misalignedData.map(item => [\n item.index,\n createBoxStyle(item.currentX, item.currentY, item.currentWidth, item.currentHeight, ANNOTATION_COLORS.RED),\n ])\n ),\n circleLabels: Object.fromEntries(\n misalignedData.map(item => [item.index, createCircleLabelStyle(item.currentX, item.currentY, ANNOTATION_COLORS.RED)])\n ),\n textLabels: Object.fromEntries(\n misalignedData.map(item => [\n item.index,\n createTextLabelStyle(item.currentX, item.currentY, item.currentHeight, ANNOTATION_COLORS.RED),\n ])\n ),\n },\n }\n );\n}\n","/**\n * Image conversion utilities for screenshot processing.\n * Handles PNG -> WebP conversion and base64 encoding.\n */\n\nimport type { Page } from 'playwright';\n\n/**\n * WebP quality for screenshot compression (1-100).\n * Higher = better quality but larger file size.\n */\nexport const SCREENSHOT_WEBP_QUALITY = 88;\n\n/**\n * Captures a Playwright page screenshot and converts it to WebP base64 data URI.\n */\nexport async function captureAsWebP(page: Page, options: { fullPage?: boolean } = {}): Promise<string> {\n const pngBuffer = await page.screenshot({\n type: 'png',\n fullPage: options.fullPage ?? false,\n });\n\n return await bufferToWebPDataUri(pngBuffer);\n}\n\n/**\n * Converts a raw image buffer to WebP base64 data URI.\n */\nexport async function bufferToWebPDataUri(buffer: Buffer): Promise<string> {\n const sharp = (await import('sharp')).default;\n const webpBuffer = await sharp(buffer).webp({ quality: SCREENSHOT_WEBP_QUALITY }).toBuffer();\n return `data:image/webp;base64,${webpBuffer.toString('base64')}`;\n}\n","import type { Browser } from 'playwright';\nimport type { MisalignedComponentData } from '../types';\nimport { bufferToWebPDataUri } from './image-converter';\nimport { ANNOTATION_COLORS, createBoxStyle, createCircleLabelStyle, createContainerStyle, createTextLabelStyle } from './annotation-styles';\n\n/**\n * Annotates the Figma thumbnail with GREEN boxes showing target positions.\n * Creates a new browser page, loads the thumbnail as background, injects annotations,\n * captures screenshot, and returns as base64 data URI.\n */\nexport async function annotateTargetWithPlaywright(\n browser: Browser,\n figmaThumbnailBase64: string,\n misalignedData: MisalignedComponentData[],\n viewport: { width: number; height: number },\n designOffset: { x: number; y: number } = { x: 0, y: 0 },\n isThumbnailCropped: boolean = true\n): Promise<string> {\n const context = await browser.newContext({ viewport });\n const page = await context.newPage();\n\n try {\n const dataUri = figmaThumbnailBase64.startsWith('data:') ? figmaThumbnailBase64 : `data:image/png;base64,${figmaThumbnailBase64}`;\n\n const html = `\n <!DOCTYPE html>\n <html>\n <head>\n <style>\n * { margin: 0; padding: 0; }\n body {\n width: ${viewport.width}px;\n height: ${viewport.height}px;\n background-image: url('${dataUri}');\n background-size: 100% 100%;\n background-repeat: no-repeat;\n background-position: top left;\n position: relative;\n overflow: hidden;\n }\n </style>\n </head>\n <body></body>\n </html>\n `;\n\n await page.setContent(html);\n await page.waitForLoadState('domcontentloaded');\n\n const offsetX = isThumbnailCropped ? 0 : designOffset.x;\n const offsetY = isThumbnailCropped ? 0 : designOffset.y;\n\n const elementsData = misalignedData.map((item, i) => ({\n index: i + 1,\n componentName: item.componentName,\n targetX: item.targetX + offsetX,\n targetY: item.targetY + offsetY,\n width: item.targetWidth,\n height: item.targetHeight,\n }));\n\n type ElementData = {\n index: number;\n componentName: string;\n targetX: number;\n targetY: number;\n width: number;\n height: number;\n };\n\n const styles = {\n container: createContainerStyle(),\n boxes: Object.fromEntries(\n elementsData.map(item => [\n item.index,\n createBoxStyle(item.targetX, item.targetY, item.width, item.height, ANNOTATION_COLORS.GREEN),\n ])\n ),\n circleLabels: Object.fromEntries(\n elementsData.map(item => [item.index, createCircleLabelStyle(item.targetX, item.targetY, ANNOTATION_COLORS.GREEN)])\n ),\n textLabels: Object.fromEntries(\n elementsData.map(item => [\n item.index,\n createTextLabelStyle(item.targetX, item.targetY, item.height, ANNOTATION_COLORS.GREEN),\n ])\n ),\n };\n\n await page.evaluate(\n (data: {\n items: ElementData[];\n styles: {\n container: string;\n boxes: Record<number, string>;\n circleLabels: Record<number, string>;\n textLabels: Record<number, string>;\n };\n }) => {\n const { items, styles } = data;\n\n const container = document.createElement('div');\n container.id = 'target-annotations';\n container.style.cssText = styles.container;\n\n items.forEach((item: ElementData) => {\n const box = document.createElement('div');\n const boxStyle = styles.boxes[item.index];\n if (boxStyle) {\n box.style.cssText = boxStyle;\n }\n container.appendChild(box);\n\n const label = document.createElement('div');\n label.textContent = `${item.index}`;\n const circleLabelStyle = styles.circleLabels[item.index];\n if (circleLabelStyle) {\n label.style.cssText = circleLabelStyle;\n }\n container.appendChild(label);\n\n const textLabel = document.createElement('div');\n textLabel.textContent = `${item.componentName}`;\n const textLabelStyle = styles.textLabels[item.index];\n if (textLabelStyle) {\n textLabel.style.cssText = textLabelStyle;\n }\n container.appendChild(textLabel);\n });\n\n document.body.appendChild(container);\n },\n { items: elementsData, styles }\n );\n\n const screenshotBuffer = await page.screenshot({ type: 'png', fullPage: false });\n return await bufferToWebPDataUri(screenshotBuffer);\n } finally {\n await page.close();\n await context.close();\n }\n}\n","import type { Browser, LaunchOptions } from 'playwright';\nimport { spawn } from 'child_process';\nimport { createRequire } from 'module';\nimport { dirname, join } from 'path';\n\nimport { logger } from '../../../../utils/logger';\n\nconst MISSING_EXECUTABLE_MESSAGE = \"Executable doesn't exist\";\n\n/**\n * Get the path to the locally installed playwright CLI.\n * Uses Node.js module resolution to ensure the version matches the imported playwright.\n *\n * Note: We can't use require.resolve('playwright/cli') directly because\n * the 'exports' field in playwright's package.json doesn't expose './cli'.\n * Instead, we resolve the main entry and derive the cli.js path from it.\n */\nfunction getLocalPlaywrightCliPath(): string {\n const require = createRequire(import.meta.url);\n const playwrightMain = require.resolve('playwright');\n return join(dirname(playwrightMain), 'cli.js');\n}\n\nlet installPromise: Promise<void> | null = null;\nlet installCompleted = false;\n\nasync function installChromiumBrowsers(): Promise<void> {\n if (installCompleted) return;\n\n if (!installPromise) {\n logger.printInfoLog('Playwright Chromium binaries are missing. Installing them automatically...');\n\n installPromise = new Promise((resolve, reject) => {\n // NOTE: Avoid --with-deps here; it can try to install system packages on some platforms.\n const cliPath = getLocalPlaywrightCliPath();\n const child = spawn(process.execPath, [cliPath, 'install', 'chromium'], {\n stdio: 'inherit',\n env: process.env,\n });\n\n child.on('error', error => {\n installPromise = null;\n reject(error);\n });\n\n child.on('close', code => {\n installPromise = null;\n if (code === 0) {\n installCompleted = true;\n logger.printSuccessLog('Playwright Chromium installation finished.');\n resolve();\n } else {\n reject(new Error(`Playwright install exited with code ${code}`));\n }\n });\n });\n }\n\n return installPromise;\n}\n\nfunction isMissingExecutableError(error: unknown): boolean {\n return error instanceof Error && error.message.includes(MISSING_EXECUTABLE_MESSAGE);\n}\n\nexport async function launchChromiumWithAutoInstall(options: LaunchOptions = {}): Promise<Browser> {\n const launchOptions: LaunchOptions = { headless: true, ...options };\n\n // Dynamic import to avoid load-time error if playwright is missing\n const { chromium } = await import('playwright');\n\n try {\n return await chromium.launch(launchOptions);\n } catch (error) {\n if (isMissingExecutableError(error)) {\n try {\n await installChromiumBrowsers();\n } catch (installError) {\n throw new Error(\n 'Failed to auto-install Playwright browsers required for validation.\\n' +\n 'Please run \"npx playwright install chromium\" or \"pnpm exec playwright install chromium\" manually and retry.\\n' +\n `Installer error: ${(installError as Error).message}`\n );\n }\n\n return chromium.launch(launchOptions);\n }\n\n throw error;\n }\n}\n","/**\n * Browser lifecycle management utilities for Playwright operations.\n * Provides higher-order functions to handle browser setup and teardown.\n */\n\nimport type { Browser, Page } from 'playwright';\nimport { launchChromiumWithAutoInstall } from '../../../nodes/validation/utils/playwright/launcher';\n\n/**\n * Executes an operation with a managed browser and page instance.\n * Automatically handles browser launch, context creation, and cleanup.\n */\nexport async function browserManagement<T>(\n viewport: { width: number; height: number },\n operation: (browser: Browser, page: Page) => Promise<T>\n): Promise<T> {\n let browser: Browser | null = null;\n let page: Page | null = null;\n\n try {\n browser = await launchChromiumWithAutoInstall({ headless: true });\n const context = await browser.newContext({ viewport });\n page = await context.newPage();\n\n return await operation(browser, page);\n } finally {\n if (page) await page.close().catch(() => {});\n if (browser) await browser.close().catch(() => {});\n }\n}\n","import fs from 'fs';\nimport path from 'path';\n\nimport type { CombineOptions } from '../types';\nimport { SCREENSHOT_WEBP_QUALITY } from './image-converter';\n\nconst DEFAULT_OPTIONS: Required<CombineOptions> = {\n leftHeader: 'RENDER (Current)',\n rightHeader: 'TARGET (Expected)',\n gapWidth: 40,\n headerHeight: 60,\n};\n\n/**\n * Combines two annotated screenshots side-by-side with headers.\n * Matches the Python reference implementation from evolt.\n */\nexport async function combineSideBySide(\n renderBase64: string,\n targetBase64: string,\n outputPath: string,\n options?: CombineOptions\n): Promise<void> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n\n try {\n const sharp = (await import('sharp')).default;\n const leftBase64 = extractBase64Data(renderBase64);\n const rightBase64 = extractBase64Data(targetBase64);\n\n const leftBuffer = Buffer.from(leftBase64, 'base64');\n const rightBuffer = Buffer.from(rightBase64, 'base64');\n\n const leftMeta = await sharp(leftBuffer).metadata();\n const rightMeta = await sharp(rightBuffer).metadata();\n\n if (!leftMeta.width || !leftMeta.height || !rightMeta.width || !rightMeta.height) {\n throw new Error('Failed to read image dimensions');\n }\n\n const scale = leftMeta.height / rightMeta.height;\n const rightResizedWidth = Math.round(rightMeta.width * scale);\n\n const rightResized = await sharp(rightBuffer).resize({ height: leftMeta.height, width: rightResizedWidth, fit: 'fill' }).toBuffer();\n\n const combinedWidth = leftMeta.width + opts.gapWidth + rightResizedWidth;\n const combinedHeight = opts.headerHeight + leftMeta.height;\n\n const centerX = leftMeta.width + opts.gapWidth / 2;\n const leftTextX = leftMeta.width / 2;\n const rightTextX = leftMeta.width + opts.gapWidth + rightResizedWidth / 2;\n const textY = opts.headerHeight / 2 + 8;\n\n const headerSvg = `\n<svg width=\"${combinedWidth}\" height=\"${opts.headerHeight}\">\n <rect width=\"${combinedWidth}\" height=\"${opts.headerHeight}\" fill=\"#F0F0F0\"/>\n <line x1=\"${centerX}\" y1=\"0\" x2=\"${centerX}\" y2=\"${combinedHeight}\"\n stroke=\"#C8C8C8\" stroke-width=\"2\"/>\n <text x=\"${leftTextX}\" y=\"${textY}\"\n font-family=\"Arial\" font-size=\"24\" font-weight=\"bold\" fill=\"#C80000\"\n text-anchor=\"middle\">\n ${opts.leftHeader}\n </text>\n <text x=\"${rightTextX}\" y=\"${textY}\"\n font-family=\"Arial\" font-size=\"24\" font-weight=\"bold\" fill=\"#009600\"\n text-anchor=\"middle\">\n ${opts.rightHeader}\n </text>\n</svg>\n `;\n\n const headerBuffer = Buffer.from(headerSvg);\n\n const outputDir = path.dirname(outputPath);\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n await sharp({\n create: {\n width: combinedWidth,\n height: combinedHeight,\n channels: 3,\n background: { r: 255, g: 255, b: 255 },\n },\n })\n .composite([\n { input: headerBuffer, top: 0, left: 0 },\n { input: leftBuffer, top: opts.headerHeight, left: 0 },\n { input: rightResized, top: opts.headerHeight, left: leftMeta.width + opts.gapWidth },\n ])\n .webp({ quality: SCREENSHOT_WEBP_QUALITY })\n .toFile(outputPath);\n } catch (error) {\n throw new Error(`Failed to combine side-by-side screenshots: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\nfunction extractBase64Data(base64String: string): string {\n const dataUriMatch = base64String.match(/^data:image\\/[a-z]+;base64,(.+)$/);\n if (dataUriMatch && dataUriMatch[1]) {\n return dataUriMatch[1];\n }\n return base64String;\n}\n","import pixelmatch from 'pixelmatch';\n\nimport { logger } from '../../../utils/logger';\nimport { bufferToWebPDataUri } from './image-converter';\n\n/**\n * Generates a pixel-difference heatmap comparing rendered and target images.\n * Uses pixelmatch algorithm for perceptually-accurate pixel comparison.\n */\nexport async function generatePixelDiffHeatmap(renderSnap: string, targetSnap: string): Promise<string> {\n const sharp = (await import('sharp')).default;\n const img1Data = await loadImageData(renderSnap);\n const img2Data = await loadImageData(targetSnap);\n\n let { width: width1, height: height1, data: data1 } = img1Data;\n let { width: width2, height: height2, data: data2 } = img2Data;\n\n if (width1 !== width2 || height1 !== height2) {\n const resized = await sharp(data2, {\n raw: { width: width2, height: height2, channels: 4 },\n })\n .resize(width1, height1, { fit: 'fill' })\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n\n data2 = resized.data;\n width2 = resized.info.width;\n height2 = resized.info.height;\n }\n\n const MAX_DIMENSION = 2500;\n if (height1 > MAX_DIMENSION || width1 > MAX_DIMENSION) {\n const scale = MAX_DIMENSION / Math.max(height1, width1);\n const newWidth = Math.floor(width1 * scale);\n const newHeight = Math.floor(height1 * scale);\n\n const downsampled1 = await sharp(data1, {\n raw: { width: width1, height: height1, channels: 4 },\n })\n .resize(newWidth, newHeight, { kernel: 'lanczos3' })\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n\n const downsampled2 = await sharp(data2, {\n raw: { width: width2, height: height2, channels: 4 },\n })\n .resize(newWidth, newHeight, { kernel: 'lanczos3' })\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n\n data1 = downsampled1.data;\n data2 = downsampled2.data;\n width1 = downsampled1.info.width;\n height1 = downsampled1.info.height;\n width2 = downsampled2.info.width;\n height2 = downsampled2.info.height;\n }\n\n const diffBuffer = Buffer.alloc(width1 * height1 * 4);\n\n const numDiffPixels = pixelmatch(data1, data2, diffBuffer, width1, height1, {\n threshold: 0.1,\n includeAA: false,\n alpha: 0.1,\n diffColor: [255, 0, 0],\n diffMask: false,\n });\n\n const totalPixels = width1 * height1;\n const diffPercentage = ((numDiffPixels / totalPixels) * 100).toFixed(2);\n logger.printTestLog(`[Pixelmatch] Different pixels: ${numDiffPixels} / ${totalPixels} (${diffPercentage}%)`);\n\n const heatmapBuffer = await generateBlueRedHeatmap(data1, data2, diffBuffer, width1, height1);\n return await bufferToWebPDataUri(heatmapBuffer);\n}\n\nasync function generateBlueRedHeatmap(data1: Buffer, data2: Buffer, diffBuffer: Buffer, width: number, height: number): Promise<Buffer> {\n const sharp = (await import('sharp')).default;\n const outputData = Buffer.alloc(width * height * 3);\n\n const gray1 = new Uint8Array(width * height);\n const gray2 = new Uint8Array(width * height);\n\n for (let i = 0; i < width * height; i++) {\n const r1 = data1[i * 4] ?? 0;\n const g1 = data1[i * 4 + 1] ?? 0;\n const b1 = data1[i * 4 + 2] ?? 0;\n gray1[i] = Math.round(0.299 * r1 + 0.587 * g1 + 0.114 * b1);\n\n const r2 = data2[i * 4] ?? 0;\n const g2 = data2[i * 4 + 1] ?? 0;\n const b2 = data2[i * 4 + 2] ?? 0;\n gray2[i] = Math.round(0.299 * r2 + 0.587 * g2 + 0.114 * b2);\n }\n\n let pixelsWithDifferences = 0;\n\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const idx = y * width + x;\n const outIdx = idx * 3;\n const pixel1 = gray1[idx] ?? 0;\n const pixel2 = gray2[idx] ?? 0;\n\n const isDifferent = (diffBuffer[idx * 4] ?? 0) > 0;\n if (isDifferent) {\n pixelsWithDifferences++;\n // Calculate difference magnitude (0-255 range)\n const diff = Math.abs(pixel1 - pixel2);\n // Normalize to 0-1 range\n const normalizedDiff = diff / 255;\n\n // Blue to Red gradient\n // Blue (0, 0, 255) for small differences -> Red (255, 0, 0) for large differences\n outputData[outIdx] = Math.round(255 * normalizedDiff); // Red increases with difference\n outputData[outIdx + 1] = 0; // No green\n outputData[outIdx + 2] = Math.round(255 * (1 - normalizedDiff)); // Blue decreases with difference\n } else {\n // Exact match: pure blue\n outputData[outIdx] = 0;\n outputData[outIdx + 1] = 0;\n outputData[outIdx + 2] = 255;\n }\n }\n }\n\n logger.printTestLog(\n `[Heatmap] Pixels with differences: ${pixelsWithDifferences} / ${width * height} (${((pixelsWithDifferences / (width * height)) * 100).toFixed(2)}%)`\n );\n\n return sharp(outputData, { raw: { width, height, channels: 3 } })\n .png()\n .toBuffer();\n}\n\nasync function loadImageData(dataUri: string): Promise<{ width: number; height: number; data: Buffer }> {\n const sharp = (await import('sharp')).default;\n if (!dataUri.startsWith('data:')) {\n const axios = (await import('axios')).default;\n const response = await axios.get(dataUri, { responseType: 'arraybuffer', timeout: 30000 });\n const base64 = Buffer.from(response.data).toString('base64');\n dataUri = `data:image/png;base64,${base64}`;\n }\n\n const base64Data = dataUri.split(',')[1];\n if (!base64Data) {\n throw new Error('Invalid data URI format: missing base64 data');\n }\n const buffer = Buffer.from(base64Data, 'base64');\n\n const image = sharp(buffer);\n const { data, info } = await image.ensureAlpha().raw().toBuffer({ resolveWithObject: true });\n\n return { width: info.width, height: info.height, data };\n}\n","import * as path from 'node:path';\nimport { tools } from 'evoltagent';\n\nimport type { StartDevServerResult, StopDevServerResult } from './types';\nimport { DevServerManager } from './utils/dev-server-manager';\n\n/**\n * Generate a stable lookup key for a dev server instance (same appPath => same key).\n * Port and pid are NOT included because:\n * - They become stale after restart (port may change, pid always changes)\n * - DevServerManager tracks current port/pid in its internal state\n * - serverKey is only used for Map lookup, never parsed\n * Stable key ensures one manager per appPath and avoids concurrent start() / duplicate port logs.\n */\nfunction makeServerKey(appPath: string): string {\n const safeApp = appPath.split(path.sep).join('_');\n return `launch:${safeApp}`;\n}\n\n@tools({\n startDevServer: {\n description: 'Start a dev server in-process and wait for it to become reachable.',\n params: [\n { name: 'appPath', type: 'string', description: 'Absolute path to the app directory' },\n { name: 'runCommand', type: 'string', description: 'Run command (e.g. \"pnpm dev\")' },\n { name: 'timeoutMs', type: 'number', description: 'Timeout in milliseconds', optional: true },\n ],\n returns: { type: 'string', description: 'JSON string containing StartDevServerResult with url/port/pid/serverKey.' },\n },\n stopDevServer: {\n description: 'Stop a previously started dev server by serverKey.',\n params: [{ name: 'serverKey', type: 'string', description: 'Server key returned by startDevServer()' }],\n returns: { type: 'string', description: 'JSON string containing StopDevServerResult' },\n },\n})\nexport class LaunchTool {\n private static readonly serverManagers = new Map<string, { manager: DevServerManager; appPath: string }>();\n /** Mutex per appPath so only one startDevServer runs at a time for a given app (avoids duplicate port logs). */\n private static readonly inFlightStarts = new Map<string, Promise<void>>();\n\n async startDevServer(appPath: string, runCommand: string, timeoutMs: number = 60_000): Promise<string> {\n const serverKey = makeServerKey(appPath);\n const prev = LaunchTool.inFlightStarts.get(appPath);\n let resolveThis: () => void;\n const thisRun = new Promise<void>(r => {\n resolveThis = r;\n });\n LaunchTool.inFlightStarts.set(appPath, thisRun);\n await prev;\n\n try {\n const entry = LaunchTool.serverManagers.get(serverKey);\n if (entry) {\n const handle = await entry.manager.restart({ timeoutMs });\n const result: StartDevServerResult = {\n success: true,\n serverKey,\n url: handle.url,\n port: handle.port,\n pid: handle.child.pid ?? undefined,\n outputTail: handle.outputTail(),\n };\n return JSON.stringify(result, null, 2);\n }\n\n const manager = new DevServerManager({ appPath, runCommand: runCommand.trim() });\n const handle = await manager.start({ timeoutMs });\n LaunchTool.serverManagers.set(serverKey, { manager, appPath });\n const result: StartDevServerResult = {\n success: true,\n serverKey,\n url: handle.url,\n port: handle.port,\n pid: handle.child.pid ?? undefined,\n outputTail: handle.outputTail(),\n };\n return JSON.stringify(result, null, 2);\n } catch (error) {\n const result: StartDevServerResult = {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n return JSON.stringify(result, null, 2);\n } finally {\n resolveThis!();\n LaunchTool.inFlightStarts.delete(appPath);\n }\n }\n\n async stopDevServer(serverKey: string): Promise<string> {\n const entry = LaunchTool.serverManagers.get(serverKey);\n if (!entry) {\n const result: StopDevServerResult = { success: false, serverKey, error: `Unknown serverKey: ${serverKey}` };\n return JSON.stringify(result, null, 2);\n }\n try {\n await entry.manager.stop();\n LaunchTool.serverManagers.delete(serverKey);\n const result: StopDevServerResult = { success: true, serverKey };\n return JSON.stringify(result, null, 2);\n } catch (error) {\n const result: StopDevServerResult = {\n success: false,\n serverKey,\n error: error instanceof Error ? error.message : String(error),\n };\n return JSON.stringify(result, null, 2);\n }\n }\n}\n","import * as http from 'http';\nimport * as net from 'net';\nimport { spawn, type ChildProcess } from 'child_process';\n\nimport { buildDevServerUrl, DEFAULT_PORT } from '../../../nodes/validation/constants';\nimport { logger } from '../../../utils/logger';\n\nexport interface DevServerHandle {\n child: ChildProcess;\n port: number;\n url: string;\n /**\n * Last tail of stdout/stderr for diagnosing startup/runtime issues.\n */\n outputTail: () => string;\n}\n\nfunction terminateChildProcess(child: ChildProcess): void {\n // Windows does not support POSIX signals like SIGTERM reliably.\n // Calling kill() without a signal uses the platform default behavior.\n try {\n if (process.platform === 'win32') {\n child.kill();\n } else {\n child.kill('SIGTERM');\n }\n } catch {\n // ignore\n }\n}\n\nfunction normalizeExecutable(executable: string): string {\n if (process.platform !== 'win32') {\n return executable;\n }\n const lower = executable.toLowerCase();\n if (lower === 'npm' || lower === 'pnpm' || lower === 'yarn' || lower === 'npx') {\n return `${lower}.cmd`;\n }\n return executable;\n}\n\nfunction parseCommandWithPortSupport(commandStr: string): { executable: string; args: string[]; needsDoubleDash: boolean } {\n const parts = commandStr.trim().split(/\\s+/);\n const executable = parts[0];\n if (!executable) {\n throw new Error('Failed to parse command: empty command string');\n }\n const args = parts.slice(1);\n const needsDoubleDash = ['npm', 'pnpm', 'yarn'].includes(executable);\n return { executable, args, needsDoubleDash };\n}\n\nasync function isPortAvailable(port: number): Promise<boolean> {\n return await new Promise(resolve => {\n const server = net.createServer();\n server.unref();\n server.on('error', () => resolve(false));\n server.listen(port, () => {\n server.close(() => resolve(true));\n });\n });\n}\n\n/**\n * Calculate deterministic port from workspace path hash.\n * Same workspace always gets the same port for consistency.\n *\n * @param workspacePath - Absolute path to workspace root\n * @param basePort - Base port for calculation (default: 5200, avoids common 5173-5180)\n * @returns Hash-based port (basePort to basePort + 999)\n */\nfunction calculateHashPort(workspacePath: string, basePort: number = 5200): number {\n // Simple hash function - same input always produces same output\n let hash = 0;\n for (let i = 0; i < workspacePath.length; i++) {\n hash = (hash << 5) - hash + workspacePath.charCodeAt(i);\n hash = hash & hash; // Convert to 32bit integer\n }\n\n // Map to port range (basePort to basePort + 999)\n const offset = Math.abs(hash) % 1000;\n return basePort + offset;\n}\n\n/**\n * Get available port using hash-based selection strategy.\n * Tries hash-based port first, then nearby ports (±10 range).\n *\n * @param workspacePath - Absolute path to workspace (used for port calculation)\n * @param _startPort - Unused (kept for API compatibility)\n * @returns Available port number\n * @throws Error if no ports available in ±10 range around hash-based port\n */\nexport async function getFreeHashPort(workspacePath: string, _startPort: number = DEFAULT_PORT): Promise<number> {\n // Calculate this workspace's hash-based port\n const preferredPort = calculateHashPort(workspacePath);\n\n // Try preferred port first\n if (await isPortAvailable(preferredPort)) {\n logger.printInfoLog(`Using workspace-preferred port: ${preferredPort}`);\n return preferredPort;\n }\n\n // If preferred port is taken, try nearby ports (±10 range)\n // This handles edge case where same workspace runs twice simultaneously\n logger.printInfoLog(`Preferred port ${preferredPort} occupied, trying nearby ports...`);\n for (let offset = 1; offset <= 10; offset++) {\n const portUp = preferredPort + offset;\n const portDown = preferredPort - offset;\n\n if (await isPortAvailable(portUp)) {\n logger.printInfoLog(`Using nearby port: ${portUp} (preferred was ${preferredPort})`);\n return portUp;\n }\n if (portDown > 1024 && (await isPortAvailable(portDown))) {\n logger.printInfoLog(`Using nearby port: ${portDown} (preferred was ${preferredPort})`);\n return portDown;\n }\n }\n\n // All ports in ±10 range are occupied\n throw new Error(`No available ports found in workspace-preferred range (${preferredPort - 10} to ${preferredPort + 10})`);\n}\n\nasync function waitForServerReady(url: string, timeoutMs: number): Promise<boolean> {\n const start = Date.now();\n const intervalMs = 400;\n\n while (Date.now() - start < timeoutMs) {\n const ok = await new Promise<boolean>(resolve => {\n const req = http.get(url, res => {\n res.resume();\n resolve(res.statusCode !== undefined && res.statusCode >= 200 && res.statusCode < 500);\n });\n req.on('error', () => resolve(false));\n req.setTimeout(500, () => req.destroy());\n });\n if (ok) return true;\n await new Promise(r => setTimeout(r, intervalMs));\n }\n\n return false;\n}\n\nexport class DevServerManager {\n private handle: DevServerHandle | null = null;\n\n constructor(private readonly params: { appPath: string; runCommand: string }) {}\n\n get current(): DevServerHandle | null {\n return this.handle;\n }\n\n async start(options: { timeoutMs: number } = { timeoutMs: 60_000 }): Promise<DevServerHandle> {\n if (this.handle) {\n return this.handle;\n }\n\n const port = await getFreeHashPort(this.params.appPath);\n const url = buildDevServerUrl(port);\n const { executable, args, needsDoubleDash } = parseCommandWithPortSupport(this.params.runCommand);\n const normalizedExecutable = normalizeExecutable(executable);\n const commandArgs = needsDoubleDash ? [...args, '--', '--port', String(port)] : [...args, '--port', String(port)];\n\n logger.printInfoLog(`Starting dev server: ${normalizedExecutable} ${commandArgs.join(' ')}`);\n\n const child = spawn(normalizedExecutable, commandArgs, {\n cwd: this.params.appPath,\n stdio: ['ignore', 'pipe', 'pipe'],\n env: {\n ...process.env,\n PORT: String(port),\n FORCE_COLOR: '1',\n },\n });\n\n const maxBytes = 1_000_000;\n let out = '';\n const push = (chunk: Buffer) => {\n out += chunk.toString('utf-8');\n if (out.length > maxBytes) {\n out = out.slice(out.length - maxBytes);\n }\n };\n child.stdout?.on('data', push);\n child.stderr?.on('data', push);\n\n // If our process exits, try to stop the child to avoid orphans.\n process.once('exit', () => {\n terminateChildProcess(child);\n });\n\n const ready = await waitForServerReady(url, options.timeoutMs);\n if (!ready) {\n const tail = out.trim();\n terminateChildProcess(child);\n throw new Error(`Dev server did not become ready at ${url} within ${options.timeoutMs}ms.\\n${tail}`);\n }\n\n this.handle = {\n child,\n port,\n url,\n outputTail: () => out.trim(),\n };\n\n logger.printSuccessLog(`Dev server ready at ${url}`);\n return this.handle;\n }\n\n async stop(): Promise<void> {\n if (!this.handle) return;\n const child = this.handle.child;\n this.handle = null;\n\n await new Promise<void>(resolve => {\n try {\n child.once('close', () => resolve());\n terminateChildProcess(child);\n } catch {\n resolve();\n }\n setTimeout(() => resolve(), 1500);\n });\n }\n\n async restart(options: { timeoutMs: number } = { timeoutMs: 60_000 }): Promise<DevServerHandle> {\n await this.stop();\n return await this.start(options);\n }\n}\n","/**\n * Unified Protocol Context Extraction\n *\n * Extracts all validation-relevant data from protocol in a single traversal.\n * Replaces the legacy multi-step extraction pipeline:\n * - extractFigmaTreeFromProtocol\n * - normalizeFigmaCoordinates\n * - FigmaNodeService\n * - extractElementMetadata\n *\n * Core principle: Protocol is the single source of truth. Extract once, use everywhere.\n */\n\nimport type { Protocol } from '../../../../types/protocol-types';\nimport type {\n ComponentInfo,\n ElementInfo,\n ElementMetadataRegistry,\n FigmaPosition,\n ValidationContext,\n ValidationFrameInfo,\n} from '../../../../types/validation-types';\nimport { workspaceManager } from '../../../../utils/workspace';\nimport type { WorkspaceStructure } from '../../../../types/workspace-types';\n\n/**\n * Extract unified validation context from protocol.\n *\n * Single traversal builds all needed maps:\n * - Component info (id, name, path)\n * - Element metadata with normalized positions\n * - Figma positions with offset applied\n *\n * @param protocol - Protocol structure tree (Protocol)\n * @returns ValidationContext containing all data needed for validation\n */\nexport function extractValidationContext(protocol: Protocol): ValidationContext {\n // Extract offset from root bounding box\n const offset = extractOffset(protocol);\n\n const elements = new Map<string, ElementInfo>();\n const components = new Map<string, ComponentInfo>();\n const elementToComponent = new Map<string, ComponentInfo>();\n const figmaPositions: Record<string, FigmaPosition | undefined> = {};\n\n // Single traversal of protocol tree\n traverseProtocol(protocol, node => {\n const componentInfo: ComponentInfo = {\n id: node.id,\n name: node.data.name,\n path: node.data.componentPath ?? node.data.path ?? node.data.kebabName ?? node.id,\n };\n components.set(node.id, componentInfo);\n\n // Determine item type based on children\n const hasChildren = Array.isArray(node.children) && node.children.length > 0;\n const itemType: 'frame' | 'component' = hasChildren ? 'frame' : 'component';\n\n // Extract elements from this component\n if (node.data.elements && Array.isArray(node.data.elements)) {\n extractElementsRecursive(\n node.data.elements as ValidationFrameInfo[],\n componentInfo,\n itemType,\n elements,\n elementToComponent,\n figmaPositions,\n offset\n );\n }\n });\n\n return { offset, elements, components, elementToComponent, figmaPositions };\n}\n\n/**\n * Extract coordinate offset from protocol root.\n */\nfunction extractOffset(protocol: Protocol): { x: number; y: number } {\n // First try: protocol.data.layout.boundingBox (pre-computed CSS coordinates)\n if (protocol.data.layout?.boundingBox) {\n return {\n x: protocol.data.layout.boundingBox.left,\n y: protocol.data.layout.boundingBox.top,\n };\n }\n\n // Second try: first element's absoluteBoundingBox (Figma coordinates)\n const firstElement = protocol.data.elements?.[0] as ValidationFrameInfo | undefined;\n if (firstElement?.absoluteBoundingBox) {\n return {\n x: firstElement.absoluteBoundingBox.x,\n y: firstElement.absoluteBoundingBox.y,\n };\n }\n\n // Default: no offset\n return { x: 0, y: 0 };\n}\n\n/**\n * Traverse protocol structure tree and invoke callback for each node.\n */\nfunction traverseProtocol(node: Protocol, callback: (node: Protocol) => void): void {\n callback(node);\n if (node.children && Array.isArray(node.children)) {\n for (const child of node.children) {\n traverseProtocol(child, callback);\n }\n }\n}\n\n/**\n * Recursively extract elements from Figma node tree.\n * Applies offset to positions and builds element metadata.\n */\nfunction extractElementsRecursive(\n elements: ValidationFrameInfo[],\n componentInfo: ComponentInfo,\n itemType: 'frame' | 'component',\n elementsMap: Map<string, ElementInfo>,\n elementToComponent: Map<string, ComponentInfo>,\n figmaPositions: Record<string, FigmaPosition | undefined>,\n offset: { x: number; y: number }\n): void {\n for (const element of elements) {\n if (!element || !element.id) continue;\n\n const bbox = element.absoluteBoundingBox;\n const position: FigmaPosition = bbox\n ? {\n x: bbox.x - offset.x,\n y: bbox.y - offset.y,\n w: bbox.width,\n h: bbox.height,\n }\n : { x: 0, y: 0, w: 0, h: 0 };\n\n // Store normalized Figma position\n figmaPositions[element.id] = position;\n\n // Store element metadata\n elementsMap.set(element.id, {\n id: element.id,\n name: element.name,\n type: element.type,\n position,\n layoutMode: element.layoutMode,\n primaryAxisAlignItems: element.primaryAxisAlignItems,\n counterAxisAlignItems: element.counterAxisAlignItems,\n itemSpacing: element.itemSpacing,\n paddingTop: element.paddingTop,\n paddingRight: element.paddingRight,\n paddingBottom: element.paddingBottom,\n paddingLeft: element.paddingLeft,\n constraints: element.constraints as Record<string, unknown> | undefined,\n parentComponentId: componentInfo.id,\n parentComponentName: componentInfo.name,\n parentComponentPath: componentInfo.path,\n parentItemType: itemType,\n });\n\n // Store element-to-component mapping\n elementToComponent.set(element.id, componentInfo);\n\n // Recurse into children and frames\n if (element.children && Array.isArray(element.children)) {\n extractElementsRecursive(element.children, componentInfo, itemType, elementsMap, elementToComponent, figmaPositions, offset);\n }\n if (element.frames && Array.isArray(element.frames)) {\n extractElementsRecursive(element.frames, componentInfo, itemType, elementsMap, elementToComponent, figmaPositions, offset);\n }\n }\n}\n\n// ============================================================================\n// Compatibility Helpers\n// ============================================================================\n\n/**\n * Extract component paths from context and resolve to absolute filesystem paths.\n *\n * Transforms protocol alias paths (@/components/Button) to absolute paths\n * (/Users/.../my-app/src/components/Button/index.tsx)\n *\n * @param context - Validation context with component info\n * @param workspace - Workspace structure for path resolution\n * @returns Map of component IDs to absolute filesystem paths\n */\nexport function extractComponentPaths(context: ValidationContext, workspace: WorkspaceStructure): Record<string, string> {\n const paths: Record<string, string> = {};\n for (const [id, info] of context.components) {\n if (info.path) {\n paths[id] = workspaceManager.resolveAppSrc(workspace, workspaceManager.resolveComponentPath(info.path));\n }\n }\n return paths;\n}\n\n/**\n * Convert ValidationContext to ElementMetadataRegistry for compatibility.\n */\nexport function toElementMetadataRegistry(context: ValidationContext): ElementMetadataRegistry {\n const elements = new Map<\n string,\n {\n id: string;\n name: string;\n parentComponentId: string;\n parentComponentName: string;\n parentComponentPath: string;\n parentItemType: 'frame' | 'component';\n }\n >();\n\n for (const [id, element] of context.elements) {\n elements.set(id, {\n id: element.id,\n name: element.name,\n parentComponentId: element.parentComponentId,\n parentComponentName: element.parentComponentName,\n parentComponentPath: element.parentComponentPath,\n parentItemType: element.parentItemType,\n });\n }\n\n return { elements, components: context.components };\n}\n","/**\n * Position validation for a single iteration.\n * Captures browser positions, groups by component, identifies misaligned components.\n */\n\nimport { logger } from '../../../utils/logger';\nimport { PositionTool } from '../../../tools/position-tool';\nimport type { MisalignedComponent } from '../../../types/validation-types';\nimport type { ValidationIterationConfig, ValidationIterationResult, SkippedElement } from '../types';\n\n/**\n * Validate positions by capturing browser positions and comparing with Figma.\n * This function integrates with the existing captureBrowserPositions tool\n * and transforms its output into the format expected by the validation loop.\n *\n * @param config - Validation iteration configuration\n * @returns Validation result with MAE, SAE, misaligned components, and viewport\n */\nexport async function validatePositions(config: ValidationIterationConfig): Promise<ValidationIterationResult> {\n const { serverUrl, figmaThumbnailUrl, protocol, positionThreshold, validationContext, elementRegistry, resolvedComponentPaths } =\n config;\n\n const positionTool = new PositionTool();\n\n // Type assertion: captureBrowserPositions accepts flexible input types for compatibility\n const captureResult = await positionTool.capturePosition({\n protocol,\n validationContext,\n url: serverUrl,\n figmaThumbnailUrl,\n positionThreshold,\n returnScreenshot: true,\n elementRegistry,\n });\n\n // Create resolved elementToComponent mapping with absolute paths\n // Replace alias paths with absolute filesystem paths from resolvedComponentPaths\n const resolvedElementToComponent = new Map<string, { id: string; name: string; path: string }>();\n for (const [elementId, componentInfo] of validationContext.elementToComponent) {\n const resolvedPath = resolvedComponentPaths[componentInfo.id] || componentInfo.path;\n resolvedElementToComponent.set(elementId, {\n id: componentInfo.id,\n name: componentInfo.name,\n path: resolvedPath,\n });\n }\n\n const aggregated = positionTool.aggregateElements(captureResult.positions, resolvedElementToComponent, positionThreshold);\n const misalignedComponents = aggregated.misalignedComponents as unknown as MisalignedComponent[];\n const skippedElements = aggregated.skippedElements as unknown as SkippedElement[];\n\n // Calculate SAE\n const sae = misalignedComponents.reduce((sum, comp) => {\n const [errorX, errorY] = comp.validationReport.absoluteError;\n return sum + errorX + errorY;\n }, 0);\n\n logger.printInfoLog(`Found ${misalignedComponents.length} misaligned components`);\n\n return {\n mae: captureResult.metadata.mae,\n sae,\n misalignedComponents,\n skippedElements,\n viewport: captureResult.metadata.viewport,\n screenshots: captureResult.screenshot\n ? {\n renderSnap: captureResult.screenshot,\n }\n : undefined,\n };\n}\n","import { tools } from 'evoltagent';\n\nimport { logger } from '../../utils/logger';\nimport { captureBrowserPositions } from './utils/capture-position';\nimport { calculatePositionMetrics } from './utils/position-metrics';\nimport { calculateComponentMetrics, toRect } from './utils/aggregate-elements';\nimport type {\n AggregateElementsResult,\n BrowserPositionInput,\n ComponentData,\n ComponentMisalignment,\n ElementAbsolutePosition,\n PositionToolMetrics,\n PositionValidationOutput,\n SkippedElement,\n} from './types';\n\n@tools({\n capturePosition: {\n description:\n 'Capture viewport-relative positions in the browser and compare to Figma absoluteBoundingBox, returning per-element deltas and metrics.',\n params: [{ name: 'input', type: 'object', description: 'BrowserPositionInput (figmaJSON, structure, url, etc.)' }],\n returns: { type: 'object', description: 'PositionValidationOutput containing metadata, positions, and errors.' },\n },\n aggregateElements: {\n description:\n 'Aggregate element-level rectangles into component-level bounds and return misaligned components based on aggregate distance threshold.',\n params: [\n { name: 'positions', type: 'object', description: 'Positions keyed by elementId (from capturePosition).' },\n {\n name: 'elementToComponentMap',\n type: 'object',\n description: 'Mapping from elementId -> {id,name,path} for parent component (built from structure tree).',\n },\n { name: 'positionThreshold', type: 'number', description: 'Pixel threshold for aggregate distance.' },\n ],\n returns: { type: 'object', description: 'AggregateElementsResult: misalignedComponents + skippedElements.' },\n },\n computeMetrics: {\n description: 'Compute MAE/MSE/RMSE/accuracy metrics from element positions, and SAE from component misalignments.',\n params: [\n { name: 'positions', type: 'object', description: 'Positions keyed by elementId (from capturePosition).' },\n {\n name: 'misalignedComponents',\n type: 'object',\n description: 'Optional component misalignments (from aggregateElements) used to compute SAE.',\n optional: true,\n },\n ],\n returns: { type: 'object', description: 'PositionToolMetrics (ValidationMetrics + sae).' },\n },\n})\nexport class PositionTool {\n async capturePosition(input: BrowserPositionInput): Promise<PositionValidationOutput> {\n return await captureBrowserPositions(input);\n }\n\n /**\n * Deterministic in-process aggregation.\n * NOTE: Map-based inputs are not JSON-friendly for future agent calls; we can add a JSON form later.\n */\n aggregateElements(\n positions: Record<string, ElementAbsolutePosition>,\n elementToComponentMap: Map<string, { id: string; name: string; path: string }>,\n positionThreshold: number\n ): AggregateElementsResult {\n const componentMap = new Map<string, ComponentData>();\n const skippedElements: SkippedElement[] = [];\n\n for (const [elementId, position] of Object.entries(positions)) {\n if (!position.figmaPosition) {\n skippedElements.push({\n elementId,\n reason: 'no_figma_position',\n details: 'Element exists in render but has no corresponding Figma position data',\n });\n continue;\n }\n\n const component = elementToComponentMap.get(elementId);\n if (!component) {\n skippedElements.push({\n elementId,\n reason: 'missing_component_mapping',\n details: 'Element has no component mapping in structure tree',\n });\n continue;\n }\n\n if (!componentMap.has(component.id)) {\n componentMap.set(component.id, {\n componentId: component.id,\n componentName: component.name,\n componentPath: component.path,\n elementIds: [],\n positions: [],\n targets: [],\n errors: [],\n });\n }\n\n const compData = componentMap.get(component.id)!;\n compData.elementIds.push(elementId);\n compData.positions.push(toRect(position.boundingBox));\n compData.targets.push(toRect(position.figmaPosition));\n compData.errors.push({\n x: Math.abs(position.metrics?.xDelta ?? 0),\n y: Math.abs(position.metrics?.yDelta ?? 0),\n });\n }\n\n this.logSkippedElementsSummary(skippedElements);\n\n const misalignedComponents: ComponentMisalignment[] = [];\n\n for (const compData of componentMap.values()) {\n if (compData.positions.length === 0 || compData.targets.length === 0) {\n for (const elemId of compData.elementIds) {\n skippedElements.push({\n elementId: elemId,\n reason: 'incomplete_data',\n details: `Component ${compData.componentName} has ${compData.positions.length} positions, ${compData.targets.length} targets`,\n });\n }\n continue;\n }\n\n const metrics = calculateComponentMetrics(compData, positionThreshold);\n if (!metrics) {\n continue;\n }\n\n const { currentBounds, targetBounds, error } = metrics;\n misalignedComponents.push({\n name: compData.componentName,\n componentId: compData.componentId,\n elementIds: compData.elementIds,\n path: compData.componentPath,\n validationReport: {\n currentPosition: [currentBounds.minX, currentBounds.minY],\n targetPosition: [targetBounds.minX, targetBounds.minY],\n absoluteError: [error.errorX, error.errorY],\n },\n currentX: currentBounds.minX,\n currentY: currentBounds.minY,\n targetX: targetBounds.minX,\n targetY: targetBounds.minY,\n currentWidth: currentBounds.width,\n currentHeight: currentBounds.height,\n targetWidth: targetBounds.width,\n targetHeight: targetBounds.height,\n distance: error.distance,\n });\n }\n\n return { misalignedComponents, skippedElements };\n }\n\n computeMetrics(\n positions: Record<string, ElementAbsolutePosition>,\n misalignedComponents?: ComponentMisalignment[]\n ): PositionToolMetrics {\n const metrics = calculatePositionMetrics(positions);\n const sae =\n misalignedComponents?.reduce((sum, comp) => {\n const [errorX, errorY] = comp.validationReport.absoluteError;\n return sum + errorX + errorY;\n }, 0) ?? 0;\n\n return { ...metrics, sae: Math.round(sae * 100) / 100 };\n }\n\n private logSkippedElementsSummary(skippedElements: SkippedElement[]): void {\n if (skippedElements.length === 0) {\n return;\n }\n\n const byReason: Record<SkippedElement['reason'], number> = {\n missing_component_mapping: 0,\n incomplete_data: 0,\n no_figma_position: 0,\n };\n\n for (const elem of skippedElements) {\n byReason[elem.reason] += 1;\n }\n\n const summary = (Object.entries(byReason) as Array<[SkippedElement['reason'], number]>)\n .filter(([, count]) => count > 0)\n .map(([reason, count]) => `${count} ${reason.replace(/_/g, ' ')}`)\n .join(', ');\n\n const firstFew = skippedElements\n .slice(0, 3)\n .map(e => e.elementId)\n .join(', ');\n\n logger.printWarnLog(`Skipped ${skippedElements.length} element(s): ${summary}. First few: ${firstFew}`);\n }\n}\n","/// <reference lib=\"dom\" />\n\nimport type { Browser, Page } from 'playwright';\n\nimport { DEFAULT_TIMEOUT, DEFAULT_VIEWPORT, POSITION_THRESHOLD, SELECTOR_WAIT_TIMEOUT } from '../../../nodes/validation/constants';\nimport { launchChromiumWithAutoInstall } from '../../../nodes/validation/utils/playwright/launcher';\nimport { logger } from '../../../utils/logger';\n\nimport type { BrowserPositionInput, ElementAbsolutePosition, PositionMetrics, PositionValidationOutput } from '../types';\nimport { calculatePositionMetrics } from './position-metrics';\n\n/**\n * Captures viewport-relative positions of elements using Playwright + getBoundingClientRect().\n */\nexport async function captureBrowserPositions(input: BrowserPositionInput): Promise<PositionValidationOutput> {\n const url = input.url;\n const timeout = input.timeout ?? DEFAULT_TIMEOUT;\n const positionThreshold = input.positionThreshold ?? POSITION_THRESHOLD;\n\n const errors: string[] = [];\n let browser: Browser | null = null;\n let page: Page | null = null;\n\n try {\n // Use pre-computed Figma positions from validation context (offset already applied)\n const figmaPositions = input.validationContext.figmaPositions;\n const designOffset = input.validationContext.offset;\n\n // Use pre-built element registry (eliminates tree traversals)\n const allElements = Array.from(input.elementRegistry.elements.values()).map(e => ({\n id: e.id,\n name: e.name,\n parentItemId: e.parentComponentId,\n parentItemName: e.parentComponentName,\n parentItemType: e.parentItemType,\n }));\n\n let viewport = input.viewport ?? DEFAULT_VIEWPORT;\n if (input.figmaThumbnailUrl && !input.viewport) {\n const { fetchThumbnailDimensions } = await import('./fetch-thumbnail-dimensions');\n const thumbnailDimensions = await fetchThumbnailDimensions(input.figmaThumbnailUrl);\n if (thumbnailDimensions) {\n viewport = { width: thumbnailDimensions.width, height: thumbnailDimensions.height };\n logger.printInfoLog(`Using viewport dimensions from Figma thumbnail: ${viewport.width}×${viewport.height}px`);\n } else {\n logger.printWarnLog(`Using default viewport dimensions: ${viewport.width}×${viewport.height}px`);\n }\n }\n\n try {\n browser = await launchChromiumWithAutoInstall({ headless: true });\n } catch (launchError) {\n throw new Error(`Failed to launch Playwright Chromium browser for position validation: ${(launchError as Error).message}`);\n }\n\n const context = await browser.newContext({ viewport });\n page = await context.newPage();\n\n try {\n await page.goto(url, { waitUntil: 'domcontentloaded', timeout });\n } catch (error) {\n throw new Error(`Failed to load ${url}. Make sure the development server is running. Error: ${(error as Error).message}`);\n }\n\n if (input.waitForSelector) {\n try {\n await page.waitForSelector(input.waitForSelector, { timeout: SELECTOR_WAIT_TIMEOUT });\n } catch {\n errors.push(`Warning: waitForSelector \"${input.waitForSelector}\" timed out`);\n }\n }\n\n let screenshot: string | undefined;\n if (input.returnScreenshot) {\n try {\n const buffer = await page.screenshot({ fullPage: true, type: 'png' });\n screenshot = `data:image/png;base64,${buffer.toString('base64')}`;\n } catch (error) {\n errors.push(`Warning: Failed to capture screenshot: ${(error as Error).message}`);\n }\n }\n\n const positions: Record<string, ElementAbsolutePosition> = {};\n let capturedCount = 0;\n\n for (const element of allElements) {\n try {\n const escapedId = element.id.replace(/:/g, '\\\\:');\n const selector = `[id=\"${escapedId}\"]`;\n\n const result = await page.evaluate((sel: string) => {\n const el = document.querySelector(sel);\n if (!el) return null;\n\n const rect = el.getBoundingClientRect();\n const style = window.getComputedStyle(el);\n\n if (rect.width === 0 && rect.height === 0) {\n return null;\n }\n\n return {\n boundingBox: {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n top: rect.top,\n left: rect.left,\n right: rect.right,\n bottom: rect.bottom,\n },\n computedStyle: {\n position: style.position,\n display: style.display,\n top: style.top,\n left: style.left,\n right: style.right,\n bottom: style.bottom,\n transform: style.transform,\n tagName: el.tagName.toLowerCase(),\n },\n };\n }, selector);\n\n if (!result) {\n errors.push(`Element ${element.id} not found in DOM or has no dimensions`);\n continue;\n }\n\n const figmaPos = figmaPositions[element.id];\n\n let metrics: PositionMetrics | undefined;\n if (figmaPos) {\n const xDelta = result.boundingBox.x - figmaPos.x;\n const yDelta = result.boundingBox.y - figmaPos.y;\n const xOffset = Math.abs(xDelta);\n const yOffset = Math.abs(yDelta);\n const absoluteDistance = Math.sqrt(xOffset ** 2 + yOffset ** 2);\n\n metrics = {\n xOffset: Math.round(xOffset * 100) / 100,\n yOffset: Math.round(yOffset * 100) / 100,\n xDelta: Math.round(xDelta * 100) / 100,\n yDelta: Math.round(yDelta * 100) / 100,\n absoluteDistance: Math.round(absoluteDistance * 100) / 100,\n status: absoluteDistance <= positionThreshold ? 'accurate' : 'misaligned',\n };\n }\n\n positions[element.id] = {\n elementId: element.id,\n elementName: element.name,\n parentItemId: element.parentItemId,\n parentItemName: element.parentItemName,\n parentItemType: element.parentItemType,\n boundingBox: {\n x: Math.round(result.boundingBox.x * 100) / 100,\n y: Math.round(result.boundingBox.y * 100) / 100,\n width: Math.round(result.boundingBox.width * 100) / 100,\n height: Math.round(result.boundingBox.height * 100) / 100,\n top: Math.round(result.boundingBox.top * 100) / 100,\n left: Math.round(result.boundingBox.left * 100) / 100,\n right: Math.round(result.boundingBox.right * 100) / 100,\n bottom: Math.round(result.boundingBox.bottom * 100) / 100,\n },\n computedStyle: result.computedStyle,\n figmaPosition: figmaPos ? { x: figmaPos.x, y: figmaPos.y, width: figmaPos.w, height: figmaPos.h } : undefined,\n metrics,\n };\n\n capturedCount++;\n } catch (error) {\n const errorMsg =\n `Failed to capture position for ${element.id}` +\n (element.name ? ` (${element.name})` : '') +\n ` in ${element.parentItemName || 'unknown component'}` +\n `: ${(error as Error).message}`;\n errors.push(errorMsg);\n }\n }\n\n const maeMetrics = calculatePositionMetrics(positions);\n\n return {\n metadata: {\n capturedAt: new Date().toISOString(),\n totalItems: allElements.length,\n capturedItems: capturedCount,\n ...maeMetrics,\n url,\n viewport,\n designOffset,\n },\n positions,\n errors,\n screenshot,\n };\n } finally {\n if (page) {\n await page.close().catch(() => {});\n }\n if (browser) {\n await browser.close().catch(() => {});\n }\n }\n}\n","/**\n * For 100% Figma replication, all elements matter equally (standard MAE, not area-weighted).\n */\n\nimport type { ElementAbsolutePosition, ValidationMetrics } from '../types';\n\nexport function calculatePositionMetrics(positions: Record<string, ElementAbsolutePosition>): ValidationMetrics {\n const positionValues = Object.values(positions);\n const comparableItems = positionValues.filter(p => p.metrics);\n const comparableCount = comparableItems.length;\n\n if (comparableCount === 0) {\n return {\n mae: 0,\n mse: 0,\n rmse: 0,\n accurateItems: 0,\n misalignedItems: 0,\n comparableItems: 0,\n accuracyRate: 0,\n averageDistance: 0,\n maxDistance: 0,\n };\n }\n\n const distances = comparableItems.map(p => p.metrics!.absoluteDistance);\n\n const mae = distances.reduce((sum, d) => sum + d, 0) / comparableCount;\n const mse = distances.reduce((sum, d) => sum + d * d, 0) / comparableCount;\n const rmse = Math.sqrt(mse);\n const maxDistance = Math.max(...distances);\n\n const accurateItems = comparableItems.filter(p => p.metrics!.status === 'accurate').length;\n const misalignedItems = comparableItems.filter(p => p.metrics!.status === 'misaligned').length;\n const accuracyRate = comparableCount > 0 ? (accurateItems / comparableCount) * 100 : 0;\n\n return {\n mae: Math.round(mae * 100) / 100,\n mse: Math.round(mse * 100) / 100,\n rmse: Math.round(rmse * 100) / 100,\n accurateItems,\n misalignedItems,\n comparableItems: comparableCount,\n accuracyRate: Math.round(accuracyRate * 100) / 100,\n averageDistance: Math.round(mae * 100) / 100,\n maxDistance: Math.round(maxDistance * 100) / 100,\n };\n}\n","/**\n * Aggregate element-level rectangles into component-level bounds and misalignment metrics.\n */\n\n/**\n * Rectangle with position and dimensions.\n */\nexport interface Rectangle {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * Converts a rect-like object to a proper Rectangle type.\n */\nexport function toRect(rectLike: { x: number; y: number; width: number; height: number }): Rectangle {\n return { x: rectLike.x, y: rectLike.y, width: rectLike.width, height: rectLike.height };\n}\n\n/**\n * Aggregate bounding box result.\n */\nexport interface BoundingBox {\n minX: number;\n minY: number;\n maxRight: number;\n maxBottom: number;\n width: number;\n height: number;\n}\n\n/**\n * Position error calculation result.\n */\nexport interface PositionError {\n errorX: number;\n errorY: number;\n distance: number;\n}\n\n/**\n * Minimum shape required for component-level aggregation.\n */\nexport interface ComponentAggregationData {\n positions: Rectangle[];\n targets: Rectangle[];\n}\n\nexport function calculateAggregateBoundingBox(rectangles: Rectangle[]): BoundingBox {\n if (rectangles.length === 0) {\n throw new Error('Cannot calculate bounding box from empty array');\n }\n\n const minX = Math.min(...rectangles.map(r => r.x));\n const minY = Math.min(...rectangles.map(r => r.y));\n const maxRight = Math.max(...rectangles.map(r => r.x + r.width));\n const maxBottom = Math.max(...rectangles.map(r => r.y + r.height));\n\n return {\n minX,\n minY,\n maxRight,\n maxBottom,\n width: maxRight - minX,\n height: maxBottom - minY,\n };\n}\n\nexport function calculatePositionError(current: BoundingBox, target: BoundingBox): PositionError {\n const errorX = Math.abs(target.minX - current.minX);\n const errorY = Math.abs(target.minY - current.minY);\n const distance = Math.sqrt(errorX ** 2 + errorY ** 2);\n\n return { errorX, errorY, distance };\n}\n\nexport function calculateComponentMetrics(\n compData: ComponentAggregationData,\n positionThreshold: number\n): {\n currentBounds: BoundingBox;\n targetBounds: BoundingBox;\n error: PositionError;\n} | null {\n if (compData.positions.length === 0 || compData.targets.length === 0) {\n return null;\n }\n\n const currentBounds = calculateAggregateBoundingBox(compData.positions);\n const targetBounds = calculateAggregateBoundingBox(compData.targets);\n const error = calculatePositionError(currentBounds, targetBounds);\n\n if (error.distance <= positionThreshold) {\n return null;\n }\n\n return { currentBounds, targetBounds, error };\n}\n","import { spawnSync } from 'child_process';\nimport { createRequire } from 'module';\nimport fs from 'fs';\nimport path from 'path';\nimport { logger } from './logger';\n\nconst require = createRequire(import.meta.url);\n\nexport function detectPackageManager(cwd: string = process.cwd()): 'npm' | 'yarn' | 'pnpm' {\n if (fs.existsSync(path.join(cwd, 'pnpm-lock.yaml'))) return 'pnpm';\n if (fs.existsSync(path.join(cwd, 'yarn.lock'))) return 'yarn';\n return 'npm';\n}\n\nexport function isPackageInstalled(packageName: string): boolean {\n try {\n require.resolve(packageName);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction formatValidationDependencyHelp(missing: string[]): string {\n const isWin = process.platform === 'win32';\n const globalInstall = [\n 'npm install -g playwright sharp',\n isWin ? 'npx playwright install chromium' : 'npx playwright install chromium',\n ].join('\\n');\n\n const localInstall = [\n 'npm install -D playwright sharp',\n isWin ? 'npx playwright install chromium' : 'npx playwright install chromium',\n ].join('\\n');\n\n const pnpmGlobal = ['pnpm add -g playwright sharp', 'pnpm exec playwright install chromium'].join('\\n');\n const pnpmLocal = ['pnpm add -D playwright sharp', 'pnpm exec playwright install chromium'].join('\\n');\n\n return [\n `Missing optional validation dependencies: ${missing.join(', ')}`,\n '',\n 'Validation requires Playwright (browsers) and Sharp (image processing).',\n 'These dependencies are NOT bundled with coderio by default to keep installation lightweight.',\n '',\n 'Recommended (global install):',\n globalInstall,\n '',\n 'Or install in your current project:',\n localInstall,\n '',\n 'If you use pnpm:',\n '',\n 'Global:',\n pnpmGlobal,\n '',\n 'Local (project):',\n pnpmLocal,\n ].join('\\n');\n}\n\nexport function assertValidationDependenciesInstalled(): void {\n const missing: string[] = [];\n if (!isPackageInstalled('sharp')) missing.push('sharp');\n if (!isPackageInstalled('playwright')) missing.push('playwright');\n\n if (missing.length === 0) {\n return;\n }\n\n throw new Error(formatValidationDependencyHelp(missing));\n}\n\nexport function ensurePackageInstalled(packageName: string, packageNameInRegistry?: string) {\n const pkgName = packageNameInRegistry || packageName;\n\n if (isPackageInstalled(packageName)) {\n return;\n }\n\n logger.printInfoLog(`Package '${packageName}' is required for validation but not installed.`);\n const pm = detectPackageManager();\n\n // For dependencies that should be devDependencies in the user's project if they are using coderio as a tool\n // But since this runs at runtime, we just install them.\n const installArgs = pm === 'npm' ? 'install' : 'add';\n const pmCmd = process.platform === 'win32' ? `${pm}.cmd` : pm;\n const installCmdDisplay = `${pmCmd} ${installArgs} ${pkgName}`;\n\n logger.printInfoLog(`Installing ${pkgName} using ${pm}...`);\n logger.printInfoLog(`Command: ${installCmdDisplay}`);\n\n try {\n const result = spawnSync(pmCmd, [installArgs, pkgName], {\n stdio: 'inherit',\n cwd: process.cwd(),\n shell: process.platform === 'win32',\n });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw new Error(`Command exited with code ${result.status}`);\n }\n logger.printSuccessLog(`Successfully installed ${pkgName}.`);\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to install ${pkgName}: ${errorMsg}. Please install it manually.`);\n }\n}\n\nexport function ensureValidationDependencies(): void {\n // Default behavior: only assert presence (do not modify user environment).\n // Auto-installing heavy native deps at runtime can fail and harms UX.\n // If you still want auto-install, call ensurePackageInstalled(...) explicitly from your own wrapper.\n assertValidationDependenciesInstalled();\n\n // NOTE: We intentionally do not preinstall Playwright browsers here.\n // The Playwright launcher has an auto-install fallback for missing Chromium binaries.\n}\n","import { GraphState } from '../../state';\nimport { logger } from '../../utils/logger';\nimport { processNode, injectRootComponentToApp } from './utils';\nimport { loadCodeCache } from '../../utils/code-cache';\n\n/**\n * Main code generation node function\n * Generates React components from the page structure tree\n */\nexport async function generateCode(state: GraphState) {\n try {\n logger.printInfoLog('🚀 Starting Code Generation...');\n\n // Validate required state fields\n if (!state.protocol) {\n throw new Error('No protocol data found');\n }\n\n // Load code cache\n const cache = loadCodeCache(state.workspace);\n\n // Process the entire node tree (cache is saved incrementally after each component)\n const totalComponents = await processNode(state, cache);\n\n // Inject root component to App.tsx (cache is saved after injection)\n await injectRootComponentToApp(state, cache);\n\n logger.printSuccessLog(`✨ Code generation completed! Generated ${totalComponents} components`);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Code generation failed: ${errorMessage}`);\n }\n}\n","import fs from 'fs';\nimport { GraphState } from '../../state';\nimport { logger } from '../../utils/logger';\nimport { callModel } from '../../utils/call-model';\nimport { promisePool } from '../../utils/promise-pool';\nimport { generateFramePrompt, generateComponentPrompt, injectRootComponentPrompt } from './prompt';\nimport { Protocol } from '../../types';\nimport { createFiles, writeFile } from '../../utils/file';\nimport { DEFAULT_APP_CONTENT, DEFAULT_STYLING } from './constants';\nimport path from 'path';\nimport { extractCode, extractFiles } from '../../utils/parser';\nimport { workspaceManager } from '../../utils/workspace';\nimport { CodeCache, isComponentGenerated, saveComponentGenerated, isAppInjected, saveAppInjected } from '../../utils/code-cache';\n\n/**\n * Process a node tree and generate code for all nodes\n * Uses post-order traversal (children first, then parent)\n */\nexport async function processNode(state: GraphState, cache: CodeCache): Promise<number> {\n // Read asset files list once for the entire generation run\n const assetFilesList = getAssetFilesList(state);\n\n // Flatten tree using post-order traversal (children first, then parent)\n const flatNodes = flattenPostOrder(state.protocol!);\n const total = flatNodes.length;\n\n if (total === 0) {\n logger.printWarnLog('No components found in structure to generate.');\n return 0;\n }\n\n logger.printInfoLog(`Processing ${total} nodes...`);\n\n let processedCount = 0;\n let skippedCount = 0;\n\n const processSingleNode = async (currentNode: Protocol) => {\n const componentName = currentNode.data.name || currentNode.data.componentName || 'UnknownComponent';\n const nodeId = currentNode.id;\n\n // Check if component is already generated\n if (isComponentGenerated(cache, nodeId)) {\n skippedCount++;\n logger.printInfoLog(`[${processedCount + skippedCount}/${total}] ⏭️ Skipping (cached): ${componentName}`);\n return;\n }\n\n const progressInfo = `[${++processedCount + skippedCount}/${total}]`;\n\n const isLeaf = !currentNode.children?.length;\n if (isLeaf) {\n await generateComponent(currentNode, state, assetFilesList, progressInfo);\n } else {\n await generateFrame(currentNode, state, assetFilesList, progressInfo);\n }\n\n // Mark component as generated and save immediately to prevent cache loss on interruption\n saveComponentGenerated(cache, nodeId, state.workspace);\n };\n\n // Process nodes with concurrency control\n await promisePool(flatNodes, processSingleNode);\n\n if (skippedCount > 0) {\n logger.printInfoLog(`⏭️ Skipped ${skippedCount} cached components`);\n }\n logger.printSuccessLog(`Generated ${processedCount} components`);\n return processedCount;\n}\n\n/**\n * Flatten tree into array using post-order traversal\n */\nexport function flattenPostOrder(node: Protocol): Protocol[] {\n const result: Protocol[] = [];\n\n function traverse(n: Protocol) {\n n.children?.forEach(child => traverse(child));\n result.push(n);\n }\n\n traverse(node);\n return result;\n}\n\n/**\n * Detect which rendering modes are used in this frame\n */\nexport function detectRenderingModes(node: Protocol): {\n hasStates: boolean;\n hasIndependentChildren: boolean;\n} {\n const hasStates = !!node.data.states?.length;\n\n let hasIndependentChildren = false;\n\n (node.children || []).forEach(child => {\n if (!child.data.componentName) {\n hasIndependentChildren = true;\n }\n });\n\n return { hasStates, hasIndependentChildren };\n}\n\n/**\n * Generate a frame/container component\n * Frames compose multiple child components based on layout\n */\nexport async function generateFrame(node: Protocol, state: GraphState, assetFilesList: string, progressInfo: string): Promise<void> {\n const frameName = node.data.name;\n logger.printInfoLog(`${progressInfo} 🖼️ Generating Frame: ${frameName}`);\n\n // Build children imports information\n const childrenImports = (node.children || []).map(child => ({\n name: child.data.name || '',\n path: child.data.path,\n }));\n\n // Detect rendering modes\n const renderingModes = detectRenderingModes(node);\n\n // Generate prompt\n const prompt = generateFramePrompt({\n frameDetails: JSON.stringify(node.data),\n childrenImports: JSON.stringify(childrenImports),\n styling: JSON.stringify(DEFAULT_STYLING),\n assetFiles: assetFilesList,\n renderingModes,\n });\n\n // Call AI model\n const code = await callModel({\n question: prompt,\n imageUrls: state.figmaInfo.thumbnail,\n });\n\n // Save generated files\n const componentPath = node.data.path || '';\n const filePath = workspaceManager.resolveAppSrc(state.workspace, workspaceManager.resolveComponentPath(componentPath));\n saveGeneratedCode(code, filePath);\n logger.printSuccessLog(`Successfully generated frame: ${frameName}`);\n}\n\n/**\n * Generate a component (leaf or reusable)\n * Components are self-contained UI elements driven by props\n */\nexport async function generateComponent(node: Protocol, state: GraphState, assetFilesList: string, progressInfo: string): Promise<void> {\n const componentName = node.data.componentName || node.data.name || 'UnknownComponent';\n const componentPath = node.data.componentPath || node.data.path || '';\n\n logger.printInfoLog(`${progressInfo} 📦 Generating Component: ${componentName}`);\n\n // Generate prompt\n const prompt = generateComponentPrompt({\n componentName,\n componentDetails: JSON.stringify(node.data),\n styling: JSON.stringify(DEFAULT_STYLING),\n assetFiles: assetFilesList,\n });\n\n // Call AI model\n const code = await callModel({\n question: prompt,\n imageUrls: state.figmaInfo.thumbnail,\n });\n\n // Save generated files\n const filePath = workspaceManager.resolveAppSrc(state.workspace, workspaceManager.resolveComponentPath(componentPath));\n saveGeneratedCode(code, filePath);\n logger.printSuccessLog(`Successfully generated component: ${componentName}`);\n}\n\n/**\n * Helper function to save generated code (handles both single and multi-file output)\n */\nexport function saveGeneratedCode(code: string, filePath: string): void {\n const files = extractFiles(code);\n\n if (files.length > 0) {\n // Multi-file output (e.g., index.tsx + index.module.less)\n createFiles({ files, filePath });\n } else {\n const extractedCode = extractCode(code);\n const folderPath = path.dirname(filePath);\n const fileName = path.basename(filePath);\n writeFile(folderPath, fileName, extractedCode);\n }\n}\n\n/**\n * Get list of available asset files for AI to match against\n */\nfunction getAssetFilesList(state: GraphState) {\n try {\n const assetsDir = workspaceManager.resolveAppSrc(state.workspace, 'assets');\n\n if (!fs.existsSync(assetsDir)) {\n return '';\n }\n\n const files = fs.readdirSync(assetsDir);\n return files.join(', ');\n } catch {\n return '';\n }\n}\n\n/**\n * Inject root component into App.tsx\n * Reads existing App.tsx, adds import and renders the root component\n */\nexport async function injectRootComponentToApp(state: GraphState, cache: CodeCache): Promise<void> {\n try {\n // Check if already injected\n if (isAppInjected(cache)) {\n logger.printInfoLog('⏭️ Skipping App.tsx injection (already injected)');\n return;\n }\n\n logger.printInfoLog('💉 Injecting root component into App.tsx...');\n\n // Construct App.tsx path\n const appTsxPath = workspaceManager.resolveAppSrc(state.workspace, 'App.tsx');\n\n // Read existing App.tsx or use default template\n let appContent: string;\n try {\n appContent = fs.readFileSync(appTsxPath, 'utf8');\n } catch {\n // Use default template if App.tsx doesn't exist\n logger.printWarnLog('App.tsx not found, using default template');\n appContent = DEFAULT_APP_CONTENT;\n }\n\n // Get root component information\n const rootNode = state.protocol!;\n const componentName = rootNode.data.name || 'RootComponent';\n const componentPath = rootNode.data.path || '';\n\n // Generate prompt\n const prompt = injectRootComponentPrompt({\n appContent,\n componentName,\n componentPath,\n });\n\n // Call AI model\n const updatedCode = await callModel({\n question: prompt,\n });\n\n // Extract code (no markdown blocks expected based on prompt requirements)\n const finalCode = updatedCode.includes('```') ? extractCode(updatedCode) : updatedCode.trim();\n\n // Write updated App.tsx\n const appFolderPath = path.dirname(appTsxPath);\n writeFile(appFolderPath, 'App.tsx', finalCode);\n\n // Mark as injected and save immediately\n saveAppInjected(cache, state.workspace);\n\n logger.printSuccessLog(`Successfully injected ${componentName} into App.tsx`);\n } catch (error) {\n logger.printErrorLog(`Failed to inject root component: ${(error as Error).message}`);\n // Don't throw - allow the process to continue even if injection fails\n }\n}\n","// ============================================\n// Common Prompt Sections\n// ============================================\n\nconst STYLING_GUIDELINES = `\n - **Style Consistency**: Implement styles using the technical stack and libraries listed in <styling>.\n - **Strict Restriction**: Absolutely ONLY use the technical stack and libraries listed in <styling>. Do NOT use any other styling methods, libraries, or frameworks (e.g., if clsx is not listed, do not use clsx).\n - **Default Styling**: If <styling> is empty or does not contain specific libraries, DEFAULT to standard vanilla CSS.\n \n - **Tailwind CSS + CSS Modules (CRITICAL)**:\n - If the stack includes BOTH Tailwind and CSS Modules (Less/SCSS), use them correctly:\n 1. **Tailwind utilities**: Use DIRECTLY in JSX className (e.g., \\`className=\"flex items-center gap-4\"\\`)\n 2. **CSS Modules**: Use ONLY for complex styles that can't be expressed with Tailwind utilities (e.g., gradients, animations, pseudo-elements)\n 3. **NEVER use \\`@apply\\` in CSS Module files** - it's a Tailwind-specific directive that doesn't work in Less/SCSS\n 4. Example correct usage:\n TSX: \\`<div className={\\`flex \\${styles.customGradient}\\`}>\\`\n Less: \\`.customGradient { background: linear-gradient(...); }\\`\n \n - **CSS Modules Only**: If the tech stack specifies CSS Modules without Tailwind:\n 1. Create a corresponding style file (e.g., \\`index.module.less\\`, \\`index.module.scss\\`, or \\`index.module.css\\`)\n 2. Import it as \\`import styles from './index.module.[ext]';\\` in the TSX\n 3. Define all styles in the style file using standard CSS/Less/SCSS syntax\n 4. Use \\`styles.className\\` in JSX`;\n\nconst ASSETS_HANDLING = `\n - **CRITICAL**: For any image URL starting with \\`@/assets\\`, you MUST import it at the top of the file.\n - **Asset Name Matching**: \n - Check the \\`<available_assets>\\` list for actual filenames in the project.\n - Asset filenames follow the pattern: \\`kebab-case-name-id1-id2.ext\\` (e.g., \"Star 2.svg\" → \"star-2-1-2861.svg\")\n - Match the base name (ignoring spaces, case, and ID suffix): \"@/assets/arXiv.svg\" → look for \"arxiv-*.svg\" in the list\n - Use the EXACT filename from the available assets list in your import.\n - Example: If available_assets contains \"arxiv-1-2956.svg\", use:\n \\`import ArXivIcon from '@/assets/arxiv-1-2956.svg';\\`\n - **Usage**: \\`<img src={ArXivIcon} />\\`, do not use backgroundImage property.\n - **NEVER** use the string path directly in JSX or styles.`;\n\nconst DOM_IDS_REQUIREMENT = `\n - Assign \\`id\\` attributes to the main container and any internal elements, matching \\`frame_details\\`.`;\n\nconst REACT_IMPORT_RULE = `\n - Do **NOT** include \\`import React from 'react';\\` at the top of the file.`;\n\nconst FILE_NAMING_CONVENTION = `\n - ALWAYS name the main component file \\`index.tsx\\`.\n - ALWAYS name the style file (if applicable) \\`index.module.[css|less|scss]\\`.\n - NEVER use PascalCase or other names for filenames (e.g., DO NOT use \\`MainFrame.tsx\\` or \\`Button.tsx\\`).`;\n\nconst OUTPUT_FORMAT = `\n <output_format>\n If only one file (TSX) is needed:\n \\`\\`\\`tsx\n // code...\n \\`\\`\\`\n\n If multiple files are needed (e.g., TSX + Styles):\n ## index.tsx\n \\`\\`\\`tsx\n // code...\n \\`\\`\\`\n\n ## index.module.[css|less|scss]\n \\`\\`\\`[css|less|scss]\n // styles...\n \\`\\`\\`\n </output_format>`;\n\n// ============================================\n// Prompt Functions\n// ============================================\n\n/**\n * Generate children rendering instructions based on detected modes\n */\nfunction generateChildrenPropsInstructions(modes: { hasStates: boolean; hasIndependentChildren: boolean }): string {\n const instructions: string[] = [];\n\n if (modes.hasStates) {\n instructions.push(`\n - **List Rendering (States-based)**:\n - Check if \\`<frame_details>\\` contains a \\`states\\` property (array).\n - Each state entry has: \\`state\\` (data array), \\`componentName\\`, \\`componentPath\\`.\n - Implementation:\n \\`\\`\\`tsx\n import ComponentName from 'path';\n \n {states[0].state.map((item, index) => (\n <ComponentName key={index} {...item} />\n ))}\n \\`\\`\\`\n - **CRITICAL - Only Use State Data**:\n - **ONLY** pass props that exist in the state data objects.\n - **DO NOT** add extra props like \\`content\\`, \\`className\\`, or any other fields not present in state.\n - **DO NOT** create or invent additional data - use exactly what's in the state array.\n - Example: If state has \\`{iconSrc, title, description}\\`, only pass those three props.\n - **Asset Imports**: If state data contains image paths (e.g., \\`imageSrc\\`, \\`iconSrc\\`), \n import them at the top and pass as values.`);\n }\n\n if (modes.hasIndependentChildren) {\n instructions.push(`\n - **Independent Components (No Props) - CRITICAL**:\n - If a child has NO \\`componentName\\` and NO \\`properties\\`, render as \\`<ComponentName />\\` without any props.\n - These components use default values or hardcoded content internally.`);\n }\n\n return instructions.join('\\n');\n}\n\nexport const generateFramePrompt = ({\n childrenImports,\n frameDetails,\n assetFiles,\n styling,\n renderingModes,\n}: {\n childrenImports: string;\n frameDetails: string;\n assetFiles?: string;\n styling: string;\n renderingModes: {\n hasStates: boolean;\n hasIndependentChildren: boolean;\n };\n}) => {\n return `\n<system_instructions>\n <role>\n You are a React Architect.\n Your task is to assemble a \"Frame\" component that composes multiple child components based on Figma layout data.\n </role>\n\n <input_context>\n <frame_details>${frameDetails}</frame_details>\n <children>${childrenImports}</children>\n <styling>${styling}</styling>\n ${assetFiles ? `<available_assets>Available asset files: ${assetFiles}</available_assets>` : ''}\n\n <frame_structure>\n The \\`frame_details\\` parameter contains:\n - \\`layout\\`: Layout information for the frame (flex/grid/absolute)\n - \\`elements\\`: Array of CSS styles and asset URLs for all elements in this component (colors, spacing, fonts, backgrounds, etc.)\n - \\`states\\` (optional): If present, this frame contains reusable components. Each state entry includes:\n * \\`state\\`: Array of data objects to be used as props for component instances\n * \\`componentName\\`: Name of the reusable component\n * \\`componentPath\\`: Import path for the component\n Use \\`states\\` data to render multiple instances of reusable components via \\`.map()\\`.\n </frame_structure>\n </input_context>\n\n <requirements>\n <req_1>\n **Children Components & Props (CRITICAL)**:\n - The \\`<children>\\` field describes child components with their import paths and prop types.\n${generateChildrenPropsInstructions(renderingModes)}\n \n - **Component Imports (CRITICAL)**:\n - You MUST use the exact import path provided in the \\`<children>\\` list for each component.\n - **Example**:\n - Provided: \\`{\"name\": \"TaskGrid\", \"path\": \"@/components/tasks-section/task-grid\"}\\`\n - CORRECT: \\`import TaskGrid from \"@/components/tasks-section/task-grid\";\\`\n - WRONG: \\`import TaskGrid from \"@/components/task-grid\";\\` (Do NOT do this!)\n </req_1>\n \n <req_2>\n **Layout & Styling**:\n - Use \\`layout_data\\` for dimensions, spacing, and flow (flex/grid).\n${STYLING_GUIDELINES}\n - Use responsive utilities provided by the chosen libraries to ensure the component is adaptive.\n - Use \\`css_context\\` for exact background styles, gradients, and shadows.\n - Use \\`relative\\` positioning for the container.\n - Use \\`spacing\\` field in <frame_details> to set the spacing between elements\n </req_2>\n \n <req_3>\n **Images & Assets**:\n${ASSETS_HANDLING}\n </req_3>\n \n <req_4>\n **DOM IDs**:\n${DOM_IDS_REQUIREMENT}\n </req_4>\n \n <req_5>\n **React Import**:\n${REACT_IMPORT_RULE}\n </req_5>\n \n <req_6>\n **File Naming**:\n${FILE_NAMING_CONVENTION}\n </req_6>\n </requirements>\n\n${OUTPUT_FORMAT}\n</system_instructions>\n`.trim();\n};\n\nexport const generateComponentPrompt = ({\n componentName,\n componentDetails,\n styling,\n assetFiles,\n}: {\n componentName: string;\n componentDetails: string;\n styling: string;\n assetFiles?: string;\n}) => {\n return `\n<system_instructions>\n <role>\n You are a Pixel-Perfect React Frontend Engineer.\n Your goal is to implement a specific UI component from Figma design data with 100% visual fidelity while ensuring header scroll to sections on click.\n </role>\n\n <input_context>\n <component_details>${componentDetails}</component_details>\n ${assetFiles ? `<available_assets>Available asset files: ${assetFiles}</available_assets>` : ''}\n <styling>${styling}</styling>\n\n <component_structure>\n The \\`component_details\\` parameter contains:\n - \\`elements\\`: Array of CSS styles and asset URLs for all elements in this component (colors, spacing, fonts, backgrounds, etc.)\n - \\`componentName\\` (optional): If present, indicates this is a **reusable component**; if absent, it's a **regular component**\n - \\`props\\` (optional): Props interface definition, only present when \\`componentName\\` exists\n </component_structure>\n\n <global_styles>\n .gradientBorder {\n position: relative;\n z-index: 0;\n &::before {\n content: '';\n position: absolute;\n inset: 0;\n padding: 1px; // From strokeWidth\n border-radius: inherit;\n background: linear-gradient(278deg, rgba(170, 255, 248, 0.60) 1.63%, rgba(71, 169, 255, 0.60) 104.34%); // From strokeColor\n -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);\n -webkit-mask-composite: destination-out;\n mask-composite: exclude;\n z-index: -1;\n }\n } \n </global_styles>\n\n <visual_reference>\n Refer to the conversation history for the page thumbnail and context.\n Use it to verify visual details like shadows, gradients, and spacing.\n </visual_reference>\n </input_context>\n\n <requirements>\n <req_1>\n **High Fidelity & Responsive**:\n${STYLING_GUIDELINES}\n - **CRITICAL**: Use exact design values from \\`component_details.elements\\` (colors, spacing, font sizes, gradients, shadows, etc.)\n - Use responsive utilities provided by the chosen libraries\n - For complex styles (gradients, shadows), use values from \\`elements\\` directly in CSS Modules or inline styles\n - For gradient rounded borders, CHECK \\`global_styles\\` for \\`.gradientBorder\\` mixin\n </req_1>\n\n <req_2>\n **DOM Identification**:\n - EVERY DOM element corresponding to a Figma node MUST have an \\`id\\` attribute.\n - The \\`id\\` value must match the \\`id\\` in the Figma Data exactly.\n - This is crucial for automated position validation.\n </req_2>\n\n <req_3>\n **Images & Assets**:\n${ASSETS_HANDLING}\n </req_3>\n\n <req_4>\n **Semantic HTML**:\n - Use semantic tags: \\`<header>\\`, \\`<footer>\\`, \\`<nav>\\`, \\`<article>\\`, \\`<section>\\`, \\`<button>\\`.\n </req_4>\n\n <req_5>\n **Layout Strategy**:\n - PREFER relative/flex/grid layout.\n - Use absolute positioning ONLY for decoration/overlays or if Figma structure explicitly implies overlay.\n </req_5>\n\n <req_6>\n **Naming Conventions**:\n - Component Name: **${componentName}** (PascalCase).\n - Export default.\n </req_6>\n\n <req_7>\n **Component Type & Props (CRITICAL)**:\n \n **IF \\`component_details.componentName\\` exists:**\n - This is a **reusable component**\n - Generate props interface from \\`component_details.props\\`: \\`interface ${componentName}Props { ... }\\`\n - Reference props in JSX: \\`{title}\\`, \\`<img src={iconSrc} />\\` (NOT hardcoded values)\n \n **IF \\`component_details.componentName\\` does NOT exist:**\n - This is a **regular component**\n - Do NOT generate props interface\n - Directly hardcode content from \\`component_details.elements\\` into JSX\n \n **Both types**: Do NOT repeat JSX to simulate grids; parent components handle iteration.\n </req_7>\n\n <req_9>\n **React Import**:\n${REACT_IMPORT_RULE}\n </req_9>\n \n <req_10>\n **File Naming**:\n${FILE_NAMING_CONVENTION}\n </req_10>\n </requirements>\n\n${OUTPUT_FORMAT}\n</system_instructions>\n`.trim();\n};\n\nexport const injectRootComponentPrompt = ({\n appContent,\n componentName,\n componentPath,\n}: {\n appContent: string;\n componentName: string;\n componentPath: string;\n}) => {\n return `\n<system_instructions>\n <role>\n You are a React code refactoring expert.\n Your task is to inject a root component into an existing App.tsx file with minimal changes.\n </role>\n\n <input_context>\n <current_app_content>\n${appContent}\n </current_app_content>\n <component_to_inject>\n - Component Name: ${componentName}\n - Import Path: ${componentPath}\n </component_to_inject>\n </input_context>\n\n <requirements>\n <req_1>\n **Import Statement**:\n - Add the import statement at the top of the file: \\`import ${componentName} from '${componentPath}';\\`\n - Place it after existing imports, before the component definition.\n - Do NOT remove or modify existing imports.\n </req_1>\n\n <req_2>\n **Component Rendering**:\n - Inside the App component's return statement, replace the existing content with \\`<${componentName} />\\`.\n - If the return contains a wrapper div or other container, keep it and place the component inside.\n - Preserve any existing className, styles, or other attributes on wrapper elements.\n </req_2>\n\n <req_3>\n **Preserve Existing Code**:\n - Keep all existing imports (CSS, Less, etc.)\n - Preserve any hooks, state, or logic inside the App component\n - Maintain the component structure and export statement\n - Do NOT add comments or explanatory text\n </req_3>\n\n <req_4>\n **Minimal Changes**:\n - Only add the necessary import and render the component\n - Do NOT refactor or optimize existing code\n - Do NOT change formatting or styling unless necessary\n - Do NOT add TypeScript types unless they already exist\n </req_4>\n\n <req_5>\n **React Import**:\n${REACT_IMPORT_RULE}\n </req_5>\n </requirements>\n\n <output_format>\n Return ONLY the complete updated App.tsx code without markdown code blocks or explanation.\n The output should be valid TypeScript/React code that can be directly written to the file.\n </output_format>\n</system_instructions>\n`.trim();\n};\n","export const DEFAULT_STYLING = {\n approach: 'Tailwind V4 and Less',\n libraries: [\n {\n name: 'Tailwind V4',\n role: 'utility_first',\n },\n {\n name: 'Less',\n role: 'css_preprocessor',\n },\n ],\n};\n\nexport const DEFAULT_APP_CONTENT = `function App() {\n return (\n <div>\n {/* Component will be injected here */}\n </div>\n );\n}\n\nexport default App;`;\n","import fs from 'node:fs';\nimport { WorkspaceStructure } from '../types/workspace-types';\nimport { logger } from './logger';\n\n/**\n * Code generation cache structure\n * Tracks which components have been generated and whether App.tsx has been injected\n */\nexport interface CodeCache {\n generatedComponents: string[]; // Array of node IDs that have been generated\n appInjected: boolean;\n}\n\n/**\n * Get the path to the cache file\n */\nfunction getCachePath(workspace: WorkspaceStructure): string {\n return workspace.checkpoint;\n}\n\n/**\n * Load code generation cache from file\n * Returns empty cache if file doesn't exist or on error\n */\nexport function loadCodeCache(workspace: WorkspaceStructure): CodeCache {\n const cachePath = getCachePath(workspace);\n\n try {\n if (!fs.existsSync(cachePath)) {\n logger.printInfoLog('No code cache found, starting fresh');\n return createEmptyCache();\n }\n\n const content = fs.readFileSync(cachePath, 'utf-8');\n const cache = JSON.parse(content) as CodeCache;\n\n // Validate cache structure\n if (!Array.isArray(cache.generatedComponents) || typeof cache.appInjected !== 'boolean') {\n logger.printWarnLog('Invalid cache format, starting fresh');\n return createEmptyCache();\n }\n\n logger.printInfoLog(`Loaded code cache: ${cache.generatedComponents.length} components cached`);\n return cache;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.printWarnLog(`Failed to load code cache: ${errorMessage}. Starting fresh.`);\n return createEmptyCache();\n }\n}\n\n/**\n * Save code generation cache to file\n */\nexport function saveCodeCache(workspace: WorkspaceStructure, cache: CodeCache): void {\n const cachePath = getCachePath(workspace);\n\n try {\n // Ensure process directory exists\n if (!fs.existsSync(workspace.process)) {\n fs.mkdirSync(workspace.process, { recursive: true });\n }\n\n const content = JSON.stringify(cache, null, 2);\n fs.writeFileSync(cachePath, content, 'utf-8');\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.printWarnLog(`Failed to save code cache: ${errorMessage}`);\n }\n}\n\n/**\n * Check if a component has already been generated\n * @param cache - The code cache object\n * @param nodeId - The unique node ID to check\n */\nexport function isComponentGenerated(cache: CodeCache, nodeId: string): boolean {\n return cache.generatedComponents.includes(nodeId);\n}\n\n/**\n * Mark a component as generated\n * @param cache - The code cache object\n * @param nodeId - The unique node ID to mark as generated\n */\nexport function markComponentGenerated(cache: CodeCache, nodeId: string): void {\n if (!isComponentGenerated(cache, nodeId)) {\n cache.generatedComponents.push(nodeId);\n }\n}\n\n/**\n * Mark a component as generated and save cache immediately\n * Combines markComponentGenerated and saveCodeCache for convenience\n * @param cache - The code cache object\n * @param nodeId - The unique node ID to mark as generated\n * @param workspace - The workspace structure containing cache file path\n */\nexport function saveComponentGenerated(cache: CodeCache, nodeId: string, workspace: WorkspaceStructure): void {\n markComponentGenerated(cache, nodeId);\n saveCodeCache(workspace, cache);\n}\n\n/**\n * Check if root component has been injected into App.tsx\n */\nexport function isAppInjected(cache: CodeCache): boolean {\n return cache.appInjected;\n}\n\n/**\n * Mark App.tsx as injected\n */\nexport function markAppInjected(cache: CodeCache): void {\n cache.appInjected = true;\n}\n\n/**\n * Mark App.tsx as injected and save cache immediately\n * Combines markAppInjected and saveCodeCache for convenience\n */\nexport function saveAppInjected(cache: CodeCache, workspace: WorkspaceStructure): void {\n markAppInjected(cache);\n saveCodeCache(workspace, cache);\n}\n\n/**\n * Create an empty cache\n */\nfunction createEmptyCache(): CodeCache {\n return {\n generatedComponents: [],\n appInjected: false,\n };\n}\n","import path from 'node:path';\nimport fs from 'node:fs';\nimport { SqliteSaver } from '@langchain/langgraph-checkpoint-sqlite';\nimport { logger } from './logger';\nimport { promptUserChoice } from '../cli/prompts';\n\n/**\n * Check if a checkpoint exists for the given thread_id\n */\nasync function checkpointExists(checkpointer: SqliteSaver, threadId: string): Promise<boolean> {\n try {\n const checkpoints = checkpointer.list({ configurable: { thread_id: threadId } }, { limit: 1 });\n const firstCheckpoint = await checkpoints.next();\n return !firstCheckpoint.done && firstCheckpoint.value !== undefined;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.printTestLog(`Error checking checkpoint: ${errorMessage}`);\n return false;\n }\n}\n\n/**\n * Clear checkpoint for the given thread_id\n */\nasync function clearCheckpoint(checkpointer: SqliteSaver, threadId: string): Promise<void> {\n try {\n // Delete all checkpoints for this thread_id\n await checkpointer.deleteThread(threadId);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.printWarnLog(`Failed to clear checkpoint: ${errorMessage}`);\n }\n}\n\n/**\n * Check and prompt user for checkpoint decision\n * Returns true if user wants to resume, false if start fresh, undefined if no checkpoint exists\n */\nexport async function promptCheckpointChoice(checkpointer: SqliteSaver, threadId: string): Promise<boolean | undefined> {\n const hasCheckpoint = await checkpointExists(checkpointer, threadId);\n\n if (!hasCheckpoint) {\n return undefined;\n }\n\n const choice = await promptUserChoice();\n return choice === 'resume';\n}\n\n/**\n * Clear checkpoint for the given thread_id (exported for external use)\n */\nexport async function clearThreadCheckpoint(checkpointer: SqliteSaver, threadId: string): Promise<void> {\n await clearCheckpoint(checkpointer, threadId);\n}\n\n/**\n * Initialize SqliteSaver with the database path\n */\nexport function initializeSqliteSaver(dbPath: string): SqliteSaver {\n // Ensure the directory exists\n const dbDir = path.dirname(dbPath);\n if (!fs.existsSync(dbDir)) {\n fs.mkdirSync(dbDir, { recursive: true });\n }\n\n // SqliteSaver.fromConnString already sets up the database\n const checkpointer = SqliteSaver.fromConnString(dbPath);\n return checkpointer;\n}\n","import prompts from 'prompts';\nimport { logger } from '../utils/logger';\n\nasync function typedPrompt<U>(config: prompts.PromptObject<string>): Promise<Record<string, U>> {\n return prompts(config, {\n onCancel: () => {\n logger.printWarnLog('Operation cancelled by user.');\n process.exit(0);\n },\n });\n}\n\ntype UserChoice = 'resume' | 'fresh';\n\nexport async function promptUserChoice(): Promise<UserChoice> {\n const response = await typedPrompt<UserChoice>({\n type: 'select',\n name: 'choice',\n message: 'What would you like to do?',\n choices: [\n { title: 'Resume from cache', value: 'resume' },\n { title: 'Start fresh (will clear existing cache)', value: 'fresh' },\n ],\n initial: 0,\n });\n return response.choice || 'resume';\n}\n","import { Command } from 'commander';\nimport { parseFigmaUrl } from '../utils/url-parser';\nimport { workspaceManager } from '../utils/workspace';\nimport { logger } from '../utils/logger';\nimport { executeFigmaAndImagesActions } from '../nodes/process';\n\n// images command: detect images from Figma document and download them\nexport const registerImagesCommand = (program: Command) => {\n program\n .command('get-images')\n .alias('images')\n .description('Detect images from Figma document and download them')\n .option('-s, --source <url>', 'Figma Link')\n .action(async (opts: { source: string }) => {\n try {\n const { source } = opts;\n const urlInfo = parseFigmaUrl(source);\n const workspace = workspaceManager.initWorkspace(urlInfo.name);\n await executeFigmaAndImagesActions(urlInfo, workspace.root, workspace.root);\n\n logger.printSuccessLog('Successfully completed detection of images from Figma document!');\n logger.printInfoLog(`Please check the output in the workspace: ${workspace.process}`);\n } catch (error) {\n logger.printErrorLog(`Error during images execution: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n};\n","import { Command } from 'commander';\nimport { workspaceManager } from '../utils/workspace';\nimport { logger } from '../utils/logger';\nimport { readFile } from 'fs/promises';\nimport { generateCode } from '../nodes/code';\nimport { Protocol } from '../types/protocol-types';\nimport { GraphState } from '../state';\nimport { initialProject } from '../nodes/initial';\n\n// p2c command: Protocol to Code\nexport const registerP2CCommand = (program: Command) => {\n program\n .command('protocol2code')\n .alias('p2c')\n .description('Generate code from protocol')\n .option('-p, --protocol <path>', 'Protocol path')\n .action(async (opts: { protocol: string }) => {\n try {\n const protocolContent = await readFile(opts.protocol, 'utf-8');\n const protocolData = JSON.parse(protocolContent) as Protocol;\n const workspace = workspaceManager.initWorkspace(protocolData.id || '');\n const state: GraphState = {\n protocol: protocolData,\n workspace,\n figmaInfo: { thumbnail: '' },\n urlInfo: {\n fileId: '',\n name: '',\n nodeId: '',\n projectName: '',\n },\n messages: [],\n config: {},\n };\n await initialProject(state);\n await generateCode(state);\n } catch (error) {\n logger.printErrorLog(`Error during p2c execution: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n};\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { Command } from 'commander';\n\nimport type { Protocol } from '../types/protocol-types';\nimport { ValidationConfig, ValidationMode } from '../types/graph-types';\nimport { logger } from '../utils/logger';\nimport { runValidation } from '../nodes/validation';\nimport { workspaceManager } from '../utils/workspace';\nimport { WorkspaceStructure } from '../types';\n\ntype ValCommandOptions = {\n workspace?: string;\n url: string;\n reportonly?: boolean;\n};\n\nfunction readJsonFile<T>(absolutePath: string): T {\n const raw = fs.readFileSync(absolutePath, 'utf-8');\n return JSON.parse(raw) as T;\n}\n\n/**\n * Register the 'validate' CLI command.\n * Validates position alignment using an existing workspace without re-running d2p/d2c.\n *\n * @param program - Commander program instance\n */\nexport function registerValidateCommand(program: Command): void {\n program\n .command('validate')\n .alias('val')\n .description('Validate position misalignment using an existing generated workspace')\n .option(\n '-w, --workspace [path]',\n 'Workspace root path (contains process/ and generated app folder). Defaults to coderio/<current-dir> if not specified'\n )\n .requiredOption('-u, --url <url>', 'Figma thumbnail URL for validation')\n .option('--reportonly', 'Run report-only validation (no code edits)', false)\n .action(async (opts: ValCommandOptions) => {\n try {\n // Determine workspace and project name\n let workspace: WorkspaceStructure;\n let projectName: string;\n\n if (opts.workspace) {\n // Use explicit workspace path\n const workspacePath = path.resolve(opts.workspace);\n const parentPath = path.dirname(path.dirname(workspacePath)); // Go up to parent of 'coderio' folder\n projectName = path.basename(workspacePath);\n workspace = workspaceManager.initWorkspace(projectName, parentPath);\n } else {\n // Default: use current directory name as project name\n projectName = path.basename(process.env.CODERIO_CLI_USER_CWD ?? process.cwd());\n workspace = workspaceManager.initWorkspace(projectName);\n }\n\n const protocolPath = path.join(workspace.process, 'protocol.json');\n\n if (!fs.existsSync(protocolPath)) {\n throw new Error(`Missing protocol at: ${protocolPath}. Run d2p/d2c first to generate process/protocol.json.`);\n }\n\n const protocol = readJsonFile<Protocol>(protocolPath);\n\n // Use the provided URL directly\n const figmaThumbnailUrl = opts.url;\n\n // Build ValidationConfig from CLI options\n const config: ValidationConfig = {\n validationMode: opts.reportonly ? ValidationMode.ReportOnly : ValidationMode.Full,\n };\n\n logger.printInfoLog(`Running validation (${config.validationMode}) using workspace: ${workspace.root}`);\n\n await runValidation({\n urlInfo: { fileId: null, name: projectName, nodeId: null, projectName: null },\n workspace,\n figmaInfo: { thumbnail: figmaThumbnailUrl },\n protocol,\n messages: [],\n config,\n });\n\n // If we reach here, validation passed\n process.exit(0);\n } catch (error) {\n logger.printErrorLog(`Error during val execution: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n}\n"],"mappings":"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","names":["axios","tools","path","fs","fs","path","axios","axios","fs","path","resolve","cssAngle","_init","tools","document","path","processNode","path","extractDataListPrompt","document","fs","path","path","fs","fs","path","fs","path","Agent","Agent","path","Agent","tools","_init","tools","tools","_init","tools","children","Agent","Agent","Agent","Agent","Agent","fs","path","tools","tools","path","styles","require","resolve","fs","path","path","fs","axios","_init","tools","axios","_init","tools","path","tools","spawn","resolve","spawn","_init","tools","handle","result","tools","fetchThumbnailDimensions","_init","tools","createRequire","require","createRequire","require","history","launchResult","path","fs","fs","path","fs","path","fs","path","fs","path","fs","readFile","readFile","fs","path"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/logger.ts","../src/nodes/process/structure/prompt.ts","../src/tools/position-tool/utils/fetch-thumbnail-dimensions.ts","../src/cli/index.ts","../src/constants/index.ts","../src/cli/init.ts","../src/tools/figma-tool/index.ts","../src/utils/axios.ts","../src/utils/config.ts","../src/utils/file.ts","../src/utils/workspace.ts","../src/tools/figma-tool/figma.ts","../src/tools/figma-tool/images.ts","../src/utils/promise-pool.ts","../src/tools/figma-tool/constants.ts","../src/tools/style-tool/index.ts","../src/tools/style-tool/color.ts","../src/tools/style-tool/utils.ts","../src/nodes/process/index.ts","../src/utils/call-model.ts","../src/nodes/process/structure/index.ts","../src/nodes/process/structure/utils.ts","../src/utils/naming.ts","../src/utils/parser.ts","../src/utils/url-parser.ts","../src/cli/d2p.ts","../src/cli/d2c.ts","../src/graph.ts","../src/state.ts","../src/agents/initial-agent/index.ts","../src/agents/initial-agent/prompt.ts","../src/nodes/initial/index.ts","../src/agents/initial-agent/instruction.ts","../src/nodes/validation/index.ts","../src/nodes/validation/constants.ts","../src/nodes/validation/core/validation-loop.ts","../src/agents/commit-agent/index.ts","../src/agents/commit-agent/prompt.ts","../src/agents/commit-agent/instruction.ts","../src/nodes/validation/commit/index.ts","../src/agents/judger-agent/index.ts","../src/tools/history-tool/index.ts","../src/tools/hierarchy-tool/index.ts","../src/nodes/validation/utils/tree/tree-traversal.ts","../src/agents/judger-agent/prompt.ts","../src/agents/judger-agent/utils.ts","../src/agents/judger-agent/instruction.ts","../src/agents/refiner-agent/index.ts","../src/agents/refiner-agent/prompt.ts","../src/agents/refiner-agent/utils.ts","../src/agents/refiner-agent/instruction.ts","../src/agents/launch-agent/index.ts","../src/agents/launch-agent/prompt.ts","../src/agents/launch-agent/utils.ts","../src/agents/launch-agent/instruction.ts","../src/nodes/validation/launch/index.ts","../src/nodes/validation/utils/extraction/extract-layout-metadata.ts","../src/nodes/validation/report/index.ts","../src/tools/report-tool/index.ts","../src/tools/visualization-tool/index.ts","../src/tools/visualization-tool/utils/annotation-styles.ts","../src/tools/visualization-tool/utils/annotate-render.ts","../src/tools/visualization-tool/utils/image-converter.ts","../src/tools/visualization-tool/utils/annotate-target.ts","../src/nodes/validation/utils/playwright/launcher.ts","../src/tools/visualization-tool/utils/browser-management.ts","../src/tools/visualization-tool/utils/combine.ts","../src/tools/visualization-tool/utils/pixel-diff-heatmap.ts","../src/tools/launch-tool/index.ts","../src/tools/launch-tool/utils/dev-server-manager.ts","../src/nodes/validation/utils/extraction/extract-protocol-context.ts","../src/nodes/validation/core/validate-position.ts","../src/tools/position-tool/index.ts","../src/tools/position-tool/utils/capture-position.ts","../src/tools/position-tool/utils/position-metrics.ts","../src/tools/position-tool/utils/aggregate-elements.ts","../src/utils/dependency-installer.ts","../src/nodes/code/index.ts","../src/nodes/code/utils.ts","../src/nodes/code/prompt.ts","../src/nodes/code/constants.ts","../src/utils/code-cache.ts","../src/utils/checkpoint.ts","../src/cli/prompts.ts","../src/cli/images.ts","../src/cli/p2c.ts","../src/cli/val.ts"],"sourcesContent":["import chalk from 'chalk';\n\n/**\n * Get current timestamp in YYYY-MM-DD HH:mm:ss format\n */\nfunction getTimestamp(): string {\n const now = new Date();\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const day = String(now.getDate()).padStart(2, '0');\n const hours = String(now.getHours()).padStart(2, '0');\n const minutes = String(now.getMinutes()).padStart(2, '0');\n const seconds = String(now.getSeconds()).padStart(2, '0');\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;\n}\n\n/**\n * Logger utility for consistent console output with colors\n */\nexport const logger = {\n /**\n * Print standard log (alias for info logs).\n *\n * Many subsystems (e.g. validation) use `printLog()` as the default logging method.\n */\n printLog(message: string): void {\n console.log(message);\n },\n\n /**\n * Print info log in blue\n */\n printInfoLog(message: string): void {\n console.log(chalk.blue(`[${getTimestamp()}] [INFO] ${message}`));\n },\n\n /**\n * Print warning log in yellow\n */\n printWarnLog(message: string): void {\n console.warn(chalk.yellow(`[${getTimestamp()}] [WARNING] ${message}`));\n },\n\n /**\n * Print error log in red\n */\n printErrorLog(message: string): void {\n console.error(chalk.red(`[${getTimestamp()}] [ERROR] ✖ ${message}`));\n },\n\n /**\n * Print test/debug log in gray\n * Only logs in development/test environments\n */\n printTestLog(message: string): void {\n if (process.env.NODE_ENV === 'development') {\n console.log(chalk.gray(`[${getTimestamp()}] [DEBUG] ${message}`));\n }\n },\n\n /**\n * Print success log in green\n */\n printSuccessLog(message: string): void {\n console.log(chalk.green(`[${getTimestamp()}] [SUCCESS] ✔ ${message}`));\n },\n};\n","/**\n * Prompt template for structure generation.\n * Matches the style used in agents/initial-agent/prompt.ts.\n */\nexport const generateStructurePrompt = (options: { positions: string; width?: string }) => {\n const { positions, width } = options;\n const imageWidth = width ?? '1440';\n return `\n<system_instructions>\n <task>Generate a semantic React component structure from Figma design data.</task>\n\n <input_context>\n <positions_json>${positions}</positions_json>\n <image_width>${imageWidth}px</image_width>\n <visual_reference>Refer to the attached image for hierarchy and grouping.</visual_reference>\n </input_context>\n\n <rules>\n <rule name=\"Hierarchy Strategy\">\n 1. Compare 'positions_json' nesting with visual grouping.\n 2. If data contradicts visual layout, IGNORE data nesting and restructure based on VISUAL proximity.\n </rule>\n\n <rule name=\"Pattern Recognition (CRITICAL)\">\n 1. **Semantic Grouping**: Group by function (e.g., \"PricingCard\", \"UserProfile\").\n 2. **Grid/List Detection**:\n - Detect repeating identical siblings (e.g., 6 Cards).\n - Create a SINGLE container (e.g., \"CardGrid\") instead of \"Card1\", \"Card2\".\n - **MERGE IDs**: The container's \\`elementIds\\` MUST include ALL children IDs of all items in the grid to ensure complete style extraction.\n - **Reusable Instances with \\`data.componentName\\`**:\n - For each visually repeated item, keep a unique \\`id\\` / \\`data.name\\` (e.g., \"TaskCard1\", \"TaskCard2\", ...).\n - Set the SAME \\`data.componentName\\` for all these items (e.g., \"TaskCard\") to mark them as instances of one reusable component.\n - Example: 12 task cards → each child has different \\`id\\` / \\`data.name\\` (\"TaskCard1\"... \"TaskCard12\"), but the SAME \\`data.componentName\\`: \"TaskCard\".\n 3. **Fragmentation**: Avoid creating components for single atoms (Text/Icon) unless reusable (Button/Chip).\n 4. **Monoliths**: Split sections >1000px height.\n </rule>\n\n <rule name=\"Component Granularity (CRITICAL - Prevent Over-Fragmentation)\">\n 1. **Maximum Depth = 2**:\n - Component tree should NOT exceed 2 levels deep (root -> children -> grandchildren is the MAX).\n - If you find yourself creating a 3rd level, STOP and merge it into the parent instead.\n\n 2. **Minimum Element Threshold**:\n - Each component MUST contain at least 5+ elements in its \\`elementIds\\`.\n - If a potential component has fewer than 5 elements, MERGE it into its parent or sibling.\n - This prevents creating tiny components like \"LegalLinks\" (3 links) or \"CommunityLinks\" (2 links).\n\n 3. **Component Count Limit**:\n - For a single section, create at most 2-3 child components.\n - Example: Footer → FooterTop, FooterBottom (2 children, NOT 4-5 like \"Logos\", \"Links\", \"QRCode\", etc.)\n\n 4. **DO NOT Create Separate Components For**:\n - A group of links (merge into parent section's elementIds)\n - A group of logos or icons (merge into parent section's elementIds)\n - Single text, image, icon, divider, link\n - Any group with < 5 elements\n These should ALL be included in parent's \\`elementIds\\`.\n\n 5. **Merge by Visual Region, NOT by Function**:\n - Divide by visual position (Top/Bottom, Left/Right), NOT by element type (Links/Logos/QRCode).\n - Example: FooterTop contains logos + links + icons together (all elements in that visual area).\n </rule>\n\n <rule name=\"Naming & ID\">\n - \\`id\\` MUST match \\`data.name\\` (PascalCase, Unique).\n - **Containers**: \\`elementIds\\` = container background/frame IDs only.\n - **Leaves**: \\`elementIds\\` = component's direct IDs + ALL nested children IDs.\n - **Integrity**: Every input ID must be assigned to exactly one component.\n </rule>\n\n <rule name=\"Layout Data\">\n For EACH node, calculate:\n - \\`boundingBox\\`: {top, left, width, height} (Absolute)\n - \\`relativeBoundingBox\\`: {top, left, width, height} (Relative to parent)\n - \\`spacing\\`: {next: number} (Distance to next sibling)\n - \\`layoutDirection\\`: \"VERTICAL\" | \"HORIZONTAL\" | \"NONE\"\n **HOW TO DETERMINE layoutDirection (ESPECIALLY FOR ROOT NODE)**:\n 1. Look at ALL direct children's \\`boundingBox.left\\` values\n 2. **If children have 2+ DIFFERENT \\`left\\` values** (difference > 50px):\n → Set \\`layoutDirection = \"HORIZONTAL\"\\`\n → Example: Sidebar at left=0, Content at left=240 → HORIZONTAL\n 3. **If ALL children have SAME \\`left\\` value** (within ±50px tolerance):\n → Set \\`layoutDirection = \"VERTICAL\"\\`\n → Example: Header at left=0, Content at left=0, Footer at left=0 → VERTICAL\n 4. Common patterns:\n - **Sidebar Layout**: Sidebar (left=0) + Main Content (left=240+) → ROOT is HORIZONTAL\n - **Stacked Layout**: All sections at same left position → ROOT is VERTICAL\n </rule>\n </rules>\n\n <output_format>\n Return ONLY a single valid JSON object (no markdown code blocks).\n Output MUST be COMPACT (no pretty-printing): avoid indentation/newlines as much as possible.\n Follow this schema exactly:\n {\n \"id\": \"ComponentName\",\n \"data\": {\n \"name\": \"ComponentName\",\n \"componentName\": \"OptionalReusableComponentName\",\n \"purpose\": \"string\",\n \"elementIds\": [\"id1\", \"...\"],\n \"layout\": {\n \"boundingBox\": { \"top\": 0, \"left\": 0, \"width\": 0, \"height\": 0 },\n \"relativeBoundingBox\": { \"top\": 0, \"left\": 0, \"width\": 0, \"height\": 0 },\n \"spacing\": { \"next\": 0 },\n \"layoutDirection\": \"VERTICAL\"\n }\n },\n \"children\": []\n }\n\n layoutDirection MUST be one of: \"VERTICAL\" | \"HORIZONTAL\" | \"NONE\"\n \n **Layout Groups**:\n - Do NOT generate \\`layoutGroups\\` field in your output\n - This field will be automatically added by post-processing if needed\n\n **CRITICAL: 2-Level Maximum Structure**\n\n Your output MUST follow a maximum 2-level structure. Level 2 nodes should have \\`children: []\\`.\n All primitive elements (single text, links, logos, icons, dividers) go into \\`elementIds\\`, NOT as child components.\n\n Example for ANY section:\n {\n \"id\": \"SectionName\",\n \"data\": {\n \"name\": \"SectionName\",\n \"purpose\": \"Main section description\",\n \"elementIds\": [\"container-id\"],\n \"layout\": {...}\n },\n \"children\": [\n {\n \"id\": \"SubSectionA\",\n \"data\": {\n \"name\": \"SubSectionA\",\n \"purpose\": \"Visual area with links, logos, text\",\n \"elementIds\": [\"all\", \"element\", \"ids\", \"including\", \"links\", \"logos\", \"text\"],\n \"layout\": {...}\n },\n \"children\": [] // MUST be empty - all elements via elementIds\n },\n {\n \"id\": \"SubSectionB\",\n \"data\": {\n \"name\": \"SubSectionB\",\n \"purpose\": \"Another visual area\",\n \"elementIds\": [\"all\", \"element\", \"ids\", \"in\", \"this\", \"area\"],\n \"layout\": {...}\n },\n \"children\": [] // MUST be empty\n }\n ]\n }\n\n For reusable component instances that share the same \\`data.componentName\\` but have different \\`id\\` and \\`data.name\\`, an additional expected example is:\n {\n \"id\": \"TaskCardGrid\",\n \"data\": {\n \"name\": \"TaskCardGrid\",\n \"purpose\": \"Grid container for task cards\",\n \"elementIds\": [\"...\"],\n \"layout\": {\n \"boundingBox\": { \"top\": 0, \"left\": 0, \"width\": 0, \"height\": 0 },\n \"relativeBoundingBox\": { \"top\": 0, \"left\": 0, \"width\": 0, \"height\": 0 },\n \"spacing\": { \"next\": 0 },\n \"layoutDirection\": \"VERTICAL\"\n }\n },\n \"children\": [\n {\n \"id\": \"TaskCard1\",\n \"data\": {\n \"name\": \"TaskCard1\",\n \"componentName\": \"TaskCard\",\n \"purpose\": \"Single task card\",\n \"elementIds\": [\"id1\", \"...\"],\n \"layout\": {\n \"boundingBox\": { \"top\": 0, \"left\": 0, \"width\": 0, \"height\": 0 },\n \"relativeBoundingBox\": { \"top\": 0, \"left\": 0, \"width\": 0, \"height\": 0 },\n \"spacing\": { \"next\": 0 },\n \"layoutDirection\": \"VERTICAL\"\n }\n },\n \"children\": []\n }\n ]\n }\n </output_format>\n</system_instructions>\n`.trim();\n};\n\n/**\n * Prompt template for extracting data list and props schema.\n */\nexport const extractDataListPrompt = (options: { containerName: string; childComponentName: string; figmaData: string }) => {\n const { containerName, childComponentName, figmaData } = options;\n return `\nYou are an expert Frontend Developer.\nYou are analyzing a container component \"${containerName}\" which contains a list of \"${childComponentName}\" components.\n\nYour task is to:\n1. Generate a **props schema** (formal parameter definitions) based on the first component instance\n2. Extract the **data array** (actual parameter values) for all component instances from the provided Figma structure data\n\nContext:\n- Container: ${containerName}\n- Child Component: ${childComponentName}\n- Figma Data:\n${figmaData}\n\nInstructions:\n1. Analyze the \"children\" in the Figma Data. Identify those that are instances of \"${childComponentName}\".\n2. For each instance, extract ALL differing content, including:\n - **Text**: Extract the **EXACT** text content found in the \"characters\" fields. Do NOT summarize or generate placeholders.\n - **Images/Icons**: Identify nodes where \\`type\\` is \"IMAGE\". These nodes will have a \\`url\\` field.\n - If a node has \\`isIcon: true\\` field, or the node name contains \"icon\", or the url ends with \".svg\", use \\`iconSrc\\` as the key.\n - Otherwise, use \\`imageSrc\\` or \\`avatarSrc\\` based on context (e.g., avatar for profile pictures).\n - **Layout/Variants**: \n - If the component has \\`layoutDirection: \"HORIZONTAL\"\\` in the layoutInfo, and contains both text and image content, determine the image position:\n - Check the \\`absoluteBoundingBox\\` positions: if image's x position is less than text's x position, image is on the **left**; otherwise on the **right**.\n - Extract as \\`imagePosition: \"left\"\\` or \\`imagePosition: \"right\"\\` prop.\n - Any other component properties or visual variants (e.g. \"variant\": \"filled\", \"active\": true).\n3. **Normalize the data keys (CRITICAL)**:\n - For text content: use \\`title\\`, \\`description\\`, \\`label\\`, etc.\n - For images/icons: ALWAYS use \\`iconSrc\\`, \\`imageSrc\\`, \\`avatarSrc\\` (with \"Src\" suffix)\n - **DO NOT** use ambiguous keys like \\`icon\\`, \\`image\\`, \\`avatar\\` alone\n - This ensures compatibility with standard React component prop naming conventions.\n - Example:\n \\`\\`\\`json\n {\n \"title\": \"Example Title\",\n \"description\": \"Example description\",\n \"imageSrc\": \"@/assets/actual-filename-from-figma.png\"\n }\n \\`\\`\\`\n4. **Generate Props Schema (CRITICAL)**:\n - Based on the first component instance, infer the prop definitions\n - For each extracted field (e.g., \"title\", \"description\", \"imageSrc\"), determine:\n * **key**: The property name (e.g., \"title\")\n * **type**: The TypeScript type - must be one of: \"string\", \"number\", \"boolean\", \"string[]\", \"number[]\"\n * **description**: A clear description of what this prop represents\n - Return as \"props\" array with objects containing { key, type, description }\n - Example:\n \\`\\`\\`json\n {\n \"key\": \"title\",\n \"type\": \"string\",\n \"description\": \"Card title text\"\n }\n \\`\\`\\`\n5. **CRITICAL Rules**:\n - **USE ACTUAL DATA ONLY**: The example above uses placeholder names. You MUST use the actual \"characters\" and \"url\" values from the Figma Data provided.\n - **NO FIGMA IDs**: Do NOT include Figma node IDs (like \"1:2859\") in the output. Only extract actual content data.\n - **NO PLACEHOLDERS**: Do NOT generate fake text or copy paths from examples. If a node does not have a \"url\" field, do not include an \"imageSrc\" property.\n - **Deep Search**: Text nodes might be nested deeply inside Frames/Groups. Look recursively for \"characters\" fields.\n - **Layout Information**: The Figma Data includes \\`layoutInfo\\` array with \\`layoutDirection\\` and \\`absoluteBoundingBox\\` for each component instance. Use this to determine layout-related props like image position (left/right) in horizontal layouts.\n - **Asset Paths - CRITICAL**: \n - Images are represented by nodes with \\`type: \"IMAGE\"\\`. These nodes MUST have a \\`url\\` field.\n - You MUST use the EXACT value from the \\`url\\` field as the value for \"imageSrc\", \"iconSrc\", or \"avatarSrc\" without any modifications.\n - The \\`url\\` field value MUST be a file path (e.g., \"@/assets/icon-name.svg\").\n - **DO NOT hallucinate or copy paths from the example above.** Every image MUST correspond to a node in the provided Figma Data.\n - CORRECT: If a node has \\`type: \"IMAGE\"\\` and \\`url: \"@/assets/real-image-123.png\"\\`, use exactly that.\n - WRONG: Using \"@/assets/start-2.svg\" if it's not in the input data.\n - If the \\`url\\` field does not exist or does not contain a valid path starting with \"@/assets/\", omit the iconSrc/imageSrc/avatarSrc field entirely.\n6. Return a JSON object with two keys:\n - \"props\": Array of prop definitions with { key, type, description }\n - \"state\": Array of data objects for each component instance\n7. Return ONLY the JSON object. Do not explain.\n\nExample Output JSON Structure (for reference only):\n{\n \"props\": [\n {\n \"key\": \"title\",\n \"type\": \"string\",\n \"description\": \"Card title text\"\n },\n {\n \"key\": \"description\",\n \"type\": \"string\",\n \"description\": \"Card description text\"\n },\n {\n \"key\": \"imageSrc\",\n \"type\": \"string\",\n \"description\": \"Path to card image\"\n }\n ],\n \"state\": [\n {\n \"title\": \"Actual Title 1\",\n \"description\": \"Actual Description 1\",\n \"imageSrc\": \"@/assets/actual-file-1.png\"\n },\n {\n \"title\": \"Actual Title 2\",\n \"description\": \"Actual Description 2\",\n \"imageSrc\": \"@/assets/actual-file-2.png\"\n }\n ]\n}\n`.trim();\n};\n","/**\n * Utility to fetch Figma thumbnail and extract its dimensions\n * Matches the Python reference implementation from evolt\n */\n\nimport axios from 'axios';\nimport { logger } from '../../../utils/logger';\n\nexport interface ThumbnailDimensions {\n width: number;\n height: number;\n}\n\n/**\n * Fetches Figma thumbnail and extracts its dimensions.\n * This ensures the browser viewport matches the Figma thumbnail dimensions,\n * preventing screenshot dimension mismatches.\n *\n * Based on evolt Python implementation: _fetch_figma_thumbnail_with_dimensions()\n *\n * @param figmaThumbnailUrl - Figma thumbnail CDN URL\n * @returns Promise resolving to thumbnail dimensions, or undefined if fetch fails\n *\n * @example\n * ```typescript\n * const dimensions = await fetchThumbnailDimensions(figmaThumbnailUrl);\n * if (dimensions) {\n * const viewport = { width: dimensions.width, height: dimensions.height };\n * // Use viewport for browser launch\n * }\n * ```\n */\nexport async function fetchThumbnailDimensions(figmaThumbnailUrl: string): Promise<ThumbnailDimensions | undefined> {\n if (!figmaThumbnailUrl) {\n return undefined;\n }\n\n try {\n const sharp = (await import('sharp')).default;\n // Fetch the image from Figma CDN\n const response = await axios.get(figmaThumbnailUrl, {\n responseType: 'arraybuffer',\n timeout: 30000,\n });\n\n // Extract dimensions using Sharp\n const imageBuffer = Buffer.from(response.data);\n const metadata = await sharp(imageBuffer).metadata();\n\n if (!metadata.width || !metadata.height) {\n return undefined;\n }\n\n return {\n width: metadata.width,\n height: metadata.height,\n };\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.printWarnLog(`Failed to fetch Figma thumbnail: ${errorMsg}`);\n return undefined;\n }\n}\n","#!/usr/bin/env node\n\n/**\n * CLI Entry Point for Coderio.\n * This file handles command registration, argument parsing, and global error handling for the CLI.\n */\n\n// Save the user's current working directory before any operations\nprocess.env.CODERIO_CLI_USER_CWD = process.cwd();\n\nimport { Command } from 'commander';\nimport { registerCommands } from './init';\nimport { logger } from '../utils/logger';\nimport { registerD2PCommand } from './d2p';\nimport { registerD2CCommand } from './d2c';\nimport { registerImagesCommand } from './images';\nimport { registerP2CCommand } from './p2c';\nimport { registerValidateCommand } from './val';\n\nasync function main(argv: string[]): Promise<void> {\n const program = new Command();\n\n // Register all commands\n registerCommands(program);\n registerD2CCommand(program);\n registerD2PCommand(program);\n registerP2CCommand(program);\n registerImagesCommand(program);\n registerValidateCommand(program);\n\n if (argv.length <= 2) {\n program.help({ error: false });\n return;\n }\n\n // Parse arguments and execute actions\n await program.parseAsync(argv);\n}\n\nmain(process.argv).catch(err => {\n const error = err as Error;\n logger.printErrorLog(`${error.message || String(error)}`);\n process.exit(1);\n});\n","/* Application constants */\n\nexport const CLI_NAME = 'coderio'; // CLI name\nexport const MAX_OUTPUT_TOKENS = 20480; // Max output tokens\n\n/* Unified agent context window token limit */\nexport const AGENT_CONTEXT_WINDOW_TOKENS = 128000;\n","import { Command } from 'commander';\nimport { CLI_NAME } from '../constants';\n\n/* Register all commands to the program */\nexport function registerCommands(program: Command): void {\n const version = typeof __VERSION__ === 'undefined' ? '0.0.1' : __VERSION__;\n program\n .name(CLI_NAME)\n .description(`${CLI_NAME} - Convert Figma designs to code`)\n .version(version, '-v, -V, --version', 'Output the version number')\n .showHelpAfterError();\n}\n","import { tools } from 'evoltagent';\nimport { checkBorder } from './figma';\nimport { FigmaFrameInfo } from '../../types/figma-types';\nimport { ImageNode } from './types';\nimport { executeDownloadImages, fetchImages, findImageNodes } from './images';\nimport { cleanFigma, fetchFigmaNode, fetchFigmaImages } from './figma';\nimport { styleTool } from '../style-tool';\n\n@tools({\n fetchAndClean: {\n description: 'Fetch and clean Figma document from URL',\n params: [\n { name: 'fileId', type: 'string', description: 'Figma file ID' },\n { name: 'nodeId', type: 'string', description: 'Figma node ID' },\n { name: 'token', type: 'string', description: 'Figma API token' },\n ],\n returns: {\n type: 'FigmaFrameInfo',\n description: 'Original Figma document fetched from the URL via official Figma API and cleaned by removing invisible nodes',\n },\n },\n downloadImages: {\n description: 'Detect and download image nodes from figma document',\n params: [\n { name: 'fileId', type: 'string', description: 'Figma file ID' },\n { name: 'token', type: 'string', description: 'Figma API token' },\n { name: 'imageDir', type: 'string', description: 'Output directory path' },\n {\n name: 'document',\n optional: true,\n type: 'FigmaFrameInfo',\n description: 'Figma document which is fetched and cleaned from the URL',\n },\n ],\n returns: {\n type: '{ successCount: number; failCount: number; imageNodesMap: Map<string, ImageNode> }',\n description: 'Download results of images from the Figma document with Map structure',\n },\n },\n simplifyImageNodes: {\n description: 'Simplify image nodes in figma document by replacing redundant properties with url',\n params: [\n { name: 'node', type: 'FigmaFrameInfo', description: 'Figma node' },\n { name: 'imageNodes', type: 'Map<string, ImageNode>', description: 'Image nodes map with id as key' },\n ],\n returns: {\n type: 'FigmaFrameInfo',\n description: 'Figma node with image nodes simplified and replaced with url',\n },\n },\n processedStyle: {\n description: 'Process styles in Figma document',\n params: [{ name: 'node', type: 'FigmaFrameInfo', description: 'Figma node' }],\n returns: {\n type: 'FigmaFrameInfo',\n description: 'Figma node with styles processed',\n },\n },\n})\nclass FigmaTool {\n async fetchAndClean(fileId: string, nodeId: string, token: string): Promise<FigmaFrameInfo | undefined> {\n if (!fileId || !nodeId || !token) {\n return undefined;\n }\n\n const document = await fetchFigmaNode(fileId, nodeId, token);\n if (!document || !document?.children?.length) {\n throw new Error('Failed to fetch Figma document');\n }\n\n const images = await fetchFigmaImages(fileId, nodeId, token);\n const thumbnail = images?.[nodeId] || '';\n if (!thumbnail) {\n throw new Error('Failed to fetch Figma document thumbnail');\n }\n document.thumbnailUrl = thumbnail;\n\n const cleanedDocument = cleanFigma(document);\n\n return cleanedDocument;\n }\n\n async downloadImages(\n fileId: string,\n token: string,\n imageDir: string,\n document?: FigmaFrameInfo\n ): Promise<{ successCount: number; failCount: number; imageNodesMap: Map<string, ImageNode> }> {\n if (!fileId) {\n return { successCount: 0, failCount: 0, imageNodesMap: new Map() };\n }\n\n /* Detect images from the document */\n const imageNodes = findImageNodes(document?.children || [], document?.absoluteBoundingBox);\n const fetchedImages = await fetchImages(imageNodes, fileId, token);\n if (!fetchedImages.length) {\n return { successCount: 0, failCount: 0, imageNodesMap: new Map() };\n }\n\n return await executeDownloadImages(fetchedImages, imageDir);\n }\n\n simplifyImageNodes(node: FigmaFrameInfo, imageNodes: Map<string, ImageNode>): FigmaFrameInfo {\n const imageTarget = imageNodes.get(node.id);\n\n if (imageTarget) {\n const basicInfo: FigmaFrameInfo = {\n id: node.id,\n name: node.name,\n type: 'IMAGE',\n url: imageTarget.url,\n absoluteBoundingBox: node.absoluteBoundingBox,\n absoluteRenderBounds: node.absoluteRenderBounds,\n };\n\n if (node.cornerRadius) {\n basicInfo.cornerRadius = node.cornerRadius;\n }\n\n if (checkBorder(node)) {\n basicInfo.strokes = node.strokes;\n basicInfo.strokeWeight = node.strokeWeight;\n basicInfo.strokeAlign = node.strokeAlign;\n }\n return basicInfo;\n }\n\n const result: FigmaFrameInfo = { ...node };\n if (node.children && Array.isArray(node.children)) {\n result.children = node.children.map(child => this.simplifyImageNodes(child, imageNodes));\n }\n\n return result;\n }\n\n processedStyle(node: FigmaFrameInfo): FigmaFrameInfo {\n // Convert current node's styles using style-tool\n const processedNode = styleTool.convert(node);\n\n // Recursively process children\n if (processedNode.children && Array.isArray(processedNode.children)) {\n processedNode.children = processedNode.children.map(child => this.processedStyle(child));\n }\n\n return processedNode;\n }\n}\n\nexport const figmaTool = new FigmaTool();\n","import axios, { AxiosRequestConfig } from 'axios';\nimport { getDebugConfig } from './config';\nimport { writeFile } from './file';\nimport { workspaceManager } from './workspace';\n\n/**\n * Save debug log\n */\nfunction saveDebugLog(\n requestInfo: { url: string; config: AxiosRequestConfig },\n responseInfo: { status: number; statusText: string; data: unknown }\n): void {\n const debugConfig = getDebugConfig();\n if (!debugConfig.enabled) {\n return;\n }\n const debugContent = [\n '------------request------------',\n JSON.stringify(requestInfo, null, 2),\n '------------response------------',\n JSON.stringify(responseInfo, null, 2),\n ].join('\\n');\n writeFile(workspaceManager.path?.debug ?? '', `fetch_${new Date().toISOString().replace(/:/g, '-')}.md`, debugContent);\n}\n\n/**\n * Axios get request with debug logging\n */\nexport async function get<T>(url: string, config?: AxiosRequestConfig<T>): Promise<T> {\n const response = await axios.get<T>(url, config);\n\n saveDebugLog(\n {\n url,\n config: config ?? {},\n },\n {\n status: response.status,\n statusText: response.statusText,\n data: response.data,\n }\n );\n\n return response.data;\n}\n","import { readFileSync, existsSync } from 'fs';\nimport { resolve } from 'path';\nimport { homedir } from 'os';\nimport yaml from 'js-yaml';\n\n// Configuration directory in user's home\nexport const CONFIG_DIR = resolve(homedir(), '.coderio');\nconst CONFIG_FILE = resolve(CONFIG_DIR, 'config.yaml');\n\n/**\n * Model configuration interface\n */\nexport interface ModelConfig {\n provider: string;\n model: string;\n baseUrl: string;\n apiKey: string;\n}\n\n/**\n * Figma configuration interface\n */\nexport interface FigmaConfig {\n token: string;\n}\n\n/**\n * Debug configuration interface\n */\nexport interface DebugConfig {\n enabled: boolean;\n outputDir?: string;\n}\n\n/**\n * Configuration file structure\n */\ninterface Config {\n model: ModelConfig;\n figma: FigmaConfig;\n debug?: DebugConfig;\n}\n\n// Cache for loaded configuration\nlet cachedConfig: Config | null = null;\n\n/**\n * Load configuration from user's config directory\n * The configuration is cached after first load\n * @returns Full configuration object\n */\nexport function loadConfig(): Config {\n if (cachedConfig) {\n return cachedConfig;\n }\n\n if (!existsSync(CONFIG_FILE)) {\n throw new Error(`Configuration file not found at: ${CONFIG_FILE}\\n` + `Please create the configuration file.`);\n }\n\n try {\n const fileContent = readFileSync(CONFIG_FILE, 'utf8');\n const rawConfig = yaml.load(fileContent) as Config;\n\n if (!rawConfig) {\n throw new Error('Invalid config.yaml structure: configuration is empty');\n }\n\n cachedConfig = rawConfig;\n return cachedConfig;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Failed to load config.yaml: ${error.message}`);\n }\n throw error;\n }\n}\n\n/**\n * Get model configuration from config.yaml\n * @returns Model configuration\n * @throws Error if configuration is invalid\n */\nexport function getModelConfig(): ModelConfig {\n const config = loadConfig();\n if (!config.model) {\n throw new Error('Model configuration not found in config.yaml');\n }\n return config.model;\n}\n\n/**\n * Get Figma configuration from config.yaml\n * @returns Figma configuration\n * @throws Error if configuration is invalid\n */\nexport function getFigmaConfig(): FigmaConfig {\n const config = loadConfig();\n if (!config.figma) {\n throw new Error('Figma configuration not found in config.yaml');\n }\n return config.figma;\n}\n\n/**\n * Get debug configuration from config.yaml\n * @returns Debug configuration (defaults to disabled if not specified)\n */\nexport function getDebugConfig(): DebugConfig {\n const config = loadConfig();\n return config.debug || { enabled: false };\n}\n\n/**\n * Get the path to the configuration file\n */\nexport function getConfigPath(): string {\n return CONFIG_FILE;\n}\n\n/**\n * Check if configuration file exists\n */\nexport function configExists(): boolean {\n return existsSync(CONFIG_FILE);\n}\n/**\n * Clear the configuration cache\n * Useful for testing or when configuration needs to be reloaded\n */\nexport function clearConfigCache(): void {\n cachedConfig = null;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { logger } from './logger';\nimport { FileInfo } from '../types/file-types';\n\n/**\n * Write file to the specified path\n * @param filePath - The path to the file\n * @param content - The content to write to the file\n */\nexport const writeFile = (folderPath: string, filePath: string, content: string) => {\n if (!folderPath || !filePath || !content) {\n return;\n }\n if (!fs.existsSync(folderPath)) {\n fs.mkdirSync(folderPath, { recursive: true });\n }\n fs.writeFileSync(path.join(folderPath, filePath), content);\n};\n\n/**\n * Create multiple files from parsed data\n */\nexport function createFiles({ files, filePath }: { files: FileInfo[]; filePath: string }): void {\n try {\n for (const file of files) {\n const dirPath = path.dirname(filePath);\n writeFile(dirPath, file.filename, file.content);\n }\n } catch (error) {\n logger.printErrorLog(`Failed to create files in ${filePath}: ${(error as Error).message}`);\n throw error;\n }\n}\n","import path from 'node:path';\nimport fs from 'node:fs';\nimport { WorkspaceStructure } from '../types/workspace-types';\nimport { logger } from './logger';\n\n/**\n * Defines the logical structure of the output workspace.\n * output directory structure\n coderio/\n └── figmaName/ # Project root directory generated from a Figma URL\n ├── my-app/ # Generated project source code\n ├── process/ # Intermediate data and cache during generation\n │ ├── validation/ # Validation reports, screenshots, and processed.json\n │ └── ... # Other process artifacts\n ├── reports.html # Validation reports summary\n └── checkpoint/ # Cache\n ├── coderio-cli.db \n └── checkpoint.json \n*/\nclass Workspace {\n path: WorkspaceStructure | null = null;\n\n initWorkspace(subPath: string, rootPath?: string, appName?: string): WorkspaceStructure {\n if (this.path) {\n return this.path;\n }\n\n const root = rootPath || (process.env.CODERIO_CLI_USER_CWD ?? process.cwd());\n const coderioRoot = path.join(root, 'coderio');\n const finalRoot = path.resolve(coderioRoot, subPath);\n const app = appName || 'my-app';\n\n const absoluteRoot = path.resolve(finalRoot);\n const processDir = path.join(absoluteRoot, 'process');\n const checkpointDir = path.join(absoluteRoot, 'checkpoint');\n const debugDir = path.join(absoluteRoot, 'debug');\n\n this.path = {\n root: absoluteRoot,\n app: path.join(absoluteRoot, app),\n process: processDir,\n debug: debugDir,\n reports: path.join(absoluteRoot, 'reports.html'),\n db: path.join(checkpointDir, 'coderio-cli.db'),\n checkpoint: path.join(checkpointDir, 'checkpoint.json'),\n };\n return this.path;\n }\n\n /**\n * Delete all files and directories inside the workspace\n * @param workspace - The workspace structure\n * @param exclude - Optional list of file/directory names to exclude from deletion\n */\n deleteWorkspace(workspace: WorkspaceStructure, exclude: string[] = []): void {\n try {\n if (fs.existsSync(workspace.root)) {\n // Read all entries in the workspace root\n const entries = fs.readdirSync(workspace.root);\n\n // Delete each entry\n for (const entry of entries) {\n if (exclude.includes(entry)) {\n continue;\n }\n const fullPath = path.join(workspace.root, entry);\n fs.rmSync(fullPath, { recursive: true, force: true });\n }\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.printWarnLog(`Failed to delete workspace: ${errorMessage}`);\n }\n }\n\n /**\n * Resolve the absolute path to the source code directory\n * @param paths - The workspace structure\n * @param srcSubPath - The subpath to the source code directory\n * @returns The absolute path to the source code directory\n */\n resolveAppSrc(paths: WorkspaceStructure, srcSubPath: string): string {\n return path.join(paths.app, 'src', srcSubPath);\n }\n\n /**\n * Resolve component alias path to absolute filesystem path.\n *\n * Handles various path formats:\n * - @/components/Button → /workspace/my-app/src/components/Button/index.tsx\n * - @/src/components/Button → /workspace/my-app/src/components/Button/index.tsx\n * - components/Button → /workspace/my-app/src/components/Button/index.tsx\n *\n */\n resolveComponentPath(aliasPath: string): string {\n // Normalize path separators for robustness across platforms.\n const normalizedAlias = aliasPath.replace(/\\\\/g, '/');\n\n // Step 1: Strip @/ prefix if present\n let relativePath = normalizedAlias.startsWith('@/')\n ? normalizedAlias.substring(2) // '@/components/Button' → 'components/Button'\n : normalizedAlias;\n\n // Step 2: Strip 'src/' prefix if present (resolveAppSrc adds it)\n // '@/src/components/Button' → 'components/Button'\n if (relativePath.startsWith('src/')) {\n relativePath = relativePath.substring(4);\n }\n\n // Step 3: Ensure path ends with /index.tsx (all components follow this convention)\n if (!relativePath.endsWith('.tsx') && !relativePath.endsWith('.ts')) {\n relativePath = `${relativePath}/index.tsx`;\n }\n\n return relativePath;\n }\n}\nexport const workspaceManager = new Workspace();\n","import { FigmaFrameInfo, FigmaImageFormat, FigmaColorObject } from '../../types/figma-types';\nimport { get } from '../../utils/axios';\nimport { logger } from '../../utils/logger';\n\n/**\n * Fetch Figma nodes by fileId and nodeId\n * @param fileId - Figma file ID\n * @param nodeId - Figma node ID\n * @param token - Figma API token\n * @returns Figma frame information\n */\nexport const fetchFigmaNode = async (fileId: string, nodeId: string, token: string): Promise<FigmaFrameInfo | undefined> => {\n const url = `https://api.figma.com/v1/files/${fileId}/nodes?ids=${nodeId}`;\n try {\n const data = await get<{ nodes: Record<string, { document: FigmaFrameInfo }> }>(url, {\n headers: {\n 'X-Figma-Token': token,\n },\n });\n // format node id to match the format in the response\n const resData = data.nodes?.[nodeId];\n return resData?.document;\n } catch (error) {\n logger.printErrorLog(`Failed to fetch Figma node: ${error instanceof Error ? error.message : 'Unknown error'}`);\n return undefined;\n }\n};\n\n/**\n * Fetch Figma image by fileId and nodeId\n * @param fileId - Figma file ID\n * @param nodeIds - Figma node ID, multiple node ids can be passed separated by commas\n * @param token - Figma API token\n * @param format - Figma image format\n * @returns Figma image\n */\nexport const fetchFigmaImages = async (\n fileId: string,\n nodeIds: string,\n token: string,\n format?: FigmaImageFormat\n): Promise<Record<string, string>> => {\n const url = `https://api.figma.com/v1/images/${fileId}`;\n try {\n const data = await get<{ images: Record<string, string> }>(url, {\n headers: {\n 'X-Figma-Token': token,\n },\n params: {\n ids: nodeIds,\n format: format || 'png',\n },\n });\n const images = data.images || {};\n // format node id to match the format from response to request\n return Object.fromEntries(Object.entries(images));\n } catch (error) {\n logger.printErrorLog(`Failed to fetch Figma images: ${error instanceof Error ? error.message : 'Unknown error'}`);\n return {};\n }\n};\n\n/**\n * Clean Figma node and children. Remove invisible nodes and children.\n * @param node - Figma node or children\n * @returns Cleaned Figma node or children. If the node is invisible, return null.\n */\nexport const cleanFigma = (node: FigmaFrameInfo): FigmaFrameInfo | undefined => {\n // if node is invisible, return undefined\n if (node.visible === false) {\n return undefined;\n }\n\n // if node has children, recursively clean each child\n if (node.children && Array.isArray(node.children)) {\n node.children = node.children\n .map(child => cleanFigma(child)) // recursively clean each child\n .filter(child => child !== undefined); // filter out invisible nodes\n }\n\n return node;\n};\n\n/**\n * Check if node has border\n * @param node - Figma node\n * @returns True if node has border, false otherwise\n */\nexport const checkBorder = (node: FigmaFrameInfo): boolean => {\n const strokes = node.strokes;\n const strokeWeight = node.strokeWeight;\n\n if (!strokes || !strokes.length || !strokeWeight) return false;\n\n const visibleStrokes = strokes.filter((s: FigmaColorObject) => s.visible !== false);\n if (visibleStrokes.length === 0) return false;\n\n return true;\n};\n","import { FigmaColorObject, FigmaFrameInfo, FigmaImageFormat, FigmaPositionAndSize } from '../../types/figma-types';\nimport { ImageNode } from './types';\nimport fs from 'fs';\nimport path from 'path';\nimport axios from 'axios';\nimport { promisePool } from '../../utils/promise-pool';\nimport { fetchFigmaImages } from './figma';\nimport { DEFAULT_DOWNLOAD_CONCURRENCY, DOWNLOAD_TIMEOUT_MS, MAX_DOWNLOAD_RETRIES, BASE_RETRY_DELAY_MS } from './constants';\nimport { logger } from '../../utils/logger';\n\n/**\n * Fetch images from figma document\n * @param nodes - Image nodes\n * @param fileId - Figma file ID\n * @param token - Figma API token\n * @returns Image nodes\n */\nexport const fetchImages = async (nodes: ImageNode[], fileId: string, token: string): Promise<ImageNode[]> => {\n if (!fileId || !nodes?.length) {\n return [];\n }\n\n const svgs = nodes.filter(node => node.format === FigmaImageFormat.SVG);\n const pngs = nodes.filter(node => node.format === FigmaImageFormat.PNG);\n const getImagePromises: Promise<{ [key: string]: string } | undefined>[] = [];\n\n if (svgs.length > 0) {\n getImagePromises.push(fetchFigmaImages(fileId, svgs.map(node => node.id).join(','), token, FigmaImageFormat.SVG));\n }\n if (pngs.length > 0) {\n getImagePromises.push(fetchFigmaImages(fileId, pngs.map(node => node.id).join(','), token, FigmaImageFormat.PNG));\n }\n\n const images: ImageNode[] = [];\n const results = await Promise.all(getImagePromises);\n results.forEach((res: { [key: string]: string } | undefined) => {\n if (res) {\n for (const [key, value] of Object.entries(res)) {\n images.push({\n id: key,\n name: '',\n format: FigmaImageFormat.PNG,\n ...(nodes.find(n => n.id === key) || {}),\n url: value || '',\n });\n }\n }\n });\n\n return images;\n};\n\n/**\n * Download images from figma document\n * @param images - Image nodes\n * @param imageDir - Output directory path\n * @param concurrency - Concurrency level\n * @returns Download results\n */\nexport const executeDownloadImages = async (\n images: ImageNode[],\n imageDir?: string,\n concurrency: number = DEFAULT_DOWNLOAD_CONCURRENCY\n): Promise<{ successCount: number; failCount: number; imageNodesMap: Map<string, ImageNode> }> => {\n if (!images || !images.length || !imageDir) {\n return {\n successCount: 0,\n failCount: 0,\n imageNodesMap: new Map(),\n };\n }\n\n // Process all images with dynamic concurrency control using promisePool\n const results = await promisePool(images, image => createDownloadTask(image, imageDir), concurrency);\n\n // Aggregate log after completion\n const successCount = results.filter(r => r.success).length;\n const failCount = results.length - successCount;\n\n // Convert results array to Map with id as key\n const imageNodesMap = new Map<string, ImageNode>(results.map(img => [img.id, img]));\n\n return {\n successCount,\n failCount,\n imageNodesMap,\n };\n};\n\n/**\n * Find image nodes in figma document\n * @param nodes - Figma nodes\n * @param absoluteBoundingBox - Absolute bounding box of the document\n * @returns Image nodes\n */\nexport const findImageNodes = (nodes: FigmaFrameInfo[], absoluteBoundingBox?: FigmaPositionAndSize): ImageNode[] => {\n const imageNodes: ImageNode[] = [];\n if (!nodes || !Array.isArray(nodes)) {\n return imageNodes;\n }\n\n for (const node of nodes) {\n if (node.visible === false) {\n continue;\n }\n // Rule 1: If node type is VECTOR, directly add to imageNodeIds\n else if (node.type === 'VECTOR') {\n imageNodes.push(assignImageObject(node, exportSvgIfNeeded(node, absoluteBoundingBox)));\n }\n // Rule 2: If node type is IMAGE or has imageRef, directly add to imageNodeIds\n else if (isImageNode(node) || isImageNodeViaName(node)) {\n if (isImageNode(node) || hasAnyImageNodeInDescendants(node)) {\n imageNodes.push(assignImageObject(node, FigmaImageFormat.PNG));\n } else {\n imageNodes.push(assignImageObject(node, exportSvgIfNeeded(node, absoluteBoundingBox)));\n }\n } else if (isMaskNode(node)) {\n imageNodes.push(assignImageObject(node, FigmaImageFormat.PNG));\n }\n // Rule 3: For nodes with children, check if any leaf descendant is a TEXT node with characters\n else if (node.children && node.children.length > 0) {\n const hasAnyTextNode = hasAnyTextNodeWithCharacters(node);\n\n if (hasAnyTextNode) {\n const firstLevelChildrenHasImageNode = node.children.some((child: FigmaFrameInfo) => isImageNode(child));\n const firstLevelChildrenHasTextNode = node.children.some((child: FigmaFrameInfo) => isTextNode(child));\n if (firstLevelChildrenHasImageNode && !firstLevelChildrenHasTextNode) {\n imageNodes.push(assignImageObject(node, FigmaImageFormat.PNG));\n } else {\n const childImageIds = findImageNodes(node.children, absoluteBoundingBox);\n imageNodes.push(...childImageIds);\n }\n } else if (hasAnyImageNodeInDescendants(node)) {\n imageNodes.push(assignImageObject(node, FigmaImageFormat.PNG));\n } else {\n imageNodes.push(assignImageObject(node, exportSvgIfNeeded(node, absoluteBoundingBox)));\n }\n }\n }\n\n return imageNodes;\n};\n\n/**\n * Determine whether a node should be exported as SVG or PNG\n * @param node - Figma node\n * @param absoluteBoundingBox - Absolute bounding box of the document\n * @returns Figma image format\n */\nexport const exportSvgIfNeeded = (node: FigmaFrameInfo, absoluteBoundingBox?: FigmaPositionAndSize) => {\n // Rule 1: Check if node is very large (likely a background) -> PNG\n if (node.absoluteBoundingBox && absoluteBoundingBox) {\n const { width, height } = node.absoluteBoundingBox;\n const { width: pageWidth, height: pageHeight } = absoluteBoundingBox;\n if (width >= pageWidth && height >= pageHeight) {\n return FigmaImageFormat.PNG;\n }\n }\n\n // Rule 2: Check exportSettings for explicit format specification\n if (node.exportSettings && node.exportSettings.length > 0) {\n const format = node.exportSettings[0].format;\n if (format === FigmaImageFormat.PNG) {\n return FigmaImageFormat.PNG;\n }\n if (format === FigmaImageFormat.SVG) {\n return FigmaImageFormat.SVG;\n }\n }\n\n // Rule 3: Check node name for background keywords -> PNG\n if (node.name.includes('背景') || node.name.toLowerCase().includes('background')) {\n return FigmaImageFormat.PNG;\n }\n\n // Default: Export as SVG\n return FigmaImageFormat.SVG;\n};\n\n/** Assign image object from figma node and format **/\nexport const assignImageObject = (node: { id: string; name: string }, format: FigmaImageFormat) => {\n return {\n id: node.id,\n name: node.name,\n format,\n };\n};\n\n/** Check if node has image ref in fills **/\nexport const hasImageRefInFills = (node: FigmaFrameInfo): boolean => {\n if (!node || !node.fills || node.fills.length === 0) {\n return false;\n }\n return node.fills.some((fill: FigmaColorObject) => {\n const fillWithImageRef = fill;\n return (fillWithImageRef.imageRef && fillWithImageRef.imageRef !== '') || fillWithImageRef.type === 'IMAGE';\n });\n};\n\n/** Check if node is image node **/\nexport const isImageNode = (node: FigmaFrameInfo): boolean => {\n if (!node) {\n return false;\n }\n\n if (node.type === 'IMAGE') {\n return true;\n }\n\n if (node.fills && node.fills.length > 0) {\n return hasImageRefInFills(node);\n }\n\n return false;\n};\n\n/** Check if node is image node via name **/\nexport const isImageNodeViaName = (node: FigmaFrameInfo): boolean => {\n return (node && node.name.toLowerCase().includes('img')) || node.name.toLowerCase().includes('image');\n};\n\n/** Check if node is mask node **/\nexport const isMaskNode = (node: FigmaFrameInfo): boolean => {\n return node && node.name.toLowerCase().includes('mask');\n};\n\n/** Check if node is text node **/\nexport const isTextNode = (node: FigmaFrameInfo): boolean => {\n return node && node.type === 'TEXT' && node.characters !== undefined && node.characters.trim() !== '';\n};\n\n/** Check if node has any image node in descendants **/\nexport const hasAnyImageNodeInDescendants = (node: FigmaFrameInfo): boolean => {\n if (!node) return false;\n\n if (!node.children || node.children.length === 0) {\n return isImageNode(node);\n }\n return node.children.some((child: FigmaFrameInfo) => hasAnyImageNodeInDescendants(child));\n};\n\n/** Check if node has any text node in descendants **/\nexport const hasAnyTextNodeWithCharacters = (node: FigmaFrameInfo): boolean => {\n if (!node) return false;\n\n if (!node.children || node.children.length === 0) {\n return isTextNode(node);\n }\n return node.children.some((child: FigmaFrameInfo) => hasAnyTextNodeWithCharacters(child));\n};\n\n/**\n * Download an image from URL and save to local directory\n * @param url - Image URL to download\n * @param filename - Local filename (with extension)\n * @param outputDir - Output directory path\n * @returns Local file path\n */\nexport async function downloadImage(url: string, filename?: string, imageDir?: string, base64?: boolean): Promise<string> {\n if (!url || (!base64 && (!filename || !imageDir))) {\n return '';\n }\n\n const maxRetries = MAX_DOWNLOAD_RETRIES;\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const response = await axios.get(url, {\n responseType: 'arraybuffer',\n timeout: DOWNLOAD_TIMEOUT_MS,\n });\n\n if (base64) {\n return Buffer.from(response.data).toString('base64');\n } else {\n if (!imageDir || !filename) {\n return '';\n }\n // Create directory if it doesn't exist\n if (!fs.existsSync(imageDir)) {\n fs.mkdirSync(imageDir, { recursive: true });\n }\n const filepath = path.join(imageDir, filename);\n fs.writeFileSync(filepath, Buffer.from(response.data));\n return filepath;\n }\n } catch (error) {\n lastError = error;\n // Don't wait on the last attempt\n if (attempt < maxRetries) {\n // Wait 1s, 2s, 3s, 4s, 5s\n const delay = BASE_RETRY_DELAY_MS * (attempt + 1);\n await new Promise(resolve => setTimeout(resolve, delay));\n }\n }\n }\n\n const errorMessage = lastError instanceof Error ? lastError.message : String(lastError);\n throw new Error(`Failed to download image from ${url} after ${maxRetries} retries: ${errorMessage}`);\n}\n\n/**\n * Create download task for image\n * @param image - Image object\n * @param outputDir - Output directory path\n * @returns Download task object\n */\nexport const createDownloadTask = async (image: ImageNode, imageDir?: string): Promise<ImageNode> => {\n if (!image.url) {\n return {\n id: image.id,\n name: image.name,\n format: image.format,\n url: image.url,\n remote: image.url,\n success: false,\n };\n }\n\n const ext = image.format || FigmaImageFormat.PNG;\n // Sanitize filename: remove special characters, replace spaces with dashes\n const sanitizedName = (image.name || image.id).replace(/[^a-zA-Z0-9-_]/g, '-').toLowerCase();\n const filename = `${sanitizedName}-${image.id.replace(/:/g, '-')}.${ext}`;\n\n try {\n const localPath = await downloadImage(image.url, filename, imageDir);\n const normalizedImageDir = imageDir ? path.normalize(imageDir) : '';\n const dirParts = normalizedImageDir.split(path.sep).filter(Boolean);\n const srcIndex = dirParts.lastIndexOf('src');\n const srcDir =\n srcIndex >= 0 ? (normalizedImageDir.startsWith(path.sep) ? path.sep : '') + path.join(...dirParts.slice(0, srcIndex + 1)) : '';\n\n const relativeFromSrc = srcDir ? path.relative(srcDir, localPath) : '';\n const normalizedRelative = relativeFromSrc.split(path.sep).join('/');\n const aliasPath = `@/${normalizedRelative}`;\n\n return {\n id: image.id,\n name: image.name,\n format: image.format,\n url: aliasPath,\n remote: image.url,\n success: true,\n };\n } catch {\n logger.printErrorLog(`Failed to download image: ${image.url}`);\n return {\n id: image.id,\n name: image.name,\n format: image.format,\n url: image.url,\n remote: image.url,\n success: false,\n };\n }\n};\n","/**\n * Run multiple asynchronous tasks with a concurrency limit.\n *\n * @param items - Array of items to process\n * @param taskGenerator - Function that creates a promise for a single item\n * @param concurrency - Maximum number of concurrent tasks\n * @returns Array of results\n */\nexport async function promisePool<T, R>(items: T[], taskGenerator: (item: T) => Promise<R>, concurrency: number = 5): Promise<R[]> {\n if (!items || !items.length) {\n return [];\n }\n const results: R[] = [];\n let nextIndex = 0;\n const executing = new Set<Promise<void>>();\n\n const processTask = async (index: number) => {\n const item = items[index];\n if (!item) {\n results[index] = undefined as unknown as R;\n return;\n }\n const result = await taskGenerator(item);\n results[index] = result;\n };\n\n while (nextIndex < items.length || executing.size > 0) {\n while (nextIndex < items.length && executing.size < concurrency) {\n const index = nextIndex++;\n const promise = processTask(index).finally(() => {\n executing.delete(promise);\n });\n executing.add(promise);\n }\n\n if (executing.size > 0) {\n await Promise.race(executing);\n }\n }\n\n return results;\n}\n","export const MAX_DOWNLOAD_RETRIES = 5; // Maximum number of download retries\nexport const DOWNLOAD_TIMEOUT_MS = 60000; // Download timeout in milliseconds\nexport const BASE_RETRY_DELAY_MS = 1000; // Base retry delay in milliseconds\nexport const DEFAULT_DOWNLOAD_CONCURRENCY = 5; // Default download concurrency\n","import { tools } from 'evoltagent';\nimport { CSSStyles, FigmaFrameInfo } from '../../types/figma-types';\nimport { convertBorderRadius, convertEffects, convertFills, convertStrokes, convertClipContent } from './utils';\n\n@tools({\n convert: {\n description: 'Convert Figma properties to CSS styles, remove redundant properties, and return the processed Figma node',\n params: [{ name: 'node', type: 'FigmaFrameInfo', description: 'Figma node' }],\n returns: {\n type: 'CSSStyles',\n description: 'CSS styles converted from Figma properties',\n },\n },\n})\nclass StyleTool {\n convert(node: FigmaFrameInfo): FigmaFrameInfo {\n const inlineStyles: CSSStyles = {};\n\n if (node.type !== 'TEXT') {\n convertBorderRadius(node, inlineStyles);\n convertEffects(node, inlineStyles);\n convertFills(node, inlineStyles);\n convertStrokes(node, inlineStyles);\n convertClipContent(node, inlineStyles);\n }\n\n // Create processed node with styles\n const processedNode: FigmaFrameInfo = {\n ...node,\n inlineStyles,\n };\n\n // Remove converted fields to reduce data size\n if (node.type !== 'TEXT') {\n const nodeWithOptionalStyles = processedNode as Partial<FigmaFrameInfo> & Record<string, unknown>;\n delete nodeWithOptionalStyles.fills;\n delete nodeWithOptionalStyles.background;\n delete nodeWithOptionalStyles.strokes;\n delete nodeWithOptionalStyles.strokeAlign;\n delete nodeWithOptionalStyles.backgroundColor;\n delete nodeWithOptionalStyles.cornerRadius;\n delete nodeWithOptionalStyles.rectangleCornerRadii;\n delete nodeWithOptionalStyles.effects;\n // delete nodeWithOptionalStyles.absoluteRenderBounds;\n delete nodeWithOptionalStyles.style;\n }\n return processedNode;\n }\n}\n\nexport const styleTool = new StyleTool();\n","/**\n * Color Converter\n * Convert Figma color objects (SOLID, GRADIENT_LINEAR, GRADIENT_RADIAL) to CSS color strings\n */\nimport { FigmaColorObject, FigmaColor, FigmaGradientStop } from '../../types/figma-types';\n\nexport class ColorConverter {\n // Main conversion entry point\n static convert(colorObject: FigmaColorObject): string {\n if (!colorObject) return 'transparent';\n\n const type = colorObject.type;\n\n switch (type) {\n case 'SOLID':\n return this.convertSolid(colorObject);\n case 'GRADIENT_LINEAR':\n return this.convertLinearGradient(colorObject);\n case 'GRADIENT_RADIAL':\n return this.convertRadialGradient(colorObject);\n default:\n return 'transparent';\n }\n }\n\n // Convert SOLID fill to rgba/rgb string\n private static convertSolid(fill: FigmaColorObject): string {\n if (!fill.color) return 'transparent';\n\n const opacity = this.getOpacity(fill.opacity);\n return this.rgbaToString(fill.color, opacity);\n }\n\n // Convert linear gradient to CSS linear-gradient\n private static convertLinearGradient(fill: FigmaColorObject): string {\n const stops = fill.gradientStops || [];\n const handles = fill.gradientHandlePositions || [];\n const fillOpacity = this.getOpacity(fill.opacity);\n\n if (stops.length === 0) return 'transparent';\n\n // Calculate gradient angle\n const angle = handles.length >= 2 ? this.calculateLinearGradientAngle(handles) : 180;\n\n // Calculate gradient stops with positions\n const stopsWithPositions = this.calculateLinearGradientStops(stops, handles, fillOpacity);\n\n return `linear-gradient(${angle}deg, ${stopsWithPositions})`;\n }\n\n // Convert radial gradient to CSS radial-gradient\n private static convertRadialGradient(fill: FigmaColorObject): string {\n const stops = fill.gradientStops || [];\n const handles = fill.gradientHandlePositions || [];\n const fillOpacity = this.getOpacity(fill.opacity);\n\n if (stops.length === 0) return 'transparent';\n\n // Calculate radial gradient parameters\n const { size, position } = this.calculateRadialGradientParams(handles);\n\n // Convert stops\n const stopsStr = stops\n .map(stop => {\n const color = this.rgbaToString(stop.color, fillOpacity);\n const pos = Math.round(stop.position * 100);\n return `${color} ${pos}%`;\n })\n .join(', ');\n\n return `radial-gradient(${size} at ${position}, ${stopsStr})`;\n }\n\n private static getOpacity(opacity?: number): number {\n return opacity !== undefined ? opacity : 1;\n }\n\n // Helper: Convert Figma color to CSS rgba/rgb/hex string\n static rgbaToString(color: FigmaColor, opacity: number = 1): string {\n if (!color) return 'transparent';\n\n const r = Math.round((color.r || 0) * 255);\n const g = Math.round((color.g || 0) * 255);\n const b = Math.round((color.b || 0) * 255);\n const a = (color.a !== undefined ? color.a : 1) * (opacity !== undefined ? opacity : 1);\n\n // Use hex format when fully opaque, rgba when transparent\n if (Math.abs(a - 1) < 0.001) {\n // Fully opaque - use hex format\n if (r === 255 && g === 255 && b === 255) return '#FFF';\n if (r === 0 && g === 0 && b === 0) return '#000';\n // Convert to hex\n const toHex = (n: number) => n.toString(16).toUpperCase().padStart(2, '0');\n return `#${toHex(r)}${toHex(g)}${toHex(b)}`;\n }\n\n // Transparent - use rgba with proper formatting\n const alphaStr = a !== undefined ? a.toFixed(2) : '1';\n return `rgba(${r}, ${g}, ${b}, ${alphaStr})`;\n }\n\n /**\n * Calculate CSS gradient angle from Figma gradient handle positions\n * Figma uses a transform matrix system with 3 points:\n * - p0: gradient origin\n * - p1: gradient direction endpoint (color changes from p0 to p1)\n * - p2: perpendicular direction endpoint\n *\n * Formula: CSS angle = atan2(v1) + angleBetween(v1, v2)\n * where v1 = p1-p0, v2 = p2-p0\n */\n private static calculateLinearGradientAngle(positions: { x: number; y: number }[]): number {\n if (positions.length < 2) return 180;\n\n const [p0, p1, p2] = positions;\n\n if (!p0 || !p1) return 180;\n\n // Vector v1: gradient direction (p0 → p1)\n const v1x = p1.x - p0.x;\n const v1y = p1.y - p0.y;\n const len1 = Math.sqrt(v1x * v1x + v1y * v1y);\n\n // Calculate angle of v1\n const angle1Rad = Math.atan2(v1y, v1x);\n const angle1Deg = angle1Rad * (180 / Math.PI);\n\n // If we don't have p2, use simple formula\n if (!p2 || positions.length < 3) {\n let cssAngle = angle1Deg + 90;\n while (cssAngle < 0) cssAngle += 360;\n while (cssAngle >= 360) cssAngle -= 360;\n return Math.round(cssAngle);\n }\n\n // Vector v2: perpendicular reference (p0 → p2)\n const v2x = p2.x - p0.x;\n const v2y = p2.y - p0.y;\n const len2 = Math.sqrt(v2x * v2x + v2y * v2y);\n\n // Calculate angle between v1 and v2\n const dot = v1x * v2x + v1y * v2y;\n const cosAngle = Math.max(-1, Math.min(1, dot / (len1 * len2)));\n const angleBetweenRad = Math.acos(cosAngle);\n const angleBetweenDeg = angleBetweenRad * (180 / Math.PI);\n\n // CSS angle = angle1 + angleBetween\n let cssAngle = angle1Deg + angleBetweenDeg;\n\n // Normalize to 0-360 range\n while (cssAngle < 0) {\n cssAngle += 360;\n }\n while (cssAngle >= 360) {\n cssAngle -= 360;\n }\n\n return Math.round(cssAngle);\n }\n\n /**\n * Calculate gradient stops with correct positions\n * Based on Figma's gradient handle positions and transform matrix\n */\n private static calculateLinearGradientStops(\n stops: FigmaGradientStop[],\n handles: { x: number; y: number }[],\n fillOpacity: number\n ): string {\n if (handles.length < 2) {\n // Fallback: simple position mapping\n return stops\n .map(stop => {\n const color = this.rgbaToString(stop.color, fillOpacity);\n const position = Math.round(stop.position * 100);\n // Format: remove .00 for whole numbers\n const posStr = position === 0 ? '0%' : `${position}%`;\n return `${color} ${posStr}`;\n })\n .join(', ');\n }\n\n const [p0, p1] = handles;\n\n if (!p0 || !p1) {\n return stops\n .map(stop => {\n const color = this.rgbaToString(stop.color, fillOpacity);\n const position = Math.round(stop.position * 100);\n const posStr = position === 0 ? '0%' : `${position}%`;\n return `${color} ${posStr}`;\n })\n .join(', ');\n }\n\n // Transform matrix vectors\n const m1x = p1.x - p0.x;\n const m1y = p1.y - p0.y;\n\n // Gradient length\n const gradientLength = Math.sqrt(m1x * m1x + m1y * m1y);\n\n if (gradientLength === 0) {\n return stops\n .map(stop => {\n const color = this.rgbaToString(stop.color, fillOpacity);\n const position = Math.round(stop.position * 100);\n const posStr = position === 0 ? '0%' : `${position}%`;\n return `${color} ${posStr}`;\n })\n .join(', ');\n }\n\n // Get CSS angle\n const cssAngle = this.calculateLinearGradientAngle(handles);\n const cssAngleRad = (cssAngle * Math.PI) / 180;\n\n // CSS gradient direction vector\n const gradDirX = Math.sin(cssAngleRad);\n const gradDirY = -Math.cos(cssAngleRad);\n\n // Project box corners onto gradient direction\n const corners = [\n { x: 0, y: 0 },\n { x: 1, y: 0 },\n { x: 0, y: 1 },\n { x: 1, y: 1 },\n ];\n\n const projections = corners.map(c => c.x * gradDirX + c.y * gradDirY);\n const minProj = Math.min(...projections);\n const maxProj = Math.max(...projections);\n const projRange = maxProj - minProj;\n\n // Calculate stop positions\n return stops\n .map(stop => {\n const color = this.rgbaToString(stop.color, fillOpacity);\n\n // Point on gradient line at this stop\n const pointX = p0.x + stop.position * m1x;\n const pointY = p0.y + stop.position * m1y;\n\n // Project onto CSS gradient direction\n const projection = pointX * gradDirX + pointY * gradDirY;\n\n // Convert to percentage\n let cssPosition = ((projection - minProj) / projRange) * 100;\n\n // Round to 2 decimal places then format\n cssPosition = cssPosition !== undefined ? Math.round(cssPosition * 100) / 100 : 0;\n\n // Format position string\n let posStr: string;\n if (cssPosition === 0) {\n posStr = '0%';\n } else if (Number.isInteger(cssPosition)) {\n posStr = `${cssPosition}%`;\n } else {\n posStr = `${cssPosition.toFixed(2)}%`;\n }\n\n return `${color} ${posStr}`;\n })\n .join(', ');\n }\n\n // Calculate radial gradient parameters from handle positions\n private static calculateRadialGradientParams(handles: { x: number; y: number }[]): {\n size: string;\n position: string;\n } {\n if (handles.length < 2) {\n return { size: 'circle', position: '50% 50%' };\n }\n\n const [center, edge, perpendicular] = handles;\n\n if (!center || !edge || !perpendicular) {\n return { size: 'circle', position: '50% 50%' };\n }\n\n // Calculate radius as distance from center to edge\n const dx = edge.x - center.x;\n const dy = edge.y - center.y;\n const radiusX = Math.sqrt(dx * dx + dy * dy);\n\n // Calculate perpendicular radius if third handle exists\n let radiusY = radiusX;\n if (perpendicular) {\n const pdx = perpendicular.x - center.x;\n const pdy = perpendicular.y - center.y;\n radiusY = Math.sqrt(pdx * pdx + pdy * pdy);\n }\n\n // Convert center position to percentage\n const centerX = center.x !== undefined ? (center.x * 100).toFixed(2) : '0';\n const centerY = center.y !== undefined ? (center.y * 100).toFixed(2) : '0';\n\n // Calculate size\n const sizeX = radiusX !== undefined ? (radiusX * 100).toFixed(2) : '0';\n const sizeY = radiusY !== undefined ? (radiusY * 100).toFixed(2) : '0';\n\n return {\n size: `${sizeY}% ${sizeX}%`,\n position: `${centerX}% ${centerY}%`,\n };\n }\n\n // Convert SOLID fill to linear-gradient format (for layering multiple fills)\n static solidToGradient(fill: FigmaColorObject): string {\n const color = this.convertSolid(fill);\n return `linear-gradient(0deg, ${color} 0%, ${color} 100%)`;\n }\n}\n","import { CSSStyles, FigmaColorObject, FigmaFrameInfo } from '../../types/figma-types';\nimport { ColorConverter } from './color';\n\n// Convert border radius\nexport const convertBorderRadius = (node: FigmaFrameInfo, inlineStyles: CSSStyles): void => {\n if (node.cornerRadius !== undefined) {\n inlineStyles.borderRadius = `${node.cornerRadius}px`;\n }\n\n // Individual corner radius\n if (node.rectangleCornerRadii) {\n const [tl, tr, br, bl] = node.rectangleCornerRadii;\n inlineStyles.borderRadius = `${tl}px ${tr}px ${br}px ${bl}px`;\n }\n};\n\n// Convert effects (shadow, filter,backdrop-filter)\nexport const convertEffects = (node: FigmaFrameInfo, inlineStyles: CSSStyles): void => {\n const effects = node.effects;\n\n if (!effects || effects.length === 0) return;\n\n const shadows: string[] = [];\n const filters: string[] = [];\n const backdropFilters: string[] = [];\n\n for (const effect of effects) {\n if (effect.visible === false) continue;\n\n if (effect.type === 'DROP_SHADOW') {\n const x = effect.offset?.x || 0;\n const y = effect.offset?.y || 0;\n const blur = effect.radius || 0;\n const spread = effect.spread || 0;\n // Use ColorConverter for shadow color\n const color = effect.color ? ColorConverter.convert({ type: 'SOLID', color: effect.color }) : 'rgba(0, 0, 0, 0.25)';\n\n shadows.push(`${x.toFixed(0)}px ${y.toFixed(0)}px ${(blur / 2).toFixed(0)}px ${spread.toFixed(0)}px ${color}`);\n } else if (effect.type === 'INNER_SHADOW') {\n const x = effect.offset?.x || 0;\n const y = effect.offset?.y || 0;\n const blur = effect.radius || 0;\n const spread = effect.spread || 0;\n const color = effect.color ? ColorConverter.convert({ type: 'SOLID', color: effect.color }) : 'rgba(0, 0, 0, 0.25)';\n\n shadows.push(`inset ${x.toFixed(0)}px ${y.toFixed(0)}px ${(blur / 2).toFixed(0)}px ${spread.toFixed(0)}px ${color}`);\n } else if (effect.type === 'LAYER_BLUR') {\n const blur = effect.radius || 0;\n filters.push(`blur(${(blur / 2).toFixed(0)}px)`);\n } else if (effect.type === 'BACKGROUND_BLUR') {\n const blur = effect.radius || 0;\n backdropFilters.push(`blur(${(blur / 2).toFixed(0)}px)`);\n }\n }\n\n if (shadows.length > 0) {\n inlineStyles.boxShadow = shadows.join(', ');\n }\n\n if (filters.length > 0) {\n inlineStyles.filter = filters.join(' ');\n }\n\n if (backdropFilters.length > 0) {\n inlineStyles.backdropFilter = backdropFilters.join(', ');\n }\n};\n\n// Convert fills to background\n// Handles multiple fills and creates layered backgrounds\nexport const convertFills = (node: FigmaFrameInfo, inlineStyles: CSSStyles): void => {\n const fills = node.fills || node.background;\n\n if (!fills || fills.length === 0) return;\n\n // Filter visible fills\n const visibleFills = fills.filter((fill: FigmaColorObject) => fill.visible !== false);\n if (visibleFills.length === 0) return;\n\n // Convert all fills to CSS\n // For multiple fills, convert SOLID to gradient format for proper layering\n const backgrounds: string[] = visibleFills.map((fill: FigmaColorObject) => {\n if (fill.type === 'SOLID' && visibleFills.length > 1) {\n return ColorConverter.solidToGradient(fill);\n }\n return ColorConverter.convert(fill);\n });\n\n // IMPORTANT: Reverse the array!\n // Figma fills: index 0 = top layer\n // CSS background: first declared = top layer\n // But Figma's rendering order is bottom-to-top in the fills array\n // So we need to reverse to match CSS rendering order\n backgrounds.reverse();\n\n // Set background with all layers\n inlineStyles.background = backgrounds.join(', ');\n};\n\n// Convert strokes to border\nexport const convertStrokes = (node: FigmaFrameInfo, inlineStyles: CSSStyles): void => {\n const strokes = node.strokes;\n\n if (!strokes || strokes.length === 0 || !node.strokeWeight) return;\n\n const visibleStrokes = strokes.filter((s: FigmaColorObject) => s.visible !== false);\n if (visibleStrokes.length === 0) return;\n\n const width = node.strokeWeight || 1;\n let strokeColor = '';\n const isGradientStroke = visibleStrokes.some((s: FigmaColorObject) => s.type.includes('GRADIENT'));\n if (isGradientStroke) {\n const gradient = visibleStrokes.find((s: FigmaColorObject) => s.type.includes('GRADIENT'));\n if (gradient) {\n strokeColor = ColorConverter.convert(gradient);\n }\n inlineStyles.strokeColor = strokeColor;\n inlineStyles.borderRadius = `${node.cornerRadius !== undefined ? node.cornerRadius.toFixed(0) : '0'}px`;\n inlineStyles.strokeWidth = `${width}px`;\n } else {\n const solid = visibleStrokes.find((s: FigmaColorObject) => s.type === 'SOLID');\n if (solid) {\n strokeColor = ColorConverter.convert(solid);\n }\n inlineStyles.border = `${width}px solid ${strokeColor}`;\n }\n};\n\n// Convert clip content\nexport const convertClipContent = (node: FigmaFrameInfo, inlineStyles: CSSStyles): void => {\n if (node.clipsContent) {\n inlineStyles.overflow = 'hidden';\n }\n};\n","import { GraphState } from '../../state';\nimport { figmaTool } from '../../tools/figma-tool';\nimport { FigmaFrameInfo, FigmaUrlInfo } from '../../types/figma-types';\nimport { getFigmaConfig } from '../../utils/config';\nimport { writeFile } from '../../utils/file';\nimport { logger } from '../../utils/logger';\nimport { generateStructure } from './structure';\nimport { ImageNode } from '../../tools/figma-tool/types';\nimport { workspaceManager } from '../../utils/workspace';\n\n/**\n * 'process' node, responsible for generating the protocol for frontend code generation.\n *\n * This function serves as a unified workflow that can be consumed by:\n * 1. LangGraph Node: As part of the design2code graph workflow\n * 2. CLI Command: `f2p` (figma2protocol) - full protocol generation\n * 3. CLI Command: `images` (get-images) - partial workflow (fetch + download only)\n * 4. Script Execution: Direct execution via tsx/node\n *\n * Workflow Steps:\n * - Step 1: Fetch and clean Figma document from API\n * - Step 2: Detect and download images from Figma document\n * - Step 3: Simplify image nodes by replacing properties with URLs\n * - Step 4: Process styles (convert Figma styles to CSS)\n * - Step 5: Write protocol.json and images.json to workspace\n * @param state - The state of the graph.\n * @returns The state of the graph.\n */\nexport const generateProtocol = async (state: GraphState) => {\n const assetsDir = workspaceManager.resolveAppSrc(state.workspace, 'assets');\n const processDir = state.workspace.process;\n const { document, imageNodesMap } = await executeFigmaAndImagesActions(state.urlInfo, assetsDir, processDir);\n\n /* Simplify image nodes in Figma document by replacing redundant properties with url */\n const simplifiedDocument = figmaTool.simplifyImageNodes(document, imageNodesMap);\n /* Process styles (convert Figma styles to CSS) */\n const processedStyleDocument = figmaTool.processedStyle(simplifiedDocument);\n /* Generate structure */\n const protocol = await generateStructure(processedStyleDocument);\n\n // Write protocol.json (contains all Figma data in data.elements)\n writeFile(state.workspace.process, 'protocol.json', JSON.stringify(protocol, null, 2));\n logger.printInfoLog(`Please check the output in the workspace: ${state.workspace.process}`);\n\n return {\n protocol,\n figmaInfo: {\n thumbnail: processedStyleDocument?.thumbnailUrl || document?.thumbnailUrl || '',\n },\n };\n};\n\n/**\n * Executes the Figma and images actions.\n * @param state - The state of the graph.\n * @returns The state of the graph with imageNodesMap as Map<string, ImageNode>.\n */\nexport const executeFigmaAndImagesActions = async (\n urlInfo: FigmaUrlInfo,\n assetsDir: string,\n processDir: string\n): Promise<{ document: FigmaFrameInfo; imageNodesMap: Map<string, ImageNode> }> => {\n const { fileId, nodeId } = urlInfo;\n if (!fileId || !nodeId) {\n throw new Error('Invalid Figma URL');\n }\n\n const token = getFigmaConfig().token;\n if (!token) {\n throw new Error('Figma API token is required');\n }\n\n /* Fetch and clean Figma document */\n const document = await figmaTool.fetchAndClean(fileId, nodeId, token);\n if (!document) {\n throw new Error('Failed to fetch and clean Figma document');\n }\n writeFile(processDir, 'figma.json', JSON.stringify(document, null, 2));\n logger.printSuccessLog(`Figma document fetched and cleaned successfully`);\n\n /* Detect and download images from Figma document */\n const downloadResult: { successCount: number; failCount: number; imageNodesMap: Map<string, ImageNode> } =\n await figmaTool.downloadImages(fileId, token, assetsDir, document);\n const { successCount, failCount, imageNodesMap } = downloadResult;\n\n if (successCount) {\n logger.printSuccessLog(`Downloaded ${successCount} images`);\n }\n if (failCount) {\n logger.printWarnLog(`Failed to download ${failCount} images`);\n }\n\n /* Write images.json with array format for JSON compatibility */\n const resultsArray = Array.from(imageNodesMap.values());\n writeFile(processDir, 'images.json', JSON.stringify(resultsArray, null, 2));\n\n return {\n document,\n imageNodesMap,\n };\n};\n","import { HumanMessage } from '@langchain/core/messages';\nimport { ChatOpenAI } from '@langchain/openai';\nimport { logger } from './logger';\nimport { getDebugConfig, getModelConfig, type ModelConfig } from './config';\nimport { writeFile } from './file';\nimport { workspaceManager } from './workspace';\n\n/**\n * Content part types for multimodal messages\n */\ntype ContentPart = { type: 'text'; text: string } | { type: 'image_url'; image_url: { url: string } };\n\n/**\n * Options for calling the model\n */\nexport interface CallModelOptions {\n question: string;\n imageUrls?: string | string[];\n streaming?: boolean;\n responseFormat?: { type: 'json_object' | 'text' };\n maxTokens?: number;\n}\n\n/**\n * Validate model configuration\n * @param config - Model configuration to validate\n * @throws Error if required fields are missing\n */\nfunction validateModelConfig(config: ModelConfig | null | undefined): asserts config is ModelConfig {\n if (!config || !config.provider || !config.model || !config.baseUrl || !config.apiKey) {\n throw new Error(\n `Invalid model configuration. Required fields: provider, model, baseUrl, apiKey. Please check your config.yaml file.`\n );\n }\n}\n\n/**\n * Call an LLM model with the given options\n * @param options - Configuration options for the model call\n * @returns The model's text response\n */\nexport async function callModel(options: CallModelOptions): Promise<string> {\n const { question, imageUrls, streaming = false, responseFormat, maxTokens } = options;\n\n // Validate input\n if (!question || !question.trim()) {\n throw new Error('Question must be a non-empty string');\n }\n\n // Get and validate config separately\n let config: ModelConfig;\n try {\n config = getModelConfig();\n validateModelConfig(config);\n } catch (error) {\n if (error instanceof Error) {\n logger.printErrorLog(`Configuration error: ${error.message}`);\n }\n throw error;\n }\n\n try {\n const requestConfig = {\n modelName: config.model,\n apiKey: config.apiKey,\n configuration: {\n baseURL: config.baseUrl,\n },\n ...(maxTokens && { maxTokens }),\n temperature: 0.1,\n streaming,\n ...(streaming && {\n streamingOptions: {\n includeUsage: true,\n },\n }),\n ...(!streaming && { streamUsage: true }),\n ...(responseFormat && { modelKwargs: { response_format: responseFormat } }),\n };\n const agentModel = new ChatOpenAI(requestConfig);\n\n // Build multimodal content parts: text + image_url\n const contentParts: ContentPart[] = [];\n contentParts.push({ type: 'text', text: question });\n\n // Add images if provided\n if (imageUrls) {\n const urls = Array.isArray(imageUrls) ? imageUrls : [imageUrls];\n for (const url of urls) {\n if (url && typeof url === 'string' && url.trim()) {\n contentParts.push({ type: 'image_url', image_url: { url: url.trim() } });\n }\n }\n }\n\n // Create user message - use array if multimodal, string if text-only\n const userMessage = new HumanMessage({\n content: contentParts.length > 1 ? contentParts : question,\n });\n\n const message = await agentModel.invoke([userMessage]);\n\n if (!message.text) {\n throw new Error('Model returned empty response');\n }\n\n const debugConfig = getDebugConfig();\n const isDebugEnabled = debugConfig.enabled;\n if (isDebugEnabled) {\n const debugContent = [\n '------------config------------',\n JSON.stringify(requestConfig, null, 2),\n '------------request------------',\n JSON.stringify(contentParts, null, 2),\n '------------response------------',\n JSON.stringify(message.text, null, 2),\n ].join('\\n');\n writeFile(workspaceManager.path?.debug ?? '', `model_${new Date().toISOString().replace(/:/g, '-')}.md`, debugContent);\n }\n\n return message.text;\n } catch (error) {\n if (error instanceof Error) {\n logger.printErrorLog(`[${config.model}] Error details: ${error.message}`);\n if (error.stack) {\n logger.printTestLog(`[${config.model}] Stack trace: ${error.stack}`);\n }\n }\n throw new Error(`${config.model} model request failed: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n}\n","import type { FigmaFrameInfo } from '../../../types/figma-types';\nimport type { Protocol } from '../../../types';\nimport { callModel } from '../../../utils/call-model';\nimport { logger } from '../../../utils/logger';\nimport { generateStructurePrompt } from './prompt';\nimport { extractNodePositionsHierarchical, postProcessStructure, populateComponentProps } from './utils';\nimport { extractJSON } from '../../../utils/parser';\n\n/**\n * Structure node - generates component hierarchy from Figma design\n *\n * Responsibilities:\n * 1. Analyzes Figma frame structure using AI model\n * 2. Extracts component relationships and data\n * 3. Generates file paths and naming conventions\n * 4. Populates component props and states for code generation\n *\n * @param state - Current graph state\n * @returns Updated state with protocol\n */\nexport const generateStructure = async (figma: FigmaFrameInfo) => {\n const frames = figma.frames || figma.children;\n const imageWidth = figma.absoluteBoundingBox?.width;\n const thumbnailUrl = figma.thumbnailUrl;\n\n if (!frames || frames.length === 0) {\n logger.printErrorLog('No processed frames found in state');\n throw new Error('No processed frames found');\n }\n\n logger.printInfoLog('Starting structure analysis...');\n\n try {\n // Extract hierarchical position data from Figma frames\n const positions = extractNodePositionsHierarchical(frames);\n const positionsJson = JSON.stringify(positions);\n\n // Generate structure using AI\n const prompt = generateStructurePrompt({\n positions: positionsJson,\n width: imageWidth ? String(imageWidth) : '1440',\n });\n\n logger.printInfoLog('Calling AI model to generate component structure...');\n\n const structureResult = await callModel({\n question: prompt,\n imageUrls: thumbnailUrl,\n responseFormat: { type: 'json_object' },\n maxTokens: 20240,\n });\n\n // Parse AI response\n const jsonContent = extractJSON(structureResult);\n const parsedStructure = JSON.parse(jsonContent) as Protocol | Protocol[];\n\n // Post-process structure: normalize names, populate elements, annotate paths\n logger.printInfoLog('Processing structure tree...');\n postProcessStructure(parsedStructure, frames);\n\n const protocol = (Array.isArray(parsedStructure) ? parsedStructure[0] : parsedStructure) as Protocol;\n\n // Extract component props and states for reusable components\n if (frames && protocol) {\n logger.printInfoLog('Extracting component properties and states...');\n await populateComponentProps(protocol, frames, thumbnailUrl);\n }\n\n logger.printSuccessLog('Component structure generated successfully');\n\n return protocol;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.printErrorLog(`Error generating component structure: ${errorMessage}`);\n throw new Error(`Failed to parse component structure: ${errorMessage}`);\n }\n};\n","import type { FigmaFrameInfo, Protocol, FrameData } from '../../../types';\nimport type { SimplifiedFigmaNode, ExtendedFrameStructNode, ParsedDataListResponse } from './types';\nimport path from 'node:path';\nimport { toKebabCase } from '../../../utils/naming';\nimport { extractJSON } from '../../../utils/parser';\nimport { callModel } from '../../../utils/call-model';\nimport { logger } from '../../../utils/logger';\n\n// ============= Figma Node Utilities =============\n/**\n * Simplifies Figma nodes for content extraction, retaining essential fields for AI processing\n * Removes heavy vector data while keeping text content, images, and layout information\n *\n * @param node - The Figma frame node to simplify\n * @returns Simplified node with only essential fields\n */\nexport function simplifyFigmaNodeForContent(node: FigmaFrameInfo): SimplifiedFigmaNode {\n const simple: SimplifiedFigmaNode = {\n id: node.id,\n name: node.name,\n type: node.type,\n };\n\n // Check both url (set by Asset node) and thumbnailUrl (original Figma field)\n const imageUrl = (node as FigmaFrameInfo & { url?: string }).url || node.thumbnailUrl;\n if (imageUrl) {\n simple.url = imageUrl;\n }\n\n if (node.cornerRadius !== undefined) {\n simple.cornerRadius = node.cornerRadius;\n }\n\n if (node.characters !== undefined && node.characters !== null) {\n simple.characters = node.characters;\n }\n\n if (node.visible !== undefined) simple.visible = node.visible;\n\n if (node.absoluteBoundingBox) simple.absoluteBoundingBox = node.absoluteBoundingBox;\n\n if (node.children && Array.isArray(node.children)) {\n simple.children = node.children.map(simplifyFigmaNodeForContent);\n }\n\n if (node.inlineStyles) {\n simple.inlineStyles = node.inlineStyles as Record<string, unknown>;\n }\n\n if (node.style) {\n simple.style = node.style as unknown as Record<string, unknown>;\n }\n\n if (node.strokes && Array.isArray(node.strokes) && node.strokes.length > 0) {\n simple.hasStrokes = true;\n }\n\n return simple;\n}\n\n/**\n * Extract node positions with hierarchical structure preserved\n * Returns nested position data maintaining parent-child relationships\n *\n * @param data - Figma frame data (single frame or array of frames)\n * @returns Hierarchical position data with node information\n */\nexport function extractNodePositionsHierarchical(data: FigmaFrameInfo[] | FigmaFrameInfo | undefined): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n if (!data) {\n return result;\n }\n\n const list = Array.isArray(data) ? data : [data];\n\n for (const item of list) {\n if (item && typeof item === 'object' && item.id) {\n const nodeData: Record<string, unknown> = {};\n\n // Extract position information\n const bounds = item.absoluteBoundingBox || item.absoluteRenderBounds;\n if (bounds) {\n nodeData.x = bounds.x;\n nodeData.y = bounds.y;\n nodeData.w = bounds.width;\n nodeData.h = bounds.height;\n }\n\n // Recursively process children\n if (item.children && Array.isArray(item.children) && item.children.length > 0) {\n nodeData.children = extractNodePositionsHierarchical(item.children);\n }\n\n result[item.id] = nodeData;\n }\n }\n\n return result;\n}\n\n/**\n * Extract nodes by IDs, including their full subtrees (all children)\n * This allows inspecting the full content of specific component instances\n */\nfunction extractNodesWithSubtreeByIds(tree: FigmaFrameInfo | FigmaFrameInfo[], idList: string[]): FigmaFrameInfo[] {\n const idSet = new Set(idList);\n const result: FigmaFrameInfo[] = [];\n\n const findNodes = (nodes: FigmaFrameInfo[]) => {\n for (const node of nodes) {\n if (idSet.has(node.id)) {\n // Deep clone the node to ensure all fields (including url) are preserved\n const clonedNode = JSON.parse(JSON.stringify(node)) as FigmaFrameInfo;\n result.push(clonedNode);\n // Do not recurse into children of a match, because the match already contains them.\n } else if (node.children && Array.isArray(node.children)) {\n findNodes(node.children);\n }\n }\n };\n\n const nodeArray = Array.isArray(tree) ? tree : [tree];\n findNodes(nodeArray);\n return result;\n}\n\n/**\n * Extract nodes by IDs while preserving hierarchical structure\n * Nodes in idList are kept; if a deep child is in idList but parent isn't, the child is still extracted\n *\n * @param tree - The Figma frame tree to search\n * @param idList - Array of node IDs to extract\n * @param options - Optional settings\n * @param options.includeSubtree - If true, includes all descendants of matched nodes\n * @returns Array of extracted nodes with hierarchy preserved\n */\nexport function extractHierarchicalNodesByIds(\n tree: FigmaFrameInfo | FigmaFrameInfo[],\n idList: string[],\n options?: { includeSubtree?: boolean }\n): FigmaFrameInfo[] {\n if (options?.includeSubtree) {\n return extractNodesWithSubtreeByIds(tree, idList);\n }\n\n const idSet = new Set(idList);\n const result: FigmaFrameInfo[] = [];\n\n // Helper function to check if a node or any of its descendants are in idList\n const hasDescendantInList = (node: FigmaFrameInfo): boolean => {\n if (idSet.has(node.id)) return true;\n\n if (node.children && Array.isArray(node.children)) {\n for (const child of node.children) {\n if (typeof child === 'object' && child !== null && 'id' in child) {\n if (hasDescendantInList(child)) {\n return true;\n }\n }\n }\n }\n\n return false;\n };\n\n // Helper function to recursively process a single node\n const processNode = (node: FigmaFrameInfo): FigmaFrameInfo[] => {\n // First check if this node or any descendant is in the list\n if (!hasDescendantInList(node)) {\n return [];\n }\n\n // If current node is in the list, keep it with filtered children\n if (idSet.has(node.id)) {\n const clonedNode: FigmaFrameInfo = { ...node };\n\n // Process children if they exist\n if (node.children && Array.isArray(node.children)) {\n const filteredChildren: FigmaFrameInfo[] = [];\n\n for (const child of node.children) {\n if (typeof child === 'object' && child !== null && 'id' in child) {\n const processedChildren = processNode(child);\n filteredChildren.push(...processedChildren);\n }\n }\n\n clonedNode.children = filteredChildren.length > 0 ? filteredChildren : [];\n } else {\n clonedNode.children = [];\n }\n\n return [clonedNode];\n } else {\n // Current node is not in the list, but some descendants are\n // Collect all matching descendants and return them (flattened)\n const matchingDescendants: FigmaFrameInfo[] = [];\n\n if (node.children && Array.isArray(node.children)) {\n for (const child of node.children) {\n if (typeof child === 'object' && child !== null && 'id' in child) {\n const processedChildren = processNode(child);\n matchingDescendants.push(...processedChildren);\n }\n }\n }\n\n return matchingDescendants;\n }\n };\n\n // Process tree (handle both single node and array)\n const nodeArray = Array.isArray(tree) ? tree : [tree];\n\n for (const node of nodeArray) {\n const processedNodes = processNode(node);\n result.push(...processedNodes);\n }\n\n return result;\n}\n\n// ============= Structure Processing Utilities =============\n\n/**\n * Post-processes the structure tree in a single traversal\n * Performs three operations simultaneously:\n * 1. Normalizes componentName (moves from top-level to data field)\n * 2. Populates elements data from elementIds\n * 3. Annotates with file system paths (path, componentPath, kebabName)\n *\n * @param structure - The parsed structure from AI model\n * @param frames - The Figma frames tree for element extraction\n */\nexport function postProcessStructure(structure?: Protocol | Protocol[] | null, frames?: FigmaFrameInfo[]): void {\n if (!structure) {\n return;\n }\n\n // Utility to join alias path segments (always POSIX '/')\n const joinSegments = (...segments: (string | undefined)[]): string =>\n path.posix.join(...segments.filter((segment): segment is string => Boolean(segment && segment.length)));\n\n const nodes = Array.isArray(structure) ? structure : [structure];\n let rootPath = '@/components';\n\n // Convert component name to kebab-case for file naming\n const toKebabName = (node: Protocol): string => {\n const source = node.data.kebabName || node.data.name || node.id || 'component';\n const kebabName = toKebabCase(source);\n if (!node.data.kebabName) {\n node.data.kebabName = kebabName;\n }\n return kebabName;\n };\n\n const traverse = (node?: Protocol | null, parentPath?: string, level = 0): void => {\n if (!node || !node.data) {\n return;\n }\n\n // 1. Normalize componentName (from top-level to data field)\n const extendedNode = node as ExtendedFrameStructNode;\n const topLevelComponentName = extendedNode.componentName;\n if (topLevelComponentName && !node.data.componentName) {\n node.data.componentName = topLevelComponentName;\n delete extendedNode.componentName;\n }\n\n // 2. Populate elements data from elementIds\n if (frames) {\n const nodeData = node.data as FrameData & { elementIds?: string[] };\n const elementIds = nodeData.elementIds;\n if (elementIds && Array.isArray(elementIds)) {\n if (elementIds.length > 0) {\n node.data.elements = extractHierarchicalNodesByIds(frames, elementIds, { includeSubtree: true });\n } else {\n node.data.elements = [];\n }\n delete nodeData.elementIds;\n } else {\n node.data.elements = node.data.elements || [];\n }\n }\n\n // 3. Annotate with file system paths\n const segment = toKebabName(node);\n let currentPath: string;\n\n if (level === 0) {\n // Root node always uses base path\n currentPath = rootPath;\n rootPath = currentPath;\n } else {\n const ancestorPath = parentPath || rootPath;\n currentPath = joinSegments(ancestorPath, segment);\n }\n\n // For reusable components, generate flat componentPath (non-hierarchical)\n if (node.data.componentName) {\n const componentKebabName = toKebabCase(node.data.componentName);\n node.data.componentPath = joinSegments(rootPath, componentKebabName);\n node.data.path = node.data.componentPath;\n }\n\n node.data.path = currentPath;\n\n // Recursively process children\n if (Array.isArray(node.children) && node.children.length > 0) {\n node.children.forEach(child => traverse(child, node.data.path, level + 1));\n }\n };\n\n nodes.forEach(node => {\n if (!node || !node.data) {\n return;\n }\n traverse(node, undefined, 0);\n });\n}\n\n/**\n * Extract component groups from protocol children\n * Groups components by their componentName for batch processing\n *\n * @param protocol - The protocol node to analyze\n * @returns Map of componentName to array of instances\n */\nexport function extractComponentGroups(node: Protocol): Map<string, Protocol[]> {\n if (!node || !node.children || node.children.length === 0) return new Map();\n const componentGroups = new Map<string, Protocol[]>();\n const validChildren = node.children.filter(c => c && c.data);\n\n validChildren.forEach(child => {\n const name = child.data.componentName;\n if (name) {\n if (!componentGroups.has(name)) {\n componentGroups.set(name, []);\n }\n componentGroups.get(name)!.push(child);\n }\n });\n\n return componentGroups;\n}\n\n/**\n * Applies props and state to the protocol node\n * @param parsed - The parsed data list response\n * @param node - The protocol node to apply the props and state to\n * @param compName - The name of the component\n * @param group - The group of components\n * @param isList - Whether the component is a list\n */\nexport function applyPropsAndStateToProtocol(\n parsed: ParsedDataListResponse,\n node: Protocol,\n compName: string,\n group: Protocol[],\n isList: boolean\n): void {\n if (parsed && parsed.state && Array.isArray(parsed.state)) {\n if (isList) {\n if (!node.data.states) {\n node.data.states = [];\n }\n\n node.data.states.push({\n state: parsed.state,\n componentName: compName,\n componentPath: group[0]?.data.componentPath || '',\n });\n\n const originalChildren: Protocol[] = node.children || [];\n const newChildren: Protocol[] = [];\n const processedComponentNames = new Set<string>();\n\n for (const child of originalChildren) {\n const childName = child.data.componentName;\n if (childName === compName) {\n if (!processedComponentNames.has(childName)) {\n child.data.name = childName;\n child.id = childName;\n const cleanKebabName = toKebabCase(childName);\n child.data.kebabName = cleanKebabName;\n delete child.data.path;\n\n if (parsed.props && Array.isArray(parsed.props)) {\n child.data.props = parsed.props;\n }\n\n newChildren.push(child);\n processedComponentNames.add(childName);\n }\n } else {\n newChildren.push(child);\n }\n }\n\n node.children = newChildren;\n }\n }\n}\n\n/**\n * Extracts component properties and states from repeated component instances\n * For components that appear multiple times (e.g., cards in a grid), this function:\n * 1. Groups instances by componentName\n * 2. Uses AI to extract data variations (text, images, etc.)\n * 3. Generates props schema for the component\n * 4. Collapses duplicate instances into a single template + state array\n *\n * @param node - Current structure node to process\n * @param frames - Figma frames for reference\n * @param thumbnailUrl - Design thumbnail URL for AI visual context\n */\nexport async function populateComponentProps(node: Protocol, frames: FigmaFrameInfo[], thumbnailUrl?: string): Promise<void> {\n if (!node || !node.children || node.children.length === 0) return;\n\n const componentGroups = extractComponentGroups(node);\n\n // Process each component group to extract props and data\n for (const [compName, group] of componentGroups) {\n if (group.length === 0) continue;\n\n const isList = group.length > 1;\n const allElements = group.flatMap(g => g.data.elements || []);\n const simplifiedNodes = allElements\n .filter((n): n is FigmaFrameInfo => typeof n === 'object' && n !== null)\n .map(n => simplifyFigmaNodeForContent(n));\n const figmaDataJson = JSON.stringify(simplifiedNodes);\n const containerName = node.data.name || 'Container';\n\n try {\n const { extractDataListPrompt } = await import('./prompt');\n const prompt = extractDataListPrompt({\n containerName,\n childComponentName: compName,\n figmaData: figmaDataJson,\n });\n\n const result = await callModel({\n question: prompt,\n imageUrls: thumbnailUrl,\n responseFormat: { type: 'json_object' },\n });\n\n const json = extractJSON(result);\n const parsed = JSON.parse(json) as ParsedDataListResponse;\n applyPropsAndStateToProtocol(parsed, node, compName, group, isList);\n } catch (e) {\n logger.printErrorLog(\n `Failed to extract data list for ${compName} in ${containerName}: ${e instanceof Error ? e.message : String(e)}`\n );\n }\n }\n\n // Recursively process children\n for (const child of node.children) {\n await populateComponentProps(child, frames, thumbnailUrl);\n }\n}\n","/**\n * Standard naming utilities for the project.\n * Ensures consistency between kebab-case file paths and PascalCase component names.\n */\n\n/**\n * Converts a string to PascalCase (e.g. \"my-component\" -> \"MyComponent\")\n * Used for Component Names and imports.\n */\nexport function toPascalCase(str: string): string {\n // 1. Replace special chars with space\n // 2. Split by space or capital letters\n // 3. Capitalize first letter of each part\n return str\n .replace(/[^a-zA-Z0-9]+/g, ' ')\n .trim()\n .split(/\\s+/)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('');\n}\n\n/**\n * Converts a string to kebab-case (e.g. \"MyComponent\" -> \"my-component\")\n * Used for file paths and directories.\n */\nexport function toKebabCase(str: string): string {\n return str\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2') // Split camelCase\n .replace(/[^a-zA-Z0-9]+/g, '-') // Replace non-alphanumeric with hyphen\n .toLowerCase()\n .replace(/^-+|-+$/g, ''); // Trim leading/trailing hyphens\n}\n","/**\n * Response parsing utilities for AI model outputs.\n * Handles extraction of structured content from markdown-formatted responses.\n */\n\nimport { FileInfo } from '../types/file-types';\n\n/**\n * Extract JSON content from markdown code blocks\n * Handles cases where AI models wrap JSON in ```json ... ``` or ``` ... ```\n * If no code block markers are found, returns the original content\n *\n * @param response - Model response that may contain markdown code blocks\n * @returns Extracted JSON string without markdown formatting\n *\n * @example\n * // Input: \"```json\\n{\\\"key\\\": \\\"value\\\"}\\n```\"\n * // Output: \"{\\\"key\\\": \\\"value\\\"}\"\n */\nexport function extractJSON(response: string): string {\n // Try to match ```json ... ``` format first\n const jsonBlockMatch = response.match(/```json\\s*\\n([\\s\\S]*?)\\n```/);\n if (jsonBlockMatch && jsonBlockMatch[1]) {\n return jsonBlockMatch[1].trim();\n }\n\n // Try to match generic ``` ... ``` format (with newlines around content)\n const codeBlockMatch = response.match(/```\\s*\\n([\\s\\S]*?)\\n```/);\n if (codeBlockMatch && codeBlockMatch[1]) {\n return codeBlockMatch[1].trim();\n }\n\n // Fallback: no proper code block; use full content but strip loose markdown fences.\n // Some models return raw JSON with trailing \"```\" (e.g. ...]```) or leading ```\\n.\n let cleaned = response.trim();\n cleaned = cleaned.replace(/^\\s*```(?:json)?\\s*\\n?/g, '').replace(/\\s*```+\\s*$/g, '');\n return cleaned;\n}\n\n/**\n * Extract code content from markdown code blocks\n * Handles cases where AI models wrap code in ```tsx ... ``` or ``` ... ```\n * If no code block markers are found, returns the original content\n */\nexport function extractCode(response: string): string {\n // 1. Try to extract content strictly within ``` fences\n // Regex captures content between ```language and ```\n const codeBlockMatch = response.match(/```(?:tsx|typescript|react|js|javascript|json|css|less|scss)?\\s*\\n([\\s\\S]*?)```/);\n\n if (codeBlockMatch && codeBlockMatch[1]) {\n return codeBlockMatch[1].trim();\n }\n\n // 2. Fallback: If no clear block structure is found (or fences are missing/malformed),\n // try to strip loose fences just in case, but usually method 1 catches the block.\n // If the model returned JUST code without fences, this preserves it.\n // If the model returned \"Here is code: code\", this returns the whole string (which might be bad, but safest fallback).\n\n // Removing loose fences if any remain (unlikely if method 1 failed but good for cleanup)\n const cleaned = response\n .replace(/```(tsx|typescript|react|js|javascript|json|css|less|scss)?/g, '')\n .replace(/```/g, '')\n .trim();\n\n return cleaned;\n}\n\n/**\n * Extract multiple files from content with file headers\n * Format:\n * ## filename.tsx\n * ```tsx\n * code...\n * ```\n *\n * ## filename.css\n * ```css\n * styles...\n * ```\n */\nexport function extractFiles(content: string): FileInfo[] {\n const files: FileInfo[] = [];\n\n // Match file sections: ## filename\\n```language\\ncode\\n```\n // Allow optional whitespace around newlines for flexibility\n const fileRegex = /##\\s+([^\\n]+)\\s*\\n\\s*```(?:\\w+)?\\s*\\n([\\s\\S]*?)\\n\\s*```/g;\n let match;\n\n while ((match = fileRegex.exec(content)) !== null) {\n if (match[1] && match[2]) {\n const filename = match[1].trim();\n const code = match[2].trim();\n files.push({ filename, content: code });\n }\n }\n\n return files;\n}\n","import { FigmaUrlInfo } from '../types/figma-types';\n\n/**\n * Parse Figma URL and extract fileId, name, and nodeId in one pass\n * @param url - Figma URL to parse\n * @returns Object containing fileId, name, and nodeId\n * @example\n * parseFigmaUrl('https://www.figma.com/design/aONcu8L82l1PdcT304Q8Za/Intern?node-id=0-495')\n * // Returns: { fileId: 'aONcu8L82l1PdcT304Q8Za', name: 'intern', nodeId: '0-495' }\n */\nexport const parseFigmaUrl = (url: string): FigmaUrlInfo => {\n let fileId: string | null = null;\n let name = 'untitled';\n let nodeId: string | null = null;\n\n try {\n const urlObj = new URL(decodeURIComponent(url));\n const pathParts = urlObj.pathname.split('/').filter(Boolean);\n if (pathParts.length >= 3) {\n fileId = pathParts[pathParts.length - 2] || null;\n const fileName = pathParts[pathParts.length - 1];\n name = fileName ? encodeURI(fileName).toLowerCase() : 'untitled';\n name = name.length > 20 ? name.substring(0, 20) : name;\n }\n\n nodeId = urlObj.searchParams.get('node-id') || null;\n nodeId = nodeId ? nodeId.replace(/-/g, ':') : null;\n } catch {}\n\n if (!fileId || !nodeId) {\n throw new Error('Invalid Figma URL');\n }\n\n return { fileId, name, nodeId, projectName: `${name}_${nodeId.replace(/:/g, '_')}` };\n};\n","import { Command } from 'commander';\nimport { generateProtocol } from '../nodes/process';\nimport { parseFigmaUrl } from '../utils/url-parser';\nimport { workspaceManager } from '../utils/workspace';\nimport { logger } from '../utils/logger';\n\n// f2p command: Figma to Protocol\nexport const registerD2PCommand = (program: Command) => {\n program\n .command('design2protocol')\n .alias('d2p')\n .description('Convert Figma design to protocol (fetch and process Figma document)')\n .option('-s, --source <url>', 'Figma Link')\n .action(async (opts: { source: string }) => {\n try {\n const { source } = opts;\n const urlInfo = parseFigmaUrl(source);\n const workspace = workspaceManager.initWorkspace(urlInfo.name);\n\n await generateProtocol({\n urlInfo,\n workspace,\n figmaInfo: { thumbnail: '' },\n protocol: undefined,\n messages: [],\n config: {},\n });\n\n logger.printSuccessLog('Successfully completed Design to Protocol conversion!');\n } catch (error) {\n logger.printErrorLog(`Error during d2p execution: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n};\n","import { Command } from 'commander';\nimport { logger } from '../utils/logger';\nimport { design2code } from '../graph';\nimport { ValidationMode } from '../types/graph-types';\n\n/**\n * Validate and map CLI mode parameter to internal validationMode.\n * @param mode - The mode string from CLI\n * @returns The mapped ValidationMode, or null if invalid\n */\nfunction getValidationMode(mode: string): ValidationMode | null {\n const validModes = ['code', 'with-report', 'full'] as const;\n type ValidMode = (typeof validModes)[number];\n const isValidMode = (m: string): m is ValidMode => {\n return validModes.includes(m as ValidMode);\n };\n\n if (!isValidMode(mode)) {\n return null;\n }\n\n // Map CLI mode to internal validationMode\n const modeMap: Record<ValidMode, ValidationMode> = {\n code: ValidationMode.CodeOnly,\n 'with-report': ValidationMode.ReportOnly,\n full: ValidationMode.Full,\n };\n\n return modeMap[mode];\n}\n\n// d2c command: Design to Code\nexport const registerD2CCommand = (program: Command) => {\n program\n .command('design2code')\n .alias('d2c')\n .description('Generate frontend code from design')\n .option('-s, --source <url>', 'Figma Link')\n .option(\n '-m, --mode [type]',\n 'Execution mode: code (generate component code only), with-report (single validation and generate report), full (iterative validation)',\n 'code'\n )\n .action(async (opts: { source: string; mode?: string }) => {\n try {\n const { source, mode = 'code' } = opts;\n\n const validationMode = getValidationMode(mode);\n if (!validationMode) {\n logger.printErrorLog(`Invalid mode: ${mode}. Must be one of: code, with-report, full`);\n process.exit(1);\n }\n\n await design2code(source, validationMode);\n\n logger.printSuccessLog('Successfully completed code generation from design! Happy coding!');\n } catch (error) {\n logger.printErrorLog(`Error during d2c execution: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n};\n","import { StateGraph, START, END } from '@langchain/langgraph';\nimport { GraphNode, ValidationMode } from './types/graph-types';\nimport { GraphStateAnnotation } from './state';\nimport { initialProject } from './nodes/initial';\nimport { generateProtocol } from './nodes/process';\nimport { runValidation } from './nodes/validation';\nimport { parseFigmaUrl } from './utils/url-parser';\nimport { workspaceManager } from './utils/workspace';\nimport { generateCode } from './nodes/code';\nimport { initializeSqliteSaver, promptCheckpointChoice, clearThreadCheckpoint } from './utils/checkpoint';\nimport { logger } from './utils/logger';\n\nexport async function design2code(url: string, mode?: ValidationMode): Promise<void> {\n const urlInfo = parseFigmaUrl(url);\n const threadId = urlInfo.projectName!;\n const workspace = workspaceManager.initWorkspace(threadId);\n\n // Initialize SqliteSaver with the database path\n const checkpointer = initializeSqliteSaver(workspace.db);\n const resume = await promptCheckpointChoice(checkpointer, threadId);\n\n logger.printInfoLog(`Starting design-to-code process for: ${urlInfo.projectName}`);\n\n // If not resuming, delete workspace and reinitialize checkpointer\n if (resume !== true) {\n // Exclude checkpoint directory to avoid EBUSY error on Windows (SQLite lock)\n workspaceManager.deleteWorkspace(workspace, ['checkpoint']);\n logger.printInfoLog('Starting fresh...');\n\n // Clear existing checkpoints for this thread instead of deleting the file\n await clearThreadCheckpoint(checkpointer, threadId);\n } else {\n logger.printInfoLog('Resuming from cache...');\n }\n\n // Compile graph with checkpointer (after potential reinitialization)\n const graph = new StateGraph(GraphStateAnnotation)\n .addNode(GraphNode.INITIAL, initialProject)\n .addNode(GraphNode.PROCESS, generateProtocol)\n .addNode(GraphNode.CODE, generateCode)\n .addNode(GraphNode.VALIDATION, runValidation)\n .addEdge(START, GraphNode.INITIAL)\n .addEdge(GraphNode.INITIAL, GraphNode.PROCESS)\n .addEdge(GraphNode.PROCESS, GraphNode.CODE)\n .addEdge(GraphNode.CODE, GraphNode.VALIDATION)\n .addEdge(GraphNode.VALIDATION, END)\n .compile({ checkpointer });\n\n const config = { configurable: { thread_id: threadId } };\n\n // If resuming from checkpoint, pass null to let LangGraph resume from saved state\n // Otherwise, pass initial state to start fresh\n const validationMode: ValidationMode = mode ?? ValidationMode.Full;\n const state =\n resume === true\n ? null\n : {\n messages: [],\n urlInfo,\n workspace,\n config: {\n validationMode,\n },\n };\n await graph.invoke(state, config);\n\n logger.printSuccessLog('Design-to-code process completed!');\n}\n","import { Annotation, MessagesAnnotation } from '@langchain/langgraph';\nimport type { FigmaUrlInfo } from './types/figma-types';\nimport type { Protocol, GlobalFigmaInfo, ValidationConfig } from './types';\nimport { WorkspaceStructure } from './types/workspace-types';\n\nexport const GraphStateAnnotation = Annotation.Root({\n ...MessagesAnnotation.spec,\n urlInfo: Annotation<FigmaUrlInfo>(),\n workspace: Annotation<WorkspaceStructure>(),\n figmaInfo: Annotation<GlobalFigmaInfo>(),\n protocol: Annotation<Protocol | undefined>(),\n config: Annotation<ValidationConfig>(),\n});\n\nexport type GraphState = typeof GraphStateAnnotation.State;\n","import { Agent, type ModelConfig } from 'evoltagent';\nimport { INITIAL_AGENT_SYSTEM_PROMPT } from './prompt';\n\n/**\n * Creates an initial agent for scaffolding a project.\n * @param options - The options for creating the agent.\n * @param options.modelConfig - The model configuration.\n * @param options.appPath - The path to the app.\n * @returns The initial agent.\n */\nexport function createInitialAgent(modelConfig: ModelConfig): Agent {\n const systemTools = ['ThinkTool.execute', 'FileEditor.read', 'FileEditor.write'];\n\n return new Agent({\n name: 'InitialAgent',\n profile: 'Expert Frontend Engineer specialized in project scaffolding with React, TypeScript, and Tailwind CSS V4.',\n system: INITIAL_AGENT_SYSTEM_PROMPT,\n tools: systemTools,\n modelConfig,\n verbose: true,\n });\n}\n","/**\n * Generates the system prompt for the InitialAgent.\n * Defines project requirements, tech stack (React + Tailwind V4), and safety constraints.\n *\n * @param options - Configuration options for the prompt generation.\n * @param options.appPath - The target directory path where the project will be scaffolded.\n */\nexport const INITIAL_AGENT_SYSTEM_PROMPT = `\n<system_instructions>\n <task>Scaffold a clean React V18 + TS + Vite + TailwindCSS V4 + Less project.</task>\n\n <input_context>\n - appPath: /absolute/path/to/app\n - appName: document title name\n </input_context>\n\n <requirements>\n <tech_stack>React V18, TypeScript, Vite, TailwindCSS V4, Less</tech_stack>\n\n <directory_constraint>\n CRITICAL: All file operations MUST be performed within the directory specified by appPath.\n When using 'FileEditor.write' or other file tools, you MUST use the full path format: {appPath}/filename.\n </directory_constraint>\n\n <file_specs>\n - \\`.gitignore\\`: Standard gitignore file. MUST include:\n * node_modules/\n * dist/ and build/ directories\n * .env file\n * Editor files (.vscode/*, .DS_Store, etc.)\n * Log files and cache directories\n * Lock files (package-lock.json, yarn.lock, pnpm-lock.yaml)\n - \\`package.json\\`: Basic scripts and dependencies. MUST include \\`tailwindcss\\` (v4) and \\`@tailwindcss/vite\\`.\n * Scripts MUST use \"pnpm exec\" prefix to ensure project dependencies are prioritized:\n - \"dev\": \"pnpm exec vite\"\n - \"build\": \"pnpm exec tsc && pnpm exec vite build\"\n - \"preview\": \"pnpm exec vite preview\"\n * IMPORTANT: Do NOT add \"coderio\" as a dependency - it's only a build tool, not a runtime dependency.\n - \\`vite.config.ts\\`: Configure React and TailwindCSS V4 plugins. MUST include path alias configuration:\n * Add \\`resolve.alias\\` with \\`@\\` pointing to \\`path.resolve(__dirname, './src')\\`\n * Import \\`path\\` from 'node:path'\n - \\`tsconfig.json\\`: Standard React-Vite TS config. MUST include path alias configuration:\n * Add \\`compilerOptions.baseUrl\\` set to \".\"\n * Add \\`compilerOptions.paths\\` with \\`\"@/*\": [\"src/*\"]\\`\n - \\`index.html\\`: Basic template with #root and entry script. set document title to appName.\n - \\`src/main.tsx\\`: Entry point rendering App.\n - \\`src/vite-env.d.ts\\`: MUST include \\`/// <reference types=\"vite/client\" />\\` to support CSS/Less module imports.\n - \\`src/App.tsx\\`: MUST be an empty component (returns null or empty div), NO React import if unused.\n - \\`src/App.less\\`: MUST be an empty file.\n - \\`src/globals.css\\`: ONLY include \\`@import \"tailwindcss\";\\`.\n </file_specs>\n </requirements>\n\n <workflow>\n 1. Use 'FileEditor.write' to create each file listed in <file_specs>, using the format {appPath}/filename for all paths.\n 2. Ensure the directory structure is correct and all files are contained within the appPath directory.\n </workflow>\n\n <final_instruction>\n Create a fully working but MINIMAL project skeleton using Tailwind CSS V4. Use 'FileEditor.write' for all file creations. Use the full path format {appPath}/filename for every file. Do not provide code blocks in chat.\n </final_instruction>\n</system_instructions>\n`.trim();\n","import { createInitialAgent } from '../../agents/initial-agent';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { logger } from '../../utils/logger';\nimport { getModelConfig } from '../../utils/config';\nimport { GraphState } from '../../state';\nimport { MAX_OUTPUT_TOKENS, AGENT_CONTEXT_WINDOW_TOKENS } from '../../constants';\nimport { initialAgentInstruction } from '../../agents/initial-agent/instruction';\n\n/**\n * 'initial' node, responsible for initializing the empty project scaffold.\n * It uses an LLM-based agent to create the basic project structure and files.\n */\nexport const initialProject = async (state: GraphState) => {\n logger.printInfoLog('Initializing project...');\n\n const envConfig = getModelConfig();\n const modelConfig = {\n ...envConfig,\n contextWindowTokens: AGENT_CONTEXT_WINDOW_TOKENS,\n maxOutputTokens: MAX_OUTPUT_TOKENS,\n };\n\n const appPath = state.workspace.app;\n const appName = state.urlInfo.name || '';\n if (!appPath) {\n throw new Error('Workspace application path is not defined.');\n }\n\n const initialAgent = createInitialAgent(modelConfig);\n const result: unknown = await initialAgent.run(initialAgentInstruction({ appPath, appName }));\n\n // Validate if essential files were created\n const essentialFiles = ['package.json', 'src', 'vite.config.ts', 'tsconfig.json', 'index.html', 'src/main.tsx', 'src/App.tsx'];\n for (const file of essentialFiles) {\n const fullPath = path.join(appPath, file);\n if (!fs.existsSync(fullPath)) {\n throw new Error(`Critical file/directory missing: \"${file}\". The project scaffolding may have failed.`);\n }\n }\n\n logger.printSuccessLog(result as string);\n\n return {};\n};\n","export function initialAgentInstruction(params: { appPath: string; appName: string }): string {\n return `\nappPath: ${params.appPath}\nappName: ${params.appName}\n\nTASK:\nScaffold a clean React V18 + TS + Vite + TailwindCSS V4 + Less project.\n`.trim();\n}\n","/**\n * Validation module.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { GraphState } from '../../state';\nimport { METRIC_DECIMAL_PLACES } from './constants';\nimport { logger } from '../../utils/logger';\nimport { validationLoop } from './core/validation-loop';\nimport { commit } from './commit/index';\nimport { ValidationMode } from '../../types/graph-types';\n\n/**\n * LangGraph node: run validation on the generated app and write a report into the workspace.\n * Reads validation mode from state.config.validationMode (defaults to 'full').\n * Throws error if validation fails (MAE threshold not reached) or execution errors occur.\n */\nexport const runValidation = async (state: GraphState): Promise<void> => {\n if (!state.protocol) {\n throw new Error('No protocol found for validation (state.protocol is missing).');\n }\n if (!state.figmaInfo?.thumbnail) {\n throw new Error('Missing Figma thumbnail URL (state.figmaInfo.thumbnail is missing).');\n }\n\n const mode = state.config?.validationMode ?? ValidationMode.Full;\n // Code-only mode: skip validation, only commit and exit\n if (mode === ValidationMode.CodeOnly) {\n logger.printInfoLog('Code-only mode: skipping validation, committing generated code...');\n const commitResult = await commit({ appPath: state.workspace.app });\n if (!commitResult.success) {\n logger.printWarnLog(`Git commit failed: ${commitResult.message}`);\n } else {\n logger.printSuccessLog('Git commit completed successfully!');\n }\n return;\n }\n\n const outputDir = path.join(state.workspace.process, 'validation');\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n logger.printInfoLog(`Starting validation loop (mode: ${mode})...`);\n\n const result = await validationLoop({\n protocol: state.protocol,\n figmaThumbnailUrl: state.figmaInfo.thumbnail,\n outputDir,\n workspace: state.workspace,\n config: { mode },\n });\n\n if (result.error) {\n throw new Error(result.error);\n }\n\n const reportHtmlPath = path.join(outputDir, 'index.html');\n if (result.validationPassed) {\n logger.printSuccessLog(`Validation PASSED (MAE: ${result.finalMae.toFixed(METRIC_DECIMAL_PLACES)}px)`);\n } else {\n logger.printWarnLog(`Validation FAILED (MAE: ${result.finalMae.toFixed(METRIC_DECIMAL_PLACES)}px)`);\n }\n logger.printInfoLog(`Validation report: ${reportHtmlPath}`);\n};\n","/**\n * Validation node-specific configuration constants.\n * These are static values specific to the validation orchestration logic.\n * Not global - scoped to validation node only.\n */\n\n/**\n * Target MAE (Mean Absolute Error) in pixels.\n *\n * Maximum acceptable average position error across all elements.\n */\nexport const TARGET_MAE = 3;\n\n/**\n * Position error threshold in pixels.\n *\n * - Elements with error <= this value are classified as \"accurate\"\n * - Elements with error > this value are classified as \"misaligned\"\n */\nexport const POSITION_THRESHOLD = 1.0;\n\n/**\n * Default timeout for browser operations in milliseconds.\n *\n * Used by Playwright for page navigation and rendering.\n */\nexport const DEFAULT_TIMEOUT = 30000;\n\n/**\n * Number of decimal places for rounding metric values.\n */\nexport const METRIC_DECIMAL_PLACES = 2;\n\n/**\n * Default viewport size for browser rendering.\n */\nexport const DEFAULT_VIEWPORT = { width: 1440, height: 900 };\n\n/**\n * Maximum number of validation-correction iterations for the judger-refiner loop.\n */\nexport const MAX_ITERATIONS = 3;\n\n/**\n * Run browser in headless mode.\n */\nexport const HEADLESS = true;\n\n/**\n * Timeout for optional selector waiting in milliseconds (5 seconds)\n */\nexport const SELECTOR_WAIT_TIMEOUT = 5000;\n\n/**\n * Default validation loop configuration.\n *\n * Used when no custom config is provided to validationLoop().\n */\nexport const DEFAULT_VALIDATION_LOOP_CONFIG = {\n maxIterations: MAX_ITERATIONS,\n targetMae: TARGET_MAE,\n positionThreshold: POSITION_THRESHOLD,\n browserTimeout: DEFAULT_TIMEOUT,\n defaultViewportWidth: DEFAULT_VIEWPORT.width,\n defaultViewportHeight: DEFAULT_VIEWPORT.height,\n headless: HEADLESS,\n};\n\n/**\n * Dev server constants used by validation/launch tooling.\n */\nexport const DEFAULT_PORT = 5173;\n\n/**\n * Builds the default dev server URL from a port number.\n */\nexport function buildDevServerUrl(port: number): string {\n return `http://localhost:${port}`;\n}\n","/**\n * Main validation loop orchestration.\n *\n * Simplified actor-critic pattern with in-memory data passing.\n * Iteratively validates positions, diagnoses errors, applies fixes until\n * MAE threshold is met or max iterations reached.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport { DEFAULT_VALIDATION_LOOP_CONFIG } from '../constants';\nimport { logger } from '../../../utils/logger';\nimport { commit } from '../commit/index';\nimport { createJudgerAgent } from '../../../agents/judger-agent';\nimport { formatJudgerInstruction } from '../../../agents/judger-agent/instruction';\nimport { createRefinerAgent, formatRefinerInstruction } from '../../../agents/refiner-agent';\nimport { launch } from '../launch/index';\nimport type { ComponentHistory, MisalignedComponent, Dict } from '../../../types/validation-types';\nimport type { JudgerDiagnosis } from '../../../agents/judger-agent/types';\nimport type { RefinerResult } from '../../../agents/refiner-agent/types';\nimport type {\n ComponentCorrectionLog,\n IterationLog,\n ProcessedOutput,\n RefinementContext,\n ValidationIterationResult,\n ValidationLoopConfig,\n ValidationLoopParams,\n ValidationLoopResult,\n SkippedElement,\n} from '../types';\nimport { extractLayoutFromContext } from '../utils/extraction/extract-layout-metadata';\nimport { report } from '../report/index';\nimport { LaunchTool } from '../../../tools/launch-tool';\nimport { VisualizationTool } from '../../../tools/visualization-tool';\nimport { extractValidationContext, extractComponentPaths, toElementMetadataRegistry } from '../utils/extraction/extract-protocol-context';\nimport { validatePositions } from './validate-position';\nimport { downloadImage } from '../../../tools/figma-tool/images';\nimport { ensureValidationDependencies } from '../../../utils/dependency-installer';\nimport { ValidationMode } from '../../../types/graph-types';\n\nfunction filterComponentsToFix(misaligned: MisalignedComponent[], positionThreshold: number): MisalignedComponent[] {\n return misaligned.filter(comp => {\n const [errorX, errorY] = comp.validationReport.absoluteError;\n return errorX > positionThreshold || errorY > positionThreshold;\n });\n}\n\nfunction recordComponentPosition(comp: MisalignedComponent, iteration: number, componentHistory: ComponentHistory): void {\n const history = componentHistory[comp.componentId] ?? [];\n history.push({\n iteration,\n position: comp.validationReport.currentPosition,\n error: comp.validationReport.absoluteError,\n fixApplied: null,\n });\n componentHistory[comp.componentId] = history;\n}\n\nasync function refineComponent(comp: MisalignedComponent, context: RefinementContext): Promise<ComponentCorrectionLog> {\n const { workspace, structureTree, componentPaths, componentHistory, validationContext, previousScreenshotPath } = context;\n\n try {\n // Extract element IDs from context for this component\n const elementIds = Array.from(validationContext.elements.values())\n .filter((e): e is NonNullable<typeof e> => e.parentComponentId === comp.componentId)\n .map(e => e.id);\n\n const figmaMetadata = extractLayoutFromContext(validationContext, elementIds);\n\n logger.printLog(` Analyzing ${comp.name}...`);\n const judger = createJudgerAgent({\n workspaceDir: workspace.app,\n structureTree,\n componentPaths,\n history: componentHistory,\n });\n const judgerInstruction = formatJudgerInstruction(comp, figmaMetadata as unknown as Record<string, unknown>, componentPaths);\n const judgerImages = previousScreenshotPath ? [previousScreenshotPath] : undefined;\n const diagnosis = (await judger.run(judgerInstruction, judgerImages)) as JudgerDiagnosis;\n\n logger.printLog(` Error type: ${diagnosis.errorType}`);\n logger.printLog(` Fix instructions: ${diagnosis.refineInstructions?.length || 0}`);\n\n // Skip refiner if no instructions (judger failed to analyze)\n if (!diagnosis.refineInstructions || diagnosis.refineInstructions.length === 0) {\n const history = componentHistory[comp.componentId];\n return {\n componentId: comp.componentId,\n componentPath: comp.path,\n elementIds: comp.elementIds,\n validationReport: comp.validationReport,\n diagnosis,\n refinerResult: {\n success: false,\n summary: ['Skipped - no instructions from judger'],\n editsApplied: 0,\n },\n positionHistory: history ? [...history] : undefined,\n };\n }\n\n logger.printLog(` Applying fixes to ${comp.name}...`);\n const refiner = createRefinerAgent(workspace.app);\n const refinerInstruction = formatRefinerInstruction(comp, diagnosis, componentPaths);\n const refinerResult = (await refiner.run(refinerInstruction)) as RefinerResult;\n\n if (refinerResult.success) {\n logger.printSuccessLog(`${comp.name}: ${refinerResult.editsApplied} edits applied`);\n } else {\n logger.printWarnLog(`${comp.name}: ${refinerResult.editsApplied} edits applied`);\n }\n\n const history = componentHistory[comp.componentId];\n const last = history?.at(-1);\n if (last) {\n last.fixApplied = refinerResult.summary;\n }\n\n return {\n componentId: comp.componentId,\n componentPath: comp.path,\n elementIds: comp.elementIds,\n validationReport: comp.validationReport,\n diagnosis,\n refinerResult,\n positionHistory: history ? [...history] : undefined,\n };\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.printInfoLog(`${comp.name}: ${errorMsg}`);\n\n const history = componentHistory[comp.componentId];\n return {\n componentId: comp.componentId,\n componentPath: comp.path,\n elementIds: comp.elementIds,\n validationReport: comp.validationReport,\n diagnosis: undefined,\n refinerResult: undefined,\n positionHistory: history ? [...history] : undefined,\n };\n }\n}\n\nfunction saveProcessedJson(outputDir: string, processedOutput: ProcessedOutput): void {\n const processedJsonPath = path.join(outputDir, 'processed.json');\n fs.writeFileSync(processedJsonPath, JSON.stringify(processedOutput, null, 2));\n logger.printInfoLog('Saved processed.json');\n}\n\n// Helper functions for reducing code duplication\nasync function performCommit(appPath: string, iteration: number | undefined, stage: string): Promise<void> {\n const commitResult = await commit({ appPath, iteration });\n if (!commitResult.success) {\n logger.printWarnLog(`Git commit (${stage}) failed: ${commitResult.message}`);\n } else if (iteration === undefined) {\n logger.printSuccessLog(`Initial project committed successfully, starting validation loop...`);\n }\n}\n\nfunction saveIterationAndProcessedJson(\n iterations: IterationLog[],\n iteration: number,\n currentMae: number,\n currentSae: number,\n misalignedCount: number,\n components: ComponentCorrectionLog[],\n screenshotPath: string,\n skippedElements: SkippedElement[] | undefined,\n outputDir: string,\n targetMae: number\n): void {\n // Add current iteration to log\n iterations.push({\n iteration,\n metrics: { mae: currentMae, sae: currentSae, misalignedCount },\n components,\n screenshotPath,\n skippedElements: skippedElements && skippedElements.length > 0 ? skippedElements : undefined,\n });\n\n // Save processed.json with updated iterations\n const processedOutput: ProcessedOutput = {\n iterations,\n finalResult: {\n success: currentMae <= targetMae,\n finalMae: currentMae,\n finalSae: currentSae,\n totalIterations: iterations.length,\n misalignedCount,\n },\n };\n saveProcessedJson(outputDir, processedOutput);\n}\n\nexport async function validationLoop(params: ValidationLoopParams): Promise<ValidationLoopResult> {\n // Ensure dependencies are installed before starting validation loop\n ensureValidationDependencies();\n\n const { protocol, figmaThumbnailUrl, outputDir, workspace } = params;\n\n if (!protocol || !figmaThumbnailUrl || !outputDir || !workspace) {\n throw new Error('Something wrong in validation loop, missing required parameters...');\n }\n\n const config: ValidationLoopConfig = {\n ...DEFAULT_VALIDATION_LOOP_CONFIG,\n ...params.config,\n };\n const mode: ValidationMode.ReportOnly | ValidationMode.Full = config.mode ?? ValidationMode.Full;\n const maxIterations = mode === ValidationMode.ReportOnly ? 1 : config.maxIterations;\n const visualizationTool = new VisualizationTool();\n\n // Variables to track server state (will be initialized in iteration 1)\n let currentServerUrl: string | undefined;\n let serverKey: string | undefined;\n\n try {\n // Extract unified validation context from protocol (single traversal)\n const validationContext = extractValidationContext(protocol);\n const designOffset: [number, number] = [validationContext.offset.x, validationContext.offset.y];\n if (Math.abs(designOffset[0]) >= 1 || Math.abs(designOffset[1]) >= 1) {\n logger.printInfoLog(`Design offset: (${designOffset[0].toFixed(0)}, ${designOffset[1].toFixed(0)} px)`);\n }\n\n // Extract component paths from context (already resolved to absolute filesystem paths)\n const resolvedComponentPaths = extractComponentPaths(validationContext, workspace);\n\n // Build element registry for compatibility with existing APIs\n const elementRegistry = toElementMetadataRegistry(validationContext);\n\n // Download and cache Figma thumbnail once to avoid redundant downloads in each iteration\n logger.printInfoLog('Downloading Figma thumbnail (will be cached for all iterations)...');\n const cachedFigmaThumbnailBase64 = await downloadImage(figmaThumbnailUrl, undefined, undefined, true);\n logger.printSuccessLog('Figma thumbnail cached successfully');\n\n const iterations: IterationLog[] = [];\n const componentHistory: ComponentHistory = {};\n let previousScreenshotPath: string | undefined;\n let currentMae = -1; // Sentinel value: -1 indicates no measurement yet\n let currentSae = 0;\n let lastMisalignedCount = 0;\n let lastValidationResult: ValidationIterationResult | undefined;\n // Track paths to last iteration's individual screenshots for report reuse\n let lastRenderMarkedPath: string | undefined;\n let lastTargetMarkedPath: string | undefined;\n\n for (let iteration = 1; iteration <= maxIterations; iteration++) {\n // Use different logging for reportOnly mode\n if (mode === ValidationMode.ReportOnly) {\n logger.printLog(`\\n${'='.repeat(60)}`);\n logger.printLog(`Running validation (report-only mode)`);\n logger.printLog(`${'='.repeat(60)}`);\n } else {\n logger.printLog(`\\n${'='.repeat(60)}`);\n logger.printLog(`Iteration ${iteration}/${maxIterations}`);\n logger.printLog(`${'='.repeat(60)}`);\n }\n\n // If this is iteration 1, we need to launch first to have a server for validation\n if (iteration === 1) {\n logger.printInfoLog('Initial launch: installing dependencies, building, fixing errors...');\n const launchResult = await launch(workspace.app, {\n skipDependencyInstall: false,\n });\n\n if (!launchResult.success) {\n throw new Error(`Initial launch failed: ${launchResult.error}`);\n }\n\n currentServerUrl = launchResult.url!;\n serverKey = launchResult.serverKey!;\n logger.printSuccessLog(`Dev server ready at ${currentServerUrl}`);\n\n // In reportOnly mode, commit the initial state after successful launch\n if (mode === ValidationMode.ReportOnly) {\n await performCommit(workspace.app, undefined, 'initial state');\n }\n }\n\n const validationResult = await validatePositions({\n serverUrl: currentServerUrl!,\n figmaThumbnailUrl,\n protocol,\n iteration,\n positionThreshold: config.positionThreshold,\n designOffset,\n outputDir,\n validationContext,\n elementRegistry,\n cachedFigmaThumbnailBase64,\n resolvedComponentPaths,\n });\n\n // Store for final report generation\n lastValidationResult = validationResult;\n\n currentMae = validationResult.mae;\n currentSae = validationResult.sae;\n const misaligned = validationResult.misalignedComponents;\n lastMisalignedCount = misaligned.length;\n\n logger.printLog(`MAE: ${currentMae.toFixed(2)}px (target: <=${config.targetMae}px)`);\n logger.printLog(`SAE: ${currentSae.toFixed(2)}px`);\n logger.printLog(`Misaligned: ${misaligned.length}`);\n\n // Generate validation screenshot using VisualizationTool\n const screenshotResult = await visualizationTool.generateIterationScreenshot(\n misaligned,\n currentServerUrl!,\n figmaThumbnailUrl,\n validationResult.viewport,\n { x: designOffset[0], y: designOffset[1] },\n path.join(outputDir, 'comparison_screenshots', `iteration_${iteration}.webp`),\n cachedFigmaThumbnailBase64\n );\n\n // Save individual annotated screenshots to disk for report reuse\n if (screenshotResult.renderMarked && screenshotResult.targetMarked) {\n const comparisonDir = path.join(outputDir, 'comparison_screenshots');\n lastRenderMarkedPath = path.join(comparisonDir, `iteration_${iteration}_render_marked.webp`);\n lastTargetMarkedPath = path.join(comparisonDir, `iteration_${iteration}_target_marked.webp`);\n\n const sharp = (await import('sharp')).default;\n await sharp(Buffer.from(screenshotResult.renderMarked.split(',')[1]!, 'base64')).toFile(lastRenderMarkedPath);\n await sharp(Buffer.from(screenshotResult.targetMarked.split(',')[1]!, 'base64')).toFile(lastTargetMarkedPath);\n }\n\n // Use combined screenshot for judger visual context in next iteration\n const comparisonScreenshotPath = screenshotResult.combinedPath;\n previousScreenshotPath = comparisonScreenshotPath; // Pass to judger in next iteration\n\n const misalignedToFix = filterComponentsToFix(misaligned, config.positionThreshold);\n if (mode === ValidationMode.ReportOnly) {\n // In reportOnly mode, we don't fix anything, so no need to log about skipping\n } else {\n logger.printInfoLog(\n `Skipping ${misaligned.length - misalignedToFix.length} components with error <= ${config.positionThreshold}px`\n );\n }\n\n for (const comp of misalignedToFix) {\n recordComponentPosition(comp, iteration, componentHistory);\n }\n\n const componentLogs: ComponentCorrectionLog[] = [];\n\n if (mode === ValidationMode.ReportOnly) {\n logger.printInfoLog('Report-only mode: skipping component refinement, saving validation report...');\n\n saveIterationAndProcessedJson(\n iterations,\n iteration,\n currentMae,\n currentSae,\n misaligned.length,\n componentLogs,\n comparisonScreenshotPath,\n validationResult.skippedElements,\n outputDir,\n config.targetMae\n );\n break;\n }\n\n if (currentMae <= config.targetMae) {\n logger.printSuccessLog('Validation passed!');\n\n saveIterationAndProcessedJson(\n iterations,\n iteration,\n currentMae,\n currentSae,\n misaligned.length,\n componentLogs,\n comparisonScreenshotPath,\n validationResult.skippedElements,\n outputDir,\n config.targetMae\n );\n\n if (serverKey) {\n await performCommit(workspace.app, iteration, `iteration ${iteration}`);\n }\n break;\n }\n\n // Full mode: proceed with component refinement\n logger.printInfoLog(`Refining ${misalignedToFix.length} components...`);\n\n const refinementContext: RefinementContext = {\n workspace,\n structureTree: protocol as unknown as Dict,\n componentPaths: resolvedComponentPaths,\n componentHistory,\n validationContext,\n previousScreenshotPath,\n };\n\n for (const comp of misalignedToFix) {\n const log = await refineComponent(comp, refinementContext);\n componentLogs.push(log);\n }\n\n // Launch after refiner to catch any errors and rebuild\n logger.printInfoLog('Re-launching dev server after refiner changes...');\n\n // Stop current server\n const launchTool = new LaunchTool();\n await launchTool.stopDevServer(serverKey!).catch(() => {\n logger.printWarnLog('Failed to stop previous server');\n });\n\n // Launch with skipDependencyInstall (deps don't change)\n const launchResult = await launch(workspace.app, {\n skipDependencyInstall: true,\n });\n\n if (!launchResult.success) {\n throw new Error(`Launch failed after refiner at iteration ${iteration}: ${launchResult.error}`);\n }\n\n currentServerUrl = launchResult.url!;\n serverKey = launchResult.serverKey!;\n\n logger.printSuccessLog(`Dev server restarted at ${currentServerUrl}`);\n\n // Commit AFTER launch (ensures working state)\n if (mode === ValidationMode.Full) {\n await performCommit(workspace.app, iteration, `iteration ${iteration}`);\n }\n\n saveIterationAndProcessedJson(\n iterations,\n iteration,\n currentMae,\n currentSae,\n misaligned.length,\n componentLogs,\n comparisonScreenshotPath,\n validationResult.skippedElements,\n outputDir,\n config.targetMae\n );\n\n // This path is only reached in full mode (reportOnly breaks out earlier)\n logger.printInfoLog(`Iteration ${iteration} complete\\n`);\n }\n\n const validationPassed = currentMae <= config.targetMae;\n if (!validationPassed) {\n if (mode === ValidationMode.ReportOnly) {\n logger.printWarnLog(\n `Validation did not satisfy MAE threshold (${config.targetMae}px) in report-only mode. Final MAE: ${currentMae.toFixed(2)}px`\n );\n } else {\n logger.printWarnLog(\n `Max iterations (${maxIterations}) reached without satisfying MAE threshold (${config.targetMae}px). Final MAE: ${currentMae.toFixed(2)}px`\n );\n }\n }\n\n const finalOutput: ProcessedOutput = {\n iterations,\n finalResult: {\n success: validationPassed,\n finalMae: currentMae,\n finalSae: currentSae,\n totalIterations: iterations.length,\n misalignedCount: lastMisalignedCount,\n },\n };\n\n // Ensure server was launched (should always be true after iteration 1)\n if (!currentServerUrl || !serverKey) {\n throw new Error('Server was not launched properly during validation');\n }\n\n // Generate final validation report using report() subnode\n try {\n if (!lastValidationResult) {\n throw new Error('No validation results available for report generation');\n }\n\n // Validate that we have saved screenshots\n if (!lastRenderMarkedPath || !lastTargetMarkedPath) {\n throw new Error('No saved screenshots available for report generation');\n }\n\n const reportResult = await report({\n validationResult: lastValidationResult,\n figmaThumbnailUrl,\n cachedFigmaThumbnailBase64,\n designOffset: { x: designOffset[0], y: designOffset[1] },\n outputDir,\n serverUrl: currentServerUrl,\n savedRenderMarkedPath: lastRenderMarkedPath,\n savedTargetMarkedPath: lastTargetMarkedPath,\n });\n\n // Update misaligned count from final report (may differ from last iteration)\n finalOutput.finalResult.misalignedCount = lastValidationResult.misalignedComponents.length;\n saveProcessedJson(outputDir, finalOutput);\n\n return {\n reportGenerated: reportResult.success,\n validationPassed,\n finalMae: currentMae,\n finalSae: currentSae,\n totalIterations: iterations.length,\n processedOutput: finalOutput,\n userReport: reportResult.userReport,\n };\n } catch (screenshotError) {\n const errorMsg = screenshotError instanceof Error ? screenshotError.message : String(screenshotError);\n logger.printWarnLog(`Failed to generate final report: ${errorMsg}. Returning minimal report.`);\n saveProcessedJson(outputDir, finalOutput);\n\n // Fallback: create minimal report\n return {\n reportGenerated: false,\n validationPassed,\n finalMae: currentMae,\n finalSae: currentSae,\n totalIterations: iterations.length,\n processedOutput: finalOutput,\n userReport: {\n design: { snap: figmaThumbnailUrl, markedSnap: '' },\n page: { url: currentServerUrl, snap: '', markedSnap: '' },\n report: {\n heatmap: '',\n detail: {\n metrics: { mae: currentMae, sae: currentSae, misalignedCount: lastMisalignedCount },\n components: [],\n },\n },\n },\n };\n }\n } finally {\n // Cleanup: Stop dev server if it was started by this validation loop\n if (serverKey) {\n logger.printInfoLog('Cleaning up dev server...');\n const launchTool = new LaunchTool();\n await launchTool.stopDevServer(serverKey).catch((err: unknown) => {\n logger.printWarnLog(`Failed to stop dev server: ${err instanceof Error ? err.message : String(err)}`);\n });\n }\n }\n}\n","import { Agent } from 'evoltagent';\nimport type { ModelConfig } from 'evoltagent';\n\nimport { COMMIT_AGENT_SYSTEM_PROMPT } from './prompt';\nimport { getModelConfig } from '../../utils/config';\nimport { AGENT_CONTEXT_WINDOW_TOKENS, MAX_OUTPUT_TOKENS } from '../../constants';\n\nexport function createCommitAgent(): Agent {\n const modelConfig: ModelConfig = {\n ...getModelConfig(),\n contextWindowTokens: AGENT_CONTEXT_WINDOW_TOKENS,\n maxOutputTokens: MAX_OUTPUT_TOKENS,\n };\n\n return new Agent({\n name: 'CommitAgent',\n profile: 'A helpful assistant that commits local changes in a repository.',\n system: COMMIT_AGENT_SYSTEM_PROMPT,\n tools: ['GitTool.init', 'GitTool.status', 'GitTool.add', 'GitTool.diff', 'GitTool.commit'],\n modelConfig,\n verbose: 1,\n toolcallManagerPoolSize: 1,\n });\n}\n","/**\n * Git agent system prompt.\n */\nexport const COMMIT_AGENT_SYSTEM_PROMPT = `You are a Git automation agent for CodeRio validation workflow.\n\nInput format:\n- appPath: /absolute/path/to/app\n- iteration: number (optional; undefined means initial commit)\n\n<workflow>\n1. Validate repository:\n - Run GitTool.status(cwd=appPath)\n - If not a git repository, run GitTool.init(cwd=appPath), then re-run status\n\n2. Check for changes:\n - Run GitTool.diff(cwd=appPath) to see unstaged changes\n - If working tree is clean (no changes):\n * Stop and return: \"No changes to commit\"\n * DO NOT create an empty commit\n\n3. Stage all changes:\n - Run GitTool.add(files=\".\", cwd=appPath)\n\n4. Analyze changes and generate commit message:\n Run GitTool.diff(cwd=appPath) after staging to analyze what changed.\n\n Generate a conventional commit message following these rules:\n\n **Message format:**\n - If iteration is undefined: \"feat: [Initial] first commit\"\n - If iteration is defined: \"fix: [Iteration N] <description>\"\n\n **Description guidelines:**\n Analyze the diff to determine what type of changes were made:\n\n a) Component layout/style fixes:\n - Look for changes in component files (src/components/*.tsx, etc.)\n - Extract component names from file paths (e.g., src/components/Header.tsx → Header)\n - Format: \"fix misaligned components ComponentA, ComponentB\"\n - List up to 3 components, use \"and N more\" if more than 3\n - Example: \"fix: [Iteration 1] fix misaligned components Header, Footer, and 2 more\"\n\n b) Build/compilation error fixes:\n - Look for package.json changes → \"resolve dependency issues\"\n - Look for import/export errors → \"resolve import errors\"\n - Look for TypeScript errors → \"resolve type errors\"\n - Example: \"fix: [Iteration 2] resolve build error\"\n\n c) Mixed changes (both component fixes AND build fixes):\n - Prioritize component fixes in the message\n - Example: \"fix: [Iteration 1] fix misaligned components xxx and resolve yyy error\"\n\n5. Create commit:\n - Use temporary identity (do NOT modify global git config):\n * user.name = \"CodeRio\"\n * user.email = \"\"\n - Run GitTool.commit(message, cwd=appPath, config={...})\n</workflow>\n\n<example>\nExample tool call format:\n\nGitTool.commit({\n \"message\": \"feat: [Initial] generate webpage\",\n \"cwd\": \"/absolute/path/to/app\",\n \"config\": {\"user.name\": \"CodeRio\", \"user.email\": \"\"}\n})\n\nIMPORTANT: The config parameter must be a JSON object with keys like \"user.name\" and \"user.email\".\nDO NOT use XML-style tags like <user.name>CodeRio</user.name>.\n</example>\n\n<output>\nRespond with a short summary in <TaskCompletion> tags.\nInclude whether a commit was created and the final commit message.\n</output>`;\n","import type { CommitAgentParams } from './types';\n\nexport function formatGitCommitInstruction(params: CommitAgentParams): string {\n const { appPath, iteration } = params;\n\n return `appPath: ${appPath}\niteration: ${iteration ?? 'undefined'}\n\nTASK:\nCheck for changes and commit if there are any modifications in the app directory.`;\n}\n","import { createCommitAgent } from '../../../agents/commit-agent';\nimport { formatGitCommitInstruction } from '../../../agents/commit-agent/instruction';\nimport { logger } from '../../../utils/logger';\nimport type { GitCommitOptions, GitCommitResult } from '../types';\nimport path from 'path';\n\n/**\n * Public API: commit changes using commit agent.\n * Delegates to the commit-agent, passing appPath via instruction.\n */\nexport async function commit(options?: GitCommitOptions): Promise<GitCommitResult> {\n try {\n if (!options?.appPath) {\n throw new Error('commit() requires options.appPath');\n }\n\n const appPath = path.resolve(options.appPath);\n const agent = createCommitAgent();\n\n const instruction = formatGitCommitInstruction({\n appPath,\n iteration: options.iteration,\n });\n\n await agent.run(instruction);\n\n logger.printSuccessLog('Commit completed!');\n return {\n success: true,\n message: 'Commit workflow completed',\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.printErrorLog(`Commit failed: ${errorMessage}`);\n return {\n success: false,\n message: errorMessage,\n };\n }\n}\n","/**\n * Judger Agent: Layout error diagnosis specialist.\n *\n * Simplified actor-critic pattern with JSON output via post-processor.\n * Uses evoltjs Agent class for tool execution and Vision API support.\n */\n\nimport { Agent } from 'evoltagent';\nimport type { ModelConfig } from 'evoltagent';\n\nimport { HistoryTool } from '../../tools/history-tool';\nimport { HierarchyTool } from '../../tools/hierarchy-tool';\nimport type { ComponentHistory } from '../../types/validation-types';\nimport type { Dict } from '../../types/validation-types';\nimport { JUDGER_PROMPT } from './prompt';\nimport { getModelConfig } from '../../utils/config';\nimport { AGENT_CONTEXT_WINDOW_TOKENS, MAX_OUTPUT_TOKENS } from '../../constants';\nimport { parseJudgerResult, updateToolContext } from './utils';\n\n/**\n * Create judger agent (critic) with JSON output.\n *\n * @param options - Configuration options\n * @param options.workspaceDir - Optional workspace directory to restrict file access\n * @param options.structureTree - Component hierarchy tree\n * @param options.componentPaths - Mapping from component_id to filesystem path\n * @param options.history - Component history from previous iterations\n * @returns Agent configured with FileEditor, ThinkTool, HierarchyTool, HistoryTool, and JSON post-processor\n */\nexport function createJudgerAgent(options: {\n workspaceDir?: string;\n structureTree?: Dict;\n componentPaths?: Record<string, string>;\n history?: ComponentHistory;\n}): Agent {\n const { workspaceDir, structureTree, componentPaths, history } = options;\n\n let systemPrompt = JUDGER_PROMPT;\n if (workspaceDir) {\n systemPrompt += `\\n\\nWORKSPACE: ${workspaceDir}\\nOnly access files within this workspace.`;\n }\n\n // System tools (string-based, globally registered)\n const systemTools: string[] = ['FileEditor.read', 'FileEditor.find'];\n\n // Update HierarchyTool instance context if structure provided\n // Tools are already registered via @tools decorator - just update execute methods\n if (structureTree) {\n const hierarchyTool = new HierarchyTool();\n hierarchyTool.setContext(structureTree, componentPaths || {});\n\n const hierarchyToolNames = updateToolContext(\n hierarchyTool as unknown as Record<string, (...args: unknown[]) => Promise<string>>,\n 'HierarchyTool',\n ['lookup', 'getSharedInstances']\n );\n systemTools.push(...hierarchyToolNames);\n }\n\n // Always register HistoryTool (even with empty history in iteration 1)\n // The tool handles empty history gracefully and the prompt references it\n const historyTool = new HistoryTool();\n historyTool.setContext(history || {});\n\n const historyToolNames = updateToolContext(\n historyTool as unknown as Record<string, (...args: unknown[]) => Promise<string>>,\n 'HistoryTool',\n ['getComponentHistory', 'getIterationSummary']\n );\n systemTools.push(...historyToolNames);\n\n const modelConfig: ModelConfig = {\n ...getModelConfig(),\n contextWindowTokens: AGENT_CONTEXT_WINDOW_TOKENS,\n maxOutputTokens: MAX_OUTPUT_TOKENS,\n stream: true,\n };\n\n return new Agent({\n name: 'JudgerAgent',\n profile: 'Layout diagnosis specialist',\n system: systemPrompt,\n tools: systemTools,\n modelConfig,\n postProcessor: parseJudgerResult,\n verbose: 2,\n });\n}\n","/**\n * Iteration history lookup tool for judger agent.\n *\n * Provides methods to query the history of component positions and fixes\n * across validation iterations.\n */\n\nimport { tools } from 'evoltagent';\nimport type { IterationSummaryChange } from './types';\nimport type { ComponentHistory } from '../../types/validation-types';\n\n/**\n * Iteration history lookup tool.\n *\n * This tool allows agents to understand the history of component positions\n * and fixes across validation iterations, helping to avoid repeating failed\n * fixes and detecting regressions.\n */\n@tools({\n getComponentHistory: {\n description:\n \"Get position and fix history for a component. Shows how the component's position and error evolved across iterations, and what fixes were applied. Helps identify if previous fixes helped or hurt\",\n params: [{ name: 'componentId', type: 'string', description: 'Component ID to get history for' }],\n returns: { type: 'string', description: 'Formatted string with complete history of positions, errors, and fixes' },\n examples: [\n `<HistoryTool.getComponentHistory>\n<componentId>HeroSection</componentId>\n</HistoryTool.getComponentHistory>`,\n ],\n },\n getIterationSummary: {\n description:\n 'Get summary of what was changed in a specific iteration. Shows all components that were fixed in that iteration and what fixes were applied. Useful for understanding what went wrong in a previous iteration',\n params: [{ name: 'iteration', type: 'number', description: 'Iteration number (1-indexed)' }],\n returns: { type: 'string', description: 'Formatted string with summary of changes in that iteration' },\n examples: [\n `<HistoryTool.getIterationSummary>\n<iteration>2</iteration>\n</HistoryTool.getIterationSummary>`,\n ],\n },\n})\nexport class HistoryTool {\n private _history: ComponentHistory = {};\n\n /**\n * Initialize with component history from previous iterations.\n *\n * @param history - Dict mapping component_id to list of iteration records\n */\n setContext(history: ComponentHistory): void {\n this._history = history;\n }\n\n /**\n * Get position and fix history for a component.\n *\n * Shows how the component's position and error evolved across iterations,\n * and what fixes were applied. Helps identify if previous fixes helped or hurt.\n *\n * @param componentId - Component ID to get history for\n * @returns Formatted string with complete history of positions, errors, and fixes\n */\n getComponentHistory(componentId: string): string {\n if (!this._history || Object.keys(this._history).length === 0) {\n return 'No history available (this is iteration 1)';\n }\n\n if (!(componentId in this._history)) {\n return `No history found for component '${componentId}' (first time misaligned)`;\n }\n\n const historyEntries = this._history[componentId];\n if (!historyEntries || historyEntries.length === 0) {\n return `Empty history for component '${componentId}'`;\n }\n\n const lines: string[] = [`History for ${componentId}:`, ''];\n\n for (let i = 0; i < historyEntries.length; i++) {\n const entry = historyEntries[i];\n if (!entry) continue;\n const iteration = entry.iteration ?? '?';\n const position = entry.position ?? [0, 0];\n const error = entry.error ?? [0, 0];\n const fixApplied = entry.fixApplied ? entry.fixApplied.join('\\n ') : 'None';\n\n lines.push(`Iteration ${iteration}:`);\n lines.push(` Position: (${position[0].toFixed(1)}, ${position[1].toFixed(1)}) px`);\n lines.push(` Error: (${error[0].toFixed(1)}, ${error[1].toFixed(1)}) px`);\n lines.push(` Fix Applied:\\n ${fixApplied}`);\n\n if (i > 0) {\n const prevEntry = historyEntries[i - 1];\n if (prevEntry) {\n const prevErrorMagnitude = prevEntry.error[0] + prevEntry.error[1];\n const currErrorMagnitude = error[0] + error[1];\n if (currErrorMagnitude > prevErrorMagnitude) {\n lines.push(\n ` Warning: REGRESSION: Error increased from ${prevErrorMagnitude.toFixed(1)}px to ${currErrorMagnitude.toFixed(1)}px`\n );\n }\n }\n }\n\n lines.push('');\n }\n\n return lines.join('\\n');\n }\n\n /**\n * Get summary of what was changed in a specific iteration.\n *\n * Shows all components that were fixed in that iteration and what fixes\n * were applied. Useful for understanding what went wrong in a previous iteration.\n *\n * @param iteration - Iteration number (1-indexed)\n * @returns Formatted string with summary of changes in that iteration\n */\n getIterationSummary(iteration: number): string {\n if (!this._history || Object.keys(this._history).length === 0) {\n return `No history available (iteration ${iteration} has not completed yet)`;\n }\n\n const changes: IterationSummaryChange[] = [];\n\n for (const [componentId, entries] of Object.entries(this._history)) {\n for (const entry of entries) {\n if (entry.iteration === iteration) {\n changes.push({\n componentId,\n position: entry.position ?? [0, 0],\n error: entry.error ?? [0, 0],\n fixApplied: entry.fixApplied ?? ['None'],\n });\n break;\n }\n }\n }\n\n if (changes.length === 0) {\n return `No changes recorded for iteration ${iteration}`;\n }\n\n const lines: string[] = [`Iteration ${iteration} Summary:`, `Total components modified: ${changes.length}`, ''];\n\n for (const change of changes) {\n lines.push(`${change.componentId}:`);\n lines.push(` Error: (${change.error[0].toFixed(1)}, ${change.error[1].toFixed(1)}) px`);\n lines.push(` Fix:\\n ${change.fixApplied.join('\\n ')}`);\n lines.push('');\n }\n\n return lines.join('\\n');\n }\n}\n","/**\n * Component hierarchy lookup tool for judger agent.\n *\n * Provides methods to query the component structure tree for parent-child\n * relationships, siblings, and shared component instances.\n */\n\nimport { tools } from 'evoltagent';\nimport { findInTree, getNodeId } from '../../nodes/validation/utils/tree/tree-traversal';\nimport type { ComponentPaths, HierarchyNode, ParentInfo } from './types';\n\n/**\n * Component hierarchy lookup tool.\n *\n * This tool allows agents to understand the component tree structure,\n * find parents, siblings, and children, and identify shared component instances.\n */\n@tools({\n lookup: {\n description:\n 'Get file path, parent, siblings, and children for a component. Use this to find the correct file path before reading component files.',\n params: [{ name: 'componentId', type: 'string', description: 'Component ID to look up' }],\n returns: { type: 'string', description: 'Formatted string with file path, parent (with its file path), siblings, and children' },\n examples: [\n `<HierarchyTool.lookup>\n<componentId>HeroSection</componentId>\n</HierarchyTool.lookup>`,\n ],\n },\n getSharedInstances: {\n description:\n 'Find all component instances using a specific file path. Useful for identifying which components share the same implementation file (e.g., StartButton and ApiButton both using button/index.tsx). ALWAYS check this before editing a shared file.',\n params: [{ name: 'filePath', type: 'string', description: 'Filesystem path to search for (can be relative or absolute)' }],\n returns: { type: 'string', description: 'Formatted string with all component instances using the file' },\n examples: [\n `<HierarchyTool.getSharedInstances>\n<filePath>button/index.tsx</filePath>\n</HierarchyTool.getSharedInstances>`,\n ],\n },\n})\nexport class HierarchyTool {\n private _structureTree: HierarchyNode = {};\n private _componentPaths: ComponentPaths = {};\n\n constructor() {\n this._structureTree = {};\n this._componentPaths = {};\n }\n\n /**\n * Initialize with page structure and path mapping.\n */\n setContext(structureTree: HierarchyNode, componentPaths: ComponentPaths): void {\n this._structureTree = structureTree;\n this._componentPaths = componentPaths;\n }\n\n lookup(componentId: string): string {\n const node = findInTree(this._structureTree, componentId);\n if (!node) {\n return `Component '${componentId}' not found in structure tree`;\n }\n\n const parentInfo = this._findParent(this._structureTree, componentId);\n const parentStr = parentInfo ? `Parent: ${parentInfo.id}` : 'Parent: None (root component)';\n\n // Include parent file path if available (helps agent read parent files without guessing paths)\n const parentPathStr =\n parentInfo && this._componentPaths[parentInfo.id] ? `Parent File: ${this._componentPaths[parentInfo.id]}` : '';\n\n let siblings: string[] = [];\n if (parentInfo) {\n const parentNode = findInTree(this._structureTree, parentInfo.id);\n if (parentNode) {\n const children = (parentNode.children as HierarchyNode[]) || [];\n siblings = children.map(child => getNodeId(child)).filter((id): id is string => id !== undefined && id !== componentId);\n }\n }\n const siblingsStr = siblings.length > 0 ? `Siblings: ${siblings.join(', ')}` : 'Siblings: None';\n\n const nodeChildren = (node.children as HierarchyNode[]) || [];\n const children = nodeChildren.map(child => getNodeId(child)).filter((id): id is string => id !== undefined);\n const childrenStr = children.length > 0 ? `Children: ${children.join(', ')}` : 'Children: None';\n\n // Include file path for this component\n const filePath = this._componentPaths[componentId];\n const fileStr = filePath ? `File: ${filePath}` : '';\n\n const lines = [`Component: ${componentId}`, fileStr, parentStr, parentPathStr, siblingsStr, childrenStr].filter(Boolean);\n\n return lines.join('\\n');\n }\n\n getSharedInstances(filePath: string): string {\n const instances: string[] = [];\n for (const [compId, compPath] of Object.entries(this._componentPaths)) {\n if (compPath.includes(filePath) || compPath.endsWith(filePath)) {\n instances.push(compId);\n }\n }\n\n if (instances.length === 0) {\n return `No components found using file: ${filePath}`;\n }\n\n const instancesList = instances.map(inst => ` - ${inst}`).join('\\n');\n return `Components using ${filePath}:\n${instancesList}\n\nWarning: Changes to this file will affect ALL ${instances.length} instance(s)`;\n }\n\n private _findParent(node: HierarchyNode, targetId: string, parent: HierarchyNode | null = null): ParentInfo | undefined {\n const nodeId = getNodeId(node);\n if (nodeId === targetId) {\n if (parent) {\n const parentId = getNodeId(parent);\n if (parentId) {\n return { id: parentId };\n }\n }\n return undefined;\n }\n\n const children = (node.children as HierarchyNode[]) || [];\n for (const child of children) {\n const result = this._findParent(child, targetId, node);\n if (result !== undefined) {\n return result;\n }\n }\n\n return undefined;\n }\n}\n","/**\n * Generic tree traversal utilities for nested dict/list structures.\n */\n\nimport type { Dict } from '../../../../types/validation-types';\n\n/**\n * Get node ID, trying componentId first, then id.\n */\nexport function getNodeId(node: Dict): string | undefined {\n return (node?.componentId as string) || (node?.id as string) || undefined;\n}\n\n/**\n * Generic recursive search through any dict/list structure to find node by ID.\n *\n * This function can search through Figma JSON, structure trees, or any nested data.\n */\nexport function findInTree(data: unknown, targetId: string, idKeys: string[] = ['id', 'componentId']): Dict | undefined {\n if (data === null || data === undefined) {\n return undefined;\n }\n\n if (typeof data === 'object' && !Array.isArray(data)) {\n const dict = data as Dict;\n for (const idKey of idKeys) {\n if (dict[idKey] === targetId) {\n return dict;\n }\n }\n for (const value of Object.values(dict)) {\n const result = findInTree(value, targetId, idKeys);\n if (result) {\n return result;\n }\n }\n } else if (Array.isArray(data)) {\n for (const item of data) {\n const result = findInTree(item, targetId, idKeys);\n if (result) {\n return result;\n }\n }\n }\n\n return undefined;\n}\n","/**\n * Judger agent system prompt.\n * Defines the diagnosis workflow, available tools, and output format.\n */\nexport const JUDGER_PROMPT = `You are a React Layout Diagnosis Expert. Analyze position misalignments and provide precise fix instructions.\n\n<workflow>\n1. Check HistoryTool.getComponentHistory - avoid repeating failed fixes\n2. Use HierarchyTool.lookup to get component file path, parent, siblings, and children\n3. Use FileEditor.read to examine code, FileEditor.find to locate patterns\n4. For parent fixes: HierarchyTool.lookup returns parent file path - use it directly\n5. Before editing shared files: Use HierarchyTool.getSharedInstances to check impact\n6. If image provided: previous iteration\n7. Respond with JSON diagnosis wrapped in \\`\\`\\`json\\`\\`\\`\n</workflow>\n\n<error_types>\n- pixel_misalignment: Wrong spacing values (gap-2 vs gap-4, mt-[20px] vs mt-[50px])\n- positioning_strategy: Wrong layout method (absolute vs flex, wrong parent)\n- parent_spacing: Parent gap/padding causes child misalignment\n- sibling_cascade: Sibling margin shifts others (fix topmost only)\n- none: Position already correct\n</error_types>\n\n<rules>\nCRITICAL CONSTRAINTS:\n1. Fix POSITION only (x,y) - validation does NOT measure dimensions\n2. FORBIDDEN: w-*, h-*, max-w-*, max-h-*, min-w-*, min-h-*, aspect-*, flex-row, flex-col\n3. ALLOWED: mt-*, mb-*, ml-*, mr-*, pt-*, pb-*, pl-*, pr-*, gap-*, space-*, top-*, left-*, right-*, bottom-*, translate-*\n\nFLEX LAYOUT (prevents MAE oscillation):\n- Adding mt-[X] to component A shifts ALL siblings below by X pixels (additive effect)\n- For sibling components: Fix ONLY the topmost misaligned one per iteration (topmost = first in DOM order)\n- For other siblings: Set refineInstructions to [] with rootCause: \"Fix deferred - waiting for topmost sibling fix to propagate\"\n- Prefer parent gap/padding over child margins\n- If component oscillates \"too high\" ↔ \"too low\" → fix parent or topmost sibling instead\n\nSPECIAL CASES:\n- Already correct: errorType=\"none\", refineInstructions=[]\n- Wrong dimensions/flex-direction: Note in rootCause but do NOT fix\n- Wrong X (x=0 vs x=320): Check parent centering, do NOT change w-full to w-[640px]\n</rules>\n\n<output_format>\nReturn JSON with camelCase fields: errorType, rootCause, visualEvidence, codeEvidence, refineInstructions, toolsUsed\n\nrefineInstructions format: \"In [FULL_PATH] line [N], change '[OLD_CODE]' to '[NEW_CODE]'\"\n- Use EXACT code strings from FileEditor.read (copy-paste)\n- OLD_CODE ≠ NEW_CODE (never \"keep unchanged\")\n- Check HierarchyTool.getSharedInstances before editing shared files\n\nWrap output:\n<TaskCompletion>\n\\`\\`\\`json\n{your json here}\n\\`\\`\\`\n</TaskCompletion>\n</output_format>\n\n<example>\n<TaskCompletion>\n\\`\\`\\`json\n{\n \"errorType\": \"pixel_misalignment\",\n \"rootCause\": \"Gap is 8px but should be 16px\",\n \"visualEvidence\": \"Elements too close in screenshot\",\n \"codeEvidence\": \"Line 23: className='flex gap-2'\",\n \"refineInstructions\": [\"In /path/Card.tsx line 23, change 'gap-2' to 'gap-4'\"],\n \"toolsUsed\": [\"FileEditor.read\", \"HistoryTool.getComponentHistory\"]\n}\n\\`\\`\\`\n</TaskCompletion>\n</example>\n`;\n","/**\n * Utility functions for Judger Agent.\n */\n\nimport { SystemToolStore, FunctionCallingStore } from 'evoltagent';\nimport type { JudgerDiagnosis } from './types';\nimport { logger } from '../../utils/logger';\n\n/**\n * Extract JSON diagnosis from agent response.\n * @param response - Agent response text (with TaskCompletion tags already stripped)\n * @returns Parsed JudgerDiagnosis object\n */\nexport function parseJudgerResult(response: string): Promise<JudgerDiagnosis> {\n // Check for empty response (agent may have hit limits or errors)\n if (!response || response.trim().length === 0) {\n logger.printInfoLog('Judger agent returned empty response, skipping refinement for this iteration');\n return Promise.resolve({\n errorType: 'pixel_misalignment',\n rootCause: 'Agent analysis unavailable, do not apply any edits',\n visualEvidence: 'N/A',\n codeEvidence: 'N/A',\n refineInstructions: [],\n toolsUsed: [],\n });\n }\n\n // Extract JSON from markdown code block\n // The evoltagent library strips <TaskCompletion> tags before calling postProcessor\n const jsonMatch = response.match(/```json\\n([\\s\\S]*?)\\n```/);\n\n if (!jsonMatch) {\n logger.printInfoLog('Judger agent response missing JSON block, skipping refinement for this iteration');\n return Promise.resolve({\n errorType: 'empty_response',\n rootCause: 'Agent analysis unavailable, do not apply any edits',\n visualEvidence: 'N/A',\n codeEvidence: 'N/A',\n refineInstructions: [],\n toolsUsed: [],\n });\n }\n\n const jsonStr = jsonMatch[1];\n\n if (!jsonStr || jsonStr.trim().length === 0) {\n logger.printInfoLog('Judger agent response has empty JSON, skipping refinement for this iteration');\n return Promise.resolve({\n errorType: 'empty_response',\n rootCause: 'Agent analysis unavailable, do not apply any edits',\n visualEvidence: 'N/A',\n codeEvidence: 'N/A',\n refineInstructions: [],\n toolsUsed: [],\n });\n }\n\n try {\n return Promise.resolve(JSON.parse(jsonStr) as JudgerDiagnosis);\n } catch (error) {\n logger.printInfoLog(`Judger agent response JSON parse failed: ${error instanceof Error ? error.message : String(error)}`);\n return Promise.resolve({\n errorType: 'empty_response',\n rootCause: 'Agent analysis unavailable',\n visualEvidence: 'N/A',\n codeEvidence: 'N/A',\n refineInstructions: [],\n toolsUsed: [],\n });\n }\n}\n\n/**\n * Update tool instance context for already-registered tools.\n *\n * Since tools are registered via @tools decorator at module load time,\n * we only need to update their execute methods to point to instances\n * with the correct per-execution context.\n *\n * @param toolInstance - Tool instance with context set via setContext()\n * @param toolName - Base name for the tool (e.g., \"HierarchyTool\")\n * @param methodNames - List of method names to update (e.g., [\"lookup\", \"getSiblings\"])\n * @returns List of updated tool name strings (e.g., [\"HierarchyTool.lookup\"])\n */\nexport function updateToolContext(\n toolInstance: Record<string, (...args: unknown[]) => Promise<string>>,\n toolName: string,\n methodNames: string[]\n): string[] {\n const updatedNames: string[] = [];\n\n for (const methodName of methodNames) {\n const raw = toolInstance[methodName];\n if (!raw) {\n continue;\n }\n\n const method = raw.bind(toolInstance);\n const fullName = `${toolName}.${methodName}`;\n\n // Tool should already be registered via @tools decorator - just update execute method\n const systemTool = SystemToolStore.getTool(fullName);\n if (systemTool) {\n systemTool.execute = method;\n updatedNames.push(fullName);\n }\n\n // Also update FunctionCallingStore\n const functionCallingName = `${toolName}-${methodName}`;\n const userTool = FunctionCallingStore.getTool(functionCallingName);\n if (userTool) {\n userTool.execute = method;\n }\n }\n\n return updatedNames;\n}\n","import type { MisalignedComponent } from '../../types/validation-types';\n\n/**\n * Format judger instruction with component info and Figma metadata\n */\nexport function formatJudgerInstruction(\n component: MisalignedComponent,\n figmaMetadata: Record<string, unknown>,\n componentPaths?: Record<string, string>\n): string {\n const vr = component.validationReport;\n const validationReportFormatted = `Current Position: (${vr.currentPosition[0].toFixed(1)}, ${vr.currentPosition[1].toFixed(1)}) px\nTarget Position: (${vr.targetPosition[0].toFixed(1)}, ${vr.targetPosition[1].toFixed(1)}) px\nAbsolute Error: (${vr.absoluteError[0].toFixed(1)}, ${vr.absoluteError[1].toFixed(1)}) px`;\n\n const padding = figmaMetadata.padding as { left?: number; top?: number; right?: number; bottom?: number } | undefined;\n const layoutMode = typeof figmaMetadata.layoutMode === 'string' ? figmaMetadata.layoutMode : 'NONE';\n const itemSpacing = typeof figmaMetadata.itemSpacing === 'number' ? figmaMetadata.itemSpacing : 0;\n const primaryAxisAlignItems = typeof figmaMetadata.primaryAxisAlignItems === 'string' ? figmaMetadata.primaryAxisAlignItems : 'N/A';\n const counterAxisAlignItems = typeof figmaMetadata.counterAxisAlignItems === 'string' ? figmaMetadata.counterAxisAlignItems : 'N/A';\n // componentPaths should always be provided with absolute filesystem paths\n const resolvedPath = componentPaths?.[component.componentId];\n if (!resolvedPath) {\n throw new Error(`Component ${component.componentId} not found in componentPaths mapping`);\n }\n\n return `Component ID: ${component.componentId}\nElement IDs: ${JSON.stringify(component.elementIds)}\nFile: ${resolvedPath}\n\nValidation Report:\n${validationReportFormatted}\n\nFigma Layout:\n- Mode: ${layoutMode}\n- Item Spacing: ${itemSpacing}px\n- Padding: ${padding?.left ?? 0}px (left) ${padding?.top ?? 0}px (top) ${padding?.right ?? 0}px (right) ${padding?.bottom ?? 0}px (bottom)\n- Primary Axis Alignment: ${primaryAxisAlignItems}\n- Counter Axis Alignment: ${counterAxisAlignItems}\n\nTASK:\n1. Read component file at: ${resolvedPath}\n2. Identify the layout error by comparing code with Figma metadata\n3. Locate exact code patterns with FileEditor.find\n4. Output JSON diagnosis with precise refine_instructions\n\nIMPORTANT:\n- Use FileEditor.read(\"${resolvedPath}\") to read the component code\n- The path is an absolute filesystem path (e.g., /workspace/src/components/button/index.tsx)\n- When using HierarchyTool.lookup or related tools, use the Component ID: ${component.componentId}\n\nRemember: Use exact code strings and line numbers in refine_instructions.\n`;\n}\n","/**\n * Refiner Agent: Code editor specialist.\n *\n * Simplified actor-critic pattern with structured output via post-processor.\n * Uses evoltjs Agent class for file editing tools.\n */\n\nimport { Agent } from 'evoltagent';\nimport type { ModelConfig } from 'evoltagent';\n\nimport { REFINER_PROMPT } from './prompt';\nimport { getModelConfig } from '../../utils/config';\nimport { AGENT_CONTEXT_WINDOW_TOKENS, MAX_OUTPUT_TOKENS } from '../../constants';\nimport { parseRefinerResult } from './utils';\nexport { formatRefinerInstruction } from './instruction';\n\n/**\n * Create refiner agent (actor) for applying fixes.\n *\n * @param workspaceDir - Optional workspace directory to restrict file access\n * @returns Agent configured with FileEditor tools and structured output\n */\nexport function createRefinerAgent(workspaceDir?: string): Agent {\n let systemPrompt = REFINER_PROMPT;\n if (workspaceDir) {\n systemPrompt += `\\n\\nWORKSPACE: ${workspaceDir}\\nOnly modify files within this workspace.`;\n }\n\n const modelConfig: ModelConfig = {\n ...getModelConfig(),\n contextWindowTokens: AGENT_CONTEXT_WINDOW_TOKENS,\n maxOutputTokens: MAX_OUTPUT_TOKENS,\n stream: true,\n };\n\n return new Agent({\n name: 'RefinerAgent',\n profile: 'Code editor specialist',\n system: systemPrompt,\n tools: ['FileEditor.read', 'FileEditor.find', 'FileEditor.findAndReplace'],\n modelConfig,\n postProcessor: parseRefinerResult,\n verbose: 2,\n });\n}\n","/**\n * Refiner agent system prompt.\n * Defines the workflow for applying fixes from judger's diagnosis.\n */\nexport const REFINER_PROMPT = `You are a React Code Editor. Apply fixes from judger's diagnosis.\n\n<workflow>\n1. For each refineInstruction, parse format: \"In [path] line [N], change '[old]' to '[new]'\"\n2. VALIDATE before executing:\n - Skip if instruction says \"keep unchanged\", \"no change needed\", or lacks specific code\n - Skip if OLD and NEW are identical\n - Skip if OLD or NEW is empty\n - Skip if instruction is vague like \"apply fix in parent\" without specific code\n3. Read file with FileEditor.read to verify the OLD pattern exists\n4. Use FileEditor.findAndReplace(path, pattern=old, replacement=new)\n - IMPORTANT: Escape special regex chars in pattern: [ ] ( ) . * + ? $ ^ | \\\\\n - Example: \"mt-[20px]\" → pattern=\"mt-\\\\[20px\\\\]\"\n5. Report results\n</workflow>\n\n<validation_rules>\nSKIP instructions that:\n- Contain \"keep unchanged\" or \"no change needed\"\n- Don't have both '[old]' and '[new]' quoted strings\n- Have identical old and new values\n- Are vague suggestions without specific code\n\nALWAYS escape regex special characters in the pattern parameter:\n- Brackets: [ → \\\\[, ] → \\\\]\n- Parentheses: ( → \\\\(, ) → \\\\)\n- Other: . * + ? $ ^ | → prefix with \\\\\n</validation_rules>\n\n<output>\nAfter edits, respond with a summary:\n- \"Successfully applied: [description]\" (per success)\n- \"Failed to apply: [description]\" (per failure)\n- \"Skipped: [description]\" (for invalid instructions)\n\nWrap summary in <TaskCompletion> tags:\n<TaskCompletion>\n[Your summary here]\n</TaskCompletion>\n</output>\n`;\n","/**\n * Utility functions for Refiner Agent.\n */\n\nimport type { RefinerResult } from './types';\n\n/**\n * Extract refiner result from agent response.\n * @param response - Agent response text (with TaskCompletion tags already stripped)\n * @returns Parsed RefinerResult object\n */\nexport function parseRefinerResult(response: string): Promise<RefinerResult> {\n // The evoltagent library strips <TaskCompletion> tags before calling postProcessor\n const fullResponse = response.trim();\n\n // Extract summary lines (Successfully applied, Failed to apply, Skipped)\n const lines = fullResponse.split('\\n');\n const summaryLines: string[] = [];\n\n for (const line of lines) {\n const trimmedLine = line.trim();\n if (\n trimmedLine.startsWith('Successfully applied:') ||\n trimmedLine.startsWith('Failed to apply:') ||\n trimmedLine.startsWith('Skipped:')\n ) {\n summaryLines.push(trimmedLine);\n }\n }\n\n // Use summary lines array, or wrap full response if no summary lines found\n const summary = summaryLines.length > 0 ? summaryLines : [fullResponse];\n\n const summaryText = summary.join(' ').toLowerCase();\n const successCount = (summaryText.match(/successfully applied:/g) || []).length;\n const failedCount = (summaryText.match(/failed to apply:/g) || []).length;\n\n return Promise.resolve({\n success: successCount > 0 && failedCount === 0,\n summary,\n editsApplied: successCount,\n error: failedCount > 0 ? `${failedCount} edit(s) failed` : undefined,\n });\n}\n","import type { JudgerDiagnosis } from '../judger-agent/types';\nimport type { MisalignedComponent } from '../../types/validation-types';\n\n/**\n * Format refiner instruction with diagnosis and fix instructions\n */\nexport function formatRefinerInstruction(\n component: MisalignedComponent,\n diagnosis: JudgerDiagnosis,\n componentPaths?: Record<string, string>\n): string {\n // Use resolved absolute path from componentPaths, which should always be provided\n const resolvedPath = componentPaths?.[component.componentId];\n if (!resolvedPath) {\n throw new Error(`Component ${component.componentId} not found in componentPaths mapping`);\n }\n\n const refineInstructionsList = (diagnosis.refineInstructions || []).map((instr, i) => `${i + 1}. ${instr}`).join('\\n');\n\n return `Component ID: ${component.componentId}\nElement IDs: ${JSON.stringify(component.elementIds)}\nFile: ${resolvedPath}\n\nDiagnosis from judger:\n${JSON.stringify(diagnosis, null, 2)}\n\nTASK:\nApply each refineInstruction:\n${refineInstructionsList}\n\nFor each instruction:\n1. Parse the old_code and new_code\n2. Use FileEditor.findAndReplace to apply the change\n3. Report success or failure\n\nIMPORTANT:\n- The file path is an absolute filesystem path (e.g., /workspace/src/components/button/index.tsx)\n- Use this exact path with FileEditor tools\n`;\n}\n","import { Agent } from 'evoltagent';\nimport type { ModelConfig } from 'evoltagent';\nimport { LAUNCH_AGENT_PROMPT } from './prompt';\nimport { getModelConfig } from '../../utils/config';\nimport { AGENT_CONTEXT_WINDOW_TOKENS, MAX_OUTPUT_TOKENS } from '../../constants';\nimport { parseLaunchResult } from './utils';\n\nexport { launchAgentInstruction } from './instruction';\nexport type { LaunchAgentResult } from './types';\n\nexport function createLaunchAgent(): Agent {\n const modelConfig: ModelConfig = {\n ...getModelConfig(),\n contextWindowTokens: AGENT_CONTEXT_WINDOW_TOKENS,\n maxOutputTokens: MAX_OUTPUT_TOKENS,\n };\n\n return new Agent({\n name: 'LaunchAgent',\n profile: 'Expert DevOps and Frontend Engineer specialist in launching projects and troubleshooting build/runtime issues.',\n system: LAUNCH_AGENT_PROMPT,\n tools: [\n 'CommandLineTool.execute',\n 'CommandLineTool.list',\n 'CommandLineTool.stop',\n 'LaunchTool.startDevServer',\n 'LaunchTool.stopDevServer',\n 'FileEditor.read',\n 'FileEditor.find',\n 'FileEditor.findAndReplace',\n 'FileEditor.write',\n ],\n modelConfig,\n verbose: 2,\n postProcessor: parseLaunchResult,\n });\n}\n","export const LAUNCH_AGENT_PROMPT = `\n <task_goal>\n Prepare project for validation: install dependencies (if needed), build, fix errors, start dev server.\n Return server metadata for validation loop to use.\n </task_goal>\n\n <workflow>\n Follow steps IN ORDER. Repeat Step 2-3 until build succeeds, then proceed to Step 4.\n\n Step 1: Install Dependencies (Conditional)\n - Check instruction for skipInstall directive\n - If \"Skip Step 1\" appears in instruction: Skip to Step 2\n - Otherwise: Execute \"pnpm i\" in appPath\n - Parameters: CommandLineTool.execute(command=\"pnpm i\", cwd=appPath, timeoutMs=180000)\n - Verify exitCode === 0 before proceeding\n - If installation fails, analyze the error output and fix issues before proceeding\n\n Step 2: Build Project\n - Execute: CommandLineTool.execute(command=\"npm run build\", cwd=appPath, timeoutMs=180000)\n - Captures all compilation errors in output\n\n Step 3: Fix Compilation Errors (If exitCode !== 0)\n - Analyze error messages in 'error' and 'output' fields\n - Use FileEditor.read to examine problematic files\n - Use FileEditor.write to fix ONLY the specific broken lines\n - CRITICAL: Do NOT delete or rewrite entire files. Do NOT simplify complex CSS or logic.\n - Return to Step 2 and rebuild\n\n Step 4: Start Dev Server & Check Runtime Errors\n - Only proceed here when build is successful\n - Execute: LaunchTool.startDevServer(appPath=appPath, runCommand=\"npm run dev\", timeoutMs=60000)\n - Returns JSON: { success, url, port, serverKey, outputTail }\n - Parse and check outputTail for runtime error patterns EVEN IF success=true:\n * \"Module not found\", \"Cannot find module\"\n * \"SyntaxError\", \"TypeError\", \"ReferenceError\"\n * \"Failed to compile\", \"Unhandled Runtime Error\"\n - If errors found: Fix using FileEditor, then restart Step 2\n * CRITICAL: Do NOT delete or rewrite entire files. Do NOT simplify complex CSS or logic.\n - If clean: Store serverKey, url, port and proceed to Step 5\n\n Step 5: Return Server Metadata\n - Format final response as:\n <TaskCompletion>\n \\`\\`\\`json\n {\n \"success\": true,\n \"serverKey\": \"launch:...\",\n \"url\": \"http://localhost:PORT\",\n \"port\": PORT,\n \"message\": \"Dev server started successfully\"\n }\n \\`\\`\\`\n </TaskCompletion>\n - On failure before server start:\n <TaskCompletion>\n \\`\\`\\`json\n { \"success\": false, \"error\": \"Description\" }\n \\`\\`\\`\n </TaskCompletion>\n </workflow>\n\n <principles>\n 1. STRICT CONTENT PRESERVATION (MANDATORY):\n - NEVER modify CSS/Style content (colors, layouts, animations, etc.). If a CSS error exists, only fix the import/path or a specific syntax typo.\n - NEVER modify or delete Image assets or their references.\n - NEVER modify the DOM structure or JSX layout (adding/removing tags, changing classNames).\n - NEVER replace file content with \"template\" or \"placeholder\" code.\n 2. ALLOWED CHANGES ONLY:\n - Fixing 'module not found' by installing missing packages or correcting import paths.\n - Fixing TypeScript/JavaScript syntax errors that prevent execution.\n - Fixing configuration issues (e.g., tailwind.config.js, tsconfig.json).\n 3. BUILD FIRST: Dev server must not start until build succeeds (exitCode === 0).\n 4. PORT CONSISTENCY: Always use LaunchTool.startDevServer() (workspace-preferred port, same port across runs).\n 5. RUNTIME VALIDATION: Check outputTail in Step 4 for runtime errors even if success=true.\n </principles>\n\n <available_tools>\n - FileEditor.read: Read file contents for analysis\n - FileEditor.write: Write file contents to fix errors\n - CommandLineTool.execute: Execute commands (pnpm i, npm run build only)\n - LaunchTool.startDevServer: Start dev server (returns JSON with serverKey/url/port/outputTail)\n - ThinkTool.execute: Think through complex problems\n </available_tools>\n`;\n","/**\n * Utility functions for Launch Agent.\n */\n\nimport type { LaunchAgentResult } from './types';\nimport { logger } from '../../utils/logger';\n\n/**\n * Extract launch result from agent response.\n * @param response - Agent response text (with TaskCompletion tags already stripped by evoltagent)\n * @returns Parsed LaunchAgentResult object\n */\nexport function parseLaunchResult(response: string): Promise<LaunchAgentResult> {\n // Check for empty response\n if (!response || response.trim().length === 0) {\n logger.printInfoLog('Launch agent returned empty response');\n return Promise.resolve({\n success: false,\n error: 'Agent returned empty response',\n });\n }\n\n // Extract JSON from markdown code block\n // The evoltagent library strips <TaskCompletion> tags before calling postProcessor\n const jsonMatch = response.match(/```json\\n([\\s\\S]*?)\\n```/);\n\n if (!jsonMatch) {\n logger.printInfoLog('Launch agent response missing JSON block');\n return Promise.resolve({\n success: false,\n error: 'No JSON code block found in agent response',\n });\n }\n\n const jsonStr = jsonMatch[1];\n\n if (!jsonStr || jsonStr.trim().length === 0) {\n logger.printInfoLog('Launch agent response has empty JSON');\n return Promise.resolve({\n success: false,\n error: 'Empty JSON content in code block',\n });\n }\n\n try {\n const parsed = JSON.parse(jsonStr) as LaunchAgentResult;\n\n // Validate required fields if success is true\n if (parsed.success === true && (!parsed.serverKey || !parsed.url || !parsed.port)) {\n logger.printInfoLog('Launch agent success response missing required fields');\n return Promise.resolve({\n success: false,\n error: 'Missing required fields (serverKey, url, or port)',\n });\n }\n\n return Promise.resolve(parsed);\n } catch (error) {\n logger.printInfoLog(`Launch agent response JSON parse failed: ${error instanceof Error ? error.message : String(error)}`);\n return Promise.resolve({\n success: false,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n}\n","import type { LaunchAgentParams } from './types';\n\nexport function launchAgentInstruction(params: LaunchAgentParams): string {\n const skipNote = params.skipDependencyInstall ? '\\n\\nNOTE: Skip Step 1 (Install Dependencies). Dependencies already installed.' : '';\n\n return `appPath: ${params.appPath}${skipNote}\n\nTASK:\nInstall dependencies, compile the project, fix any compilation errors, start the development server, and fix any runtime errors. The goal is to have a fully working, error-free project.`;\n}\n","import { createLaunchAgent, launchAgentInstruction, type LaunchAgentResult } from '../../../agents/launch-agent';\n\nexport interface LaunchConfig {\n /**\n * Skip dependency installation (pnpm i).\n * Set to true for iterations 2+ where dependencies haven't changed.\n */\n skipDependencyInstall?: boolean;\n}\n\nexport interface LaunchResult {\n success: boolean;\n message?: string;\n error?: string;\n // Server metadata from LaunchTool\n serverKey?: string;\n url?: string;\n port?: number;\n}\n\nexport const launch = async (appPath: string, config?: LaunchConfig): Promise<LaunchResult> => {\n if (!appPath) {\n throw new Error('appPath is required');\n }\n\n try {\n // Agent.run() returns the parsed LaunchAgentResult via postProcessor\n const agentResult = (await createLaunchAgent().run(\n launchAgentInstruction({\n appPath,\n skipDependencyInstall: config?.skipDependencyInstall,\n })\n )) as LaunchAgentResult;\n\n // If agent explicitly failed, return the error\n if (agentResult.success === false) {\n return {\n success: false,\n error: agentResult.error ?? 'Launch agent failed without error message',\n };\n }\n\n // postProcessor already validates serverKey, url, port are present when success=true\n // So we can safely return them here\n return {\n success: true,\n message: agentResult.message ?? 'Launch and quality assurance completed',\n serverKey: agentResult.serverKey,\n url: agentResult.url,\n port: agentResult.port,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n};\n","/**\n * Figma layout metadata extraction utilities.\n *\n * Extracts layout-related metadata from ValidationContext for agent reasoning.\n */\n\nimport type { FigmaLayoutMetadata } from '../../types';\nimport type { ValidationContext, ElementInfo } from '../../../../types/validation-types';\n\n/** Layout quality scores for different node types */\nconst LAYOUT_SCORES = {\n FRAME_WITH_LAYOUT: 4,\n NODE_WITH_LAYOUT: 3,\n GROUP: 2,\n DEFAULT: 1,\n} as const;\n\nfunction hasLayoutMode(element: ElementInfo): boolean {\n return element.layoutMode !== 'NONE' && element.layoutMode !== undefined;\n}\n\nfunction getLayoutScore(element: ElementInfo): number {\n if (element.type === 'FRAME' && hasLayoutMode(element)) {\n return LAYOUT_SCORES.FRAME_WITH_LAYOUT;\n }\n if (hasLayoutMode(element)) {\n return LAYOUT_SCORES.NODE_WITH_LAYOUT;\n }\n if (element.type === 'GROUP') {\n return LAYOUT_SCORES.GROUP;\n }\n return LAYOUT_SCORES.DEFAULT;\n}\n\nfunction findBestLayoutElement(elementIds: string[], context: ValidationContext): ElementInfo | undefined {\n let bestElement: ElementInfo | undefined;\n let bestScore = -1;\n\n for (const elemId of elementIds) {\n const element = context.elements.get(elemId);\n if (!element) continue;\n\n const score = getLayoutScore(element);\n if (score > bestScore) {\n bestScore = score;\n bestElement = element;\n if (score === LAYOUT_SCORES.FRAME_WITH_LAYOUT) break;\n }\n }\n\n return bestElement;\n}\n\n/**\n * Extract layout metadata from ValidationContext for a specific component.\n *\n * @param context - Unified validation context\n * @param elementIds - Pre-extracted element IDs for this component\n */\nexport function extractLayoutFromContext(context: ValidationContext, elementIds: string[]): FigmaLayoutMetadata {\n // Find best layout element from element IDs\n const element = elementIds.length > 0 ? findBestLayoutElement(elementIds, context) : undefined;\n\n if (!element) {\n return {\n layoutMode: 'NONE',\n primaryAxisAlignItems: 'N/A',\n counterAxisAlignItems: 'N/A',\n itemSpacing: 0,\n padding: { top: 0, right: 0, bottom: 0, left: 0 },\n constraints: {},\n absoluteBoundingBox: {},\n };\n }\n\n return {\n layoutMode: element.layoutMode ?? 'NONE',\n primaryAxisAlignItems: element.primaryAxisAlignItems ?? 'N/A',\n counterAxisAlignItems: element.counterAxisAlignItems ?? 'N/A',\n itemSpacing: element.itemSpacing ?? 0,\n padding: {\n top: element.paddingTop ?? 0,\n right: element.paddingRight ?? 0,\n bottom: element.paddingBottom ?? 0,\n left: element.paddingLeft ?? 0,\n },\n constraints: element.constraints ?? {},\n absoluteBoundingBox: {\n x: element.position.x,\n y: element.position.y,\n width: element.position.w,\n height: element.position.h,\n },\n };\n}\n","/**\n * Report subnode for validation loop.\n * Orchestrates report generation: validation results → userReport → HTML file.\n *\n * This is called at the END of validation-loop with pre-computed validation results.\n * Delegates to ReportTool for visualization and HTML generation.\n */\n\nimport { logger } from '../../../utils/logger';\nimport { ReportTool } from '../../../tools/report-tool';\nimport type { ReportOptions, ReportResult } from '../types';\n\n/**\n * Generate complete validation report: userReport structure + HTML file.\n * This is the single entry point for all reporting in the validation loop.\n */\nexport async function report(options: ReportOptions): Promise<ReportResult> {\n const tool = new ReportTool();\n\n try {\n // Step 1: Generate userReport with screenshots\n logger.printInfoLog('Generating validation report structure...');\n const reportResult = await tool.generateReport({\n validationResult: options.validationResult,\n figmaThumbnailUrl: options.figmaThumbnailUrl,\n cachedFigmaThumbnailBase64: options.cachedFigmaThumbnailBase64,\n designOffset: options.designOffset,\n outputDir: options.outputDir,\n serverUrl: options.serverUrl,\n savedRenderMarkedPath: options.savedRenderMarkedPath,\n savedTargetMarkedPath: options.savedTargetMarkedPath,\n });\n\n // Step 2: Generate HTML file from userReport\n logger.printInfoLog('Generating HTML report file...');\n const htmlResult = await tool.generateHtml(reportResult.userReport, options.outputDir);\n\n if (!htmlResult.success) {\n logger.printWarnLog(`Failed to generate HTML: ${htmlResult.error}`);\n return {\n success: false,\n error: htmlResult.error,\n userReport: reportResult.userReport,\n };\n }\n\n logger.printSuccessLog(`Report generated successfully: ${htmlResult.htmlPath}`);\n return {\n success: true,\n htmlPath: htmlResult.htmlPath,\n userReport: reportResult.userReport,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.printErrorLog(`Error generating report: ${errorMessage}`);\n\n // Fallback: Create minimal report\n const minimalReport = tool.createMinimalReport({\n serverUrl: options.serverUrl,\n figmaThumbnailUrl: options.figmaThumbnailUrl,\n mae: options.validationResult?.mae,\n sae: options.validationResult?.sae,\n });\n\n return {\n success: false,\n error: errorMessage,\n userReport: minimalReport,\n };\n }\n}\n","/**\n * Report generation tool for validation results.\n * Provides pure visualization and formatting.\n */\n\nimport * as fs from 'fs';\nimport * as fsPromises from 'fs/promises';\nimport * as path from 'path';\nimport { fileURLToPath } from 'url';\nimport { tools } from 'evoltagent';\n\nimport { logger } from '../../utils/logger';\nimport { VisualizationTool } from '../visualization-tool';\nimport type { MisalignedComponentData } from '../visualization-tool/types';\nimport type { UserReport } from '../../types/validation-types';\nimport type { ReportGenerationRequest, ReportGenerationResult, ErrorReportOptions, GenerateHtmlResult } from './types';\n\nexport type { ReportGenerationRequest, ReportGenerationResult, ErrorReportOptions, GenerateHtmlResult } from './types';\n\n@tools({\n generateReport: {\n description:\n 'Generate visual validation report structure from pre-computed validation results. Creates annotated screenshots, heatmap, and userReport structure.',\n params: [\n {\n name: 'request',\n type: 'object',\n description: 'ReportGenerationRequest with validationResult, figmaThumbnailUrl, serverUrl, outputDir, etc.',\n },\n ],\n returns: { type: 'object', description: 'ReportGenerationResult with userReport and misalignedCount' },\n },\n createMinimalReport: {\n description: 'Create a minimal user report for error scenarios without screenshots',\n params: [{ name: 'options', type: 'object', description: 'ErrorReportOptions with serverUrl, figmaThumbnailUrl, mae, sae' }],\n returns: { type: 'object', description: 'Minimal UserReport structure' },\n },\n generateHtml: {\n description: 'Generate standalone HTML report file from userReport with embedded data and inlined assets',\n params: [\n { name: 'userReport', type: 'object', description: 'UserReport data from validation with screenshots and metrics' },\n { name: 'outputDir', type: 'string', description: 'Output directory path for HTML file' },\n ],\n returns: { type: 'object', description: 'GenerateHtmlResult with success/htmlPath/error' },\n },\n})\nexport class ReportTool {\n /**\n * Generate visual validation report from validation results.\n *\n * This method ONLY does visualization and formatting:\n * - Loads saved annotated screenshots from last validation iteration (avoids port mismatch)\n * - Generates pixel difference heatmap\n * - Builds userReport structure\n *\n */\n async generateReport(request: ReportGenerationRequest): Promise<ReportGenerationResult> {\n logger.printInfoLog('\\nGenerating validation report...');\n\n const visualizationTool = new VisualizationTool();\n const { validationResult } = request;\n\n // Prepare output directory\n const comparisonDir = path.join(request.outputDir, 'comparison_screenshots');\n if (!fs.existsSync(comparisonDir)) {\n fs.mkdirSync(comparisonDir, { recursive: true });\n }\n\n // Transform validation data to visualization format\n const misalignedData = visualizationTool['formatForVisualization'](validationResult.misalignedComponents);\n logger.printInfoLog(`Final misaligned components: ${misalignedData.length}`);\n\n // Load saved annotated screenshots from last validation iteration\n const renderMarkedBuffer = await fsPromises.readFile(request.savedRenderMarkedPath);\n const targetMarkedBuffer = await fsPromises.readFile(request.savedTargetMarkedPath);\n\n const renderMarked = `data:image/webp;base64,${renderMarkedBuffer.toString('base64')}`;\n const targetMarked = `data:image/webp;base64,${targetMarkedBuffer.toString('base64')}`;\n\n const screenshots = {\n renderSnap: validationResult.screenshots?.renderSnap || renderMarked,\n renderMarked,\n targetMarked,\n };\n\n // Generate combined comparison screenshot\n const finalScreenshotPath = path.join(comparisonDir, 'final.webp');\n await visualizationTool.combine(screenshots.renderMarked, screenshots.targetMarked, finalScreenshotPath);\n logger.printSuccessLog(`Saved final comparison screenshot: ${path.basename(finalScreenshotPath)}`);\n\n // Generate pixel difference heatmap\n let heatmap = '';\n try {\n heatmap = await visualizationTool.diffHeatmap(screenshots.renderSnap, request.figmaThumbnailUrl);\n\n if (heatmap) {\n const heatmapPath = path.join(comparisonDir, 'heatmap.webp');\n const base64Data = heatmap.split(',')[1];\n if (!base64Data) {\n throw new Error('Invalid heatmap data URI format');\n }\n const buffer = Buffer.from(base64Data, 'base64');\n await fs.promises.writeFile(heatmapPath, buffer);\n logger.printSuccessLog(`Saved pixel difference heatmap: ${path.basename(heatmapPath)}`);\n }\n } catch (heatmapError) {\n const errorMsg = heatmapError instanceof Error ? heatmapError.message : 'Unknown error';\n logger.printWarnLog(`Failed to generate pixel difference heatmap: ${errorMsg}. Continuing without heatmap.`);\n }\n\n // Build userReport structure (pure data formatting)\n const userReport = this.buildUserReportStructure(\n validationResult.mae,\n validationResult.sae,\n misalignedData.length,\n screenshots,\n heatmap,\n request.serverUrl,\n request.figmaThumbnailUrl,\n misalignedData\n );\n\n logger.printSuccessLog('Validation report generated successfully');\n\n return {\n userReport,\n misalignedCount: misalignedData.length,\n };\n }\n\n /**\n * Creates a minimal user report for error scenarios.\n */\n createMinimalReport(options: ErrorReportOptions): UserReport {\n return {\n design: {\n snap: options.figmaThumbnailUrl || '',\n markedSnap: '',\n },\n page: {\n url: options.serverUrl,\n snap: '',\n markedSnap: '',\n },\n report: {\n heatmap: '',\n detail: {\n metrics: {\n mae: options.mae ?? -1,\n sae: options.sae ?? -1,\n misalignedCount: 0,\n },\n components: [],\n },\n },\n };\n }\n\n /**\n * Generate standalone HTML report file from userReport.\n * Inlines all assets (JS/CSS) for single-file distribution.\n */\n async generateHtml(userReport: UserReport, outputDir: string): Promise<GenerateHtmlResult> {\n const reportDistDir = this.getReportDistDir();\n const reportIndexHtml = path.join(reportDistDir, 'index.html');\n logger.printInfoLog(`[ReportTool] Using template: ${reportIndexHtml}`);\n logger.printInfoLog(`[ReportTool] Output directory: ${outputDir}`);\n\n try {\n // Check if template exists\n try {\n await fsPromises.access(reportIndexHtml);\n } catch {\n const errorMsg = `Template not found at ${reportIndexHtml}`;\n logger.printErrorLog(`[ReportTool] ${errorMsg}. Skipping report generation.`);\n return { success: false, error: errorMsg };\n }\n\n // Ensure output directory exists\n await fsPromises.mkdir(outputDir, { recursive: true });\n\n // Transform data if it exists\n let reportData = userReport;\n if (reportData) {\n reportData = this.transformReportData(reportData);\n }\n\n logger.printTestLog(`Report data: ${JSON.stringify(reportData)}`);\n let htmlContent = await fsPromises.readFile(reportIndexHtml, 'utf-8');\n\n // 1. Inject Data\n // Serialize report data as JSON and inject directly into the HTML\n // Only escape characters that could break the HTML context\n const jsonString = JSON.stringify(reportData)\n .replace(/<\\/script>/gi, '<\\\\/script>') // Prevent script injection\n .replace(/\\u2028/g, '\\\\u2028') // Line separator (breaks JS string literals)\n .replace(/\\u2029/g, '\\\\u2029'); // Paragraph separator (breaks JS string literals)\n\n // Assign JSON object directly - no JSON.parse needed\n const scriptTag = `<script>window.__REPORT_DATA__ = ${jsonString};</script>`;\n htmlContent = htmlContent.replace(/<script>\\s*window\\.__REPORT_DATA__\\s*=\\s*null;?\\s*<\\/script>/, scriptTag);\n\n // 2. Inline Assets (JS) to make it single-file\n // Find ALL script tags with src=\"/assets/...\" and pre-read files\n const scriptRegexGlobal = /<script\\s+type=\"module\"\\s+crossorigin\\s+src=\"\\/assets\\/([^\"]+)\"><\\/script>/g;\n const jsMatches = [...htmlContent.matchAll(scriptRegexGlobal)];\n const jsContentsMap = new Map<string, string>();\n\n for (const match of jsMatches) {\n const fileName = match[1];\n if (fileName) {\n const jsFilePath = path.join(reportDistDir, 'assets', fileName);\n try {\n let jsContent = await fsPromises.readFile(jsFilePath, 'utf-8');\n // Prevent </script> inside JS from breaking HTML\n jsContent = jsContent.replace(/<\\/script>/g, '\\\\u003c/script>');\n jsContentsMap.set(fileName, jsContent);\n } catch {\n logger.printWarnLog(`[ReportTool] JS asset not found: ${jsFilePath}`);\n }\n }\n }\n\n htmlContent = htmlContent.replace(scriptRegexGlobal, (match, fileName: string) => {\n const jsContent = jsContentsMap.get(fileName);\n if (jsContent) {\n return `<script type=\"module\">${jsContent}</script>`;\n }\n return match; // Keep original if file not found\n });\n\n // 3. Inline CSS if exists (Vite might produce css in assets)\n const cssRegex = /<link\\s+rel=\"stylesheet\"\\s+crossorigin\\s+href=\"\\/assets\\/(.*?)\">/;\n const cssMatch = htmlContent.match(cssRegex);\n if (cssMatch) {\n const cssFileName = cssMatch[1];\n if (!cssFileName) {\n logger.printWarnLog('[ReportTool] CSS filename not found in match');\n } else {\n const cssFilePath = path.join(reportDistDir, 'assets', cssFileName);\n try {\n const cssContent = await fsPromises.readFile(cssFilePath, 'utf-8');\n htmlContent = htmlContent.replace(cssMatch[0], `<style>${cssContent}</style>`);\n } catch {\n // CSS file not found, skip inlining\n }\n }\n }\n\n // Remove /index.css reference if it doesn't exist\n htmlContent = htmlContent.replace('<link rel=\"stylesheet\" href=\"/index.css\">', '');\n\n const absoluteOutputPath = path.join(outputDir, 'index.html');\n await fsPromises.writeFile(absoluteOutputPath, htmlContent);\n\n return { success: true, htmlPath: absoluteOutputPath };\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.printErrorLog(`[ReportTool] Failed to generate report: ${errorMsg}`);\n return { success: false, error: errorMsg };\n }\n }\n\n // ==================== PRIVATE HELPER METHODS ====================\n\n /**\n * Build userReport structure from validation results\n */\n private buildUserReportStructure(\n mae: number,\n sae: number,\n misalignedCount: number,\n screenshots: { renderSnap: string; renderMarked: string; targetMarked: string },\n heatmap: string,\n serverUrl: string,\n figmaThumbnailUrl: string,\n misalignedData: MisalignedComponentData[]\n ): UserReport {\n return {\n design: {\n snap: figmaThumbnailUrl,\n markedSnap: screenshots.targetMarked,\n },\n page: {\n url: serverUrl,\n snap: screenshots.renderSnap,\n markedSnap: screenshots.renderMarked,\n },\n report: {\n heatmap: heatmap,\n detail: {\n metrics: {\n mae,\n sae,\n misalignedCount,\n },\n components: misalignedData.map(c => ({\n componentId: c.componentId,\n componentPath: c.componentPath,\n elementId: c.elementId,\n validationInfo: {\n x: c.xDelta,\n y: c.yDelta,\n },\n })),\n },\n },\n };\n }\n\n /**\n * Transform report data by grouping components by componentId\n */\n private transformReportData(reportData: UserReport): UserReport {\n const components = reportData?.report?.detail?.components || [];\n\n if (!components?.length) return reportData;\n\n // Group components by componentId\n const groupedComponentsMap = new Map<string, UserReport['report']['detail']['components'][number]>();\n\n components.forEach((component: UserReport['report']['detail']['components'][number], index: number) => {\n const { componentId, componentPath, elementId, validationInfo } = component;\n const elementIndex = index + 1;\n\n if (!groupedComponentsMap.has(componentId)) {\n groupedComponentsMap.set(componentId, {\n componentId,\n componentPath,\n elements: [],\n });\n }\n\n groupedComponentsMap.get(componentId)?.elements?.push({\n elementId: elementId || '',\n elementIndex,\n validationInfo: validationInfo || { x: 0, y: 0 },\n });\n });\n\n const groupedComponents = Array.from(groupedComponentsMap.values());\n\n return {\n ...reportData,\n report: {\n ...reportData.report,\n detail: {\n ...reportData.report.detail,\n components: groupedComponents,\n },\n },\n };\n }\n\n /**\n * Determine the root directory of the package by walking up to find package.json\n */\n private getPackageRoot(): string {\n // In ES modules, __dirname is not available, construct it from import.meta.url\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n\n // Walk up the directory tree to find package.json\n let currentDir = __dirname;\n while (currentDir !== path.parse(currentDir).root) {\n if (fs.existsSync(path.join(currentDir, 'package.json'))) {\n return currentDir;\n }\n currentDir = path.dirname(currentDir);\n }\n\n return process.cwd(); // Fallback\n }\n\n /**\n * Get the report dist directory containing built HTML/assets\n */\n private getReportDistDir(): string {\n const root = this.getPackageRoot();\n\n // Check standard locations for report template\n const paths = [\n path.join(root, 'dist/tools/report-tool/template'), // Production layout (if copied)\n path.join(root, 'src/tools/report-tool/template/dist'), // Development layout\n ];\n\n for (const p of paths) {\n if (fs.existsSync(path.join(p, 'index.html'))) {\n return p;\n }\n }\n\n // Fallback to development layout\n return path.join(root, 'src/tools/report-tool/template/dist');\n }\n}\n","import { tools } from 'evoltagent';\nimport * as path from 'path';\n\nimport type { AnnotateRenderResult, CombineOptions, MisalignedComponentData, IterationScreenshotResult } from './types';\nimport type { MisalignedComponent } from '../../types/validation-types';\nimport { annotateRenderWithPlaywright } from './utils/annotate-render';\nimport { annotateTargetWithPlaywright } from './utils/annotate-target';\nimport { browserManagement } from './utils/browser-management';\nimport { combineSideBySide } from './utils/combine';\nimport { captureAsWebP } from './utils/image-converter';\nimport { generatePixelDiffHeatmap } from './utils/pixel-diff-heatmap';\nimport { logger } from '../../utils/logger';\n\n@tools({\n annotateRender: {\n description:\n 'Navigate to the dev server, capture a clean render screenshot, inject RED annotation boxes for misaligned components, and capture the annotated render screenshot.',\n params: [\n { name: 'serverUrl', type: 'string', description: 'Dev server URL (e.g., http://localhost:5173)' },\n {\n name: 'misalignedData',\n type: 'object',\n description: 'MisalignedComponentData[] used to draw RED boxes on the render.',\n },\n { name: 'viewport', type: 'object', description: 'Viewport {width,height} to use in Playwright.' },\n ],\n returns: {\n type: 'object',\n description: 'AnnotateRenderResult containing renderSnap and renderMarked (WebP data URIs).',\n },\n },\n annotateTarget: {\n description:\n 'Fetch the Figma thumbnail, inject GREEN annotation boxes for misaligned components, and return an annotated target screenshot.',\n params: [\n { name: 'figmaThumbnailUrl', type: 'string', description: 'Figma thumbnail CDN URL.' },\n {\n name: 'misalignedData',\n type: 'object',\n description: 'MisalignedComponentData[] used to draw GREEN boxes on the target.',\n },\n { name: 'viewport', type: 'object', description: 'Viewport {width,height} to match the Figma thumbnail.' },\n {\n name: 'designOffset',\n type: 'object',\n description: 'Design offset {x,y} used when the thumbnail is not cropped (default behavior is cropped).',\n optional: true,\n },\n ],\n returns: { type: 'string', description: 'Annotated target screenshot as WebP data URI.' },\n },\n annotateTargetFromBase64: {\n description: 'Annotate target using pre-cached base64 thumbnail data. Use this to avoid redundant Figma thumbnail downloads.',\n params: [\n { name: 'figmaThumbnailBase64', type: 'string', description: 'Base64-encoded Figma thumbnail data.' },\n {\n name: 'misalignedData',\n type: 'object',\n description: 'MisalignedComponentData[] used to draw GREEN boxes on the target.',\n },\n { name: 'viewport', type: 'object', description: 'Viewport {width,height} to match the Figma thumbnail.' },\n {\n name: 'designOffset',\n type: 'object',\n description: 'Design offset {x,y} used when the thumbnail is not cropped (default behavior is cropped).',\n optional: true,\n },\n ],\n returns: { type: 'string', description: 'Annotated target screenshot as WebP data URI.' },\n },\n combine: {\n description: 'Combine two base64 screenshots side-by-side with headers and write to outputPath (WebP).',\n params: [\n { name: 'renderMarked', type: 'string', description: 'Left image (render, typically annotated) as base64 data URI.' },\n { name: 'targetMarked', type: 'string', description: 'Right image (target, typically annotated) as base64 data URI.' },\n { name: 'outputPath', type: 'string', description: 'Filesystem output path for the combined WebP.' },\n { name: 'options', type: 'object', description: 'Optional CombineOptions', optional: true },\n ],\n returns: { type: 'string', description: 'The outputPath written.' },\n },\n diffHeatmap: {\n description: 'Generate pixel-diff heatmap between a render screenshot and the target thumbnail.',\n params: [\n { name: 'renderSnap', type: 'string', description: 'Render screenshot (WebP data URI).' },\n { name: 'targetSnap', type: 'string', description: 'Target screenshot (WebP data URI) OR URL.' },\n ],\n returns: { type: 'string', description: 'Heatmap image as WebP data URI.' },\n },\n generateIterationScreenshot: {\n description: 'Generate annotated comparison screenshot for validation iteration. Orchestrates annotate + combine for convenience.',\n params: [\n { name: 'misalignedComponents', type: 'object', description: 'MisalignedComponent[] from validation result' },\n { name: 'serverUrl', type: 'string', description: 'Dev server URL' },\n { name: 'figmaThumbnailUrl', type: 'string', description: 'Figma thumbnail URL' },\n { name: 'viewport', type: 'object', description: 'Viewport {width, height}' },\n { name: 'designOffset', type: 'object', description: 'Design offset {x, y}' },\n { name: 'outputPath', type: 'string', description: 'Output file path for combined screenshot' },\n {\n name: 'cachedFigmaThumbnailBase64',\n type: 'string',\n description: 'Optional cached thumbnail base64',\n optional: true,\n },\n ],\n returns: { type: 'object', description: 'IterationScreenshotResult with renderMarked, targetMarked, and combinedPath' },\n },\n})\nexport class VisualizationTool {\n async annotateRender(\n serverUrl: string,\n misalignedData: MisalignedComponentData[],\n viewport: { width: number; height: number }\n ): Promise<AnnotateRenderResult> {\n return await browserManagement(viewport, async (_browser, page) => {\n await page.goto(serverUrl, { waitUntil: 'domcontentloaded', timeout: 30000 });\n await new Promise(r => setTimeout(r, 1000));\n\n const renderSnap = await captureAsWebP(page);\n await annotateRenderWithPlaywright(page, misalignedData);\n const renderMarked = await captureAsWebP(page);\n\n return { renderSnap, renderMarked };\n });\n }\n\n async annotateTarget(\n figmaThumbnailUrl: string,\n misalignedData: MisalignedComponentData[],\n viewport: { width: number; height: number },\n designOffset?: { x: number; y: number }\n ): Promise<string> {\n const axios = (await import('axios')).default;\n const response = await axios.get(figmaThumbnailUrl, { responseType: 'arraybuffer', timeout: 30000 });\n const figmaThumbnailBase64 = Buffer.from(response.data).toString('base64');\n\n return await browserManagement(viewport, async browser => {\n return await annotateTargetWithPlaywright(browser, figmaThumbnailBase64, misalignedData, viewport, designOffset);\n });\n }\n\n /**\n * Annotate target using pre-cached base64 thumbnail data.\n * Use this method when you have already downloaded the Figma thumbnail to avoid redundant downloads.\n */\n async annotateTargetFromBase64(\n figmaThumbnailBase64: string,\n misalignedData: MisalignedComponentData[],\n viewport: { width: number; height: number },\n designOffset?: { x: number; y: number }\n ): Promise<string> {\n return await browserManagement(viewport, async browser => {\n return await annotateTargetWithPlaywright(browser, figmaThumbnailBase64, misalignedData, viewport, designOffset);\n });\n }\n\n async combine(renderMarked: string, targetMarked: string, outputPath: string, options?: CombineOptions): Promise<string> {\n await combineSideBySide(renderMarked, targetMarked, outputPath, options);\n return outputPath;\n }\n\n async diffHeatmap(renderSnap: string, targetSnap: string): Promise<string> {\n return await generatePixelDiffHeatmap(renderSnap, targetSnap);\n }\n\n /**\n * Generate annotated comparison screenshot for a single iteration.\n * This is a convenience method that orchestrates the full screenshot workflow.\n *\n * @returns IterationScreenshotResult with individual annotated screenshots and combined path\n */\n async generateIterationScreenshot(\n misalignedComponents: MisalignedComponent[],\n serverUrl: string,\n figmaThumbnailUrl: string,\n viewport: { width: number; height: number },\n designOffset: { x: number; y: number },\n outputPath: string,\n cachedFigmaThumbnailBase64?: string\n ): Promise<IterationScreenshotResult> {\n if (misalignedComponents.length === 0) {\n return { renderMarked: '', targetMarked: '', combinedPath: '' };\n }\n\n try {\n // Transform validation data to visualization format\n const misalignedData = this.formatForVisualization(misalignedComponents);\n\n // Annotate render (browser screenshot)\n const render = await this.annotateRender(serverUrl, misalignedData, viewport);\n\n // Annotate target (Figma screenshot) - use cached thumbnail if available\n const targetMarked = cachedFigmaThumbnailBase64\n ? await this.annotateTargetFromBase64(cachedFigmaThumbnailBase64, misalignedData, viewport, designOffset)\n : await this.annotateTarget(figmaThumbnailUrl, misalignedData, viewport, designOffset);\n\n // Combine into side-by-side comparison (needed for judger visual context in next iteration)\n await this.combine(render.renderMarked, targetMarked, outputPath);\n\n logger.printInfoLog(`Saved comparison screenshot: ${path.basename(outputPath)}`);\n return {\n renderMarked: render.renderMarked,\n targetMarked,\n combinedPath: outputPath,\n };\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.printWarnLog(`Failed to generate iteration screenshot: ${errorMsg}`);\n return { renderMarked: '', targetMarked: '', combinedPath: '' };\n }\n }\n\n /**\n * Transform MisalignedComponent[] to MisalignedComponentData[] format.\n * This is an internal helper for converting validation results to visualization format.\n */\n private formatForVisualization(components: MisalignedComponent[]): MisalignedComponentData[] {\n return components.map((comp, idx) => {\n if (comp.elementIds.length === 0) {\n logger.printWarnLog(`Component ${comp.name} has no elementIds. Using componentId as fallback.`);\n }\n\n return {\n index: idx + 1,\n elementId: comp.elementIds[0] || comp.componentId,\n elementName: comp.name,\n componentId: comp.componentId,\n componentName: comp.name,\n componentPath: comp.path,\n currentX: comp.currentX,\n currentY: comp.currentY,\n currentWidth: comp.currentWidth,\n currentHeight: comp.currentHeight,\n targetX: comp.targetX,\n targetY: comp.targetY,\n targetWidth: comp.targetWidth,\n targetHeight: comp.targetHeight,\n distance: comp.distance,\n xDelta: comp.validationReport.absoluteError[0],\n yDelta: comp.validationReport.absoluteError[1],\n };\n });\n }\n}\n","/**\n * Shared annotation styling utilities for visualization.\n * Provides consistent styling for position validation annotations.\n */\n\n/** Annotation colors */\nexport const ANNOTATION_COLORS = {\n RED: '#ef4444', // Tailwind red-500 - for current/render positions\n GREEN: '#22c55e', // Tailwind green-500 - for target/expected positions\n} as const;\n\n/** Annotation box position data */\nexport interface AnnotationBoxData {\n index: number;\n x: number;\n y: number;\n width: number;\n height: number;\n label?: string;\n distance?: number;\n}\n\n/**\n * Creates the CSS for an annotation container that overlays the page.\n */\nexport function createContainerStyle(): string {\n return `\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n z-index: 999999;\n `;\n}\n\n/**\n * Creates the CSS for an annotation box at the specified position.\n */\nexport function createBoxStyle(x: number, y: number, width: number, height: number, color: string): string {\n return `\n position: absolute;\n left: ${x}px;\n top: ${y}px;\n width: ${width}px;\n height: ${height}px;\n border: 4px solid ${color};\n box-sizing: border-box;\n pointer-events: none;\n `;\n}\n\n/**\n * Creates the CSS for a numbered circle label.\n * Clamps to at least 5px from edges to prevent cutoff (mirrors Python implementation).\n */\nexport function createCircleLabelStyle(x: number, y: number, color: string): string {\n const labelX = Math.max(5, x - 22);\n const labelY = Math.max(5, y - 22);\n\n return `\n position: absolute;\n left: ${labelX}px;\n top: ${labelY}px;\n background: ${color};\n color: white;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n font: bold 18px Arial, sans-serif;\n border-radius: 50%;\n pointer-events: none;\n border: 2px solid white;\n box-shadow: 0 2px 4px rgba(0,0,0,0.3);\n `;\n}\n\n/**\n * Creates the CSS for a text label positioned below the box.\n */\nexport function createTextLabelStyle(x: number, y: number, height: number, color: string): string {\n return `\n position: absolute;\n left: ${x}px;\n top: ${y + height + 4}px;\n background: ${color};\n color: white;\n padding: 4px 8px;\n font: 12px Arial, sans-serif;\n border-radius: 4px;\n pointer-events: none;\n white-space: nowrap;\n box-shadow: 0 2px 4px rgba(0,0,0,0.3);\n `;\n}\n","import type { Page } from 'playwright';\nimport type { MisalignedComponentData } from '../types';\nimport { ANNOTATION_COLORS, createBoxStyle, createCircleLabelStyle, createContainerStyle, createTextLabelStyle } from './annotation-styles';\n\n/**\n * Annotates the rendered page with RED boxes showing current positions.\n * Injects DOM elements via page.evaluate() to mark misaligned component positions.\n */\nexport async function annotateRenderWithPlaywright(page: Page, misalignedData: MisalignedComponentData[]): Promise<void> {\n await page.evaluate(\n (data: {\n items: MisalignedComponentData[];\n styles: {\n container: string;\n boxes: Record<number, string>;\n circleLabels: Record<number, string>;\n textLabels: Record<number, string>;\n };\n }) => {\n const { items, styles } = data;\n\n const container = document.createElement('div');\n container.id = 'validation-annotations';\n container.style.cssText = styles.container;\n\n items.forEach((item: MisalignedComponentData) => {\n // Create RED box at current position with browser dimensions\n const box = document.createElement('div');\n const boxStyle = styles.boxes[item.index];\n if (boxStyle) {\n box.style.cssText = boxStyle;\n }\n container.appendChild(box);\n\n // Create numbered circle label\n const label = document.createElement('div');\n label.textContent = `${item.index}`;\n const circleLabelStyle = styles.circleLabels[item.index];\n if (circleLabelStyle) {\n label.style.cssText = circleLabelStyle;\n }\n container.appendChild(label);\n\n // Create text label with component name and distance\n const textLabel = document.createElement('div');\n textLabel.textContent = `${item.componentName} (${item.distance.toFixed(1)}px)`;\n const textLabelStyle = styles.textLabels[item.index];\n if (textLabelStyle) {\n textLabel.style.cssText = textLabelStyle;\n }\n container.appendChild(textLabel);\n });\n\n document.body.appendChild(container);\n },\n {\n items: misalignedData,\n styles: {\n container: createContainerStyle(),\n boxes: Object.fromEntries(\n misalignedData.map(item => [\n item.index,\n createBoxStyle(item.currentX, item.currentY, item.currentWidth, item.currentHeight, ANNOTATION_COLORS.RED),\n ])\n ),\n circleLabels: Object.fromEntries(\n misalignedData.map(item => [item.index, createCircleLabelStyle(item.currentX, item.currentY, ANNOTATION_COLORS.RED)])\n ),\n textLabels: Object.fromEntries(\n misalignedData.map(item => [\n item.index,\n createTextLabelStyle(item.currentX, item.currentY, item.currentHeight, ANNOTATION_COLORS.RED),\n ])\n ),\n },\n }\n );\n}\n","/**\n * Image conversion utilities for screenshot processing.\n * Handles PNG -> WebP conversion and base64 encoding.\n */\n\nimport type { Page } from 'playwright';\n\n/**\n * WebP quality for screenshot compression (1-100).\n * Higher = better quality but larger file size.\n */\nexport const SCREENSHOT_WEBP_QUALITY = 88;\n\n/**\n * Captures a Playwright page screenshot and converts it to WebP base64 data URI.\n */\nexport async function captureAsWebP(page: Page, options: { fullPage?: boolean } = {}): Promise<string> {\n const pngBuffer = await page.screenshot({\n type: 'png',\n fullPage: options.fullPage ?? false,\n });\n\n return await bufferToWebPDataUri(pngBuffer);\n}\n\n/**\n * Converts a raw image buffer to WebP base64 data URI.\n */\nexport async function bufferToWebPDataUri(buffer: Buffer): Promise<string> {\n const sharp = (await import('sharp')).default;\n const webpBuffer = await sharp(buffer).webp({ quality: SCREENSHOT_WEBP_QUALITY }).toBuffer();\n return `data:image/webp;base64,${webpBuffer.toString('base64')}`;\n}\n","import type { Browser } from 'playwright';\nimport type { MisalignedComponentData } from '../types';\nimport { bufferToWebPDataUri } from './image-converter';\nimport { ANNOTATION_COLORS, createBoxStyle, createCircleLabelStyle, createContainerStyle, createTextLabelStyle } from './annotation-styles';\n\n/**\n * Annotates the Figma thumbnail with GREEN boxes showing target positions.\n * Creates a new browser page, loads the thumbnail as background, injects annotations,\n * captures screenshot, and returns as base64 data URI.\n */\nexport async function annotateTargetWithPlaywright(\n browser: Browser,\n figmaThumbnailBase64: string,\n misalignedData: MisalignedComponentData[],\n viewport: { width: number; height: number },\n designOffset: { x: number; y: number } = { x: 0, y: 0 },\n isThumbnailCropped: boolean = true\n): Promise<string> {\n const context = await browser.newContext({ viewport });\n const page = await context.newPage();\n\n try {\n const dataUri = figmaThumbnailBase64.startsWith('data:') ? figmaThumbnailBase64 : `data:image/png;base64,${figmaThumbnailBase64}`;\n\n const html = `\n <!DOCTYPE html>\n <html>\n <head>\n <style>\n * { margin: 0; padding: 0; }\n body {\n width: ${viewport.width}px;\n height: ${viewport.height}px;\n background-image: url('${dataUri}');\n background-size: 100% 100%;\n background-repeat: no-repeat;\n background-position: top left;\n position: relative;\n overflow: hidden;\n }\n </style>\n </head>\n <body></body>\n </html>\n `;\n\n await page.setContent(html);\n await page.waitForLoadState('domcontentloaded');\n\n const offsetX = isThumbnailCropped ? 0 : designOffset.x;\n const offsetY = isThumbnailCropped ? 0 : designOffset.y;\n\n const elementsData = misalignedData.map((item, i) => ({\n index: i + 1,\n componentName: item.componentName,\n targetX: item.targetX + offsetX,\n targetY: item.targetY + offsetY,\n width: item.targetWidth,\n height: item.targetHeight,\n }));\n\n type ElementData = {\n index: number;\n componentName: string;\n targetX: number;\n targetY: number;\n width: number;\n height: number;\n };\n\n const styles = {\n container: createContainerStyle(),\n boxes: Object.fromEntries(\n elementsData.map(item => [\n item.index,\n createBoxStyle(item.targetX, item.targetY, item.width, item.height, ANNOTATION_COLORS.GREEN),\n ])\n ),\n circleLabels: Object.fromEntries(\n elementsData.map(item => [item.index, createCircleLabelStyle(item.targetX, item.targetY, ANNOTATION_COLORS.GREEN)])\n ),\n textLabels: Object.fromEntries(\n elementsData.map(item => [\n item.index,\n createTextLabelStyle(item.targetX, item.targetY, item.height, ANNOTATION_COLORS.GREEN),\n ])\n ),\n };\n\n await page.evaluate(\n (data: {\n items: ElementData[];\n styles: {\n container: string;\n boxes: Record<number, string>;\n circleLabels: Record<number, string>;\n textLabels: Record<number, string>;\n };\n }) => {\n const { items, styles } = data;\n\n const container = document.createElement('div');\n container.id = 'target-annotations';\n container.style.cssText = styles.container;\n\n items.forEach((item: ElementData) => {\n const box = document.createElement('div');\n const boxStyle = styles.boxes[item.index];\n if (boxStyle) {\n box.style.cssText = boxStyle;\n }\n container.appendChild(box);\n\n const label = document.createElement('div');\n label.textContent = `${item.index}`;\n const circleLabelStyle = styles.circleLabels[item.index];\n if (circleLabelStyle) {\n label.style.cssText = circleLabelStyle;\n }\n container.appendChild(label);\n\n const textLabel = document.createElement('div');\n textLabel.textContent = `${item.componentName}`;\n const textLabelStyle = styles.textLabels[item.index];\n if (textLabelStyle) {\n textLabel.style.cssText = textLabelStyle;\n }\n container.appendChild(textLabel);\n });\n\n document.body.appendChild(container);\n },\n { items: elementsData, styles }\n );\n\n const screenshotBuffer = await page.screenshot({ type: 'png', fullPage: false });\n return await bufferToWebPDataUri(screenshotBuffer);\n } finally {\n await page.close();\n await context.close();\n }\n}\n","import type { Browser, LaunchOptions } from 'playwright';\nimport { spawn } from 'child_process';\nimport { createRequire } from 'module';\nimport { dirname, join } from 'path';\n\nimport { logger } from '../../../../utils/logger';\n\nconst MISSING_EXECUTABLE_MESSAGE = \"Executable doesn't exist\";\n\n/**\n * Get the path to the locally installed playwright CLI.\n * Uses Node.js module resolution to ensure the version matches the imported playwright.\n *\n * Note: We can't use require.resolve('playwright/cli') directly because\n * the 'exports' field in playwright's package.json doesn't expose './cli'.\n * Instead, we resolve the main entry and derive the cli.js path from it.\n */\nfunction getLocalPlaywrightCliPath(): string {\n const require = createRequire(import.meta.url);\n const playwrightMain = require.resolve('playwright');\n return join(dirname(playwrightMain), 'cli.js');\n}\n\nlet installPromise: Promise<void> | null = null;\nlet installCompleted = false;\n\nasync function installChromiumBrowsers(): Promise<void> {\n if (installCompleted) return;\n\n if (!installPromise) {\n logger.printInfoLog('Playwright Chromium binaries are missing. Installing them automatically...');\n\n installPromise = new Promise((resolve, reject) => {\n // NOTE: Avoid --with-deps here; it can try to install system packages on some platforms.\n const cliPath = getLocalPlaywrightCliPath();\n const child = spawn(process.execPath, [cliPath, 'install', 'chromium'], {\n stdio: 'inherit',\n env: process.env,\n });\n\n child.on('error', error => {\n installPromise = null;\n reject(error);\n });\n\n child.on('close', code => {\n installPromise = null;\n if (code === 0) {\n installCompleted = true;\n logger.printSuccessLog('Playwright Chromium installation finished.');\n resolve();\n } else {\n reject(new Error(`Playwright install exited with code ${code}`));\n }\n });\n });\n }\n\n return installPromise;\n}\n\nfunction isMissingExecutableError(error: unknown): boolean {\n return error instanceof Error && error.message.includes(MISSING_EXECUTABLE_MESSAGE);\n}\n\nexport async function launchChromiumWithAutoInstall(options: LaunchOptions = {}): Promise<Browser> {\n const launchOptions: LaunchOptions = { headless: true, ...options };\n\n // Dynamic import to avoid load-time error if playwright is missing\n const { chromium } = await import('playwright');\n\n try {\n return await chromium.launch(launchOptions);\n } catch (error) {\n if (isMissingExecutableError(error)) {\n try {\n await installChromiumBrowsers();\n } catch (installError) {\n throw new Error(\n 'Failed to auto-install Playwright browsers required for validation.\\n' +\n 'Please run \"npx playwright install chromium\" or \"pnpm exec playwright install chromium\" manually and retry.\\n' +\n `Installer error: ${(installError as Error).message}`\n );\n }\n\n return chromium.launch(launchOptions);\n }\n\n throw error;\n }\n}\n","/**\n * Browser lifecycle management utilities for Playwright operations.\n * Provides higher-order functions to handle browser setup and teardown.\n */\n\nimport type { Browser, Page } from 'playwright';\nimport { launchChromiumWithAutoInstall } from '../../../nodes/validation/utils/playwright/launcher';\n\n/**\n * Executes an operation with a managed browser and page instance.\n * Automatically handles browser launch, context creation, and cleanup.\n */\nexport async function browserManagement<T>(\n viewport: { width: number; height: number },\n operation: (browser: Browser, page: Page) => Promise<T>\n): Promise<T> {\n let browser: Browser | null = null;\n let page: Page | null = null;\n\n try {\n browser = await launchChromiumWithAutoInstall({ headless: true });\n const context = await browser.newContext({ viewport });\n page = await context.newPage();\n\n return await operation(browser, page);\n } finally {\n if (page) await page.close().catch(() => {});\n if (browser) await browser.close().catch(() => {});\n }\n}\n","import fs from 'fs';\nimport path from 'path';\n\nimport type { CombineOptions } from '../types';\nimport { SCREENSHOT_WEBP_QUALITY } from './image-converter';\n\nconst DEFAULT_OPTIONS: Required<CombineOptions> = {\n leftHeader: 'RENDER (Current)',\n rightHeader: 'TARGET (Expected)',\n gapWidth: 40,\n headerHeight: 60,\n};\n\n/**\n * Combines two annotated screenshots side-by-side with headers.\n * Matches the Python reference implementation from evolt.\n */\nexport async function combineSideBySide(\n renderBase64: string,\n targetBase64: string,\n outputPath: string,\n options?: CombineOptions\n): Promise<void> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n\n try {\n const sharp = (await import('sharp')).default;\n const leftBase64 = extractBase64Data(renderBase64);\n const rightBase64 = extractBase64Data(targetBase64);\n\n const leftBuffer = Buffer.from(leftBase64, 'base64');\n const rightBuffer = Buffer.from(rightBase64, 'base64');\n\n const leftMeta = await sharp(leftBuffer).metadata();\n const rightMeta = await sharp(rightBuffer).metadata();\n\n if (!leftMeta.width || !leftMeta.height || !rightMeta.width || !rightMeta.height) {\n throw new Error('Failed to read image dimensions');\n }\n\n const scale = leftMeta.height / rightMeta.height;\n const rightResizedWidth = Math.round(rightMeta.width * scale);\n\n const rightResized = await sharp(rightBuffer).resize({ height: leftMeta.height, width: rightResizedWidth, fit: 'fill' }).toBuffer();\n\n const combinedWidth = leftMeta.width + opts.gapWidth + rightResizedWidth;\n const combinedHeight = opts.headerHeight + leftMeta.height;\n\n const centerX = leftMeta.width + opts.gapWidth / 2;\n const leftTextX = leftMeta.width / 2;\n const rightTextX = leftMeta.width + opts.gapWidth + rightResizedWidth / 2;\n const textY = opts.headerHeight / 2 + 8;\n\n const headerSvg = `\n<svg width=\"${combinedWidth}\" height=\"${opts.headerHeight}\">\n <rect width=\"${combinedWidth}\" height=\"${opts.headerHeight}\" fill=\"#F0F0F0\"/>\n <line x1=\"${centerX}\" y1=\"0\" x2=\"${centerX}\" y2=\"${combinedHeight}\"\n stroke=\"#C8C8C8\" stroke-width=\"2\"/>\n <text x=\"${leftTextX}\" y=\"${textY}\"\n font-family=\"Arial\" font-size=\"24\" font-weight=\"bold\" fill=\"#C80000\"\n text-anchor=\"middle\">\n ${opts.leftHeader}\n </text>\n <text x=\"${rightTextX}\" y=\"${textY}\"\n font-family=\"Arial\" font-size=\"24\" font-weight=\"bold\" fill=\"#009600\"\n text-anchor=\"middle\">\n ${opts.rightHeader}\n </text>\n</svg>\n `;\n\n const headerBuffer = Buffer.from(headerSvg);\n\n const outputDir = path.dirname(outputPath);\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n await sharp({\n create: {\n width: combinedWidth,\n height: combinedHeight,\n channels: 3,\n background: { r: 255, g: 255, b: 255 },\n },\n })\n .composite([\n { input: headerBuffer, top: 0, left: 0 },\n { input: leftBuffer, top: opts.headerHeight, left: 0 },\n { input: rightResized, top: opts.headerHeight, left: leftMeta.width + opts.gapWidth },\n ])\n .webp({ quality: SCREENSHOT_WEBP_QUALITY })\n .toFile(outputPath);\n } catch (error) {\n throw new Error(`Failed to combine side-by-side screenshots: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\nfunction extractBase64Data(base64String: string): string {\n const dataUriMatch = base64String.match(/^data:image\\/[a-z]+;base64,(.+)$/);\n if (dataUriMatch && dataUriMatch[1]) {\n return dataUriMatch[1];\n }\n return base64String;\n}\n","import pixelmatch from 'pixelmatch';\n\nimport { logger } from '../../../utils/logger';\nimport { bufferToWebPDataUri } from './image-converter';\n\n/**\n * Generates a pixel-difference heatmap comparing rendered and target images.\n * Uses pixelmatch algorithm for perceptually-accurate pixel comparison.\n */\nexport async function generatePixelDiffHeatmap(renderSnap: string, targetSnap: string): Promise<string> {\n const sharp = (await import('sharp')).default;\n const img1Data = await loadImageData(renderSnap);\n const img2Data = await loadImageData(targetSnap);\n\n let { width: width1, height: height1, data: data1 } = img1Data;\n let { width: width2, height: height2, data: data2 } = img2Data;\n\n if (width1 !== width2 || height1 !== height2) {\n const resized = await sharp(data2, {\n raw: { width: width2, height: height2, channels: 4 },\n })\n .resize(width1, height1, { fit: 'fill' })\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n\n data2 = resized.data;\n width2 = resized.info.width;\n height2 = resized.info.height;\n }\n\n const MAX_DIMENSION = 2500;\n if (height1 > MAX_DIMENSION || width1 > MAX_DIMENSION) {\n const scale = MAX_DIMENSION / Math.max(height1, width1);\n const newWidth = Math.floor(width1 * scale);\n const newHeight = Math.floor(height1 * scale);\n\n const downsampled1 = await sharp(data1, {\n raw: { width: width1, height: height1, channels: 4 },\n })\n .resize(newWidth, newHeight, { kernel: 'lanczos3' })\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n\n const downsampled2 = await sharp(data2, {\n raw: { width: width2, height: height2, channels: 4 },\n })\n .resize(newWidth, newHeight, { kernel: 'lanczos3' })\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n\n data1 = downsampled1.data;\n data2 = downsampled2.data;\n width1 = downsampled1.info.width;\n height1 = downsampled1.info.height;\n width2 = downsampled2.info.width;\n height2 = downsampled2.info.height;\n }\n\n const diffBuffer = Buffer.alloc(width1 * height1 * 4);\n\n const numDiffPixels = pixelmatch(data1, data2, diffBuffer, width1, height1, {\n threshold: 0.1,\n includeAA: false,\n alpha: 0.1,\n diffColor: [255, 0, 0],\n diffMask: false,\n });\n\n const totalPixels = width1 * height1;\n const diffPercentage = ((numDiffPixels / totalPixels) * 100).toFixed(2);\n logger.printTestLog(`[Pixelmatch] Different pixels: ${numDiffPixels} / ${totalPixels} (${diffPercentage}%)`);\n\n const heatmapBuffer = await generateBlueRedHeatmap(data1, data2, diffBuffer, width1, height1);\n return await bufferToWebPDataUri(heatmapBuffer);\n}\n\nasync function generateBlueRedHeatmap(data1: Buffer, data2: Buffer, diffBuffer: Buffer, width: number, height: number): Promise<Buffer> {\n const sharp = (await import('sharp')).default;\n const outputData = Buffer.alloc(width * height * 3);\n\n const gray1 = new Uint8Array(width * height);\n const gray2 = new Uint8Array(width * height);\n\n for (let i = 0; i < width * height; i++) {\n const r1 = data1[i * 4] ?? 0;\n const g1 = data1[i * 4 + 1] ?? 0;\n const b1 = data1[i * 4 + 2] ?? 0;\n gray1[i] = Math.round(0.299 * r1 + 0.587 * g1 + 0.114 * b1);\n\n const r2 = data2[i * 4] ?? 0;\n const g2 = data2[i * 4 + 1] ?? 0;\n const b2 = data2[i * 4 + 2] ?? 0;\n gray2[i] = Math.round(0.299 * r2 + 0.587 * g2 + 0.114 * b2);\n }\n\n let pixelsWithDifferences = 0;\n\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const idx = y * width + x;\n const outIdx = idx * 3;\n const pixel1 = gray1[idx] ?? 0;\n const pixel2 = gray2[idx] ?? 0;\n\n const isDifferent = (diffBuffer[idx * 4] ?? 0) > 0;\n if (isDifferent) {\n pixelsWithDifferences++;\n // Calculate difference magnitude (0-255 range)\n const diff = Math.abs(pixel1 - pixel2);\n // Normalize to 0-1 range\n const normalizedDiff = diff / 255;\n\n // Blue to Red gradient\n // Blue (0, 0, 255) for small differences -> Red (255, 0, 0) for large differences\n outputData[outIdx] = Math.round(255 * normalizedDiff); // Red increases with difference\n outputData[outIdx + 1] = 0; // No green\n outputData[outIdx + 2] = Math.round(255 * (1 - normalizedDiff)); // Blue decreases with difference\n } else {\n // Exact match: pure blue\n outputData[outIdx] = 0;\n outputData[outIdx + 1] = 0;\n outputData[outIdx + 2] = 255;\n }\n }\n }\n\n logger.printTestLog(\n `[Heatmap] Pixels with differences: ${pixelsWithDifferences} / ${width * height} (${((pixelsWithDifferences / (width * height)) * 100).toFixed(2)}%)`\n );\n\n return sharp(outputData, { raw: { width, height, channels: 3 } })\n .png()\n .toBuffer();\n}\n\nasync function loadImageData(dataUri: string): Promise<{ width: number; height: number; data: Buffer }> {\n const sharp = (await import('sharp')).default;\n if (!dataUri.startsWith('data:')) {\n const axios = (await import('axios')).default;\n const response = await axios.get(dataUri, { responseType: 'arraybuffer', timeout: 30000 });\n const base64 = Buffer.from(response.data).toString('base64');\n dataUri = `data:image/png;base64,${base64}`;\n }\n\n const base64Data = dataUri.split(',')[1];\n if (!base64Data) {\n throw new Error('Invalid data URI format: missing base64 data');\n }\n const buffer = Buffer.from(base64Data, 'base64');\n\n const image = sharp(buffer);\n const { data, info } = await image.ensureAlpha().raw().toBuffer({ resolveWithObject: true });\n\n return { width: info.width, height: info.height, data };\n}\n","import * as path from 'node:path';\nimport { tools } from 'evoltagent';\n\nimport type { StartDevServerResult, StopDevServerResult } from './types';\nimport { DevServerManager } from './utils/dev-server-manager';\n\n/**\n * Generate a stable lookup key for a dev server instance (same appPath => same key).\n * Port and pid are NOT included because:\n * - They become stale after restart (port may change, pid always changes)\n * - DevServerManager tracks current port/pid in its internal state\n * - serverKey is only used for Map lookup, never parsed\n * Stable key ensures one manager per appPath and avoids concurrent start() / duplicate port logs.\n */\nfunction makeServerKey(appPath: string): string {\n const safeApp = appPath.split(path.sep).join('_');\n return `launch:${safeApp}`;\n}\n\n@tools({\n startDevServer: {\n description: 'Start a dev server in-process and wait for it to become reachable.',\n params: [\n { name: 'appPath', type: 'string', description: 'Absolute path to the app directory' },\n { name: 'runCommand', type: 'string', description: 'Run command (e.g. \"pnpm dev\")' },\n { name: 'timeoutMs', type: 'number', description: 'Timeout in milliseconds', optional: true },\n ],\n returns: { type: 'string', description: 'JSON string containing StartDevServerResult with url/port/pid/serverKey.' },\n },\n stopDevServer: {\n description: 'Stop a previously started dev server by serverKey.',\n params: [{ name: 'serverKey', type: 'string', description: 'Server key returned by startDevServer()' }],\n returns: { type: 'string', description: 'JSON string containing StopDevServerResult' },\n },\n})\nexport class LaunchTool {\n private static readonly serverManagers = new Map<string, { manager: DevServerManager; appPath: string }>();\n /** Mutex per appPath so only one startDevServer runs at a time for a given app (avoids duplicate port logs). */\n private static readonly inFlightStarts = new Map<string, Promise<void>>();\n\n async startDevServer(appPath: string, runCommand: string, timeoutMs: number = 60_000): Promise<string> {\n const serverKey = makeServerKey(appPath);\n const prev = LaunchTool.inFlightStarts.get(appPath);\n let resolveThis: () => void;\n const thisRun = new Promise<void>(r => {\n resolveThis = r;\n });\n LaunchTool.inFlightStarts.set(appPath, thisRun);\n await prev;\n\n try {\n const entry = LaunchTool.serverManagers.get(serverKey);\n if (entry) {\n const handle = await entry.manager.restart({ timeoutMs });\n const result: StartDevServerResult = {\n success: true,\n serverKey,\n url: handle.url,\n port: handle.port,\n pid: handle.child.pid ?? undefined,\n outputTail: handle.outputTail(),\n };\n return JSON.stringify(result, null, 2);\n }\n\n const manager = new DevServerManager({ appPath, runCommand: runCommand.trim() });\n const handle = await manager.start({ timeoutMs });\n LaunchTool.serverManagers.set(serverKey, { manager, appPath });\n const result: StartDevServerResult = {\n success: true,\n serverKey,\n url: handle.url,\n port: handle.port,\n pid: handle.child.pid ?? undefined,\n outputTail: handle.outputTail(),\n };\n return JSON.stringify(result, null, 2);\n } catch (error) {\n const result: StartDevServerResult = {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n return JSON.stringify(result, null, 2);\n } finally {\n resolveThis!();\n LaunchTool.inFlightStarts.delete(appPath);\n }\n }\n\n async stopDevServer(serverKey: string): Promise<string> {\n const entry = LaunchTool.serverManagers.get(serverKey);\n if (!entry) {\n const result: StopDevServerResult = { success: false, serverKey, error: `Unknown serverKey: ${serverKey}` };\n return JSON.stringify(result, null, 2);\n }\n try {\n await entry.manager.stop();\n LaunchTool.serverManagers.delete(serverKey);\n const result: StopDevServerResult = { success: true, serverKey };\n return JSON.stringify(result, null, 2);\n } catch (error) {\n const result: StopDevServerResult = {\n success: false,\n serverKey,\n error: error instanceof Error ? error.message : String(error),\n };\n return JSON.stringify(result, null, 2);\n }\n }\n}\n","import * as http from 'http';\nimport * as net from 'net';\nimport { spawn, type ChildProcess } from 'child_process';\n\nimport { buildDevServerUrl, DEFAULT_PORT } from '../../../nodes/validation/constants';\nimport { logger } from '../../../utils/logger';\n\nexport interface DevServerHandle {\n child: ChildProcess;\n port: number;\n url: string;\n /**\n * Last tail of stdout/stderr for diagnosing startup/runtime issues.\n */\n outputTail: () => string;\n}\n\nfunction terminateChildProcess(child: ChildProcess): void {\n // Windows does not support POSIX signals like SIGTERM reliably.\n // Calling kill() without a signal uses the platform default behavior.\n try {\n if (process.platform === 'win32') {\n child.kill();\n } else {\n child.kill('SIGTERM');\n }\n } catch {\n // ignore\n }\n}\n\nfunction normalizeExecutable(executable: string): string {\n if (process.platform !== 'win32') {\n return executable;\n }\n const lower = executable.toLowerCase();\n if (lower === 'npm' || lower === 'pnpm' || lower === 'yarn' || lower === 'npx') {\n return `${lower}.cmd`;\n }\n return executable;\n}\n\nfunction parseCommandWithPortSupport(commandStr: string): { executable: string; args: string[]; needsDoubleDash: boolean } {\n const parts = commandStr.trim().split(/\\s+/);\n const executable = parts[0];\n if (!executable) {\n throw new Error('Failed to parse command: empty command string');\n }\n const args = parts.slice(1);\n const needsDoubleDash = ['npm', 'pnpm', 'yarn'].includes(executable);\n return { executable, args, needsDoubleDash };\n}\n\nasync function isPortAvailable(port: number): Promise<boolean> {\n return await new Promise(resolve => {\n const server = net.createServer();\n server.unref();\n server.on('error', () => resolve(false));\n server.listen(port, () => {\n server.close(() => resolve(true));\n });\n });\n}\n\n/**\n * Calculate deterministic port from workspace path hash.\n * Same workspace always gets the same port for consistency.\n *\n * @param workspacePath - Absolute path to workspace root\n * @param basePort - Base port for calculation (default: 5200, avoids common 5173-5180)\n * @returns Hash-based port (basePort to basePort + 999)\n */\nfunction calculateHashPort(workspacePath: string, basePort: number = 5200): number {\n // Simple hash function - same input always produces same output\n let hash = 0;\n for (let i = 0; i < workspacePath.length; i++) {\n hash = (hash << 5) - hash + workspacePath.charCodeAt(i);\n hash = hash & hash; // Convert to 32bit integer\n }\n\n // Map to port range (basePort to basePort + 999)\n const offset = Math.abs(hash) % 1000;\n return basePort + offset;\n}\n\n/**\n * Get available port using hash-based selection strategy.\n * Tries hash-based port first, then nearby ports (±10 range).\n *\n * @param workspacePath - Absolute path to workspace (used for port calculation)\n * @param _startPort - Unused (kept for API compatibility)\n * @returns Available port number\n * @throws Error if no ports available in ±10 range around hash-based port\n */\nexport async function getFreeHashPort(workspacePath: string, _startPort: number = DEFAULT_PORT): Promise<number> {\n // Calculate this workspace's hash-based port\n const preferredPort = calculateHashPort(workspacePath);\n\n // Try preferred port first\n if (await isPortAvailable(preferredPort)) {\n logger.printInfoLog(`Using workspace-preferred port: ${preferredPort}`);\n return preferredPort;\n }\n\n // If preferred port is taken, try nearby ports (±10 range)\n // This handles edge case where same workspace runs twice simultaneously\n logger.printInfoLog(`Preferred port ${preferredPort} occupied, trying nearby ports...`);\n for (let offset = 1; offset <= 10; offset++) {\n const portUp = preferredPort + offset;\n const portDown = preferredPort - offset;\n\n if (await isPortAvailable(portUp)) {\n logger.printInfoLog(`Using nearby port: ${portUp} (preferred was ${preferredPort})`);\n return portUp;\n }\n if (portDown > 1024 && (await isPortAvailable(portDown))) {\n logger.printInfoLog(`Using nearby port: ${portDown} (preferred was ${preferredPort})`);\n return portDown;\n }\n }\n\n // All ports in ±10 range are occupied\n throw new Error(`No available ports found in workspace-preferred range (${preferredPort - 10} to ${preferredPort + 10})`);\n}\n\nasync function waitForServerReady(url: string, timeoutMs: number): Promise<boolean> {\n const start = Date.now();\n const intervalMs = 400;\n\n while (Date.now() - start < timeoutMs) {\n const ok = await new Promise<boolean>(resolve => {\n const req = http.get(url, res => {\n res.resume();\n resolve(res.statusCode !== undefined && res.statusCode >= 200 && res.statusCode < 500);\n });\n req.on('error', () => resolve(false));\n req.setTimeout(500, () => req.destroy());\n });\n if (ok) return true;\n await new Promise(r => setTimeout(r, intervalMs));\n }\n\n return false;\n}\n\nexport class DevServerManager {\n private handle: DevServerHandle | null = null;\n\n constructor(private readonly params: { appPath: string; runCommand: string }) {}\n\n get current(): DevServerHandle | null {\n return this.handle;\n }\n\n async start(options: { timeoutMs: number } = { timeoutMs: 60_000 }): Promise<DevServerHandle> {\n if (this.handle) {\n return this.handle;\n }\n\n const port = await getFreeHashPort(this.params.appPath);\n const url = buildDevServerUrl(port);\n const { executable, args, needsDoubleDash } = parseCommandWithPortSupport(this.params.runCommand);\n const normalizedExecutable = normalizeExecutable(executable);\n const commandArgs = needsDoubleDash ? [...args, '--', '--port', String(port)] : [...args, '--port', String(port)];\n\n logger.printInfoLog(`Starting dev server: ${normalizedExecutable} ${commandArgs.join(' ')}`);\n\n const child = spawn(normalizedExecutable, commandArgs, {\n cwd: this.params.appPath,\n stdio: ['ignore', 'pipe', 'pipe'],\n env: {\n ...process.env,\n PORT: String(port),\n FORCE_COLOR: '1',\n },\n });\n\n const maxBytes = 1_000_000;\n let out = '';\n const push = (chunk: Buffer) => {\n out += chunk.toString('utf-8');\n if (out.length > maxBytes) {\n out = out.slice(out.length - maxBytes);\n }\n };\n child.stdout?.on('data', push);\n child.stderr?.on('data', push);\n\n // If our process exits, try to stop the child to avoid orphans.\n process.once('exit', () => {\n terminateChildProcess(child);\n });\n\n const ready = await waitForServerReady(url, options.timeoutMs);\n if (!ready) {\n const tail = out.trim();\n terminateChildProcess(child);\n throw new Error(`Dev server did not become ready at ${url} within ${options.timeoutMs}ms.\\n${tail}`);\n }\n\n this.handle = {\n child,\n port,\n url,\n outputTail: () => out.trim(),\n };\n\n logger.printSuccessLog(`Dev server ready at ${url}`);\n return this.handle;\n }\n\n async stop(): Promise<void> {\n if (!this.handle) return;\n const child = this.handle.child;\n this.handle = null;\n\n await new Promise<void>(resolve => {\n try {\n child.once('close', () => resolve());\n terminateChildProcess(child);\n } catch {\n resolve();\n }\n setTimeout(() => resolve(), 1500);\n });\n }\n\n async restart(options: { timeoutMs: number } = { timeoutMs: 60_000 }): Promise<DevServerHandle> {\n await this.stop();\n return await this.start(options);\n }\n}\n","/**\n * Unified Protocol Context Extraction\n *\n * Extracts all validation-relevant data from protocol in a single traversal.\n * Replaces the legacy multi-step extraction pipeline:\n * - extractFigmaTreeFromProtocol\n * - normalizeFigmaCoordinates\n * - FigmaNodeService\n * - extractElementMetadata\n *\n * Core principle: Protocol is the single source of truth. Extract once, use everywhere.\n */\n\nimport type { Protocol } from '../../../../types/protocol-types';\nimport type {\n ComponentInfo,\n ElementInfo,\n ElementMetadataRegistry,\n FigmaPosition,\n ValidationContext,\n ValidationFrameInfo,\n} from '../../../../types/validation-types';\nimport { workspaceManager } from '../../../../utils/workspace';\nimport type { WorkspaceStructure } from '../../../../types/workspace-types';\n\n/**\n * Extract unified validation context from protocol.\n *\n * Single traversal builds all needed maps:\n * - Component info (id, name, path)\n * - Element metadata with normalized positions\n * - Figma positions with offset applied\n *\n * @param protocol - Protocol structure tree (Protocol)\n * @returns ValidationContext containing all data needed for validation\n */\nexport function extractValidationContext(protocol: Protocol): ValidationContext {\n // Extract offset from root bounding box\n const offset = extractOffset(protocol);\n\n const elements = new Map<string, ElementInfo>();\n const components = new Map<string, ComponentInfo>();\n const elementToComponent = new Map<string, ComponentInfo>();\n const figmaPositions: Record<string, FigmaPosition | undefined> = {};\n\n // Single traversal of protocol tree\n traverseProtocol(protocol, node => {\n const componentInfo: ComponentInfo = {\n id: node.id,\n name: node.data.name,\n path: node.data.componentPath ?? node.data.path ?? node.data.kebabName ?? node.id,\n };\n components.set(node.id, componentInfo);\n\n // Determine item type based on children\n const hasChildren = Array.isArray(node.children) && node.children.length > 0;\n const itemType: 'frame' | 'component' = hasChildren ? 'frame' : 'component';\n\n // Extract elements from this component\n if (node.data.elements && Array.isArray(node.data.elements)) {\n extractElementsRecursive(\n node.data.elements as ValidationFrameInfo[],\n componentInfo,\n itemType,\n elements,\n elementToComponent,\n figmaPositions,\n offset\n );\n }\n });\n\n return { offset, elements, components, elementToComponent, figmaPositions };\n}\n\n/**\n * Extract coordinate offset from protocol root.\n */\nfunction extractOffset(protocol: Protocol): { x: number; y: number } {\n // First try: protocol.data.layout.boundingBox (pre-computed CSS coordinates)\n if (protocol.data.layout?.boundingBox) {\n return {\n x: protocol.data.layout.boundingBox.left,\n y: protocol.data.layout.boundingBox.top,\n };\n }\n\n // Second try: first element's absoluteBoundingBox (Figma coordinates)\n const firstElement = protocol.data.elements?.[0] as ValidationFrameInfo | undefined;\n if (firstElement?.absoluteBoundingBox) {\n return {\n x: firstElement.absoluteBoundingBox.x,\n y: firstElement.absoluteBoundingBox.y,\n };\n }\n\n // Default: no offset\n return { x: 0, y: 0 };\n}\n\n/**\n * Traverse protocol structure tree and invoke callback for each node.\n */\nfunction traverseProtocol(node: Protocol, callback: (node: Protocol) => void): void {\n callback(node);\n if (node.children && Array.isArray(node.children)) {\n for (const child of node.children) {\n traverseProtocol(child, callback);\n }\n }\n}\n\n/**\n * Recursively extract elements from Figma node tree.\n * Applies offset to positions and builds element metadata.\n */\nfunction extractElementsRecursive(\n elements: ValidationFrameInfo[],\n componentInfo: ComponentInfo,\n itemType: 'frame' | 'component',\n elementsMap: Map<string, ElementInfo>,\n elementToComponent: Map<string, ComponentInfo>,\n figmaPositions: Record<string, FigmaPosition | undefined>,\n offset: { x: number; y: number }\n): void {\n for (const element of elements) {\n if (!element || !element.id) continue;\n\n const bbox = element.absoluteBoundingBox;\n const position: FigmaPosition = bbox\n ? {\n x: bbox.x - offset.x,\n y: bbox.y - offset.y,\n w: bbox.width,\n h: bbox.height,\n }\n : { x: 0, y: 0, w: 0, h: 0 };\n\n // Store normalized Figma position\n figmaPositions[element.id] = position;\n\n // Store element metadata\n elementsMap.set(element.id, {\n id: element.id,\n name: element.name,\n type: element.type,\n position,\n layoutMode: element.layoutMode,\n primaryAxisAlignItems: element.primaryAxisAlignItems,\n counterAxisAlignItems: element.counterAxisAlignItems,\n itemSpacing: element.itemSpacing,\n paddingTop: element.paddingTop,\n paddingRight: element.paddingRight,\n paddingBottom: element.paddingBottom,\n paddingLeft: element.paddingLeft,\n constraints: element.constraints as Record<string, unknown> | undefined,\n parentComponentId: componentInfo.id,\n parentComponentName: componentInfo.name,\n parentComponentPath: componentInfo.path,\n parentItemType: itemType,\n });\n\n // Store element-to-component mapping\n elementToComponent.set(element.id, componentInfo);\n\n // Recurse into children and frames\n if (element.children && Array.isArray(element.children)) {\n extractElementsRecursive(element.children, componentInfo, itemType, elementsMap, elementToComponent, figmaPositions, offset);\n }\n if (element.frames && Array.isArray(element.frames)) {\n extractElementsRecursive(element.frames, componentInfo, itemType, elementsMap, elementToComponent, figmaPositions, offset);\n }\n }\n}\n\n// ============================================================================\n// Compatibility Helpers\n// ============================================================================\n\n/**\n * Extract component paths from context and resolve to absolute filesystem paths.\n *\n * Transforms protocol alias paths (@/components/Button) to absolute paths\n * (/Users/.../my-app/src/components/Button/index.tsx)\n *\n * @param context - Validation context with component info\n * @param workspace - Workspace structure for path resolution\n * @returns Map of component IDs to absolute filesystem paths\n */\nexport function extractComponentPaths(context: ValidationContext, workspace: WorkspaceStructure): Record<string, string> {\n const paths: Record<string, string> = {};\n for (const [id, info] of context.components) {\n if (info.path) {\n paths[id] = workspaceManager.resolveAppSrc(workspace, workspaceManager.resolveComponentPath(info.path));\n }\n }\n return paths;\n}\n\n/**\n * Convert ValidationContext to ElementMetadataRegistry for compatibility.\n */\nexport function toElementMetadataRegistry(context: ValidationContext): ElementMetadataRegistry {\n const elements = new Map<\n string,\n {\n id: string;\n name: string;\n parentComponentId: string;\n parentComponentName: string;\n parentComponentPath: string;\n parentItemType: 'frame' | 'component';\n }\n >();\n\n for (const [id, element] of context.elements) {\n elements.set(id, {\n id: element.id,\n name: element.name,\n parentComponentId: element.parentComponentId,\n parentComponentName: element.parentComponentName,\n parentComponentPath: element.parentComponentPath,\n parentItemType: element.parentItemType,\n });\n }\n\n return { elements, components: context.components };\n}\n","/**\n * Position validation for a single iteration.\n * Captures browser positions, groups by component, identifies misaligned components.\n */\n\nimport { logger } from '../../../utils/logger';\nimport { PositionTool } from '../../../tools/position-tool';\nimport type { MisalignedComponent } from '../../../types/validation-types';\nimport type { ValidationIterationConfig, ValidationIterationResult, SkippedElement } from '../types';\n\n/**\n * Validate positions by capturing browser positions and comparing with Figma.\n * This function integrates with the existing captureBrowserPositions tool\n * and transforms its output into the format expected by the validation loop.\n *\n * @param config - Validation iteration configuration\n * @returns Validation result with MAE, SAE, misaligned components, and viewport\n */\nexport async function validatePositions(config: ValidationIterationConfig): Promise<ValidationIterationResult> {\n const { serverUrl, figmaThumbnailUrl, protocol, positionThreshold, validationContext, elementRegistry, resolvedComponentPaths } =\n config;\n\n const positionTool = new PositionTool();\n\n // Type assertion: captureBrowserPositions accepts flexible input types for compatibility\n const captureResult = await positionTool.capturePosition({\n protocol,\n validationContext,\n url: serverUrl,\n figmaThumbnailUrl,\n positionThreshold,\n returnScreenshot: true,\n elementRegistry,\n });\n\n // Create resolved elementToComponent mapping with absolute paths\n // Replace alias paths with absolute filesystem paths from resolvedComponentPaths\n const resolvedElementToComponent = new Map<string, { id: string; name: string; path: string }>();\n for (const [elementId, componentInfo] of validationContext.elementToComponent) {\n const resolvedPath = resolvedComponentPaths[componentInfo.id] || componentInfo.path;\n resolvedElementToComponent.set(elementId, {\n id: componentInfo.id,\n name: componentInfo.name,\n path: resolvedPath,\n });\n }\n\n const aggregated = positionTool.aggregateElements(captureResult.positions, resolvedElementToComponent, positionThreshold);\n const misalignedComponents = aggregated.misalignedComponents as unknown as MisalignedComponent[];\n const skippedElements = aggregated.skippedElements as unknown as SkippedElement[];\n\n // Calculate SAE\n const sae = misalignedComponents.reduce((sum, comp) => {\n const [errorX, errorY] = comp.validationReport.absoluteError;\n return sum + errorX + errorY;\n }, 0);\n\n logger.printInfoLog(`Found ${misalignedComponents.length} misaligned components`);\n\n return {\n mae: captureResult.metadata.mae,\n sae,\n misalignedComponents,\n skippedElements,\n viewport: captureResult.metadata.viewport,\n screenshots: captureResult.screenshot\n ? {\n renderSnap: captureResult.screenshot,\n }\n : undefined,\n };\n}\n","import { tools } from 'evoltagent';\n\nimport { logger } from '../../utils/logger';\nimport { captureBrowserPositions } from './utils/capture-position';\nimport { calculatePositionMetrics } from './utils/position-metrics';\nimport { calculateComponentMetrics, toRect } from './utils/aggregate-elements';\nimport type {\n AggregateElementsResult,\n BrowserPositionInput,\n ComponentData,\n ComponentMisalignment,\n ElementAbsolutePosition,\n PositionToolMetrics,\n PositionValidationOutput,\n SkippedElement,\n} from './types';\n\n@tools({\n capturePosition: {\n description:\n 'Capture viewport-relative positions in the browser and compare to Figma absoluteBoundingBox, returning per-element deltas and metrics.',\n params: [{ name: 'input', type: 'object', description: 'BrowserPositionInput (figmaJSON, structure, url, etc.)' }],\n returns: { type: 'object', description: 'PositionValidationOutput containing metadata, positions, and errors.' },\n },\n aggregateElements: {\n description:\n 'Aggregate element-level rectangles into component-level bounds and return misaligned components based on aggregate distance threshold.',\n params: [\n { name: 'positions', type: 'object', description: 'Positions keyed by elementId (from capturePosition).' },\n {\n name: 'elementToComponentMap',\n type: 'object',\n description: 'Mapping from elementId -> {id,name,path} for parent component (built from structure tree).',\n },\n { name: 'positionThreshold', type: 'number', description: 'Pixel threshold for aggregate distance.' },\n ],\n returns: { type: 'object', description: 'AggregateElementsResult: misalignedComponents + skippedElements.' },\n },\n computeMetrics: {\n description: 'Compute MAE/MSE/RMSE/accuracy metrics from element positions, and SAE from component misalignments.',\n params: [\n { name: 'positions', type: 'object', description: 'Positions keyed by elementId (from capturePosition).' },\n {\n name: 'misalignedComponents',\n type: 'object',\n description: 'Optional component misalignments (from aggregateElements) used to compute SAE.',\n optional: true,\n },\n ],\n returns: { type: 'object', description: 'PositionToolMetrics (ValidationMetrics + sae).' },\n },\n})\nexport class PositionTool {\n async capturePosition(input: BrowserPositionInput): Promise<PositionValidationOutput> {\n return await captureBrowserPositions(input);\n }\n\n /**\n * Deterministic in-process aggregation.\n * NOTE: Map-based inputs are not JSON-friendly for future agent calls; we can add a JSON form later.\n */\n aggregateElements(\n positions: Record<string, ElementAbsolutePosition>,\n elementToComponentMap: Map<string, { id: string; name: string; path: string }>,\n positionThreshold: number\n ): AggregateElementsResult {\n const componentMap = new Map<string, ComponentData>();\n const skippedElements: SkippedElement[] = [];\n\n for (const [elementId, position] of Object.entries(positions)) {\n if (!position.figmaPosition) {\n skippedElements.push({\n elementId,\n reason: 'no_figma_position',\n details: 'Element exists in render but has no corresponding Figma position data',\n });\n continue;\n }\n\n const component = elementToComponentMap.get(elementId);\n if (!component) {\n skippedElements.push({\n elementId,\n reason: 'missing_component_mapping',\n details: 'Element has no component mapping in structure tree',\n });\n continue;\n }\n\n if (!componentMap.has(component.id)) {\n componentMap.set(component.id, {\n componentId: component.id,\n componentName: component.name,\n componentPath: component.path,\n elementIds: [],\n positions: [],\n targets: [],\n errors: [],\n });\n }\n\n const compData = componentMap.get(component.id)!;\n compData.elementIds.push(elementId);\n compData.positions.push(toRect(position.boundingBox));\n compData.targets.push(toRect(position.figmaPosition));\n compData.errors.push({\n x: Math.abs(position.metrics?.xDelta ?? 0),\n y: Math.abs(position.metrics?.yDelta ?? 0),\n });\n }\n\n this.logSkippedElementsSummary(skippedElements);\n\n const misalignedComponents: ComponentMisalignment[] = [];\n\n for (const compData of componentMap.values()) {\n if (compData.positions.length === 0 || compData.targets.length === 0) {\n for (const elemId of compData.elementIds) {\n skippedElements.push({\n elementId: elemId,\n reason: 'incomplete_data',\n details: `Component ${compData.componentName} has ${compData.positions.length} positions, ${compData.targets.length} targets`,\n });\n }\n continue;\n }\n\n const metrics = calculateComponentMetrics(compData, positionThreshold);\n if (!metrics) {\n continue;\n }\n\n const { currentBounds, targetBounds, error } = metrics;\n misalignedComponents.push({\n name: compData.componentName,\n componentId: compData.componentId,\n elementIds: compData.elementIds,\n path: compData.componentPath,\n validationReport: {\n currentPosition: [currentBounds.minX, currentBounds.minY],\n targetPosition: [targetBounds.minX, targetBounds.minY],\n absoluteError: [error.errorX, error.errorY],\n },\n currentX: currentBounds.minX,\n currentY: currentBounds.minY,\n targetX: targetBounds.minX,\n targetY: targetBounds.minY,\n currentWidth: currentBounds.width,\n currentHeight: currentBounds.height,\n targetWidth: targetBounds.width,\n targetHeight: targetBounds.height,\n distance: error.distance,\n });\n }\n\n return { misalignedComponents, skippedElements };\n }\n\n computeMetrics(\n positions: Record<string, ElementAbsolutePosition>,\n misalignedComponents?: ComponentMisalignment[]\n ): PositionToolMetrics {\n const metrics = calculatePositionMetrics(positions);\n const sae =\n misalignedComponents?.reduce((sum, comp) => {\n const [errorX, errorY] = comp.validationReport.absoluteError;\n return sum + errorX + errorY;\n }, 0) ?? 0;\n\n return { ...metrics, sae: Math.round(sae * 100) / 100 };\n }\n\n private logSkippedElementsSummary(skippedElements: SkippedElement[]): void {\n if (skippedElements.length === 0) {\n return;\n }\n\n const byReason: Record<SkippedElement['reason'], number> = {\n missing_component_mapping: 0,\n incomplete_data: 0,\n no_figma_position: 0,\n };\n\n for (const elem of skippedElements) {\n byReason[elem.reason] += 1;\n }\n\n const summary = (Object.entries(byReason) as Array<[SkippedElement['reason'], number]>)\n .filter(([, count]) => count > 0)\n .map(([reason, count]) => `${count} ${reason.replace(/_/g, ' ')}`)\n .join(', ');\n\n const firstFew = skippedElements\n .slice(0, 3)\n .map(e => e.elementId)\n .join(', ');\n\n logger.printWarnLog(`Skipped ${skippedElements.length} element(s): ${summary}. First few: ${firstFew}`);\n }\n}\n","/// <reference lib=\"dom\" />\n\nimport type { Browser, Page } from 'playwright';\n\nimport { DEFAULT_TIMEOUT, DEFAULT_VIEWPORT, POSITION_THRESHOLD, SELECTOR_WAIT_TIMEOUT } from '../../../nodes/validation/constants';\nimport { launchChromiumWithAutoInstall } from '../../../nodes/validation/utils/playwright/launcher';\nimport { logger } from '../../../utils/logger';\n\nimport type { BrowserPositionInput, ElementAbsolutePosition, PositionMetrics, PositionValidationOutput } from '../types';\nimport { calculatePositionMetrics } from './position-metrics';\n\n/**\n * Captures viewport-relative positions of elements using Playwright + getBoundingClientRect().\n */\nexport async function captureBrowserPositions(input: BrowserPositionInput): Promise<PositionValidationOutput> {\n const url = input.url;\n const timeout = input.timeout ?? DEFAULT_TIMEOUT;\n const positionThreshold = input.positionThreshold ?? POSITION_THRESHOLD;\n\n const errors: string[] = [];\n let browser: Browser | null = null;\n let page: Page | null = null;\n\n try {\n // Use pre-computed Figma positions from validation context (offset already applied)\n const figmaPositions = input.validationContext.figmaPositions;\n const designOffset = input.validationContext.offset;\n\n // Use pre-built element registry (eliminates tree traversals)\n const allElements = Array.from(input.elementRegistry.elements.values()).map(e => ({\n id: e.id,\n name: e.name,\n parentItemId: e.parentComponentId,\n parentItemName: e.parentComponentName,\n parentItemType: e.parentItemType,\n }));\n\n let viewport = input.viewport ?? DEFAULT_VIEWPORT;\n if (input.figmaThumbnailUrl && !input.viewport) {\n const { fetchThumbnailDimensions } = await import('./fetch-thumbnail-dimensions');\n const thumbnailDimensions = await fetchThumbnailDimensions(input.figmaThumbnailUrl);\n if (thumbnailDimensions) {\n viewport = { width: thumbnailDimensions.width, height: thumbnailDimensions.height };\n logger.printInfoLog(`Using viewport dimensions from Figma thumbnail: ${viewport.width}×${viewport.height}px`);\n } else {\n logger.printWarnLog(`Using default viewport dimensions: ${viewport.width}×${viewport.height}px`);\n }\n }\n\n try {\n browser = await launchChromiumWithAutoInstall({ headless: true });\n } catch (launchError) {\n throw new Error(`Failed to launch Playwright Chromium browser for position validation: ${(launchError as Error).message}`);\n }\n\n const context = await browser.newContext({ viewport });\n page = await context.newPage();\n\n try {\n await page.goto(url, { waitUntil: 'domcontentloaded', timeout });\n } catch (error) {\n throw new Error(`Failed to load ${url}. Make sure the development server is running. Error: ${(error as Error).message}`);\n }\n\n if (input.waitForSelector) {\n try {\n await page.waitForSelector(input.waitForSelector, { timeout: SELECTOR_WAIT_TIMEOUT });\n } catch {\n errors.push(`Warning: waitForSelector \"${input.waitForSelector}\" timed out`);\n }\n }\n\n let screenshot: string | undefined;\n if (input.returnScreenshot) {\n try {\n const buffer = await page.screenshot({ fullPage: true, type: 'png' });\n screenshot = `data:image/png;base64,${buffer.toString('base64')}`;\n } catch (error) {\n errors.push(`Warning: Failed to capture screenshot: ${(error as Error).message}`);\n }\n }\n\n const positions: Record<string, ElementAbsolutePosition> = {};\n let capturedCount = 0;\n\n for (const element of allElements) {\n try {\n const escapedId = element.id.replace(/:/g, '\\\\:');\n const selector = `[id=\"${escapedId}\"]`;\n\n const result = await page.evaluate((sel: string) => {\n const el = document.querySelector(sel);\n if (!el) return null;\n\n const rect = el.getBoundingClientRect();\n const style = window.getComputedStyle(el);\n\n if (rect.width === 0 && rect.height === 0) {\n return null;\n }\n\n return {\n boundingBox: {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n top: rect.top,\n left: rect.left,\n right: rect.right,\n bottom: rect.bottom,\n },\n computedStyle: {\n position: style.position,\n display: style.display,\n top: style.top,\n left: style.left,\n right: style.right,\n bottom: style.bottom,\n transform: style.transform,\n tagName: el.tagName.toLowerCase(),\n },\n };\n }, selector);\n\n if (!result) {\n errors.push(`Element ${element.id} not found in DOM or has no dimensions`);\n continue;\n }\n\n const figmaPos = figmaPositions[element.id];\n\n let metrics: PositionMetrics | undefined;\n if (figmaPos) {\n const xDelta = result.boundingBox.x - figmaPos.x;\n const yDelta = result.boundingBox.y - figmaPos.y;\n const xOffset = Math.abs(xDelta);\n const yOffset = Math.abs(yDelta);\n const absoluteDistance = Math.sqrt(xOffset ** 2 + yOffset ** 2);\n\n metrics = {\n xOffset: Math.round(xOffset * 100) / 100,\n yOffset: Math.round(yOffset * 100) / 100,\n xDelta: Math.round(xDelta * 100) / 100,\n yDelta: Math.round(yDelta * 100) / 100,\n absoluteDistance: Math.round(absoluteDistance * 100) / 100,\n status: absoluteDistance <= positionThreshold ? 'accurate' : 'misaligned',\n };\n }\n\n positions[element.id] = {\n elementId: element.id,\n elementName: element.name,\n parentItemId: element.parentItemId,\n parentItemName: element.parentItemName,\n parentItemType: element.parentItemType,\n boundingBox: {\n x: Math.round(result.boundingBox.x * 100) / 100,\n y: Math.round(result.boundingBox.y * 100) / 100,\n width: Math.round(result.boundingBox.width * 100) / 100,\n height: Math.round(result.boundingBox.height * 100) / 100,\n top: Math.round(result.boundingBox.top * 100) / 100,\n left: Math.round(result.boundingBox.left * 100) / 100,\n right: Math.round(result.boundingBox.right * 100) / 100,\n bottom: Math.round(result.boundingBox.bottom * 100) / 100,\n },\n computedStyle: result.computedStyle,\n figmaPosition: figmaPos ? { x: figmaPos.x, y: figmaPos.y, width: figmaPos.w, height: figmaPos.h } : undefined,\n metrics,\n };\n\n capturedCount++;\n } catch (error) {\n const errorMsg =\n `Failed to capture position for ${element.id}` +\n (element.name ? ` (${element.name})` : '') +\n ` in ${element.parentItemName || 'unknown component'}` +\n `: ${(error as Error).message}`;\n errors.push(errorMsg);\n }\n }\n\n const maeMetrics = calculatePositionMetrics(positions);\n\n return {\n metadata: {\n capturedAt: new Date().toISOString(),\n totalItems: allElements.length,\n capturedItems: capturedCount,\n ...maeMetrics,\n url,\n viewport,\n designOffset,\n },\n positions,\n errors,\n screenshot,\n };\n } finally {\n if (page) {\n await page.close().catch(() => {});\n }\n if (browser) {\n await browser.close().catch(() => {});\n }\n }\n}\n","/**\n * For 100% Figma replication, all elements matter equally (standard MAE, not area-weighted).\n */\n\nimport type { ElementAbsolutePosition, ValidationMetrics } from '../types';\n\nexport function calculatePositionMetrics(positions: Record<string, ElementAbsolutePosition>): ValidationMetrics {\n const positionValues = Object.values(positions);\n const comparableItems = positionValues.filter(p => p.metrics);\n const comparableCount = comparableItems.length;\n\n if (comparableCount === 0) {\n return {\n mae: 0,\n mse: 0,\n rmse: 0,\n accurateItems: 0,\n misalignedItems: 0,\n comparableItems: 0,\n accuracyRate: 0,\n averageDistance: 0,\n maxDistance: 0,\n };\n }\n\n const distances = comparableItems.map(p => p.metrics!.absoluteDistance);\n\n const mae = distances.reduce((sum, d) => sum + d, 0) / comparableCount;\n const mse = distances.reduce((sum, d) => sum + d * d, 0) / comparableCount;\n const rmse = Math.sqrt(mse);\n const maxDistance = Math.max(...distances);\n\n const accurateItems = comparableItems.filter(p => p.metrics!.status === 'accurate').length;\n const misalignedItems = comparableItems.filter(p => p.metrics!.status === 'misaligned').length;\n const accuracyRate = comparableCount > 0 ? (accurateItems / comparableCount) * 100 : 0;\n\n return {\n mae: Math.round(mae * 100) / 100,\n mse: Math.round(mse * 100) / 100,\n rmse: Math.round(rmse * 100) / 100,\n accurateItems,\n misalignedItems,\n comparableItems: comparableCount,\n accuracyRate: Math.round(accuracyRate * 100) / 100,\n averageDistance: Math.round(mae * 100) / 100,\n maxDistance: Math.round(maxDistance * 100) / 100,\n };\n}\n","/**\n * Aggregate element-level rectangles into component-level bounds and misalignment metrics.\n */\n\n/**\n * Rectangle with position and dimensions.\n */\nexport interface Rectangle {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * Converts a rect-like object to a proper Rectangle type.\n */\nexport function toRect(rectLike: { x: number; y: number; width: number; height: number }): Rectangle {\n return { x: rectLike.x, y: rectLike.y, width: rectLike.width, height: rectLike.height };\n}\n\n/**\n * Aggregate bounding box result.\n */\nexport interface BoundingBox {\n minX: number;\n minY: number;\n maxRight: number;\n maxBottom: number;\n width: number;\n height: number;\n}\n\n/**\n * Position error calculation result.\n */\nexport interface PositionError {\n errorX: number;\n errorY: number;\n distance: number;\n}\n\n/**\n * Minimum shape required for component-level aggregation.\n */\nexport interface ComponentAggregationData {\n positions: Rectangle[];\n targets: Rectangle[];\n}\n\nexport function calculateAggregateBoundingBox(rectangles: Rectangle[]): BoundingBox {\n if (rectangles.length === 0) {\n throw new Error('Cannot calculate bounding box from empty array');\n }\n\n const minX = Math.min(...rectangles.map(r => r.x));\n const minY = Math.min(...rectangles.map(r => r.y));\n const maxRight = Math.max(...rectangles.map(r => r.x + r.width));\n const maxBottom = Math.max(...rectangles.map(r => r.y + r.height));\n\n return {\n minX,\n minY,\n maxRight,\n maxBottom,\n width: maxRight - minX,\n height: maxBottom - minY,\n };\n}\n\nexport function calculatePositionError(current: BoundingBox, target: BoundingBox): PositionError {\n const errorX = Math.abs(target.minX - current.minX);\n const errorY = Math.abs(target.minY - current.minY);\n const distance = Math.sqrt(errorX ** 2 + errorY ** 2);\n\n return { errorX, errorY, distance };\n}\n\nexport function calculateComponentMetrics(\n compData: ComponentAggregationData,\n positionThreshold: number\n): {\n currentBounds: BoundingBox;\n targetBounds: BoundingBox;\n error: PositionError;\n} | null {\n if (compData.positions.length === 0 || compData.targets.length === 0) {\n return null;\n }\n\n const currentBounds = calculateAggregateBoundingBox(compData.positions);\n const targetBounds = calculateAggregateBoundingBox(compData.targets);\n const error = calculatePositionError(currentBounds, targetBounds);\n\n if (error.distance <= positionThreshold) {\n return null;\n }\n\n return { currentBounds, targetBounds, error };\n}\n","import { spawnSync } from 'child_process';\nimport { createRequire } from 'module';\nimport fs from 'fs';\nimport path from 'path';\nimport { logger } from './logger';\n\nconst require = createRequire(import.meta.url);\n\nexport function detectPackageManager(cwd: string = process.cwd()): 'npm' | 'yarn' | 'pnpm' {\n if (fs.existsSync(path.join(cwd, 'pnpm-lock.yaml'))) return 'pnpm';\n if (fs.existsSync(path.join(cwd, 'yarn.lock'))) return 'yarn';\n return 'npm';\n}\n\nexport function isPackageInstalled(packageName: string): boolean {\n try {\n require.resolve(packageName);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction formatValidationDependencyHelp(missing: string[]): string {\n const isWin = process.platform === 'win32';\n const globalInstall = [\n 'npm install -g playwright sharp',\n isWin ? 'npx playwright install chromium' : 'npx playwright install chromium',\n ].join('\\n');\n\n const localInstall = [\n 'npm install -D playwright sharp',\n isWin ? 'npx playwright install chromium' : 'npx playwright install chromium',\n ].join('\\n');\n\n const pnpmGlobal = ['pnpm add -g playwright sharp', 'pnpm exec playwright install chromium'].join('\\n');\n const pnpmLocal = ['pnpm add -D playwright sharp', 'pnpm exec playwright install chromium'].join('\\n');\n\n return [\n `Missing optional validation dependencies: ${missing.join(', ')}`,\n '',\n 'Validation requires Playwright (browsers) and Sharp (image processing).',\n 'These dependencies are NOT bundled with coderio by default to keep installation lightweight.',\n '',\n 'Recommended (global install):',\n globalInstall,\n '',\n 'Or install in your current project:',\n localInstall,\n '',\n 'If you use pnpm:',\n '',\n 'Global:',\n pnpmGlobal,\n '',\n 'Local (project):',\n pnpmLocal,\n ].join('\\n');\n}\n\nexport function assertValidationDependenciesInstalled(): void {\n const missing: string[] = [];\n if (!isPackageInstalled('sharp')) missing.push('sharp');\n if (!isPackageInstalled('playwright')) missing.push('playwright');\n\n if (missing.length === 0) {\n return;\n }\n\n throw new Error(formatValidationDependencyHelp(missing));\n}\n\nexport function ensurePackageInstalled(packageName: string, packageNameInRegistry?: string) {\n const pkgName = packageNameInRegistry || packageName;\n\n if (isPackageInstalled(packageName)) {\n return;\n }\n\n logger.printInfoLog(`Package '${packageName}' is required for validation but not installed.`);\n const pm = detectPackageManager();\n\n // For dependencies that should be devDependencies in the user's project if they are using coderio as a tool\n // But since this runs at runtime, we just install them.\n const installArgs = pm === 'npm' ? 'install' : 'add';\n const pmCmd = process.platform === 'win32' ? `${pm}.cmd` : pm;\n const installCmdDisplay = `${pmCmd} ${installArgs} ${pkgName}`;\n\n logger.printInfoLog(`Installing ${pkgName} using ${pm}...`);\n logger.printInfoLog(`Command: ${installCmdDisplay}`);\n\n try {\n const result = spawnSync(pmCmd, [installArgs, pkgName], {\n stdio: 'inherit',\n cwd: process.cwd(),\n shell: process.platform === 'win32',\n });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw new Error(`Command exited with code ${result.status}`);\n }\n logger.printSuccessLog(`Successfully installed ${pkgName}.`);\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to install ${pkgName}: ${errorMsg}. Please install it manually.`);\n }\n}\n\nexport function ensureValidationDependencies(): void {\n // Default behavior: only assert presence (do not modify user environment).\n // Auto-installing heavy native deps at runtime can fail and harms UX.\n // If you still want auto-install, call ensurePackageInstalled(...) explicitly from your own wrapper.\n assertValidationDependenciesInstalled();\n\n // NOTE: We intentionally do not preinstall Playwright browsers here.\n // The Playwright launcher has an auto-install fallback for missing Chromium binaries.\n}\n","import { GraphState } from '../../state';\nimport { logger } from '../../utils/logger';\nimport { processNode, injectRootComponentToApp } from './utils';\nimport { loadCodeCache } from '../../utils/code-cache';\n\n/**\n * Main code generation node function\n * Generates React components from the page structure tree\n */\nexport async function generateCode(state: GraphState) {\n try {\n logger.printInfoLog('🚀 Starting Code Generation...');\n\n // Validate required state fields\n if (!state.protocol) {\n throw new Error('No protocol data found');\n }\n\n // Load code cache\n const cache = loadCodeCache(state.workspace);\n\n // Process the entire node tree (cache is saved incrementally after each component)\n const totalComponents = await processNode(state, cache);\n\n // Inject root component to App.tsx (cache is saved after injection)\n await injectRootComponentToApp(state, cache);\n\n logger.printSuccessLog(`✨ Code generation completed! Generated ${totalComponents} components`);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Code generation failed: ${errorMessage}`);\n }\n}\n","import fs from 'fs';\nimport { GraphState } from '../../state';\nimport { logger } from '../../utils/logger';\nimport { callModel } from '../../utils/call-model';\nimport { promisePool } from '../../utils/promise-pool';\nimport { generateFramePrompt, generateComponentPrompt, injectRootComponentPrompt } from './prompt';\nimport { Protocol } from '../../types';\nimport { createFiles, writeFile } from '../../utils/file';\nimport { DEFAULT_APP_CONTENT, DEFAULT_STYLING } from './constants';\nimport path from 'path';\nimport { extractCode, extractFiles } from '../../utils/parser';\nimport { workspaceManager } from '../../utils/workspace';\nimport { CodeCache, isComponentGenerated, saveComponentGenerated, isAppInjected, saveAppInjected } from '../../utils/code-cache';\n\n/**\n * Process a node tree and generate code for all nodes\n * Uses post-order traversal (children first, then parent)\n */\nexport async function processNode(state: GraphState, cache: CodeCache): Promise<number> {\n // Read asset files list once for the entire generation run\n const assetFilesList = getAssetFilesList(state);\n\n // Flatten tree using post-order traversal (children first, then parent)\n const flatNodes = flattenPostOrder(state.protocol!);\n const total = flatNodes.length;\n\n if (total === 0) {\n logger.printWarnLog('No components found in structure to generate.');\n return 0;\n }\n\n logger.printInfoLog(`Processing ${total} nodes...`);\n\n let processedCount = 0;\n let skippedCount = 0;\n\n const processSingleNode = async (currentNode: Protocol) => {\n const componentName = currentNode.data.name || currentNode.data.componentName || 'UnknownComponent';\n const nodeId = currentNode.id;\n\n // Check if component is already generated\n if (isComponentGenerated(cache, nodeId)) {\n skippedCount++;\n logger.printInfoLog(`[${processedCount + skippedCount}/${total}] ⏭️ Skipping (cached): ${componentName}`);\n return;\n }\n\n const progressInfo = `[${++processedCount + skippedCount}/${total}]`;\n\n const isLeaf = !currentNode.children?.length;\n if (isLeaf) {\n await generateComponent(currentNode, state, assetFilesList, progressInfo);\n } else {\n await generateFrame(currentNode, state, assetFilesList, progressInfo);\n }\n\n // Mark component as generated and save immediately to prevent cache loss on interruption\n saveComponentGenerated(cache, nodeId, state.workspace);\n };\n\n // Process nodes with concurrency control\n await promisePool(flatNodes, processSingleNode);\n\n if (skippedCount > 0) {\n logger.printInfoLog(`⏭️ Skipped ${skippedCount} cached components`);\n }\n logger.printSuccessLog(`Generated ${processedCount} components`);\n return processedCount;\n}\n\n/**\n * Flatten tree into array using post-order traversal\n */\nexport function flattenPostOrder(node: Protocol): Protocol[] {\n const result: Protocol[] = [];\n\n function traverse(n: Protocol) {\n n.children?.forEach(child => traverse(child));\n result.push(n);\n }\n\n traverse(node);\n return result;\n}\n\n/**\n * Detect which rendering modes are used in this frame\n */\nexport function detectRenderingModes(node: Protocol): {\n hasStates: boolean;\n hasIndependentChildren: boolean;\n} {\n const hasStates = !!node.data.states?.length;\n\n let hasIndependentChildren = false;\n\n (node.children || []).forEach(child => {\n if (!child.data.componentName) {\n hasIndependentChildren = true;\n }\n });\n\n return { hasStates, hasIndependentChildren };\n}\n\n/**\n * Generate a frame/container component\n * Frames compose multiple child components based on layout\n */\nexport async function generateFrame(node: Protocol, state: GraphState, assetFilesList: string, progressInfo: string): Promise<void> {\n const frameName = node.data.name;\n logger.printInfoLog(`${progressInfo} 🖼️ Generating Frame: ${frameName}`);\n\n // Build children imports information\n const childrenImports = (node.children || []).map(child => ({\n name: child.data.name || '',\n path: child.data.path,\n }));\n\n // Detect rendering modes\n const renderingModes = detectRenderingModes(node);\n\n // Generate prompt\n const prompt = generateFramePrompt({\n frameDetails: JSON.stringify(node.data),\n childrenImports: JSON.stringify(childrenImports),\n styling: JSON.stringify(DEFAULT_STYLING),\n assetFiles: assetFilesList,\n renderingModes,\n });\n\n // Call AI model\n const code = await callModel({\n question: prompt,\n imageUrls: state.figmaInfo.thumbnail,\n });\n\n // Save generated files\n const componentPath = node.data.path || '';\n const filePath = workspaceManager.resolveAppSrc(state.workspace, workspaceManager.resolveComponentPath(componentPath));\n saveGeneratedCode(code, filePath);\n logger.printSuccessLog(`Successfully generated frame: ${frameName}`);\n}\n\n/**\n * Generate a component (leaf or reusable)\n * Components are self-contained UI elements driven by props\n */\nexport async function generateComponent(node: Protocol, state: GraphState, assetFilesList: string, progressInfo: string): Promise<void> {\n const componentName = node.data.componentName || node.data.name || 'UnknownComponent';\n const componentPath = node.data.componentPath || node.data.path || '';\n\n logger.printInfoLog(`${progressInfo} 📦 Generating Component: ${componentName}`);\n\n // Generate prompt\n const prompt = generateComponentPrompt({\n componentName,\n componentDetails: JSON.stringify(node.data),\n styling: JSON.stringify(DEFAULT_STYLING),\n assetFiles: assetFilesList,\n });\n\n // Call AI model\n const code = await callModel({\n question: prompt,\n imageUrls: state.figmaInfo.thumbnail,\n });\n\n // Save generated files\n const filePath = workspaceManager.resolveAppSrc(state.workspace, workspaceManager.resolveComponentPath(componentPath));\n saveGeneratedCode(code, filePath);\n logger.printSuccessLog(`Successfully generated component: ${componentName}`);\n}\n\n/**\n * Helper function to save generated code (handles both single and multi-file output)\n */\nexport function saveGeneratedCode(code: string, filePath: string): void {\n const files = extractFiles(code);\n\n if (files.length > 0) {\n // Multi-file output (e.g., index.tsx + index.module.less)\n createFiles({ files, filePath });\n } else {\n const extractedCode = extractCode(code);\n const folderPath = path.dirname(filePath);\n const fileName = path.basename(filePath);\n writeFile(folderPath, fileName, extractedCode);\n }\n}\n\n/**\n * Get list of available asset files for AI to match against\n */\nfunction getAssetFilesList(state: GraphState) {\n try {\n const assetsDir = workspaceManager.resolveAppSrc(state.workspace, 'assets');\n\n if (!fs.existsSync(assetsDir)) {\n return '';\n }\n\n const files = fs.readdirSync(assetsDir);\n return files.join(', ');\n } catch {\n return '';\n }\n}\n\n/**\n * Inject root component into App.tsx\n * Reads existing App.tsx, adds import and renders the root component\n */\nexport async function injectRootComponentToApp(state: GraphState, cache: CodeCache): Promise<void> {\n try {\n // Check if already injected\n if (isAppInjected(cache)) {\n logger.printInfoLog('⏭️ Skipping App.tsx injection (already injected)');\n return;\n }\n\n logger.printInfoLog('💉 Injecting root component into App.tsx...');\n\n // Construct App.tsx path\n const appTsxPath = workspaceManager.resolveAppSrc(state.workspace, 'App.tsx');\n\n // Read existing App.tsx or use default template\n let appContent: string;\n try {\n appContent = fs.readFileSync(appTsxPath, 'utf8');\n } catch {\n // Use default template if App.tsx doesn't exist\n logger.printWarnLog('App.tsx not found, using default template');\n appContent = DEFAULT_APP_CONTENT;\n }\n\n // Get root component information\n const rootNode = state.protocol!;\n const componentName = rootNode.data.name || 'RootComponent';\n const componentPath = rootNode.data.path || '';\n\n // Generate prompt\n const prompt = injectRootComponentPrompt({\n appContent,\n componentName,\n componentPath,\n });\n\n // Call AI model\n const updatedCode = await callModel({\n question: prompt,\n });\n\n // Extract code (no markdown blocks expected based on prompt requirements)\n const finalCode = updatedCode.includes('```') ? extractCode(updatedCode) : updatedCode.trim();\n\n // Write updated App.tsx\n const appFolderPath = path.dirname(appTsxPath);\n writeFile(appFolderPath, 'App.tsx', finalCode);\n\n // Mark as injected and save immediately\n saveAppInjected(cache, state.workspace);\n\n logger.printSuccessLog(`Successfully injected ${componentName} into App.tsx`);\n } catch (error) {\n logger.printErrorLog(`Failed to inject root component: ${(error as Error).message}`);\n // Don't throw - allow the process to continue even if injection fails\n }\n}\n","// ============================================\n// Common Prompt Sections\n// ============================================\n\nconst STYLING_GUIDELINES = `\n - **Style Consistency**: Implement styles using the technical stack and libraries listed in <styling>.\n - **Strict Restriction**: Absolutely ONLY use the technical stack and libraries listed in <styling>. Do NOT use any other styling methods, libraries, or frameworks (e.g., if clsx is not listed, do not use clsx).\n - **Default Styling**: If <styling> is empty or does not contain specific libraries, DEFAULT to standard vanilla CSS.\n \n - **Tailwind CSS + CSS Modules (CRITICAL)**:\n - If the stack includes BOTH Tailwind and CSS Modules (Less/SCSS), use them correctly:\n 1. **Tailwind utilities**: Use DIRECTLY in JSX className (e.g., \\`className=\"flex items-center gap-4\"\\`)\n 2. **CSS Modules**: Use ONLY for complex styles that can't be expressed with Tailwind utilities (e.g., gradients, animations, pseudo-elements)\n 3. **NEVER use \\`@apply\\` in CSS Module files** - it's a Tailwind-specific directive that doesn't work in Less/SCSS\n 4. Example correct usage:\n TSX: \\`<div className={\\`flex \\${styles.customGradient}\\`}>\\`\n Less: \\`.customGradient { background: linear-gradient(...); }\\`\n \n - **CSS Modules Only**: If the tech stack specifies CSS Modules without Tailwind:\n 1. Create a corresponding style file (e.g., \\`index.module.less\\`, \\`index.module.scss\\`, or \\`index.module.css\\`)\n 2. Import it as \\`import styles from './index.module.[ext]';\\` in the TSX\n 3. Define all styles in the style file using standard CSS/Less/SCSS syntax\n 4. Use \\`styles.className\\` in JSX`;\n\nconst ASSETS_HANDLING = `\n - **CRITICAL**: For any image URL starting with \\`@/assets\\`, you MUST import it at the top of the file.\n - **Asset Name Matching**: \n - Check the \\`<available_assets>\\` list for actual filenames in the project.\n - Asset filenames follow the pattern: \\`kebab-case-name-id1-id2.ext\\` (e.g., \"Star 2.svg\" → \"star-2-1-2861.svg\")\n - Match the base name (ignoring spaces, case, and ID suffix): \"@/assets/arXiv.svg\" → look for \"arxiv-*.svg\" in the list\n - Use the EXACT filename from the available assets list in your import.\n - Example: If available_assets contains \"arxiv-1-2956.svg\", use:\n \\`import ArXivIcon from '@/assets/arxiv-1-2956.svg';\\`\n - **Usage**: \\`<img src={ArXivIcon} />\\`, do not use backgroundImage property.\n - **NEVER** use the string path directly in JSX or styles.`;\n\nconst DOM_IDS_REQUIREMENT = `\n - Assign \\`id\\` attributes to the main container and any internal elements, matching \\`frame_details\\`.`;\n\nconst REACT_IMPORT_RULE = `\n - Do **NOT** include \\`import React from 'react';\\` at the top of the file.`;\n\nconst FILE_NAMING_CONVENTION = `\n - ALWAYS name the main component file \\`index.tsx\\`.\n - ALWAYS name the style file (if applicable) \\`index.module.[css|less|scss]\\`.\n - NEVER use PascalCase or other names for filenames (e.g., DO NOT use \\`MainFrame.tsx\\` or \\`Button.tsx\\`).`;\n\nconst OUTPUT_FORMAT = `\n <output_format>\n If only one file (TSX) is needed:\n \\`\\`\\`tsx\n // code...\n \\`\\`\\`\n\n If multiple files are needed (e.g., TSX + Styles):\n ## index.tsx\n \\`\\`\\`tsx\n // code...\n \\`\\`\\`\n\n ## index.module.[css|less|scss]\n \\`\\`\\`[css|less|scss]\n // styles...\n \\`\\`\\`\n </output_format>`;\n\n// ============================================\n// Prompt Functions\n// ============================================\n\n/**\n * Generate children rendering instructions based on detected modes\n */\nfunction generateChildrenPropsInstructions(modes: { hasStates: boolean; hasIndependentChildren: boolean }): string {\n const instructions: string[] = [];\n\n if (modes.hasStates) {\n instructions.push(`\n - **List Rendering (States-based)**:\n - Check if \\`<frame_details>\\` contains a \\`states\\` property (array).\n - Each state entry has: \\`state\\` (data array), \\`componentName\\`, \\`componentPath\\`.\n - Implementation:\n \\`\\`\\`tsx\n import ComponentName from 'path';\n \n {states[0].state.map((item, index) => (\n <ComponentName key={index} {...item} />\n ))}\n \\`\\`\\`\n - **CRITICAL - Only Use State Data**:\n - **ONLY** pass props that exist in the state data objects.\n - **DO NOT** add extra props like \\`content\\`, \\`className\\`, or any other fields not present in state.\n - **DO NOT** create or invent additional data - use exactly what's in the state array.\n - Example: If state has \\`{iconSrc, title, description}\\`, only pass those three props.\n - **Asset Imports**: If state data contains image paths (e.g., \\`imageSrc\\`, \\`iconSrc\\`), \n import them at the top and pass as values.`);\n }\n\n if (modes.hasIndependentChildren) {\n instructions.push(`\n - **Independent Components (No Props) - CRITICAL**:\n - If a child has NO \\`componentName\\` and NO \\`properties\\`, render as \\`<ComponentName />\\` without any props.\n - These components use default values or hardcoded content internally.`);\n }\n\n return instructions.join('\\n');\n}\n\nexport const generateFramePrompt = ({\n childrenImports,\n frameDetails,\n assetFiles,\n styling,\n renderingModes,\n}: {\n childrenImports: string;\n frameDetails: string;\n assetFiles?: string;\n styling: string;\n renderingModes: {\n hasStates: boolean;\n hasIndependentChildren: boolean;\n };\n}) => {\n return `\n<system_instructions>\n <role>\n You are a React Architect.\n Your task is to assemble a \"Frame\" component that composes multiple child components based on Figma layout data.\n </role>\n\n <input_context>\n <frame_details>${frameDetails}</frame_details>\n <children>${childrenImports}</children>\n <styling>${styling}</styling>\n ${assetFiles ? `<available_assets>Available asset files: ${assetFiles}</available_assets>` : ''}\n\n <frame_structure>\n The \\`frame_details\\` parameter contains:\n - \\`layout\\`: Layout information for the frame (flex/grid/absolute)\n - \\`elements\\`: Array of CSS styles and asset URLs for all elements in this component (colors, spacing, fonts, backgrounds, etc.)\n - \\`states\\` (optional): If present, this frame contains reusable components. Each state entry includes:\n * \\`state\\`: Array of data objects to be used as props for component instances\n * \\`componentName\\`: Name of the reusable component\n * \\`componentPath\\`: Import path for the component\n Use \\`states\\` data to render multiple instances of reusable components via \\`.map()\\`.\n </frame_structure>\n </input_context>\n\n <requirements>\n <req_1>\n **Children Components & Props (CRITICAL)**:\n - The \\`<children>\\` field describes child components with their import paths and prop types.\n${generateChildrenPropsInstructions(renderingModes)}\n \n - **Component Imports (CRITICAL)**:\n - You MUST use the exact import path provided in the \\`<children>\\` list for each component.\n - **Example**:\n - Provided: \\`{\"name\": \"TaskGrid\", \"path\": \"@/components/tasks-section/task-grid\"}\\`\n - CORRECT: \\`import TaskGrid from \"@/components/tasks-section/task-grid\";\\`\n - WRONG: \\`import TaskGrid from \"@/components/task-grid\";\\` (Do NOT do this!)\n </req_1>\n \n <req_2>\n **Layout & Styling**:\n - Use \\`layout_data\\` for dimensions, spacing, and flow (flex/grid).\n${STYLING_GUIDELINES}\n - Use responsive utilities provided by the chosen libraries to ensure the component is adaptive.\n - Use \\`css_context\\` for exact background styles, gradients, and shadows.\n - Use \\`relative\\` positioning for the container.\n - Use \\`spacing\\` field in <frame_details> to set the spacing between elements\n </req_2>\n \n <req_3>\n **Images & Assets**:\n${ASSETS_HANDLING}\n </req_3>\n \n <req_4>\n **DOM IDs**:\n${DOM_IDS_REQUIREMENT}\n </req_4>\n \n <req_5>\n **React Import**:\n${REACT_IMPORT_RULE}\n </req_5>\n \n <req_6>\n **File Naming**:\n${FILE_NAMING_CONVENTION}\n </req_6>\n </requirements>\n\n${OUTPUT_FORMAT}\n</system_instructions>\n`.trim();\n};\n\nexport const generateComponentPrompt = ({\n componentName,\n componentDetails,\n styling,\n assetFiles,\n}: {\n componentName: string;\n componentDetails: string;\n styling: string;\n assetFiles?: string;\n}) => {\n return `\n<system_instructions>\n <role>\n You are a Pixel-Perfect React Frontend Engineer.\n Your goal is to implement a specific UI component from Figma design data with 100% visual fidelity while ensuring header scroll to sections on click.\n </role>\n\n <input_context>\n <component_details>${componentDetails}</component_details>\n ${assetFiles ? `<available_assets>Available asset files: ${assetFiles}</available_assets>` : ''}\n <styling>${styling}</styling>\n\n <component_structure>\n The \\`component_details\\` parameter contains:\n - \\`elements\\`: Array of CSS styles and asset URLs for all elements in this component (colors, spacing, fonts, backgrounds, etc.)\n - \\`componentName\\` (optional): If present, indicates this is a **reusable component**; if absent, it's a **regular component**\n - \\`props\\` (optional): Props interface definition, only present when \\`componentName\\` exists\n </component_structure>\n\n <global_styles>\n .gradientBorder {\n position: relative;\n z-index: 0;\n &::before {\n content: '';\n position: absolute;\n inset: 0;\n padding: 1px; // From strokeWidth\n border-radius: inherit;\n background: linear-gradient(278deg, rgba(170, 255, 248, 0.60) 1.63%, rgba(71, 169, 255, 0.60) 104.34%); // From strokeColor\n -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);\n -webkit-mask-composite: destination-out;\n mask-composite: exclude;\n z-index: -1;\n }\n } \n </global_styles>\n\n <visual_reference>\n Refer to the conversation history for the page thumbnail and context.\n Use it to verify visual details like shadows, gradients, and spacing.\n </visual_reference>\n </input_context>\n\n <requirements>\n <req_1>\n **High Fidelity & Responsive**:\n${STYLING_GUIDELINES}\n - **CRITICAL**: Use exact design values from \\`component_details.elements\\` (colors, spacing, font sizes, gradients, shadows, etc.)\n - Use responsive utilities provided by the chosen libraries\n - For complex styles (gradients, shadows), use values from \\`elements\\` directly in CSS Modules or inline styles\n - For gradient rounded borders, CHECK \\`global_styles\\` for \\`.gradientBorder\\` mixin\n </req_1>\n\n <req_2>\n **DOM Identification**:\n - EVERY DOM element corresponding to a Figma node MUST have an \\`id\\` attribute.\n - The \\`id\\` value must match the \\`id\\` in the Figma Data exactly.\n - This is crucial for automated position validation.\n </req_2>\n\n <req_3>\n **Images & Assets**:\n${ASSETS_HANDLING}\n </req_3>\n\n <req_4>\n **Semantic HTML**:\n - Use semantic tags: \\`<header>\\`, \\`<footer>\\`, \\`<nav>\\`, \\`<article>\\`, \\`<section>\\`, \\`<button>\\`.\n </req_4>\n\n <req_5>\n **Layout Strategy**:\n - PREFER relative/flex/grid layout.\n - Use absolute positioning ONLY for decoration/overlays or if Figma structure explicitly implies overlay.\n </req_5>\n\n <req_6>\n **Naming Conventions**:\n - Component Name: **${componentName}** (PascalCase).\n - Export default.\n </req_6>\n\n <req_7>\n **Component Type & Props (CRITICAL)**:\n \n **IF \\`component_details.componentName\\` exists:**\n - This is a **reusable component**\n - Generate props interface from \\`component_details.props\\`: \\`interface ${componentName}Props { ... }\\`\n - Reference props in JSX: \\`{title}\\`, \\`<img src={iconSrc} />\\` (NOT hardcoded values)\n \n **IF \\`component_details.componentName\\` does NOT exist:**\n - This is a **regular component**\n - Do NOT generate props interface\n - Directly hardcode content from \\`component_details.elements\\` into JSX\n \n **Both types**: Do NOT repeat JSX to simulate grids; parent components handle iteration.\n </req_7>\n\n <req_9>\n **React Import**:\n${REACT_IMPORT_RULE}\n </req_9>\n \n <req_10>\n **File Naming**:\n${FILE_NAMING_CONVENTION}\n </req_10>\n </requirements>\n\n${OUTPUT_FORMAT}\n</system_instructions>\n`.trim();\n};\n\nexport const injectRootComponentPrompt = ({\n appContent,\n componentName,\n componentPath,\n}: {\n appContent: string;\n componentName: string;\n componentPath: string;\n}) => {\n return `\n<system_instructions>\n <role>\n You are a React code refactoring expert.\n Your task is to inject a root component into an existing App.tsx file with minimal changes.\n </role>\n\n <input_context>\n <current_app_content>\n${appContent}\n </current_app_content>\n <component_to_inject>\n - Component Name: ${componentName}\n - Import Path: ${componentPath}\n </component_to_inject>\n </input_context>\n\n <requirements>\n <req_1>\n **Import Statement**:\n - Add the import statement at the top of the file: \\`import ${componentName} from '${componentPath}';\\`\n - Place it after existing imports, before the component definition.\n - Do NOT remove or modify existing imports.\n </req_1>\n\n <req_2>\n **Component Rendering**:\n - Inside the App component's return statement, replace the existing content with \\`<${componentName} />\\`.\n - If the return contains a wrapper div or other container, keep it and place the component inside.\n - Preserve any existing className, styles, or other attributes on wrapper elements.\n </req_2>\n\n <req_3>\n **Preserve Existing Code**:\n - Keep all existing imports (CSS, Less, etc.)\n - Preserve any hooks, state, or logic inside the App component\n - Maintain the component structure and export statement\n - Do NOT add comments or explanatory text\n </req_3>\n\n <req_4>\n **Minimal Changes**:\n - Only add the necessary import and render the component\n - Do NOT refactor or optimize existing code\n - Do NOT change formatting or styling unless necessary\n - Do NOT add TypeScript types unless they already exist\n </req_4>\n\n <req_5>\n **React Import**:\n${REACT_IMPORT_RULE}\n </req_5>\n </requirements>\n\n <output_format>\n Return ONLY the complete updated App.tsx code without markdown code blocks or explanation.\n The output should be valid TypeScript/React code that can be directly written to the file.\n </output_format>\n</system_instructions>\n`.trim();\n};\n","export const DEFAULT_STYLING = {\n approach: 'Tailwind V4 and Less',\n libraries: [\n {\n name: 'Tailwind V4',\n role: 'utility_first',\n },\n {\n name: 'Less',\n role: 'css_preprocessor',\n },\n ],\n};\n\nexport const DEFAULT_APP_CONTENT = `function App() {\n return (\n <div>\n {/* Component will be injected here */}\n </div>\n );\n}\n\nexport default App;`;\n","import fs from 'node:fs';\nimport { WorkspaceStructure } from '../types/workspace-types';\nimport { logger } from './logger';\n\n/**\n * Code generation cache structure\n * Tracks which components have been generated and whether App.tsx has been injected\n */\nexport interface CodeCache {\n generatedComponents: string[]; // Array of node IDs that have been generated\n appInjected: boolean;\n}\n\n/**\n * Get the path to the cache file\n */\nfunction getCachePath(workspace: WorkspaceStructure): string {\n return workspace.checkpoint;\n}\n\n/**\n * Load code generation cache from file\n * Returns empty cache if file doesn't exist or on error\n */\nexport function loadCodeCache(workspace: WorkspaceStructure): CodeCache {\n const cachePath = getCachePath(workspace);\n\n try {\n if (!fs.existsSync(cachePath)) {\n logger.printInfoLog('No code cache found, starting fresh');\n return createEmptyCache();\n }\n\n const content = fs.readFileSync(cachePath, 'utf-8');\n const cache = JSON.parse(content) as CodeCache;\n\n // Validate cache structure\n if (!Array.isArray(cache.generatedComponents) || typeof cache.appInjected !== 'boolean') {\n logger.printWarnLog('Invalid cache format, starting fresh');\n return createEmptyCache();\n }\n\n logger.printInfoLog(`Loaded code cache: ${cache.generatedComponents.length} components cached`);\n return cache;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.printWarnLog(`Failed to load code cache: ${errorMessage}. Starting fresh.`);\n return createEmptyCache();\n }\n}\n\n/**\n * Save code generation cache to file\n */\nexport function saveCodeCache(workspace: WorkspaceStructure, cache: CodeCache): void {\n const cachePath = getCachePath(workspace);\n\n try {\n // Ensure process directory exists\n if (!fs.existsSync(workspace.process)) {\n fs.mkdirSync(workspace.process, { recursive: true });\n }\n\n const content = JSON.stringify(cache, null, 2);\n fs.writeFileSync(cachePath, content, 'utf-8');\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.printWarnLog(`Failed to save code cache: ${errorMessage}`);\n }\n}\n\n/**\n * Check if a component has already been generated\n * @param cache - The code cache object\n * @param nodeId - The unique node ID to check\n */\nexport function isComponentGenerated(cache: CodeCache, nodeId: string): boolean {\n return cache.generatedComponents.includes(nodeId);\n}\n\n/**\n * Mark a component as generated\n * @param cache - The code cache object\n * @param nodeId - The unique node ID to mark as generated\n */\nexport function markComponentGenerated(cache: CodeCache, nodeId: string): void {\n if (!isComponentGenerated(cache, nodeId)) {\n cache.generatedComponents.push(nodeId);\n }\n}\n\n/**\n * Mark a component as generated and save cache immediately\n * Combines markComponentGenerated and saveCodeCache for convenience\n * @param cache - The code cache object\n * @param nodeId - The unique node ID to mark as generated\n * @param workspace - The workspace structure containing cache file path\n */\nexport function saveComponentGenerated(cache: CodeCache, nodeId: string, workspace: WorkspaceStructure): void {\n markComponentGenerated(cache, nodeId);\n saveCodeCache(workspace, cache);\n}\n\n/**\n * Check if root component has been injected into App.tsx\n */\nexport function isAppInjected(cache: CodeCache): boolean {\n return cache.appInjected;\n}\n\n/**\n * Mark App.tsx as injected\n */\nexport function markAppInjected(cache: CodeCache): void {\n cache.appInjected = true;\n}\n\n/**\n * Mark App.tsx as injected and save cache immediately\n * Combines markAppInjected and saveCodeCache for convenience\n */\nexport function saveAppInjected(cache: CodeCache, workspace: WorkspaceStructure): void {\n markAppInjected(cache);\n saveCodeCache(workspace, cache);\n}\n\n/**\n * Create an empty cache\n */\nfunction createEmptyCache(): CodeCache {\n return {\n generatedComponents: [],\n appInjected: false,\n };\n}\n","import path from 'node:path';\nimport fs from 'node:fs';\nimport { SqliteSaver } from '@langchain/langgraph-checkpoint-sqlite';\nimport { logger } from './logger';\nimport { promptUserChoice } from '../cli/prompts';\n\n/**\n * Check if a checkpoint exists for the given thread_id\n */\nasync function checkpointExists(checkpointer: SqliteSaver, threadId: string): Promise<boolean> {\n try {\n const checkpoints = checkpointer.list({ configurable: { thread_id: threadId } }, { limit: 1 });\n const firstCheckpoint = await checkpoints.next();\n return !firstCheckpoint.done && firstCheckpoint.value !== undefined;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.printTestLog(`Error checking checkpoint: ${errorMessage}`);\n return false;\n }\n}\n\n/**\n * Clear checkpoint for the given thread_id\n */\nasync function clearCheckpoint(checkpointer: SqliteSaver, threadId: string): Promise<void> {\n try {\n // Delete all checkpoints for this thread_id\n await checkpointer.deleteThread(threadId);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.printWarnLog(`Failed to clear checkpoint: ${errorMessage}`);\n }\n}\n\n/**\n * Check and prompt user for checkpoint decision\n * Returns true if user wants to resume, false if start fresh, undefined if no checkpoint exists\n */\nexport async function promptCheckpointChoice(checkpointer: SqliteSaver, threadId: string): Promise<boolean | undefined> {\n const hasCheckpoint = await checkpointExists(checkpointer, threadId);\n\n if (!hasCheckpoint) {\n return undefined;\n }\n\n const choice = await promptUserChoice();\n return choice === 'resume';\n}\n\n/**\n * Clear checkpoint for the given thread_id (exported for external use)\n */\nexport async function clearThreadCheckpoint(checkpointer: SqliteSaver, threadId: string): Promise<void> {\n await clearCheckpoint(checkpointer, threadId);\n}\n\n/**\n * Initialize SqliteSaver with the database path\n */\nexport function initializeSqliteSaver(dbPath: string): SqliteSaver {\n // Ensure the directory exists\n const dbDir = path.dirname(dbPath);\n if (!fs.existsSync(dbDir)) {\n fs.mkdirSync(dbDir, { recursive: true });\n }\n\n // SqliteSaver.fromConnString already sets up the database\n const checkpointer = SqliteSaver.fromConnString(dbPath);\n return checkpointer;\n}\n","import prompts from 'prompts';\nimport { logger } from '../utils/logger';\n\nasync function typedPrompt<U>(config: prompts.PromptObject<string>): Promise<Record<string, U>> {\n return prompts(config, {\n onCancel: () => {\n logger.printWarnLog('Operation cancelled by user.');\n process.exit(0);\n },\n });\n}\n\ntype UserChoice = 'resume' | 'fresh';\n\nexport async function promptUserChoice(): Promise<UserChoice> {\n const response = await typedPrompt<UserChoice>({\n type: 'select',\n name: 'choice',\n message: 'What would you like to do?',\n choices: [\n { title: 'Resume from cache', value: 'resume' },\n { title: 'Start fresh (will clear existing cache)', value: 'fresh' },\n ],\n initial: 0,\n });\n return response.choice || 'resume';\n}\n","import { Command } from 'commander';\nimport { parseFigmaUrl } from '../utils/url-parser';\nimport { workspaceManager } from '../utils/workspace';\nimport { logger } from '../utils/logger';\nimport { executeFigmaAndImagesActions } from '../nodes/process';\n\n// images command: detect images from Figma document and download them\nexport const registerImagesCommand = (program: Command) => {\n program\n .command('get-images')\n .alias('images')\n .description('Detect images from Figma document and download them')\n .option('-s, --source <url>', 'Figma Link')\n .action(async (opts: { source: string }) => {\n try {\n const { source } = opts;\n const urlInfo = parseFigmaUrl(source);\n const workspace = workspaceManager.initWorkspace(urlInfo.name);\n await executeFigmaAndImagesActions(urlInfo, workspace.root, workspace.root);\n\n logger.printSuccessLog('Successfully completed detection of images from Figma document!');\n logger.printInfoLog(`Please check the output in the workspace: ${workspace.process}`);\n } catch (error) {\n logger.printErrorLog(`Error during images execution: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n};\n","import { Command } from 'commander';\nimport { workspaceManager } from '../utils/workspace';\nimport { logger } from '../utils/logger';\nimport { readFile } from 'fs/promises';\nimport { generateCode } from '../nodes/code';\nimport { Protocol } from '../types/protocol-types';\nimport { GraphState } from '../state';\nimport { initialProject } from '../nodes/initial';\n\n// p2c command: Protocol to Code\nexport const registerP2CCommand = (program: Command) => {\n program\n .command('protocol2code')\n .alias('p2c')\n .description('Generate code from protocol')\n .option('-p, --protocol <path>', 'Protocol path')\n .action(async (opts: { protocol: string }) => {\n try {\n const protocolContent = await readFile(opts.protocol, 'utf-8');\n const protocolData = JSON.parse(protocolContent) as Protocol;\n const workspace = workspaceManager.initWorkspace(protocolData.id || '');\n const state: GraphState = {\n protocol: protocolData,\n workspace,\n figmaInfo: { thumbnail: '' },\n urlInfo: {\n fileId: '',\n name: '',\n nodeId: '',\n projectName: '',\n },\n messages: [],\n config: {},\n };\n await initialProject(state);\n await generateCode(state);\n } catch (error) {\n logger.printErrorLog(`Error during p2c execution: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n};\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { Command } from 'commander';\n\nimport type { Protocol } from '../types/protocol-types';\nimport { ValidationConfig, ValidationMode } from '../types/graph-types';\nimport { logger } from '../utils/logger';\nimport { runValidation } from '../nodes/validation';\nimport { workspaceManager } from '../utils/workspace';\nimport { WorkspaceStructure } from '../types';\n\ntype ValCommandOptions = {\n workspace?: string;\n url: string;\n reportonly?: boolean;\n};\n\nfunction readJsonFile<T>(absolutePath: string): T {\n const raw = fs.readFileSync(absolutePath, 'utf-8');\n return JSON.parse(raw) as T;\n}\n\n/**\n * Register the 'validate' CLI command.\n * Validates position alignment using an existing workspace without re-running d2p/d2c.\n *\n * @param program - Commander program instance\n */\nexport function registerValidateCommand(program: Command): void {\n program\n .command('validate')\n .alias('val')\n .description('Validate position misalignment using an existing generated workspace')\n .option(\n '-w, --workspace [path]',\n 'Workspace root path (contains process/ and generated app folder). Defaults to coderio/<current-dir> if not specified'\n )\n .requiredOption('-u, --url <url>', 'Figma thumbnail URL for validation')\n .option('--reportonly', 'Run report-only validation (no code edits)', false)\n .action(async (opts: ValCommandOptions) => {\n try {\n // Determine workspace and project name\n let workspace: WorkspaceStructure;\n let projectName: string;\n\n if (opts.workspace) {\n // Use explicit workspace path\n const workspacePath = path.resolve(opts.workspace);\n const parentPath = path.dirname(path.dirname(workspacePath)); // Go up to parent of 'coderio' folder\n projectName = path.basename(workspacePath);\n workspace = workspaceManager.initWorkspace(projectName, parentPath);\n } else {\n // Default: use current directory name as project name\n projectName = path.basename(process.env.CODERIO_CLI_USER_CWD ?? process.cwd());\n workspace = workspaceManager.initWorkspace(projectName);\n }\n\n const protocolPath = path.join(workspace.process, 'protocol.json');\n\n if (!fs.existsSync(protocolPath)) {\n throw new Error(`Missing protocol at: ${protocolPath}. Run d2p/d2c first to generate process/protocol.json.`);\n }\n\n const protocol = readJsonFile<Protocol>(protocolPath);\n\n // Use the provided URL directly\n const figmaThumbnailUrl = opts.url;\n\n // Build ValidationConfig from CLI options\n const config: ValidationConfig = {\n validationMode: opts.reportonly ? ValidationMode.ReportOnly : ValidationMode.Full,\n };\n\n logger.printInfoLog(`Running validation (${config.validationMode}) using workspace: ${workspace.root}`);\n\n await runValidation({\n urlInfo: { fileId: null, name: projectName, nodeId: null, projectName: null },\n workspace,\n figmaInfo: { thumbnail: figmaThumbnailUrl },\n protocol,\n messages: [],\n config,\n });\n\n // If we reach here, validation passed\n process.exit(0);\n } catch (error) {\n logger.printErrorLog(`Error during val execution: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n}\n"],"mappings":"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","names":["axios","tools","path","fs","fs","path","axios","axios","fs","path","resolve","cssAngle","_init","tools","document","path","processNode","path","extractDataListPrompt","document","fs","path","path","fs","fs","path","fs","path","Agent","Agent","path","Agent","tools","_init","tools","tools","_init","tools","children","Agent","Agent","Agent","Agent","Agent","fs","path","tools","tools","path","styles","require","resolve","fs","path","path","fs","axios","_init","tools","axios","_init","tools","path","tools","spawn","resolve","spawn","_init","tools","handle","result","tools","fetchThumbnailDimensions","_init","tools","createRequire","require","createRequire","require","history","launchResult","path","fs","fs","path","fs","path","fs","path","fs","path","fs","readFile","readFile","fs","path"]}
|