sonance-brand-mcp 1.3.57 → 1.3.58
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/dist/assets/api/sonance-vision-apply/route.ts +122 -295
- package/dist/assets/api/sonance-vision-edit/route.ts +47 -285
- package/dist/assets/dev-tools/components/ApplyFirstPreview.tsx +238 -28
- package/dist/assets/dev-tools/components/ChatInterface.tsx +2 -1
- package/dist/assets/dev-tools/panels/ComponentsPanel.tsx +5 -2
- package/dist/assets/dev-tools/types.ts +7 -4
- package/package.json +1 -1
|
@@ -434,104 +434,43 @@ function searchFilesSmart(
|
|
|
434
434
|
return sortedResults.map(r => ({ path: r.path, content: r.content, score: r.score }));
|
|
435
435
|
}
|
|
436
436
|
|
|
437
|
-
const VISION_SYSTEM_PROMPT = `You are
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
═══════════════════════════════════════════════════════════════════════════════
|
|
460
|
-
PATCH FORMAT
|
|
461
|
-
═══════════════════════════════════════════════════════════════════════════════
|
|
462
|
-
|
|
463
|
-
Return search/replace patches (NOT full files). The system applies your patches to the original.
|
|
464
|
-
|
|
465
|
-
**Patch Rules:**
|
|
466
|
-
- "search" must match the original code EXACTLY (including whitespace/indentation)
|
|
467
|
-
- "replace" contains your modified version
|
|
468
|
-
- Include 2-4 lines of context in "search" to make it unique
|
|
469
|
-
- You may ONLY edit files provided in the PAGE CONTEXT section
|
|
470
|
-
- CRITICAL: NEVER invent or guess code. Your "search" string MUST be copied EXACTLY from the provided file content. If you cannot find the exact code to modify, return an empty modifications array.
|
|
471
|
-
- If the file content appears truncated, only modify code that is visible in the provided content.
|
|
472
|
-
|
|
473
|
-
═══════════════════════════════════════════════════════════════════════════════
|
|
474
|
-
SONANCE BRAND COLOR SYSTEM
|
|
475
|
-
═══════════════════════════════════════════════════════════════════════════════
|
|
476
|
-
|
|
477
|
-
**Core Colors:**
|
|
478
|
-
- Primary (Charcoal): #333F48 - main text, dark backgrounds
|
|
479
|
-
- Accent (Cyan "The Beam"): #00D3C8 - highlights, interactive elements, CTAs
|
|
480
|
-
- Success: Green tones - positive states, confirmations
|
|
481
|
-
- Warning: Amber/Orange tones - caution states, alerts
|
|
482
|
-
- Destructive: Red tones - errors, delete actions
|
|
483
|
-
|
|
484
|
-
**CRITICAL CONTRAST RULES:**
|
|
485
|
-
When using colored backgrounds, ALWAYS use high-contrast text:
|
|
486
|
-
|
|
487
|
-
| Background | Use This Text | NEVER Use |
|
|
488
|
-
|-------------------|------------------------------------|-----------------------|
|
|
489
|
-
| bg-accent | text-white | text-accent-foreground |
|
|
490
|
-
| bg-primary | text-primary-foreground, text-white | text-primary |
|
|
491
|
-
| bg-success | text-white | text-success |
|
|
492
|
-
| bg-warning | text-white | text-warning |
|
|
493
|
-
| bg-destructive | text-white | text-destructive |
|
|
494
|
-
|
|
495
|
-
**SEMANTIC TOKEN PATTERNS:**
|
|
496
|
-
- text-{color} = the color itself (use on NEUTRAL backgrounds like white/gray)
|
|
497
|
-
- text-{color}-foreground = INTENDED for text on {color} backgrounds, but MAY have contrast issues
|
|
498
|
-
- bg-{color} = background in that color
|
|
499
|
-
- WHEN IN DOUBT: Use text-white on any colored background for guaranteed contrast
|
|
500
|
-
|
|
501
|
-
**BUTTON PATTERNS (Sonance Standard):**
|
|
502
|
-
- Primary CTA: bg-primary text-primary-foreground
|
|
503
|
-
- Accent/Highlight: bg-accent text-white (NOT text-accent-foreground)
|
|
504
|
-
- Success: bg-success text-white
|
|
505
|
-
- Warning: bg-warning text-white
|
|
506
|
-
- Destructive: bg-destructive text-white
|
|
507
|
-
- Outlined: border-border bg-transparent text-foreground
|
|
508
|
-
|
|
509
|
-
**COMMON MISTAKES TO AVOID:**
|
|
510
|
-
- WRONG: bg-accent text-accent-foreground (accent-foreground is often dark = invisible text)
|
|
511
|
-
- RIGHT: bg-accent text-white (white text on cyan = visible)
|
|
512
|
-
- WRONG: bg-primary text-primary (same color = invisible)
|
|
513
|
-
- RIGHT: bg-primary text-primary-foreground OR text-white
|
|
514
|
-
|
|
515
|
-
**RESPONSE FORMAT:**
|
|
516
|
-
CRITICAL: Return ONLY the JSON object below. Do NOT include any text, explanation, or thinking before or after the JSON. No preamble. No "Looking at the screenshot..." No markdown code blocks. Just raw JSON:
|
|
437
|
+
const VISION_SYSTEM_PROMPT = `You are a code editor. Make ONLY the change the user requested.
|
|
438
|
+
|
|
439
|
+
RULES:
|
|
440
|
+
1. Make the SMALLEST possible change to accomplish the request
|
|
441
|
+
2. Do NOT refactor, rebrand, or "improve" anything else
|
|
442
|
+
3. Do NOT change import statements unless explicitly required
|
|
443
|
+
4. Do NOT change component libraries (e.g., heroui to shadcn)
|
|
444
|
+
5. If fixing a color/visibility issue, change ONLY that element's classes
|
|
445
|
+
6. Your patch should typically be 1-5 lines, not 50+
|
|
446
|
+
7. NEVER invent or guess code - your "search" string MUST match the file EXACTLY
|
|
447
|
+
8. NEVER change data mappings (icon names, keys, enum values) unless user explicitly provides the new values
|
|
448
|
+
9. If you don't know what values exist in a database or data source, DO NOT guess - ask for clarification
|
|
449
|
+
|
|
450
|
+
CRITICAL - DATA INTEGRITY:
|
|
451
|
+
- If code references database values (like icon_name, type, status), DO NOT change the mapping keys
|
|
452
|
+
- You cannot see database content - only change STRUCTURE, not DATA MAPPINGS
|
|
453
|
+
- Example: If you see iconMap["EyeOff"] = SomeIcon, do NOT change "EyeOff" to something else
|
|
454
|
+
- If user wants different icons, they must tell you the EXACT icon names they want
|
|
455
|
+
|
|
456
|
+
PATCH FORMAT:
|
|
457
|
+
Return ONLY raw JSON (no markdown, no preamble):
|
|
517
458
|
{
|
|
518
|
-
"reasoning": "
|
|
519
|
-
"modifications": [
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
"
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
],
|
|
529
|
-
"previewCSS": "optional CSS for live preview"
|
|
530
|
-
}
|
|
531
|
-
],
|
|
459
|
+
"reasoning": "brief explanation",
|
|
460
|
+
"modifications": [{
|
|
461
|
+
"filePath": "path/to/file.tsx",
|
|
462
|
+
"patches": [{
|
|
463
|
+
"search": "exact original code (copy from provided file)",
|
|
464
|
+
"replace": "minimal change",
|
|
465
|
+
"explanation": "what this does"
|
|
466
|
+
}],
|
|
467
|
+
"previewCSS": "optional CSS for live preview"
|
|
468
|
+
}],
|
|
532
469
|
"aggregatedPreviewCSS": "combined CSS for all changes",
|
|
533
|
-
"explanation": "summary
|
|
534
|
-
}
|
|
470
|
+
"explanation": "summary"
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
If you cannot find the exact code to modify, OR if you would need to guess data values, return empty modifications array with explanation.`;
|
|
535
474
|
|
|
536
475
|
export async function POST(request: Request) {
|
|
537
476
|
// Only allow in development
|
|
@@ -708,141 +647,6 @@ export async function POST(request: Request) {
|
|
|
708
647
|
});
|
|
709
648
|
}
|
|
710
649
|
|
|
711
|
-
// ========== PHASE A: VISUAL PROBLEM ANALYSIS ==========
|
|
712
|
-
// Before generating patches, analyze WHAT is visually wrong
|
|
713
|
-
// This forces the LLM to articulate the problem before trying to fix it
|
|
714
|
-
interface VisualAnalysis {
|
|
715
|
-
element: string;
|
|
716
|
-
elementText: string; // The visible text content of the element (for finding in code)
|
|
717
|
-
problem: string;
|
|
718
|
-
changeType: "styling" | "structural" | "content" | "other";
|
|
719
|
-
currentClasses?: string; // For styling changes: what classes appear to be applied
|
|
720
|
-
classChange?: {
|
|
721
|
-
remove?: string[]; // Classes to remove
|
|
722
|
-
add?: string[]; // Classes to add
|
|
723
|
-
};
|
|
724
|
-
structuralChange?: string; // For structural changes: what to add/remove/wrap
|
|
725
|
-
solution: string;
|
|
726
|
-
confidence: "high" | "medium" | "low";
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
let visualAnalysis: VisualAnalysis | null = null;
|
|
730
|
-
|
|
731
|
-
if (screenshot && userPrompt) {
|
|
732
|
-
debugLog("Phase A: Starting visual problem analysis");
|
|
733
|
-
|
|
734
|
-
const analysisClient = new Anthropic({ apiKey });
|
|
735
|
-
|
|
736
|
-
try {
|
|
737
|
-
const analysisResponse = await analysisClient.messages.create({
|
|
738
|
-
model: "claude-sonnet-4-20250514",
|
|
739
|
-
max_tokens: 1024,
|
|
740
|
-
messages: [
|
|
741
|
-
{
|
|
742
|
-
role: "user",
|
|
743
|
-
content: [
|
|
744
|
-
{
|
|
745
|
-
type: "image",
|
|
746
|
-
source: {
|
|
747
|
-
type: "base64",
|
|
748
|
-
media_type: "image/png",
|
|
749
|
-
data: base64Data,
|
|
750
|
-
},
|
|
751
|
-
},
|
|
752
|
-
{
|
|
753
|
-
type: "text",
|
|
754
|
-
text: `You are analyzing a UI screenshot to understand what the user wants changed.
|
|
755
|
-
|
|
756
|
-
User request: "${userPrompt}"
|
|
757
|
-
|
|
758
|
-
${focusedElements && focusedElements.length > 0 ? `User clicked on these elements:
|
|
759
|
-
${focusedElements.map((el) => `- ${el.name} (${el.type}) at position (${el.coordinates.x}, ${el.coordinates.y})`).join("\n")}
|
|
760
|
-
` : ""}
|
|
761
|
-
|
|
762
|
-
Analyze the request and determine:
|
|
763
|
-
1. ELEMENT: Which specific UI element needs to change? (describe location and appearance)
|
|
764
|
-
2. ELEMENT TEXT: What text is visible inside this element? (EXACT text for finding in code)
|
|
765
|
-
3. PROBLEM: What is wrong or what does the user want changed?
|
|
766
|
-
4. CHANGE TYPE: Is this a "styling" (colors/size/spacing), "structural" (add/remove elements), "content" (text changes), or "other" change?
|
|
767
|
-
5. For STYLING changes: What Tailwind classes should be REMOVED and what should be ADDED?
|
|
768
|
-
6. For STRUCTURAL changes: What element should be added, removed, or wrapped?
|
|
769
|
-
7. SOLUTION: Describe the complete fix
|
|
770
|
-
8. CONFIDENCE: high/medium/low
|
|
771
|
-
|
|
772
|
-
IMPORTANT for styling fixes:
|
|
773
|
-
- If text is invisible on a background, typically REMOVE the problematic text color class and ADD a contrasting one
|
|
774
|
-
- Common fix for invisible text on colored backgrounds: REMOVE "text-accent-foreground" or similar, ADD "text-white" or "text-black"
|
|
775
|
-
- Be SPECIFIC about exact class names
|
|
776
|
-
|
|
777
|
-
Return ONLY valid JSON:
|
|
778
|
-
{
|
|
779
|
-
"element": "description of the UI element",
|
|
780
|
-
"elementText": "exact visible text in the element",
|
|
781
|
-
"problem": "what is wrong",
|
|
782
|
-
"changeType": "styling",
|
|
783
|
-
"currentClasses": "classes that appear to be applied (best guess)",
|
|
784
|
-
"classChange": {
|
|
785
|
-
"remove": ["text-accent-foreground"],
|
|
786
|
-
"add": ["text-white"]
|
|
787
|
-
},
|
|
788
|
-
"solution": "complete description of the fix",
|
|
789
|
-
"confidence": "high"
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
For structural changes:
|
|
793
|
-
{
|
|
794
|
-
"element": "description of the UI element",
|
|
795
|
-
"elementText": "text near the element",
|
|
796
|
-
"problem": "what is wrong",
|
|
797
|
-
"changeType": "structural",
|
|
798
|
-
"structuralChange": "Add a new button after the existing one",
|
|
799
|
-
"solution": "complete description of the fix",
|
|
800
|
-
"confidence": "high"
|
|
801
|
-
}`,
|
|
802
|
-
},
|
|
803
|
-
],
|
|
804
|
-
},
|
|
805
|
-
],
|
|
806
|
-
});
|
|
807
|
-
|
|
808
|
-
const analysisText = analysisResponse.content.find((block) => block.type === "text");
|
|
809
|
-
if (analysisText && analysisText.type === "text") {
|
|
810
|
-
// Parse the JSON response
|
|
811
|
-
let jsonText = analysisText.text.trim();
|
|
812
|
-
// Extract JSON if wrapped in code blocks
|
|
813
|
-
const jsonMatch = jsonText.match(/```(?:json)?\s*([\s\S]*?)\s*```/) || jsonText.match(/(\{[\s\S]*\})/);
|
|
814
|
-
if (jsonMatch) {
|
|
815
|
-
jsonText = jsonMatch[1];
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
try {
|
|
819
|
-
visualAnalysis = JSON.parse(jsonText) as VisualAnalysis;
|
|
820
|
-
debugLog("Phase A: Visual problem analysis complete", visualAnalysis);
|
|
821
|
-
|
|
822
|
-
// If low confidence, return early with clarification request
|
|
823
|
-
if (visualAnalysis.confidence === "low") {
|
|
824
|
-
debugLog("Phase A: Low confidence - requesting clarification");
|
|
825
|
-
return NextResponse.json({
|
|
826
|
-
success: false,
|
|
827
|
-
needsClarification: true,
|
|
828
|
-
analysis: visualAnalysis,
|
|
829
|
-
message: `I can see "${visualAnalysis.element}" but I'm not certain about the problem: "${visualAnalysis.problem}". Can you be more specific about what needs to change?`,
|
|
830
|
-
});
|
|
831
|
-
}
|
|
832
|
-
} catch (parseError) {
|
|
833
|
-
debugLog("Phase A: Failed to parse analysis response", {
|
|
834
|
-
error: String(parseError),
|
|
835
|
-
response: jsonText.substring(0, 500)
|
|
836
|
-
});
|
|
837
|
-
// Continue without analysis if parsing fails
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
} catch (analysisError) {
|
|
841
|
-
debugLog("Phase A: Analysis call failed", { error: String(analysisError) });
|
|
842
|
-
// Continue without analysis - fall back to existing behavior
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
|
|
846
650
|
// ========== SMART CONTEXT BUDGETING ==========
|
|
847
651
|
// Claude can handle 200k tokens (~800k chars), so we can safely include large files
|
|
848
652
|
// Priority: Recommended file (NEVER truncate) > Page file (limited) > Other components (dynamic)
|
|
@@ -879,58 +683,6 @@ ${focusedElements.map((el) => `- ${el.name} (${el.type}) at (${el.coordinates.x}
|
|
|
879
683
|
`;
|
|
880
684
|
}
|
|
881
685
|
|
|
882
|
-
// ========== VISUAL PROBLEM ANALYSIS (from Phase A) ==========
|
|
883
|
-
if (visualAnalysis) {
|
|
884
|
-
let analysisInstructions = `═══════════════════════════════════════════════════════════════════════════════
|
|
885
|
-
🔍 VISUAL PROBLEM ANALYSIS (I analyzed the screenshot first)
|
|
886
|
-
═══════════════════════════════════════════════════════════════════════════════
|
|
887
|
-
|
|
888
|
-
**Element:** ${visualAnalysis.element}
|
|
889
|
-
**Element Text:** "${visualAnalysis.elementText || "unknown"}"
|
|
890
|
-
**Problem:** ${visualAnalysis.problem}
|
|
891
|
-
**Change Type:** ${visualAnalysis.changeType}
|
|
892
|
-
**Solution:** ${visualAnalysis.solution}
|
|
893
|
-
**Confidence:** ${visualAnalysis.confidence}
|
|
894
|
-
|
|
895
|
-
`;
|
|
896
|
-
|
|
897
|
-
// Add specific instructions based on change type
|
|
898
|
-
if (visualAnalysis.changeType === "styling" && visualAnalysis.classChange) {
|
|
899
|
-
analysisInstructions += `🎯 EXACT CLASS CHANGES REQUIRED:
|
|
900
|
-
`;
|
|
901
|
-
if (visualAnalysis.classChange.remove && visualAnalysis.classChange.remove.length > 0) {
|
|
902
|
-
analysisInstructions += ` REMOVE these classes: ${visualAnalysis.classChange.remove.join(", ")}
|
|
903
|
-
`;
|
|
904
|
-
}
|
|
905
|
-
if (visualAnalysis.classChange.add && visualAnalysis.classChange.add.length > 0) {
|
|
906
|
-
analysisInstructions += ` ADD these classes: ${visualAnalysis.classChange.add.join(", ")}
|
|
907
|
-
`;
|
|
908
|
-
}
|
|
909
|
-
analysisInstructions += `
|
|
910
|
-
⚠️ YOUR PATCH MUST:
|
|
911
|
-
1. Find the element containing "${visualAnalysis.elementText || visualAnalysis.element}"
|
|
912
|
-
2. In its className, ${visualAnalysis.classChange.remove?.length ? `REMOVE: ${visualAnalysis.classChange.remove.join(", ")}` : ""}
|
|
913
|
-
3. ${visualAnalysis.classChange.add?.length ? `ADD: ${visualAnalysis.classChange.add.join(", ")}` : ""}
|
|
914
|
-
4. Do NOT add unrelated changes like font-weight or hover states unless specifically requested
|
|
915
|
-
|
|
916
|
-
`;
|
|
917
|
-
} else if (visualAnalysis.changeType === "structural" && visualAnalysis.structuralChange) {
|
|
918
|
-
analysisInstructions += `🔧 STRUCTURAL CHANGE REQUIRED:
|
|
919
|
-
${visualAnalysis.structuralChange}
|
|
920
|
-
|
|
921
|
-
⚠️ YOUR PATCH MUST implement this structural change exactly as described.
|
|
922
|
-
|
|
923
|
-
`;
|
|
924
|
-
} else {
|
|
925
|
-
analysisInstructions += `⚠️ IMPORTANT: Your patches MUST implement the fix described above.
|
|
926
|
-
Find the code that renders "${visualAnalysis.element}" and apply: ${visualAnalysis.solution}
|
|
927
|
-
|
|
928
|
-
`;
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
textContent += analysisInstructions;
|
|
932
|
-
}
|
|
933
|
-
|
|
934
686
|
// ========== TARGET COMPONENT (RECOMMENDED FILE) - SHOWN FIRST ==========
|
|
935
687
|
if (recommendedFileContent) {
|
|
936
688
|
// Never truncate the recommended file - AI needs full context to avoid hallucination
|
|
@@ -995,17 +747,27 @@ ${truncatedContent}${wasTruncated ? "\n// ... (truncated)" : ""}
|
|
|
995
747
|
}
|
|
996
748
|
}
|
|
997
749
|
|
|
998
|
-
// ========== THEME DISCOVERY ==========
|
|
750
|
+
// ========== THEME DISCOVERY (REFERENCE ONLY) ==========
|
|
999
751
|
// Dynamically discover theme tokens from the target codebase
|
|
752
|
+
// This is marked as REFERENCE ONLY so the LLM doesn't use it to justify extra changes
|
|
1000
753
|
const discoveredTheme = await discoverTheme(projectRoot);
|
|
1001
754
|
const themeContext = formatThemeForPrompt(discoveredTheme);
|
|
1002
755
|
|
|
1003
756
|
if (discoveredTheme.discoveredFiles.length > 0) {
|
|
1004
757
|
textContent += `
|
|
1005
758
|
═══════════════════════════════════════════════════════════════════════════════
|
|
1006
|
-
|
|
759
|
+
REFERENCE ONLY (do not use this to justify additional changes)
|
|
1007
760
|
═══════════════════════════════════════════════════════════════════════════════
|
|
1008
761
|
|
|
762
|
+
If you need to pick a color for a VISIBILITY fix, these are safe choices:
|
|
763
|
+
- bg-accent text-white (cyan button with white text)
|
|
764
|
+
- bg-primary text-white (charcoal button with white text)
|
|
765
|
+
- bg-success text-white (green button with white text)
|
|
766
|
+
- bg-destructive text-white (red button with white text)
|
|
767
|
+
|
|
768
|
+
But ONLY use these if the user is asking for a color/visibility change.
|
|
769
|
+
Do NOT rebrand or change other elements to match.
|
|
770
|
+
|
|
1009
771
|
`;
|
|
1010
772
|
debugLog("Theme discovery complete", {
|
|
1011
773
|
filesFound: discoveredTheme.discoveredFiles,
|