0xray 2.0.0
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.
- package/.opencode/agents/api-design.yml +31 -0
- package/.opencode/agents/architect.yml +15 -0
- package/.opencode/agents/architecture-patterns.yml +14 -0
- package/.opencode/agents/auto-format.yml +14 -0
- package/.opencode/agents/backend-engineer.yml +12 -0
- package/.opencode/agents/boot-orchestrator.yml +14 -0
- package/.opencode/agents/bug-triage-specialist.yml +15 -0
- package/.opencode/agents/code-analyzer.yml +12 -0
- package/.opencode/agents/code-reviewer.yml +14 -0
- package/.opencode/agents/content-creator.yml +12 -0
- package/.opencode/agents/database-engineer.yml +12 -0
- package/.opencode/agents/devops-engineer.yml +12 -0
- package/.opencode/agents/framework-compliance-audit.yml +14 -0
- package/.opencode/agents/frontend-engineer.yml +12 -0
- package/.opencode/agents/frontend-ui-ux-engineer.yml +12 -0
- package/.opencode/agents/git-workflow.yml +15 -0
- package/.opencode/agents/growth-strategist.yml +12 -0
- package/.opencode/agents/hermes-agent.yml +12 -0
- package/.opencode/agents/inference-improve.yml +12 -0
- package/.opencode/agents/lint.yml +14 -0
- package/.opencode/agents/log-monitor.yml +12 -0
- package/.opencode/agents/mobile-developer.yml +12 -0
- package/.opencode/agents/model-health-check.yml +12 -0
- package/.opencode/agents/multimodal-looker.yml +12 -0
- package/.opencode/agents/performance-analysis.yml +12 -0
- package/.opencode/agents/performance-engineer.yml +12 -0
- package/.opencode/agents/performance-optimization.yml +12 -0
- package/.opencode/agents/processor-pipeline.yml +14 -0
- package/.opencode/agents/project-analysis.yml +12 -0
- package/.opencode/agents/refactorer.yml +12 -0
- package/.opencode/agents/researcher.yml +12 -0
- package/.opencode/agents/security-auditor.yml +12 -0
- package/.opencode/agents/security-scan.yml +12 -0
- package/.opencode/agents/seo-consultant.yml +12 -0
- package/.opencode/agents/session-management.yml +12 -0
- package/.opencode/agents/state-manager.yml +12 -0
- package/.opencode/agents/storyteller.yml +12 -0
- package/.opencode/agents/strategist.yml +12 -0
- package/.opencode/agents/tech-writer.yml +12 -0
- package/.opencode/agents/testing-best-practices.yml +12 -0
- package/.opencode/agents/testing-lead.yml +12 -0
- package/.opencode/agents/ui-ux-design.yml +12 -0
- package/.opencode/codex.codex +8 -0
- package/.opencode/commands/auto-format.md +99 -0
- package/.opencode/commands/auto-summary-capture.md +90 -0
- package/.opencode/commands/dependency-audit.md +184 -0
- package/.opencode/commands/enforcer-daily-scan.md +137 -0
- package/.opencode/commands/framework-compliance-audit.md +205 -0
- package/.opencode/commands/interactive-validator.md +75 -0
- package/.opencode/commands/job-summary-logger.md +68 -0
- package/.opencode/commands/lint.md +11 -0
- package/.opencode/commands/mode-switch.md +95 -0
- package/.opencode/commands/model-health-check.md +186 -0
- package/.opencode/commands/performance-analysis.md +144 -0
- package/.opencode/commands/pre-commit-introspection.md +185 -0
- package/.opencode/commands/pre-commit-introspection.sh +133 -0
- package/.opencode/commands/security-scan.md +157 -0
- package/.opencode/commands/sisyphus-validation.md +128 -0
- package/.opencode/commands/summary-logger.md +83 -0
- package/.opencode/enforcer-config.json +285 -0
- package/.opencode/hooks/hook-metrics.json +380 -0
- package/.opencode/hooks/post-commit +114 -0
- package/.opencode/hooks/post-push +34 -0
- package/.opencode/init.sh +151 -0
- package/.opencode/skills/api-design/SKILL.md +37 -0
- package/.opencode/skills/architect-tools/SKILL.md +37 -0
- package/.opencode/skills/architecture-patterns/SKILL.md +37 -0
- package/.opencode/skills/auto-format/SKILL.md +37 -0
- package/.opencode/skills/backend-engineer/SKILL.md +49 -0
- package/.opencode/skills/boot-orchestrator/SKILL.md +37 -0
- package/.opencode/skills/bug-triage/SKILL.md +43 -0
- package/.opencode/skills/code-analyzer/SKILL.md +45 -0
- package/.opencode/skills/code-review/SKILL.md +52 -0
- package/.opencode/skills/content-creator/SKILL.md +38 -0
- package/.opencode/skills/database-engineer/SKILL.md +46 -0
- package/.opencode/skills/devops-engineer/SKILL.md +49 -0
- package/.opencode/skills/enforcer/SKILL.md +37 -0
- package/.opencode/skills/framework-compliance-audit/SKILL.md +37 -0
- package/.opencode/skills/frontend-engineer/SKILL.md +49 -0
- package/.opencode/skills/frontend-ui-ux-engineer/SKILL.md +41 -0
- package/.opencode/skills/git-workflow/SKILL.md +37 -0
- package/.opencode/skills/growth-strategist/SKILL.md +48 -0
- package/.opencode/skills/hermes-agent/SKILL.md +212 -0
- package/.opencode/skills/inference-improve/SKILL.md +97 -0
- package/.opencode/skills/lint/SKILL.md +37 -0
- package/.opencode/skills/log-monitor/SKILL.md +44 -0
- package/.opencode/skills/mobile-developer/SKILL.md +42 -0
- package/.opencode/skills/model-health-check/SKILL.md +37 -0
- package/.opencode/skills/multimodal-looker/SKILL.md +45 -0
- package/.opencode/skills/orchestrator/SKILL.md +37 -0
- package/.opencode/skills/performance-analysis/SKILL.md +37 -0
- package/.opencode/skills/performance-engineer/SKILL.md +41 -0
- package/.opencode/skills/performance-optimization/SKILL.md +37 -0
- package/.opencode/skills/processor-pipeline/SKILL.md +37 -0
- package/.opencode/skills/project-analysis/SKILL.md +42 -0
- package/.opencode/skills/refactoring-strategies/SKILL.md +37 -0
- package/.opencode/skills/registry.json +66 -0
- package/.opencode/skills/researcher/SKILL.md +37 -0
- package/.opencode/skills/security-audit/SKILL.md +47 -0
- package/.opencode/skills/security-scan/SKILL.md +37 -0
- package/.opencode/skills/seo-consultant/SKILL.md +43 -0
- package/.opencode/skills/session-management/SKILL.md +36 -0
- package/.opencode/skills/state-manager/SKILL.md +37 -0
- package/.opencode/skills/storyteller/SKILL.md +130 -0
- package/.opencode/skills/strategist/SKILL.md +32 -0
- package/.opencode/skills/tech-writer/SKILL.md +37 -0
- package/.opencode/skills/testing-best-practices/SKILL.md +37 -0
- package/.opencode/skills/testing-strategy/SKILL.md +43 -0
- package/.opencode/skills/ui-ux-design/SKILL.md +603 -0
- package/.opencode/workflows/post-deployment-audit.yml +123 -0
- package/AGENTS.md +110 -0
- package/LICENSE +21 -0
- package/README.md +131 -0
- package/dist/AGENTS.md +110 -0
- package/dist/CHANGELOG.md +2182 -0
- package/dist/LICENSE +21 -0
- package/dist/README.md +131 -0
- package/dist/agents/architect.js +56 -0
- package/dist/agents/backend-engineer.js +81 -0
- package/dist/agents/bug-triage-specialist.js +74 -0
- package/dist/agents/code-analyzer.js +150 -0
- package/dist/agents/code-reviewer.js +69 -0
- package/dist/agents/content-creator.js +72 -0
- package/dist/agents/database-engineer.js +76 -0
- package/dist/agents/devops-engineer.js +84 -0
- package/dist/agents/frontend-engineer.js +78 -0
- package/dist/agents/frontend-ui-ux-engineer.js +64 -0
- package/dist/agents/growth-strategist.js +111 -0
- package/dist/agents/index.js +45 -0
- package/dist/agents/librarian-agents-updater.js +333 -0
- package/dist/agents/log-monitor.js +109 -0
- package/dist/agents/mobile-developer.js +102 -0
- package/dist/agents/multimodal-looker.js +93 -0
- package/dist/agents/performance-engineer.js +86 -0
- package/dist/agents/refactorer.js +80 -0
- package/dist/agents/registry.js +340 -0
- package/dist/agents/researcher.js +83 -0
- package/dist/agents/security-auditor.js +158 -0
- package/dist/agents/seo-consultant.js +53 -0
- package/dist/agents/strategist.js +47 -0
- package/dist/agents/tech-writer.js +84 -0
- package/dist/agents/testing-lead.js +95 -0
- package/dist/agents/types.js +1 -0
- package/dist/analytics/consent-manager.js +258 -0
- package/dist/analytics/emerging-pattern-detector.js +260 -0
- package/dist/analytics/pattern-learning-engine.js +278 -0
- package/dist/analytics/pattern-performance-tracker.js +336 -0
- package/dist/analytics/predictive-analytics.js +248 -0
- package/dist/analytics/prompt-pattern-analyzer.js +371 -0
- package/dist/analytics/routing-performance-analyzer.js +356 -0
- package/dist/analytics/routing-refiner.js +380 -0
- package/dist/analytics/simple-pattern-analyzer.js +297 -0
- package/dist/architect/architect-tools.js +437 -0
- package/dist/architect/architectural-integrity.js +78 -0
- package/dist/benchmark/performance-benchmark.js +372 -0
- package/dist/cli/commands/analytics-disable.js +72 -0
- package/dist/cli/commands/analytics-enable-action.js +82 -0
- package/dist/cli/commands/analytics-preview.js +106 -0
- package/dist/cli/commands/analytics-status.js +68 -0
- package/dist/cli/commands/antigravity-status.js +106 -0
- package/dist/cli/commands/archive-logs.js +161 -0
- package/dist/cli/commands/credible-init.js +82 -0
- package/dist/cli/commands/grok-install.js +16 -0
- package/dist/cli/commands/hermes-install.js +66 -0
- package/dist/cli/commands/mcp-install.js +253 -0
- package/dist/cli/commands/openclaw-install.js +44 -0
- package/dist/cli/commands/opencode-install.js +99 -0
- package/dist/cli/commands/plugin-commands.js +246 -0
- package/dist/cli/commands/publish-agent.js +184 -0
- package/dist/cli/commands/security-audit.js +219 -0
- package/dist/cli/commands/skill-install.js +481 -0
- package/dist/cli/commands/status.js +196 -0
- package/dist/cli/commands/storyteller.js +230 -0
- package/dist/cli/index.js +986 -0
- package/dist/cli/server.js +147 -0
- package/dist/config/default-agents.js +16 -0
- package/dist/core/activity-logger.js +260 -0
- package/dist/core/adaptive-kernel.js +192 -0
- package/dist/core/agent-spawn-gate.js +120 -0
- package/dist/core/boot-orchestrator.js +812 -0
- package/dist/core/bridge.mjs +945 -0
- package/dist/core/codex-formatter.js +220 -0
- package/dist/core/codex-injector.js +424 -0
- package/dist/core/config-loader.js +148 -0
- package/dist/core/config-paths.js +162 -0
- package/dist/core/context-loader.js +269 -0
- package/dist/core/context-validator.js +212 -0
- package/dist/core/features-config.js +457 -0
- package/dist/core/framework-logger.js +275 -0
- package/dist/core/index.js +6 -0
- package/dist/core/kernel-patterns.js +302 -0
- package/dist/core/logging-config.js +43 -0
- package/dist/core/model-router.js +175 -0
- package/dist/core/orchestrator.js +408 -0
- package/dist/core/system-prompt-generator.js +265 -0
- package/dist/core/trace-context.js +33 -0
- package/dist/core/xray-activation.js +134 -0
- package/dist/delegation/agent-delegator.js +769 -0
- package/dist/delegation/agent-expertise.js +156 -0
- package/dist/delegation/analytics/index.js +12 -0
- package/dist/delegation/analytics/learning-engine.js +277 -0
- package/dist/delegation/analytics/outcome-tracker.js +279 -0
- package/dist/delegation/analytics/routing-analytics.js +193 -0
- package/dist/delegation/ast-code-parser.js +878 -0
- package/dist/delegation/codebase-context-analyzer.js +1040 -0
- package/dist/delegation/complexity-analyzer.js +282 -0
- package/dist/delegation/complexity-core.js +219 -0
- package/dist/delegation/config/types.js +6 -0
- package/dist/delegation/dependency-graph-builder.js +409 -0
- package/dist/delegation/index.js +20 -0
- package/dist/delegation/metrics-aggregator.js +335 -0
- package/dist/delegation/session-coordinator.js +352 -0
- package/dist/delegation/strategy-selector.js +108 -0
- package/dist/delegation/voting-coordinator.js +375 -0
- package/dist/delegation/voting-types.js +10 -0
- package/dist/delegation/weighted-voting-aggregator.js +194 -0
- package/dist/enforcement/core/index.js +19 -0
- package/dist/enforcement/core/rule-executor.js +365 -0
- package/dist/enforcement/core/rule-hierarchy.js +259 -0
- package/dist/enforcement/core/rule-registry.js +240 -0
- package/dist/enforcement/core/violation-fixer.js +651 -0
- package/dist/enforcement/enforcer-tools.js +909 -0
- package/dist/enforcement/index.js +41 -0
- package/dist/enforcement/loaders/agent-triage-loader.js +222 -0
- package/dist/enforcement/loaders/agents-md-validation-loader.js +252 -0
- package/dist/enforcement/loaders/base-loader.js +86 -0
- package/dist/enforcement/loaders/codex-loader.js +396 -0
- package/dist/enforcement/loaders/index.js +40 -0
- package/dist/enforcement/loaders/loader-orchestrator.js +168 -0
- package/dist/enforcement/loaders/processor-loader.js +113 -0
- package/dist/enforcement/rule-enforcer.js +298 -0
- package/dist/enforcement/test-auto-healing.js +325 -0
- package/dist/enforcement/types.js +30 -0
- package/dist/enforcement/validators/architecture-validators.js +600 -0
- package/dist/enforcement/validators/base-validator.js +108 -0
- package/dist/enforcement/validators/code-quality-validators.js +336 -0
- package/dist/enforcement/validators/index.js +21 -0
- package/dist/enforcement/validators/security-validators.js +220 -0
- package/dist/enforcement/validators/testing-validators.js +253 -0
- package/dist/enforcement/validators/validator-registry.js +150 -0
- package/dist/execution/opencode-cli-invoker.js +173 -0
- package/dist/execution/proposal-applier.js +254 -0
- package/dist/governance/codex-policy.service.js +167 -0
- package/dist/governance/governance-core.js +152 -0
- package/dist/governance/governance-service.js +274 -0
- package/dist/governance/governance-types.js +6 -0
- package/dist/index.js +24 -0
- package/dist/inference/deploy-verifier.js +161 -0
- package/dist/inference/index.js +5 -0
- package/dist/inference/inference-accumulator.js +126 -0
- package/dist/inference/inference-cycle.js +1168 -0
- package/dist/inference/semantic-patterns.js +310 -0
- package/dist/inference/session-capture.js +308 -0
- package/dist/integrations/base/ExampleIntegration.js +181 -0
- package/dist/integrations/base/Integration.js +395 -0
- package/dist/integrations/base/README.md +446 -0
- package/dist/integrations/base/index.js +16 -0
- package/dist/integrations/base/registry.js +606 -0
- package/dist/integrations/base/types.js +118 -0
- package/dist/integrations/governance/governance-client.js +316 -0
- package/dist/integrations/governance/index.js +373 -0
- package/dist/integrations/governance/types.js +97 -0
- package/dist/integrations/grok/grok-cli.js +83 -0
- package/dist/integrations/grok/hooks/pre-tool-use.js +134 -0
- package/dist/integrations/grok/plugin/0xray/.mcp.json +15 -0
- package/dist/integrations/grok/plugin/0xray/hooks/hooks.json +30 -0
- package/dist/integrations/hermes-agent/__init__.py +718 -0
- package/dist/integrations/hermes-agent/after-install.md +71 -0
- package/dist/integrations/hermes-agent/bridge.mjs +861 -0
- package/dist/integrations/hermes-agent/conftest.py +14 -0
- package/dist/integrations/hermes-agent/plugin.yaml +12 -0
- package/dist/integrations/hermes-agent/schemas.py +100 -0
- package/dist/integrations/hermes-agent/test_plugin.py +1100 -0
- package/dist/integrations/hermes-agent/tools.py +253 -0
- package/dist/integrations/openclaw/README.md +134 -0
- package/dist/integrations/openclaw/api-server.js +389 -0
- package/dist/integrations/openclaw/client.js +492 -0
- package/dist/integrations/openclaw/config.js +374 -0
- package/dist/integrations/openclaw/hooks/strray-hooks.js +280 -0
- package/dist/integrations/openclaw/index.js +351 -0
- package/dist/integrations/openclaw/types.js +153 -0
- package/dist/integrations/plugins/index.js +10 -0
- package/dist/integrations/plugins/plugin-integration.js +606 -0
- package/dist/integrations/plugins/plugin-registry.js +580 -0
- package/dist/mcps/agent-resolver.js +106 -0
- package/dist/mcps/architect-tools.server.js +277 -0
- package/dist/mcps/auto-format.server.js +413 -0
- package/dist/mcps/boot-orchestrator.server.js +853 -0
- package/dist/mcps/config/config-loader.js +103 -0
- package/dist/mcps/config/config-validator.js +101 -0
- package/dist/mcps/config/index.js +30 -0
- package/dist/mcps/config/plugin-server-registry.js +223 -0
- package/dist/mcps/config/server-config-registry.js +348 -0
- package/dist/mcps/connection/connection-manager.js +79 -0
- package/dist/mcps/connection/connection-pool.js +164 -0
- package/dist/mcps/connection/mcp-connection.js +233 -0
- package/dist/mcps/connection/process-spawner.js +34 -0
- package/dist/mcps/enforcer-tools.server.js +778 -0
- package/dist/mcps/estimation.server.js +192 -0
- package/dist/mcps/framework-compliance-audit.server.js +500 -0
- package/dist/mcps/framework-help.server.js +400 -0
- package/dist/mcps/governance.server.js +464 -0
- package/dist/mcps/in-process-skill-registry.js +48 -0
- package/dist/mcps/knowledge-skills/api-design.server.js +123 -0
- package/dist/mcps/knowledge-skills/architecture-patterns.server.js +113 -0
- package/dist/mcps/knowledge-skills/bug-triage-specialist.server.js +474 -0
- package/dist/mcps/knowledge-skills/code-analyzer.server.js +605 -0
- package/dist/mcps/knowledge-skills/code-review.server.js +847 -0
- package/dist/mcps/knowledge-skills/content-creator.server.js +256 -0
- package/dist/mcps/knowledge-skills/database-design.server.js +822 -0
- package/dist/mcps/knowledge-skills/devops-deployment.server.js +1180 -0
- package/dist/mcps/knowledge-skills/git-workflow.server.js +115 -0
- package/dist/mcps/knowledge-skills/growth-strategist.server.js +361 -0
- package/dist/mcps/knowledge-skills/log-monitor.server.js +451 -0
- package/dist/mcps/knowledge-skills/mobile-development.server.js +525 -0
- package/dist/mcps/knowledge-skills/multimodal-looker.server.js +1063 -0
- package/dist/mcps/knowledge-skills/performance-optimization.server.js +1587 -0
- package/dist/mcps/knowledge-skills/project-analysis.server.js +811 -0
- package/dist/mcps/knowledge-skills/refactoring-strategies.server.js +796 -0
- package/dist/mcps/knowledge-skills/security-audit.server.js +846 -0
- package/dist/mcps/knowledge-skills/seo-consultant.server.js +937 -0
- package/dist/mcps/knowledge-skills/session-management.server.js +470 -0
- package/dist/mcps/knowledge-skills/skill-invocation.server.js +729 -0
- package/dist/mcps/knowledge-skills/strategist.server.js +217 -0
- package/dist/mcps/knowledge-skills/tech-writer.server.js +1191 -0
- package/dist/mcps/knowledge-skills/testing-best-practices.server.js +866 -0
- package/dist/mcps/knowledge-skills/testing-strategy.server.js +827 -0
- package/dist/mcps/knowledge-skills/ui-ux-design.server.js +1538 -0
- package/dist/mcps/lint.server.js +381 -0
- package/dist/mcps/mcp-client.js +574 -0
- package/dist/mcps/model-health-check.server.js +228 -0
- package/dist/mcps/orchestrator/config/agent-capabilities.js +87 -0
- package/dist/mcps/orchestrator/execution/execution-planner.js +279 -0
- package/dist/mcps/orchestrator/handlers/complexity-handler.js +94 -0
- package/dist/mcps/orchestrator/handlers/status-handler.js +232 -0
- package/dist/mcps/orchestrator/handlers/task-handler.js +197 -0
- package/dist/mcps/orchestrator/server.js +305 -0
- package/dist/mcps/orchestrator/types.js +6 -0
- package/dist/mcps/orchestrator.server.js +19 -0
- package/dist/mcps/performance-analysis.server.js +519 -0
- package/dist/mcps/processor-pipeline.server.js +561 -0
- package/dist/mcps/protocol/protocol-constants.js +46 -0
- package/dist/mcps/registry.json +110 -0
- package/dist/mcps/researcher.server.js +504 -0
- package/dist/mcps/security-scan.server.js +531 -0
- package/dist/mcps/simulation/index.js +12 -0
- package/dist/mcps/simulation/server-simulations.js +219 -0
- package/dist/mcps/simulation/simulation-engine.js +96 -0
- package/dist/mcps/state-manager.server.js +637 -0
- package/dist/mcps/tools/index.js +14 -0
- package/dist/mcps/tools/tool-cache.js +112 -0
- package/dist/mcps/tools/tool-discovery.js +65 -0
- package/dist/mcps/tools/tool-executor.js +75 -0
- package/dist/mcps/tools/tool-registry.js +67 -0
- package/dist/mcps/types/index.js +15 -0
- package/dist/mcps/types/json-rpc.types.js +7 -0
- package/dist/mcps/types/mcp.types.js +7 -0
- package/dist/metrics/agent-metrics.js +574 -0
- package/dist/metrics/index.js +6 -0
- package/dist/monitoring/advanced-profiler.js +232 -0
- package/dist/monitoring/memory-monitor.js +315 -0
- package/dist/monitoring/nudge-watchdog.js +356 -0
- package/dist/monitoring/test-auto-generation-monitor.js +157 -0
- package/dist/orchestrator/agent-spawn-governor.js +559 -0
- package/dist/orchestrator/enhanced-multi-agent-orchestrator.js +399 -0
- package/dist/orchestrator/intelligent-commit-batcher.js +353 -0
- package/dist/orchestrator/multi-agent-orchestration-coordinator.js +456 -0
- package/dist/orchestrator/orchestrator.js +657 -0
- package/dist/orchestrator/self-direction-activation.js +245 -0
- package/dist/orchestrator/universal-librarian-consultation.js +216 -0
- package/dist/orchestrator/universal-registry-bridge.js +247 -0
- package/dist/performance/performance-budget-enforcer.js +434 -0
- package/dist/performance/performance-regression-tester.js +342 -0
- package/dist/plugin/xray-codex-injection.js +857 -0
- package/dist/postprocessor/PostProcessor.js +1048 -0
- package/dist/postprocessor/analysis/FailureAnalysisEngine.js +245 -0
- package/dist/postprocessor/autofix/AutoFixEngine.js +254 -0
- package/dist/postprocessor/autofix/FixValidator.js +56 -0
- package/dist/postprocessor/config.js +65 -0
- package/dist/postprocessor/escalation/EscalationEngine.js +492 -0
- package/dist/postprocessor/monitoring/MonitoringEngine.js +125 -0
- package/dist/postprocessor/redeploy/RedeployCoordinator.js +342 -0
- package/dist/postprocessor/services/RegressionAnalysisService.js +131 -0
- package/dist/postprocessor/success/SuccessHandler.js +134 -0
- package/dist/postprocessor/triggers/APITrigger.js +115 -0
- package/dist/postprocessor/triggers/GitHookTrigger.js +551 -0
- package/dist/postprocessor/triggers/WebhookTrigger.js +211 -0
- package/dist/postprocessor/types.js +4 -0
- package/dist/processors/doc-write-guard.js +46 -0
- package/dist/processors/implementations/agents-md-validation-processor.js +286 -0
- package/dist/processors/implementations/async-pattern-processor.js +158 -0
- package/dist/processors/implementations/codex-compliance-processor.js +57 -0
- package/dist/processors/implementations/commit-batcher-processor.js +71 -0
- package/dist/processors/implementations/console-log-guard-processor.js +163 -0
- package/dist/processors/implementations/coverage-analysis-processor.js +138 -0
- package/dist/processors/implementations/error-boundary-processor.js +44 -0
- package/dist/processors/implementations/inference-improvement-processor.js +270 -0
- package/dist/processors/implementations/log-protection-processor.js +118 -0
- package/dist/processors/implementations/nudge-processor.js +130 -0
- package/dist/processors/implementations/performance-budget-processor.js +217 -0
- package/dist/processors/implementations/postprocessor-chain-validator.js +149 -0
- package/dist/processors/implementations/pre-validate-processor.js +18 -0
- package/dist/processors/implementations/publish-preflight-processor.js +249 -0
- package/dist/processors/implementations/refactoring-logging-processor-wrapper.js +33 -0
- package/dist/processors/implementations/refactoring-logging-processor.js +96 -0
- package/dist/processors/implementations/regression-testing-processor.js +59 -0
- package/dist/processors/implementations/session-capture-processor.js +37 -0
- package/dist/processors/implementations/session-summary-processor.js +130 -0
- package/dist/processors/implementations/spawn-governance-processor.js +219 -0
- package/dist/processors/implementations/state-validation-processor.js +15 -0
- package/dist/processors/implementations/storytelling-trigger-processor.js +589 -0
- package/dist/processors/implementations/test-auto-creation-processor.js +484 -0
- package/dist/processors/implementations/test-execution-processor.js +132 -0
- package/dist/processors/implementations/typescript-compilation-processor.js +87 -0
- package/dist/processors/implementations/version-compliance-processor.js +350 -0
- package/dist/processors/processor-interfaces.js +126 -0
- package/dist/processors/processor-manager.js +826 -0
- package/dist/processors/processor-types.js +12 -0
- package/dist/public/about.html +228 -0
- package/dist/public/enterprise.html +27 -0
- package/dist/public/features.html +102 -0
- package/dist/public/index.html +145 -0
- package/dist/reporting/framework-reporting-system.js +187 -0
- package/dist/reporting/log-parser.js +281 -0
- package/dist/reporting/metrics.js +202 -0
- package/dist/reporting/report-formatter.js +146 -0
- package/dist/reporting/types.js +1 -0
- package/dist/scripts/activate-kernel-pipeline.js +101 -0
- package/dist/scripts/integration.js +234 -0
- package/dist/scripts/pre-command +26 -0
- package/dist/scripts/pre-command.mjs +358 -0
- package/dist/security/comprehensive-security-audit.js +1005 -0
- package/dist/security/index.js +13 -0
- package/dist/security/prompt-security-validator.js +148 -0
- package/dist/security/security-agent-coordinator.js +204 -0
- package/dist/security/security-auditor.js +584 -0
- package/dist/security/security-hardener.js +170 -0
- package/dist/security/security-hardening-system.js +727 -0
- package/dist/security/security-headers.js +118 -0
- package/dist/security/security-orchestration-layer.js +496 -0
- package/dist/security/security-scanner.js +429 -0
- package/dist/services/inference-tuner.js +301 -0
- package/dist/session/index.js +3 -0
- package/dist/session/session-cleanup-manager.js +366 -0
- package/dist/session/session-monitor.js +503 -0
- package/dist/session/session-state-manager.js +522 -0
- package/dist/skills/api-design/SKILL.md +37 -0
- package/dist/skills/architect-tools/SKILL.md +37 -0
- package/dist/skills/architecture-patterns/SKILL.md +37 -0
- package/dist/skills/auto-format/SKILL.md +37 -0
- package/dist/skills/backend-engineer/SKILL.md +49 -0
- package/dist/skills/boot-orchestrator/SKILL.md +37 -0
- package/dist/skills/bug-triage/SKILL.md +43 -0
- package/dist/skills/code-analyzer/SKILL.md +45 -0
- package/dist/skills/code-review/SKILL.md +52 -0
- package/dist/skills/content-creator/SKILL.md +38 -0
- package/dist/skills/database-engineer/SKILL.md +46 -0
- package/dist/skills/devops-engineer/SKILL.md +49 -0
- package/dist/skills/enforcer/SKILL.md +37 -0
- package/dist/skills/framework-compliance-audit/SKILL.md +37 -0
- package/dist/skills/frontend-engineer/SKILL.md +49 -0
- package/dist/skills/frontend-ui-ux-engineer/SKILL.md +41 -0
- package/dist/skills/git-workflow/SKILL.md +37 -0
- package/dist/skills/growth-strategist/SKILL.md +48 -0
- package/dist/skills/hermes-agent/SKILL.md +212 -0
- package/dist/skills/inference-improve/SKILL.md +97 -0
- package/dist/skills/lint/SKILL.md +37 -0
- package/dist/skills/log-monitor/SKILL.md +44 -0
- package/dist/skills/mobile-developer/SKILL.md +42 -0
- package/dist/skills/model-health-check/SKILL.md +37 -0
- package/dist/skills/multimodal-looker/SKILL.md +45 -0
- package/dist/skills/orchestrator/SKILL.md +37 -0
- package/dist/skills/performance-analysis/SKILL.md +37 -0
- package/dist/skills/performance-engineer/SKILL.md +41 -0
- package/dist/skills/performance-optimization/SKILL.md +37 -0
- package/dist/skills/processor-pipeline/SKILL.md +37 -0
- package/dist/skills/project-analysis/SKILL.md +42 -0
- package/dist/skills/refactoring-strategies/SKILL.md +37 -0
- package/dist/skills/registry.json +66 -0
- package/dist/skills/researcher/SKILL.md +37 -0
- package/dist/skills/security-audit/SKILL.md +48 -0
- package/dist/skills/security-scan/SKILL.md +37 -0
- package/dist/skills/seo-consultant/SKILL.md +43 -0
- package/dist/skills/session-management/SKILL.md +36 -0
- package/dist/skills/state-manager/SKILL.md +37 -0
- package/dist/skills/storyteller/SKILL.md +130 -0
- package/dist/skills/strategist/SKILL.md +32 -0
- package/dist/skills/tech-writer/SKILL.md +37 -0
- package/dist/skills/testing-best-practices/SKILL.md +37 -0
- package/dist/skills/testing-strategy/SKILL.md +43 -0
- package/dist/skills/ui-ux-design/SKILL.md +603 -0
- package/dist/state/context-providers.js +1 -0
- package/dist/state/index.js +7 -0
- package/dist/state/state-manager.js +208 -0
- package/dist/state/state-types.js +1 -0
- package/dist/testing/memory-regression-suite.js +258 -0
- package/dist/utils/batch-operations.js +292 -0
- package/dist/utils/codex-parser.js +445 -0
- package/dist/utils/command-runner.js +96 -0
- package/dist/utils/import-resolver.js +189 -0
- package/dist/utils/language-detector.js +383 -0
- package/dist/utils/path-resolver.js +112 -0
- package/dist/utils/shutdown-handler.js +75 -0
- package/dist/utils/test-template-generator.js +178 -0
- package/dist/utils/token-manager.js +163 -0
- package/dist/validation/estimation-validator.js +241 -0
- package/dist/validation/report-content-validator.js +218 -0
- package/opencode.json +153 -0
- package/package.json +170 -0
- package/scripts/helpers/resolve-config-path.cjs +57 -0
- package/scripts/helpers/resolve-config-path.mjs +73 -0
- package/scripts/hooks/pre-command +26 -0
- package/scripts/hooks/pre-command.mjs +358 -0
- package/scripts/hooks/run-hook.js +570 -0
- package/scripts/mjs/test-consumer-readiness.mjs +273 -0
- package/scripts/mjs/test-mcp-functionality.mjs +507 -0
- package/scripts/mjs/validate-mcp-connectivity.cjs +75 -0
- package/scripts/mjs/validate-postinstall-config.mjs +308 -0
- package/scripts/node/auto-reflection-generator.mjs +496 -0
- package/scripts/node/basic-security-audit.cjs +338 -0
- package/scripts/node/ci-cd-auto-fix.cjs +263 -0
- package/scripts/node/ci-report-generator.mjs +227 -0
- package/scripts/node/enforce-agents-md.mjs +420 -0
- package/scripts/node/enforce-version-compliance.sh +22 -0
- package/scripts/node/enforce-version-compliance.ts +126 -0
- package/scripts/node/github-actions-monitor.cjs +23 -0
- package/scripts/node/govern-reflection.mjs +160 -0
- package/scripts/node/postinstall.cjs +78 -0
- package/scripts/node/pre-publish-guard.js +267 -0
- package/scripts/node/prepare-consumer.cjs +143 -0
- package/scripts/node/reflection-processor.cjs +213 -0
- package/scripts/node/reflection-validate.sh +194 -0
- package/scripts/node/release-tweet.mjs +39 -0
- package/scripts/node/release.js +159 -0
- package/scripts/node/release.mjs +213 -0
- package/scripts/node/setup-dev.cjs +83 -0
- package/scripts/node/setup.cjs +214 -0
- package/scripts/node/sync-versions.mjs +140 -0
- package/scripts/node/universal-version-manager.js +1025 -0
- package/scripts/node/validate-external-processes.js +265 -0
- package/scripts/node/validate-mcp-connectivity.js +258 -0
- package/scripts/node/version-manager.mjs +524 -0
- package/scripts/validate-stringray-comprehensive.js +636 -0
- package/src/integrations/grok/plugin/0xray/.mcp.json +15 -0
- package/src/integrations/grok/plugin/0xray/hooks/hooks.json +30 -0
- package/src/mcps/agent-resolver.ts +168 -0
- package/src/mcps/architect-tools.server.ts +343 -0
- package/src/mcps/auto-format.server.ts +529 -0
- package/src/mcps/boot-orchestrator.server.ts +1082 -0
- package/src/mcps/config/__tests__/config-loader.test.ts +338 -0
- package/src/mcps/config/__tests__/config-validator.test.ts +646 -0
- package/src/mcps/config/__tests__/server-config-registry.test.ts +257 -0
- package/src/mcps/config/config-loader.ts +127 -0
- package/src/mcps/config/config-validator.ts +127 -0
- package/src/mcps/config/index.ts +32 -0
- package/src/mcps/config/plugin-server-registry.ts +335 -0
- package/src/mcps/config/server-config-registry.ts +395 -0
- package/src/mcps/connection/connection-manager.ts +91 -0
- package/src/mcps/connection/connection-pool.ts +216 -0
- package/src/mcps/connection/mcp-connection.ts +327 -0
- package/src/mcps/connection/process-spawner.ts +47 -0
- package/src/mcps/enforcer-tools.server.ts +1106 -0
- package/src/mcps/estimation.server.ts +229 -0
- package/src/mcps/framework-compliance-audit.server.ts +635 -0
- package/src/mcps/framework-help.server.ts +467 -0
- package/src/mcps/governance.server.ts +551 -0
- package/src/mcps/in-process-skill-registry.ts +79 -0
- package/src/mcps/knowledge-skills/api-design.server.test.ts +41 -0
- package/src/mcps/knowledge-skills/api-design.server.ts +160 -0
- package/src/mcps/knowledge-skills/architecture-patterns.server.ts +152 -0
- package/src/mcps/knowledge-skills/bug-triage-specialist.server.ts +624 -0
- package/src/mcps/knowledge-skills/code-analyzer.server.test.ts +129 -0
- package/src/mcps/knowledge-skills/code-analyzer.server.ts +591 -0
- package/src/mcps/knowledge-skills/code-review.server.ts +1132 -0
- package/src/mcps/knowledge-skills/content-creator.server.ts +300 -0
- package/src/mcps/knowledge-skills/database-design.server.ts +1200 -0
- package/src/mcps/knowledge-skills/devops-deployment.server.ts +1622 -0
- package/src/mcps/knowledge-skills/git-workflow.server.ts +152 -0
- package/src/mcps/knowledge-skills/growth-strategist.server.ts +413 -0
- package/src/mcps/knowledge-skills/log-monitor.server.ts +619 -0
- package/src/mcps/knowledge-skills/mobile-development.server.ts +672 -0
- package/src/mcps/knowledge-skills/multimodal-looker.server.ts +1500 -0
- package/src/mcps/knowledge-skills/performance-optimization.server.ts +2065 -0
- package/src/mcps/knowledge-skills/project-analysis.server.ts +1111 -0
- package/src/mcps/knowledge-skills/refactoring-strategies.server.ts +1092 -0
- package/src/mcps/knowledge-skills/security-audit.server.test.ts +112 -0
- package/src/mcps/knowledge-skills/security-audit.server.ts +1193 -0
- package/src/mcps/knowledge-skills/seo-consultant.server.ts +1160 -0
- package/src/mcps/knowledge-skills/session-management.server.ts +576 -0
- package/src/mcps/knowledge-skills/skill-invocation.server.ts +941 -0
- package/src/mcps/knowledge-skills/strategist.server.ts +267 -0
- package/src/mcps/knowledge-skills/tech-writer.server.ts +1638 -0
- package/src/mcps/knowledge-skills/testing-best-practices.server.test.ts +136 -0
- package/src/mcps/knowledge-skills/testing-best-practices.server.ts +1232 -0
- package/src/mcps/knowledge-skills/testing-strategy.server.test.ts +100 -0
- package/src/mcps/knowledge-skills/testing-strategy.server.ts +1172 -0
- package/src/mcps/knowledge-skills/ui-ux-design.server.ts +2076 -0
- package/src/mcps/lint.server.ts +483 -0
- package/src/mcps/mcp-client.ts +706 -0
- package/src/mcps/model-health-check.server.ts +292 -0
- package/src/mcps/orchestrator/config/agent-capabilities.ts +108 -0
- package/src/mcps/orchestrator/execution/execution-planner.ts +353 -0
- package/src/mcps/orchestrator/handlers/complexity-handler.ts +125 -0
- package/src/mcps/orchestrator/handlers/status-handler.ts +295 -0
- package/src/mcps/orchestrator/handlers/task-handler.ts +268 -0
- package/src/mcps/orchestrator/server.ts +388 -0
- package/src/mcps/orchestrator/types.ts +81 -0
- package/src/mcps/orchestrator.server.ts +34 -0
- package/src/mcps/performance-analysis.server.ts +715 -0
- package/src/mcps/processor-pipeline.server.ts +778 -0
- package/src/mcps/protocol/protocol-constants.ts +51 -0
- package/src/mcps/registry.json +110 -0
- package/src/mcps/researcher.server.ts +595 -0
- package/src/mcps/security-scan.server.ts +651 -0
- package/src/mcps/simulation/__tests__/simulation-engine.test.ts +275 -0
- package/src/mcps/simulation/index.ts +23 -0
- package/src/mcps/simulation/server-simulations.ts +241 -0
- package/src/mcps/simulation/simulation-engine.ts +126 -0
- package/src/mcps/state-manager.server.ts +777 -0
- package/src/mcps/tools/__tests__/tool-cache.test.ts +205 -0
- package/src/mcps/tools/__tests__/tool-discovery.test.ts +189 -0
- package/src/mcps/tools/__tests__/tool-executor.test.ts +215 -0
- package/src/mcps/tools/__tests__/tool-registry.test.ts +230 -0
- package/src/mcps/tools/index.ts +15 -0
- package/src/mcps/tools/tool-cache.ts +145 -0
- package/src/mcps/tools/tool-discovery.ts +83 -0
- package/src/mcps/tools/tool-executor.ts +106 -0
- package/src/mcps/tools/tool-registry.ts +78 -0
- package/src/mcps/types/__tests__/types.test.ts +341 -0
- package/src/mcps/types/index.ts +17 -0
- package/src/mcps/types/json-rpc.types.ts +38 -0
- package/src/mcps/types/mcp.types.ts +115 -0
- package/src/opencode/agents/api-design.yml +31 -0
- package/src/opencode/agents/architect.yml +15 -0
- package/src/opencode/agents/architecture-patterns.yml +14 -0
- package/src/opencode/agents/auto-format.yml +14 -0
- package/src/opencode/agents/backend-engineer.yml +12 -0
- package/src/opencode/agents/boot-orchestrator.yml +14 -0
- package/src/opencode/agents/bug-triage-specialist.yml +15 -0
- package/src/opencode/agents/code-analyzer.yml +12 -0
- package/src/opencode/agents/code-reviewer.yml +14 -0
- package/src/opencode/agents/content-creator.yml +12 -0
- package/src/opencode/agents/database-engineer.yml +12 -0
- package/src/opencode/agents/devops-engineer.yml +12 -0
- package/src/opencode/agents/framework-compliance-audit.yml +14 -0
- package/src/opencode/agents/frontend-engineer.yml +12 -0
- package/src/opencode/agents/frontend-ui-ux-engineer.yml +12 -0
- package/src/opencode/agents/git-workflow.yml +15 -0
- package/src/opencode/agents/growth-strategist.yml +12 -0
- package/src/opencode/agents/hermes-agent.yml +12 -0
- package/src/opencode/agents/inference-improve.yml +12 -0
- package/src/opencode/agents/lint.yml +14 -0
- package/src/opencode/agents/log-monitor.yml +12 -0
- package/src/opencode/agents/mobile-developer.yml +12 -0
- package/src/opencode/agents/model-health-check.yml +12 -0
- package/src/opencode/agents/multimodal-looker.yml +12 -0
- package/src/opencode/agents/performance-analysis.yml +12 -0
- package/src/opencode/agents/performance-engineer.yml +12 -0
- package/src/opencode/agents/performance-optimization.yml +12 -0
- package/src/opencode/agents/processor-pipeline.yml +14 -0
- package/src/opencode/agents/project-analysis.yml +12 -0
- package/src/opencode/agents/refactorer.yml +12 -0
- package/src/opencode/agents/researcher.yml +12 -0
- package/src/opencode/agents/security-auditor.yml +12 -0
- package/src/opencode/agents/security-scan.yml +12 -0
- package/src/opencode/agents/seo-consultant.yml +12 -0
- package/src/opencode/agents/session-management.yml +12 -0
- package/src/opencode/agents/state-manager.yml +12 -0
- package/src/opencode/agents/storyteller.yml +12 -0
- package/src/opencode/agents/strategist.yml +12 -0
- package/src/opencode/agents/tech-writer.yml +12 -0
- package/src/opencode/agents/testing-best-practices.yml +12 -0
- package/src/opencode/agents/testing-lead.yml +12 -0
- package/src/opencode/agents/ui-ux-design.yml +12 -0
- package/src/opencode/codex.codex +8 -0
- package/src/opencode/commands/auto-format.md +99 -0
- package/src/opencode/commands/auto-summary-capture.md +90 -0
- package/src/opencode/commands/dependency-audit.md +184 -0
- package/src/opencode/commands/enforcer-daily-scan.md +137 -0
- package/src/opencode/commands/framework-compliance-audit.md +205 -0
- package/src/opencode/commands/interactive-validator.md +75 -0
- package/src/opencode/commands/job-summary-logger.md +68 -0
- package/src/opencode/commands/lint.md +11 -0
- package/src/opencode/commands/mode-switch.md +95 -0
- package/src/opencode/commands/model-health-check.md +186 -0
- package/src/opencode/commands/performance-analysis.md +144 -0
- package/src/opencode/commands/pre-commit-introspection.md +185 -0
- package/src/opencode/commands/pre-commit-introspection.sh +133 -0
- package/src/opencode/commands/security-scan.md +157 -0
- package/src/opencode/commands/sisyphus-validation.md +128 -0
- package/src/opencode/commands/summary-logger.md +83 -0
- package/src/opencode/enforcer-config.json +285 -0
- package/src/opencode/openclaw/config.json +25 -0
- package/src/opencode/workflows/post-deployment-audit.yml +123 -0
- package/src/skills/api-design/SKILL.md +37 -0
- package/src/skills/architect-tools/SKILL.md +37 -0
- package/src/skills/architecture-patterns/SKILL.md +37 -0
- package/src/skills/auto-format/SKILL.md +37 -0
- package/src/skills/backend-engineer/SKILL.md +49 -0
- package/src/skills/boot-orchestrator/SKILL.md +37 -0
- package/src/skills/bug-triage/SKILL.md +43 -0
- package/src/skills/code-analyzer/SKILL.md +45 -0
- package/src/skills/code-review/SKILL.md +52 -0
- package/src/skills/content-creator/SKILL.md +38 -0
- package/src/skills/database-engineer/SKILL.md +46 -0
- package/src/skills/devops-engineer/SKILL.md +49 -0
- package/src/skills/enforcer/SKILL.md +37 -0
- package/src/skills/framework-compliance-audit/SKILL.md +37 -0
- package/src/skills/frontend-engineer/SKILL.md +49 -0
- package/src/skills/frontend-ui-ux-engineer/SKILL.md +41 -0
- package/src/skills/git-workflow/SKILL.md +37 -0
- package/src/skills/growth-strategist/SKILL.md +48 -0
- package/src/skills/hermes-agent/SKILL.md +212 -0
- package/src/skills/inference-improve/SKILL.md +97 -0
- package/src/skills/lint/SKILL.md +37 -0
- package/src/skills/log-monitor/SKILL.md +44 -0
- package/src/skills/mobile-developer/SKILL.md +42 -0
- package/src/skills/model-health-check/SKILL.md +37 -0
- package/src/skills/multimodal-looker/SKILL.md +45 -0
- package/src/skills/orchestrator/SKILL.md +37 -0
- package/src/skills/performance-analysis/SKILL.md +37 -0
- package/src/skills/performance-engineer/SKILL.md +41 -0
- package/src/skills/performance-optimization/SKILL.md +37 -0
- package/src/skills/processor-pipeline/SKILL.md +37 -0
- package/src/skills/project-analysis/SKILL.md +42 -0
- package/src/skills/refactoring-strategies/SKILL.md +37 -0
- package/src/skills/registry.json +66 -0
- package/src/skills/researcher/SKILL.md +37 -0
- package/src/skills/security-audit/SKILL.md +48 -0
- package/src/skills/security-scan/SKILL.md +37 -0
- package/src/skills/seo-consultant/SKILL.md +43 -0
- package/src/skills/session-management/SKILL.md +36 -0
- package/src/skills/state-manager/SKILL.md +37 -0
- package/src/skills/storyteller/SKILL.md +130 -0
- package/src/skills/strategist/SKILL.md +32 -0
- package/src/skills/tech-writer/SKILL.md +37 -0
- package/src/skills/testing-best-practices/SKILL.md +37 -0
- package/src/skills/testing-strategy/SKILL.md +43 -0
- package/src/skills/ui-ux-design/SKILL.md +603 -0
|
@@ -0,0 +1,2076 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* xray UI/UX Design MCP Server
|
|
3
|
+
*
|
|
4
|
+
* Knowledge skill for user interface and user experience design,
|
|
5
|
+
* component patterns, accessibility compliance, and design system guidance
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
9
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
10
|
+
import {
|
|
11
|
+
CallToolRequestSchema,
|
|
12
|
+
ListToolsRequestSchema,
|
|
13
|
+
type CallToolResult,
|
|
14
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
15
|
+
import { frameworkLogger } from "../../core/framework-logger.js";
|
|
16
|
+
|
|
17
|
+
interface UIDesignAnalysis {
|
|
18
|
+
component: string;
|
|
19
|
+
issues: UIIssue[];
|
|
20
|
+
accessibilityScore: number;
|
|
21
|
+
usabilityScore: number;
|
|
22
|
+
recommendations: string[];
|
|
23
|
+
designPatterns: string[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface UIIssue {
|
|
27
|
+
type:
|
|
28
|
+
| "accessibility"
|
|
29
|
+
| "usability"
|
|
30
|
+
| "performance"
|
|
31
|
+
| "responsive"
|
|
32
|
+
| "semantic";
|
|
33
|
+
severity: "critical" | "high" | "medium" | "low";
|
|
34
|
+
element?: string;
|
|
35
|
+
description: string;
|
|
36
|
+
wcag?: string; // WCAG guideline reference
|
|
37
|
+
recommendation: string;
|
|
38
|
+
codeSnippet?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface DesignSystem {
|
|
42
|
+
colors: ColorScheme;
|
|
43
|
+
typography: TypographyScale;
|
|
44
|
+
spacing: SpacingScale;
|
|
45
|
+
components: ComponentLibrary;
|
|
46
|
+
patterns: DesignPattern[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface ColorScheme {
|
|
50
|
+
primary: string[];
|
|
51
|
+
secondary: string[];
|
|
52
|
+
semantic: {
|
|
53
|
+
success: string;
|
|
54
|
+
warning: string;
|
|
55
|
+
error: string;
|
|
56
|
+
info: string;
|
|
57
|
+
};
|
|
58
|
+
contrastRatios: Record<string, number>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
interface TypographyScale {
|
|
62
|
+
fontFamilies: string[];
|
|
63
|
+
sizes: Record<string, string>;
|
|
64
|
+
weights: Record<string, number>;
|
|
65
|
+
lineHeights: Record<string, number>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
interface SpacingScale {
|
|
69
|
+
base: number;
|
|
70
|
+
scale: number[];
|
|
71
|
+
names: Record<string, number>;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
interface ComponentLibrary {
|
|
75
|
+
buttons: ComponentVariant[];
|
|
76
|
+
inputs: ComponentVariant[];
|
|
77
|
+
navigation: ComponentVariant[];
|
|
78
|
+
feedback: ComponentVariant[];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
interface ComponentVariant {
|
|
82
|
+
name: string;
|
|
83
|
+
states: string[];
|
|
84
|
+
accessibility: string[];
|
|
85
|
+
responsive: boolean;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
interface DesignPattern {
|
|
89
|
+
name: string;
|
|
90
|
+
category: "layout" | "navigation" | "interaction" | "content";
|
|
91
|
+
description: string;
|
|
92
|
+
useCases: string[];
|
|
93
|
+
accessibility: string[];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
interface AnalyzeUIComponentArgs {
|
|
97
|
+
componentCode: string;
|
|
98
|
+
framework: string;
|
|
99
|
+
checkAccessibility?: boolean;
|
|
100
|
+
checkResponsive?: boolean;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
interface DesignComponentArgs {
|
|
104
|
+
componentType: string;
|
|
105
|
+
requirements: string;
|
|
106
|
+
framework: string;
|
|
107
|
+
accessibility?: boolean;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
interface AuditAccessibilityArgs {
|
|
111
|
+
htmlContent: string;
|
|
112
|
+
cssContent?: string;
|
|
113
|
+
wcagLevel?: string;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
interface GenerateDesignSystemArgs {
|
|
117
|
+
brandGuidelines: string;
|
|
118
|
+
targetAudience?: string;
|
|
119
|
+
platform: string;
|
|
120
|
+
includeAccessibility?: boolean;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
interface ValidateMobileDesignArgs {
|
|
124
|
+
componentCode: string;
|
|
125
|
+
viewportWidth?: number;
|
|
126
|
+
framework?: string;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
interface AnalyzeVisualHierarchyArgs {
|
|
130
|
+
designCode: string;
|
|
131
|
+
pageType?: string;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
interface RecommendImagesArgs {
|
|
135
|
+
context: string;
|
|
136
|
+
style?: string;
|
|
137
|
+
budget?: string;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
interface ComponentDesign {
|
|
141
|
+
componentType: string;
|
|
142
|
+
requirements: string;
|
|
143
|
+
framework: string;
|
|
144
|
+
accessibility: boolean;
|
|
145
|
+
structure: string[];
|
|
146
|
+
props: string[];
|
|
147
|
+
states: string[];
|
|
148
|
+
variants: string[];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
interface WCAGViolation {
|
|
152
|
+
guideline: string;
|
|
153
|
+
severity: string;
|
|
154
|
+
description: string;
|
|
155
|
+
recommendation?: string;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
interface MobileDesignIssue {
|
|
159
|
+
type: string;
|
|
160
|
+
severity: string;
|
|
161
|
+
message: string;
|
|
162
|
+
wcag?: string;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
interface HierarchyIssue {
|
|
166
|
+
type: string;
|
|
167
|
+
severity: string;
|
|
168
|
+
message: string;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
interface ImageLibrary {
|
|
172
|
+
name: string;
|
|
173
|
+
url: string;
|
|
174
|
+
description: string;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
interface ImageRecommendations {
|
|
178
|
+
libraries: ImageLibrary[];
|
|
179
|
+
tips: string[];
|
|
180
|
+
style: string;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
interface ToolResponse {
|
|
184
|
+
content: Array<{ type: "text"; text: string }>;
|
|
185
|
+
data?: unknown;
|
|
186
|
+
isError?: boolean;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
class StringRayUIUXDesignServer {
|
|
190
|
+
private server: Server;
|
|
191
|
+
|
|
192
|
+
constructor() {
|
|
193
|
+
this.server = new Server(
|
|
194
|
+
{
|
|
195
|
+
name: "ui-ux-design", version: "1.22.67",
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
capabilities: {
|
|
199
|
+
tools: {},
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
this.setupToolHandlers();
|
|
205
|
+
// Server initialization - removed unnecessary startup logging
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
private setupToolHandlers() {
|
|
209
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
210
|
+
return {
|
|
211
|
+
tools: [
|
|
212
|
+
{
|
|
213
|
+
name: "analyze_ui_component",
|
|
214
|
+
description:
|
|
215
|
+
"Analyze UI component for accessibility, usability, and design best practices",
|
|
216
|
+
inputSchema: {
|
|
217
|
+
type: "object",
|
|
218
|
+
properties: {
|
|
219
|
+
componentCode: {
|
|
220
|
+
type: "string",
|
|
221
|
+
description: "React/Vue/Angular component code to analyze",
|
|
222
|
+
},
|
|
223
|
+
framework: {
|
|
224
|
+
type: "string",
|
|
225
|
+
enum: ["react", "vue", "angular", "svelte"],
|
|
226
|
+
description: "UI framework being used",
|
|
227
|
+
},
|
|
228
|
+
checkAccessibility: {
|
|
229
|
+
type: "boolean",
|
|
230
|
+
description: "Include WCAG accessibility analysis",
|
|
231
|
+
default: true,
|
|
232
|
+
},
|
|
233
|
+
checkResponsive: {
|
|
234
|
+
type: "boolean",
|
|
235
|
+
description: "Include responsive design analysis",
|
|
236
|
+
default: true,
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
required: ["componentCode", "framework"],
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
name: "design_component",
|
|
244
|
+
description:
|
|
245
|
+
"Design a UI component with proper accessibility and UX patterns",
|
|
246
|
+
inputSchema: {
|
|
247
|
+
type: "object",
|
|
248
|
+
properties: {
|
|
249
|
+
componentType: {
|
|
250
|
+
type: "string",
|
|
251
|
+
enum: [
|
|
252
|
+
"button",
|
|
253
|
+
"input",
|
|
254
|
+
"modal",
|
|
255
|
+
"navigation",
|
|
256
|
+
"card",
|
|
257
|
+
"form",
|
|
258
|
+
],
|
|
259
|
+
description: "Type of component to design",
|
|
260
|
+
},
|
|
261
|
+
requirements: {
|
|
262
|
+
type: "string",
|
|
263
|
+
description: "Functional requirements and use cases",
|
|
264
|
+
},
|
|
265
|
+
framework: {
|
|
266
|
+
type: "string",
|
|
267
|
+
enum: ["react", "vue", "angular", "svelte"],
|
|
268
|
+
description: "Target UI framework",
|
|
269
|
+
},
|
|
270
|
+
accessibility: {
|
|
271
|
+
type: "boolean",
|
|
272
|
+
description: "Include accessibility features",
|
|
273
|
+
default: true,
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
required: ["componentType", "requirements", "framework"],
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
name: "audit_accessibility",
|
|
281
|
+
description:
|
|
282
|
+
"Perform comprehensive accessibility audit using WCAG guidelines",
|
|
283
|
+
inputSchema: {
|
|
284
|
+
type: "object",
|
|
285
|
+
properties: {
|
|
286
|
+
htmlContent: {
|
|
287
|
+
type: "string",
|
|
288
|
+
description: "HTML content to audit for accessibility",
|
|
289
|
+
},
|
|
290
|
+
cssContent: {
|
|
291
|
+
type: "string",
|
|
292
|
+
description: "CSS styles to check for accessibility",
|
|
293
|
+
},
|
|
294
|
+
wcagLevel: {
|
|
295
|
+
type: "string",
|
|
296
|
+
enum: ["A", "AA", "AAA"],
|
|
297
|
+
description: "WCAG conformance level to check",
|
|
298
|
+
default: "AA",
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
required: ["htmlContent"],
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
name: "generate_design_system",
|
|
306
|
+
description:
|
|
307
|
+
"Generate a comprehensive design system with colors, typography, and components",
|
|
308
|
+
inputSchema: {
|
|
309
|
+
type: "object",
|
|
310
|
+
properties: {
|
|
311
|
+
brandGuidelines: {
|
|
312
|
+
type: "string",
|
|
313
|
+
description: "Brand colors, fonts, and style guidelines",
|
|
314
|
+
},
|
|
315
|
+
targetAudience: {
|
|
316
|
+
type: "string",
|
|
317
|
+
description: "Target user demographics and preferences",
|
|
318
|
+
},
|
|
319
|
+
platform: {
|
|
320
|
+
type: "string",
|
|
321
|
+
enum: ["web", "mobile", "desktop"],
|
|
322
|
+
description: "Target platform",
|
|
323
|
+
},
|
|
324
|
+
includeAccessibility: {
|
|
325
|
+
type: "boolean",
|
|
326
|
+
description: "Include accessibility-compliant design tokens",
|
|
327
|
+
default: true,
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
required: ["brandGuidelines", "platform"],
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
name: "validate_mobile_design",
|
|
335
|
+
description:
|
|
336
|
+
"Validate mobile-first design principles including touch targets, responsive typography, and thumb zone optimization",
|
|
337
|
+
inputSchema: {
|
|
338
|
+
type: "object",
|
|
339
|
+
properties: {
|
|
340
|
+
componentCode: {
|
|
341
|
+
type: "string",
|
|
342
|
+
description: "Component code to validate for mobile",
|
|
343
|
+
},
|
|
344
|
+
viewportWidth: {
|
|
345
|
+
type: "number",
|
|
346
|
+
description:
|
|
347
|
+
"Minimum viewport width to validate (default: 320)",
|
|
348
|
+
default: 320,
|
|
349
|
+
},
|
|
350
|
+
framework: {
|
|
351
|
+
type: "string",
|
|
352
|
+
enum: ["react", "vue", "angular", "svelte", "css"],
|
|
353
|
+
description: "UI framework or CSS",
|
|
354
|
+
},
|
|
355
|
+
},
|
|
356
|
+
required: ["componentCode"],
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
name: "analyze_visual_hierarchy",
|
|
361
|
+
description:
|
|
362
|
+
"Analyze visual hierarchy and cognitive load following 'Don't Make Me Think' principles",
|
|
363
|
+
inputSchema: {
|
|
364
|
+
type: "object",
|
|
365
|
+
properties: {
|
|
366
|
+
designCode: {
|
|
367
|
+
type: "string",
|
|
368
|
+
description: "HTML/CSS/React code of the design to analyze",
|
|
369
|
+
},
|
|
370
|
+
pageType: {
|
|
371
|
+
type: "string",
|
|
372
|
+
enum: [
|
|
373
|
+
"landing",
|
|
374
|
+
"dashboard",
|
|
375
|
+
"form",
|
|
376
|
+
"content",
|
|
377
|
+
"ecommerce",
|
|
378
|
+
],
|
|
379
|
+
description: "Type of page being analyzed",
|
|
380
|
+
},
|
|
381
|
+
},
|
|
382
|
+
required: ["designCode"],
|
|
383
|
+
},
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
name: "recommend_images",
|
|
387
|
+
description:
|
|
388
|
+
"Recommend appropriate image libraries, styles, and optimization strategies for the design context",
|
|
389
|
+
inputSchema: {
|
|
390
|
+
type: "object",
|
|
391
|
+
properties: {
|
|
392
|
+
context: {
|
|
393
|
+
type: "string",
|
|
394
|
+
description:
|
|
395
|
+
"Design context (e.g., 'hero section', 'product gallery', 'team portraits')",
|
|
396
|
+
},
|
|
397
|
+
style: {
|
|
398
|
+
type: "string",
|
|
399
|
+
enum: [
|
|
400
|
+
"photography",
|
|
401
|
+
"illustration",
|
|
402
|
+
"3d",
|
|
403
|
+
"abstract",
|
|
404
|
+
"minimal",
|
|
405
|
+
],
|
|
406
|
+
description: "Preferred visual style",
|
|
407
|
+
},
|
|
408
|
+
budget: {
|
|
409
|
+
type: "string",
|
|
410
|
+
enum: ["free", "low", "premium"],
|
|
411
|
+
description: "Budget constraint",
|
|
412
|
+
default: "free",
|
|
413
|
+
},
|
|
414
|
+
},
|
|
415
|
+
required: ["context"],
|
|
416
|
+
},
|
|
417
|
+
},
|
|
418
|
+
],
|
|
419
|
+
};
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request): Promise<CallToolResult> => {
|
|
423
|
+
const { name, arguments: args } = request.params;
|
|
424
|
+
|
|
425
|
+
switch (name) {
|
|
426
|
+
case "analyze_ui_component":
|
|
427
|
+
return await this.analyzeUIComponent(args as unknown as AnalyzeUIComponentArgs) as CallToolResult;
|
|
428
|
+
case "design_component":
|
|
429
|
+
return await this.designComponent(args as unknown as DesignComponentArgs) as CallToolResult;
|
|
430
|
+
case "audit_accessibility":
|
|
431
|
+
return await this.auditAccessibility(args as unknown as AuditAccessibilityArgs) as CallToolResult;
|
|
432
|
+
case "generate_design_system":
|
|
433
|
+
return await this.generateDesignSystem(args as unknown as GenerateDesignSystemArgs) as CallToolResult;
|
|
434
|
+
case "validate_mobile_design":
|
|
435
|
+
return await this.validateMobileDesign(args as unknown as ValidateMobileDesignArgs) as CallToolResult;
|
|
436
|
+
case "analyze_visual_hierarchy":
|
|
437
|
+
return await this.analyzeVisualHierarchy(args as unknown as AnalyzeVisualHierarchyArgs) as CallToolResult;
|
|
438
|
+
case "recommend_images":
|
|
439
|
+
return await this.recommendImages(args as unknown as RecommendImagesArgs) as CallToolResult;
|
|
440
|
+
default:
|
|
441
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
private async analyzeUIComponent(args: AnalyzeUIComponentArgs): Promise<ToolResponse> {
|
|
447
|
+
const {
|
|
448
|
+
componentCode,
|
|
449
|
+
framework,
|
|
450
|
+
checkAccessibility = true,
|
|
451
|
+
checkResponsive = true,
|
|
452
|
+
} = args;
|
|
453
|
+
|
|
454
|
+
try {
|
|
455
|
+
const componentName = this.extractComponentName(componentCode, framework);
|
|
456
|
+
const issues = this.analyzeComponentCode(
|
|
457
|
+
componentCode,
|
|
458
|
+
framework,
|
|
459
|
+
checkAccessibility,
|
|
460
|
+
checkResponsive,
|
|
461
|
+
);
|
|
462
|
+
|
|
463
|
+
const accessibilityScore = this.calculateAccessibilityScore(issues);
|
|
464
|
+
const usabilityScore = this.calculateUsabilityScore(issues);
|
|
465
|
+
const recommendations = this.generateUIRecommendations(issues, framework);
|
|
466
|
+
const designPatterns = this.identifyDesignPatterns(
|
|
467
|
+
componentCode,
|
|
468
|
+
framework,
|
|
469
|
+
);
|
|
470
|
+
|
|
471
|
+
const analysis: UIDesignAnalysis = {
|
|
472
|
+
component: componentName,
|
|
473
|
+
issues,
|
|
474
|
+
accessibilityScore,
|
|
475
|
+
usabilityScore,
|
|
476
|
+
recommendations,
|
|
477
|
+
designPatterns,
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
return {
|
|
481
|
+
content: [
|
|
482
|
+
{
|
|
483
|
+
type: "text",
|
|
484
|
+
text:
|
|
485
|
+
`UI Component Analysis: ${componentName}\n\n` +
|
|
486
|
+
`🎯 SCORES\n` +
|
|
487
|
+
`Accessibility: ${accessibilityScore}/100\n` +
|
|
488
|
+
`Usability: ${usabilityScore}/100\n\n` +
|
|
489
|
+
`🔍 ISSUES FOUND: ${issues.length}\n` +
|
|
490
|
+
issues
|
|
491
|
+
.slice(0, 5)
|
|
492
|
+
.map(
|
|
493
|
+
(issue) =>
|
|
494
|
+
`${this.getSeverityIcon(issue.severity)} ${issue.type.toUpperCase()}: ${issue.description}`,
|
|
495
|
+
)
|
|
496
|
+
.join("\n") +
|
|
497
|
+
"\n\n" +
|
|
498
|
+
`💡 RECOMMENDATIONS\n${recommendations
|
|
499
|
+
.slice(0, 5)
|
|
500
|
+
.map((rec, i) => `${i + 1}. ${rec}`)
|
|
501
|
+
.join("\n")}\n\n` +
|
|
502
|
+
`🎨 DESIGN PATTERNS DETECTED\n${designPatterns
|
|
503
|
+
.slice(0, 3)
|
|
504
|
+
.map((pattern) => `• ${pattern}`)
|
|
505
|
+
.join("\n")}`,
|
|
506
|
+
},
|
|
507
|
+
],
|
|
508
|
+
data: analysis,
|
|
509
|
+
};
|
|
510
|
+
} catch (error) {
|
|
511
|
+
return {
|
|
512
|
+
content: [
|
|
513
|
+
{
|
|
514
|
+
type: "text",
|
|
515
|
+
text: `Error analyzing UI component: ${error instanceof Error ? error.message : String(error)}`,
|
|
516
|
+
},
|
|
517
|
+
],
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
private async designComponent(args: DesignComponentArgs): Promise<ToolResponse> {
|
|
523
|
+
const {
|
|
524
|
+
componentType,
|
|
525
|
+
requirements,
|
|
526
|
+
framework,
|
|
527
|
+
accessibility = true,
|
|
528
|
+
} = args;
|
|
529
|
+
|
|
530
|
+
try {
|
|
531
|
+
const designSpec = this.generateComponentDesign(
|
|
532
|
+
componentType,
|
|
533
|
+
requirements,
|
|
534
|
+
framework,
|
|
535
|
+
accessibility,
|
|
536
|
+
);
|
|
537
|
+
const implementation = this.generateComponentCode(designSpec, framework);
|
|
538
|
+
const accessibilityFeatures = accessibility
|
|
539
|
+
? this.addAccessibilityFeatures(designSpec, framework)
|
|
540
|
+
: [];
|
|
541
|
+
|
|
542
|
+
return {
|
|
543
|
+
content: [
|
|
544
|
+
{
|
|
545
|
+
type: "text",
|
|
546
|
+
text:
|
|
547
|
+
`Component Design: ${componentType.toUpperCase()}\n\n` +
|
|
548
|
+
`📋 REQUIREMENTS\n${requirements.substring(0, 200)}${requirements.length > 200 ? "..." : ""}\n\n` +
|
|
549
|
+
`🎨 DESIGN SPECIFICATION\n` +
|
|
550
|
+
`Framework: ${framework.toUpperCase()}\n` +
|
|
551
|
+
`Accessibility: ${accessibility ? "✅ Included" : "❌ Not included"}\n\n` +
|
|
552
|
+
`🏗️ COMPONENT STRUCTURE\n${designSpec.structure.map((item: string) => `• ${item}`).join("\n")}\n\n` +
|
|
553
|
+
`♿ ACCESSIBILITY FEATURES\n${accessibilityFeatures.map((feature) => `• ${feature}`).join("\n")}\n\n` +
|
|
554
|
+
`💻 IMPLEMENTATION\n\`\`\`${framework}\n${implementation}\n\`\`\``,
|
|
555
|
+
},
|
|
556
|
+
],
|
|
557
|
+
data: { designSpec, implementation, accessibilityFeatures },
|
|
558
|
+
};
|
|
559
|
+
} catch (error) {
|
|
560
|
+
return {
|
|
561
|
+
content: [
|
|
562
|
+
{
|
|
563
|
+
type: "text",
|
|
564
|
+
text: `Error designing component: ${error instanceof Error ? error.message : String(error)}`,
|
|
565
|
+
},
|
|
566
|
+
],
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
private async auditAccessibility(args: AuditAccessibilityArgs): Promise<ToolResponse> {
|
|
572
|
+
const { htmlContent, cssContent, wcagLevel = "AA" } = args;
|
|
573
|
+
|
|
574
|
+
try {
|
|
575
|
+
const violations = this.checkWCAGCompliance(
|
|
576
|
+
htmlContent,
|
|
577
|
+
cssContent,
|
|
578
|
+
wcagLevel,
|
|
579
|
+
);
|
|
580
|
+
const score = this.calculateWCAGScore(violations, wcagLevel);
|
|
581
|
+
const recommendations =
|
|
582
|
+
this.generateAccessibilityRecommendations(violations);
|
|
583
|
+
|
|
584
|
+
return {
|
|
585
|
+
content: [
|
|
586
|
+
{
|
|
587
|
+
type: "text",
|
|
588
|
+
text:
|
|
589
|
+
`Accessibility Audit (WCAG ${wcagLevel})\n\n` +
|
|
590
|
+
`📊 COMPLIANCE SCORE: ${score}/100\n\n` +
|
|
591
|
+
`🚨 VIOLATIONS FOUND: ${violations.length}\n` +
|
|
592
|
+
violations
|
|
593
|
+
.slice(0, 10)
|
|
594
|
+
.map(
|
|
595
|
+
(violation) =>
|
|
596
|
+
`${this.getSeverityIcon(violation.severity)} ${violation.guideline}: ${violation.description}`,
|
|
597
|
+
)
|
|
598
|
+
.join("\n") +
|
|
599
|
+
"\n\n" +
|
|
600
|
+
`💡 REMEDIATION STEPS\n${recommendations
|
|
601
|
+
.slice(0, 5)
|
|
602
|
+
.map((rec, i) => `${i + 1}. ${rec}`)
|
|
603
|
+
.join("\n")}`,
|
|
604
|
+
},
|
|
605
|
+
],
|
|
606
|
+
data: { violations, score, recommendations, wcagLevel },
|
|
607
|
+
};
|
|
608
|
+
} catch (error) {
|
|
609
|
+
return {
|
|
610
|
+
content: [
|
|
611
|
+
{
|
|
612
|
+
type: "text",
|
|
613
|
+
text: `Error auditing accessibility: ${error instanceof Error ? error.message : String(error)}`,
|
|
614
|
+
},
|
|
615
|
+
],
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
private async generateDesignSystem(args: GenerateDesignSystemArgs): Promise<ToolResponse> {
|
|
621
|
+
const {
|
|
622
|
+
brandGuidelines,
|
|
623
|
+
targetAudience,
|
|
624
|
+
platform,
|
|
625
|
+
includeAccessibility = true,
|
|
626
|
+
} = args;
|
|
627
|
+
|
|
628
|
+
try {
|
|
629
|
+
const designSystem = this.createDesignSystem(
|
|
630
|
+
brandGuidelines,
|
|
631
|
+
targetAudience,
|
|
632
|
+
platform,
|
|
633
|
+
includeAccessibility,
|
|
634
|
+
);
|
|
635
|
+
const tokens = this.generateDesignTokens(designSystem);
|
|
636
|
+
const documentation = this.generateDesignSystemDocs(designSystem);
|
|
637
|
+
|
|
638
|
+
return {
|
|
639
|
+
content: [
|
|
640
|
+
{
|
|
641
|
+
type: "text",
|
|
642
|
+
text:
|
|
643
|
+
`Design System Generated for ${platform.toUpperCase()}\n\n` +
|
|
644
|
+
`🎨 COLOR PALETTE\n` +
|
|
645
|
+
`Primary: ${designSystem.colors.primary.join(", ")}\n` +
|
|
646
|
+
`Semantic: Success(${designSystem.colors.semantic.success}), Warning(${designSystem.colors.semantic.warning}), Error(${designSystem.colors.semantic.error})\n\n` +
|
|
647
|
+
`📝 TYPOGRAPHY SCALE\n` +
|
|
648
|
+
`Fonts: ${designSystem.typography.fontFamilies.join(", ")}\n` +
|
|
649
|
+
`Sizes: ${Object.entries(designSystem.typography.sizes)
|
|
650
|
+
.slice(0, 3)
|
|
651
|
+
.map(([k, v]) => `${k}: ${v}`)
|
|
652
|
+
.join(", ")}\n\n` +
|
|
653
|
+
`📏 SPACING SYSTEM\n` +
|
|
654
|
+
`Base: ${designSystem.spacing.base}px\n` +
|
|
655
|
+
`Scale: ${designSystem.spacing.scale.join(", ")}\n\n` +
|
|
656
|
+
`🧩 COMPONENT LIBRARY\n` +
|
|
657
|
+
`Buttons: ${designSystem.components.buttons.length} variants\n` +
|
|
658
|
+
`Inputs: ${designSystem.components.inputs.length} variants\n` +
|
|
659
|
+
`Navigation: ${designSystem.components.navigation.length} patterns\n\n` +
|
|
660
|
+
`♿ ACCESSIBILITY: ${includeAccessibility ? "✅ Included" : "❌ Not included"}\n\n` +
|
|
661
|
+
`📚 DESIGN TOKENS\n\`\`\`json\n${JSON.stringify(tokens, null, 2).substring(0, 500)}...\n\`\`\``,
|
|
662
|
+
},
|
|
663
|
+
],
|
|
664
|
+
data: { designSystem, tokens, documentation },
|
|
665
|
+
};
|
|
666
|
+
} catch (error) {
|
|
667
|
+
return {
|
|
668
|
+
content: [
|
|
669
|
+
{
|
|
670
|
+
type: "text",
|
|
671
|
+
text: `Error generating design system: ${error instanceof Error ? error.message : String(error)}`,
|
|
672
|
+
},
|
|
673
|
+
],
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
private extractComponentName(code: string, framework: string): string {
|
|
679
|
+
// Extract component name based on framework
|
|
680
|
+
switch (framework) {
|
|
681
|
+
case "react":
|
|
682
|
+
const reactMatch = code.match(/function\s+(\w+)|const\s+(\w+)\s*=/);
|
|
683
|
+
return reactMatch
|
|
684
|
+
? reactMatch[1] || reactMatch[2] || "UnknownComponent"
|
|
685
|
+
: "UnknownComponent";
|
|
686
|
+
case "vue":
|
|
687
|
+
const vueMatch = code.match(/name:\s*['"](\w+)['"]/);
|
|
688
|
+
return vueMatch && vueMatch[1] ? vueMatch[1] : "UnknownComponent";
|
|
689
|
+
case "angular":
|
|
690
|
+
const angularMatch = code.match(/selector:\s*['"]([^'"]+)['"]/);
|
|
691
|
+
return angularMatch && angularMatch[1]
|
|
692
|
+
? angularMatch[1].replace(/[\[\]]/g, "")
|
|
693
|
+
: "UnknownComponent";
|
|
694
|
+
default:
|
|
695
|
+
return "UnknownComponent";
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
private analyzeComponentCode(
|
|
700
|
+
code: string,
|
|
701
|
+
framework: string,
|
|
702
|
+
checkAccessibility: boolean,
|
|
703
|
+
checkResponsive: boolean,
|
|
704
|
+
): UIIssue[] {
|
|
705
|
+
const issues: UIIssue[] = [];
|
|
706
|
+
|
|
707
|
+
// Accessibility checks
|
|
708
|
+
if (checkAccessibility) {
|
|
709
|
+
issues.push(...this.checkAccessibilityIssues(code, framework));
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// Responsive design checks
|
|
713
|
+
if (checkResponsive) {
|
|
714
|
+
issues.push(...this.checkResponsiveIssues(code, framework));
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
// Usability checks
|
|
718
|
+
issues.push(...this.checkUsabilityIssues(code, framework));
|
|
719
|
+
|
|
720
|
+
// Performance checks
|
|
721
|
+
issues.push(...this.checkPerformanceIssues(code, framework));
|
|
722
|
+
|
|
723
|
+
// Semantic HTML checks
|
|
724
|
+
issues.push(...this.checkSemanticIssues(code, framework));
|
|
725
|
+
|
|
726
|
+
return issues;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
private checkAccessibilityIssues(code: string, framework: string): UIIssue[] {
|
|
730
|
+
const issues: UIIssue[] = [];
|
|
731
|
+
|
|
732
|
+
// Missing alt text
|
|
733
|
+
if (code.includes("<img") && !code.includes("alt=")) {
|
|
734
|
+
issues.push({
|
|
735
|
+
type: "accessibility",
|
|
736
|
+
severity: "high",
|
|
737
|
+
description: "Image missing alt attribute",
|
|
738
|
+
wcag: "1.1.1",
|
|
739
|
+
recommendation: "Add descriptive alt text for all images",
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
// Missing form labels
|
|
744
|
+
if (
|
|
745
|
+
code.includes("<input") &&
|
|
746
|
+
!code.includes("aria-label") &&
|
|
747
|
+
!code.includes("<label")
|
|
748
|
+
) {
|
|
749
|
+
issues.push({
|
|
750
|
+
type: "accessibility",
|
|
751
|
+
severity: "high",
|
|
752
|
+
description: "Form input missing label",
|
|
753
|
+
wcag: "3.3.2",
|
|
754
|
+
recommendation:
|
|
755
|
+
"Associate labels with form inputs using <label> or aria-label",
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
// Insufficient color contrast (basic check)
|
|
760
|
+
if (code.includes("color:") && code.includes("background:")) {
|
|
761
|
+
issues.push({
|
|
762
|
+
type: "accessibility",
|
|
763
|
+
severity: "medium",
|
|
764
|
+
description: "Potential color contrast issues detected",
|
|
765
|
+
wcag: "1.4.3",
|
|
766
|
+
recommendation:
|
|
767
|
+
"Ensure color contrast ratio meets WCAG AA standards (4.5:1)",
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
// Missing focus indicators
|
|
772
|
+
if (
|
|
773
|
+
code.includes("<button") ||
|
|
774
|
+
(code.includes("<a") && !code.includes("focus"))
|
|
775
|
+
) {
|
|
776
|
+
issues.push({
|
|
777
|
+
type: "accessibility",
|
|
778
|
+
severity: "medium",
|
|
779
|
+
description: "Interactive element may lack visible focus indicator",
|
|
780
|
+
wcag: "2.4.7",
|
|
781
|
+
recommendation: "Add visible focus styles for keyboard navigation",
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
return issues;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
private checkResponsiveIssues(code: string, framework: string): UIIssue[] {
|
|
789
|
+
const issues: UIIssue[] = [];
|
|
790
|
+
|
|
791
|
+
// Fixed widths/heights
|
|
792
|
+
if (
|
|
793
|
+
code.includes("width:") &&
|
|
794
|
+
code.includes("px") &&
|
|
795
|
+
!code.includes("@media")
|
|
796
|
+
) {
|
|
797
|
+
issues.push({
|
|
798
|
+
type: "responsive",
|
|
799
|
+
severity: "medium",
|
|
800
|
+
description: "Fixed pixel widths may not be responsive",
|
|
801
|
+
recommendation:
|
|
802
|
+
"Use relative units (%, em, rem) and media queries for responsive design",
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
// Missing viewport meta tag (would be in HTML, not component)
|
|
807
|
+
if (framework === "react" && !code.includes("viewport")) {
|
|
808
|
+
issues.push({
|
|
809
|
+
type: "responsive",
|
|
810
|
+
severity: "low",
|
|
811
|
+
description: "Ensure viewport meta tag is set in HTML head",
|
|
812
|
+
recommendation:
|
|
813
|
+
'Add <meta name="viewport" content="width=device-width, initial-scale=1">',
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
return issues;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
private checkUsabilityIssues(code: string, framework: string): UIIssue[] {
|
|
821
|
+
const issues: UIIssue[] = [];
|
|
822
|
+
|
|
823
|
+
// Button text issues
|
|
824
|
+
if (
|
|
825
|
+
code.includes("<button") &&
|
|
826
|
+
code.includes("OK") &&
|
|
827
|
+
!code.includes("aria-label")
|
|
828
|
+
) {
|
|
829
|
+
issues.push({
|
|
830
|
+
type: "usability",
|
|
831
|
+
severity: "medium",
|
|
832
|
+
description: 'Button with generic text "OK" lacks context',
|
|
833
|
+
recommendation:
|
|
834
|
+
"Use descriptive button text or add aria-label for clarity",
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
// Form validation feedback
|
|
839
|
+
if (
|
|
840
|
+
code.includes("<form") &&
|
|
841
|
+
!code.includes("error") &&
|
|
842
|
+
!code.includes("invalid")
|
|
843
|
+
) {
|
|
844
|
+
issues.push({
|
|
845
|
+
type: "usability",
|
|
846
|
+
severity: "low",
|
|
847
|
+
description: "Form may lack validation error feedback",
|
|
848
|
+
recommendation:
|
|
849
|
+
"Add visible error messages for form validation failures",
|
|
850
|
+
});
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
return issues;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
private checkPerformanceIssues(code: string, framework: string): UIIssue[] {
|
|
857
|
+
const issues: UIIssue[] = [];
|
|
858
|
+
|
|
859
|
+
// Large inline styles
|
|
860
|
+
const styleMatches = code.match(/style=\{[^}]{100,}\}/g);
|
|
861
|
+
if (styleMatches && styleMatches.length > 0) {
|
|
862
|
+
issues.push({
|
|
863
|
+
type: "performance",
|
|
864
|
+
severity: "low",
|
|
865
|
+
description: "Large inline style objects may impact performance",
|
|
866
|
+
recommendation: "Extract styles to CSS classes or styled-components",
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
// Excessive re-renders (React specific)
|
|
871
|
+
if (
|
|
872
|
+
framework === "react" &&
|
|
873
|
+
code.includes("useEffect") &&
|
|
874
|
+
code.includes("[]")
|
|
875
|
+
) {
|
|
876
|
+
issues.push({
|
|
877
|
+
type: "performance",
|
|
878
|
+
severity: "medium",
|
|
879
|
+
description:
|
|
880
|
+
"useEffect with empty dependency array may cause unnecessary re-renders",
|
|
881
|
+
recommendation:
|
|
882
|
+
"Review useEffect dependencies to prevent infinite loops",
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
return issues;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
private checkSemanticIssues(code: string, framework: string): UIIssue[] {
|
|
890
|
+
const issues: UIIssue[] = [];
|
|
891
|
+
|
|
892
|
+
// Using div instead of semantic elements
|
|
893
|
+
if (
|
|
894
|
+
code.includes("<div") &&
|
|
895
|
+
code.includes("click") &&
|
|
896
|
+
!code.includes("<button")
|
|
897
|
+
) {
|
|
898
|
+
issues.push({
|
|
899
|
+
type: "semantic",
|
|
900
|
+
severity: "medium",
|
|
901
|
+
description: "Clickable div used instead of semantic button element",
|
|
902
|
+
recommendation:
|
|
903
|
+
"Use <button> element for clickable actions to improve accessibility",
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
// Missing heading hierarchy
|
|
908
|
+
const headingMatches = code.match(/<h[1-6]/g);
|
|
909
|
+
if (headingMatches && headingMatches.length > 1) {
|
|
910
|
+
// Check for proper hierarchy (simplified)
|
|
911
|
+
const hasH1 = code.includes("<h1");
|
|
912
|
+
const hasH2 = code.includes("<h2");
|
|
913
|
+
if (!hasH1 && hasH2) {
|
|
914
|
+
issues.push({
|
|
915
|
+
type: "semantic",
|
|
916
|
+
severity: "low",
|
|
917
|
+
description: "Heading hierarchy may skip levels",
|
|
918
|
+
recommendation:
|
|
919
|
+
"Ensure proper heading hierarchy (h1 → h2 → h3, etc.)",
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
return issues;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
private calculateAccessibilityScore(issues: UIIssue[]): number {
|
|
928
|
+
const accessibilityIssues = issues.filter(
|
|
929
|
+
(i) => i.type === "accessibility",
|
|
930
|
+
);
|
|
931
|
+
let score = 100;
|
|
932
|
+
|
|
933
|
+
accessibilityIssues.forEach((issue) => {
|
|
934
|
+
switch (issue.severity) {
|
|
935
|
+
case "critical":
|
|
936
|
+
score -= 15;
|
|
937
|
+
break;
|
|
938
|
+
case "high":
|
|
939
|
+
score -= 10;
|
|
940
|
+
break;
|
|
941
|
+
case "medium":
|
|
942
|
+
score -= 5;
|
|
943
|
+
break;
|
|
944
|
+
case "low":
|
|
945
|
+
score -= 2;
|
|
946
|
+
break;
|
|
947
|
+
}
|
|
948
|
+
});
|
|
949
|
+
|
|
950
|
+
return Math.max(0, Math.min(100, score));
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
private calculateUsabilityScore(issues: UIIssue[]): number {
|
|
954
|
+
const usabilityIssues = issues.filter(
|
|
955
|
+
(i) => i.type === "usability" || i.type === "responsive",
|
|
956
|
+
);
|
|
957
|
+
let score = 100;
|
|
958
|
+
|
|
959
|
+
usabilityIssues.forEach((issue) => {
|
|
960
|
+
switch (issue.severity) {
|
|
961
|
+
case "high":
|
|
962
|
+
score -= 8;
|
|
963
|
+
break;
|
|
964
|
+
case "medium":
|
|
965
|
+
score -= 4;
|
|
966
|
+
break;
|
|
967
|
+
case "low":
|
|
968
|
+
score -= 2;
|
|
969
|
+
break;
|
|
970
|
+
}
|
|
971
|
+
});
|
|
972
|
+
|
|
973
|
+
return Math.max(0, Math.min(100, score));
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
private generateUIRecommendations(
|
|
977
|
+
issues: UIIssue[],
|
|
978
|
+
framework: string,
|
|
979
|
+
): string[] {
|
|
980
|
+
const recommendations: string[] = [];
|
|
981
|
+
|
|
982
|
+
// Group issues by type
|
|
983
|
+
const byType = issues.reduce(
|
|
984
|
+
(acc, issue) => {
|
|
985
|
+
acc[issue.type] = (acc[issue.type] || 0) + 1;
|
|
986
|
+
return acc;
|
|
987
|
+
},
|
|
988
|
+
{} as Record<string, number>,
|
|
989
|
+
);
|
|
990
|
+
|
|
991
|
+
if ((byType.accessibility || 0) > 0) {
|
|
992
|
+
recommendations.push(
|
|
993
|
+
`Address ${byType.accessibility} accessibility issues to improve WCAG compliance`,
|
|
994
|
+
);
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
if ((byType.responsive || 0) > 0) {
|
|
998
|
+
recommendations.push(
|
|
999
|
+
`Fix ${byType.responsive} responsive design issues for mobile compatibility`,
|
|
1000
|
+
);
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
if ((byType.usability || 0) > 0) {
|
|
1004
|
+
recommendations.push(
|
|
1005
|
+
`Improve ${byType.usability} usability issues for better user experience`,
|
|
1006
|
+
);
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
// Framework-specific recommendations
|
|
1010
|
+
switch (framework) {
|
|
1011
|
+
case "react":
|
|
1012
|
+
recommendations.push(
|
|
1013
|
+
"Consider using React Testing Library for accessibility testing",
|
|
1014
|
+
);
|
|
1015
|
+
break;
|
|
1016
|
+
case "vue":
|
|
1017
|
+
recommendations.push(
|
|
1018
|
+
"Use Vue's built-in accessibility features and vue-a11y library",
|
|
1019
|
+
);
|
|
1020
|
+
break;
|
|
1021
|
+
case "angular":
|
|
1022
|
+
recommendations.push("Leverage Angular CDK for accessible components");
|
|
1023
|
+
break;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
recommendations.push("Run automated accessibility audits regularly");
|
|
1027
|
+
recommendations.push("Test with real users and assistive technologies");
|
|
1028
|
+
|
|
1029
|
+
return recommendations;
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
private identifyDesignPatterns(code: string, framework: string): string[] {
|
|
1033
|
+
const patterns: string[] = [];
|
|
1034
|
+
|
|
1035
|
+
// Common design patterns
|
|
1036
|
+
if (code.includes("useState") && code.includes("onClick")) {
|
|
1037
|
+
patterns.push("Controlled Component Pattern");
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
if (code.includes("Context") && code.includes("Provider")) {
|
|
1041
|
+
patterns.push("Context Provider Pattern");
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
if (code.includes("children") && code.includes("props")) {
|
|
1045
|
+
patterns.push("Render Props Pattern");
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
if (code.includes("forwardRef")) {
|
|
1049
|
+
patterns.push("Ref Forwarding Pattern");
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
if (code.includes("useMemo") || code.includes("useCallback")) {
|
|
1053
|
+
patterns.push("Memoization Pattern");
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
// Layout patterns
|
|
1057
|
+
if (code.includes("flex") || code.includes("grid")) {
|
|
1058
|
+
patterns.push("Modern CSS Layout (Flexbox/Grid)");
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
if (code.includes("media") && code.includes("query")) {
|
|
1062
|
+
patterns.push("Responsive Design Pattern");
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
return patterns;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
private generateComponentDesign(
|
|
1069
|
+
componentType: string,
|
|
1070
|
+
requirements: string,
|
|
1071
|
+
framework: string,
|
|
1072
|
+
accessibility: boolean,
|
|
1073
|
+
): ComponentDesign {
|
|
1074
|
+
const design = {
|
|
1075
|
+
componentType,
|
|
1076
|
+
requirements,
|
|
1077
|
+
framework,
|
|
1078
|
+
accessibility,
|
|
1079
|
+
structure: [] as string[],
|
|
1080
|
+
props: [] as string[],
|
|
1081
|
+
states: [] as string[],
|
|
1082
|
+
variants: [] as string[],
|
|
1083
|
+
};
|
|
1084
|
+
|
|
1085
|
+
switch (componentType) {
|
|
1086
|
+
case "button":
|
|
1087
|
+
design.structure = [
|
|
1088
|
+
"Button container with proper spacing",
|
|
1089
|
+
"Icon support (optional)",
|
|
1090
|
+
"Loading state indicator",
|
|
1091
|
+
"Focus ring for accessibility",
|
|
1092
|
+
];
|
|
1093
|
+
design.props = [
|
|
1094
|
+
"children: ReactNode",
|
|
1095
|
+
'variant: "primary" | "secondary" | "danger"',
|
|
1096
|
+
'size: "sm" | "md" | "lg"',
|
|
1097
|
+
"disabled: boolean",
|
|
1098
|
+
"loading: boolean",
|
|
1099
|
+
"onClick: () => void",
|
|
1100
|
+
];
|
|
1101
|
+
design.states = [
|
|
1102
|
+
"normal",
|
|
1103
|
+
"hover",
|
|
1104
|
+
"active",
|
|
1105
|
+
"focus",
|
|
1106
|
+
"disabled",
|
|
1107
|
+
"loading",
|
|
1108
|
+
];
|
|
1109
|
+
design.variants = [
|
|
1110
|
+
"primary",
|
|
1111
|
+
"secondary",
|
|
1112
|
+
"outline",
|
|
1113
|
+
"ghost",
|
|
1114
|
+
"danger",
|
|
1115
|
+
];
|
|
1116
|
+
break;
|
|
1117
|
+
|
|
1118
|
+
case "input":
|
|
1119
|
+
design.structure = [
|
|
1120
|
+
"Input wrapper with label",
|
|
1121
|
+
"Input field with proper styling",
|
|
1122
|
+
"Error message container",
|
|
1123
|
+
"Helper text support",
|
|
1124
|
+
"Icon support",
|
|
1125
|
+
];
|
|
1126
|
+
design.props = [
|
|
1127
|
+
"label: string",
|
|
1128
|
+
"placeholder: string",
|
|
1129
|
+
"value: string",
|
|
1130
|
+
"error: string",
|
|
1131
|
+
"helperText: string",
|
|
1132
|
+
"required: boolean",
|
|
1133
|
+
"disabled: boolean",
|
|
1134
|
+
];
|
|
1135
|
+
design.states = ["normal", "focus", "error", "disabled"];
|
|
1136
|
+
design.variants = ["text", "email", "password", "search", "textarea"];
|
|
1137
|
+
break;
|
|
1138
|
+
|
|
1139
|
+
case "modal":
|
|
1140
|
+
design.structure = [
|
|
1141
|
+
"Modal overlay",
|
|
1142
|
+
"Modal container with backdrop",
|
|
1143
|
+
"Header with title and close button",
|
|
1144
|
+
"Content area",
|
|
1145
|
+
"Footer with action buttons",
|
|
1146
|
+
"Focus trap for accessibility",
|
|
1147
|
+
];
|
|
1148
|
+
design.props = [
|
|
1149
|
+
"isOpen: boolean",
|
|
1150
|
+
"title: string",
|
|
1151
|
+
"children: ReactNode",
|
|
1152
|
+
"onClose: () => void",
|
|
1153
|
+
"actions: ActionButton[]",
|
|
1154
|
+
];
|
|
1155
|
+
design.states = ["open", "closed", "opening", "closing"];
|
|
1156
|
+
design.variants = ["default", "fullscreen", "sidebar"];
|
|
1157
|
+
break;
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
return design;
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
private generateComponentCode(design: ComponentDesign, framework: string): string {
|
|
1164
|
+
// Generate basic component code structure
|
|
1165
|
+
switch (framework) {
|
|
1166
|
+
case "react":
|
|
1167
|
+
return this.generateReactComponent(design);
|
|
1168
|
+
case "vue":
|
|
1169
|
+
return this.generateVueComponent(design);
|
|
1170
|
+
case "angular":
|
|
1171
|
+
return this.generateAngularComponent(design);
|
|
1172
|
+
default:
|
|
1173
|
+
return `// Component code generation for ${framework} not yet implemented`;
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
private generateReactComponent(design: ComponentDesign): string {
|
|
1178
|
+
const propsInterface = design.props
|
|
1179
|
+
.map((prop: string) => ` ${prop};`)
|
|
1180
|
+
.join("\n");
|
|
1181
|
+
|
|
1182
|
+
return `import React from 'react';
|
|
1183
|
+
|
|
1184
|
+
interface ${design.componentType.charAt(0).toUpperCase() + design.componentType.slice(1)}Props {
|
|
1185
|
+
${propsInterface}
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
export const ${design.componentType.charAt(0).toUpperCase() + design.componentType.slice(1)}: React.FC<${design.componentType.charAt(0).toUpperCase() + design.componentType.slice(1)}Props> = ({
|
|
1189
|
+
// props destructuring
|
|
1190
|
+
}) => {
|
|
1191
|
+
return (
|
|
1192
|
+
<div className="${design.componentType}-container">
|
|
1193
|
+
{/* ${design.componentType} implementation */}
|
|
1194
|
+
</div>
|
|
1195
|
+
);
|
|
1196
|
+
};`;
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
private generateVueComponent(design: ComponentDesign): string {
|
|
1200
|
+
return `<template>
|
|
1201
|
+
<div class="${design.componentType}-container">
|
|
1202
|
+
<!-- ${design.componentType} implementation -->
|
|
1203
|
+
</div>
|
|
1204
|
+
</template>
|
|
1205
|
+
|
|
1206
|
+
<script setup lang="ts">
|
|
1207
|
+
// Props definition would go here
|
|
1208
|
+
</script>
|
|
1209
|
+
|
|
1210
|
+
<style scoped>
|
|
1211
|
+
.${design.componentType}-container {
|
|
1212
|
+
/* styles */
|
|
1213
|
+
}
|
|
1214
|
+
</style>`;
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
private generateAngularComponent(design: ComponentDesign): string {
|
|
1218
|
+
return `import { Component, Input, Output, EventEmitter } from '@angular/core';
|
|
1219
|
+
// frameworkLogger imported above — single import at line 15
|
|
1220
|
+
|
|
1221
|
+
@Component({
|
|
1222
|
+
selector: 'app-${design.componentType}',
|
|
1223
|
+
template: \`
|
|
1224
|
+
<div class="${design.componentType}-container">
|
|
1225
|
+
<!-- ${design.componentType} implementation -->
|
|
1226
|
+
</div>
|
|
1227
|
+
\`,
|
|
1228
|
+
styles: [\`
|
|
1229
|
+
.${design.componentType}-container {
|
|
1230
|
+
/* styles */
|
|
1231
|
+
}
|
|
1232
|
+
\`]
|
|
1233
|
+
})
|
|
1234
|
+
export class ${design.componentType.charAt(0).toUpperCase() + design.componentType.slice(1)}Component {
|
|
1235
|
+
// Component logic
|
|
1236
|
+
}`;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
private addAccessibilityFeatures(design: ComponentDesign, framework: string): string[] {
|
|
1240
|
+
const features: string[] = [];
|
|
1241
|
+
|
|
1242
|
+
switch (design.componentType) {
|
|
1243
|
+
case "button":
|
|
1244
|
+
features.push("Keyboard navigation support (Enter/Space activation)");
|
|
1245
|
+
features.push("ARIA pressed state for toggle buttons");
|
|
1246
|
+
features.push("Screen reader announcements for state changes");
|
|
1247
|
+
features.push("Focus management and visible focus indicators");
|
|
1248
|
+
break;
|
|
1249
|
+
|
|
1250
|
+
case "input":
|
|
1251
|
+
features.push("ARIA labels and descriptions");
|
|
1252
|
+
features.push("Error message association with input");
|
|
1253
|
+
features.push("Required field indicators");
|
|
1254
|
+
features.push("Input validation feedback");
|
|
1255
|
+
break;
|
|
1256
|
+
|
|
1257
|
+
case "modal":
|
|
1258
|
+
features.push("Focus trap within modal");
|
|
1259
|
+
features.push("ARIA modal role and properties");
|
|
1260
|
+
features.push("Escape key handling");
|
|
1261
|
+
features.push("Initial focus management");
|
|
1262
|
+
break;
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
return features;
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
private checkWCAGCompliance(
|
|
1269
|
+
htmlContent: string,
|
|
1270
|
+
cssContent: string | undefined,
|
|
1271
|
+
level: string,
|
|
1272
|
+
): WCAGViolation[] {
|
|
1273
|
+
const violations: WCAGViolation[] = [];
|
|
1274
|
+
|
|
1275
|
+
// Basic WCAG checks (simplified)
|
|
1276
|
+
if (!htmlContent.includes("lang=")) {
|
|
1277
|
+
violations.push({
|
|
1278
|
+
guideline: "3.1.1 Language of Page",
|
|
1279
|
+
severity: "medium",
|
|
1280
|
+
description: "Missing language attribute on html element",
|
|
1281
|
+
});
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
// Enhanced color contrast checking
|
|
1285
|
+
if (cssContent) {
|
|
1286
|
+
const contrastIssues = this.analyzeColorContrast(cssContent, htmlContent);
|
|
1287
|
+
violations.push(...contrastIssues);
|
|
1288
|
+
|
|
1289
|
+
// Hero section specific checks
|
|
1290
|
+
const heroIssues = this.analyzeHeroSectionContrast(
|
|
1291
|
+
cssContent,
|
|
1292
|
+
htmlContent,
|
|
1293
|
+
);
|
|
1294
|
+
violations.push(...heroIssues);
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
return violations;
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
/**
|
|
1301
|
+
* Parse color value and convert to RGB
|
|
1302
|
+
*/
|
|
1303
|
+
private parseColor(
|
|
1304
|
+
color: string,
|
|
1305
|
+
): { r: number; g: number; b: number } | null {
|
|
1306
|
+
// Hex color
|
|
1307
|
+
const hexMatch = color.match(/#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/);
|
|
1308
|
+
if (hexMatch && hexMatch[1]) {
|
|
1309
|
+
let hex: string = hexMatch[1];
|
|
1310
|
+
if (hex.length === 3) {
|
|
1311
|
+
hex = hex
|
|
1312
|
+
.split("")
|
|
1313
|
+
.map((c) => c + c)
|
|
1314
|
+
.join("");
|
|
1315
|
+
}
|
|
1316
|
+
return {
|
|
1317
|
+
r: parseInt(hex.substring(0, 2), 16),
|
|
1318
|
+
g: parseInt(hex.substring(2, 4), 16),
|
|
1319
|
+
b: parseInt(hex.substring(4, 6), 16),
|
|
1320
|
+
};
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
// RGB/RGBA
|
|
1324
|
+
const rgbMatch = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
|
|
1325
|
+
if (rgbMatch && rgbMatch[1] && rgbMatch[2] && rgbMatch[3]) {
|
|
1326
|
+
return {
|
|
1327
|
+
r: parseInt(rgbMatch[1], 10),
|
|
1328
|
+
g: parseInt(rgbMatch[2], 10),
|
|
1329
|
+
b: parseInt(rgbMatch[3], 10),
|
|
1330
|
+
};
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
// Named colors
|
|
1334
|
+
const namedColors: Record<string, string> = {
|
|
1335
|
+
white: "#ffffff",
|
|
1336
|
+
black: "#000000",
|
|
1337
|
+
red: "#ff0000",
|
|
1338
|
+
blue: "#0000ff",
|
|
1339
|
+
green: "#008000",
|
|
1340
|
+
gray: "#808080",
|
|
1341
|
+
lightgray: "#d3d3d3",
|
|
1342
|
+
darkgray: "#a9a9a9",
|
|
1343
|
+
};
|
|
1344
|
+
|
|
1345
|
+
const lowerColor = color.toLowerCase().trim();
|
|
1346
|
+
if (namedColors[lowerColor]) {
|
|
1347
|
+
return this.parseColor(namedColors[lowerColor]);
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
return null;
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
/**
|
|
1354
|
+
* Calculate relative luminance (WCAG formula)
|
|
1355
|
+
*/
|
|
1356
|
+
private getLuminance(r: number, g: number, b: number): number {
|
|
1357
|
+
const rs = this.getLuminanceComponent(r);
|
|
1358
|
+
const gs = this.getLuminanceComponent(g);
|
|
1359
|
+
const bs = this.getLuminanceComponent(b);
|
|
1360
|
+
return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
private getLuminanceComponent(c: number): number {
|
|
1364
|
+
const normalized = c / 255;
|
|
1365
|
+
return normalized <= 0.03928
|
|
1366
|
+
? normalized / 12.92
|
|
1367
|
+
: Math.pow((normalized + 0.055) / 1.055, 2.4);
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
/**
|
|
1371
|
+
* Calculate contrast ratio between two colors
|
|
1372
|
+
*/
|
|
1373
|
+
private calculateContrastRatio(
|
|
1374
|
+
color1: string,
|
|
1375
|
+
color2: string,
|
|
1376
|
+
): number | null {
|
|
1377
|
+
const rgb1 = this.parseColor(color1);
|
|
1378
|
+
const rgb2 = this.parseColor(color2);
|
|
1379
|
+
|
|
1380
|
+
if (!rgb1 || !rgb2) return null;
|
|
1381
|
+
|
|
1382
|
+
const lum1 = this.getLuminance(rgb1.r, rgb1.g, rgb1.b);
|
|
1383
|
+
const lum2 = this.getLuminance(rgb2.r, rgb2.g, rgb2.b);
|
|
1384
|
+
|
|
1385
|
+
const lighter = Math.max(lum1, lum2);
|
|
1386
|
+
const darker = Math.min(lum1, lum2);
|
|
1387
|
+
|
|
1388
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
/**
|
|
1392
|
+
* Analyze color contrast in CSS
|
|
1393
|
+
*/
|
|
1394
|
+
private analyzeColorContrast(cssContent: string, htmlContent: string): WCAGViolation[] {
|
|
1395
|
+
const violations: WCAGViolation[] = [];
|
|
1396
|
+
|
|
1397
|
+
// Extract color pairs from CSS
|
|
1398
|
+
const colorRegex = /color:\s*([^;]+)/gi;
|
|
1399
|
+
const bgRegex = /background(?:-color)?:\s*([^;]+)/gi;
|
|
1400
|
+
|
|
1401
|
+
const colors: string[] = [];
|
|
1402
|
+
const backgrounds: string[] = [];
|
|
1403
|
+
|
|
1404
|
+
let match: RegExpExecArray | null;
|
|
1405
|
+
while ((match = colorRegex.exec(cssContent)) !== null) {
|
|
1406
|
+
if (match[1]) {
|
|
1407
|
+
colors.push(match[1].trim());
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
while ((match = bgRegex.exec(cssContent)) !== null) {
|
|
1411
|
+
if (match[1]) {
|
|
1412
|
+
backgrounds.push(match[1].trim());
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
// Check for known problematic combinations
|
|
1417
|
+
const problematicCombos = [
|
|
1418
|
+
{ fg: "#ffffff", bg: "#f3f4f6", desc: "White text on light gray" },
|
|
1419
|
+
{ fg: "#ffffff", bg: "#e5e7eb", desc: "White text on gray" },
|
|
1420
|
+
{ fg: "#ffffff", bg: "#d1d5db", desc: "White text on medium gray" },
|
|
1421
|
+
{ fg: "#000000", bg: "#1f2937", desc: "Black text on dark gray" },
|
|
1422
|
+
{ fg: "#9ca3af", bg: "#ffffff", desc: "Light gray text on white" },
|
|
1423
|
+
{ fg: "#d1d5db", bg: "#ffffff", desc: "Medium gray text on white" },
|
|
1424
|
+
];
|
|
1425
|
+
|
|
1426
|
+
problematicCombos.forEach((combo) => {
|
|
1427
|
+
const ratio = this.calculateContrastRatio(combo.fg, combo.bg);
|
|
1428
|
+
if (ratio && ratio < 4.5) {
|
|
1429
|
+
violations.push({
|
|
1430
|
+
guideline: "1.4.3 Contrast (Minimum)",
|
|
1431
|
+
severity: "high",
|
|
1432
|
+
description: `${combo.desc} has insufficient contrast (${ratio.toFixed(1)}:1, needs 4.5:1)`,
|
|
1433
|
+
recommendation: `Use a darker text color or lighter background to achieve 4.5:1 contrast ratio`,
|
|
1434
|
+
});
|
|
1435
|
+
}
|
|
1436
|
+
});
|
|
1437
|
+
|
|
1438
|
+
return violations;
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
/**
|
|
1442
|
+
* Specifically analyze hero section for contrast issues
|
|
1443
|
+
*/
|
|
1444
|
+
private analyzeHeroSectionContrast(
|
|
1445
|
+
cssContent: string,
|
|
1446
|
+
htmlContent: string,
|
|
1447
|
+
): WCAGViolation[] {
|
|
1448
|
+
const violations: WCAGViolation[] = [];
|
|
1449
|
+
|
|
1450
|
+
// Check for hero section patterns
|
|
1451
|
+
const heroPatterns = [
|
|
1452
|
+
/class="[^"]*hero[^"]*"/i,
|
|
1453
|
+
/id="[^"]*hero[^"]*"/i,
|
|
1454
|
+
/hero-section/i,
|
|
1455
|
+
/landing-hero/i,
|
|
1456
|
+
];
|
|
1457
|
+
|
|
1458
|
+
const hasHero = heroPatterns.some(
|
|
1459
|
+
(pattern) => pattern.test(htmlContent) || pattern.test(cssContent),
|
|
1460
|
+
);
|
|
1461
|
+
|
|
1462
|
+
if (!hasHero) return violations;
|
|
1463
|
+
|
|
1464
|
+
// Check for hero with background image but no overlay
|
|
1465
|
+
const hasBackgroundImage = /background(?:-image)?\s*:\s*url\s*\(/i.test(
|
|
1466
|
+
cssContent,
|
|
1467
|
+
);
|
|
1468
|
+
const hasOverlay =
|
|
1469
|
+
/(?:rgba?\([^)]+\)|#[a-f0-9]{3,8}).*overlay|gradient.*rgba/i.test(
|
|
1470
|
+
cssContent,
|
|
1471
|
+
);
|
|
1472
|
+
const hasTextShadow = /text-shadow\s*:/i.test(cssContent);
|
|
1473
|
+
|
|
1474
|
+
if (hasBackgroundImage && !hasOverlay && !hasTextShadow) {
|
|
1475
|
+
violations.push({
|
|
1476
|
+
guideline: "1.4.3 Contrast (Minimum) - Hero Section",
|
|
1477
|
+
severity: "critical",
|
|
1478
|
+
description:
|
|
1479
|
+
"Hero section with background image lacks text overlay or shadow",
|
|
1480
|
+
recommendation:
|
|
1481
|
+
"Add a semi-transparent overlay (e.g., rgba(0,0,0,0.5)) or text-shadow to ensure text readability",
|
|
1482
|
+
});
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
// Check for light-on-light or dark-on-dark in hero
|
|
1486
|
+
const heroSection = this.extractHeroCSS(cssContent);
|
|
1487
|
+
if (heroSection) {
|
|
1488
|
+
const bgMatch = heroSection.match(/background(?:-color)?\s*:\s*([^;]+)/i);
|
|
1489
|
+
const colorMatch = heroSection.match(/color\s*:\s*([^;]+)/i);
|
|
1490
|
+
|
|
1491
|
+
if (bgMatch?.[1] && colorMatch?.[1]) {
|
|
1492
|
+
const bg = bgMatch[1].trim();
|
|
1493
|
+
const color = colorMatch[1].trim();
|
|
1494
|
+
|
|
1495
|
+
const ratio = this.calculateContrastRatio(color, bg);
|
|
1496
|
+
if (ratio && ratio < 4.5) {
|
|
1497
|
+
violations.push({
|
|
1498
|
+
guideline: "1.4.3 Contrast (Minimum) - Hero Section",
|
|
1499
|
+
severity: "critical",
|
|
1500
|
+
description: `Hero section has poor contrast (${ratio.toFixed(1)}:1, needs 4.5:1)`,
|
|
1501
|
+
recommendation: `Background: ${bg}, Text: ${color}. Use contrasting colors: white text on dark backgrounds or dark text on light backgrounds`,
|
|
1502
|
+
});
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
return violations;
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
/**
|
|
1511
|
+
* Extract CSS for hero section
|
|
1512
|
+
*/
|
|
1513
|
+
private extractHeroCSS(cssContent: string): string | null {
|
|
1514
|
+
const heroRegex = /(?:\.hero|#hero)[^{]*\{([^}]+)\}/gi;
|
|
1515
|
+
const matches: string[] = [];
|
|
1516
|
+
let match: RegExpExecArray | null;
|
|
1517
|
+
|
|
1518
|
+
while ((match = heroRegex.exec(cssContent)) !== null) {
|
|
1519
|
+
if (match[1]) {
|
|
1520
|
+
matches.push(match[1]);
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
return matches.length > 0 ? matches.join(" ") : null;
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1527
|
+
private calculateWCAGScore(violations: WCAGViolation[], level: string): number {
|
|
1528
|
+
let score = 100;
|
|
1529
|
+
|
|
1530
|
+
violations.forEach((violation) => {
|
|
1531
|
+
switch (violation.severity) {
|
|
1532
|
+
case "critical":
|
|
1533
|
+
score -= 20;
|
|
1534
|
+
break;
|
|
1535
|
+
case "high":
|
|
1536
|
+
score -= 15;
|
|
1537
|
+
break;
|
|
1538
|
+
case "medium":
|
|
1539
|
+
score -= 10;
|
|
1540
|
+
break;
|
|
1541
|
+
case "low":
|
|
1542
|
+
score -= 5;
|
|
1543
|
+
break;
|
|
1544
|
+
}
|
|
1545
|
+
});
|
|
1546
|
+
|
|
1547
|
+
return Math.max(0, Math.min(100, score));
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
private generateAccessibilityRecommendations(violations: WCAGViolation[]): string[] {
|
|
1551
|
+
const recommendations: string[] = [];
|
|
1552
|
+
|
|
1553
|
+
violations.forEach((violation) => {
|
|
1554
|
+
recommendations.push(
|
|
1555
|
+
`Fix ${violation.guideline}: ${violation.description}`,
|
|
1556
|
+
);
|
|
1557
|
+
});
|
|
1558
|
+
|
|
1559
|
+
recommendations.push("Use automated accessibility testing tools");
|
|
1560
|
+
recommendations.push("Conduct manual testing with assistive technologies");
|
|
1561
|
+
recommendations.push("Include accessibility in design reviews");
|
|
1562
|
+
|
|
1563
|
+
return recommendations;
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
private createDesignSystem(
|
|
1567
|
+
brandGuidelines: string,
|
|
1568
|
+
targetAudience: string | undefined,
|
|
1569
|
+
platform: string,
|
|
1570
|
+
includeAccessibility: boolean,
|
|
1571
|
+
): DesignSystem {
|
|
1572
|
+
// Generate a basic design system based on inputs
|
|
1573
|
+
const colors: ColorScheme = {
|
|
1574
|
+
primary: ["#007bff", "#0056b3", "#004085"],
|
|
1575
|
+
secondary: ["#6c757d", "#545b62", "#383d41"],
|
|
1576
|
+
semantic: {
|
|
1577
|
+
success: "#28a745",
|
|
1578
|
+
warning: "#ffc107",
|
|
1579
|
+
error: "#dc3545",
|
|
1580
|
+
info: "#17a2b8",
|
|
1581
|
+
},
|
|
1582
|
+
contrastRatios: {},
|
|
1583
|
+
};
|
|
1584
|
+
|
|
1585
|
+
const typography: TypographyScale = {
|
|
1586
|
+
fontFamilies: ["Inter", "system-ui", "-apple-system"],
|
|
1587
|
+
sizes: {
|
|
1588
|
+
xs: "0.75rem",
|
|
1589
|
+
sm: "0.875rem",
|
|
1590
|
+
base: "1rem",
|
|
1591
|
+
lg: "1.125rem",
|
|
1592
|
+
xl: "1.25rem",
|
|
1593
|
+
"2xl": "1.5rem",
|
|
1594
|
+
},
|
|
1595
|
+
weights: {
|
|
1596
|
+
normal: 400,
|
|
1597
|
+
medium: 500,
|
|
1598
|
+
semibold: 600,
|
|
1599
|
+
bold: 700,
|
|
1600
|
+
},
|
|
1601
|
+
lineHeights: {
|
|
1602
|
+
tight: 1.25,
|
|
1603
|
+
normal: 1.5,
|
|
1604
|
+
relaxed: 1.625,
|
|
1605
|
+
},
|
|
1606
|
+
};
|
|
1607
|
+
|
|
1608
|
+
const spacing: SpacingScale = {
|
|
1609
|
+
base: 4,
|
|
1610
|
+
scale: [4, 8, 12, 16, 24, 32, 48, 64],
|
|
1611
|
+
names: {
|
|
1612
|
+
xs: 4,
|
|
1613
|
+
sm: 8,
|
|
1614
|
+
md: 16,
|
|
1615
|
+
lg: 24,
|
|
1616
|
+
xl: 32,
|
|
1617
|
+
"2xl": 48,
|
|
1618
|
+
},
|
|
1619
|
+
};
|
|
1620
|
+
|
|
1621
|
+
const components: ComponentLibrary = {
|
|
1622
|
+
buttons: [
|
|
1623
|
+
{
|
|
1624
|
+
name: "primary",
|
|
1625
|
+
states: ["normal", "hover", "active", "disabled"],
|
|
1626
|
+
accessibility: ["focus-visible"],
|
|
1627
|
+
responsive: true,
|
|
1628
|
+
},
|
|
1629
|
+
{
|
|
1630
|
+
name: "secondary",
|
|
1631
|
+
states: ["normal", "hover", "active", "disabled"],
|
|
1632
|
+
accessibility: ["focus-visible"],
|
|
1633
|
+
responsive: true,
|
|
1634
|
+
},
|
|
1635
|
+
],
|
|
1636
|
+
inputs: [
|
|
1637
|
+
{
|
|
1638
|
+
name: "text",
|
|
1639
|
+
states: ["normal", "focus", "error", "disabled"],
|
|
1640
|
+
accessibility: ["aria-label", "aria-invalid"],
|
|
1641
|
+
responsive: true,
|
|
1642
|
+
},
|
|
1643
|
+
],
|
|
1644
|
+
navigation: [
|
|
1645
|
+
{
|
|
1646
|
+
name: "header",
|
|
1647
|
+
states: ["normal", "mobile-open"],
|
|
1648
|
+
accessibility: ["aria-expanded"],
|
|
1649
|
+
responsive: true,
|
|
1650
|
+
},
|
|
1651
|
+
],
|
|
1652
|
+
feedback: [
|
|
1653
|
+
{
|
|
1654
|
+
name: "alert",
|
|
1655
|
+
states: ["info", "success", "warning", "error"],
|
|
1656
|
+
accessibility: ["role", "aria-live"],
|
|
1657
|
+
responsive: true,
|
|
1658
|
+
},
|
|
1659
|
+
],
|
|
1660
|
+
};
|
|
1661
|
+
|
|
1662
|
+
const patterns: DesignPattern[] = [
|
|
1663
|
+
{
|
|
1664
|
+
name: "Card Layout",
|
|
1665
|
+
category: "layout",
|
|
1666
|
+
description: "Container for related content and actions",
|
|
1667
|
+
useCases: ["Product display", "User profiles", "Content preview"],
|
|
1668
|
+
accessibility: ["Proper heading hierarchy", "Focus management"],
|
|
1669
|
+
},
|
|
1670
|
+
{
|
|
1671
|
+
name: "Progressive Disclosure",
|
|
1672
|
+
category: "interaction",
|
|
1673
|
+
description: "Show information gradually to reduce cognitive load",
|
|
1674
|
+
useCases: ["Forms", "Settings panels", "Help documentation"],
|
|
1675
|
+
accessibility: ["ARIA expanded states", "Keyboard navigation"],
|
|
1676
|
+
},
|
|
1677
|
+
];
|
|
1678
|
+
|
|
1679
|
+
return { colors, typography, spacing, components, patterns };
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
private generateDesignTokens(system: DesignSystem): Record<string, unknown> {
|
|
1683
|
+
return {
|
|
1684
|
+
colors: {
|
|
1685
|
+
primary: system.colors.primary,
|
|
1686
|
+
secondary: system.colors.secondary,
|
|
1687
|
+
semantic: system.colors.semantic,
|
|
1688
|
+
},
|
|
1689
|
+
typography: system.typography,
|
|
1690
|
+
spacing: system.spacing,
|
|
1691
|
+
breakpoints: {
|
|
1692
|
+
sm: "640px",
|
|
1693
|
+
md: "768px",
|
|
1694
|
+
lg: "1024px",
|
|
1695
|
+
xl: "1280px",
|
|
1696
|
+
},
|
|
1697
|
+
};
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
private generateDesignSystemDocs(system: DesignSystem): string {
|
|
1701
|
+
return `# Design System Documentation
|
|
1702
|
+
|
|
1703
|
+
## Colors
|
|
1704
|
+
Primary: ${system.colors.primary.join(", ")}
|
|
1705
|
+
Secondary: ${system.colors.secondary.join(", ")}
|
|
1706
|
+
|
|
1707
|
+
## Typography
|
|
1708
|
+
Fonts: ${system.typography.fontFamilies.join(", ")}
|
|
1709
|
+
|
|
1710
|
+
## Spacing
|
|
1711
|
+
Base unit: ${system.spacing.base}px
|
|
1712
|
+
Scale: ${system.spacing.scale.join(", ")}
|
|
1713
|
+
|
|
1714
|
+
## Components
|
|
1715
|
+
Available: ${Object.keys(system.components).length} component types
|
|
1716
|
+
`;
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
private getSeverityIcon(severity: string): string {
|
|
1720
|
+
const icons = {
|
|
1721
|
+
critical: "🚨",
|
|
1722
|
+
high: "🔴",
|
|
1723
|
+
medium: "🟡",
|
|
1724
|
+
low: "🟢",
|
|
1725
|
+
};
|
|
1726
|
+
return icons[severity as keyof typeof icons] || "❓";
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
private async validateMobileDesign(args: ValidateMobileDesignArgs): Promise<ToolResponse> {
|
|
1730
|
+
const { componentCode, viewportWidth = 320, framework = "css" } = args;
|
|
1731
|
+
|
|
1732
|
+
const issues: MobileDesignIssue[] = [];
|
|
1733
|
+
const recommendations: string[] = [];
|
|
1734
|
+
|
|
1735
|
+
// Check touch target sizes
|
|
1736
|
+
const touchTargetRegex =
|
|
1737
|
+
/(width|height|padding|min-width|min-height):\s*(\d+)(px|rem|em)/gi;
|
|
1738
|
+
let match: RegExpExecArray | null;
|
|
1739
|
+
while ((match = touchTargetRegex.exec(componentCode)) !== null) {
|
|
1740
|
+
if (match[2] && match[3]) {
|
|
1741
|
+
const value = parseInt(match[2], 10);
|
|
1742
|
+
const unit = match[3];
|
|
1743
|
+
const pixelValue = unit === "px" ? value : value * 16;
|
|
1744
|
+
|
|
1745
|
+
if (pixelValue < 44) {
|
|
1746
|
+
issues.push({
|
|
1747
|
+
type: "mobile",
|
|
1748
|
+
severity: "high",
|
|
1749
|
+
message: `Touch target ${match[1]}:${match[0]} is too small (${pixelValue}px). Minimum: 44px`,
|
|
1750
|
+
wcag: "2.5.5",
|
|
1751
|
+
});
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
// Check for responsive units
|
|
1757
|
+
if (
|
|
1758
|
+
componentCode.includes("px") &&
|
|
1759
|
+
!componentCode.includes("rem") &&
|
|
1760
|
+
!componentCode.includes("em")
|
|
1761
|
+
) {
|
|
1762
|
+
recommendations.push(
|
|
1763
|
+
"Consider using rem/em instead of px for better accessibility",
|
|
1764
|
+
);
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
// Check for media queries
|
|
1768
|
+
if (!componentCode.includes("@media")) {
|
|
1769
|
+
recommendations.push(
|
|
1770
|
+
"Add responsive breakpoints (@media) for different viewport sizes",
|
|
1771
|
+
);
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1774
|
+
// Check for mobile navigation pattern
|
|
1775
|
+
if (
|
|
1776
|
+
componentCode.includes("nav") &&
|
|
1777
|
+
!componentCode.includes("hamburger") &&
|
|
1778
|
+
!componentCode.includes("menu")
|
|
1779
|
+
) {
|
|
1780
|
+
recommendations.push(
|
|
1781
|
+
"Consider mobile navigation pattern (hamburger menu) for small screens",
|
|
1782
|
+
);
|
|
1783
|
+
}
|
|
1784
|
+
|
|
1785
|
+
return {
|
|
1786
|
+
content: [
|
|
1787
|
+
{
|
|
1788
|
+
type: "text",
|
|
1789
|
+
text: `## Mobile Design Validation (Viewport: ${viewportWidth}px)\n\n### Issues Found: ${issues.length}\n${issues.map((i: MobileDesignIssue) => `- ${i.severity.toUpperCase()}: ${i.message} (WCAG ${i.wcag})`).join("\n") || "None"}\n\n### Recommendations:\n${recommendations.map((r: string) => `- ${r}`).join("\n") || "None"}\n\n### Mobile-First Checklist:\n- [ ] Touch targets ≥ 44px\n- [ ] Responsive typography (rem/em)\n- [ ] Media queries for breakpoints\n- [ ] Mobile navigation pattern\n- [ ] Readable without zoom (16px min)`,
|
|
1790
|
+
},
|
|
1791
|
+
],
|
|
1792
|
+
};
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1795
|
+
private async analyzeVisualHierarchy(args: AnalyzeVisualHierarchyArgs): Promise<ToolResponse> {
|
|
1796
|
+
const { designCode, pageType = "landing" } = args;
|
|
1797
|
+
|
|
1798
|
+
const issues: HierarchyIssue[] = [];
|
|
1799
|
+
const cognitiveLoadScore = 100;
|
|
1800
|
+
const recommendations: string[] = [];
|
|
1801
|
+
|
|
1802
|
+
// Check heading hierarchy
|
|
1803
|
+
const h1Count = (designCode.match(/<h1/gi) || []).length;
|
|
1804
|
+
const h2Count = (designCode.match(/<h2/gi) || []).length;
|
|
1805
|
+
const h3Count = (designCode.match(/<h3/gi) || []).length;
|
|
1806
|
+
|
|
1807
|
+
if (h1Count === 0) {
|
|
1808
|
+
issues.push({
|
|
1809
|
+
type: "hierarchy",
|
|
1810
|
+
severity: "critical",
|
|
1811
|
+
message: "Missing H1 heading - page purpose unclear",
|
|
1812
|
+
});
|
|
1813
|
+
} else if (h1Count > 1) {
|
|
1814
|
+
issues.push({
|
|
1815
|
+
type: "hierarchy",
|
|
1816
|
+
severity: "high",
|
|
1817
|
+
message: `Multiple H1 headings (${h1Count}) - confuses page structure`,
|
|
1818
|
+
});
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
if (h2Count > 7) {
|
|
1822
|
+
recommendations.push(
|
|
1823
|
+
"Consider reducing number of H2 sections (current: " +
|
|
1824
|
+
h2Count +
|
|
1825
|
+
") - may overwhelm users",
|
|
1826
|
+
);
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
// Check for clear CTAs
|
|
1830
|
+
const ctaPatterns = [
|
|
1831
|
+
/class="[^"]*cta[^"]*"/i,
|
|
1832
|
+
/class="[^"]*button[^"]*"/i,
|
|
1833
|
+
/<button/i,
|
|
1834
|
+
];
|
|
1835
|
+
const hasCTA = ctaPatterns.some((pattern) => pattern.test(designCode));
|
|
1836
|
+
|
|
1837
|
+
if (!hasCTA && pageType === "landing") {
|
|
1838
|
+
issues.push({
|
|
1839
|
+
type: "conversion",
|
|
1840
|
+
severity: "high",
|
|
1841
|
+
message: "No clear CTA found - users don't know what to do",
|
|
1842
|
+
});
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
// Check for progressive disclosure (accordions, tabs, etc.)
|
|
1846
|
+
const hasProgressiveDisclosure =
|
|
1847
|
+
designCode.includes("accordion") ||
|
|
1848
|
+
designCode.includes("tab") ||
|
|
1849
|
+
designCode.includes("collapsible");
|
|
1850
|
+
if (!hasProgressiveDisclosure && designCode.length > 5000) {
|
|
1851
|
+
recommendations.push(
|
|
1852
|
+
"Consider progressive disclosure (accordions/tabs) to reduce cognitive load",
|
|
1853
|
+
);
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
// Check for "Don't Make Me Think" violations
|
|
1857
|
+
const unclearLabels = [/click here/i, /read more/i, /learn more$/i];
|
|
1858
|
+
unclearLabels.forEach((pattern) => {
|
|
1859
|
+
if (pattern.test(designCode)) {
|
|
1860
|
+
issues.push({
|
|
1861
|
+
type: "usability",
|
|
1862
|
+
severity: "medium",
|
|
1863
|
+
message: `Vague link text found: "${pattern.source}" - be descriptive`,
|
|
1864
|
+
});
|
|
1865
|
+
}
|
|
1866
|
+
});
|
|
1867
|
+
|
|
1868
|
+
return {
|
|
1869
|
+
content: [
|
|
1870
|
+
{
|
|
1871
|
+
type: "text",
|
|
1872
|
+
text: `## Visual Hierarchy & Cognitive Load Analysis\n\n### "Don't Make Me Think" Score: ${Math.max(0, cognitiveLoadScore - issues.length * 10)}/100\n\n### Heading Structure:\n- H1: ${h1Count} ${h1Count === 1 ? "✅" : "❌"}\n- H2: ${h2Count}\n- H3: ${h3Count}\n\n### Issues (${issues.length}):\n${issues.map((i: HierarchyIssue) => `- ${i.severity.toUpperCase()}: ${i.message}`).join("\n") || "None"}\n\n### Cognitive Load Recommendations:\n${recommendations.map((r: string) => `- ${r}`).join("\n") || "None"}\n\n### 3-Second Rule Checklist:\n- [ ] Page purpose immediately clear\n- [ ] Primary action obvious\n- [ ] No ambiguous labels\n- [ ] Clear visual hierarchy\n- [ ] Progressive disclosure used`,
|
|
1873
|
+
},
|
|
1874
|
+
],
|
|
1875
|
+
};
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
private async recommendImages(args: RecommendImagesArgs): Promise<ToolResponse> {
|
|
1879
|
+
const { context, style = "photography", budget = "free" } = args;
|
|
1880
|
+
|
|
1881
|
+
const recommendations: ImageRecommendations = {
|
|
1882
|
+
libraries: [],
|
|
1883
|
+
tips: [],
|
|
1884
|
+
style: style,
|
|
1885
|
+
};
|
|
1886
|
+
|
|
1887
|
+
// Context-specific recommendations
|
|
1888
|
+
if (context.toLowerCase().includes("hero")) {
|
|
1889
|
+
recommendations.tips.push(
|
|
1890
|
+
"Hero images should be high-impact but not compete with text",
|
|
1891
|
+
);
|
|
1892
|
+
recommendations.tips.push(
|
|
1893
|
+
"Use overlay/gradient to ensure text readability",
|
|
1894
|
+
);
|
|
1895
|
+
recommendations.tips.push(
|
|
1896
|
+
"Recommended size: 1920x1080px, optimized to < 200KB",
|
|
1897
|
+
);
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1900
|
+
if (
|
|
1901
|
+
context.toLowerCase().includes("team") ||
|
|
1902
|
+
context.toLowerCase().includes("portrait")
|
|
1903
|
+
) {
|
|
1904
|
+
recommendations.tips.push(
|
|
1905
|
+
"Use consistent lighting and background for team photos",
|
|
1906
|
+
);
|
|
1907
|
+
recommendations.tips.push("Square or 4:5 aspect ratio works best");
|
|
1908
|
+
}
|
|
1909
|
+
|
|
1910
|
+
if (context.toLowerCase().includes("product")) {
|
|
1911
|
+
recommendations.tips.push(
|
|
1912
|
+
"Use high-quality product photography with neutral background",
|
|
1913
|
+
);
|
|
1914
|
+
recommendations.tips.push("Include multiple angles and detail shots");
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1917
|
+
// Library recommendations based on budget and style
|
|
1918
|
+
if (budget === "free") {
|
|
1919
|
+
if (style === "photography") {
|
|
1920
|
+
recommendations.libraries.push({
|
|
1921
|
+
name: "Unsplash",
|
|
1922
|
+
url: "unsplash.com",
|
|
1923
|
+
description: "Free, high-quality photography",
|
|
1924
|
+
});
|
|
1925
|
+
recommendations.libraries.push({
|
|
1926
|
+
name: "Pexels",
|
|
1927
|
+
url: "pexels.com",
|
|
1928
|
+
description: "Free stock photos and videos",
|
|
1929
|
+
});
|
|
1930
|
+
} else if (style === "illustration") {
|
|
1931
|
+
recommendations.libraries.push({
|
|
1932
|
+
name: "unDraw",
|
|
1933
|
+
url: "undraw.co",
|
|
1934
|
+
description: "Customizable open-source illustrations",
|
|
1935
|
+
});
|
|
1936
|
+
recommendations.libraries.push({
|
|
1937
|
+
name: "Humaaans",
|
|
1938
|
+
url: "humaaans.com",
|
|
1939
|
+
description: "Mix-and-match people illustrations",
|
|
1940
|
+
});
|
|
1941
|
+
} else if (style === "3d") {
|
|
1942
|
+
recommendations.libraries.push({
|
|
1943
|
+
name: "BlenderKit",
|
|
1944
|
+
url: "blenderkit.com",
|
|
1945
|
+
description: "Free 3D assets",
|
|
1946
|
+
});
|
|
1947
|
+
}
|
|
1948
|
+
} else if (budget === "premium") {
|
|
1949
|
+
recommendations.libraries.push({
|
|
1950
|
+
name: "Shutterstock",
|
|
1951
|
+
url: "shutterstock.com",
|
|
1952
|
+
description: "Extensive premium catalog",
|
|
1953
|
+
});
|
|
1954
|
+
recommendations.libraries.push({
|
|
1955
|
+
name: "Getty Images",
|
|
1956
|
+
url: "gettyimages.com",
|
|
1957
|
+
description: "Editorial and commercial quality",
|
|
1958
|
+
});
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
// Icon recommendations
|
|
1962
|
+
recommendations.libraries.push({
|
|
1963
|
+
name: "Lucide",
|
|
1964
|
+
url: "lucide.dev",
|
|
1965
|
+
description: "Clean, consistent icon library (Free)",
|
|
1966
|
+
});
|
|
1967
|
+
recommendations.libraries.push({
|
|
1968
|
+
name: "Heroicons",
|
|
1969
|
+
url: "heroicons.com",
|
|
1970
|
+
description: "Beautiful SVG icons by Tailwind (Free)",
|
|
1971
|
+
});
|
|
1972
|
+
|
|
1973
|
+
return {
|
|
1974
|
+
content: [
|
|
1975
|
+
{
|
|
1976
|
+
type: "text",
|
|
1977
|
+
text: `## Image Recommendations for: ${context}\n\n### Style: ${style}\n### Budget: ${budget}\n\n### Recommended Libraries:\n${recommendations.libraries.map((lib: ImageLibrary) => `- **${lib.name}** (${lib.url})\n ${lib.description}`).join("\n")}\n\n### Context-Specific Tips:\n${recommendations.tips.map((tip: string) => `- ${tip}`).join("\n")}\n\n### Image Optimization Checklist:\n- [ ] WebP format with JPEG fallback\n- [ ] Responsive srcset for different sizes\n- [ ] Alt text describing purpose (not just "image")\n- [ ] Lazy loading for below-fold images\n- [ ] Compressed to < 200KB without quality loss\n- [ ] Consistent style across all images`,
|
|
1978
|
+
},
|
|
1979
|
+
],
|
|
1980
|
+
};
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
async run(): Promise<void> {
|
|
1984
|
+
const transport = new StdioServerTransport();
|
|
1985
|
+
await this.server.connect(transport);
|
|
1986
|
+
await frameworkLogger.log(
|
|
1987
|
+
"ui-ux-design.server",
|
|
1988
|
+
"-strray-ui-ux-design-mcp-server-running-",
|
|
1989
|
+
"info",
|
|
1990
|
+
{ message: "xray UI/UX Design MCP Server running..." },
|
|
1991
|
+
);
|
|
1992
|
+
|
|
1993
|
+
const cleanup = async (signal: string) => {
|
|
1994
|
+
await frameworkLogger.log(
|
|
1995
|
+
"ui-ux-design.server",
|
|
1996
|
+
"-received-signal-shutting-down-gracefully-",
|
|
1997
|
+
"info",
|
|
1998
|
+
{ message: `Received ${signal}, shutting down gracefully...` },
|
|
1999
|
+
);
|
|
2000
|
+
|
|
2001
|
+
// Set a timeout to force exit if graceful shutdown fails
|
|
2002
|
+
const timeout = setTimeout(() => {
|
|
2003
|
+
frameworkLogger.log("mcps/ui-ux-design", "shutdown", "error", { message: "Graceful shutdown timeout, forcing exit..." });
|
|
2004
|
+
process.exit(1);
|
|
2005
|
+
}, 5000); // 5 second timeout
|
|
2006
|
+
|
|
2007
|
+
try {
|
|
2008
|
+
if (this.server && typeof this.server.close === "function") {
|
|
2009
|
+
await this.server.close();
|
|
2010
|
+
}
|
|
2011
|
+
clearTimeout(timeout);
|
|
2012
|
+
await frameworkLogger.log(
|
|
2013
|
+
"ui-ux-design.server",
|
|
2014
|
+
"-strray-mcp-server-shut-down-gracefully-",
|
|
2015
|
+
"info",
|
|
2016
|
+
{ message: "xray MCP Server shut down gracefully" },
|
|
2017
|
+
);
|
|
2018
|
+
process.exit(0);
|
|
2019
|
+
} catch (error) {
|
|
2020
|
+
clearTimeout(timeout);
|
|
2021
|
+
frameworkLogger.log("mcps/ui-ux-design", "shutdown", "error", { message: `Error during server shutdown: ${String(error)}` });
|
|
2022
|
+
process.exit(1);
|
|
2023
|
+
}
|
|
2024
|
+
};
|
|
2025
|
+
|
|
2026
|
+
// Handle multiple shutdown signals
|
|
2027
|
+
process.on("SIGINT", () => cleanup("SIGINT"));
|
|
2028
|
+
process.on("SIGTERM", () => cleanup("SIGTERM"));
|
|
2029
|
+
process.on("SIGHUP", () => cleanup("SIGHUP"));
|
|
2030
|
+
|
|
2031
|
+
// Monitor parent process (opencode) and shutdown if it dies
|
|
2032
|
+
const checkParent = async () => {
|
|
2033
|
+
try {
|
|
2034
|
+
process.kill(process.ppid, 0); // Check if parent is alive
|
|
2035
|
+
setTimeout(checkParent, 1000); // Check again in 1 second
|
|
2036
|
+
} catch (error) {
|
|
2037
|
+
// Parent process died, shut down gracefully
|
|
2038
|
+
await frameworkLogger.log(
|
|
2039
|
+
"ui-ux-design.server",
|
|
2040
|
+
"-parent-process-opencode-died-shutting-down-mcp-se",
|
|
2041
|
+
"info",
|
|
2042
|
+
{
|
|
2043
|
+
message:
|
|
2044
|
+
"Parent process (opencode) died, shutting down MCP server...",
|
|
2045
|
+
},
|
|
2046
|
+
);
|
|
2047
|
+
cleanup("parent-process-death");
|
|
2048
|
+
}
|
|
2049
|
+
};
|
|
2050
|
+
|
|
2051
|
+
// Start monitoring parent process
|
|
2052
|
+
setTimeout(checkParent, 2000); // Start checking after 2 seconds
|
|
2053
|
+
|
|
2054
|
+
// Handle uncaught exceptions and unhandled rejections
|
|
2055
|
+
process.on("uncaughtException", (error) => {
|
|
2056
|
+
frameworkLogger.log("mcps/ui-ux-design", "uncaughtException", "error", { error: String(error) });
|
|
2057
|
+
cleanup("uncaughtException");
|
|
2058
|
+
});
|
|
2059
|
+
|
|
2060
|
+
process.on("unhandledRejection", (reason, promise) => {
|
|
2061
|
+
frameworkLogger.log("mcps/ui-ux-design", "unhandledRejection", "error", { error: String(reason) });
|
|
2062
|
+
cleanup("unhandledRejection");
|
|
2063
|
+
});
|
|
2064
|
+
|
|
2065
|
+
process.on("SIGINT", cleanup);
|
|
2066
|
+
process.on("SIGTERM", cleanup);
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
|
|
2070
|
+
// Run the server if this file is executed directly
|
|
2071
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
2072
|
+
const server = new StringRayUIUXDesignServer();
|
|
2073
|
+
server.run().catch((error) => frameworkLogger.log("mcps/ui-ux-design", "run", "error", { error: String(error) }));
|
|
2074
|
+
}
|
|
2075
|
+
|
|
2076
|
+
export { StringRayUIUXDesignServer };
|