sonance-brand-mcp 1.3.28 → 1.3.30

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.
@@ -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/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
- // Full sync includes API routes
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.28",
3
+ "version": "1.3.30",
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",