sonance-brand-mcp 1.3.22 → 1.3.24

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.
@@ -60,27 +60,39 @@ const VISION_SYSTEM_PROMPT = `You are a React/Tailwind CSS expert with vision ca
60
60
  You can see screenshots of web pages and understand their visual layout, then modify code to implement requested changes.
61
61
 
62
62
  ═══════════════════════════════════════════════════════════════════════════════
63
- CRITICAL RULES
63
+ ABSOLUTE RULES - VIOLATION WILL BREAK THE APPLICATION
64
64
  ═══════════════════════════════════════════════════════════════════════════════
65
65
 
66
- **ANALYSIS:**
67
- 1. CAREFULLY analyze the screenshot to understand the current visual state
68
- 2. Identify elements mentioned in the user's request
69
- 3. Understand the current styling and layout
70
- 4. Consider how changes will affect the overall design
71
-
72
- **PRESERVATION RULES:**
73
- 5. NEVER delete or remove existing content, children, or JSX elements
74
- 6. NEVER change component structure unless specifically requested
75
- 7. NEVER modify TypeScript types, imports, or exports unless necessary
76
- 8. NEVER remove data-sonance-* attributes
66
+ **SURGICAL EDITING (MOST CRITICAL):**
67
+ 1. You are making SURGICAL EDITS, not rewriting files
68
+ 2. Change ONLY the specific lines that need modification
69
+ 3. The modified file MUST have approximately the same line count as the original
70
+ 4. If original file has 200 lines, modified file should have ~195-210 lines
71
+ 5. NEVER rewrite a file from scratch - this destroys the application
72
+
73
+ **FILE RULES:**
74
+ 6. You may ONLY edit files that are provided in the PAGE CONTEXT section
75
+ 7. NEVER create new files - only modify existing ones shown to you
76
+ 8. The filePath in your response MUST exactly match one of the provided file paths
77
+
78
+ **PRESERVATION RULES (ZERO TOLERANCE):**
79
+ 9. NEVER delete or remove existing functions, hooks, state, or logic
80
+ 10. NEVER remove imports - you may only ADD imports if needed
81
+ 11. NEVER remove useEffect, useState, useCallback, or other React hooks
82
+ 12. NEVER remove API calls, fetch requests, or data loading logic
83
+ 13. NEVER remove error handling, loading states, or conditional rendering
84
+ 14. NEVER remove data-sonance-* attributes
85
+ 15. NEVER change component structure unless specifically requested
86
+ 16. NEVER modify TypeScript types or interfaces unless specifically requested
77
87
 
78
88
  **CHANGE RULES:**
79
- 9. Make ONLY the changes requested by the user
80
- 10. Modify the minimum amount of code necessary
81
- 11. Use semantic Tailwind classes (bg-primary, text-foreground, etc.)
82
- 12. Maintain dark mode compatibility with CSS variables
83
- 13. Keep the cn() utility for className merging
89
+ 17. Make ONLY the changes requested by the user
90
+ 18. Modify the MINIMUM amount of code necessary
91
+ 19. Keep all existing className values and ADD to them if needed
92
+ 20. Use semantic Tailwind classes (bg-primary, text-foreground, etc.)
93
+ 21. Maintain dark mode compatibility with CSS variables
94
+ 22. Keep the cn() utility for className merging
95
+ 23. CRITICAL: You MUST return the FULL file content in "modifiedContent". Do NOT use comments like "// ... existing code ..." or "// ... rest of file ...". Return every single line of code, even if unchanged.
84
96
 
85
97
  **SONANCE BRAND COLORS:**
86
98
  - Charcoal: #333F48, #343D46 (primary)
@@ -96,9 +108,16 @@ The JSON must include:
96
108
  - "reasoning": Brief explanation of what you see in the screenshot and your plan
97
109
  - "modifications": Array of file modifications, each with:
98
110
  - "filePath": Path to the file
99
- - "modifiedContent": Complete updated file content
111
+ - "modifiedContent": Complete updated file content (MUST BE FULL CONTENT, NO TRUNCATION)
100
112
  - "explanation": What changed in this file
101
- - "explanation": Overall summary of changes`;
113
+ - "explanation": Overall summary of changes
114
+
115
+ **EXAMPLE OF CORRECT EDIT:**
116
+ If user asks to "make buttons smaller", you should:
117
+ - Find the button elements in the code
118
+ - Change ONLY the size-related classes (e.g., h-10 -> h-8, px-4 -> px-3)
119
+ - Keep ALL other code exactly the same
120
+ - Return the FULL file with this tiny change`;
102
121
 
103
122
  export async function POST(request: Request) {
104
123
  // Only allow in development
@@ -234,12 +253,19 @@ GLOBALS.CSS (relevant theme variables):
234
253
  ${pageContext.globalsCSS.substring(0, 2000)}${pageContext.globalsCSS.length > 2000 ? "\n/* ... (truncated) */" : ""}
235
254
  \`\`\`
236
255
 
256
+ VALID FILES YOU MAY EDIT:
257
+ ${pageContext.pageFile ? `- ${pageContext.pageFile}` : ""}
258
+ ${pageContext.componentSources.map((c) => `- ${c.path}`).join("\n")}
259
+
237
260
  INSTRUCTIONS:
238
261
  1. Look at the screenshot and identify elements mentioned in the user's request
239
262
  2. Review the code to understand current implementation
240
- 3. Determine which files need modifications
241
- 4. Generate complete modified code for each file
242
- 5. Return as JSON in the specified format`;
263
+ 3. Make SURGICAL EDITS - change only the specific lines needed
264
+ 4. PRESERVE all existing logic, hooks, API calls, and error handling
265
+ 5. Return the FULL file content (no truncation, no "// ... existing ..." comments)
266
+ 6. Only use file paths from the VALID FILES list above
267
+
268
+ CRITICAL: Your modified file should have approximately the same number of lines as the original. If the original has 200 lines and your output has 50 lines, you have made a mistake.`;
243
269
 
244
270
  messageContent.push({
245
271
  type: "text",
@@ -320,6 +346,9 @@ INSTRUCTIONS:
320
346
 
321
347
  // Read original content and prepare modifications
322
348
  const modifications: VisionFileModification[] = [];
349
+ const validationErrors: string[] = [];
350
+ const validationWarnings: string[] = [];
351
+
323
352
  for (const mod of aiResponse.modifications) {
324
353
  const fullPath = path.join(projectRoot, mod.filePath);
325
354
  let originalContent = "";
@@ -327,6 +356,18 @@ INSTRUCTIONS:
327
356
  originalContent = fs.readFileSync(fullPath, "utf-8");
328
357
  }
329
358
 
359
+ // Validate the modification
360
+ const validation = validateModification(originalContent, mod.modifiedContent, mod.filePath);
361
+
362
+ if (!validation.valid) {
363
+ validationErrors.push(validation.error || "Unknown validation error");
364
+ continue; // Skip this modification
365
+ }
366
+
367
+ if (validation.warnings.length > 0) {
368
+ validationWarnings.push(...validation.warnings.map(w => `${mod.filePath}: ${w}`));
369
+ }
370
+
330
371
  modifications.push({
331
372
  filePath: mod.filePath,
332
373
  originalContent,
@@ -336,6 +377,23 @@ INSTRUCTIONS:
336
377
  });
337
378
  }
338
379
 
380
+ // If all modifications failed validation, return error
381
+ if (validationErrors.length > 0 && modifications.length === 0) {
382
+ console.error("All AI modifications failed validation:", validationErrors);
383
+ return NextResponse.json(
384
+ {
385
+ success: false,
386
+ error: validationErrors.join("\n\n"),
387
+ },
388
+ { status: 400 }
389
+ );
390
+ }
391
+
392
+ // Log warnings for review
393
+ if (validationWarnings.length > 0) {
394
+ console.warn("Vision apply validation warnings:", validationWarnings);
395
+ }
396
+
339
397
  // Create backups and apply changes atomically
340
398
  const applyResult = await applyChangesWithBackup(
341
399
  modifications,
@@ -650,3 +708,105 @@ function generateSimpleDiff(original: string, modified: string): string {
650
708
 
651
709
  return diff.join("\n");
652
710
  }
711
+
712
+ /**
713
+ * Validate that AI modifications are surgical edits, not complete rewrites
714
+ */
715
+ interface ValidationResult {
716
+ valid: boolean;
717
+ error?: string;
718
+ warnings: string[];
719
+ }
720
+
721
+ function validateModification(
722
+ originalContent: string,
723
+ modifiedContent: string,
724
+ filePath: string
725
+ ): ValidationResult {
726
+ const warnings: string[] = [];
727
+
728
+ // Skip validation for new files (no original content)
729
+ if (!originalContent || originalContent.trim() === "") {
730
+ return { valid: true, warnings: ["New file - no original to compare"] };
731
+ }
732
+
733
+ const originalLines = originalContent.split("\n");
734
+ const modifiedLines = modifiedContent.split("\n");
735
+
736
+ // Check 1: Truncation detection - look for placeholder comments
737
+ const truncationPatterns = [
738
+ /\/\/\s*\.\.\.\s*existing/i,
739
+ /\/\/\s*\.\.\.\s*rest\s*of/i,
740
+ /\/\/\s*\.\.\.\s*more\s*code/i,
741
+ /\/\*\s*\.\.\.\s*\*\//,
742
+ /\/\/\s*\.\.\./,
743
+ ];
744
+
745
+ for (const pattern of truncationPatterns) {
746
+ if (pattern.test(modifiedContent)) {
747
+ return {
748
+ valid: false,
749
+ error: `File ${filePath} contains truncation placeholder (e.g., "// ... existing code"). The AI must return the complete file content. Please try again.`,
750
+ warnings,
751
+ };
752
+ }
753
+ }
754
+
755
+ // Check 2: Line count shrinkage - reject if file shrinks by more than 30%
756
+ const lineDelta = modifiedLines.length - originalLines.length;
757
+ const shrinkagePercent = (lineDelta / originalLines.length) * 100;
758
+
759
+ if (shrinkagePercent < -30) {
760
+ return {
761
+ valid: false,
762
+ error: `File ${filePath} shrank from ${originalLines.length} to ${modifiedLines.length} lines (${Math.abs(shrinkagePercent).toFixed(0)}% reduction). This suggests the AI rewrote the file instead of making surgical edits. Please try a more specific request.`,
763
+ warnings,
764
+ };
765
+ }
766
+
767
+ if (shrinkagePercent < -15) {
768
+ warnings.push(`File shrank by ${Math.abs(shrinkagePercent).toFixed(0)}% - review carefully`);
769
+ }
770
+
771
+ // Check 3: Change percentage - warn if too many lines are different
772
+ let changedLines = 0;
773
+ const minLines = Math.min(originalLines.length, modifiedLines.length);
774
+
775
+ for (let i = 0; i < minLines; i++) {
776
+ if (originalLines[i] !== modifiedLines[i]) {
777
+ changedLines++;
778
+ }
779
+ }
780
+
781
+ // Add lines that were added or removed
782
+ changedLines += Math.abs(originalLines.length - modifiedLines.length);
783
+
784
+ const changePercent = (changedLines / originalLines.length) * 100;
785
+
786
+ if (changePercent > 50) {
787
+ return {
788
+ valid: false,
789
+ error: `File ${filePath} has ${changePercent.toFixed(0)}% of lines changed. This suggests the AI rewrote the file instead of making surgical edits. For safety, this change has been rejected. Please try a more specific request.`,
790
+ warnings,
791
+ };
792
+ }
793
+
794
+ if (changePercent > 30) {
795
+ warnings.push(`${changePercent.toFixed(0)}% of lines changed - larger than expected for a surgical edit`);
796
+ }
797
+
798
+ // Check 4: Import preservation - ensure imports aren't removed
799
+ const importRegex = /^import\s+/gm;
800
+ const originalImports = (originalContent.match(importRegex) || []).length;
801
+ const modifiedImports = (modifiedContent.match(importRegex) || []).length;
802
+
803
+ if (modifiedImports < originalImports * 0.5 && originalImports > 2) {
804
+ return {
805
+ valid: false,
806
+ error: `File ${filePath} went from ${originalImports} imports to ${modifiedImports}. Imports should not be removed. Please try again.`,
807
+ warnings,
808
+ };
809
+ }
810
+
811
+ return { valid: true, warnings };
812
+ }
@@ -61,36 +61,42 @@ const VISION_SYSTEM_PROMPT = `You are a React/Tailwind CSS expert with vision ca
61
61
  You can see screenshots of web pages and understand their visual layout, then modify code to implement requested changes.
