sonance-brand-mcp 1.3.41 → 1.3.43
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.
|
@@ -521,17 +521,32 @@ export async function POST(request: Request) {
|
|
|
521
521
|
|
|
522
522
|
// Identify the recommended file (highest scoring file, prefer filename matches)
|
|
523
523
|
if (searchResults.length > 0) {
|
|
524
|
-
//
|
|
525
|
-
const
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
524
|
+
// Helper to extract filename without extension
|
|
525
|
+
const getFilenameWithoutExt = (filePath: string): string => {
|
|
526
|
+
const filename = filePath.split('/').pop() || '';
|
|
527
|
+
return filename.replace(/\.(tsx?|jsx?)$/, '').toLowerCase();
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
// Find file where FILENAME matches a component name (not just path)
|
|
531
|
+
const filenameMatch = searchResults.find(r => {
|
|
532
|
+
const filename = getFilenameWithoutExt(r.path);
|
|
533
|
+
return analysis.componentNames.some(name => {
|
|
534
|
+
const nameLower = name.toLowerCase();
|
|
535
|
+
// Exact match: ProcessDetailPanel === processdetailpanel
|
|
536
|
+
// Or filename contains the component name
|
|
537
|
+
return filename === nameLower || filename.includes(nameLower);
|
|
538
|
+
});
|
|
539
|
+
});
|
|
530
540
|
|
|
531
541
|
if (filenameMatch) {
|
|
542
|
+
const matchedName = analysis.componentNames.find(name => {
|
|
543
|
+
const filename = getFilenameWithoutExt(filenameMatch.path);
|
|
544
|
+
const nameLower = name.toLowerCase();
|
|
545
|
+
return filename === nameLower || filename.includes(nameLower);
|
|
546
|
+
});
|
|
532
547
|
recommendedFile = {
|
|
533
548
|
path: filenameMatch.path,
|
|
534
|
-
reason: `
|
|
549
|
+
reason: `Filename matches component "${matchedName}" from screenshot`
|
|
535
550
|
};
|
|
536
551
|
} else {
|
|
537
552
|
// Fall back to highest score
|
|
@@ -589,6 +604,27 @@ export async function POST(request: Request) {
|
|
|
589
604
|
});
|
|
590
605
|
}
|
|
591
606
|
|
|
607
|
+
// ========== SMART CONTEXT BUDGETING ==========
|
|
608
|
+
// Total budget: 100k chars (~25k tokens, safe for Claude)
|
|
609
|
+
// Priority: Recommended file (full) > Page file (limited) > Other components (dynamic)
|
|
610
|
+
const TOTAL_CONTEXT_BUDGET = 100000;
|
|
611
|
+
const MAX_RECOMMENDED_FILE = 50000; // 50k chars max for recommended file
|
|
612
|
+
const MAX_PAGE_FILE = 2000; // Page file is just a wrapper
|
|
613
|
+
const MAX_GLOBALS_CSS = 1500;
|
|
614
|
+
const MAX_FILES = 25;
|
|
615
|
+
|
|
616
|
+
let usedContext = 0;
|
|
617
|
+
|
|
618
|
+
// Extract recommended file from component sources (to show first, avoid duplication)
|
|
619
|
+
let recommendedFileContent: { path: string; content: string } | null = null;
|
|
620
|
+
if (recommendedFile) {
|
|
621
|
+
const idx = pageContext.componentSources.findIndex(c => c.path === recommendedFile.path);
|
|
622
|
+
if (idx !== -1) {
|
|
623
|
+
recommendedFileContent = pageContext.componentSources[idx];
|
|
624
|
+
pageContext.componentSources.splice(idx, 1); // Remove to avoid duplication
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
|
|
592
628
|
// Build text content
|
|
593
629
|
let textContent = `VISION MODE EDIT REQUEST
|
|
594
630
|
|
|
@@ -604,41 +640,63 @@ ${focusedElements.map((el) => `- ${el.name} (${el.type}) at (${el.coordinates.x}
|
|
|
604
640
|
`;
|
|
605
641
|
}
|
|
606
642
|
|
|
607
|
-
|
|
643
|
+
// ========== TARGET COMPONENT (RECOMMENDED FILE) - SHOWN FIRST ==========
|
|
644
|
+
if (recommendedFileContent) {
|
|
645
|
+
const content = recommendedFileContent.content.length > MAX_RECOMMENDED_FILE
|
|
646
|
+
? recommendedFileContent.content.substring(0, MAX_RECOMMENDED_FILE) + "\n// ... (file truncated at 50k chars, showing component definition and main logic)"
|
|
647
|
+
: recommendedFileContent.content;
|
|
648
|
+
|
|
649
|
+
textContent += `═══════════════════════════════════════════════════════════════════════════════
|
|
650
|
+
⚡ TARGET COMPONENT - YOU MUST EDIT THIS FILE
|
|
651
|
+
═══════════════════════════════════════════════════════════════════════════════
|
|
652
|
+
|
|
653
|
+
This is the component that renders the UI you see in the screenshot.
|
|
654
|
+
File: ${recommendedFileContent.path}
|
|
655
|
+
|
|
656
|
+
\`\`\`tsx
|
|
657
|
+
${content}
|
|
658
|
+
\`\`\`
|
|
659
|
+
|
|
660
|
+
`;
|
|
661
|
+
usedContext += content.length;
|
|
662
|
+
debugLog("Added TARGET COMPONENT to context", {
|
|
663
|
+
path: recommendedFileContent.path,
|
|
664
|
+
originalSize: recommendedFileContent.content.length,
|
|
665
|
+
includedSize: content.length
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
// ========== PAGE CONTEXT (wrapper - de-emphasized) ==========
|
|
670
|
+
const pageContentTruncated = pageContext.pageContent.substring(0, MAX_PAGE_FILE);
|
|
671
|
+
const pageWasTruncated = pageContext.pageContent.length > MAX_PAGE_FILE;
|
|
672
|
+
|
|
673
|
+
textContent += `PAGE CONTEXT (wrapper only${recommendedFileContent ? " - DO NOT edit this, edit the TARGET COMPONENT above" : ""}):
|
|
608
674
|
|
|
609
675
|
Page File: ${pageContext.pageFile || "Not found"}
|
|
610
|
-
${pageContext.pageContent ? `\`\`\`tsx\n${
|
|
676
|
+
${pageContext.pageContent ? `\`\`\`tsx\n${pageContentTruncated}${pageWasTruncated ? "\n// ... (wrapper truncated)" : ""}\n\`\`\`` : ""}
|
|
611
677
|
|
|
612
678
|
`;
|
|
679
|
+
usedContext += pageContentTruncated.length;
|
|
613
680
|
|
|
681
|
+
// ========== SUPPORTING COMPONENTS (dynamic budget) ==========
|
|
614
682
|
if (pageContext.componentSources.length > 0) {
|
|
615
|
-
|
|
616
|
-
const
|
|
617
|
-
const
|
|
618
|
-
const MAX_PER_FILE_SECONDARY = 1500; // Remaining files get less
|
|
619
|
-
const MAX_FILES = 30; // Limit total number of files
|
|
620
|
-
|
|
621
|
-
let usedContext = pageContext.pageContent.length + pageContext.globalsCSS.length;
|
|
622
|
-
const truncatedComponents = pageContext.componentSources.slice(0, MAX_FILES);
|
|
683
|
+
const remainingBudget = TOTAL_CONTEXT_BUDGET - usedContext - MAX_GLOBALS_CSS - 5000; // Reserve 5k for instructions
|
|
684
|
+
const filesToInclude = pageContext.componentSources.slice(0, MAX_FILES);
|
|
685
|
+
const perFileLimit = Math.max(1000, Math.floor(remainingBudget / Math.max(filesToInclude.length, 1)));
|
|
623
686
|
|
|
624
|
-
textContent += `
|
|
687
|
+
textContent += `SUPPORTING COMPONENTS (${filesToInclude.length} files, ~${Math.round(perFileLimit/1000)}k chars each):\n`;
|
|
625
688
|
|
|
626
|
-
for (
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
const maxSize = isPriority ? MAX_PER_FILE_PRIORITY : MAX_PER_FILE_SECONDARY;
|
|
630
|
-
|
|
631
|
-
// Stop if we've used too much context
|
|
632
|
-
if (usedContext > MAX_TOTAL_CONTEXT) {
|
|
633
|
-
textContent += `\n// ... (${truncatedComponents.length - i} more files omitted to stay within context limits)\n`;
|
|
689
|
+
for (const comp of filesToInclude) {
|
|
690
|
+
if (usedContext > TOTAL_CONTEXT_BUDGET - 10000) {
|
|
691
|
+
textContent += `\n// ... (remaining files omitted to stay within context limits)\n`;
|
|
634
692
|
break;
|
|
635
693
|
}
|
|
636
694
|
|
|
637
|
-
const truncatedContent = comp.content.substring(0,
|
|
638
|
-
const wasTruncated = comp.content.length >
|
|
695
|
+
const truncatedContent = comp.content.substring(0, perFileLimit);
|
|
696
|
+
const wasTruncated = comp.content.length > perFileLimit;
|
|
639
697
|
|
|
640
698
|
textContent += `
|
|
641
|
-
File: ${comp.path}
|
|
699
|
+
File: ${comp.path}
|
|
642
700
|
\`\`\`tsx
|
|
643
701
|
${truncatedContent}${wasTruncated ? "\n// ... (truncated)" : ""}
|
|
644
702
|
\`\`\`
|
|
@@ -647,42 +705,28 @@ ${truncatedContent}${wasTruncated ? "\n// ... (truncated)" : ""}
|
|
|
647
705
|
}
|
|
648
706
|
}
|
|
649
707
|
|
|
708
|
+
// ========== GLOBALS CSS ==========
|
|
709
|
+
const globalsTruncated = pageContext.globalsCSS.substring(0, MAX_GLOBALS_CSS);
|
|
650
710
|
textContent += `
|
|
651
|
-
GLOBALS.CSS (
|
|
711
|
+
GLOBALS.CSS (theme variables):
|
|
652
712
|
\`\`\`css
|
|
653
|
-
${
|
|
713
|
+
${globalsTruncated}${pageContext.globalsCSS.length > MAX_GLOBALS_CSS ? "\n/* ... (truncated) */" : ""}
|
|
654
714
|
\`\`\`
|
|
655
715
|
|
|
656
716
|
`;
|
|
657
717
|
|
|
658
|
-
//
|
|
659
|
-
if (recommendedFile) {
|
|
660
|
-
textContent += `═══════════════════════════════════════════════════════════════════════════════
|
|
661
|
-
⚡ RECOMMENDED FILE TO EDIT
|
|
662
|
-
═══════════════════════════════════════════════════════════════════════════════
|
|
663
|
-
|
|
664
|
-
Based on the screenshot analysis, the component you should edit is:
|
|
665
|
-
**${recommendedFile.path}**
|
|
666
|
-
Reason: ${recommendedFile.reason}
|
|
667
|
-
|
|
668
|
-
The page file (${pageContext.pageFile}) is just a wrapper - the actual UI elements are in the component above.
|
|
669
|
-
YOU MUST edit the recommended file unless you have a specific reason not to.
|
|
670
|
-
|
|
671
|
-
`;
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
// Build VALID FILES list with recommended file first and marked
|
|
718
|
+
// ========== VALID FILES LIST ==========
|
|
675
719
|
const validFilesList: string[] = [];
|
|
676
720
|
const recommendedPath = recommendedFile?.path;
|
|
677
721
|
|
|
678
722
|
// Add recommended file first with marker
|
|
679
723
|
if (recommendedPath) {
|
|
680
|
-
validFilesList.push(`- ${recommendedPath} (***
|
|
724
|
+
validFilesList.push(`- ${recommendedPath} (*** TARGET - EDIT THIS FILE ***)`);
|
|
681
725
|
}
|
|
682
726
|
|
|
683
727
|
// Add page file (if not the recommended file)
|
|
684
728
|
if (pageContext.pageFile && pageContext.pageFile !== recommendedPath) {
|
|
685
|
-
validFilesList.push(`- ${pageContext.pageFile}`);
|
|
729
|
+
validFilesList.push(`- ${pageContext.pageFile} (wrapper only)`);
|
|
686
730
|
}
|
|
687
731
|
|
|
688
732
|
// Add other component sources (excluding recommended file)
|
|
@@ -697,14 +741,14 @@ ${validFilesList.join("\n")}
|
|
|
697
741
|
|
|
698
742
|
INSTRUCTIONS:
|
|
699
743
|
1. Look at the screenshot and identify elements mentioned in the user's request
|
|
700
|
-
2.
|
|
744
|
+
2. The TARGET COMPONENT shown first contains the UI - EDIT THAT FILE
|
|
701
745
|
3. Make SURGICAL EDITS - change only the specific lines needed
|
|
702
746
|
4. PRESERVE all existing logic, hooks, API calls, and error handling
|
|
703
|
-
5. Return the
|
|
747
|
+
5. Return patches in the specified format (search/replace)
|
|
704
748
|
6. Only use file paths from the VALID FILES list above
|
|
705
|
-
7.
|
|
749
|
+
7. DO NOT edit the page wrapper unless the TARGET COMPONENT is unavailable
|
|
706
750
|
|
|
707
|
-
CRITICAL:
|
|
751
|
+
CRITICAL: Edit the TARGET COMPONENT (marked with ***), not the page wrapper.`;
|
|
708
752
|
|
|
709
753
|
messageContent.push({
|
|
710
754
|
type: "text",
|
|
@@ -794,6 +838,11 @@ CRITICAL: Your modified file should have approximately the same number of lines
|
|
|
794
838
|
validFilePaths.add(comp.path);
|
|
795
839
|
}
|
|
796
840
|
|
|
841
|
+
// FIX: Add the recommended file to validFilePaths (it was spliced out for display purposes)
|
|
842
|
+
if (recommendedFileContent) {
|
|
843
|
+
validFilePaths.add(recommendedFileContent.path);
|
|
844
|
+
}
|
|
845
|
+
|
|
797
846
|
debugLog("VALIDATION: Valid file paths from page context", {
|
|
798
847
|
pageFile: pageContext.pageFile,
|
|
799
848
|
validFilePaths: Array.from(validFilePaths),
|
|
@@ -531,17 +531,32 @@ export async function POST(request: Request) {
|
|
|
531
531
|
|
|
532
532
|
// Identify the recommended file (highest scoring file, prefer filename matches)
|
|
533
533
|
if (searchResults.length > 0) {
|
|
534
|
-
//
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
534
|
+
// Helper to extract filename without extension
|
|
535
|
+
const getFilenameWithoutExt = (filePath: string): string => {
|
|
536
|
+
const filename = filePath.split('/').pop() || '';
|
|
537
|
+
return filename.replace(/\.(tsx?|jsx?)$/, '').toLowerCase();
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
// Find file where FILENAME matches a component name (not just path)
|
|
541
|
+
const filenameMatch = searchResults.find(r => {
|
|
542
|
+
const filename = getFilenameWithoutExt(r.path);
|
|
543
|
+
return analysis.componentNames.some(name => {
|
|
544
|
+
const nameLower = name.toLowerCase();
|
|
545
|
+
// Exact match: ProcessDetailPanel === processdetailpanel
|
|
546
|
+
// Or filename contains the component name
|
|
547
|
+
return filename === nameLower || filename.includes(nameLower);
|
|
548
|
+
});
|
|
549
|
+
});
|
|
540
550
|
|
|
541
551
|
if (filenameMatch) {
|
|
552
|
+
const matchedName = analysis.componentNames.find(name => {
|
|
553
|
+
const filename = getFilenameWithoutExt(filenameMatch.path);
|
|
554
|
+
const nameLower = name.toLowerCase();
|
|
555
|
+
return filename === nameLower || filename.includes(nameLower);
|
|
556
|
+
});
|
|
542
557
|
recommendedFile = {
|
|
543
558
|
path: filenameMatch.path,
|
|
544
|
-
reason: `
|
|
559
|
+
reason: `Filename matches component "${matchedName}" from screenshot`
|
|
545
560
|
};
|
|
546
561
|
} else {
|
|
547
562
|
// Fall back to highest score
|
|
@@ -599,6 +614,27 @@ export async function POST(request: Request) {
|
|
|
599
614
|
});
|
|
600
615
|
}
|
|
601
616
|
|
|
617
|
+
// ========== SMART CONTEXT BUDGETING ==========
|
|
618
|
+
// Total budget: 100k chars (~25k tokens, safe for Claude)
|
|
619
|
+
// Priority: Recommended file (full) > Page file (limited) > Other components (dynamic)
|
|
620
|
+
const TOTAL_CONTEXT_BUDGET = 100000;
|
|
621
|
+
const MAX_RECOMMENDED_FILE = 50000; // 50k chars max for recommended file
|
|
622
|
+
const MAX_PAGE_FILE = 2000; // Page file is just a wrapper
|
|
623
|
+
const MAX_GLOBALS_CSS = 1500;
|
|
624
|
+
const MAX_FILES = 25;
|
|
625
|
+
|
|
626
|
+
let usedContext = 0;
|
|
627
|
+
|
|
628
|
+
// Extract recommended file from component sources (to show first, avoid duplication)
|
|
629
|
+
let recommendedFileContent: { path: string; content: string } | null = null;
|
|
630
|
+
if (recommendedFile) {
|
|
631
|
+
const idx = pageContext.componentSources.findIndex(c => c.path === recommendedFile.path);
|
|
632
|
+
if (idx !== -1) {
|
|
633
|
+
recommendedFileContent = pageContext.componentSources[idx];
|
|
634
|
+
pageContext.componentSources.splice(idx, 1); // Remove to avoid duplication
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
|
|
602
638
|
// Build text content
|
|
603
639
|
let textContent = `VISION MODE EDIT REQUEST
|
|
604
640
|
|
|
@@ -614,41 +650,63 @@ ${focusedElements.map((el) => `- ${el.name} (${el.type}) at (${el.coordinates.x}
|
|
|
614
650
|
`;
|
|
615
651
|
}
|
|
616
652
|
|
|
617
|
-
|
|
653
|
+
// ========== TARGET COMPONENT (RECOMMENDED FILE) - SHOWN FIRST ==========
|
|
654
|
+
if (recommendedFileContent) {
|
|
655
|
+
const content = recommendedFileContent.content.length > MAX_RECOMMENDED_FILE
|
|
656
|
+
? recommendedFileContent.content.substring(0, MAX_RECOMMENDED_FILE) + "\n// ... (file truncated at 50k chars, showing component definition and main logic)"
|
|
657
|
+
: recommendedFileContent.content;
|
|
658
|
+
|
|
659
|
+
textContent += `═══════════════════════════════════════════════════════════════════════════════
|
|
660
|
+
⚡ TARGET COMPONENT - YOU MUST EDIT THIS FILE
|
|
661
|
+
═══════════════════════════════════════════════════════════════════════════════
|
|
662
|
+
|
|
663
|
+
This is the component that renders the UI you see in the screenshot.
|
|
664
|
+
File: ${recommendedFileContent.path}
|
|
665
|
+
|
|
666
|
+
\`\`\`tsx
|
|
667
|
+
${content}
|
|
668
|
+
\`\`\`
|
|
669
|
+
|
|
670
|
+
`;
|
|
671
|
+
usedContext += content.length;
|
|
672
|
+
debugLog("Added TARGET COMPONENT to context", {
|
|
673
|
+
path: recommendedFileContent.path,
|
|
674
|
+
originalSize: recommendedFileContent.content.length,
|
|
675
|
+
includedSize: content.length
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// ========== PAGE CONTEXT (wrapper - de-emphasized) ==========
|
|
680
|
+
const pageContentTruncated = pageContext.pageContent.substring(0, MAX_PAGE_FILE);
|
|
681
|
+
const pageWasTruncated = pageContext.pageContent.length > MAX_PAGE_FILE;
|
|
682
|
+
|
|
683
|
+
textContent += `PAGE CONTEXT (wrapper only${recommendedFileContent ? " - DO NOT edit this, edit the TARGET COMPONENT above" : ""}):
|
|
618
684
|
|
|
619
685
|
Page File: ${pageContext.pageFile || "Not found"}
|
|
620
|
-
${pageContext.pageContent ? `\`\`\`tsx\n${
|
|
686
|
+
${pageContext.pageContent ? `\`\`\`tsx\n${pageContentTruncated}${pageWasTruncated ? "\n// ... (wrapper truncated)" : ""}\n\`\`\`` : ""}
|
|
621
687
|
|
|
622
688
|
`;
|
|
689
|
+
usedContext += pageContentTruncated.length;
|
|
623
690
|
|
|
691
|
+
// ========== SUPPORTING COMPONENTS (dynamic budget) ==========
|
|
624
692
|
if (pageContext.componentSources.length > 0) {
|
|
625
|
-
|
|
626
|
-
const
|
|
627
|
-
const
|
|
628
|
-
const MAX_PER_FILE_SECONDARY = 1500; // Remaining files get less
|
|
629
|
-
const MAX_FILES = 30; // Limit total number of files
|
|
693
|
+
const remainingBudget = TOTAL_CONTEXT_BUDGET - usedContext - MAX_GLOBALS_CSS - 5000; // Reserve 5k for instructions
|
|
694
|
+
const filesToInclude = pageContext.componentSources.slice(0, MAX_FILES);
|
|
695
|
+
const perFileLimit = Math.max(1000, Math.floor(remainingBudget / Math.max(filesToInclude.length, 1)));
|
|
630
696
|
|
|
631
|
-
|
|
632
|
-
const truncatedComponents = pageContext.componentSources.slice(0, MAX_FILES);
|
|
697
|
+
textContent += `SUPPORTING COMPONENTS (${filesToInclude.length} files, ~${Math.round(perFileLimit/1000)}k chars each):\n`;
|
|
633
698
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
const comp = truncatedComponents[i];
|
|
638
|
-
const isPriority = i < 10; // First 10 files are priority (direct imports)
|
|
639
|
-
const maxSize = isPriority ? MAX_PER_FILE_PRIORITY : MAX_PER_FILE_SECONDARY;
|
|
640
|
-
|
|
641
|
-
// Stop if we've used too much context
|
|
642
|
-
if (usedContext > MAX_TOTAL_CONTEXT) {
|
|
643
|
-
textContent += `\n// ... (${truncatedComponents.length - i} more files omitted to stay within context limits)\n`;
|
|
699
|
+
for (const comp of filesToInclude) {
|
|
700
|
+
if (usedContext > TOTAL_CONTEXT_BUDGET - 10000) {
|
|
701
|
+
textContent += `\n// ... (remaining files omitted to stay within context limits)\n`;
|
|
644
702
|
break;
|
|
645
703
|
}
|
|
646
704
|
|
|
647
|
-
const truncatedContent = comp.content.substring(0,
|
|
648
|
-
const wasTruncated = comp.content.length >
|
|
705
|
+
const truncatedContent = comp.content.substring(0, perFileLimit);
|
|
706
|
+
const wasTruncated = comp.content.length > perFileLimit;
|
|
649
707
|
|
|
650
708
|
textContent += `
|
|
651
|
-
File: ${comp.path}
|
|
709
|
+
File: ${comp.path}
|
|
652
710
|
\`\`\`tsx
|
|
653
711
|
${truncatedContent}${wasTruncated ? "\n// ... (truncated)" : ""}
|
|
654
712
|
\`\`\`
|
|
@@ -657,42 +715,28 @@ ${truncatedContent}${wasTruncated ? "\n// ... (truncated)" : ""}
|
|
|
657
715
|
}
|
|
658
716
|
}
|
|
659
717
|
|
|
718
|
+
// ========== GLOBALS CSS ==========
|
|
719
|
+
const globalsTruncated = pageContext.globalsCSS.substring(0, MAX_GLOBALS_CSS);
|
|
660
720
|
textContent += `
|
|
661
|
-
GLOBALS.CSS (
|
|
721
|
+
GLOBALS.CSS (theme variables):
|
|
662
722
|
\`\`\`css
|
|
663
|
-
${
|
|
723
|
+
${globalsTruncated}${pageContext.globalsCSS.length > MAX_GLOBALS_CSS ? "\n/* ... (truncated) */" : ""}
|
|
664
724
|
\`\`\`
|
|
665
725
|
|
|
666
726
|
`;
|
|
667
727
|
|
|
668
|
-
//
|
|
669
|
-
if (recommendedFile) {
|
|
670
|
-
textContent += `═══════════════════════════════════════════════════════════════════════════════
|
|
671
|
-
⚡ RECOMMENDED FILE TO EDIT
|
|
672
|
-
═══════════════════════════════════════════════════════════════════════════════
|
|
673
|
-
|
|
674
|
-
Based on the screenshot analysis, the component you should edit is:
|
|
675
|
-
**${recommendedFile.path}**
|
|
676
|
-
Reason: ${recommendedFile.reason}
|
|
677
|
-
|
|
678
|
-
The page file (${pageContext.pageFile}) is just a wrapper - the actual UI elements are in the component above.
|
|
679
|
-
YOU MUST edit the recommended file unless you have a specific reason not to.
|
|
680
|
-
|
|
681
|
-
`;
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
// Build VALID FILES list with recommended file first and marked
|
|
728
|
+
// ========== VALID FILES LIST ==========
|
|
685
729
|
const validFilesList: string[] = [];
|
|
686
730
|
const recommendedPath = recommendedFile?.path;
|
|
687
731
|
|
|
688
732
|
// Add recommended file first with marker
|
|
689
733
|
if (recommendedPath) {
|
|
690
|
-
validFilesList.push(`- ${recommendedPath} (***
|
|
734
|
+
validFilesList.push(`- ${recommendedPath} (*** TARGET - EDIT THIS FILE ***)`);
|
|
691
735
|
}
|
|
692
736
|
|
|
693
737
|
// Add page file (if not the recommended file)
|
|
694
738
|
if (pageContext.pageFile && pageContext.pageFile !== recommendedPath) {
|
|
695
|
-
validFilesList.push(`- ${pageContext.pageFile}`);
|
|
739
|
+
validFilesList.push(`- ${pageContext.pageFile} (wrapper only)`);
|
|
696
740
|
}
|
|
697
741
|
|
|
698
742
|
// Add other component sources (excluding recommended file)
|
|
@@ -707,14 +751,14 @@ ${validFilesList.join("\n")}
|
|
|
707
751
|
|
|
708
752
|
INSTRUCTIONS:
|
|
709
753
|
1. Look at the screenshot and identify elements mentioned in the user's request
|
|
710
|
-
2.
|
|
754
|
+
2. The TARGET COMPONENT shown first contains the UI - EDIT THAT FILE
|
|
711
755
|
3. Choose which of the VALID FILES above need modifications
|
|
712
756
|
4. Generate complete modified code for each file
|
|
713
757
|
5. Provide previewCSS for immediate visual feedback
|
|
714
758
|
6. Return as JSON in the specified format
|
|
715
|
-
7.
|
|
759
|
+
7. DO NOT edit the page wrapper unless the TARGET COMPONENT is unavailable
|
|
716
760
|
|
|
717
|
-
CRITICAL:
|
|
761
|
+
CRITICAL: Edit the TARGET COMPONENT (marked with ***), not the page wrapper.`;
|
|
718
762
|
|
|
719
763
|
messageContent.push({
|
|
720
764
|
type: "text",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sonance-brand-mcp",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.43",
|
|
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",
|