sonance-brand-mcp 1.3.39 → 1.3.41
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.
|
@@ -504,6 +504,8 @@ export async function POST(request: Request) {
|
|
|
504
504
|
// PHASE 1+2: LLM-driven smart file discovery
|
|
505
505
|
// The LLM analyzes the screenshot and deduces component names, code patterns, and visible text
|
|
506
506
|
let smartSearchFiles: { path: string; content: string }[] = [];
|
|
507
|
+
let recommendedFile: { path: string; reason: string } | null = null;
|
|
508
|
+
|
|
507
509
|
if (screenshot) {
|
|
508
510
|
debugLog("Starting Phase 1: LLM screenshot analysis");
|
|
509
511
|
const analysis = await analyzeScreenshotForSearch(screenshot, userPrompt, apiKey);
|
|
@@ -516,13 +518,39 @@ export async function POST(request: Request) {
|
|
|
516
518
|
// PHASE 2: Smart search using component names, text, and code patterns
|
|
517
519
|
const searchResults = searchFilesSmart(analysis, projectRoot, 10);
|
|
518
520
|
smartSearchFiles = searchResults.map(r => ({ path: r.path, content: r.content }));
|
|
521
|
+
|
|
522
|
+
// Identify the recommended file (highest scoring file, prefer filename matches)
|
|
523
|
+
if (searchResults.length > 0) {
|
|
524
|
+
// Find the best filename match first
|
|
525
|
+
const filenameMatch = searchResults.find(r =>
|
|
526
|
+
analysis.componentNames.some(name =>
|
|
527
|
+
r.path.toLowerCase().includes(name.toLowerCase())
|
|
528
|
+
)
|
|
529
|
+
);
|
|
530
|
+
|
|
531
|
+
if (filenameMatch) {
|
|
532
|
+
recommendedFile = {
|
|
533
|
+
path: filenameMatch.path,
|
|
534
|
+
reason: `Component name match from screenshot analysis`
|
|
535
|
+
};
|
|
536
|
+
} else {
|
|
537
|
+
// Fall back to highest score
|
|
538
|
+
recommendedFile = {
|
|
539
|
+
path: searchResults[0].path,
|
|
540
|
+
reason: `Highest content match score (${searchResults[0].score} points)`
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
debugLog("Recommended file for editing", recommendedFile);
|
|
544
|
+
}
|
|
545
|
+
|
|
519
546
|
debugLog("Phase 1+2 complete", {
|
|
520
547
|
analysis: {
|
|
521
548
|
visibleText: analysis.visibleText.slice(0, 5),
|
|
522
549
|
componentNames: analysis.componentNames,
|
|
523
550
|
codePatterns: analysis.codePatterns.slice(0, 5)
|
|
524
551
|
},
|
|
525
|
-
filesFound: smartSearchFiles.map(f => f.path)
|
|
552
|
+
filesFound: smartSearchFiles.map(f => f.path),
|
|
553
|
+
recommendedFile
|
|
526
554
|
});
|
|
527
555
|
}
|
|
528
556
|
}
|
|
@@ -625,9 +653,47 @@ GLOBALS.CSS (relevant theme variables):
|
|
|
625
653
|
${pageContext.globalsCSS.substring(0, 2000)}${pageContext.globalsCSS.length > 2000 ? "\n/* ... (truncated) */" : ""}
|
|
626
654
|
\`\`\`
|
|
627
655
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
656
|
+
`;
|
|
657
|
+
|
|
658
|
+
// Add recommendation block just before VALID FILES if we have one
|
|
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
|
|
675
|
+
const validFilesList: string[] = [];
|
|
676
|
+
const recommendedPath = recommendedFile?.path;
|
|
677
|
+
|
|
678
|
+
// Add recommended file first with marker
|
|
679
|
+
if (recommendedPath) {
|
|
680
|
+
validFilesList.push(`- ${recommendedPath} (*** RECOMMENDED - EDIT THIS FILE ***)`);
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
// Add page file (if not the recommended file)
|
|
684
|
+
if (pageContext.pageFile && pageContext.pageFile !== recommendedPath) {
|
|
685
|
+
validFilesList.push(`- ${pageContext.pageFile}`);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
// Add other component sources (excluding recommended file)
|
|
689
|
+
for (const comp of pageContext.componentSources) {
|
|
690
|
+
if (comp.path !== recommendedPath) {
|
|
691
|
+
validFilesList.push(`- ${comp.path}`);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
textContent += `VALID FILES YOU MAY EDIT:
|
|
696
|
+
${validFilesList.join("\n")}
|
|
631
697
|
|
|
632
698
|
INSTRUCTIONS:
|
|
633
699
|
1. Look at the screenshot and identify elements mentioned in the user's request
|
|
@@ -636,6 +702,7 @@ INSTRUCTIONS:
|
|
|
636
702
|
4. PRESERVE all existing logic, hooks, API calls, and error handling
|
|
637
703
|
5. Return the FULL file content (no truncation, no "// ... existing ..." comments)
|
|
638
704
|
6. Only use file paths from the VALID FILES list above
|
|
705
|
+
7. ALWAYS prioritize the (*** RECOMMENDED ***) file if one is marked - it contains the UI you see in the screenshot
|
|
639
706
|
|
|
640
707
|
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.`;
|
|
641
708
|
|
|
@@ -514,6 +514,8 @@ export async function POST(request: Request) {
|
|
|
514
514
|
// PHASE 1+2: LLM-driven smart file discovery
|
|
515
515
|
// The LLM analyzes the screenshot and deduces component names, code patterns, and visible text
|
|
516
516
|
let smartSearchFiles: { path: string; content: string }[] = [];
|
|
517
|
+
let recommendedFile: { path: string; reason: string } | null = null;
|
|
518
|
+
|
|
517
519
|
if (screenshot) {
|
|
518
520
|
debugLog("Starting Phase 1: LLM screenshot analysis");
|
|
519
521
|
const analysis = await analyzeScreenshotForSearch(screenshot, userPrompt, apiKey);
|
|
@@ -526,13 +528,39 @@ export async function POST(request: Request) {
|
|
|
526
528
|
// PHASE 2: Smart search using component names, text, and code patterns
|
|
527
529
|
const searchResults = searchFilesSmart(analysis, projectRoot, 10);
|
|
528
530
|
smartSearchFiles = searchResults.map(r => ({ path: r.path, content: r.content }));
|
|
531
|
+
|
|
532
|
+
// Identify the recommended file (highest scoring file, prefer filename matches)
|
|
533
|
+
if (searchResults.length > 0) {
|
|
534
|
+
// Find the best filename match first
|
|
535
|
+
const filenameMatch = searchResults.find(r =>
|
|
536
|
+
analysis.componentNames.some(name =>
|
|
537
|
+
r.path.toLowerCase().includes(name.toLowerCase())
|
|
538
|
+
)
|
|
539
|
+
);
|
|
540
|
+
|
|
541
|
+
if (filenameMatch) {
|
|
542
|
+
recommendedFile = {
|
|
543
|
+
path: filenameMatch.path,
|
|
544
|
+
reason: `Component name match from screenshot analysis`
|
|
545
|
+
};
|
|
546
|
+
} else {
|
|
547
|
+
// Fall back to highest score
|
|
548
|
+
recommendedFile = {
|
|
549
|
+
path: searchResults[0].path,
|
|
550
|
+
reason: `Highest content match score (${searchResults[0].score} points)`
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
debugLog("Recommended file for editing", recommendedFile);
|
|
554
|
+
}
|
|
555
|
+
|
|
529
556
|
debugLog("Phase 1+2 complete", {
|
|
530
557
|
analysis: {
|
|
531
558
|
visibleText: analysis.visibleText.slice(0, 5),
|
|
532
559
|
componentNames: analysis.componentNames,
|
|
533
560
|
codePatterns: analysis.codePatterns.slice(0, 5)
|
|
534
561
|
},
|
|
535
|
-
filesFound: smartSearchFiles.map(f => f.path)
|
|
562
|
+
filesFound: smartSearchFiles.map(f => f.path),
|
|
563
|
+
recommendedFile
|
|
536
564
|
});
|
|
537
565
|
}
|
|
538
566
|
}
|
|
@@ -635,9 +663,47 @@ GLOBALS.CSS (relevant theme variables):
|
|
|
635
663
|
${pageContext.globalsCSS.substring(0, 2000)}${pageContext.globalsCSS.length > 2000 ? "\n/* ... (truncated) */" : ""}
|
|
636
664
|
\`\`\`
|
|
637
665
|
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
666
|
+
`;
|
|
667
|
+
|
|
668
|
+
// Add recommendation block just before VALID FILES if we have one
|
|
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
|
|
685
|
+
const validFilesList: string[] = [];
|
|
686
|
+
const recommendedPath = recommendedFile?.path;
|
|
687
|
+
|
|
688
|
+
// Add recommended file first with marker
|
|
689
|
+
if (recommendedPath) {
|
|
690
|
+
validFilesList.push(`- ${recommendedPath} (*** RECOMMENDED - EDIT THIS FILE ***)`);
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// Add page file (if not the recommended file)
|
|
694
|
+
if (pageContext.pageFile && pageContext.pageFile !== recommendedPath) {
|
|
695
|
+
validFilesList.push(`- ${pageContext.pageFile}`);
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
// Add other component sources (excluding recommended file)
|
|
699
|
+
for (const comp of pageContext.componentSources) {
|
|
700
|
+
if (comp.path !== recommendedPath) {
|
|
701
|
+
validFilesList.push(`- ${comp.path}`);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
textContent += `VALID FILES YOU MAY EDIT:
|
|
706
|
+
${validFilesList.join("\n")}
|
|
641
707
|
|
|
642
708
|
INSTRUCTIONS:
|
|
643
709
|
1. Look at the screenshot and identify elements mentioned in the user's request
|
|
@@ -646,6 +712,7 @@ INSTRUCTIONS:
|
|
|
646
712
|
4. Generate complete modified code for each file
|
|
647
713
|
5. Provide previewCSS for immediate visual feedback
|
|
648
714
|
6. Return as JSON in the specified format
|
|
715
|
+
7. ALWAYS prioritize the (*** RECOMMENDED ***) file if one is marked - it contains the UI you see in the screenshot
|
|
649
716
|
|
|
650
717
|
CRITICAL: Only use file paths from the VALID FILES list above. Do NOT create new files.`;
|
|
651
718
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sonance-brand-mcp",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.41",
|
|
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",
|