solidworks-mcp-server
Version:
Clean Architecture SolidWorks MCP Server - Production-ready with SOLID principles
228 lines • 7.4 kB
JavaScript
/**
* Macro Recorder for SolidWorks MCP
* Records and manages macro operations
*/
import { v4 as uuidv4 } from 'uuid';
export class MacroRecorder {
currentRecording = null;
recordings = new Map();
executions = new Map();
actionHandlers = new Map();
/**
* Start a new macro recording
*/
startRecording(name, description = '') {
if (this.currentRecording) {
throw new Error('A recording is already in progress');
}
const id = uuidv4();
this.currentRecording = {
id,
name,
description,
startTime: new Date().toISOString(),
actions: [],
metadata: {
createdBy: 'solidworks-mcp',
version: '1.0.0',
tags: []
}
};
return id;
}
/**
* Stop the current recording
*/
stopRecording() {
if (!this.currentRecording) {
return null;
}
this.currentRecording.endTime = new Date().toISOString();
const recording = this.currentRecording;
this.recordings.set(recording.id, recording);
this.currentRecording = null;
return recording;
}
/**
* Record an action
*/
recordAction(type, name, parameters) {
if (!this.currentRecording) {
throw new Error('No recording in progress');
}
const action = {
id: uuidv4(),
type,
name,
timestamp: new Date().toISOString(),
parameters
};
this.currentRecording.actions.push(action);
}
/**
* Get a recording by ID
*/
getRecording(id) {
return this.recordings.get(id);
}
/**
* Get all recordings
*/
getAllRecordings() {
return Array.from(this.recordings.values());
}
/**
* Delete a recording
*/
deleteRecording(id) {
return this.recordings.delete(id);
}
/**
* Register an action handler
*/
registerActionHandler(type, handler) {
this.actionHandlers.set(type, handler);
}
/**
* Execute a macro recording
*/
async executeMacro(macroId, parameters) {
const recording = this.recordings.get(macroId);
if (!recording) {
throw new Error(`Macro '${macroId}' not found`);
}
const executionId = uuidv4();
const execution = {
id: executionId,
macroId,
startTime: new Date().toISOString(),
status: 'running',
logs: []
};
this.executions.set(executionId, execution);
try {
const results = [];
for (const action of recording.actions) {
const handler = this.actionHandlers.get(action.type);
if (!handler) {
throw new Error(`No handler registered for action type '${action.type}'`);
}
this.addLog(execution, 'info', `Executing action: ${action.name}`);
try {
const result = await handler({
...action,
parameters: { ...action.parameters, ...parameters }
});
results.push(result);
this.addLog(execution, 'debug', `Action completed: ${action.name}`, result);
}
catch (error) {
this.addLog(execution, 'error', `Action failed: ${action.name}`, error);
throw error;
}
}
execution.status = 'completed';
execution.endTime = new Date().toISOString();
execution.result = results;
}
catch (error) {
execution.status = 'failed';
execution.endTime = new Date().toISOString();
execution.error = error instanceof Error ? error.message : String(error);
this.addLog(execution, 'error', 'Macro execution failed', error);
}
return execution;
}
/**
* Get execution by ID
*/
getExecution(id) {
return this.executions.get(id);
}
/**
* Get all executions for a macro
*/
getMacroExecutions(macroId) {
return Array.from(this.executions.values()).filter(e => e.macroId === macroId);
}
/**
* Add a log entry to an execution
*/
addLog(execution, level, message, data) {
execution.logs.push({
timestamp: new Date().toISOString(),
level,
message,
data
});
}
/**
* Export recording to VBA code
*/
exportToVBA(macroId) {
const recording = this.recordings.get(macroId);
if (!recording) {
throw new Error(`Macro '${macroId}' not found`);
}
const vbaLines = [
`' Macro: ${recording.name}`,
`' Description: ${recording.description}`,
`' Generated: ${new Date().toISOString()}`,
`' By: SolidWorks MCP Server`,
'',
`Sub ${this.sanitizeName(recording.name)}()`,
' Dim swApp As SldWorks.SldWorks',
' Dim swModel As SldWorks.ModelDoc2',
' ',
' Set swApp = Application.SldWorks',
' Set swModel = swApp.ActiveDoc',
' ',
' If swModel Is Nothing Then',
' MsgBox "No active document found"',
' Exit Sub',
' End If',
' '
];
// Convert actions to VBA code
for (const action of recording.actions) {
const vbaCode = this.actionToVBA(action);
if (vbaCode) {
vbaLines.push(` ' ${action.name}`);
vbaLines.push(...vbaCode.split('\n').map(line => ` ${line}`));
vbaLines.push('');
}
}
vbaLines.push('End Sub');
return vbaLines.join('\n');
}
/**
* Convert action to VBA code
*/
actionToVBA(action) {
// This would be expanded with specific action type conversions
const vbaGenerators = {
'create-sketch': (params) => `swModel.CreateSketch "${params.plane}"`,
'add-line': (params) => `swModel.CreateLine2 ${params.x1}, ${params.y1}, ${params.z1}, ${params.x2}, ${params.y2}, ${params.z2}`,
'add-circle': (params) => `swModel.CreateCircle2 ${params.centerX}, ${params.centerY}, ${params.centerZ}, ${params.radius}`,
'extrude': (params) => `swModel.FeatureManager.FeatureExtrusion3 True, False, False, 0, 0, ${params.depth}, 0, False, False, False, False, 0, 0, False, False, False, False, True, True, True, 0, 0, False`,
// Add more action types as needed
};
const generator = vbaGenerators[action.type];
return generator ? generator(action.parameters) : `' Unsupported action: ${action.type}`;
}
/**
* Sanitize name for VBA
*/
sanitizeName(name) {
return name.replace(/[^a-zA-Z0-9_]/g, '_');
}
/**
* Clear all recordings and executions
*/
clear() {
this.currentRecording = null;
this.recordings.clear();
this.executions.clear();
}
}
//# sourceMappingURL=recorder.js.map