62
62
 
63
63
  ═══════════════════════════════════════════════════════════════════════════════
64
- CRITICAL RULES
64
+ ABSOLUTE RULES - VIOLATION WILL BREAK THE APPLICATION
65
65
  ═══════════════════════════════════════════════════════════════════════════════
66
66
 
67
- **FILE RULES (MOST IMPORTANT):**
68
- 1. You may ONLY edit files that are provided in the PAGE CONTEXT section
69
- 2. NEVER create new files - only modify existing ones shown to you
70
- 3. The filePath in your response MUST exactly match one of the provided file paths
71
- 4. If you cannot find the right file to edit, explain this in your response instead of creating a new file
72
-
73
- **ANALYSIS:**
74
- 5. CAREFULLY analyze the screenshot to understand the current visual state
75
- 6. Identify elements mentioned in the user's request
76
- 7. Understand the current styling and layout
77
- 8. Consider how changes will affect the overall design
78
-
79
- **PRESERVATION RULES:**
80
- 9. NEVER delete or remove existing content, children, or JSX elements
81
- 10. NEVER change component structure unless specifically requested
82
- 11. NEVER modify TypeScript types, imports, or exports unless necessary
83
- 12. NEVER remove data-sonance-* attributes
67
+ **SURGICAL EDITING (MOST CRITICAL):**
68
+ 1. You are making SURGICAL EDITS, not rewriting files
69
+ 2. Change ONLY the specific lines that need modification
70
+ 3. The modified file MUST have approximately the same line count as the original
71
+ 4. If original file has 200 lines, modified file should have ~195-210 lines
72
+ 5. NEVER rewrite a file from scratch - this destroys the application
73
+
74
+ **FILE RULES:**
75
+ 6. You may ONLY edit files that are provided in the PAGE CONTEXT section
76
+ 7. NEVER create new files - only modify existing ones shown to you
77
+ 8. The filePath in your response MUST exactly match one of the provided file paths
78
+ 9. If you cannot find the right file to edit, explain this in your response instead of creating a new file
79
+
80
+ **PRESERVATION RULES (ZERO TOLERANCE):**
81
+ 10. NEVER delete or remove existing functions, hooks, state, or logic
82
+ 11. NEVER remove imports - you may only ADD imports if needed
83
+ 12. NEVER remove useEffect, useState, useCallback, or other React hooks
84
+ 13. NEVER remove API calls, fetch requests, or data loading logic
85
+ 14. NEVER remove error handling, loading states, or conditional rendering
86
+ 15. NEVER remove data-sonance-* attributes
87
+ 16. NEVER change component structure unless specifically requested
88
+ 17. NEVER modify TypeScript types or interfaces unless specifically requested
84
89
 
