Initial commit: Clean DSS implementation

Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm

Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)

Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability

Migration completed: $(date)
🤖 Clean migration with full functionality preserved
This commit is contained in:
Digital Production Factory
2025-12-09 18:45:48 -03:00
commit 276ed71f31
884 changed files with 373737 additions and 0 deletions

View File

@@ -0,0 +1,449 @@
/**
* Tools Service - Manages MCP tools catalog and execution
*/
import api from '../core/api.js';
import logger from '../core/logger.js';
class ToolsService {
constructor() {
this.tools = [];
this.toolsMetadata = this._getToolsMetadata();
this.executionHistory = [];
this.toolStatus = {};
this.teamToolMappings = this._getTeamToolMappings();
}
/**
* Define which tools are relevant for each team
*/
_getTeamToolMappings() {
return {
'ui': [
'extract_tokens', 'extract_components', 'generate_component_code',
'sync_tokens_to_file', 'ingest_css_tokens', 'ingest_scss_tokens',
'ingest_tailwind_tokens', 'merge_tokens', 'export_tokens',
'scan_storybook', 'generate_story', 'generate_stories_batch',
'generate_storybook_theme'
],
'ux': [
'analyze_style_values', 'check_naming_consistency', 'find_style_patterns',
'validate_tokens', 'extract_tokens', 'export_tokens',
'discover_project', 'get_sync_history'
],
'qa': [
'get_quick_wins', 'get_quick_wins_report', 'validate_tokens',
'find_unused_styles', 'find_inline_styles', 'analyze_react_components',
'build_source_graph', 'get_story_coverage'
],
'all': [] // Empty means all tools
};
}
/**
* Get metadata for all 32 MCP tools
*/
_getToolsMetadata() {
return {
// Projects
list_projects: {
name: 'list_projects',
category: 'Projects',
description: 'List all design system projects',
parameters: [],
icon: '📁'
},
create_project: {
name: 'create_project',
category: 'Projects',
description: 'Create a new design system project',
parameters: ['name', 'description', 'figma_file_key'],
icon: ''
},
get_project: {
name: 'get_project',
category: 'Projects',
description: 'Get details of a specific project',
parameters: ['project_id'],
icon: '🔍'
},
// Figma
extract_tokens: {
name: 'extract_tokens',
category: 'Figma',
description: 'Extract design tokens from Figma file',
parameters: ['file_key', 'format'],
icon: '🎨',
requiresConfig: ['figma_token']
},
extract_components: {
name: 'extract_components',
category: 'Figma',
description: 'Extract components from Figma file',
parameters: ['file_key'],
icon: '🧩',
requiresConfig: ['figma_token']
},
generate_component_code: {
name: 'generate_component_code',
category: 'Figma',
description: 'Generate React code from Figma component',
parameters: ['file_key', 'node_id', 'framework'],
icon: '⚛️',
requiresConfig: ['figma_token']
},
sync_tokens_to_file: {
name: 'sync_tokens_to_file',
category: 'Figma',
description: 'Sync tokens to output file',
parameters: ['file_key', 'output_path', 'format'],
icon: '🔄',
requiresConfig: ['figma_token']
},
// Ingestion
ingest_css_tokens: {
name: 'ingest_css_tokens',
category: 'Ingestion',
description: 'Ingest tokens from CSS variables',
parameters: ['source'],
icon: '📥'
},
ingest_scss_tokens: {
name: 'ingest_scss_tokens',
category: 'Ingestion',
description: 'Ingest tokens from SCSS variables',
parameters: ['source'],
icon: '📥'
},
ingest_tailwind_tokens: {
name: 'ingest_tailwind_tokens',
category: 'Ingestion',
description: 'Ingest tokens from Tailwind config',
parameters: ['source'],
icon: '📥'
},
ingest_json_tokens: {
name: 'ingest_json_tokens',
category: 'Ingestion',
description: 'Ingest tokens from JSON format',
parameters: ['source'],
icon: '📥'
},
merge_tokens: {
name: 'merge_tokens',
category: 'Ingestion',
description: 'Merge tokens from multiple sources',
parameters: ['sources', 'strategy'],
icon: '🔗'
},
export_tokens: {
name: 'export_tokens',
category: 'Ingestion',
description: 'Export tokens to specified format',
parameters: ['format', 'output_path'],
icon: '📤'
},
validate_tokens: {
name: 'validate_tokens',
category: 'Ingestion',
description: 'Validate token structure and values',
parameters: ['source'],
icon: '✓'
},
// Analysis
discover_project: {
name: 'discover_project',
category: 'Analysis',
description: 'Discover project structure and frameworks',
parameters: ['path'],
icon: '🔎',
quickWin: true
},
analyze_react_components: {
name: 'analyze_react_components',
category: 'Analysis',
description: 'Analyze React components in project',
parameters: ['path'],
icon: '⚛️',
quickWin: true
},
find_inline_styles: {
name: 'find_inline_styles',
category: 'Analysis',
description: 'Find components with inline styles',
parameters: ['path'],
icon: '🎯',
quickWin: true
},
find_style_patterns: {
name: 'find_style_patterns',
category: 'Analysis',
description: 'Identify common style patterns',
parameters: ['path'],
icon: '📊',
quickWin: true
},
analyze_style_values: {
name: 'analyze_style_values',
category: 'Analysis',
description: 'Analyze style property values',
parameters: ['path', 'property'],
icon: '📈',
quickWin: true
},
find_unused_styles: {
name: 'find_unused_styles',
category: 'Analysis',
description: 'Find unused style definitions',
parameters: ['path'],
icon: '🗑️',
quickWin: true
},
build_source_graph: {
name: 'build_source_graph',
category: 'Analysis',
description: 'Build component dependency graph',
parameters: ['path', 'depth'],
icon: '🕸️'
},
get_quick_wins: {
name: 'get_quick_wins',
category: 'Analysis',
description: 'Get actionable improvement opportunities',
parameters: ['path'],
icon: '⚡',
quickWin: true,
featured: true
},
get_quick_wins_report: {
name: 'get_quick_wins_report',
category: 'Analysis',
description: 'Generate detailed quick wins report',
parameters: ['path'],
icon: '📋',
quickWin: true
},
check_naming_consistency: {
name: 'check_naming_consistency',
category: 'Analysis',
description: 'Check component naming consistency',
parameters: ['path'],
icon: '🏷️',
quickWin: true
},
// Storybook
scan_storybook: {
name: 'scan_storybook',
category: 'Storybook',
description: 'Scan existing Storybook configuration',
parameters: ['path'],
icon: '📚'
},
generate_story: {
name: 'generate_story',
category: 'Storybook',
description: 'Generate Storybook story for component',
parameters: ['component_path', 'template'],
icon: '📖'
},
generate_stories_batch: {
name: 'generate_stories_batch',
category: 'Storybook',
description: 'Generate stories for multiple components',
parameters: ['components', 'template'],
icon: '📚'
},
generate_storybook_theme: {
name: 'generate_storybook_theme',
category: 'Storybook',
description: 'Generate Storybook theme from tokens',
parameters: ['tokens', 'output_path'],
icon: '🎨'
},
get_story_coverage: {
name: 'get_story_coverage',
category: 'Storybook',
description: 'Check which components have stories',
parameters: ['path'],
icon: '📊'
},
// Activity
get_status: {
name: 'get_status',
category: 'Activity',
description: 'Get server status and statistics',
parameters: [],
icon: '💚'
},
get_sync_history: {
name: 'get_sync_history',
category: 'Activity',
description: 'Get token sync history',
parameters: ['limit'],
icon: '📜'
},
get_activity: {
name: 'get_activity',
category: 'Activity',
description: 'Get recent activity log',
parameters: ['limit'],
icon: '📝'
}
};
}
/**
* Get all tools with metadata
*/
getAllTools() {
return Object.values(this.toolsMetadata).map(tool => ({
...tool,
status: this.toolStatus[tool.name] || 'available',
lastUsed: this._getLastUsed(tool.name)
}));
}
/**
* Get tools by category
*/
getToolsByCategory(category) {
return this.getAllTools().filter(tool => tool.category === category);
}
/**
* Get quick win tools
*/
getQuickWinTools() {
return this.getAllTools().filter(tool => tool.quickWin);
}
/**
* Get featured tools
*/
getFeaturedTools() {
return this.getAllTools().filter(tool => tool.featured);
}
/**
* Get tools filtered by team context
*/
getToolsByTeam(teamContext = 'all') {
if (teamContext === 'all' || !this.teamToolMappings[teamContext]) {
return this.getAllTools();
}
const teamTools = this.teamToolMappings[teamContext];
return this.getAllTools().filter(tool => teamTools.includes(tool.name));
}
/**
* Execute a tool
*/
async executeTool(toolName, params = {}) {
logger.info('Tools', `Executing tool: ${toolName}`, params);
this.toolStatus[toolName] = 'executing';
const startTime = Date.now();
try {
// Map tool name to API endpoint
const result = await api.executeMCPTool(toolName, params);
const duration = Date.now() - startTime;
this.toolStatus[toolName] = 'success';
// Log execution
this._logExecution(toolName, params, result, duration, 'success');
logger.info('Tools', `Tool ${toolName} succeeded in ${duration}ms`);
return result;
} catch (error) {
const duration = Date.now() - startTime;
this.toolStatus[toolName] = 'error';
// Log error
this._logExecution(toolName, params, null, duration, 'error', error.message);
logger.error('Tools', `Tool ${toolName} failed: ${error.message}`, error);
throw error;
}
}
/**
* Log tool execution
*/
_logExecution(toolName, params, result, duration, status, error = null) {
const execution = {
toolName,
params,
result,
duration,
status,
error,
timestamp: new Date().toISOString()
};
this.executionHistory.push(execution);
// Keep only last 100 executions
if (this.executionHistory.length > 100) {
this.executionHistory.shift();
}
}
/**
* Get execution history for a tool
*/
getToolHistory(toolName) {
return this.executionHistory
.filter(exec => exec.toolName === toolName)
.slice(-10);
}
/**
* Get last used timestamp
*/
_getLastUsed(toolName) {
const executions = this.executionHistory.filter(exec => exec.toolName === toolName);
if (executions.length === 0) return null;
return executions[executions.length - 1].timestamp;
}
/**
* Get tool success rate
*/
getSuccessRate(toolName) {
const executions = this.executionHistory.filter(exec => exec.toolName === toolName);
if (executions.length === 0) return null;
const successful = executions.filter(exec => exec.status === 'success').length;
return successful / executions.length;
}
/**
* Get all categories
*/
getCategories() {
const categories = new Set();
Object.values(this.toolsMetadata).forEach(tool => {
categories.add(tool.category);
});
return Array.from(categories);
}
}
// Singleton instance
const toolsService = new ToolsService();
export default toolsService;
export { ToolsService };