blockmine 1.24.0 → 1.25.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/CHANGELOG.md +32 -0
- package/README.en.md +427 -0
- package/README.md +40 -0
- package/backend/cli.js +1 -1
- package/backend/src/ai/plugin-assistant-system-prompt.md +664 -5
- package/backend/src/api/routes/bots.js +13 -0
- package/backend/src/api/routes/servers.js +14 -2
- package/backend/src/core/BotProcess.js +98 -2
- package/backend/src/core/PluginLoader.js +83 -3
- package/backend/src/core/PluginManager.js +75 -5
- package/backend/src/core/services/BotLifecycleService.js +186 -2
- package/backend/src/server.js +11 -1
- package/frontend/dist/assets/browser-ponyfill-DN7pwmHT.js +2 -0
- package/frontend/dist/assets/index-LSy71uwm.js +11261 -0
- package/frontend/dist/assets/index-SfhKxI4-.css +32 -0
- package/frontend/dist/flags/en.svg +32 -0
- package/frontend/dist/flags/ru.svg +5 -0
- package/frontend/dist/index.html +2 -2
- package/frontend/dist/locales/en/admin.json +100 -0
- package/frontend/dist/locales/en/api-keys.json +58 -0
- package/frontend/dist/locales/en/bots.json +110 -0
- package/frontend/dist/locales/en/common.json +47 -0
- package/frontend/dist/locales/en/configuration.json +22 -0
- package/frontend/dist/locales/en/console.json +10 -0
- package/frontend/dist/locales/en/dashboard.json +85 -0
- package/frontend/dist/locales/en/dialogs.json +70 -0
- package/frontend/dist/locales/en/event-graphs.json +50 -0
- package/frontend/dist/locales/en/graph-store.json +70 -0
- package/frontend/dist/locales/en/login.json +34 -0
- package/frontend/dist/locales/en/management.json +114 -0
- package/frontend/dist/locales/en/minecraft-viewer.json +27 -0
- package/frontend/dist/locales/en/nodes.json +1077 -0
- package/frontend/dist/locales/en/permissions.json +50 -0
- package/frontend/dist/locales/en/plugin-detail.json +49 -0
- package/frontend/dist/locales/en/plugins.json +110 -0
- package/frontend/dist/locales/en/proxies.json +81 -0
- package/frontend/dist/locales/en/servers.json +39 -0
- package/frontend/dist/locales/en/setup.json +17 -0
- package/frontend/dist/locales/en/sidebar.json +27 -0
- package/frontend/dist/locales/en/tasks.json +62 -0
- package/frontend/dist/locales/en/visual-editor.json +219 -0
- package/frontend/dist/locales/en/websocket.json +86 -0
- package/frontend/dist/locales/ru/admin.json +100 -0
- package/frontend/dist/locales/ru/api-keys.json +58 -0
- package/frontend/dist/locales/ru/bots.json +110 -0
- package/frontend/dist/locales/ru/common.json +49 -0
- package/frontend/dist/locales/ru/configuration.json +22 -0
- package/frontend/dist/locales/ru/console.json +10 -0
- package/frontend/dist/locales/ru/dashboard.json +85 -0
- package/frontend/dist/locales/ru/dialogs.json +70 -0
- package/frontend/dist/locales/ru/event-graphs.json +50 -0
- package/frontend/dist/locales/ru/graph-store.json +70 -0
- package/frontend/dist/locales/ru/login.json +34 -0
- package/frontend/dist/locales/ru/management.json +114 -0
- package/frontend/dist/locales/ru/minecraft-viewer.json +27 -0
- package/frontend/dist/locales/ru/nodes.json +1077 -0
- package/frontend/dist/locales/ru/permissions.json +50 -0
- package/frontend/dist/locales/ru/plugin-detail.json +49 -0
- package/frontend/dist/locales/ru/plugins.json +110 -0
- package/frontend/dist/locales/ru/proxies.json +81 -0
- package/frontend/dist/locales/ru/servers.json +39 -0
- package/frontend/dist/locales/ru/setup.json +17 -0
- package/frontend/dist/locales/ru/sidebar.json +27 -0
- package/frontend/dist/locales/ru/tasks.json +62 -0
- package/frontend/dist/locales/ru/visual-editor.json +221 -0
- package/frontend/dist/locales/ru/websocket.json +86 -0
- package/frontend/dist/monacoeditorwork/css.worker.bundle.js +7 -7
- package/frontend/dist/monacoeditorwork/html.worker.bundle.js +7 -7
- package/frontend/dist/monacoeditorwork/json.worker.bundle.js +7 -7
- package/frontend/dist/monacoeditorwork/ts.worker.bundle.js +3 -3
- package/frontend/package.json +4 -0
- package/package.json +1 -1
- package/screen/3dviewer.png +0 -0
- package/screen/console.png +0 -0
- package/screen/dashboard.png +0 -0
- package/screen/graph_collabe.png +0 -0
- package/screen/graph_live_debug.png +0 -0
- package/screen/language_selector.png +0 -0
- package/screen/management_command.png +0 -0
- package/screen/node_debug_trace.png +0 -0
- package/screen/plugin_/320/276/320/261/320/267/320/276/321/200.png +0 -0
- package/screen/websocket.png +0 -0
- package/screen//320/275/320/260/321/201/321/202/321/200/320/276/320/271/320/272/320/270_/320/276/321/202/320/264/320/265/320/273/321/214/320/275/321/213/321/205_/320/272/320/276/320/274/320/260/320/275/320/264_/320/272/320/260/320/266/320/264/321/203_/320/272/320/276/320/274/320/260/320/275/320/273/320/264/321/203_/320/274/320/276/320/266/320/275/320/276_/320/275/320/260/321/201/321/202/321/200/320/260/320/270/320/262/320/260/321/202/321/214.png +0 -0
- package/screen//320/277/320/273/320/260/320/275/320/270/321/200/320/276/320/262/321/211/320/270/320/272_/320/274/320/276/320/266/320/275/320/276_/320/267/320/260/320/264/320/260/320/262/320/260/321/202/321/214_/320/264/320/265/320/271/321/201/321/202/320/262/320/270/321/217_/320/277/320/276_/320/262/321/200/320/265/320/274/320/265/320/275/320/270.png +0 -0
- package/.claude/agents/README.md +0 -469
- package/.claude/agents/auth-route-debugger.md +0 -118
- package/.claude/agents/auth-route-tester.md +0 -93
- package/.claude/agents/auto-error-resolver.md +0 -97
- package/.claude/agents/build-optimizer.md +0 -236
- package/.claude/agents/code-architect.md +0 -34
- package/.claude/agents/code-architecture-reviewer.md +0 -83
- package/.claude/agents/code-explorer.md +0 -51
- package/.claude/agents/code-refactor-master.md +0 -94
- package/.claude/agents/code-reviewer.md +0 -46
- package/.claude/agents/cost-optimizer.md +0 -134
- package/.claude/agents/deployment-orchestrator.md +0 -113
- package/.claude/agents/documentation-architect.md +0 -82
- package/.claude/agents/frontend-error-fixer.md +0 -77
- package/.claude/agents/iac-code-generator.md +0 -71
- package/.claude/agents/incident-responder.md +0 -346
- package/.claude/agents/infrastructure-architect.md +0 -31
- package/.claude/agents/kubernetes-specialist.md +0 -56
- package/.claude/agents/migration-planner.md +0 -181
- package/.claude/agents/network-architect.md +0 -196
- package/.claude/agents/plan-reviewer.md +0 -52
- package/.claude/agents/refactor-planner.md +0 -63
- package/.claude/agents/security-scanner.md +0 -102
- package/.claude/agents/web-research-specialist.md +0 -78
- package/.claude/commands/cost-analysis.md +0 -315
- package/.claude/commands/dev-docs-update.md +0 -55
- package/.claude/commands/dev-docs.md +0 -51
- package/.claude/commands/feature-dev.md +0 -125
- package/.claude/commands/incident-debug.md +0 -247
- package/.claude/commands/infra-plan.md +0 -81
- package/.claude/commands/migration-plan.md +0 -478
- package/.claude/commands/route-research-for-testing.md +0 -37
- package/.claude/commands/security-review.md +0 -66
- package/.claude/hooks/CONFIG.md +0 -448
- package/.claude/hooks/README.md +0 -163
- package/.claude/hooks/SKILL_ACTIVATION_COMPLETE.md +0 -226
- package/.claude/hooks/WINDOWS_HOOKS_README.md +0 -151
- package/.claude/hooks/add-skill-activation-banners.ts +0 -132
- package/.claude/hooks/comprehensive-skill-test.ts +0 -1315
- package/.claude/hooks/error-handling-reminder.sh +0 -12
- package/.claude/hooks/error-handling-reminder.ts +0 -222
- package/.claude/hooks/k8s-manifest-validator.sh +0 -56
- package/.claude/hooks/package-lock.json +0 -556
- package/.claude/hooks/package.json +0 -16
- package/.claude/hooks/post-tool-use-tracker.ps1 +0 -174
- package/.claude/hooks/post-tool-use-tracker.sh +0 -183
- package/.claude/hooks/security-policy-check.sh +0 -247
- package/.claude/hooks/skill-activation-prompt.ps1 +0 -10
- package/.claude/hooks/skill-activation-prompt.sh +0 -10
- package/.claude/hooks/skill-activation-prompt.ts +0 -141
- package/.claude/hooks/stop-build-check-enhanced.sh +0 -130
- package/.claude/hooks/terraform-validator.sh +0 -53
- package/.claude/hooks/test-input.json +0 -7
- package/.claude/hooks/test-skill-activation.ts +0 -427
- package/.claude/hooks/trigger-build-resolver.sh +0 -79
- package/.claude/hooks/tsc-check.sh +0 -173
- package/.claude/hooks/tsconfig.json +0 -19
- package/.claude/settings.json +0 -59
- package/.claude/settings.local.json +0 -67
- package/.claude/skills/README.md +0 -507
- package/.claude/skills/api-engineering/SKILL.md +0 -63
- package/.claude/skills/api-engineering/resources/api-versioning.md +0 -88
- package/.claude/skills/api-engineering/resources/graphql-patterns.md +0 -106
- package/.claude/skills/api-engineering/resources/rate-limiting.md +0 -118
- package/.claude/skills/api-engineering/resources/rest-api-design.md +0 -105
- package/.claude/skills/backend-dev-guidelines/SKILL.md +0 -306
- package/.claude/skills/backend-dev-guidelines/resources/architecture-overview.md +0 -451
- package/.claude/skills/backend-dev-guidelines/resources/async-and-errors.md +0 -307
- package/.claude/skills/backend-dev-guidelines/resources/complete-examples.md +0 -638
- package/.claude/skills/backend-dev-guidelines/resources/configuration.md +0 -275
- package/.claude/skills/backend-dev-guidelines/resources/database-patterns.md +0 -224
- package/.claude/skills/backend-dev-guidelines/resources/middleware-guide.md +0 -213
- package/.claude/skills/backend-dev-guidelines/resources/routing-and-controllers.md +0 -756
- package/.claude/skills/backend-dev-guidelines/resources/sentry-and-monitoring.md +0 -336
- package/.claude/skills/backend-dev-guidelines/resources/services-and-repositories.md +0 -789
- package/.claude/skills/backend-dev-guidelines/resources/testing-guide.md +0 -235
- package/.claude/skills/backend-dev-guidelines/resources/validation-patterns.md +0 -754
- package/.claude/skills/budget-and-cost-management/SKILL.md +0 -850
- package/.claude/skills/build-engineering/SKILL.md +0 -431
- package/.claude/skills/build-engineering/resources/artifact-repositories.md +0 -72
- package/.claude/skills/build-engineering/resources/build-caching.md +0 -96
- package/.claude/skills/build-engineering/resources/build-pipelines.md +0 -105
- package/.claude/skills/build-engineering/resources/build-security.md +0 -95
- package/.claude/skills/build-engineering/resources/build-systems.md +0 -389
- package/.claude/skills/build-engineering/resources/compilation-optimization.md +0 -201
- package/.claude/skills/build-engineering/resources/dependency-management.md +0 -73
- package/.claude/skills/build-engineering/resources/monorepo-builds.md +0 -110
- package/.claude/skills/build-engineering/resources/performance-optimization.md +0 -113
- package/.claude/skills/build-engineering/resources/reproducible-builds.md +0 -82
- package/.claude/skills/cloud-engineering/SKILL.md +0 -675
- package/.claude/skills/cloud-engineering/resources/aws-patterns.md +0 -742
- package/.claude/skills/cloud-engineering/resources/azure-patterns.md +0 -714
- package/.claude/skills/cloud-engineering/resources/cleared-cloud-environments.md +0 -987
- package/.claude/skills/cloud-engineering/resources/cloud-cost-optimization.md +0 -757
- package/.claude/skills/cloud-engineering/resources/cloud-networking.md +0 -1058
- package/.claude/skills/cloud-engineering/resources/cloud-security-tools.md +0 -1530
- package/.claude/skills/cloud-engineering/resources/cloud-security.md +0 -990
- package/.claude/skills/cloud-engineering/resources/gcp-patterns.md +0 -758
- package/.claude/skills/cloud-engineering/resources/migration-strategies.md +0 -820
- package/.claude/skills/cloud-engineering/resources/multi-cloud-strategies.md +0 -670
- package/.claude/skills/cloud-engineering/resources/oci-patterns.md +0 -1198
- package/.claude/skills/cloud-engineering/resources/serverless-patterns.md +0 -795
- package/.claude/skills/cloud-engineering/resources/well-architected-frameworks.md +0 -966
- package/.claude/skills/cybersecurity/SKILL.md +0 -409
- package/.claude/skills/cybersecurity/resources/security-architecture.md +0 -266
- package/.claude/skills/database-engineering/SKILL.md +0 -61
- package/.claude/skills/database-engineering/resources/backup-and-recovery.md +0 -72
- package/.claude/skills/database-engineering/resources/database-replication.md +0 -63
- package/.claude/skills/database-engineering/resources/postgresql-fundamentals.md +0 -70
- package/.claude/skills/database-engineering/resources/query-optimization.md +0 -68
- package/.claude/skills/devsecops/SKILL.md +0 -374
- package/.claude/skills/devsecops/resources/ci-cd-security.md +0 -204
- package/.claude/skills/devsecops/resources/compliance-automation.md +0 -530
- package/.claude/skills/devsecops/resources/compliance-frameworks.md +0 -2322
- package/.claude/skills/devsecops/resources/container-security.md +0 -915
- package/.claude/skills/devsecops/resources/cspm-integration.md +0 -1440
- package/.claude/skills/devsecops/resources/policy-enforcement.md +0 -619
- package/.claude/skills/devsecops/resources/secrets-management.md +0 -755
- package/.claude/skills/devsecops/resources/security-monitoring.md +0 -146
- package/.claude/skills/devsecops/resources/security-scanning.md +0 -887
- package/.claude/skills/devsecops/resources/security-testing.md +0 -203
- package/.claude/skills/devsecops/resources/supply-chain-security.md +0 -518
- package/.claude/skills/devsecops/resources/vulnerability-management.md +0 -481
- package/.claude/skills/devsecops/resources/zero-trust-architecture.md +0 -177
- package/.claude/skills/documentation-as-code/SKILL.md +0 -323
- package/.claude/skills/documentation-as-code/resources/api-documentation.md +0 -90
- package/.claude/skills/documentation-as-code/resources/changelog-management.md +0 -79
- package/.claude/skills/documentation-as-code/resources/diagram-generation.md +0 -44
- package/.claude/skills/documentation-as-code/resources/docs-as-code-workflow.md +0 -99
- package/.claude/skills/documentation-as-code/resources/documentation-automation.md +0 -68
- package/.claude/skills/documentation-as-code/resources/documentation-sites.md +0 -79
- package/.claude/skills/documentation-as-code/resources/markdown-best-practices.md +0 -162
- package/.claude/skills/documentation-as-code/resources/openapi-specification.md +0 -77
- package/.claude/skills/documentation-as-code/resources/readme-engineering.md +0 -60
- package/.claude/skills/documentation-as-code/resources/technical-writing-guide.md +0 -202
- package/.claude/skills/engineering-management/SKILL.md +0 -356
- package/.claude/skills/engineering-management/resources/career-ladders.md +0 -609
- package/.claude/skills/engineering-management/resources/hiring-and-assessment.md +0 -555
- package/.claude/skills/engineering-management/resources/one-on-one-guides.md +0 -609
- package/.claude/skills/engineering-management/resources/resource-planning.md +0 -557
- package/.claude/skills/engineering-management/resources/team-organization-patterns.md +0 -491
- package/.claude/skills/engineering-management/resources/technical-interviews.md +0 -474
- package/.claude/skills/engineering-operations-management/SKILL.md +0 -817
- package/.claude/skills/error-tracking/SKILL.md +0 -379
- package/.claude/skills/frontend-design/SKILL.md +0 -42
- package/.claude/skills/frontend-dev-guidelines/SKILL.md +0 -403
- package/.claude/skills/frontend-dev-guidelines/resources/common-patterns.md +0 -331
- package/.claude/skills/frontend-dev-guidelines/resources/complete-examples.md +0 -872
- package/.claude/skills/frontend-dev-guidelines/resources/component-patterns.md +0 -502
- package/.claude/skills/frontend-dev-guidelines/resources/data-fetching.md +0 -767
- package/.claude/skills/frontend-dev-guidelines/resources/file-organization.md +0 -502
- package/.claude/skills/frontend-dev-guidelines/resources/loading-and-error-states.md +0 -501
- package/.claude/skills/frontend-dev-guidelines/resources/performance.md +0 -406
- package/.claude/skills/frontend-dev-guidelines/resources/routing-guide.md +0 -364
- package/.claude/skills/frontend-dev-guidelines/resources/styling-guide.md +0 -428
- package/.claude/skills/frontend-dev-guidelines/resources/typescript-standards.md +0 -418
- package/.claude/skills/general-it-engineering/SKILL.md +0 -393
- package/.claude/skills/general-it-engineering/resources/asset-management.md +0 -712
- package/.claude/skills/general-it-engineering/resources/automation-orchestration.md +0 -817
- package/.claude/skills/general-it-engineering/resources/business-continuity.md +0 -786
- package/.claude/skills/general-it-engineering/resources/change-management.md +0 -715
- package/.claude/skills/general-it-engineering/resources/enterprise-monitoring.md +0 -729
- package/.claude/skills/general-it-engineering/resources/help-desk-operations.md +0 -738
- package/.claude/skills/general-it-engineering/resources/incident-service-management.md +0 -834
- package/.claude/skills/general-it-engineering/resources/it-governance.md +0 -753
- package/.claude/skills/general-it-engineering/resources/itil-framework.md +0 -503
- package/.claude/skills/general-it-engineering/resources/service-management.md +0 -669
- package/.claude/skills/infrastructure-architecture/SKILL.md +0 -328
- package/.claude/skills/infrastructure-architecture/resources/architecture-decision-records.md +0 -505
- package/.claude/skills/infrastructure-architecture/resources/architecture-patterns.md +0 -528
- package/.claude/skills/infrastructure-architecture/resources/capacity-planning.md +0 -453
- package/.claude/skills/infrastructure-architecture/resources/cleared-environment-architecture.md +0 -773
- package/.claude/skills/infrastructure-architecture/resources/cost-architecture.md +0 -499
- package/.claude/skills/infrastructure-architecture/resources/data-architecture.md +0 -501
- package/.claude/skills/infrastructure-architecture/resources/disaster-recovery.md +0 -535
- package/.claude/skills/infrastructure-architecture/resources/migration-architecture.md +0 -512
- package/.claude/skills/infrastructure-architecture/resources/multi-region-design.md +0 -608
- package/.claude/skills/infrastructure-architecture/resources/reference-architectures.md +0 -562
- package/.claude/skills/infrastructure-architecture/resources/security-architecture.md +0 -538
- package/.claude/skills/infrastructure-architecture/resources/system-design-principles.md +0 -489
- package/.claude/skills/infrastructure-architecture/resources/workload-classification.md +0 -1000
- package/.claude/skills/infrastructure-strategy/SKILL.md +0 -924
- package/.claude/skills/network-engineering/SKILL.md +0 -385
- package/.claude/skills/network-engineering/resources/dns-management.md +0 -738
- package/.claude/skills/network-engineering/resources/load-balancing.md +0 -820
- package/.claude/skills/network-engineering/resources/network-architecture.md +0 -546
- package/.claude/skills/network-engineering/resources/network-security.md +0 -921
- package/.claude/skills/network-engineering/resources/network-troubleshooting.md +0 -749
- package/.claude/skills/network-engineering/resources/routing-switching.md +0 -373
- package/.claude/skills/network-engineering/resources/sdn-networking.md +0 -695
- package/.claude/skills/network-engineering/resources/service-mesh-networking.md +0 -777
- package/.claude/skills/network-engineering/resources/tcp-ip-protocols.md +0 -444
- package/.claude/skills/network-engineering/resources/vpn-connectivity.md +0 -672
- package/.claude/skills/node-development/SKILL.md +0 -317
- package/.claude/skills/observability-engineering/SKILL.md +0 -101
- package/.claude/skills/observability-engineering/resources/apm-tools.md +0 -97
- package/.claude/skills/observability-engineering/resources/correlation-strategies.md +0 -87
- package/.claude/skills/observability-engineering/resources/distributed-tracing.md +0 -98
- package/.claude/skills/observability-engineering/resources/logs-aggregation.md +0 -118
- package/.claude/skills/observability-engineering/resources/observability-cost-optimization.md +0 -141
- package/.claude/skills/observability-engineering/resources/opentelemetry.md +0 -110
- package/.claude/skills/platform-engineering/SKILL.md +0 -555
- package/.claude/skills/platform-engineering/resources/architecture-overview.md +0 -600
- package/.claude/skills/platform-engineering/resources/container-orchestration.md +0 -916
- package/.claude/skills/platform-engineering/resources/cost-optimization.md +0 -634
- package/.claude/skills/platform-engineering/resources/developer-platforms.md +0 -670
- package/.claude/skills/platform-engineering/resources/gitops-automation.md +0 -650
- package/.claude/skills/platform-engineering/resources/infrastructure-as-code.md +0 -778
- package/.claude/skills/platform-engineering/resources/infrastructure-standards.md +0 -708
- package/.claude/skills/platform-engineering/resources/multi-tenancy.md +0 -602
- package/.claude/skills/platform-engineering/resources/platform-security.md +0 -711
- package/.claude/skills/platform-engineering/resources/resource-management.md +0 -592
- package/.claude/skills/platform-engineering/resources/service-mesh.md +0 -628
- package/.claude/skills/release-engineering/SKILL.md +0 -393
- package/.claude/skills/release-engineering/resources/artifact-management.md +0 -108
- package/.claude/skills/release-engineering/resources/build-optimization.md +0 -84
- package/.claude/skills/release-engineering/resources/ci-cd-pipelines.md +0 -411
- package/.claude/skills/release-engineering/resources/deployment-strategies.md +0 -197
- package/.claude/skills/release-engineering/resources/pipeline-security.md +0 -62
- package/.claude/skills/release-engineering/resources/progressive-delivery.md +0 -83
- package/.claude/skills/release-engineering/resources/release-automation.md +0 -68
- package/.claude/skills/release-engineering/resources/release-orchestration.md +0 -77
- package/.claude/skills/release-engineering/resources/rollback-strategies.md +0 -66
- package/.claude/skills/release-engineering/resources/versioning-strategies.md +0 -59
- package/.claude/skills/route-tester/SKILL.md +0 -392
- package/.claude/skills/skill-developer/ADVANCED.md +0 -197
- package/.claude/skills/skill-developer/HOOK_MECHANISMS.md +0 -306
- package/.claude/skills/skill-developer/PATTERNS_LIBRARY.md +0 -152
- package/.claude/skills/skill-developer/SKILL.md +0 -430
- package/.claude/skills/skill-developer/SKILL_RULES_REFERENCE.md +0 -315
- package/.claude/skills/skill-developer/TRIGGER_TYPES.md +0 -305
- package/.claude/skills/skill-developer/TROUBLESHOOTING.md +0 -514
- package/.claude/skills/skill-rules.json +0 -2989
- package/.claude/skills/sre/SKILL.md +0 -464
- package/.claude/skills/sre/resources/alerting-best-practices.md +0 -282
- package/.claude/skills/sre/resources/capacity-planning.md +0 -226
- package/.claude/skills/sre/resources/chaos-engineering.md +0 -193
- package/.claude/skills/sre/resources/disaster-recovery.md +0 -232
- package/.claude/skills/sre/resources/incident-management.md +0 -436
- package/.claude/skills/sre/resources/observability-stack.md +0 -240
- package/.claude/skills/sre/resources/on-call-runbooks.md +0 -167
- package/.claude/skills/sre/resources/performance-optimization.md +0 -108
- package/.claude/skills/sre/resources/reliability-patterns.md +0 -183
- package/.claude/skills/sre/resources/slo-sli-sla.md +0 -464
- package/.claude/skills/sre/resources/toil-reduction.md +0 -145
- package/.claude/skills/systems-engineering/SKILL.md +0 -648
- package/.claude/skills/systems-engineering/resources/automation-patterns.md +0 -771
- package/.claude/skills/systems-engineering/resources/configuration-management.md +0 -998
- package/.claude/skills/systems-engineering/resources/linux-administration.md +0 -672
- package/.claude/skills/systems-engineering/resources/networking-fundamentals.md +0 -982
- package/.claude/skills/systems-engineering/resources/performance-tuning.md +0 -871
- package/.claude/skills/systems-engineering/resources/powershell-scripting.md +0 -482
- package/.claude/skills/systems-engineering/resources/security-hardening.md +0 -739
- package/.claude/skills/systems-engineering/resources/shell-scripting.md +0 -915
- package/.claude/skills/systems-engineering/resources/storage-management.md +0 -628
- package/.claude/skills/systems-engineering/resources/system-monitoring.md +0 -787
- package/.claude/skills/systems-engineering/resources/troubleshooting-guide.md +0 -753
- package/.claude/skills/systems-engineering/resources/windows-administration.md +0 -738
- package/.claude/skills/technical-leadership/SKILL.md +0 -728
- package/backend/docs/SECRETS_DOCUMENTATION.md +0 -327
- package/frontend/dist/assets/index-BC-NbKXi.css +0 -32
- package/frontend/dist/assets/index-DqJXZMHY.js +0 -11266
|
@@ -477,8 +477,21 @@ router.put('/:id', authenticateUniversal, checkBotAccess, authorize('bot:update'
|
|
|
477
477
|
const proxyIdValue = dataToUpdate.proxyId;
|
|
478
478
|
delete dataToUpdate.proxyId;
|
|
479
479
|
if (proxyIdValue) {
|
|
480
|
+
// Используем прокси из списка - очищаем кастомные поля
|
|
480
481
|
dataToUpdate.proxy = { connect: { id: proxyIdValue } };
|
|
482
|
+
dataToUpdate.proxyHost = null;
|
|
483
|
+
dataToUpdate.proxyPort = null;
|
|
484
|
+
dataToUpdate.proxyUsername = null;
|
|
485
|
+
dataToUpdate.proxyPassword = null;
|
|
486
|
+
} else if (!dataToUpdate.proxyHost) {
|
|
487
|
+
// Отключаем прокси только если нет кастомного proxyHost
|
|
488
|
+
dataToUpdate.proxy = { disconnect: true };
|
|
489
|
+
dataToUpdate.proxyHost = null;
|
|
490
|
+
dataToUpdate.proxyPort = null;
|
|
491
|
+
dataToUpdate.proxyUsername = null;
|
|
492
|
+
dataToUpdate.proxyPassword = null;
|
|
481
493
|
} else {
|
|
494
|
+
// Кастомный прокси: отключаем связь с proxy, но сохраняем кастомные поля
|
|
482
495
|
dataToUpdate.proxy = { disconnect: true };
|
|
483
496
|
}
|
|
484
497
|
}
|
|
@@ -39,8 +39,14 @@ router.post('/', authorize('server:create'), async (req, res) => {
|
|
|
39
39
|
if (!name || !host || !version) {
|
|
40
40
|
return res.status(400).json({ error: 'Имя, хост и версия сервера обязательны' });
|
|
41
41
|
}
|
|
42
|
+
|
|
43
|
+
const portNumber = port ? parseInt(port, 10) : 25565;
|
|
44
|
+
if (isNaN(portNumber) || portNumber < 1 || portNumber > 65535) {
|
|
45
|
+
return res.status(400).json({ error: 'Порт должен быть числом от 1 до 65535 (максимум 5 цифр)' });
|
|
46
|
+
}
|
|
47
|
+
|
|
42
48
|
const newServer = await prisma.server.create({
|
|
43
|
-
data: { name, host, port:
|
|
49
|
+
data: { name, host, port: portNumber, version },
|
|
44
50
|
});
|
|
45
51
|
res.status(201).json(newServer);
|
|
46
52
|
} catch (error) {
|
|
@@ -58,7 +64,13 @@ router.put('/:id', authorize('server:create'), async (req, res) => {
|
|
|
58
64
|
const dataToUpdate = {};
|
|
59
65
|
if (name !== undefined) dataToUpdate.name = name;
|
|
60
66
|
if (host !== undefined) dataToUpdate.host = host;
|
|
61
|
-
if (port !== undefined && port !== '')
|
|
67
|
+
if (port !== undefined && port !== '') {
|
|
68
|
+
const portNumber = parseInt(port, 10);
|
|
69
|
+
if (isNaN(portNumber) || portNumber < 1 || portNumber > 65535) {
|
|
70
|
+
return res.status(400).json({ error: 'Порт должен быть числом от 1 до 65535 (максимум 5 цифр)' });
|
|
71
|
+
}
|
|
72
|
+
dataToUpdate.port = portNumber;
|
|
73
|
+
}
|
|
62
74
|
if (version !== undefined) dataToUpdate.version = version;
|
|
63
75
|
|
|
64
76
|
Object.keys(dataToUpdate).forEach(k => { if (dataToUpdate[k] === undefined) delete dataToUpdate[k]; });
|
|
@@ -6,7 +6,7 @@ const { Vec3 } = require('vec3');
|
|
|
6
6
|
const { PrismaClient } = require('@prisma/client');
|
|
7
7
|
const { loadCommands } = require('./system/CommandRegistry');
|
|
8
8
|
const { getRuntimeCommandRegistry } = require('./system/RuntimeCommandRegistry');
|
|
9
|
-
const { initializePlugins } = require('./PluginLoader');
|
|
9
|
+
const { initializePlugins, ensurePluginDependencies } = require('./PluginLoader');
|
|
10
10
|
const MessageQueue = require('./MessageQueue');
|
|
11
11
|
const Command = require('./system/Command');
|
|
12
12
|
const { parseArguments } = require('./system/parseArguments');
|
|
@@ -179,6 +179,16 @@ process.on('message', async (message) => {
|
|
|
179
179
|
}
|
|
180
180
|
pendingRequests.delete(message.requestId);
|
|
181
181
|
}
|
|
182
|
+
} else if (message.type === 'credentials_operation_response') {
|
|
183
|
+
if (pendingRequests.has(message.requestId)) {
|
|
184
|
+
const { resolve, reject } = pendingRequests.get(message.requestId);
|
|
185
|
+
if (message.error) {
|
|
186
|
+
reject(new Error(message.error));
|
|
187
|
+
} else {
|
|
188
|
+
resolve(message.payload);
|
|
189
|
+
}
|
|
190
|
+
pendingRequests.delete(message.requestId);
|
|
191
|
+
}
|
|
182
192
|
} else if (message.type === 'system:get_player_list') {
|
|
183
193
|
const playerList = bot ? Object.keys(bot.players) : [];
|
|
184
194
|
if (process.send) {
|
|
@@ -503,6 +513,9 @@ process.on('message', async (message) => {
|
|
|
503
513
|
bot.sendLog = sendLog;
|
|
504
514
|
bot.messageQueue = new MessageQueue(bot);
|
|
505
515
|
|
|
516
|
+
// Plugin Registry для экспорта API между плагинами
|
|
517
|
+
bot.pluginRegistry = new Map();
|
|
518
|
+
|
|
506
519
|
const installedPluginNames = config.plugins.map(p => p.name);
|
|
507
520
|
bot.api = {
|
|
508
521
|
Command: Command,
|
|
@@ -783,10 +796,92 @@ process.on('message', async (message) => {
|
|
|
783
796
|
payload: newState
|
|
784
797
|
});
|
|
785
798
|
}
|
|
799
|
+
},
|
|
800
|
+
|
|
801
|
+
// === Методы для управления credentials ===
|
|
802
|
+
updateCredentials: async ({ username, password }) => {
|
|
803
|
+
return new Promise((resolve, reject) => {
|
|
804
|
+
const requestId = uuidv4();
|
|
805
|
+
pendingRequests.set(requestId, { resolve, reject });
|
|
806
|
+
|
|
807
|
+
if (process.send) {
|
|
808
|
+
process.send({
|
|
809
|
+
type: 'update_credentials',
|
|
810
|
+
requestId,
|
|
811
|
+
payload: {
|
|
812
|
+
botId: bot.config.id,
|
|
813
|
+
username,
|
|
814
|
+
password
|
|
815
|
+
}
|
|
816
|
+
});
|
|
817
|
+
} else {
|
|
818
|
+
reject(new Error('IPC channel is not available.'));
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
setTimeout(() => {
|
|
822
|
+
if (pendingRequests.has(requestId)) {
|
|
823
|
+
reject(new Error('Request to update credentials timed out.'));
|
|
824
|
+
pendingRequests.delete(requestId);
|
|
825
|
+
}
|
|
826
|
+
}, 10000);
|
|
827
|
+
});
|
|
828
|
+
},
|
|
829
|
+
|
|
830
|
+
restart: async () => {
|
|
831
|
+
return new Promise((resolve, reject) => {
|
|
832
|
+
const requestId = uuidv4();
|
|
833
|
+
pendingRequests.set(requestId, { resolve, reject });
|
|
834
|
+
|
|
835
|
+
if (process.send) {
|
|
836
|
+
process.send({
|
|
837
|
+
type: 'restart_bot',
|
|
838
|
+
requestId,
|
|
839
|
+
payload: {
|
|
840
|
+
botId: bot.config.id
|
|
841
|
+
}
|
|
842
|
+
});
|
|
843
|
+
} else {
|
|
844
|
+
reject(new Error('IPC channel is not available.'));
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
setTimeout(() => {
|
|
848
|
+
if (pendingRequests.has(requestId)) {
|
|
849
|
+
reject(new Error('Request to restart bot timed out.'));
|
|
850
|
+
pendingRequests.delete(requestId);
|
|
851
|
+
}
|
|
852
|
+
}, 10000);
|
|
853
|
+
});
|
|
854
|
+
},
|
|
855
|
+
|
|
856
|
+
changeCredentials: async ({ username, password }) => {
|
|
857
|
+
return new Promise((resolve, reject) => {
|
|
858
|
+
const requestId = uuidv4();
|
|
859
|
+
pendingRequests.set(requestId, { resolve, reject });
|
|
860
|
+
|
|
861
|
+
if (process.send) {
|
|
862
|
+
process.send({
|
|
863
|
+
type: 'change_credentials',
|
|
864
|
+
requestId,
|
|
865
|
+
payload: {
|
|
866
|
+
botId: bot.config.id,
|
|
867
|
+
username,
|
|
868
|
+
password
|
|
869
|
+
}
|
|
870
|
+
});
|
|
871
|
+
} else {
|
|
872
|
+
reject(new Error('IPC channel is not available.'));
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
setTimeout(() => {
|
|
876
|
+
if (pendingRequests.has(requestId)) {
|
|
877
|
+
reject(new Error('Request to change credentials timed out.'));
|
|
878
|
+
pendingRequests.delete(requestId);
|
|
879
|
+
}
|
|
880
|
+
}, 10000);
|
|
881
|
+
});
|
|
786
882
|
}
|
|
787
883
|
};
|
|
788
884
|
|
|
789
|
-
// Упрощенный alias для отправки сообщений (используется в командах и нодах)
|
|
790
885
|
bot.sendMessage = (type, message, username) => {
|
|
791
886
|
bot.api.sendMessage(type, message, username);
|
|
792
887
|
};
|
|
@@ -909,6 +1004,7 @@ process.on('message', async (message) => {
|
|
|
909
1004
|
}
|
|
910
1005
|
}
|
|
911
1006
|
|
|
1007
|
+
await ensurePluginDependencies(config.plugins, sendLog);
|
|
912
1008
|
await initializePlugins(bot, config.plugins, prisma);
|
|
913
1009
|
sendLog('[System] Все системы инициализированы.');
|
|
914
1010
|
|
|
@@ -10,6 +10,61 @@ const { execSync: execSyncRaw } = require('child_process');
|
|
|
10
10
|
|
|
11
11
|
const projectRoot = path.resolve(__dirname, '..');
|
|
12
12
|
|
|
13
|
+
// Проверяет и устанавливает зависимости для всех плагинов
|
|
14
|
+
async function ensurePluginDependencies(installedPlugins = [], sendLog = console.log) {
|
|
15
|
+
if (!installedPlugins || installedPlugins.length === 0) return;
|
|
16
|
+
|
|
17
|
+
sendLog(`[PluginLoader] Проверка зависимостей ${installedPlugins.length} плагинов...`);
|
|
18
|
+
|
|
19
|
+
for (const plugin of installedPlugins) {
|
|
20
|
+
if (!plugin || !plugin.path) continue;
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const packageJsonPath = path.join(plugin.path, 'package.json');
|
|
24
|
+
|
|
25
|
+
// Проверяем есть ли package.json
|
|
26
|
+
if (!fssync.existsSync(packageJsonPath)) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const packageJson = JSON.parse(fssync.readFileSync(packageJsonPath, 'utf-8'));
|
|
31
|
+
const dependencies = packageJson.dependencies || {};
|
|
32
|
+
|
|
33
|
+
if (Object.keys(dependencies).length === 0) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Проверяем есть ли node_modules
|
|
38
|
+
const nodeModulesPath = path.join(plugin.path, 'node_modules');
|
|
39
|
+
const needsInstall = !fssync.existsSync(nodeModulesPath);
|
|
40
|
+
|
|
41
|
+
if (needsInstall) {
|
|
42
|
+
sendLog(`[PluginLoader] Установка зависимостей для ${plugin.name}...`);
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
execSync('npm install --omit=dev --no-audit --no-fund', {
|
|
46
|
+
cwd: plugin.path,
|
|
47
|
+
stdio: 'inherit'
|
|
48
|
+
});
|
|
49
|
+
sendLog(`[PluginLoader] ✓ Зависимости установлены для ${plugin.name}`);
|
|
50
|
+
} catch (e1) {
|
|
51
|
+
sendLog(`[PluginLoader] Повторная попытка с --legacy-peer-deps для ${plugin.name}...`);
|
|
52
|
+
execSync('npm install --omit=dev --legacy-peer-deps --no-audit --no-fund', {
|
|
53
|
+
cwd: plugin.path,
|
|
54
|
+
stdio: 'inherit'
|
|
55
|
+
});
|
|
56
|
+
sendLog(`[PluginLoader] ✓ Зависимости установлены для ${plugin.name}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
} catch (error) {
|
|
61
|
+
sendLog(`[PluginLoader] [WARN] Не удалось проверить зависимости для ${plugin.name}: ${error.message}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
sendLog(`[PluginLoader] Проверка зависимостей завершена`);
|
|
66
|
+
}
|
|
67
|
+
|
|
13
68
|
// Создаёт обёрнутый console для перехвата логов плагина
|
|
14
69
|
function createPluginConsole(botId, pluginName, originalConsole) {
|
|
15
70
|
const emitLog = (level, args) => {
|
|
@@ -160,6 +215,16 @@ async function initializePlugins(bot, installedPlugins = [], prisma) {
|
|
|
160
215
|
} else {
|
|
161
216
|
sendLog(`[PluginLoader] [ERROR] ${plugin.name} не экспортирует функцию или объект с методом onLoad.`);
|
|
162
217
|
}
|
|
218
|
+
|
|
219
|
+
if (pluginModule && pluginModule.exports && typeof pluginModule.exports === 'object') {
|
|
220
|
+
if (bot.pluginRegistry) {
|
|
221
|
+
bot.pluginRegistry.set(plugin.name, pluginModule.exports);
|
|
222
|
+
}
|
|
223
|
+
} else if (pluginModule && pluginModule.default && pluginModule.default.exports) {
|
|
224
|
+
if (bot.pluginRegistry) {
|
|
225
|
+
bot.pluginRegistry.set(plugin.name, pluginModule.default.exports);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
163
228
|
};
|
|
164
229
|
|
|
165
230
|
sendLog(`[PluginLoader] Загрузка: ${plugin.name} (v${plugin.version}) из ${normalizedPath}`);
|
|
@@ -184,12 +249,27 @@ async function initializePlugins(bot, installedPlugins = [], prisma) {
|
|
|
184
249
|
} catch (error) {
|
|
185
250
|
let handled = false;
|
|
186
251
|
let lastError = error;
|
|
187
|
-
|
|
252
|
+
// Проверяем не только сообщение ошибки, но и весь стек
|
|
253
|
+
const errorString = error.message + '\n' + (error.stack || '');
|
|
254
|
+
const isModuleError = errorString.includes('Cannot find module');
|
|
255
|
+
if (isModuleError) {
|
|
188
256
|
const moduleMatch = error.message.match(/Cannot find module '([^']+)'/);
|
|
189
257
|
const missingModule = moduleMatch ? moduleMatch[1] : null;
|
|
190
258
|
if (missingModule) {
|
|
259
|
+
const isFilePath = missingModule.startsWith('/') ||
|
|
260
|
+
missingModule.startsWith('./') ||
|
|
261
|
+
missingModule.startsWith('../') ||
|
|
262
|
+
missingModule.startsWith('\\') ||
|
|
263
|
+
/^[A-Za-z]:[\\/]/.test(missingModule) || // Windows absolute path
|
|
264
|
+
/\.(js|json|node|ts|mjs|cjs)$/i.test(missingModule);
|
|
265
|
+
|
|
266
|
+
if (isFilePath) {
|
|
267
|
+
sendLog(`[PluginLoader] [ERROR] Файл не найден: ${missingModule}`);
|
|
268
|
+
sendLog(`[PluginLoader] [ERROR] Плагин ${plugin.name} содержит ошибку — отсутствует файл. Проверьте код плагина.`);
|
|
269
|
+
throw error;
|
|
270
|
+
}
|
|
271
|
+
|
|
191
272
|
try {
|
|
192
|
-
// Диагностика текущего состояния резолва
|
|
193
273
|
pluginRequire.resolve(missingModule);
|
|
194
274
|
sendLog(`[PluginLoader] [DEBUG] ${missingModule} уже резолвится до установки? Это неожиданно.`);
|
|
195
275
|
} catch {
|
|
@@ -300,4 +380,4 @@ async function initializePlugins(bot, installedPlugins = [], prisma) {
|
|
|
300
380
|
}
|
|
301
381
|
}
|
|
302
382
|
|
|
303
|
-
module.exports = { initializePlugins };
|
|
383
|
+
module.exports = { initializePlugins, ensurePluginDependencies };
|
|
@@ -48,6 +48,52 @@ class PluginManager {
|
|
|
48
48
|
await fse.mkdir(PLUGINS_BASE_DIR, { recursive: true }).catch(console.error);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Проверяет зависимости плагина из package.json
|
|
53
|
+
* @param {number} botId - ID бота
|
|
54
|
+
* @param {object} packageJson - package.json плагина
|
|
55
|
+
* @returns {Promise<{isValid: boolean, missing: string[], warnings: string[]}>}
|
|
56
|
+
*/
|
|
57
|
+
async checkPluginDependencies(botId, packageJson) {
|
|
58
|
+
const result = {
|
|
59
|
+
isValid: true,
|
|
60
|
+
missing: [],
|
|
61
|
+
warnings: []
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Проверяем зависимости из botpanel.dependencies
|
|
65
|
+
const pluginDeps = packageJson.botpanel?.dependencies || {};
|
|
66
|
+
if (Object.keys(pluginDeps).length === 0) {
|
|
67
|
+
return result; // Нет зависимостей
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const installedPlugins = await prisma.installedPlugin.findMany({
|
|
71
|
+
where: { botId },
|
|
72
|
+
select: { name: true, version: true }
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const installedMap = new Map(installedPlugins.map(p => [p.name, p.version]));
|
|
76
|
+
|
|
77
|
+
for (const [depName, depVersion] of Object.entries(pluginDeps)) {
|
|
78
|
+
if (!installedMap.has(depName)) {
|
|
79
|
+
result.missing.push(`${depName} (требуется ${depVersion})`);
|
|
80
|
+
result.isValid = false;
|
|
81
|
+
} else {
|
|
82
|
+
const installedVersion = installedMap.get(depName);
|
|
83
|
+
if (depVersion.startsWith('^') || depVersion.startsWith('~')) {
|
|
84
|
+
const requiredBase = depVersion.slice(1);
|
|
85
|
+
if (!installedVersion.startsWith(requiredBase.split('.')[0])) {
|
|
86
|
+
result.warnings.push(
|
|
87
|
+
`${depName}: установлена v${installedVersion}, требуется ${depVersion}`
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
|
|
51
97
|
async _installDependencies(pluginPath) {
|
|
52
98
|
const packageJsonPath = path.join(pluginPath, 'package.json');
|
|
53
99
|
try {
|
|
@@ -108,9 +154,22 @@ class PluginManager {
|
|
|
108
154
|
}
|
|
109
155
|
|
|
110
156
|
async installFromLocalPath(botId, directoryPath) {
|
|
157
|
+
// Проверяем зависимости плагина перед установкой
|
|
158
|
+
const packageJsonPath = path.join(directoryPath, 'package.json');
|
|
159
|
+
const packageJson = JSON.parse(await fse.readFile(packageJsonPath, 'utf-8'));
|
|
160
|
+
|
|
161
|
+
const depCheck = await this.checkPluginDependencies(botId, packageJson);
|
|
162
|
+
if (!depCheck.isValid) {
|
|
163
|
+
const missingList = depCheck.missing.join(', ');
|
|
164
|
+
console.warn(`[PluginManager] ⚠️ Плагин ${packageJson.name} требует: ${missingList}`);
|
|
165
|
+
console.warn(`[PluginManager] Плагин будет установлен, но может работать некорректно без зависимостей.`);
|
|
166
|
+
}
|
|
167
|
+
if (depCheck.warnings.length > 0) {
|
|
168
|
+
depCheck.warnings.forEach(w => console.warn(`[PluginManager] ⚠️ ${w}`));
|
|
169
|
+
}
|
|
170
|
+
|
|
111
171
|
const newPlugin = await this.registerPlugin(botId, directoryPath, 'LOCAL', directoryPath);
|
|
112
172
|
try {
|
|
113
|
-
const packageJson = JSON.parse(await fse.readFile(path.join(directoryPath, 'package.json'), 'utf-8'));
|
|
114
173
|
reportPluginDownload(packageJson.name);
|
|
115
174
|
} catch(e) {
|
|
116
175
|
console.error('Не удалось прочитать package.json для отправки статистики локального плагина');
|
|
@@ -118,11 +177,11 @@ class PluginManager {
|
|
|
118
177
|
|
|
119
178
|
await this._installDependencies(directoryPath);
|
|
120
179
|
await this.loadPluginGraphs(botId, newPlugin.id, directoryPath);
|
|
121
|
-
|
|
180
|
+
|
|
122
181
|
if (this.botManager) {
|
|
123
182
|
await this.botManager.reloadPlugins(botId);
|
|
124
183
|
}
|
|
125
|
-
|
|
184
|
+
|
|
126
185
|
return newPlugin;
|
|
127
186
|
}
|
|
128
187
|
|
|
@@ -193,9 +252,20 @@ class PluginManager {
|
|
|
193
252
|
|
|
194
253
|
await this._installDependencies(localPath);
|
|
195
254
|
|
|
196
|
-
|
|
197
|
-
|
|
255
|
+
|
|
198
256
|
const packageJson = JSON.parse(await fse.readFile(path.join(localPath, 'package.json'), 'utf-8'));
|
|
257
|
+
const depCheck = await this.checkPluginDependencies(botId, packageJson);
|
|
258
|
+
if (!depCheck.isValid) {
|
|
259
|
+
const missingList = depCheck.missing.join(', ');
|
|
260
|
+
console.warn(`[PluginManager] ⚠️ Плагин ${packageJson.name} требует: ${missingList}`);
|
|
261
|
+
console.warn(`[PluginManager] Плагин будет установлен, но может работать некорректно без зависимостей.`);
|
|
262
|
+
}
|
|
263
|
+
if (depCheck.warnings.length > 0) {
|
|
264
|
+
depCheck.warnings.forEach(w => console.warn(`[PluginManager] ⚠️ ${w}`));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const newPlugin = await this.registerPlugin(botId, localPath, 'GITHUB', repoUrl, prismaClient);
|
|
268
|
+
|
|
199
269
|
reportPluginDownload(packageJson.name);
|
|
200
270
|
|
|
201
271
|
await this.loadPluginGraphs(botId, newPlugin.id, localPath);
|
|
@@ -147,8 +147,8 @@ class BotLifecycleService {
|
|
|
147
147
|
return this.processManager.getProcess(botId);
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
async restartBot(botId) {
|
|
151
|
-
const botConfig = this.processManager.getProcess(botId)?.botConfig;
|
|
150
|
+
async restartBot(botId, providedBotConfig = null) {
|
|
151
|
+
const botConfig = providedBotConfig || this.processManager.getProcess(botId)?.botConfig;
|
|
152
152
|
if (!botConfig) {
|
|
153
153
|
throw new Error('Bot configuration not found');
|
|
154
154
|
}
|
|
@@ -229,6 +229,15 @@ class BotLifecycleService {
|
|
|
229
229
|
case 'debug:check_step_mode':
|
|
230
230
|
await this._handleDebugStepModeCheck(botId, child, message);
|
|
231
231
|
break;
|
|
232
|
+
case 'update_credentials':
|
|
233
|
+
await this._handleUpdateCredentials(botId, child, message);
|
|
234
|
+
break;
|
|
235
|
+
case 'restart_bot':
|
|
236
|
+
await this._handleRestartBot(botId, child, message);
|
|
237
|
+
break;
|
|
238
|
+
case 'change_credentials':
|
|
239
|
+
await this._handleChangeCredentials(botId, child, message);
|
|
240
|
+
break;
|
|
232
241
|
}
|
|
233
242
|
} catch (error) {
|
|
234
243
|
this.appendLog(botId, `[SYSTEM-ERROR] Критическая ошибка в обработчике: ${error.stack}`);
|
|
@@ -830,6 +839,181 @@ class BotLifecycleService {
|
|
|
830
839
|
});
|
|
831
840
|
}
|
|
832
841
|
}
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* Обработчик обновления credentials в БД (без рестарта)
|
|
845
|
+
*/
|
|
846
|
+
async _handleUpdateCredentials(botId, child, message) {
|
|
847
|
+
const { requestId, payload } = message;
|
|
848
|
+
const { username, password } = payload;
|
|
849
|
+
|
|
850
|
+
try {
|
|
851
|
+
// Валидация входных данных
|
|
852
|
+
if (!username || username.trim().length === 0) {
|
|
853
|
+
throw new Error('Username не может быть пустым');
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
const existingBot = await this.botRepository.findByUsername(username);
|
|
857
|
+
if (existingBot && existingBot.id !== botId) {
|
|
858
|
+
throw new Error(`Username "${username}" уже используется другим ботом (ID: ${existingBot.id})`);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
const { encrypt } = require('../utils/crypto');
|
|
862
|
+
const updateData = { username };
|
|
863
|
+
|
|
864
|
+
if (password !== undefined && password !== null) {
|
|
865
|
+
if (password.trim().length === 0) {
|
|
866
|
+
throw new Error('Password не может быть пустым');
|
|
867
|
+
}
|
|
868
|
+
updateData.password = encrypt(password);
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
await this.botRepository.update(botId, updateData);
|
|
872
|
+
|
|
873
|
+
if (child.botConfig) {
|
|
874
|
+
child.botConfig.username = username;
|
|
875
|
+
if (password !== undefined && password !== null) {
|
|
876
|
+
child.botConfig.password = updateData.password;
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
this.logger.info({ botId, username }, 'Credentials обновлены в БД');
|
|
881
|
+
this.appendLog(botId, `[API] Credentials обновлены: username="${username}"`);
|
|
882
|
+
|
|
883
|
+
child.send({
|
|
884
|
+
type: 'credentials_operation_response',
|
|
885
|
+
requestId,
|
|
886
|
+
payload: {
|
|
887
|
+
success: true,
|
|
888
|
+
message: 'Credentials успешно обновлены в БД'
|
|
889
|
+
}
|
|
890
|
+
});
|
|
891
|
+
|
|
892
|
+
} catch (error) {
|
|
893
|
+
this.logger.error({ botId, error }, 'Ошибка обновления credentials');
|
|
894
|
+
this.appendLog(botId, `[API ERROR] Не удалось обновить credentials: ${error.message}`);
|
|
895
|
+
|
|
896
|
+
child.send({
|
|
897
|
+
type: 'credentials_operation_response',
|
|
898
|
+
requestId,
|
|
899
|
+
error: error.message
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
/**
|
|
905
|
+
* Обработчик рестарта бота
|
|
906
|
+
*/
|
|
907
|
+
async _handleRestartBot(botId, child, message) {
|
|
908
|
+
const { requestId } = message;
|
|
909
|
+
|
|
910
|
+
try {
|
|
911
|
+
this.logger.info({ botId }, 'Запрос на рестарт бота от плагина');
|
|
912
|
+
this.appendLog(botId, '[API] Получен запрос на рестарт бота от плагина');
|
|
913
|
+
|
|
914
|
+
const savedBotConfig = { ...child.botConfig };
|
|
915
|
+
|
|
916
|
+
child.send({
|
|
917
|
+
type: 'credentials_operation_response',
|
|
918
|
+
requestId,
|
|
919
|
+
payload: {
|
|
920
|
+
success: true,
|
|
921
|
+
message: 'Рестарт инициирован'
|
|
922
|
+
}
|
|
923
|
+
});
|
|
924
|
+
|
|
925
|
+
setTimeout(async () => {
|
|
926
|
+
try {
|
|
927
|
+
await this.restartBot(botId, savedBotConfig);
|
|
928
|
+
this.logger.info({ botId }, 'Бот успешно перезапущен');
|
|
929
|
+
} catch (error) {
|
|
930
|
+
this.logger.error({ botId, error }, 'Ошибка при рестарте бота');
|
|
931
|
+
this.appendLog(botId, `[API ERROR] Ошибка при рестарте: ${error.message}`);
|
|
932
|
+
}
|
|
933
|
+
}, 3000);
|
|
934
|
+
|
|
935
|
+
} catch (error) {
|
|
936
|
+
this.logger.error({ botId, error }, 'Ошибка инициализации рестарта');
|
|
937
|
+
|
|
938
|
+
child.send({
|
|
939
|
+
type: 'credentials_operation_response',
|
|
940
|
+
requestId,
|
|
941
|
+
error: error.message
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
/**
|
|
947
|
+
* Обработчик изменения credentials с автоматическим рестартом
|
|
948
|
+
*/
|
|
949
|
+
async _handleChangeCredentials(botId, child, message) {
|
|
950
|
+
const { requestId, payload } = message;
|
|
951
|
+
const { username, password } = payload;
|
|
952
|
+
|
|
953
|
+
try {
|
|
954
|
+
if (!username || username.trim().length === 0) {
|
|
955
|
+
throw new Error('Username не может быть пустым');
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
const existingBot = await this.botRepository.findByUsername(username);
|
|
959
|
+
if (existingBot && existingBot.id !== botId) {
|
|
960
|
+
throw new Error(`Username "${username}" уже используется другим ботом (ID: ${existingBot.id})`);
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
const { encrypt } = require('../utils/crypto');
|
|
964
|
+
const updateData = { username };
|
|
965
|
+
|
|
966
|
+
if (password !== undefined && password !== null) {
|
|
967
|
+
if (password.trim().length === 0) {
|
|
968
|
+
throw new Error('Password не может быть пустым');
|
|
969
|
+
}
|
|
970
|
+
updateData.password = encrypt(password);
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
await this.botRepository.update(botId, updateData);
|
|
974
|
+
|
|
975
|
+
if (child.botConfig) {
|
|
976
|
+
child.botConfig.username = username;
|
|
977
|
+
if (password !== undefined && password !== null) {
|
|
978
|
+
child.botConfig.password = updateData.password;
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
const savedBotConfig = { ...child.botConfig };
|
|
983
|
+
|
|
984
|
+
this.logger.info({ botId, username }, 'Credentials обновлены, инициирован рестарт');
|
|
985
|
+
this.appendLog(botId, `[API] Credentials изменены: username="${username}". Выполняется рестарт...`);
|
|
986
|
+
|
|
987
|
+
child.send({
|
|
988
|
+
type: 'credentials_operation_response',
|
|
989
|
+
requestId,
|
|
990
|
+
payload: {
|
|
991
|
+
success: true,
|
|
992
|
+
message: 'Credentials обновлены, рестарт инициирован'
|
|
993
|
+
}
|
|
994
|
+
});
|
|
995
|
+
|
|
996
|
+
setTimeout(async () => {
|
|
997
|
+
try {
|
|
998
|
+
await this.restartBot(botId, savedBotConfig);
|
|
999
|
+
this.logger.info({ botId }, 'Бот успешно перезапущен с новыми credentials');
|
|
1000
|
+
} catch (error) {
|
|
1001
|
+
this.logger.error({ botId, error }, 'Ошибка при рестарте бота после изменения credentials');
|
|
1002
|
+
this.appendLog(botId, `[API ERROR] Ошибка при рестарте: ${error.message}`);
|
|
1003
|
+
}
|
|
1004
|
+
}, 3000);
|
|
1005
|
+
|
|
1006
|
+
} catch (error) {
|
|
1007
|
+
this.logger.error({ botId, error }, 'Ошибка изменения credentials');
|
|
1008
|
+
this.appendLog(botId, `[API ERROR] Не удалось изменить credentials: ${error.message}`);
|
|
1009
|
+
|
|
1010
|
+
child.send({
|
|
1011
|
+
type: 'credentials_operation_response',
|
|
1012
|
+
requestId,
|
|
1013
|
+
error: error.message
|
|
1014
|
+
});
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
833
1017
|
}
|
|
834
1018
|
|
|
835
1019
|
module.exports = BotLifecycleService;
|
package/backend/src/server.js
CHANGED
|
@@ -102,6 +102,16 @@ app.get(/^(?!\/api).*/, (req, res) => {
|
|
|
102
102
|
|
|
103
103
|
async function runStartupMigrations() {
|
|
104
104
|
try {
|
|
105
|
+
// Удаляем серверы с невалидными портами напрямую через SQL,
|
|
106
|
+
// потому что Prisma не может их прочитать если значение не помещается в INT
|
|
107
|
+
const result = await prisma.$executeRawUnsafe(
|
|
108
|
+
`DELETE FROM Server WHERE length(CAST(port AS TEXT)) > 5 OR port > 65535 OR port < 1`
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
if (result > 0) {
|
|
112
|
+
console.log(`[Migration] Удалено ${result} серверов с невалидными портами.`);
|
|
113
|
+
}
|
|
114
|
+
|
|
105
115
|
const adminRole = await prisma.panelRole.findUnique({ where: { name: 'Admin' } });
|
|
106
116
|
if (adminRole) {
|
|
107
117
|
const permissions = JSON.parse(adminRole.permissions);
|
|
@@ -109,7 +119,7 @@ async function runStartupMigrations() {
|
|
|
109
119
|
const newPermissions = ALL_PERMISSIONS
|
|
110
120
|
.map(p => p.id)
|
|
111
121
|
.filter(id => id !== '*');
|
|
112
|
-
|
|
122
|
+
|
|
113
123
|
await prisma.panelRole.update({
|
|
114
124
|
where: { id: adminRole.id },
|
|
115
125
|
data: { permissions: JSON.stringify(newPermissions) }
|