85
90
  **CHANGE RULES:**
86
- 13. Make ONLY the changes requested by the user
87
- 14. Modify the minimum amount of code necessary
88
- 15. Use semantic Tailwind classes (bg-primary, text-foreground, etc.)
89
- 16. Maintain dark mode compatibility with CSS variables
90
- 17. Keep the cn() utility for className merging
91
- 18. CRITICAL: You MUST return the FULL file content in "modifiedContent". Do NOT use comments like "// ... existing code ..." or "// ... rest of file ...". Return every single line of code, even if unchanged.
92
-
93
- **SONANCE BRAND COLORS:**
91
+ 18. Make ONLY the changes requested by the user
92
+ 19. Modify the MINIMUM amount of code necessary
93
+ 20. Keep all existing className values and ADD to them if needed
94
+ 21. Use semantic Tailwind classes (bg-primary, text-foreground, etc.)
95
+ 22. Maintain dark mode compatibility with CSS variables
96
+ 23. Keep the cn() utility for className merging
97
+ 24. CRITICAL: You MUST return the FULL file content in "modifiedContent". Do NOT use comments like "// ... existing code ..." or "// ... rest of file ...". Return every single line of code, even if unchanged.
98
+
99
+ **SONANCE BRAND COLORS:**
94
100
  - Charcoal: #333F48, #343D46 (primary)
