sonance-brand-mcp 1.3.39 → 1.3.40
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
|
}
|
|
@@ -569,6 +597,22 @@ User Request: "${userPrompt}"
|
|
|
569
597
|
|
|
570
598
|
`;
|
|
571
599
|
|
|
600
|
+
// Add recommendation if smart search identified a best match
|
|
601
|
+
if (recommendedFile) {
|
|
602
|
+
textContent += `═══════════════════════════════════════════════════════════════════════════════
|
|
603
|
+
⚡ RECOMMENDED FILE TO EDIT
|
|
604
|
+
═══════════════════════════════════════════════════════════════════════════════
|
|
605
|
+
|
|
606
|
+
Based on the screenshot analysis, the component you should edit is:
|
|
607
|
+
**${recommendedFile.path}**
|
|
608
|
+
Reason: ${recommendedFile.reason}
|
|
609
|
+
|
|
610
|
+
The page file (${pageContext.pageFile}) is just a wrapper - the actual UI elements are in the component above.
|
|
611
|
+
STRONGLY PREFER editing the recommended file unless you have a specific reason not to.
|
|
612
|
+
|
|
613
|
+
`;
|
|
614
|
+
}
|
|
615
|
+
|
|
572
616
|
if (focusedElements && focusedElements.length > 0) {
|
|
573
617
|
textContent += `FOCUSED ELEMENTS (user clicked on these):
|
|
574
618
|
${focusedElements.map((el) => `- ${el.name} (${el.type}) at (${el.coordinates.x}, ${el.coordinates.y})`).join("\n")}
|
|
@@ -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
|
}
|
|
@@ -579,6 +607,22 @@ User Request: "${userPrompt}"
|
|
|
579
607
|
|
|
580
608
|
`;
|
|
581
609
|
|
|
610
|
+
// Add recommendation if smart search identified a best match
|
|
611
|
+
if (recommendedFile) {
|
|
612
|
+
textContent += `═══════════════════════════════════════════════════════════════════════════════
|
|
613
|
+
⚡ RECOMMENDED FILE TO EDIT
|
|
614
|
+
═══════════════════════════════════════════════════════════════════════════════
|
|
615
|
+
|
|
616
|
+
Based on the screenshot analysis, the component you should edit is:
|
|
617
|
+
**${recommendedFile.path}**
|
|
618
|
+
Reason: ${recommendedFile.reason}
|
|
619
|
+
|
|
620
|
+
The page file (${pageContext.pageFile}) is just a wrapper - the actual UI elements are in the component above.
|
|
621
|
+
STRONGLY PREFER editing the recommended file unless you have a specific reason not to.
|
|
622
|
+
|
|
623
|
+
`;
|
|
624
|
+
}
|
|
625
|
+
|
|
582
626
|
if (focusedElements && focusedElements.length > 0) {
|
|
583
627
|
textContent += `FOCUSED ELEMENTS (user clicked on these):
|
|
584
628
|
${focusedElements.map((el) => `- ${el.name} (${el.type}) at (${el.coordinates.x}, ${el.coordinates.y})`).join("\n")}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sonance-brand-mcp",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.40",
|
|
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",
|