sonance-brand-mcp 1.3.48 → 1.3.49

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.
@@ -545,6 +545,7 @@ export async function POST(request: Request) {
545
545
  return NextResponse.json({
546
546
  success: result.success,
547
547
  message: result.message,
548
+ error: result.success ? undefined : result.message, // Include error for client compatibility
548
549
  filesReverted: result.filesReverted,
549
550
  });
550
551
  }
@@ -846,6 +847,14 @@ CRITICAL: Edit the TARGET COMPONENT (marked with ***), not the page wrapper.`;
846
847
  // If this is a retry, add feedback about what went wrong
847
848
  if (retryCount > 0 && lastPatchErrors.length > 0) {
848
849
  debugLog("Retry attempt with feedback", { retryCount, errorCount: lastPatchErrors.length });
850
+
851
+ // Get a snippet of the actual file content to help AI find correct code
852
+ let fileSnippet = "";
853
+ if (recommendedFileContent) {
854
+ // Show first 800 chars to give AI context about what code actually exists
855
+ fileSnippet = recommendedFileContent.content.substring(0, 800).replace(/\n/g, "\n");
856
+ }
857
+
849
858
  currentMessages.push({
850
859
  role: "assistant",
851
860
  content: "I'll analyze the screenshot and generate the patches now.",
@@ -857,10 +866,20 @@ CRITICAL: Edit the TARGET COMPONENT (marked with ***), not the page wrapper.`;
857
866
  Failed patches:
858
867
  ${lastPatchErrors.join("\n\n")}
859
868
 
860
- IMPORTANT: You must copy the "search" string EXACTLY from the file content I provided. Do NOT invent or guess code.
861
- Look carefully at the ACTUAL file content in the TARGET COMPONENT section above and try again.
869
+ ${fileSnippet ? `Here is the ACTUAL beginning of the file you're trying to edit:
870
+ \`\`\`tsx
871
+ ${fileSnippet}...
872
+ \`\`\`
873
+ ` : ""}
874
+ CRITICAL INSTRUCTIONS:
875
+ 1. Your "search" string MUST be copied EXACTLY from the file content I provided above
876
+ 2. Do NOT invent, guess, or imagine code that might exist
877
+ 3. Look for the ACTUAL code in the TARGET COMPONENT section and copy it exactly
862
878
 
863
- If you cannot find the exact code to modify, return an empty modifications array with an explanation.`,
879
+ If you still cannot find the exact code to modify after reviewing the file:
880
+ - Return {"modifications": [], "explanation": "Could not locate the exact code. Please specify which element you want to change more precisely."}
881
+
882
+ This is better than generating patches with made-up code.`,
864
883
  });
865
884
  }
866
885
 