95
101
  - Silver: #E2E2E2, #D1D1D6 (secondary)
96
102
  - IPORT Orange: #FC4C02
@@ -102,13 +108,20 @@ CRITICAL RULES
102
108
  Return ONLY a valid JSON object. Do not include any conversational text before or after the JSON.
103
109
  The JSON must include:
104
110
  - "reasoning": Brief explanation of what you see in the screenshot and your plan
105
- - "modifications": Array of file modifications, each with:
106
- - "filePath": Path to the file
107
- - "modifiedContent": Complete updated file content (MUST BE FULL CONTENT, NO TRUNCATION)
108
- - "explanation": What changed in this file
109
- - "previewCSS": CSS for live preview (use [data-sonance-name="ComponentName"] selectors)
111
+ - "modifications": Array of file modifications, each with:
112
+ - "filePath": Path to the file
113
+ - "modifiedContent": Complete updated file content (MUST BE FULL CONTENT, NO TRUNCATION)
114
+ - "explanation": What changed in this file
115
+ - "previewCSS": CSS for live preview (use [data-sonance-name="ComponentName"] selectors)
110
116
  - "aggregatedPreviewCSS": Combined CSS for all changes
111
- - "explanation": Overall summary of changes`;
117
+ - "explanation": Overall summary of changes
118
+
119
+ **EXAMPLE OF CORRECT EDIT:**
120
+ If user asks to "make buttons smaller", you should:
121
+ - Find the button elements in the code
122
+ - Change ONLY the size-related classes (e.g., h-10 -> h-8, px-4 -> px-3)
123
+ - Keep ALL other code exactly the same
124
+ - Return the FULL file with this tiny change`;
112
125
 
