sonance-brand-mcp 1.3.29 → 1.3.31
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.
|
@@ -746,17 +746,23 @@ function gatherAllImports(
|
|
|
746
746
|
maxDepth: number = 4
|
|
747
747
|
): { path: string; content: string }[] {
|
|
748
748
|
// Prevent infinite loops and limit total files
|
|
749
|
-
if (visited.has(filePath) || visited.size > 50)
|
|
749
|
+
if (visited.has(filePath) || visited.size > 50) {
|
|
750
|
+
return [];
|
|
751
|
+
}
|
|
750
752
|
visited.add(filePath);
|
|
751
753
|
|
|
752
754
|
const results: { path: string; content: string }[] = [];
|
|
753
755
|
const fullPath = path.join(projectRoot, filePath);
|
|
754
756
|
|
|
755
|
-
if (!fs.existsSync(fullPath))
|
|
757
|
+
if (!fs.existsSync(fullPath)) {
|
|
758
|
+
debugLog("[apply] gatherAllImports: file not found", { filePath, fullPath });
|
|
759
|
+
return results;
|
|
760
|
+
}
|
|
756
761
|
|
|
757
762
|
try {
|
|
758
763
|
const content = fs.readFileSync(fullPath, "utf-8");
|
|
759
764
|
results.push({ path: filePath, content });
|
|
765
|
+
debugLog("[apply] gatherAllImports: added file", { filePath, contentLength: content.length });
|
|
760
766
|
|
|
761
767
|
// Continue recursing if we haven't hit max depth
|
|
762
768
|
if (maxDepth > 0) {
|
|
@@ -769,8 +775,8 @@ function gatherAllImports(
|
|
|
769
775
|
}
|
|
770
776
|
}
|
|
771
777
|
}
|
|
772
|
-
} catch {
|
|
773
|
-
|
|
778
|
+
} catch (e) {
|
|
779
|
+
debugLog("[apply] gatherAllImports: error reading file", { filePath, error: String(e) });
|
|
774
780
|
}
|
|
775
781
|
|
|
776
782
|
return results;
|
|
@@ -1081,7 +1087,8 @@ function findDynamicRoute(cleanRoute: string, projectRoot: string): string | nul
|
|
|
1081
1087
|
}
|
|
1082
1088
|
|
|
1083
1089
|
function extractImports(content: string): string[] {
|
|
1084
|
-
|
|
1090
|
+
// Match ALL @/ imports (not just @/components) and relative imports
|
|
1091
|
+
const importRegex = /import\s+.*?\s+from\s+["'](@\/[^"']+|\.\.?\/[^"']+)["']/g;
|
|
1085
1092
|
const imports: string[] = [];
|
|
1086
1093
|
let match;
|
|
1087
1094
|
|
|
@@ -1089,32 +1096,134 @@ function extractImports(content: string): string[] {
|
|
|
1089
1096
|
imports.push(match[1]);
|
|
1090
1097
|
}
|
|
1091
1098
|
|
|
1099
|
+
debugLog("[apply] Extracted imports", { count: imports.length, imports: imports.slice(0, 10) });
|
|
1092
1100
|
return imports;
|
|
1093
1101
|
}
|
|
1094
1102
|
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
+
// Cache for tsconfig path aliases
|
|
1104
|
+
let cachedPathAliases: Map<string, string> | null = null;
|
|
1105
|
+
let cachedProjectRoot: string | null = null;
|
|
1106
|
+
|
|
1107
|
+
/**
|
|
1108
|
+
* Read and parse tsconfig.json to get path aliases
|
|
1109
|
+
*/
|
|
1110
|
+
function getPathAliases(projectRoot: string): Map<string, string> {
|
|
1111
|
+
// Return cached if same project
|
|
1112
|
+
if (cachedPathAliases && cachedProjectRoot === projectRoot) {
|
|
1113
|
+
return cachedPathAliases;
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
const aliases = new Map<string, string>();
|
|
1117
|
+
|
|
1118
|
+
// Try to read tsconfig.json
|
|
1119
|
+
const tsconfigPath = path.join(projectRoot, "tsconfig.json");
|
|
1120
|
+
if (fs.existsSync(tsconfigPath)) {
|
|
1121
|
+
try {
|
|
1122
|
+
const content = fs.readFileSync(tsconfigPath, "utf-8");
|
|
1123
|
+
// Remove comments (tsconfig allows them)
|
|
1124
|
+
const cleanContent = content.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
1125
|
+
const tsconfig = JSON.parse(cleanContent);
|
|
1126
|
+
|
|
1127
|
+
const paths = tsconfig.compilerOptions?.paths || {};
|
|
1128
|
+
const baseUrl = tsconfig.compilerOptions?.baseUrl || ".";
|
|
1129
|
+
|
|
1130
|
+
// Parse path mappings
|
|
1131
|
+
for (const [alias, targets] of Object.entries(paths)) {
|
|
1132
|
+
if (Array.isArray(targets) && targets.length > 0) {
|
|
1133
|
+
// Convert @/* to @/ and src/* to src/
|
|
1134
|
+
const cleanAlias = alias.replace("/*", "/");
|
|
1135
|
+
const cleanTarget = (targets[0] as string).replace("/*", "/").replace("./", "");
|
|
1136
|
+
aliases.set(cleanAlias, cleanTarget);
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
debugLog("[apply] Loaded tsconfig path aliases", { aliases: Object.fromEntries(aliases) });
|
|
1141
|
+
} catch (e) {
|
|
1142
|
+
debugLog("[apply] Failed to parse tsconfig.json", { error: String(e) });
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
// If no @/ alias found, try common defaults
|
|
1147
|
+
if (!aliases.has("@/")) {
|
|
1148
|
+
// Check if src/ exists
|
|
1149
|
+
if (fs.existsSync(path.join(projectRoot, "src"))) {
|
|
1150
|
+
aliases.set("@/", "src/");
|
|
1151
|
+
} else if (fs.existsSync(path.join(projectRoot, "app"))) {
|
|
1152
|
+
// Next.js App Router without src/
|
|
1153
|
+
aliases.set("@/", "");
|
|
1154
|
+
} else {
|
|
1155
|
+
aliases.set("@/", "");
|
|
1156
|
+
}
|
|
1157
|
+
debugLog("[apply] Using default @/ alias", { alias: aliases.get("@/") });
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
cachedPathAliases = aliases;
|
|
1161
|
+
cachedProjectRoot = projectRoot;
|
|
1162
|
+
return aliases;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
/**
|
|
1166
|
+
* Try multiple file extensions for an import
|
|
1167
|
+
*/
|
|
1168
|
+
function tryFileExtensions(basePath: string, projectRoot: string): string | null {
|
|
1169
|
+
const extensions = [".tsx", ".ts", ".jsx", ".js"];
|
|
1170
|
+
|
|
1171
|
+
// First try exact path (if already has extension)
|
|
1172
|
+
if (extensions.some(ext => basePath.endsWith(ext))) {
|
|
1173
|
+
if (fs.existsSync(path.join(projectRoot, basePath))) {
|
|
1174
|
+
return basePath;
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
// Try each extension
|
|
1179
|
+
for (const ext of extensions) {
|
|
1180
|
+
const withExt = `${basePath}${ext}`;
|
|
1103
1181
|
if (fs.existsSync(path.join(projectRoot, withExt))) {
|
|
1104
1182
|
return withExt;
|
|
1105
1183
|
}
|
|
1106
|
-
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
// Try as directory with index file
|
|
1187
|
+
for (const ext of extensions) {
|
|
1188
|
+
const indexPath = `${basePath}/index${ext}`;
|
|
1107
1189
|
if (fs.existsSync(path.join(projectRoot, indexPath))) {
|
|
1108
1190
|
return indexPath;
|
|
1109
1191
|
}
|
|
1110
|
-
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
return null;
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
function resolveImportPath(
|
|
1198
|
+
importPath: string,
|
|
1199
|
+
fromFile: string,
|
|
1200
|
+
projectRoot: string
|
|
1201
|
+
): string | null {
|
|
1202
|
+
const aliases = getPathAliases(projectRoot);
|
|
1203
|
+
|
|
1204
|
+
// Handle aliased imports (e.g., @/, ~/, etc.)
|
|
1205
|
+
for (const [alias, target] of aliases) {
|
|
1206
|
+
if (importPath.startsWith(alias)) {
|
|
1207
|
+
const resolved = importPath.replace(alias, target);
|
|
1208
|
+
const result = tryFileExtensions(resolved, projectRoot);
|
|
1209
|
+
if (result) {
|
|
1210
|
+
debugLog("[apply] Resolved alias import", { importPath, resolved: result });
|
|
1211
|
+
return result;
|
|
1212
|
+
}
|
|
1213
|
+
// Return best guess even if file not found
|
|
1214
|
+
return `${resolved}.tsx`;
|
|
1215
|
+
}
|
|
1111
1216
|
}
|
|
1112
1217
|
|
|
1218
|
+
// Handle relative imports
|
|
1113
1219
|
if (importPath.startsWith(".")) {
|
|
1114
1220
|
const dir = path.dirname(fromFile);
|
|
1115
1221
|
const resolved = path.join(dir, importPath);
|
|
1116
|
-
const
|
|
1117
|
-
|
|
1222
|
+
const result = tryFileExtensions(resolved, projectRoot);
|
|
1223
|
+
if (result) {
|
|
1224
|
+
return result;
|
|
1225
|
+
}
|
|
1226
|
+
return `${resolved}.tsx`;
|
|
1118
1227
|
}
|
|
1119
1228
|
|
|
1120
1229
|
return null;
|
|
@@ -614,17 +614,23 @@ function gatherAllImports(
|
|
|
614
614
|
maxDepth: number = 4
|
|
615
615
|
): { path: string; content: string }[] {
|
|
616
616
|
// Prevent infinite loops and limit total files
|
|
617
|
-
if (visited.has(filePath) || visited.size > 50)
|
|
617
|
+
if (visited.has(filePath) || visited.size > 50) {
|
|
618
|
+
return [];
|
|
619
|
+
}
|
|
618
620
|
visited.add(filePath);
|
|
619
621
|
|
|
620
622
|
const results: { path: string; content: string }[] = [];
|
|
621
623
|
const fullPath = path.join(projectRoot, filePath);
|
|
622
624
|
|
|
623
|
-
if (!fs.existsSync(fullPath))
|
|
625
|
+
if (!fs.existsSync(fullPath)) {
|
|
626
|
+
debugLog("[edit] gatherAllImports: file not found", { filePath, fullPath });
|
|
627
|
+
return results;
|
|
628
|
+
}
|
|
624
629
|
|
|
625
630
|
try {
|
|
626
631
|
const content = fs.readFileSync(fullPath, "utf-8");
|
|
627
632
|
results.push({ path: filePath, content });
|
|
633
|
+
debugLog("[edit] gatherAllImports: added file", { filePath, contentLength: content.length });
|
|
628
634
|
|
|
629
635
|
// Continue recursing if we haven't hit max depth
|
|
630
636
|
if (maxDepth > 0) {
|
|
@@ -637,8 +643,8 @@ function gatherAllImports(
|
|
|
637
643
|
}
|
|
638
644
|
}
|
|
639
645
|
}
|
|
640
|
-
} catch {
|
|
641
|
-
|
|
646
|
+
} catch (e) {
|
|
647
|
+
debugLog("[edit] gatherAllImports: error reading file", { filePath, error: String(e) });
|
|
642
648
|
}
|
|
643
649
|
|
|
644
650
|
return results;
|
|
@@ -972,7 +978,8 @@ function findDynamicRoute(cleanRoute: string, projectRoot: string): string | nul
|
|
|
972
978
|
* Extract import paths from file content
|
|
973
979
|
*/
|
|
974
980
|
function extractImports(content: string): string[] {
|
|
975
|
-
|
|
981
|
+
// Match ALL @/ imports (not just @/components) and relative imports
|
|
982
|
+
const importRegex = /import\s+.*?\s+from\s+["'](@\/[^"']+|\.\.?\/[^"']+)["']/g;
|
|
976
983
|
const imports: string[] = [];
|
|
977
984
|
let match;
|
|
978
985
|
|
|
@@ -980,9 +987,104 @@ function extractImports(content: string): string[] {
|
|
|
980
987
|
imports.push(match[1]);
|
|
981
988
|
}
|
|
982
989
|
|
|
990
|
+
debugLog("[edit] Extracted imports", { count: imports.length, imports: imports.slice(0, 10) });
|
|
983
991
|
return imports;
|
|
984
992
|
}
|
|
985
993
|
|
|
994
|
+
// Cache for tsconfig path aliases
|
|
995
|
+
let cachedPathAliases: Map<string, string> | null = null;
|
|
996
|
+
let cachedProjectRoot: string | null = null;
|
|
997
|
+
|
|
998
|
+
/**
|
|
999
|
+
* Read and parse tsconfig.json to get path aliases
|
|
1000
|
+
*/
|
|
1001
|
+
function getPathAliases(projectRoot: string): Map<string, string> {
|
|
1002
|
+
// Return cached if same project
|
|
1003
|
+
if (cachedPathAliases && cachedProjectRoot === projectRoot) {
|
|
1004
|
+
return cachedPathAliases;
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
const aliases = new Map<string, string>();
|
|
1008
|
+
|
|
1009
|
+
// Try to read tsconfig.json
|
|
1010
|
+
const tsconfigPath = path.join(projectRoot, "tsconfig.json");
|
|
1011
|
+
if (fs.existsSync(tsconfigPath)) {
|
|
1012
|
+
try {
|
|
1013
|
+
const content = fs.readFileSync(tsconfigPath, "utf-8");
|
|
1014
|
+
// Remove comments (tsconfig allows them)
|
|
1015
|
+
const cleanContent = content.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
1016
|
+
const tsconfig = JSON.parse(cleanContent);
|
|
1017
|
+
|
|
1018
|
+
const paths = tsconfig.compilerOptions?.paths || {};
|
|
1019
|
+
const baseUrl = tsconfig.compilerOptions?.baseUrl || ".";
|
|
1020
|
+
|
|
1021
|
+
// Parse path mappings
|
|
1022
|
+
for (const [alias, targets] of Object.entries(paths)) {
|
|
1023
|
+
if (Array.isArray(targets) && targets.length > 0) {
|
|
1024
|
+
// Convert @/* to @/ and src/* to src/
|
|
1025
|
+
const cleanAlias = alias.replace("/*", "/");
|
|
1026
|
+
const cleanTarget = (targets[0] as string).replace("/*", "/").replace("./", "");
|
|
1027
|
+
aliases.set(cleanAlias, cleanTarget);
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
debugLog("[edit] Loaded tsconfig path aliases", { aliases: Object.fromEntries(aliases) });
|
|
1032
|
+
} catch (e) {
|
|
1033
|
+
debugLog("[edit] Failed to parse tsconfig.json", { error: String(e) });
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
// If no @/ alias found, try common defaults
|
|
1038
|
+
if (!aliases.has("@/")) {
|
|
1039
|
+
// Check if src/ exists
|
|
1040
|
+
if (fs.existsSync(path.join(projectRoot, "src"))) {
|
|
1041
|
+
aliases.set("@/", "src/");
|
|
1042
|
+
} else if (fs.existsSync(path.join(projectRoot, "app"))) {
|
|
1043
|
+
// Next.js App Router without src/
|
|
1044
|
+
aliases.set("@/", "");
|
|
1045
|
+
} else {
|
|
1046
|
+
aliases.set("@/", "");
|
|
1047
|
+
}
|
|
1048
|
+
debugLog("[edit] Using default @/ alias", { alias: aliases.get("@/") });
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
cachedPathAliases = aliases;
|
|
1052
|
+
cachedProjectRoot = projectRoot;
|
|
1053
|
+
return aliases;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
/**
|
|
1057
|
+
* Try multiple file extensions for an import
|
|
1058
|
+
*/
|
|
1059
|
+
function tryFileExtensions(basePath: string, projectRoot: string): string | null {
|
|
1060
|
+
const extensions = [".tsx", ".ts", ".jsx", ".js"];
|
|
1061
|
+
|
|
1062
|
+
// First try exact path (if already has extension)
|
|
1063
|
+
if (extensions.some(ext => basePath.endsWith(ext))) {
|
|
1064
|
+
if (fs.existsSync(path.join(projectRoot, basePath))) {
|
|
1065
|
+
return basePath;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
// Try each extension
|
|
1070
|
+
for (const ext of extensions) {
|
|
1071
|
+
const withExt = `${basePath}${ext}`;
|
|
1072
|
+
if (fs.existsSync(path.join(projectRoot, withExt))) {
|
|
1073
|
+
return withExt;
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
// Try as directory with index file
|
|
1078
|
+
for (const ext of extensions) {
|
|
1079
|
+
const indexPath = `${basePath}/index${ext}`;
|
|
1080
|
+
if (fs.existsSync(path.join(projectRoot, indexPath))) {
|
|
1081
|
+
return indexPath;
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
return null;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
986
1088
|
/**
|
|
987
1089
|
* Resolve an import path to a file system path
|
|
988
1090
|
*/
|
|
@@ -991,28 +1093,31 @@ function resolveImportPath(
|
|
|
991
1093
|
fromFile: string,
|
|
992
1094
|
projectRoot: string
|
|
993
1095
|
): string | null {
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1096
|
+
const aliases = getPathAliases(projectRoot);
|
|
1097
|
+
|
|
1098
|
+
// Handle aliased imports (e.g., @/, ~/, etc.)
|
|
1099
|
+
for (const [alias, target] of aliases) {
|
|
1100
|
+
if (importPath.startsWith(alias)) {
|
|
1101
|
+
const resolved = importPath.replace(alias, target);
|
|
1102
|
+
const result = tryFileExtensions(resolved, projectRoot);
|
|
1103
|
+
if (result) {
|
|
1104
|
+
debugLog("[edit] Resolved alias import", { importPath, resolved: result });
|
|
1105
|
+
return result;
|
|
1106
|
+
}
|
|
1107
|
+
// Return best guess even if file not found
|
|
1108
|
+
return `${resolved}.tsx`;
|
|
1006
1109
|
}
|
|
1007
|
-
return withExt; // Return even if not found for context
|
|
1008
1110
|
}
|
|
1009
1111
|
|
|
1010
1112
|
// Handle relative imports
|
|
1011
1113
|
if (importPath.startsWith(".")) {
|
|
1012
1114
|
const dir = path.dirname(fromFile);
|
|
1013
1115
|
const resolved = path.join(dir, importPath);
|
|
1014
|
-
const
|
|
1015
|
-
|
|
1116
|
+
const result = tryFileExtensions(resolved, projectRoot);
|
|
1117
|
+
if (result) {
|
|
1118
|
+
return result;
|
|
1119
|
+
}
|
|
1120
|
+
return `${resolved}.tsx`;
|
|
1016
1121
|
}
|
|
1017
1122
|
|
|
1018
1123
|
return null;
|
|
@@ -260,6 +260,35 @@ export function SonanceDevTools() {
|
|
|
260
260
|
}
|
|
261
261
|
}, [mounted, DEVTOOLS_POSITION_KEY]);
|
|
262
262
|
|
|
263
|
+
// Restore apply-first session from localStorage on mount
|
|
264
|
+
// This allows the Accept/Revert UI to survive page refreshes
|
|
265
|
+
useEffect(() => {
|
|
266
|
+
if (!mounted) return;
|
|
267
|
+
try {
|
|
268
|
+
const savedSession = localStorage.getItem("sonance-apply-first-session");
|
|
269
|
+
if (savedSession) {
|
|
270
|
+
const session = JSON.parse(savedSession);
|
|
271
|
+
// Check if session is recent (< 1 hour old)
|
|
272
|
+
const MAX_SESSION_AGE = 60 * 60 * 1000; // 1 hour
|
|
273
|
+
if (session.timestamp && Date.now() - session.timestamp < MAX_SESSION_AGE) {
|
|
274
|
+
console.log("[Apply-First] Restoring session from localStorage:", session.sessionId);
|
|
275
|
+
setApplyFirstSession(session);
|
|
276
|
+
setApplyFirstStatus("reviewing");
|
|
277
|
+
// Auto-open the DevTools panel so user sees the Accept/Revert UI
|
|
278
|
+
setIsOpen(true);
|
|
279
|
+
setActiveTab("components");
|
|
280
|
+
} else {
|
|
281
|
+
// Session expired, clear it
|
|
282
|
+
console.log("[Apply-First] Session expired, clearing localStorage");
|
|
283
|
+
localStorage.removeItem("sonance-apply-first-session");
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
} catch (e) {
|
|
287
|
+
console.warn("[Apply-First] Failed to restore session:", e);
|
|
288
|
+
localStorage.removeItem("sonance-apply-first-session");
|
|
289
|
+
}
|
|
290
|
+
}, [mounted]);
|
|
291
|
+
|
|
263
292
|
// Drag handlers for movable panel
|
|
264
293
|
const headerRef = useRef<HTMLDivElement>(null);
|
|
265
294
|
|
|
@@ -1097,6 +1126,17 @@ export function SonanceDevTools() {
|
|
|
1097
1126
|
setApplyFirstStatus("waiting-hmr");
|
|
1098
1127
|
setVisionModeActive(false);
|
|
1099
1128
|
|
|
1129
|
+
// Persist session to localStorage so it survives page refreshes
|
|
1130
|
+
try {
|
|
1131
|
+
localStorage.setItem("sonance-apply-first-session", JSON.stringify({
|
|
1132
|
+
...session,
|
|
1133
|
+
timestamp: Date.now(),
|
|
1134
|
+
}));
|
|
1135
|
+
console.log("[Apply-First] Session persisted to localStorage");
|
|
1136
|
+
} catch (e) {
|
|
1137
|
+
console.warn("[Apply-First] Failed to persist session:", e);
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1100
1140
|
// After a brief delay, assume HMR has completed
|
|
1101
1141
|
setTimeout(() => {
|
|
1102
1142
|
setApplyFirstStatus("reviewing");
|
|
@@ -1128,6 +1168,13 @@ export function SonanceDevTools() {
|
|
|
1128
1168
|
setApplyFirstStatus("idle");
|
|
1129
1169
|
setVisionFocusedElements([]);
|
|
1130
1170
|
setChangedElements([]); // Clear highlights
|
|
1171
|
+
// Clear persisted session from localStorage
|
|
1172
|
+
try {
|
|
1173
|
+
localStorage.removeItem("sonance-apply-first-session");
|
|
1174
|
+
console.log("[Apply-First] Session cleared from localStorage");
|
|
1175
|
+
} catch (e) {
|
|
1176
|
+
console.warn("[Apply-First] Failed to clear session:", e);
|
|
1177
|
+
}
|
|
1131
1178
|
} else {
|
|
1132
1179
|
console.error("[Apply-First] Accept failed:", result.error);
|
|
1133
1180
|
setApplyFirstStatus("error");
|
|
@@ -1164,6 +1211,13 @@ export function SonanceDevTools() {
|
|
|
1164
1211
|
setVisionFocusedElements([]);
|
|
1165
1212
|
setChangedElements([]); // Clear highlights
|
|
1166
1213
|
// HMR will automatically refresh with restored files
|
|
1214
|
+
// Clear persisted session from localStorage
|
|
1215
|
+
try {
|
|
1216
|
+
localStorage.removeItem("sonance-apply-first-session");
|
|
1217
|
+
console.log("[Apply-First] Session cleared from localStorage");
|
|
1218
|
+
} catch (e) {
|
|
1219
|
+
console.warn("[Apply-First] Failed to clear session:", e);
|
|
1220
|
+
}
|
|
1167
1221
|
} else {
|
|
1168
1222
|
console.error("[Apply-First] Revert failed:", result.error);
|
|
1169
1223
|
setApplyFirstStatus("error");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sonance-brand-mcp",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.31",
|
|
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",
|