sonance-brand-mcp 1.3.89 → 1.3.90
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.
|
@@ -229,6 +229,139 @@ function findElementIdInFile(
|
|
|
229
229
|
return null;
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
+
/**
|
|
233
|
+
* Find the line number of a focused element in the source code
|
|
234
|
+
* Uses multiple strategies in priority order:
|
|
235
|
+
* 1. DOM id (highest confidence)
|
|
236
|
+
* 2. Text content
|
|
237
|
+
* 3. ClassName patterns
|
|
238
|
+
*
|
|
239
|
+
* This extends the basic ID matching to handle elements without IDs.
|
|
240
|
+
*/
|
|
241
|
+
function findElementLineInFile(
|
|
242
|
+
fileContent: string,
|
|
243
|
+
focusedElement: VisionFocusedElement
|
|
244
|
+
): { lineNumber: number; snippet: string; confidence: 'high' | 'medium' | 'low'; matchedBy: string } | null {
|
|
245
|
+
if (!fileContent) return null;
|
|
246
|
+
|
|
247
|
+
const lines = fileContent.split('\n');
|
|
248
|
+
|
|
249
|
+
// PRIORITY 1: DOM id - highest confidence (exact match)
|
|
250
|
+
if (focusedElement.elementId) {
|
|
251
|
+
const idPattern = new RegExp(`id=["'\`]${focusedElement.elementId}["'\`]`);
|
|
252
|
+
for (let i = 0; i < lines.length; i++) {
|
|
253
|
+
if (idPattern.test(lines[i])) {
|
|
254
|
+
return {
|
|
255
|
+
lineNumber: i + 1,
|
|
256
|
+
snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
|
|
257
|
+
confidence: 'high',
|
|
258
|
+
matchedBy: `DOM id="${focusedElement.elementId}"`
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Also try child IDs with high confidence
|
|
265
|
+
if (focusedElement.childIds && focusedElement.childIds.length > 0) {
|
|
266
|
+
for (const childId of focusedElement.childIds) {
|
|
267
|
+
const idPattern = new RegExp(`id=["'\`]${childId}["'\`]`);
|
|
268
|
+
for (let i = 0; i < lines.length; i++) {
|
|
269
|
+
if (idPattern.test(lines[i])) {
|
|
270
|
+
return {
|
|
271
|
+
lineNumber: i + 1,
|
|
272
|
+
snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
|
|
273
|
+
confidence: 'high',
|
|
274
|
+
matchedBy: `child id="${childId}"`
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// PRIORITY 2: Exact text content in JSX
|
|
282
|
+
if (focusedElement.textContent && focusedElement.textContent.trim().length >= 2) {
|
|
283
|
+
const text = focusedElement.textContent.trim();
|
|
284
|
+
// Escape special regex characters in the text
|
|
285
|
+
const escapedText = text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
286
|
+
|
|
287
|
+
for (let i = 0; i < lines.length; i++) {
|
|
288
|
+
const line = lines[i];
|
|
289
|
+
// Match patterns like: >Text<, >Text</tag, "Text", 'Text', {`Text`}
|
|
290
|
+
const textPatterns = [
|
|
291
|
+
`>${escapedText}<`, // JSX content: >Text<
|
|
292
|
+
`"${escapedText}"`, // String literal
|
|
293
|
+
`'${escapedText}'`, // String literal
|
|
294
|
+
`\`${escapedText}\``, // Template literal
|
|
295
|
+
];
|
|
296
|
+
|
|
297
|
+
for (const pattern of textPatterns) {
|
|
298
|
+
if (line.includes(pattern.replace(/\\/g, ''))) {
|
|
299
|
+
return {
|
|
300
|
+
lineNumber: i + 1,
|
|
301
|
+
snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
|
|
302
|
+
confidence: 'high',
|
|
303
|
+
matchedBy: `textContent="${text.substring(0, 30)}${text.length > 30 ? '...' : ''}"`
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Try partial match for longer text (first 15+ chars)
|
|
310
|
+
if (text.length > 15) {
|
|
311
|
+
const partialText = text.substring(0, 15);
|
|
312
|
+
for (let i = 0; i < lines.length; i++) {
|
|
313
|
+
if (lines[i].includes(`>${partialText}`) || lines[i].includes(`"${partialText}`)) {
|
|
314
|
+
return {
|
|
315
|
+
lineNumber: i + 1,
|
|
316
|
+
snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
|
|
317
|
+
confidence: 'medium',
|
|
318
|
+
matchedBy: `partial textContent starting with "${partialText}..."`
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// PRIORITY 3: Distinctive className patterns
|
|
326
|
+
if (focusedElement.className) {
|
|
327
|
+
// Extract distinctive class names (long, not hover/focus pseudo-classes)
|
|
328
|
+
const classes = focusedElement.className.split(/\s+/)
|
|
329
|
+
.filter(c => c.length > 8 && !c.startsWith('hover:') && !c.startsWith('focus:') && !c.startsWith('active:'));
|
|
330
|
+
|
|
331
|
+
for (const cls of classes) {
|
|
332
|
+
for (let i = 0; i < lines.length; i++) {
|
|
333
|
+
if (lines[i].includes(cls)) {
|
|
334
|
+
return {
|
|
335
|
+
lineNumber: i + 1,
|
|
336
|
+
snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
|
|
337
|
+
confidence: 'medium',
|
|
338
|
+
matchedBy: `className contains "${cls}"`
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Try shorter but unique-looking class names (not utility classes)
|
|
345
|
+
const uniqueClasses = focusedElement.className.split(/\s+/)
|
|
346
|
+
.filter(c => c.length > 4 && !c.match(/^(p[xytblr]?-|m[xytblr]?-|w-|h-|bg-|text-|flex|grid|block|hidden)/));
|
|
347
|
+
|
|
348
|
+
for (const cls of uniqueClasses) {
|
|
349
|
+
for (let i = 0; i < lines.length; i++) {
|
|
350
|
+
if (lines[i].includes(cls)) {
|
|
351
|
+
return {
|
|
352
|
+
lineNumber: i + 1,
|
|
353
|
+
snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
|
|
354
|
+
confidence: 'low',
|
|
355
|
+
matchedBy: `className contains "${cls}"`
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
|
|
232
365
|
/**
|
|
233
366
|
* PHASE 0: Deterministic Element ID Search (Cursor-style)
|
|
234
367
|
* Grep entire codebase for the element ID. If found in multiple files,
|
|
@@ -1330,12 +1463,21 @@ User Request: "${userPrompt}"
|
|
|
1330
1463
|
if (recommendedFileContent) {
|
|
1331
1464
|
const content = recommendedFileContent.content;
|
|
1332
1465
|
|
|
1333
|
-
// Search for element
|
|
1334
|
-
|
|
1335
|
-
|
|
1466
|
+
// Search for focused element in the file using multiple strategies
|
|
1467
|
+
// Priority: DOM id > textContent > className patterns
|
|
1468
|
+
let elementLocation: { lineNumber: number; snippet: string; confidence: 'high' | 'medium' | 'low'; matchedBy: string } | null = null;
|
|
1469
|
+
if (focusedElements && focusedElements.length > 0) {
|
|
1336
1470
|
for (const el of focusedElements) {
|
|
1337
|
-
|
|
1338
|
-
if (
|
|
1471
|
+
elementLocation = findElementLineInFile(content, el);
|
|
1472
|
+
if (elementLocation) {
|
|
1473
|
+
debugLog("Found focused element in file", {
|
|
1474
|
+
matchedBy: elementLocation.matchedBy,
|
|
1475
|
+
lineNumber: elementLocation.lineNumber,
|
|
1476
|
+
confidence: elementLocation.confidence,
|
|
1477
|
+
file: recommendedFileContent.path,
|
|
1478
|
+
});
|
|
1479
|
+
break;
|
|
1480
|
+
}
|
|
1339
1481
|
}
|
|
1340
1482
|
}
|
|
1341
1483
|
|
|
@@ -1350,22 +1492,36 @@ User Request: "${userPrompt}"
|
|
|
1350
1492
|
textContent += `\n`;
|
|
1351
1493
|
}
|
|
1352
1494
|
|
|
1353
|
-
// Add precise targeting
|
|
1354
|
-
if (
|
|
1495
|
+
// Add precise targeting with line number and snippet
|
|
1496
|
+
if (elementLocation) {
|
|
1355
1497
|
textContent += `
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
→
|
|
1498
|
+
══════════════════════════════════════════════════════════════════════════════
|
|
1499
|
+
PRECISE TARGET LOCATION (${elementLocation.confidence} confidence)
|
|
1500
|
+
══════════════════════════════════════════════════════════════════════════════
|
|
1501
|
+
→ Matched by: ${elementLocation.matchedBy}
|
|
1502
|
+
→ Line: ${elementLocation.lineNumber}
|
|
1503
|
+
|
|
1504
|
+
THE USER CLICKED ON THE ELEMENT AT LINE ${elementLocation.lineNumber}.
|
|
1505
|
+
Here is the exact code around that element:
|
|
1506
|
+
\`\`\`
|
|
1507
|
+
${elementLocation.snippet}
|
|
1508
|
+
\`\`\`
|
|
1509
|
+
|
|
1510
|
+
⚠️ IMPORTANT: Modify ONLY the element at line ${elementLocation.lineNumber}, NOT other similar elements in the file.
|
|
1360
1511
|
|
|
1361
1512
|
`;
|
|
1362
|
-
debugLog("Found element ID in file", {
|
|
1363
|
-
matchedId: idMatch.matchedId,
|
|
1364
|
-
lineNumber: idMatch.lineNumber,
|
|
1365
|
-
file: recommendedFileContent.path,
|
|
1366
|
-
});
|
|
1367
1513
|
} else {
|
|
1368
1514
|
textContent += `\n`;
|
|
1515
|
+
debugLog("Could not locate focused element in file - no ID, textContent, or className match", {
|
|
1516
|
+
file: recommendedFileContent.path,
|
|
1517
|
+
focusedElements: focusedElements.map(el => ({
|
|
1518
|
+
name: el.name,
|
|
1519
|
+
type: el.type,
|
|
1520
|
+
textContent: el.textContent?.substring(0, 30),
|
|
1521
|
+
className: el.className?.substring(0, 50),
|
|
1522
|
+
elementId: el.elementId,
|
|
1523
|
+
}))
|
|
1524
|
+
});
|
|
1369
1525
|
}
|
|
1370
1526
|
}
|
|
1371
1527
|
|
|
@@ -225,6 +225,139 @@ function findElementIdInFile(
|
|
|
225
225
|
return null;
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
+
/**
|
|
229
|
+
* Find the line number of a focused element in the source code
|
|
230
|
+
* Uses multiple strategies in priority order:
|
|
231
|
+
* 1. DOM id (highest confidence)
|
|
232
|
+
* 2. Text content
|
|
233
|
+
* 3. ClassName patterns
|
|
234
|
+
*
|
|
235
|
+
* This extends the basic ID matching to handle elements without IDs.
|
|
236
|
+
*/
|
|
237
|
+
function findElementLineInFile(
|
|
238
|
+
fileContent: string,
|
|
239
|
+
focusedElement: VisionFocusedElement
|
|
240
|
+
): { lineNumber: number; snippet: string; confidence: 'high' | 'medium' | 'low'; matchedBy: string } | null {
|
|
241
|
+
if (!fileContent) return null;
|
|
242
|
+
|
|
243
|
+
const lines = fileContent.split('\n');
|
|
244
|
+
|
|
245
|
+
// PRIORITY 1: DOM id - highest confidence (exact match)
|
|
246
|
+
if (focusedElement.elementId) {
|
|
247
|
+
const idPattern = new RegExp(`id=["'\`]${focusedElement.elementId}["'\`]`);
|
|
248
|
+
for (let i = 0; i < lines.length; i++) {
|
|
249
|
+
if (idPattern.test(lines[i])) {
|
|
250
|
+
return {
|
|
251
|
+
lineNumber: i + 1,
|
|
252
|
+
snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
|
|
253
|
+
confidence: 'high',
|
|
254
|
+
matchedBy: `DOM id="${focusedElement.elementId}"`
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Also try child IDs with high confidence
|
|
261
|
+
if (focusedElement.childIds && focusedElement.childIds.length > 0) {
|
|
262
|
+
for (const childId of focusedElement.childIds) {
|
|
263
|
+
const idPattern = new RegExp(`id=["'\`]${childId}["'\`]`);
|
|
264
|
+
for (let i = 0; i < lines.length; i++) {
|
|
265
|
+
if (idPattern.test(lines[i])) {
|
|
266
|
+
return {
|
|
267
|
+
lineNumber: i + 1,
|
|
268
|
+
snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
|
|
269
|
+
confidence: 'high',
|
|
270
|
+
matchedBy: `child id="${childId}"`
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// PRIORITY 2: Exact text content in JSX
|
|
278
|
+
if (focusedElement.textContent && focusedElement.textContent.trim().length >= 2) {
|
|
279
|
+
const text = focusedElement.textContent.trim();
|
|
280
|
+
// Escape special regex characters in the text
|
|
281
|
+
const escapedText = text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
282
|
+
|
|
283
|
+
for (let i = 0; i < lines.length; i++) {
|
|
284
|
+
const line = lines[i];
|
|
285
|
+
// Match patterns like: >Text<, >Text</tag, "Text", 'Text', {`Text`}
|
|
286
|
+
const textPatterns = [
|
|
287
|
+
`>${escapedText}<`, // JSX content: >Text<
|
|
288
|
+
`"${escapedText}"`, // String literal
|
|
289
|
+
`'${escapedText}'`, // String literal
|
|
290
|
+
`\`${escapedText}\``, // Template literal
|
|
291
|
+
];
|
|
292
|
+
|
|
293
|
+
for (const pattern of textPatterns) {
|
|
294
|
+
if (line.includes(pattern.replace(/\\/g, ''))) {
|
|
295
|
+
return {
|
|
296
|
+
lineNumber: i + 1,
|
|
297
|
+
snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
|
|
298
|
+
confidence: 'high',
|
|
299
|
+
matchedBy: `textContent="${text.substring(0, 30)}${text.length > 30 ? '...' : ''}"`
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Try partial match for longer text (first 15+ chars)
|
|
306
|
+
if (text.length > 15) {
|
|
307
|
+
const partialText = text.substring(0, 15);
|
|
308
|
+
for (let i = 0; i < lines.length; i++) {
|
|
309
|
+
if (lines[i].includes(`>${partialText}`) || lines[i].includes(`"${partialText}`)) {
|
|
310
|
+
return {
|
|
311
|
+
lineNumber: i + 1,
|
|
312
|
+
snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
|
|
313
|
+
confidence: 'medium',
|
|
314
|
+
matchedBy: `partial textContent starting with "${partialText}..."`
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// PRIORITY 3: Distinctive className patterns
|
|
322
|
+
if (focusedElement.className) {
|
|
323
|
+
// Extract distinctive class names (long, not hover/focus pseudo-classes)
|
|
324
|
+
const classes = focusedElement.className.split(/\s+/)
|
|
325
|
+
.filter(c => c.length > 8 && !c.startsWith('hover:') && !c.startsWith('focus:') && !c.startsWith('active:'));
|
|
326
|
+
|
|
327
|
+
for (const cls of classes) {
|
|
328
|
+
for (let i = 0; i < lines.length; i++) {
|
|
329
|
+
if (lines[i].includes(cls)) {
|
|
330
|
+
return {
|
|
331
|
+
lineNumber: i + 1,
|
|
332
|
+
snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
|
|
333
|
+
confidence: 'medium',
|
|
334
|
+
matchedBy: `className contains "${cls}"`
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Try shorter but unique-looking class names (not utility classes)
|
|
341
|
+
const uniqueClasses = focusedElement.className.split(/\s+/)
|
|
342
|
+
.filter(c => c.length > 4 && !c.match(/^(p[xytblr]?-|m[xytblr]?-|w-|h-|bg-|text-|flex|grid|block|hidden)/));
|
|
343
|
+
|
|
344
|
+
for (const cls of uniqueClasses) {
|
|
345
|
+
for (let i = 0; i < lines.length; i++) {
|
|
346
|
+
if (lines[i].includes(cls)) {
|
|
347
|
+
return {
|
|
348
|
+
lineNumber: i + 1,
|
|
349
|
+
snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
|
|
350
|
+
confidence: 'low',
|
|
351
|
+
matchedBy: `className contains "${cls}"`
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
|
|
228
361
|
/**
|
|
229
362
|
* PHASE 0: Deterministic Element ID Search (Cursor-style)
|
|
230
363
|
* Grep entire codebase for the element ID. If found in multiple files,
|
|
@@ -1299,12 +1432,21 @@ User Request: "${userPrompt}"
|
|
|
1299
1432
|
if (recommendedFileContent) {
|
|
1300
1433
|
const content = recommendedFileContent.content;
|
|
1301
1434
|
|
|
1302
|
-
// Search for element
|
|
1303
|
-
|
|
1304
|
-
|
|
1435
|
+
// Search for focused element in the file using multiple strategies
|
|
1436
|
+
// Priority: DOM id > textContent > className patterns
|
|
1437
|
+
let elementLocation: { lineNumber: number; snippet: string; confidence: 'high' | 'medium' | 'low'; matchedBy: string } | null = null;
|
|
1438
|
+
if (focusedElements && focusedElements.length > 0) {
|
|
1305
1439
|
for (const el of focusedElements) {
|
|
1306
|
-
|
|
1307
|
-
if (
|
|
1440
|
+
elementLocation = findElementLineInFile(content, el);
|
|
1441
|
+
if (elementLocation) {
|
|
1442
|
+
debugLog("Found focused element in file", {
|
|
1443
|
+
matchedBy: elementLocation.matchedBy,
|
|
1444
|
+
lineNumber: elementLocation.lineNumber,
|
|
1445
|
+
confidence: elementLocation.confidence,
|
|
1446
|
+
file: recommendedFileContent.path,
|
|
1447
|
+
});
|
|
1448
|
+
break;
|
|
1449
|
+
}
|
|
1308
1450
|
}
|
|
1309
1451
|
}
|
|
1310
1452
|
|
|
@@ -1319,22 +1461,36 @@ User Request: "${userPrompt}"
|
|
|
1319
1461
|
textContent += `\n`;
|
|
1320
1462
|
}
|
|
1321
1463
|
|
|
1322
|
-
// Add precise targeting
|
|
1323
|
-
if (
|
|
1464
|
+
// Add precise targeting with line number and snippet
|
|
1465
|
+
if (elementLocation) {
|
|
1324
1466
|
textContent += `
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
→
|
|
1467
|
+
══════════════════════════════════════════════════════════════════════════════
|
|
1468
|
+
PRECISE TARGET LOCATION (${elementLocation.confidence} confidence)
|
|
1469
|
+
══════════════════════════════════════════════════════════════════════════════
|
|
1470
|
+
→ Matched by: ${elementLocation.matchedBy}
|
|
1471
|
+
→ Line: ${elementLocation.lineNumber}
|
|
1472
|
+
|
|
1473
|
+
THE USER CLICKED ON THE ELEMENT AT LINE ${elementLocation.lineNumber}.
|
|
1474
|
+
Here is the exact code around that element:
|
|
1475
|
+
\`\`\`
|
|
1476
|
+
${elementLocation.snippet}
|
|
1477
|
+
\`\`\`
|
|
1478
|
+
|
|
1479
|
+
⚠️ IMPORTANT: Modify ONLY the element at line ${elementLocation.lineNumber}, NOT other similar elements in the file.
|
|
1329
1480
|
|
|
1330
1481
|
`;
|
|
1331
|
-
debugLog("Found element ID in file", {
|
|
1332
|
-
matchedId: idMatch.matchedId,
|
|
1333
|
-
lineNumber: idMatch.lineNumber,
|
|
1334
|
-
file: recommendedFileContent.path,
|
|
1335
|
-
});
|
|
1336
1482
|
} else {
|
|
1337
1483
|
textContent += `\n`;
|
|
1484
|
+
debugLog("Could not locate focused element in file - no ID, textContent, or className match", {
|
|
1485
|
+
file: recommendedFileContent.path,
|
|
1486
|
+
focusedElements: focusedElements.map(el => ({
|
|
1487
|
+
name: el.name,
|
|
1488
|
+
type: el.type,
|
|
1489
|
+
textContent: el.textContent?.substring(0, 30),
|
|
1490
|
+
className: el.className?.substring(0, 50),
|
|
1491
|
+
elementId: el.elementId,
|
|
1492
|
+
}))
|
|
1493
|
+
});
|
|
1338
1494
|
}
|
|
1339
1495
|
}
|
|
1340
1496
|
|
|
@@ -1215,10 +1215,11 @@ export function SonanceDevTools() {
|
|
|
1215
1215
|
console.warn("[Apply-First] Failed to persist session:", e);
|
|
1216
1216
|
}
|
|
1217
1217
|
|
|
1218
|
-
//
|
|
1218
|
+
// Force page refresh to ensure changes are visible
|
|
1219
|
+
// Session is already persisted to localStorage, so it survives refresh
|
|
1219
1220
|
setTimeout(() => {
|
|
1220
|
-
|
|
1221
|
-
},
|
|
1221
|
+
window.location.reload();
|
|
1222
|
+
}, 500);
|
|
1222
1223
|
}, [visionFocusedElements]);
|
|
1223
1224
|
|
|
1224
1225
|
// Accept changes - delete backups
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sonance-brand-mcp",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.90",
|
|
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",
|