113
126
  export async function POST(request: Request) {
114
127
  // Only allow in development
@@ -370,6 +383,9 @@ CRITICAL: Only use file paths from the VALID FILES list above. Do NOT create new
370
383
 
371
384
  // Read original content and generate diffs for each modification
372
385
  const modificationsWithOriginals: VisionFileModification[] = [];
386
+ const validationErrors: string[] = [];
387
+ const validationWarnings: string[] = [];
388
+
373
389
  for (const mod of aiResponse.modifications || []) {
374
390
  const fullPath = path.join(projectRoot, mod.filePath);
375
391
  let originalContent = "";
@@ -377,6 +393,18 @@ CRITICAL: Only use file paths from the VALID FILES list above. Do NOT create new
377
393
  originalContent = fs.readFileSync(fullPath, "utf-8");
378
394
  }
379
395
 
396
+ // Validate the modification
397
+ const validation = validateModification(originalContent, mod.modifiedContent, mod.filePath);
398
+
399
+ if (!validation.valid) {
400
+ validationErrors.push(validation.error || "Unknown validation error");
401
+ continue; // Skip this modification
402
+ }
403
+
404
+ if (validation.warnings.length > 0) {
405
+ validationWarnings.push(...validation.warnings.map(w => `${mod.filePath}: ${w}`));
406
+ }
407
+
380
408
  modificationsWithOriginals.push({
381
409
  filePath: mod.filePath,
382
410
  originalContent,
@@ -387,6 +415,23 @@ CRITICAL: Only use file paths from the VALID FILES list above. Do NOT create new
387
415
  });
388
416
  }
389
417
 
418
+ // If all modifications failed validation, return error
419
+ if (validationErrors.length > 0 && modificationsWithOriginals.length === 0) {
420
+ console.error("All AI modifications failed validation:", validationErrors);
421
+ return NextResponse.json(
422
+ {
423
+ success: false,
424
+ error: validationErrors.join("\n\n"),
425
+ } as VisionEditResponse,
426
+ { status: 400 }
427
+ );
428
+ }
429
+
430
+ // Log warnings for review
431
+ if (validationWarnings.length > 0) {
432
+ console.warn("Vision edit validation warnings:", validationWarnings);
433
+ }
434
+
390
435
  // Aggregate preview CSS
391
436
  const aggregatedCSS = modificationsWithOriginals
392
437
  .filter((m) => m.previewCSS)
@@ -655,3 +700,105 @@ function generateSimpleDiff(original: string, modified: string): string {
655
700
 
656
701
  return diff.join("\n");
657
702
  }
