sonance-brand-mcp 1.3.27 → 1.3.29
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.
|
@@ -58,6 +58,26 @@ interface BackupManifest {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
const BACKUP_ROOT = ".sonance-backups";
|
|
61
|
+
const DEBUG_LOG_FILE = "sonance-debug.log";
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Debug logging utility - writes to sonance-debug.log in project root
|
|
65
|
+
* This helps diagnose issues with file discovery, validation, and revert
|
|
66
|
+
*/
|
|
67
|
+
function debugLog(message: string, data?: unknown) {
|
|
68
|
+
const timestamp = new Date().toISOString();
|
|
69
|
+
const dataStr = data !== undefined ? `\n${JSON.stringify(data, null, 2)}` : "";
|
|
70
|
+
const logEntry = `[${timestamp}] [apply] ${message}${dataStr}\n`;
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
const logPath = path.join(process.cwd(), DEBUG_LOG_FILE);
|
|
74
|
+
fs.appendFileSync(logPath, logEntry);
|
|
75
|
+
// Also log to console for terminal visibility
|
|
76
|
+
console.log(`[Sonance] ${message}`, data !== undefined ? data : "");
|
|
77
|
+
} catch (e) {
|
|
78
|
+
console.error("[Sonance] Failed to write debug log:", e);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
61
81
|
|
|
62
82
|
const VISION_SYSTEM_PROMPT = `You are an expert React/TypeScript developer with vision capabilities. You can see screenshots and modify code.
|
|
63
83
|
|
|
@@ -377,6 +397,12 @@ CRITICAL: Your modified file should have approximately the same number of lines
|
|
|
377
397
|
validFilePaths.add(comp.path);
|
|
378
398
|
}
|
|
379
399
|
|
|
400
|
+
debugLog("VALIDATION: Valid file paths from page context", {
|
|
401
|
+
pageFile: pageContext.pageFile,
|
|
402
|
+
validFilePaths: Array.from(validFilePaths),
|
|
403
|
+
aiRequestedFiles: aiResponse.modifications.map(m => m.filePath)
|
|
404
|
+
});
|
|
405
|
+
|
|
380
406
|
// Process modifications - apply patches to get modified content
|
|
381
407
|
const modifications: VisionFileModification[] = [];
|
|
382
408
|
const patchErrors: string[] = [];
|
|
@@ -384,7 +410,15 @@ CRITICAL: Your modified file should have approximately the same number of lines
|
|
|
384
410
|
for (const mod of aiResponse.modifications) {
|
|
385
411
|
// Validate that the file path is in the page context
|
|
386
412
|
// This prevents the AI from creating new files
|
|
387
|
-
|
|
413
|
+
const isValidPath = validFilePaths.has(mod.filePath);
|
|
414
|
+
debugLog(`VALIDATION CHECK: ${mod.filePath}`, {
|
|
415
|
+
isValidPath,
|
|
416
|
+
fileExists: fs.existsSync(path.join(projectRoot, mod.filePath)),
|
|
417
|
+
validPaths: Array.from(validFilePaths)
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
if (!isValidPath) {
|
|
421
|
+
debugLog(`REJECTED: File not in page context`, { filePath: mod.filePath });
|
|
388
422
|
console.warn(`[Apply-First] Rejected modification to unknown file: ${mod.filePath}`);
|
|
389
423
|
console.warn(`[Apply-First] Valid files are: ${Array.from(validFilePaths).join(", ")}`);
|
|
390
424
|
patchErrors.push(`${mod.filePath}: This file was not found in the page context. The AI can only modify existing files that are part of the current page.`);
|
|
@@ -603,9 +637,11 @@ async function revertFromBackups(
|
|
|
603
637
|
sessionId: string,
|
|
604
638
|
projectRoot: string
|
|
605
639
|
): Promise<{ success: boolean; message: string; filesReverted: number }> {
|
|
640
|
+
debugLog("revertFromBackups called", { sessionId, projectRoot });
|
|
606
641
|
const backupDir = path.join(projectRoot, BACKUP_ROOT, sessionId);
|
|
607
642
|
|
|
608
643
|
if (!fs.existsSync(backupDir)) {
|
|
644
|
+
debugLog("REVERT ERROR: Backup directory not found", { backupDir });
|
|
609
645
|
return {
|
|
610
646
|
success: false,
|
|
611
647
|
message: "Backup session not found",
|
|
@@ -617,7 +653,7 @@ async function revertFromBackups(
|
|
|
617
653
|
const manifestPath = path.join(backupDir, "manifest.json");
|
|
618
654
|
|
|
619
655
|
if (!fs.existsSync(manifestPath)) {
|
|
620
|
-
|
|
656
|
+
debugLog("REVERT ERROR: Manifest not found", { manifestPath });
|
|
621
657
|
return {
|
|
622
658
|
success: false,
|
|
623
659
|
message: "Backup manifest not found",
|
|
@@ -628,18 +664,31 @@ async function revertFromBackups(
|
|
|
628
664
|
const manifest: BackupManifest = JSON.parse(
|
|
629
665
|
fs.readFileSync(manifestPath, "utf-8")
|
|
630
666
|
);
|
|
667
|
+
|
|
668
|
+
debugLog("REVERT: Loaded manifest", {
|
|
669
|
+
sessionId: manifest.sessionId,
|
|
670
|
+
fileCount: manifest.files.length,
|
|
671
|
+
files: manifest.files.map(f => ({ path: f.original, isNewFile: f.isNewFile }))
|
|
672
|
+
});
|
|
631
673
|
|
|
632
674
|
let filesReverted = 0;
|
|
633
675
|
let filesDeleted = 0;
|
|
634
676
|
|
|
635
677
|
for (const file of manifest.files) {
|
|
636
678
|
const originalPath = path.join(projectRoot, file.original);
|
|
679
|
+
debugLog(`REVERT: Processing file`, {
|
|
680
|
+
filePath: file.original,
|
|
681
|
+
isNewFile: file.isNewFile,
|
|
682
|
+
fileExists: fs.existsSync(originalPath)
|
|
683
|
+
});
|
|
637
684
|
|
|
638
685
|
// Handle new files - delete them
|
|
639
686
|
if (file.isNewFile) {
|
|
687
|
+
debugLog(`REVERT: Attempting to delete new file`, { originalPath });
|
|
640
688
|
if (fs.existsSync(originalPath)) {
|
|
641
689
|
fs.unlinkSync(originalPath);
|
|
642
690
|
filesDeleted++;
|
|
691
|
+
debugLog(`REVERT: Successfully deleted new file`, { originalPath });
|
|
643
692
|
console.log(`[Revert] Deleted new file: ${file.original}`);
|
|
644
693
|
|
|
645
694
|
// Clean up empty parent directories
|
|
@@ -853,8 +902,11 @@ function gatherPageContext(
|
|
|
853
902
|
}
|
|
854
903
|
|
|
855
904
|
function discoverPageFile(route: string, projectRoot: string): string | null {
|
|
905
|
+
debugLog("discoverPageFile called", { route, projectRoot });
|
|
906
|
+
|
|
856
907
|
// Handle root route
|
|
857
908
|
if (route === "/" || route === "") {
|
|
909
|
+
debugLog("Handling root route, checking patterns...");
|
|
858
910
|
const rootPatterns = [
|
|
859
911
|
// App Router patterns
|
|
860
912
|
"src/app/page.tsx",
|
|
@@ -901,18 +953,26 @@ function discoverPageFile(route: string, projectRoot: string): string | null {
|
|
|
901
953
|
];
|
|
902
954
|
|
|
903
955
|
for (const pattern of patterns) {
|
|
904
|
-
|
|
956
|
+
const fullPath = path.join(projectRoot, pattern);
|
|
957
|
+
const exists = fs.existsSync(fullPath);
|
|
958
|
+
debugLog(`Checking exact pattern: ${pattern}`, { exists });
|
|
959
|
+
if (exists) {
|
|
960
|
+
debugLog("Found exact match!", { pattern });
|
|
905
961
|
return pattern;
|
|
906
962
|
}
|
|
907
963
|
}
|
|
908
964
|
|
|
965
|
+
debugLog("No exact match found, trying dynamic route matching...");
|
|
966
|
+
|
|
909
967
|
// If exact match not found, try dynamic route matching
|
|
910
968
|
// e.g., /processes/123 -> src/pages/processes/[id].tsx
|
|
911
969
|
const dynamicResult = findDynamicRoute(cleanRoute, projectRoot);
|
|
912
970
|
if (dynamicResult) {
|
|
971
|
+
debugLog("Found dynamic route match!", { dynamicResult });
|
|
913
972
|
return dynamicResult;
|
|
914
973
|
}
|
|
915
974
|
|
|
975
|
+
debugLog("discoverPageFile: NO FILE FOUND for route", { route });
|
|
916
976
|
return null;
|
|
917
977
|
}
|
|
918
978
|
|
|
@@ -922,6 +982,7 @@ function discoverPageFile(route: string, projectRoot: string): string | null {
|
|
|
922
982
|
*/
|
|
923
983
|
function findDynamicRoute(cleanRoute: string, projectRoot: string): string | null {
|
|
924
984
|
const segments = cleanRoute.split("/");
|
|
985
|
+
debugLog("findDynamicRoute called", { cleanRoute, segments });
|
|
925
986
|
|
|
926
987
|
// Try replacing the last segment with dynamic patterns
|
|
927
988
|
const baseDirs = [
|
|
@@ -936,7 +997,10 @@ function findDynamicRoute(cleanRoute: string, projectRoot: string): string | nul
|
|
|
936
997
|
|
|
937
998
|
for (const baseDir of baseDirs) {
|
|
938
999
|
const basePath = path.join(projectRoot, baseDir);
|
|
939
|
-
if (!fs.existsSync(basePath))
|
|
1000
|
+
if (!fs.existsSync(basePath)) {
|
|
1001
|
+
debugLog(`Base dir does not exist: ${baseDir}`);
|
|
1002
|
+
continue;
|
|
1003
|
+
}
|
|
940
1004
|
|
|
941
1005
|
// Build path with all segments except the last one
|
|
942
1006
|
const parentSegments = segments.slice(0, -1);
|
|
@@ -944,6 +1008,8 @@ function findDynamicRoute(cleanRoute: string, projectRoot: string): string | nul
|
|
|
944
1008
|
? path.join(basePath, ...parentSegments)
|
|
945
1009
|
: basePath;
|
|
946
1010
|
|
|
1011
|
+
debugLog(`Checking parent path for dynamic routes`, { baseDir, parentPath, exists: fs.existsSync(parentPath) });
|
|
1012
|
+
|
|
947
1013
|
if (!fs.existsSync(parentPath)) continue;
|
|
948
1014
|
|
|
949
1015
|
// Check for dynamic route files
|
|
@@ -974,31 +1040,43 @@ function findDynamicRoute(cleanRoute: string, projectRoot: string): string | nul
|
|
|
974
1040
|
// Also scan directory for any dynamic segment pattern [...]
|
|
975
1041
|
try {
|
|
976
1042
|
const entries = fs.readdirSync(parentPath, { withFileTypes: true });
|
|
1043
|
+
const dynamicEntries = entries.filter(e => e.name.startsWith("[") && e.name.includes("]"));
|
|
1044
|
+
debugLog(`Scanning directory for dynamic segments`, { parentPath, dynamicEntries: dynamicEntries.map(e => e.name) });
|
|
1045
|
+
|
|
977
1046
|
for (const entry of entries) {
|
|
978
1047
|
if (entry.name.startsWith("[") && entry.name.includes("]")) {
|
|
1048
|
+
debugLog(`Found dynamic segment: ${entry.name}`, { isDirectory: entry.isDirectory() });
|
|
979
1049
|
for (const ext of extensions) {
|
|
980
1050
|
if (entry.isDirectory()) {
|
|
981
1051
|
// App Router or Pages Router with folder
|
|
982
1052
|
const pagePath = path.join(parentPath, entry.name, `page${ext}`);
|
|
983
1053
|
const indexPath = path.join(parentPath, entry.name, `index${ext}`);
|
|
1054
|
+
debugLog(`Checking dynamic folder paths`, { pagePath, indexPath, pageExists: fs.existsSync(pagePath), indexExists: fs.existsSync(indexPath) });
|
|
984
1055
|
if (fs.existsSync(pagePath)) {
|
|
985
|
-
|
|
1056
|
+
const result = path.relative(projectRoot, pagePath);
|
|
1057
|
+
debugLog(`Found dynamic route (folder/page)!`, { result });
|
|
1058
|
+
return result;
|
|
986
1059
|
}
|
|
987
1060
|
if (fs.existsSync(indexPath)) {
|
|
988
|
-
|
|
1061
|
+
const result = path.relative(projectRoot, indexPath);
|
|
1062
|
+
debugLog(`Found dynamic route (folder/index)!`, { result });
|
|
1063
|
+
return result;
|
|
989
1064
|
}
|
|
990
1065
|
} else if (entry.isFile() && entry.name.endsWith(ext)) {
|
|
991
1066
|
// Pages Router file-based
|
|
992
|
-
|
|
1067
|
+
const result = path.relative(projectRoot, path.join(parentPath, entry.name));
|
|
1068
|
+
debugLog(`Found dynamic route (file)!`, { result });
|
|
1069
|
+
return result;
|
|
993
1070
|
}
|
|
994
1071
|
}
|
|
995
1072
|
}
|
|
996
1073
|
}
|
|
997
|
-
} catch {
|
|
998
|
-
|
|
1074
|
+
} catch (e) {
|
|
1075
|
+
debugLog(`Error scanning directory: ${parentPath}`, { error: String(e) });
|
|
999
1076
|
}
|
|
1000
1077
|
}
|
|
1001
1078
|
|
|
1079
|
+
debugLog("findDynamicRoute: NO DYNAMIC ROUTE FOUND");
|
|
1002
1080
|
return null;
|
|
1003
1081
|
}
|
|
1004
1082
|
|
|
@@ -56,6 +56,27 @@ interface VisionEditResponse {
|
|
|
56
56
|
error?: string;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
const DEBUG_LOG_FILE = "sonance-debug.log";
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Debug logging utility - writes to sonance-debug.log in project root
|
|
63
|
+
* This helps diagnose issues with file discovery, validation, and revert
|
|
64
|
+
*/
|
|
65
|
+
function debugLog(message: string, data?: unknown) {
|
|
66
|
+
const timestamp = new Date().toISOString();
|
|
67
|
+
const dataStr = data !== undefined ? `\n${JSON.stringify(data, null, 2)}` : "";
|
|
68
|
+
const logEntry = `[${timestamp}] [edit] ${message}${dataStr}\n`;
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
const logPath = path.join(process.cwd(), DEBUG_LOG_FILE);
|
|
72
|
+
fs.appendFileSync(logPath, logEntry);
|
|
73
|
+
// Also log to console for terminal visibility
|
|
74
|
+
console.log(`[Sonance] ${message}`, data !== undefined ? data : "");
|
|
75
|
+
} catch (e) {
|
|
76
|
+
console.error("[Sonance] Failed to write debug log:", e);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
59
80
|
const VISION_SYSTEM_PROMPT = `You are an expert React/TypeScript developer with vision capabilities. You can see screenshots and modify code.
|
|
60
81
|
|
|
61
82
|
═══════════════════════════════════════════════════════════════════════════════
|
|
@@ -381,12 +402,19 @@ CRITICAL: Only use file paths from the VALID FILES list above. Do NOT create new
|
|
|
381
402
|
validPaths.add(comp.path);
|
|
382
403
|
}
|
|
383
404
|
|
|
405
|
+
debugLog("VALIDATION: Valid file paths from page context", {
|
|
406
|
+
pageFile: pageContext.pageFile,
|
|
407
|
+
validPaths: Array.from(validPaths),
|
|
408
|
+
aiRequestedFiles: (aiResponse.modifications || []).map(m => m.filePath)
|
|
409
|
+
});
|
|
410
|
+
|
|
384
411
|
// Validate AI response - reject any file paths not in our valid list
|
|
385
412
|
const invalidMods = (aiResponse.modifications || []).filter(
|
|
386
413
|
(mod) => !validPaths.has(mod.filePath)
|
|
387
414
|
);
|
|
388
415
|
|
|
389
416
|
if (invalidMods.length > 0) {
|
|
417
|
+
debugLog("REJECTED: AI attempted to create new files", { invalidMods: invalidMods.map(m => m.filePath) });
|
|
390
418
|
console.error(
|
|
391
419
|
"AI attempted to create new files:",
|
|
392
420
|
invalidMods.map((m) => m.filePath)
|
|
@@ -761,8 +789,11 @@ function gatherPageContext(
|
|
|
761
789
|
* Supports both App Router (src/app/) and Pages Router (src/pages/, pages/)
|
|
762
790
|
*/
|
|
763
791
|
function discoverPageFile(route: string, projectRoot: string): string | null {
|
|
792
|
+
debugLog("discoverPageFile called", { route, projectRoot });
|
|
793
|
+
|
|
764
794
|
// Handle root route
|
|
765
795
|
if (route === "/" || route === "") {
|
|
796
|
+
debugLog("Handling root route, checking patterns...");
|
|
766
797
|
const rootPatterns = [
|
|
767
798
|
// App Router patterns
|
|
768
799
|
"src/app/page.tsx",
|
|
@@ -810,18 +841,26 @@ function discoverPageFile(route: string, projectRoot: string): string | null {
|
|
|
810
841
|
];
|
|
811
842
|
|
|
812
843
|
for (const pattern of patterns) {
|
|
813
|
-
|
|
844
|
+
const fullPath = path.join(projectRoot, pattern);
|
|
845
|
+
const exists = fs.existsSync(fullPath);
|
|
846
|
+
debugLog(`Checking exact pattern: ${pattern}`, { exists });
|
|
847
|
+
if (exists) {
|
|
848
|
+
debugLog("Found exact match!", { pattern });
|
|
814
849
|
return pattern;
|
|
815
850
|
}
|
|
816
851
|
}
|
|
817
852
|
|
|
853
|
+
debugLog("No exact match found, trying dynamic route matching...");
|
|
854
|
+
|
|
818
855
|
// If exact match not found, try dynamic route matching
|
|
819
856
|
// e.g., /processes/123 -> src/pages/processes/[id].tsx
|
|
820
857
|
const dynamicResult = findDynamicRoute(cleanRoute, projectRoot);
|
|
821
858
|
if (dynamicResult) {
|
|
859
|
+
debugLog("Found dynamic route match!", { dynamicResult });
|
|
822
860
|
return dynamicResult;
|
|
823
861
|
}
|
|
824
862
|
|
|
863
|
+
debugLog("discoverPageFile: NO FILE FOUND for route", { route });
|
|
825
864
|
return null;
|
|
826
865
|
}
|
|
827
866
|
|
|
@@ -831,6 +870,7 @@ function discoverPageFile(route: string, projectRoot: string): string | null {
|
|
|
831
870
|
*/
|
|
832
871
|
function findDynamicRoute(cleanRoute: string, projectRoot: string): string | null {
|
|
833
872
|
const segments = cleanRoute.split("/");
|
|
873
|
+
debugLog("findDynamicRoute called", { cleanRoute, segments });
|
|
834
874
|
|
|
835
875
|
// Try replacing the last segment with dynamic patterns
|
|
836
876
|
const baseDirs = [
|
|
@@ -845,7 +885,10 @@ function findDynamicRoute(cleanRoute: string, projectRoot: string): string | nul
|
|
|
845
885
|
|
|
846
886
|
for (const baseDir of baseDirs) {
|
|
847
887
|
const basePath = path.join(projectRoot, baseDir);
|
|
848
|
-
if (!fs.existsSync(basePath))
|
|
888
|
+
if (!fs.existsSync(basePath)) {
|
|
889
|
+
debugLog(`Base dir does not exist: ${baseDir}`);
|
|
890
|
+
continue;
|
|
891
|
+
}
|
|
849
892
|
|
|
850
893
|
// Build path with all segments except the last one
|
|
851
894
|
const parentSegments = segments.slice(0, -1);
|
|
@@ -853,6 +896,8 @@ function findDynamicRoute(cleanRoute: string, projectRoot: string): string | nul
|
|
|
853
896
|
? path.join(basePath, ...parentSegments)
|
|
854
897
|
: basePath;
|
|
855
898
|
|
|
899
|
+
debugLog(`Checking parent path for dynamic routes`, { baseDir, parentPath, exists: fs.existsSync(parentPath) });
|
|
900
|
+
|
|
856
901
|
if (!fs.existsSync(parentPath)) continue;
|
|
857
902
|
|
|
858
903
|
// Check for dynamic route files
|
|
@@ -883,31 +928,43 @@ function findDynamicRoute(cleanRoute: string, projectRoot: string): string | nul
|
|
|
883
928
|
// Also scan directory for any dynamic segment pattern [...]
|
|
884
929
|
try {
|
|
885
930
|
const entries = fs.readdirSync(parentPath, { withFileTypes: true });
|
|
931
|
+
const dynamicEntries = entries.filter(e => e.name.startsWith("[") && e.name.includes("]"));
|
|
932
|
+
debugLog(`Scanning directory for dynamic segments`, { parentPath, dynamicEntries: dynamicEntries.map(e => e.name) });
|
|
933
|
+
|
|
886
934
|
for (const entry of entries) {
|
|
887
935
|
if (entry.name.startsWith("[") && entry.name.includes("]")) {
|
|
936
|
+
debugLog(`Found dynamic segment: ${entry.name}`, { isDirectory: entry.isDirectory() });
|
|
888
937
|
for (const ext of extensions) {
|
|
889
938
|
if (entry.isDirectory()) {
|
|
890
939
|
// App Router or Pages Router with folder
|
|
891
940
|
const pagePath = path.join(parentPath, entry.name, `page${ext}`);
|
|
892
941
|
const indexPath = path.join(parentPath, entry.name, `index${ext}`);
|
|
942
|
+
debugLog(`Checking dynamic folder paths`, { pagePath, indexPath, pageExists: fs.existsSync(pagePath), indexExists: fs.existsSync(indexPath) });
|
|
893
943
|
if (fs.existsSync(pagePath)) {
|
|
894
|
-
|
|
944
|
+
const result = path.relative(projectRoot, pagePath);
|
|
945
|
+
debugLog(`Found dynamic route (folder/page)!`, { result });
|
|
946
|
+
return result;
|
|
895
947
|
}
|
|
896
948
|
if (fs.existsSync(indexPath)) {
|
|
897
|
-
|
|
949
|
+
const result = path.relative(projectRoot, indexPath);
|
|
950
|
+
debugLog(`Found dynamic route (folder/index)!`, { result });
|
|
951
|
+
return result;
|
|
898
952
|
}
|
|
899
953
|
} else if (entry.isFile() && entry.name.endsWith(ext)) {
|
|
900
954
|
// Pages Router file-based
|
|
901
|
-
|
|
955
|
+
const result = path.relative(projectRoot, path.join(parentPath, entry.name));
|
|
956
|
+
debugLog(`Found dynamic route (file)!`, { result });
|
|
957
|
+
return result;
|
|
902
958
|
}
|
|
903
959
|
}
|
|
904
960
|
}
|
|
905
961
|
}
|
|
906
|
-
} catch {
|
|
907
|
-
|
|
962
|
+
} catch (e) {
|
|
963
|
+
debugLog(`Error scanning directory: ${parentPath}`, { error: String(e) });
|
|
908
964
|
}
|
|
909
965
|
}
|
|
910
966
|
|
|
967
|
+
debugLog("findDynamicRoute: NO DYNAMIC ROUTE FOUND");
|
|
911
968
|
return null;
|
|
912
969
|
}
|
|
913
970
|
|
package/dist/index.js
CHANGED
|
@@ -1099,12 +1099,16 @@ function runDevToolsSync(fullSync = false) {
|
|
|
1099
1099
|
let sourceBrandContext;
|
|
1100
1100
|
let sourceApiAnalyze;
|
|
1101
1101
|
let sourceApiSaveColors;
|
|
1102
|
+
let sourceApiVisionApply;
|
|
1103
|
+
let sourceApiVisionEdit;
|
|
1102
1104
|
if (IS_BUNDLED) {
|
|
1103
1105
|
sourceDevTools = path.join(BUNDLED_ASSETS, "dev-tools");
|
|
1104
1106
|
sourceBrandSystem = path.join(BUNDLED_ASSETS, "brand-system.ts");
|
|
1105
1107
|
sourceBrandContext = path.join(BUNDLED_ASSETS, "brand-context.tsx");
|
|
1106
1108
|
sourceApiAnalyze = path.join(BUNDLED_ASSETS, "api/sonance-analyze/route.ts");
|
|
1107
1109
|
sourceApiSaveColors = path.join(BUNDLED_ASSETS, "api/sonance-save-colors/route.ts");
|
|
1110
|
+
sourceApiVisionApply = path.join(BUNDLED_ASSETS, "api/sonance-vision-apply/route.ts");
|
|
1111
|
+
sourceApiVisionEdit = path.join(BUNDLED_ASSETS, "api/sonance-vision-edit/route.ts");
|
|
1108
1112
|
}
|
|
1109
1113
|
else {
|
|
1110
1114
|
sourceDevTools = path.join(DEV_PROJECT_ROOT, "src/components/dev-tools");
|
|
@@ -1112,6 +1116,8 @@ function runDevToolsSync(fullSync = false) {
|
|
|
1112
1116
|
sourceBrandContext = path.join(DEV_PROJECT_ROOT, "src/lib/brand-context.tsx");
|
|
1113
1117
|
sourceApiAnalyze = path.join(DEV_PROJECT_ROOT, "src/app/api/sonance-analyze/route.ts");
|
|
1114
1118
|
sourceApiSaveColors = path.join(DEV_PROJECT_ROOT, "src/app/api/sonance-save-colors/route.ts");
|
|
1119
|
+
sourceApiVisionApply = path.join(DEV_PROJECT_ROOT, "src/app/api/sonance-vision-apply/route.ts");
|
|
1120
|
+
sourceApiVisionEdit = path.join(DEV_PROJECT_ROOT, "src/app/api/sonance-vision-edit/route.ts");
|
|
1115
1121
|
}
|
|
1116
1122
|
// Core files to sync (always synced)
|
|
1117
1123
|
const coreFiles = [
|
|
@@ -1164,7 +1170,33 @@ function runDevToolsSync(fullSync = false) {
|
|
|
1164
1170
|
}
|
|
1165
1171
|
}
|
|
1166
1172
|
}
|
|
1167
|
-
//
|
|
1173
|
+
// Always sync Vision API routes (critical for Vision Mode)
|
|
1174
|
+
const visionApiFiles = [
|
|
1175
|
+
{ src: sourceApiVisionApply, dest: path.join(targetDir, baseDir, "app/api/sonance-vision-apply/route.ts"), name: "sonance-vision-apply" },
|
|
1176
|
+
{ src: sourceApiVisionEdit, dest: path.join(targetDir, baseDir, "app/api/sonance-vision-edit/route.ts"), name: "sonance-vision-edit" },
|
|
1177
|
+
];
|
|
1178
|
+
for (const file of visionApiFiles) {
|
|
1179
|
+
if (fs.existsSync(file.src)) {
|
|
1180
|
+
try {
|
|
1181
|
+
// Ensure directory exists
|
|
1182
|
+
const destDir = path.dirname(file.dest);
|
|
1183
|
+
if (!fs.existsSync(destDir)) {
|
|
1184
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
1185
|
+
}
|
|
1186
|
+
fs.copyFileSync(file.src, file.dest);
|
|
1187
|
+
console.log(` ✓ Synced api/${file.name}/route.ts`);
|
|
1188
|
+
syncedCount++;
|
|
1189
|
+
}
|
|
1190
|
+
catch (err) {
|
|
1191
|
+
console.log(` ✗ Failed: api/${file.name}/route.ts`);
|
|
1192
|
+
errorCount++;
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
else {
|
|
1196
|
+
console.log(` ⚠️ Source not found: ${file.name} (run 'npm run build' in mcp-server)`);
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
// Full sync includes additional API routes
|
|
1168
1200
|
if (fullSync) {
|
|
1169
1201
|
const apiFiles = [
|
|
1170
1202
|
{ src: sourceApiAnalyze, dest: path.join(targetDir, baseDir, "app/api/sonance-analyze/route.ts"), name: "sonance-analyze" },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sonance-brand-mcp",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.29",
|
|
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",
|