style: apply Prettier formatting to TS/JS/JSON/MD files

Add Prettier as a dev dependency with .prettierrc.json config and
.prettierignore. Hook added via mirrors-prettier in pre-commit config.
All TypeScript, JSON, Markdown, and YAML files auto-formatted.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Eugene Mikhantyev
2026-03-29 13:05:50 +01:00
parent c44bd9205d
commit 7d50fa1d4c
82 changed files with 18314 additions and 17317 deletions

View File

@@ -54,18 +54,8 @@ function findPythonExecutable(scriptPath: string): string {
// Check for virtual environment
const venvPaths = [
join(
projectRoot,
"venv",
isWindows ? "Scripts" : "bin",
isWindows ? "python.exe" : "python",
),
join(
projectRoot,
".venv",
isWindows ? "Scripts" : "bin",
isWindows ? "python.exe" : "python",
),
join(projectRoot, "venv", isWindows ? "Scripts" : "bin", isWindows ? "python.exe" : "python"),
join(projectRoot, ".venv", isWindows ? "Scripts" : "bin", isWindows ? "python.exe" : "python"),
];
for (const venvPath of venvPaths) {
@@ -77,9 +67,7 @@ function findPythonExecutable(scriptPath: string): string {
// Allow override via KICAD_PYTHON environment variable (any platform)
if (process.env.KICAD_PYTHON) {
logger.info(
`Using KICAD_PYTHON environment variable: ${process.env.KICAD_PYTHON}`,
);
logger.info(`Using KICAD_PYTHON environment variable: ${process.env.KICAD_PYTHON}`);
return process.env.KICAD_PYTHON;
}
@@ -123,9 +111,7 @@ function findPythonExecutable(scriptPath: string): string {
for (const path of homebrewPaths) {
if (existsSync(path)) {
logger.info(
`Found Homebrew Python at: ${path} (ensure pcbnew is importable)`,
);
logger.info(`Found Homebrew Python at: ${path} (ensure pcbnew is importable)`);
return path;
}
}
@@ -196,19 +182,14 @@ export class KiCADMcpServer {
* @param kicadScriptPath Path to the Python KiCAD interface script
* @param logLevel Log level for the server
*/
constructor(
kicadScriptPath: string,
logLevel: "error" | "warn" | "info" | "debug" = "info",
) {
constructor(kicadScriptPath: string, logLevel: "error" | "warn" | "info" | "debug" = "info") {
// Set up the logger
logger.setLogLevel(logLevel);
// Check if KiCAD script exists
this.kicadScriptPath = kicadScriptPath;
if (!existsSync(this.kicadScriptPath)) {
throw new Error(
`KiCAD interface script not found: ${this.kicadScriptPath}`,
);
throw new Error(`KiCAD interface script not found: ${this.kicadScriptPath}`);
}
// Initialize the MCP server
@@ -267,9 +248,7 @@ export class KiCADMcpServer {
registerFootprintPrompts(this.server);
logger.info("All KiCAD tools, resources, and prompts registered");
logger.info(
"Router pattern enabled: 4 router tools + direct tools for discovery",
);
logger.info("Router pattern enabled: 4 router tools + direct tools for discovery");
}
/**
@@ -277,15 +256,12 @@ export class KiCADMcpServer {
*/
private async validatePrerequisites(pythonExe: string): Promise<boolean> {
const isWindows = process.platform === "win32";
const isLinux =
process.platform !== "win32" && process.platform !== "darwin";
const isLinux = process.platform !== "win32" && process.platform !== "darwin";
const errors: string[] = [];
// Check if Python executable exists (for absolute paths) or is executable (for commands)
const isAbsolutePath =
pythonExe.startsWith("/") ||
pythonExe.startsWith("C:") ||
pythonExe.startsWith("\\");
pythonExe.startsWith("/") || pythonExe.startsWith("C:") || pythonExe.startsWith("\\");
if (isAbsolutePath) {
// Absolute path: use existsSync
@@ -293,16 +269,10 @@ export class KiCADMcpServer {
errors.push(`Python executable not found: ${pythonExe}`);
if (isWindows) {
errors.push(
"Windows: Install KiCAD 9.0+ from https://www.kicad.org/download/windows/",
);
errors.push(
"Or run: .\\setup-windows.ps1 for automatic configuration",
);
errors.push("Windows: Install KiCAD 9.0+ from https://www.kicad.org/download/windows/");
errors.push("Or run: .\\setup-windows.ps1 for automatic configuration");
} else if (isLinux) {
errors.push(
"Linux: Install KiCAD 9.0+ or set KICAD_PYTHON environment variable",
);
errors.push("Linux: Install KiCAD 9.0+ or set KICAD_PYTHON environment variable");
errors.push("Set KICAD_PYTHON to specify a custom Python path");
}
}
@@ -334,20 +304,14 @@ export class KiCADMcpServer {
} catch (error: any) {
errors.push(`Python executable not found in PATH: ${pythonExe}`);
errors.push(`Error: ${error.message}`);
errors.push(
"Set KICAD_PYTHON environment variable to specify full path",
);
errors.push("Set KICAD_PYTHON environment variable to specify full path");
if (isLinux) {
errors.push("");
errors.push("Linux troubleshooting:");
errors.push("1. Check if python3 is installed: which python3");
errors.push(
"2. Install KiCAD: sudo apt install kicad (Ubuntu/Debian)",
);
errors.push(
"3. Set KICAD_PYTHON=/usr/bin/python3 in your MCP config",
);
errors.push("2. Install KiCAD: sudo apt install kicad (Ubuntu/Debian)");
errors.push("3. Set KICAD_PYTHON=/usr/bin/python3 in your MCP config");
}
}
}
@@ -358,11 +322,7 @@ export class KiCADMcpServer {
}
// Check if dist/index.js exists (if running from compiled code)
const distPath = join(
dirname(dirname(this.kicadScriptPath)),
"dist",
"index.js",
);
const distPath = join(dirname(dirname(this.kicadScriptPath)), "dist", "index.js");
if (!existsSync(distPath)) {
errors.push("Project not built. Run: npm run build");
}
@@ -458,9 +418,7 @@ export class KiCADMcpServer {
logger.info("Starting KiCAD MCP server...");
// Start the Python process for KiCAD scripting
logger.info(
`Starting Python process with script: ${this.kicadScriptPath}`,
);
logger.info(`Starting Python process with script: ${this.kicadScriptPath}`);
const pythonExe = findPythonExecutable(this.kicadScriptPath);
logger.info(`Using Python executable: ${pythonExe}`);
@@ -468,25 +426,20 @@ export class KiCADMcpServer {
// Validate prerequisites
const isValid = await this.validatePrerequisites(pythonExe);
if (!isValid) {
throw new Error(
"Prerequisites validation failed. See logs above for details.",
);
throw new Error("Prerequisites validation failed. See logs above for details.");
}
this.pythonProcess = spawn(pythonExe, [this.kicadScriptPath], {
stdio: ["pipe", "pipe", "pipe"],
env: {
...process.env,
PYTHONPATH:
process.env.PYTHONPATH ||
"C:/Program Files/KiCad/9.0/lib/python3/dist-packages",
process.env.PYTHONPATH || "C:/Program Files/KiCad/9.0/lib/python3/dist-packages",
},
});
// Listen for process exit
this.pythonProcess.on("exit", (code, signal) => {
logger.warn(
`Python process exited with code ${code} and signal ${signal}`,
);
logger.warn(`Python process exited with code ${code} and signal ${signal}`);
this.pythonProcess = null;
});
@@ -563,17 +516,10 @@ export class KiCADMcpServer {
// Determine timeout based on command type
// DRC and export operations need longer timeouts for large boards
let commandTimeout = 30000; // Default 30 seconds
const longRunningCommands = [
"run_drc",
"export_gerber",
"export_pdf",
"export_3d",
];
const longRunningCommands = ["run_drc", "export_gerber", "export_pdf", "export_3d"];
if (longRunningCommands.includes(command)) {
commandTimeout = 600000; // 10 minutes for long operations
logger.info(
`Using extended timeout (${commandTimeout / 1000}s) for command: ${command}`,
);
logger.info(`Using extended timeout (${commandTimeout / 1000}s) for command: ${command}`);
}
// Add request to queue with timeout info
@@ -678,12 +624,8 @@ export class KiCADMcpServer {
// Set a timeout (use command-specific timeout or default)
const timeoutDuration = request.timeout || 30000;
const timeoutHandle = setTimeout(() => {
logger.error(
`Command timeout after ${timeoutDuration / 1000}s: ${request.command}`,
);
logger.error(
`Buffer contents: ${this.responseBuffer.substring(0, 200)}...`,
);
logger.error(`Command timeout after ${timeoutDuration / 1000}s: ${request.command}`);
logger.error(`Buffer contents: ${this.responseBuffer.substring(0, 200)}...`);
// Clear state
this.responseBuffer = "";
@@ -691,11 +633,7 @@ export class KiCADMcpServer {
this.processingRequest = false;
// Reject the promise
reject(
new Error(
`Command timeout after ${timeoutDuration / 1000}s: ${request.command}`,
),
);
reject(new Error(`Command timeout after ${timeoutDuration / 1000}s: ${request.command}`));
// Process next request
setTimeout(() => this.processNextRequest(), 0);