703
+
704
+ /**
705
+ * Validate that AI modifications are surgical edits, not complete rewrites
706
+ */
707
+ interface ValidationResult {
708
+ valid: boolean;
709
+ error?: string;
710
+ warnings: string[];
711
+ }
712
+
713
+ function validateModification(
714
+ originalContent: string,
715
+ modifiedContent: string,
716
+ filePath: string
717
+ ): ValidationResult {
718
+ const warnings: string[] = [];
719
+
720
+ // Skip validation for new files (no original content)
721
+ if (!originalContent || originalContent.trim() === "") {
722
+ return { valid: true, warnings: ["New file - no original to compare"] };
723
+ }
724
+
725
+ const originalLines = originalContent.split("\n");
726
+ const modifiedLines = modifiedContent.split("\n");
727
+
728
+ // Check 1: Truncation detection - look for placeholder comments
729
+ const truncationPatterns = [
730
+ /\/\/\s*\.\.\.\s*existing/i,
731
+ /\/\/\s*\.\.\.\s*rest\s*of/i,
732
+ /\/\/\s*\.\.\.\s*more\s*code/i,
733
+ /\/\*\s*\.\.\.\s*\*\//,
734
+ /\/\/\s*\.\.\./,
735
+ ];
736
+
737
+ for (const pattern of truncationPatterns) {
738
+ if (pattern.test(modifiedContent)) {
739
+ return {
740
+ valid: false,
741
+ error: `File ${filePath} contains truncation placeholder (e.g., "// ... existing code"). The AI must return the complete file content. Please try again.`,
742
+ warnings,
743
+ };
744
+ }
745
+ }
746
+
747
+ // Check 2: Line count shrinkage - reject if file shrinks by more than 30%
748
+ const lineDelta = modifiedLines.length - originalLines.length;
749
+ const shrinkagePercent = (lineDelta / originalLines.length) * 100;
750
+
751
+ if (shrinkagePercent < -30) {
752
+ return {
753
+ valid: false,
754
+ error: `File ${filePath} shrank from ${originalLines.length} to ${modifiedLines.length} lines (${Math.abs(shrinkagePercent).toFixed(0)}% reduction). This suggests the AI rewrote the file instead of making surgical edits. Please try a more specific request.`,
755
+ warnings,
756
+ };
757
+ }
758
+
759
+ if (shrinkagePercent < -15) {
760
+ warnings.push(`File shrank by ${Math.abs(shrinkagePercent).toFixed(0)}% - review carefully`);
761
+ }
762
+
763
+ // Check 3: Change percentage - warn if too many lines are different
764
+ let changedLines = 0;
765
+ const minLines = Math.min(originalLines.length, modifiedLines.length);
766
+
767
+ for (let i = 0; i < minLines; i++) {
768
+ if (originalLines[i] !== modifiedLines[i]) {
769
+ changedLines++;
770
+ }
771
+ }
772
+
773
+ // Add lines that were added or removed
774
+ changedLines += Math.abs(originalLines.length - modifiedLines.length);
775
+
776
+ const changePercent = (changedLines / originalLines.length) * 100;
777
+
778
+ if (changePercent > 50) {
779
+ return {
780
+ valid: false,
781
+ error: `File ${filePath} has ${changePercent.toFixed(0)}% of lines changed. This suggests the AI rewrote the file instead of making surgical edits. For safety, this change has been rejected. Please try a more specific request.`,
782
+ warnings,
783
+ };
784
+ }
785
+
786
+ if (changePercent > 30) {
787
+ warnings.push(`${changePercent.toFixed(0)}% of lines changed - larger than expected for a surgical edit`);
788
+ }
789
+
790
+ // Check 4: Import preservation - ensure imports aren't removed
791
+ const importRegex = /^import\s+/gm;
792
+ const originalImports = (originalContent.match(importRegex) || []).length;
793
+ const modifiedImports = (modifiedContent.match(importRegex) || []).length;
794
+
795
+ if (modifiedImports < originalImports * 0.5 && originalImports > 2) {
796
+ return {
797
+ valid: false,
798
+ error: `File ${filePath} went from ${originalImports} imports to ${modifiedImports}. Imports should not be removed. Please try again.`,
799
+ warnings,
800
+ };
801
+ }
802
+
803
+ return { valid: true, warnings };
804
+ }
@@ -582,6 +582,9 @@ export function ComponentsPanel({
582
582
  )}
583
583
 
584
584
  {/* AI Chat Interface - hide when any pending edit is present */}
585
+ {/* Apply-First mode: Files written immediately with backups for instant HMR preview
586
+ User sees structural + CSS changes live, then clicks Accept or Revert
587
+ Original files are always backed up and can be restored */}
585
588
  {!pendingEdit && !visionPendingEdit && !applyFirstSession && (
586
589
  <ChatInterface
587
590
  componentType={selectedComponentType}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sonance-brand-mcp",
3
- "version": "1.3.22",
3
+ "version": "1.3.24",
4
4
  "description": "MCP Server for Sonance Brand Guidelines and Component Library - gives Claude instant access to brand colors, typography, and UI components.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",