@@ -1849,6 +1868,7 @@ function searchFilesForKeywords(
1849
1868
  let cachedPathAliases: Map<string, string> | null = null;
1850
1869
  let cachedProjectRoot: string | null = null;
1851
1870
  let cachedTsconfigMtime: number | null = null;
1871
+ let cachedParseError: string | null = null; // Cache parse errors to avoid log spam
1852
1872
 
1853
1873
  /**
1854
1874
  * Clean tsconfig.json content to make it valid JSON
@@ -1921,21 +1941,23 @@ function getPathAliases(projectRoot: string): Map<string, string> {
1921
1941
  cachedTsconfigMtime = null;
1922
1942
  }
1923
1943
  } catch (e) {
1924
- // Log the error with more context for debugging
1925
1944
  const errorStr = String(e);
1926
- const posMatch = errorStr.match(/position (\d+)/);
1927
- let context = "";
1928
- if (posMatch) {
1929
- const pos = parseInt(posMatch[1], 10);
1930
- const content = fs.readFileSync(tsconfigPath, "utf-8");
1931
- context = `Near: "${content.substring(Math.max(0, pos - 20), pos + 20)}"`;
1945
+
1946
+ // Only log parse error once to avoid log spam
1947
+ if (!cachedParseError) {
1948
+ const posMatch = errorStr.match(/position (\d+)/);
1949
+ let context = "";
1950
+ if (posMatch) {
1951
+ const pos = parseInt(posMatch[1], 10);
1952
+ const content = fs.readFileSync(tsconfigPath, "utf-8");
1953
+ context = `Near: "${content.substring(Math.max(0, pos - 20), pos + 20)}"`;
1954
+ }
1955
+ debugLog("[apply] Failed to parse tsconfig.json (will use defaults, logging once)", { error: errorStr, context });
1956
+ cachedParseError = errorStr;
1932
1957
  }
1933
- debugLog("[apply] Failed to parse tsconfig.json", { error: errorStr, context });
1934
1958
 
1935
- // Clear cache on error so we retry next time
1936
- cachedPathAliases = null;
1937
- cachedProjectRoot = null;
1938
- cachedTsconfigMtime = null;
1959
+ // Don't clear cache - we'll use the fallback aliases
1960
+ // cachedPathAliases will remain null, triggering fallback below
1939
1961
  }
1940
1962
  }
1941
1963
 
@@ -1950,13 +1972,16 @@ function getPathAliases(projectRoot: string): Map<string, string> {
1950
1972
  } else {
1951
1973
  aliases.set("@/", "");
1952
1974
  }
1953
- debugLog("[apply] Using default @/ alias", { alias: aliases.get("@/") });
1975
+ // Only log default alias once (not when using cached error fallback)
1976
+ if (!cachedParseError) {
1977
+ debugLog("[apply] Using default @/ alias", { alias: aliases.get("@/") });
1978
+ }
1954
1979
  }
1955
1980
 
1956
- // Only cache if we parsed successfully or there's no tsconfig
1957
- if (parsedSuccessfully || !fs.existsSync(tsconfigPath)) {
1958
- cachedPathAliases = aliases;
1959
- cachedProjectRoot = projectRoot;
1981
+ // Cache aliases if parsed successfully, no tsconfig exists, OR we have a parse error (cache fallback)
1982
+ if (parsedSuccessfully || !fs.existsSync(tsconfigPath) || cachedParseError) {
1983
+ cachedPathAliases = aliases;
1984
+ cachedProjectRoot = projectRoot;
1960
1985
  }
1961
1986
 
1962
1987
  return aliases;
@@ -852,6 +852,14 @@ CRITICAL: Edit the TARGET COMPONENT (marked with ***), not the page wrapper.`;
852
852
  // If this is a retry, add feedback about what went wrong
853
853
  if (retryCount > 0 && lastPatchErrors.length > 0) {
854
854
  debugLog("Retry attempt with feedback", { retryCount, errorCount: lastPatchErrors.length });
855
+
856
+ // Get a snippet of the actual file content to help AI find correct code
857
+ let fileSnippet = "";
858
+ if (recommendedFileContent) {
859
+ // Show first 800 chars to give AI context about what code actually exists
860
+ fileSnippet = recommendedFileContent.content.substring(0, 800).replace(/\n/g, "\n");
861
+ }
862
+
855
863
  currentMessages.push({
856
864
  role: "assistant",
857
865
  content: "I'll analyze the screenshot and generate the patches now.",
@@ -863,10 +871,20 @@ CRITICAL: Edit the TARGET COMPONENT (marked with ***), not the page wrapper.`;
863
871
  Failed patches:
864
872
  ${lastPatchErrors.join("\n\n")}
865
873
 
866
- IMPORTANT: You must copy the "search" string EXACTLY from the file content I provided. Do NOT invent or guess code.
867
- Look carefully at the ACTUAL file content in the TARGET COMPONENT section above and try again.
874
+ ${fileSnippet ? `Here is the ACTUAL beginning of the file you're trying to edit:
875
+ \`\`\`tsx
876
+ ${fileSnippet}...
877
+ \`\`\`
878
+ ` : ""}
879
+ CRITICAL INSTRUCTIONS:
880
+ 1. Your "search" string MUST be copied EXACTLY from the file content I provided above
881
+ 2. Do NOT invent, guess, or imagine code that might exist
882
+ 3. Look for the ACTUAL code in the TARGET COMPONENT section and copy it exactly
868
883
 
869
- If you cannot find the exact code to modify, return an empty modifications array with an explanation.`,
884
+ If you still cannot find the exact code to modify after reviewing the file:
885
+ - Return {"modifications": [], "explanation": "Could not locate the exact code. Please specify which element you want to change more precisely."}
886
+
887
+ This is better than generating patches with made-up code.`,
870
888
  });
871
889
  }
872
890
 
@@ -1755,6 +1773,7 @@ function searchFilesForKeywords(
1755
1773
  let cachedPathAliases: Map<string, string> | null = null;
1756
1774
  let cachedProjectRoot: string | null = null;
1757
1775
  let cachedTsconfigMtime: number | null = null;
1776
+ let cachedParseError: string | null = null; // Cache parse errors to avoid log spam
1758
1777
 
1759
1778
  /**
1760
1779
  * Clean tsconfig.json content to make it valid JSON
@@ -1827,21 +1846,23 @@ function getPathAliases(projectRoot: string): Map<string, string> {
1827
1846
  cachedTsconfigMtime = null;
1828
1847
  }
1829
1848
  } catch (e) {
1830
- // Log the error with more context for debugging
1831
1849
  const errorStr = String(e);
1832
- const posMatch = errorStr.match(/position (\d+)/);
1833
- let context = "";
1834
- if (posMatch) {
1835
- const pos = parseInt(posMatch[1], 10);
1836
- const content = fs.readFileSync(tsconfigPath, "utf-8");
1837
- context = `Near: "${content.substring(Math.max(0, pos - 20), pos + 20)}"`;
1850
+
1851
+ // Only log parse error once to avoid log spam
1852
+ if (!cachedParseError) {
1853
+ const posMatch = errorStr.match(/position (\d+)/);
1854
+ let context = "";
1855
+ if (posMatch) {
1856
+ const pos = parseInt(posMatch[1], 10);
1857
+ const content = fs.readFileSync(tsconfigPath, "utf-8");
1858
+ context = `Near: "${content.substring(Math.max(0, pos - 20), pos + 20)}"`;
1859
+ }
1860
+ debugLog("[edit] Failed to parse tsconfig.json (will use defaults, logging once)", { error: errorStr, context });
1861
+ cachedParseError = errorStr;
1838
1862
  }
1839
- debugLog("[edit] Failed to parse tsconfig.json", { error: errorStr, context });
1840
1863
 
1841
- // Clear cache on error so we retry next time
1842
- cachedPathAliases = null;
1843
- cachedProjectRoot = null;
1844
- cachedTsconfigMtime = null;
1864
+ // Don't clear cache - we'll use the fallback aliases
1865
+ // cachedPathAliases will remain null, triggering fallback below
1845
1866
  }
1846
1867
  }
1847
1868
 
@@ -1856,13 +1877,16 @@ function getPathAliases(projectRoot: string): Map<string, string> {
1856
1877
  } else {
1857
1878
  aliases.set("@/", "");
1858
1879
  }
1859
- debugLog("[edit] Using default @/ alias", { alias: aliases.get("@/") });
1880
+ // Only log default alias once (not when using cached error fallback)
1881
+ if (!cachedParseError) {
1882
+ debugLog("[edit] Using default @/ alias", { alias: aliases.get("@/") });
1883
+ }
1860
1884
  }
1861
1885
 
1862
- // Only cache if we parsed successfully or there's no tsconfig
1863
- if (parsedSuccessfully || !fs.existsSync(tsconfigPath)) {
1864
- cachedPathAliases = aliases;
1865
- cachedProjectRoot = projectRoot;
1886
+ // Cache aliases if parsed successfully, no tsconfig exists, OR we have a parse error (cache fallback)
1887
+ if (parsedSuccessfully || !fs.existsSync(tsconfigPath) || cachedParseError) {
1888
+ cachedPathAliases = aliases;
1889
+ cachedProjectRoot = projectRoot;
1866
1890
  }
1867
1891
 
1868
1892
  return aliases;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sonance-brand-mcp",
3
- "version": "1.3.48",
3
+ "version": "1.3.49",
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",