blockmine 1.24.0 → 1.27.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 +76 -1
- package/README.en.md +427 -0
- package/README.md +40 -0
- package/backend/package.json +2 -2
- package/backend/prisma/migrations/20260328173000_add_plugin_source_ref/migration.sql +2 -0
- package/backend/prisma/migrations/migration_lock.toml +2 -2
- package/backend/prisma/schema.prisma +2 -0
- package/backend/src/ai/plugin-assistant-system-prompt.md +664 -5
- package/backend/src/api/routes/apiKeys.js +8 -0
- package/backend/src/api/routes/bots.js +271 -9
- package/backend/src/api/routes/eventGraphs.js +151 -1
- package/backend/src/api/routes/health.js +38 -0
- package/backend/src/api/routes/nodeRegistry.js +63 -0
- package/backend/src/api/routes/plugins.js +254 -29
- package/backend/src/api/routes/servers.js +14 -2
- package/backend/src/container.js +11 -8
- package/backend/src/core/BotCommandLoader.js +161 -0
- package/backend/src/core/BotConnection.js +125 -0
- package/backend/src/core/BotEventHandlers.js +234 -0
- package/backend/src/core/BotIPCHandler.js +445 -0
- package/backend/src/core/BotManager.js +15 -7
- package/backend/src/core/BotProcess.js +169 -140
- package/backend/src/core/EventGraphManager.js +7 -3
- package/backend/src/core/GraphDebugHandler.js +229 -0
- package/backend/src/core/GraphDebugIPC.js +117 -0
- package/backend/src/core/GraphExecutionEngine.js +545 -978
- package/backend/src/core/GraphTraversal.js +80 -0
- package/backend/src/core/GraphValidation.js +73 -0
- package/backend/src/core/NodeDefinition.js +138 -0
- package/backend/src/core/NodeRegistry.js +153 -141
- package/backend/src/core/PluginLoader.js +83 -3
- package/backend/src/core/PluginManager.js +346 -35
- package/backend/src/core/RewindSignal.js +9 -0
- package/backend/src/core/config/ConfigValidator.js +72 -0
- package/backend/src/core/config/FeatureFlags.js +52 -0
- package/backend/src/core/config/__tests__/ConfigValidator.test.js +232 -0
- package/backend/src/core/domain/entities/Bot.js +39 -0
- package/backend/src/core/domain/entities/Command.js +41 -0
- package/backend/src/core/domain/entities/EventGraph.js +39 -0
- package/backend/src/core/domain/entities/Plugin.js +45 -0
- package/backend/src/core/domain/entities/User.js +40 -0
- package/backend/src/core/domain/services/DependencyResolver.js +168 -0
- package/backend/src/core/domain/services/GraphValidator.js +117 -0
- package/backend/src/core/domain/services/PermissionChecker.js +34 -0
- package/backend/src/core/domain/services/__tests__/DependencyResolver.test.js +126 -0
- package/backend/src/core/domain/valueObjects/BotConfig.js +27 -0
- package/backend/src/core/domain/valueObjects/DependencyGraph.js +86 -0
- package/backend/src/core/domain/valueObjects/PluginManifest.js +36 -0
- package/backend/src/core/errors/BaseError.js +29 -0
- package/backend/src/core/errors/ErrorHandler.js +81 -0
- package/backend/src/core/errors/__tests__/ErrorHandler.test.js +188 -0
- package/backend/src/core/errors/index.js +68 -0
- package/backend/src/core/infrastructure/BatchingUtility.js +66 -0
- package/backend/src/core/infrastructure/CircuitBreaker.js +103 -0
- package/backend/src/core/infrastructure/ConnectionPool.js +81 -0
- package/backend/src/core/infrastructure/RateLimiter.js +64 -0
- package/backend/src/core/infrastructure/__tests__/BatchingUtility.test.js +86 -0
- package/backend/src/core/infrastructure/__tests__/CircuitBreaker.test.js +156 -0
- package/backend/src/core/infrastructure/__tests__/ConnectionPool.test.js +146 -0
- package/backend/src/core/infrastructure/__tests__/RateLimiter.test.js +171 -0
- package/backend/src/core/ipc/botApiFactory.js +72 -0
- package/backend/src/core/ipc/ipcMessageTypes.js +115 -0
- package/backend/src/core/logging/AuditLogger.js +61 -0
- package/backend/src/core/logging/StructuredLogger.js +80 -0
- package/backend/src/core/logging/__tests__/StructuredLogger.test.js +213 -0
- package/backend/src/core/logging/index.js +7 -0
- package/backend/src/core/metrics/MetricsCollector.js +104 -0
- package/backend/src/core/metrics/__tests__/MetricsCollector.test.js +131 -0
- package/backend/src/core/node-registries/actionsNodes.js +191 -0
- package/backend/src/core/node-registries/arraysNodes.js +152 -0
- package/backend/src/core/node-registries/botNodes.js +48 -0
- package/backend/src/core/node-registries/containerNodes.js +141 -0
- package/backend/src/core/node-registries/dataNodes.js +284 -0
- package/backend/src/core/node-registries/debugNodes.js +23 -0
- package/backend/src/core/node-registries/eventsNodes.js +223 -0
- package/backend/src/core/node-registries/flowNodes.js +151 -0
- package/backend/src/core/node-registries/furnaceNodes.js +123 -0
- package/backend/src/core/node-registries/index.js +108 -0
- package/backend/src/core/node-registries/inventory.js +102 -106
- package/backend/src/core/node-registries/logicNodes.js +54 -0
- package/backend/src/core/node-registries/mathNodes.js +38 -0
- package/backend/src/core/node-registries/navigationNodes.js +109 -0
- package/backend/src/core/node-registries/objectsNodes.js +90 -0
- package/backend/src/core/node-registries/stringsNodes.js +165 -0
- package/backend/src/core/node-registries/timeNodes.js +105 -0
- package/backend/src/core/node-registries/typeNodes.js +22 -0
- package/backend/src/core/node-registries/usersNodes.js +126 -0
- package/backend/src/core/nodes/arrays/shuffle.js +14 -0
- package/backend/src/core/nodes/bot/get_name.js +8 -0
- package/backend/src/core/nodes/bot/stop_bot.js +5 -0
- package/backend/src/core/nodes/container/open.js +101 -111
- package/backend/src/core/nodes/data/store_read.js +26 -0
- package/backend/src/core/nodes/data/store_write.js +23 -0
- package/backend/src/core/nodes/event/call_event.js +31 -0
- package/backend/src/core/nodes/event/custom_event.js +8 -0
- package/backend/src/core/nodes/flow/timer.js +35 -0
- package/backend/src/core/nodes/inventory/drop.js +73 -65
- package/backend/src/core/nodes/inventory/equip.js +54 -45
- package/backend/src/core/nodes/inventory/select_slot.js +48 -46
- package/backend/src/core/nodes/navigation/follow.js +54 -51
- package/backend/src/core/nodes/navigation/go_to.js +41 -53
- package/backend/src/core/nodes/navigation/go_to_entity.js +65 -69
- package/backend/src/core/nodes/navigation/go_to_player.js +65 -70
- package/backend/src/core/nodes/navigation/stop.js +17 -26
- package/backend/src/core/nodes/users/add_to_group.js +24 -0
- package/backend/src/core/nodes/users/check_permission.js +26 -0
- package/backend/src/core/nodes/users/remove_from_group.js +24 -0
- package/backend/src/core/services/BotIPCMessageRouter.js +337 -0
- package/backend/src/core/services/BotLifecycleService.js +43 -450
- package/backend/src/core/services/CacheManager.js +83 -23
- package/backend/src/core/services/CrashRestartManager.js +42 -0
- package/backend/src/core/services/DebugSessionManager.js +114 -12
- package/backend/src/core/services/EventGraphService.js +69 -0
- package/backend/src/core/services/MinecraftBotManager.js +9 -1
- package/backend/src/core/services/PluginManagementService.js +84 -0
- package/backend/src/core/services/TestModeContext.js +65 -0
- package/backend/src/core/services/__tests__/CacheManager.test.js +168 -0
- package/backend/src/core/services.js +1 -11
- package/backend/src/core/validation/InputValidator.js +167 -0
- package/backend/src/core/validation/__tests__/InputValidator.test.js +296 -0
- package/backend/src/real-time/botApi/index.js +1 -1
- package/backend/src/real-time/socketHandler.js +26 -0
- package/backend/src/server.js +21 -6
- package/frontend/dist/assets/browser-ponyfill-D8y0Ty7C.js +2 -0
- package/frontend/dist/assets/index-CFJLS0dk.css +32 -0
- package/frontend/dist/assets/index-D91UGNMG.js +11260 -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 +113 -0
- package/frontend/dist/locales/en/common.json +53 -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 +36 -0
- package/frontend/dist/locales/en/management.json +192 -0
- package/frontend/dist/locales/en/minecraft-viewer.json +27 -0
- package/frontend/dist/locales/en/nodes.json +1132 -0
- package/frontend/dist/locales/en/permissions.json +50 -0
- package/frontend/dist/locales/en/plugin-detail.json +69 -0
- package/frontend/dist/locales/en/plugins.json +329 -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 +19 -0
- package/frontend/dist/locales/en/sidebar.json +195 -0
- package/frontend/dist/locales/en/tasks.json +62 -0
- package/frontend/dist/locales/en/visual-editor.json +418 -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 +113 -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 +36 -0
- package/frontend/dist/locales/ru/management.json +192 -0
- package/frontend/dist/locales/ru/minecraft-viewer.json +30 -0
- package/frontend/dist/locales/ru/nodes.json +1131 -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 +209 -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 +19 -0
- package/frontend/dist/locales/ru/sidebar.json +195 -0
- package/frontend/dist/locales/ru/tasks.json +62 -0
- package/frontend/dist/locales/ru/visual-editor.json +420 -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 +6 -0
- package/nul +12 -0
- package/package.json +3 -3
- 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/backend/package-lock.json +0 -6801
- package/backend/src/core/node-registries/actions.js +0 -202
- package/backend/src/core/node-registries/arrays.js +0 -155
- package/backend/src/core/node-registries/bot.js +0 -23
- package/backend/src/core/node-registries/container.js +0 -162
- package/backend/src/core/node-registries/data.js +0 -290
- package/backend/src/core/node-registries/debug.js +0 -26
- package/backend/src/core/node-registries/events.js +0 -201
- package/backend/src/core/node-registries/flow.js +0 -139
- package/backend/src/core/node-registries/furnace.js +0 -143
- package/backend/src/core/node-registries/logic.js +0 -62
- package/backend/src/core/node-registries/math.js +0 -42
- package/backend/src/core/node-registries/navigation.js +0 -111
- package/backend/src/core/node-registries/objects.js +0 -98
- package/backend/src/core/node-registries/strings.js +0 -187
- package/backend/src/core/node-registries/time.js +0 -113
- package/backend/src/core/node-registries/type.js +0 -25
- package/backend/src/core/node-registries/users.js +0 -79
- package/frontend/dist/assets/index-BC-NbKXi.css +0 -32
- package/frontend/dist/assets/index-DqJXZMHY.js +0 -11266
|
@@ -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 };
|
|
@@ -13,7 +13,192 @@ const DATA_DIR = path.join(os.homedir(), '.blockmine');
|
|
|
13
13
|
const PLUGINS_BASE_DIR = path.join(DATA_DIR, 'storage', 'plugins');
|
|
14
14
|
|
|
15
15
|
const TELEMETRY_ENABLED = true;
|
|
16
|
-
const STATS_SERVER_URL = 'http://185.65.200.184:3000';
|
|
16
|
+
const STATS_SERVER_URL = process.env.STATS_SERVER_URL || 'http://185.65.200.184:3000';
|
|
17
|
+
|
|
18
|
+
function normalizeGithubRepoUrl(repoUrl) {
|
|
19
|
+
if (!repoUrl || typeof repoUrl !== 'string') return null;
|
|
20
|
+
|
|
21
|
+
let trimmed = repoUrl.trim();
|
|
22
|
+
if (!trimmed) return null;
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
trimmed = trimmed.replace(/^git\+/i, '');
|
|
26
|
+
if (/^github\.com\//i.test(trimmed)) {
|
|
27
|
+
trimmed = `https://${trimmed}`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const sshMatch = trimmed.match(/^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/i);
|
|
31
|
+
if (sshMatch) {
|
|
32
|
+
const owner = sshMatch[1].toLowerCase();
|
|
33
|
+
const repo = sshMatch[2].toLowerCase();
|
|
34
|
+
return `https://github.com/${owner}/${repo}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const parsed = new URL(trimmed);
|
|
38
|
+
const hostname = parsed.hostname.toLowerCase();
|
|
39
|
+
if (hostname !== 'github.com' && hostname !== 'www.github.com') return null;
|
|
40
|
+
|
|
41
|
+
const pathParts = parsed.pathname.split('/').filter(Boolean);
|
|
42
|
+
if (pathParts.length < 2) return null;
|
|
43
|
+
|
|
44
|
+
const owner = pathParts[0].toLowerCase();
|
|
45
|
+
const repo = pathParts[1].replace(/\.git$/i, '').toLowerCase();
|
|
46
|
+
return `https://github.com/${owner}/${repo}`;
|
|
47
|
+
} catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function parseGithubOwnerRepo(repoUrl) {
|
|
53
|
+
const normalized = normalizeGithubRepoUrl(repoUrl);
|
|
54
|
+
if (!normalized) return null;
|
|
55
|
+
try {
|
|
56
|
+
const parsed = new URL(normalized);
|
|
57
|
+
const parts = parsed.pathname.split('/').filter(Boolean);
|
|
58
|
+
if (parts.length < 2) return null;
|
|
59
|
+
return { owner: parts[0], repo: parts[1] };
|
|
60
|
+
} catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function getGithubRepoName(repoUrl) {
|
|
66
|
+
const ownerRepo = parseGithubOwnerRepo(repoUrl);
|
|
67
|
+
return ownerRepo?.repo || null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function getGithubHeaders(extra = {}) {
|
|
71
|
+
const headers = {
|
|
72
|
+
Accept: 'application/vnd.github+json',
|
|
73
|
+
'User-Agent': 'BlockMine',
|
|
74
|
+
...extra
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
if (process.env.GITHUB_TOKEN) {
|
|
78
|
+
headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return headers;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function fetchJsonWithTimeout(url, timeoutMs = 7000) {
|
|
85
|
+
const controller = new AbortController();
|
|
86
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
87
|
+
try {
|
|
88
|
+
const response = await fetch(url, { headers: getGithubHeaders(), signal: controller.signal });
|
|
89
|
+
if (!response.ok) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
return response.json();
|
|
93
|
+
} catch {
|
|
94
|
+
return null;
|
|
95
|
+
} finally {
|
|
96
|
+
clearTimeout(timeoutId);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async function fetchGithubResponseWithTimeout(url, options = {}, timeoutMs = 10000) {
|
|
101
|
+
const controller = new AbortController();
|
|
102
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
const response = await fetch(url, {
|
|
106
|
+
...options,
|
|
107
|
+
headers: getGithubHeaders(options.headers || {}),
|
|
108
|
+
signal: controller.signal
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
if (!response.ok) {
|
|
112
|
+
const error = new Error(`GitHub request failed with status ${response.status}.`);
|
|
113
|
+
error.status = response.status;
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return response;
|
|
118
|
+
} catch (error) {
|
|
119
|
+
if (error.name === 'AbortError') {
|
|
120
|
+
const timeoutError = new Error('GitHub request timed out.');
|
|
121
|
+
timeoutError.name = 'AbortError';
|
|
122
|
+
throw timeoutError;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
throw error;
|
|
126
|
+
} finally {
|
|
127
|
+
clearTimeout(timeoutId);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async function fetchGithubRepoInfo(repoUrl) {
|
|
132
|
+
const ownerRepo = parseGithubOwnerRepo(repoUrl);
|
|
133
|
+
if (!ownerRepo) return null;
|
|
134
|
+
|
|
135
|
+
return fetchJsonWithTimeout(`https://api.github.com/repos/${ownerRepo.owner}/${ownerRepo.repo}`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function downloadGithubArchive(repoUrl, ref) {
|
|
139
|
+
const ownerRepo = parseGithubOwnerRepo(repoUrl);
|
|
140
|
+
if (!ownerRepo) {
|
|
141
|
+
throw new Error('Invalid GitHub repository URL.');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const response = await fetchGithubResponseWithTimeout(
|
|
145
|
+
`https://api.github.com/repos/${ownerRepo.owner}/${ownerRepo.repo}/zipball/${encodeURIComponent(ref)}`,
|
|
146
|
+
{ headers: { Accept: 'application/vnd.github+json' } },
|
|
147
|
+
15000
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
return response;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async function fetchGithubPackageVersion(repoUrl, ref = null) {
|
|
154
|
+
const ownerRepo = parseGithubOwnerRepo(repoUrl);
|
|
155
|
+
if (!ownerRepo) return null;
|
|
156
|
+
|
|
157
|
+
const resolvedRef = ref || (await fetchGithubRepoInfo(repoUrl))?.default_branch;
|
|
158
|
+
if (!resolvedRef) return null;
|
|
159
|
+
|
|
160
|
+
const packageJsonData = await fetchJsonWithTimeout(
|
|
161
|
+
`https://api.github.com/repos/${ownerRepo.owner}/${ownerRepo.repo}/contents/package.json?ref=${encodeURIComponent(resolvedRef)}`
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
if (!packageJsonData?.content) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
const packageJsonRaw = Buffer.from(packageJsonData.content, packageJsonData.encoding || 'base64').toString('utf8');
|
|
170
|
+
const packageJson = JSON.parse(packageJsonRaw);
|
|
171
|
+
return typeof packageJson?.version === 'string' ? packageJson.version : null;
|
|
172
|
+
} catch {
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async function fetchLatestGithubVersionTag(repoUrl) {
|
|
178
|
+
const ownerRepo = parseGithubOwnerRepo(repoUrl);
|
|
179
|
+
if (!ownerRepo) return null;
|
|
180
|
+
|
|
181
|
+
const releaseData = await fetchJsonWithTimeout(`https://api.github.com/repos/${ownerRepo.owner}/${ownerRepo.repo}/releases/latest`);
|
|
182
|
+
const releaseTag = typeof releaseData?.tag_name === 'string' ? releaseData.tag_name : null;
|
|
183
|
+
if (releaseTag) return releaseTag;
|
|
184
|
+
|
|
185
|
+
const tagsData = await fetchJsonWithTimeout(`https://api.github.com/repos/${ownerRepo.owner}/${ownerRepo.repo}/tags?per_page=20`);
|
|
186
|
+
if (!Array.isArray(tagsData) || tagsData.length === 0) return null;
|
|
187
|
+
|
|
188
|
+
const semverTags = tagsData
|
|
189
|
+
.map(item => item?.name)
|
|
190
|
+
.filter(Boolean)
|
|
191
|
+
.map(tag => ({ tag, normalized: semver.coerce(tag)?.version || null }))
|
|
192
|
+
.filter(item => item.normalized);
|
|
193
|
+
|
|
194
|
+
if (semverTags.length > 0) {
|
|
195
|
+
semverTags.sort((a, b) => semver.rcompare(a.normalized, b.normalized));
|
|
196
|
+
return semverTags[0].tag;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const firstTag = tagsData[0]?.name;
|
|
200
|
+
return typeof firstTag === 'string' ? firstTag : null;
|
|
201
|
+
}
|
|
17
202
|
|
|
18
203
|
function reportPluginDownload(pluginName) {
|
|
19
204
|
if (!TELEMETRY_ENABLED) return;
|
|
@@ -48,6 +233,52 @@ class PluginManager {
|
|
|
48
233
|
await fse.mkdir(PLUGINS_BASE_DIR, { recursive: true }).catch(console.error);
|
|
49
234
|
}
|
|
50
235
|
|
|
236
|
+
/**
|
|
237
|
+
* Проверяет зависимости плагина из package.json
|
|
238
|
+
* @param {number} botId - ID бота
|
|
239
|
+
* @param {object} packageJson - package.json плагина
|
|
240
|
+
* @returns {Promise<{isValid: boolean, missing: string[], warnings: string[]}>}
|
|
241
|
+
*/
|
|
242
|
+
async checkPluginDependencies(botId, packageJson) {
|
|
243
|
+
const result = {
|
|
244
|
+
isValid: true,
|
|
245
|
+
missing: [],
|
|
246
|
+
warnings: []
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// Проверяем зависимости из botpanel.dependencies
|
|
250
|
+
const pluginDeps = packageJson.botpanel?.dependencies || {};
|
|
251
|
+
if (Object.keys(pluginDeps).length === 0) {
|
|
252
|
+
return result; // Нет зависимостей
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const installedPlugins = await prisma.installedPlugin.findMany({
|
|
256
|
+
where: { botId },
|
|
257
|
+
select: { name: true, version: true }
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
const installedMap = new Map(installedPlugins.map(p => [p.name, p.version]));
|
|
261
|
+
|
|
262
|
+
for (const [depName, depVersion] of Object.entries(pluginDeps)) {
|
|
263
|
+
if (!installedMap.has(depName)) {
|
|
264
|
+
result.missing.push(`${depName} (требуется ${depVersion})`);
|
|
265
|
+
result.isValid = false;
|
|
266
|
+
} else {
|
|
267
|
+
const installedVersion = installedMap.get(depName);
|
|
268
|
+
if (depVersion.startsWith('^') || depVersion.startsWith('~')) {
|
|
269
|
+
const requiredBase = depVersion.slice(1);
|
|
270
|
+
if (!installedVersion.startsWith(requiredBase.split('.')[0])) {
|
|
271
|
+
result.warnings.push(
|
|
272
|
+
`${depName}: установлена v${installedVersion}, требуется ${depVersion}`
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return result;
|
|
280
|
+
}
|
|
281
|
+
|
|
51
282
|
async _installDependencies(pluginPath) {
|
|
52
283
|
const packageJsonPath = path.join(pluginPath, 'package.json');
|
|
53
284
|
try {
|
|
@@ -108,9 +339,22 @@ class PluginManager {
|
|
|
108
339
|
}
|
|
109
340
|
|
|
110
341
|
async installFromLocalPath(botId, directoryPath) {
|
|
342
|
+
// Проверяем зависимости плагина перед установкой
|
|
343
|
+
const packageJsonPath = path.join(directoryPath, 'package.json');
|
|
344
|
+
const packageJson = JSON.parse(await fse.readFile(packageJsonPath, 'utf-8'));
|
|
345
|
+
|
|
346
|
+
const depCheck = await this.checkPluginDependencies(botId, packageJson);
|
|
347
|
+
if (!depCheck.isValid) {
|
|
348
|
+
const missingList = depCheck.missing.join(', ');
|
|
349
|
+
console.warn(`[PluginManager] ⚠️ Плагин ${packageJson.name} требует: ${missingList}`);
|
|
350
|
+
console.warn(`[PluginManager] Плагин будет установлен, но может работать некорректно без зависимостей.`);
|
|
351
|
+
}
|
|
352
|
+
if (depCheck.warnings.length > 0) {
|
|
353
|
+
depCheck.warnings.forEach(w => console.warn(`[PluginManager] ⚠️ ${w}`));
|
|
354
|
+
}
|
|
355
|
+
|
|
111
356
|
const newPlugin = await this.registerPlugin(botId, directoryPath, 'LOCAL', directoryPath);
|
|
112
357
|
try {
|
|
113
|
-
const packageJson = JSON.parse(await fse.readFile(path.join(directoryPath, 'package.json'), 'utf-8'));
|
|
114
358
|
reportPluginDownload(packageJson.name);
|
|
115
359
|
} catch(e) {
|
|
116
360
|
console.error('Не удалось прочитать package.json для отправки статистики локального плагина');
|
|
@@ -118,17 +362,19 @@ class PluginManager {
|
|
|
118
362
|
|
|
119
363
|
await this._installDependencies(directoryPath);
|
|
120
364
|
await this.loadPluginGraphs(botId, newPlugin.id, directoryPath);
|
|
121
|
-
|
|
365
|
+
|
|
122
366
|
if (this.botManager) {
|
|
123
367
|
await this.botManager.reloadPlugins(botId);
|
|
124
368
|
}
|
|
125
|
-
|
|
369
|
+
|
|
126
370
|
return newPlugin;
|
|
127
371
|
}
|
|
128
372
|
|
|
129
373
|
async installFromGithub(botId, repoUrl, prismaClient = prisma, isUpdate = false, tag = null) {
|
|
130
374
|
const botPluginsDir = path.join(PLUGINS_BASE_DIR, `bot_${botId}`);
|
|
131
375
|
await fse.mkdir(botPluginsDir, { recursive: true });
|
|
376
|
+
let sourceRefType = tag ? 'tag' : 'branch';
|
|
377
|
+
let sourceRef = tag || 'main';
|
|
132
378
|
|
|
133
379
|
if (!isUpdate) {
|
|
134
380
|
const existing = await prismaClient.installedPlugin.findFirst({ where: { botId, sourceUri: repoUrl } });
|
|
@@ -138,32 +384,30 @@ class PluginManager {
|
|
|
138
384
|
try {
|
|
139
385
|
const url = new URL(repoUrl);
|
|
140
386
|
const repoPath = url.pathname.replace(/^\/|\.git$/g, '');
|
|
387
|
+
const repoInfo = tag ? null : await fetchGithubRepoInfo(repoUrl);
|
|
388
|
+
if (repoInfo?.default_branch) {
|
|
389
|
+
sourceRef = repoInfo.default_branch;
|
|
390
|
+
}
|
|
141
391
|
|
|
142
392
|
let response;
|
|
143
393
|
|
|
144
|
-
// Если указан тег - скачиваем конкретный релиз
|
|
145
394
|
if (tag) {
|
|
146
|
-
const archiveUrlTag = `https://github.com/${repoPath}/archive/refs/tags/${encodeURIComponent(tag)}.zip`;
|
|
147
395
|
console.log(`[PluginManager] Скачиваем релиз ${tag} из ${repoUrl}...`);
|
|
148
396
|
try {
|
|
149
|
-
response = await
|
|
397
|
+
response = await downloadGithubArchive(repoUrl, tag);
|
|
150
398
|
} catch (err) {
|
|
151
399
|
throw new Error(`Ошибка сети при скачивании релиза ${tag}: ${err.message || err}`);
|
|
152
400
|
}
|
|
153
|
-
if (!response.ok) {
|
|
154
|
-
throw new Error(`Не удалось скачать релиз ${tag}. Статус: ${response.status}. Возможно, тег не существует.`);
|
|
155
|
-
}
|
|
156
401
|
} else {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
throw new Error(`Не удалось скачать архив плагина. Статус: ${response.status}`);
|
|
402
|
+
try {
|
|
403
|
+
response = await downloadGithubArchive(repoUrl, sourceRef);
|
|
404
|
+
} catch (err) {
|
|
405
|
+
if (!repoInfo && sourceRef !== 'master') {
|
|
406
|
+
console.log(`[PluginManager] Ветка '${sourceRef}' не найдена для ${repoUrl}, пробую 'master'...`);
|
|
407
|
+
sourceRef = 'master';
|
|
408
|
+
response = await downloadGithubArchive(repoUrl, sourceRef);
|
|
409
|
+
} else {
|
|
410
|
+
throw new Error(`Не удалось скачать архив плагина: ${err.message || err}`);
|
|
167
411
|
}
|
|
168
412
|
}
|
|
169
413
|
}
|
|
@@ -193,9 +437,23 @@ class PluginManager {
|
|
|
193
437
|
|
|
194
438
|
await this._installDependencies(localPath);
|
|
195
439
|
|
|
196
|
-
|
|
197
|
-
|
|
440
|
+
|
|
198
441
|
const packageJson = JSON.parse(await fse.readFile(path.join(localPath, 'package.json'), 'utf-8'));
|
|
442
|
+
const depCheck = await this.checkPluginDependencies(botId, packageJson);
|
|
443
|
+
if (!depCheck.isValid) {
|
|
444
|
+
const missingList = depCheck.missing.join(', ');
|
|
445
|
+
console.warn(`[PluginManager] ⚠️ Плагин ${packageJson.name} требует: ${missingList}`);
|
|
446
|
+
console.warn(`[PluginManager] Плагин будет установлен, но может работать некорректно без зависимостей.`);
|
|
447
|
+
}
|
|
448
|
+
if (depCheck.warnings.length > 0) {
|
|
449
|
+
depCheck.warnings.forEach(w => console.warn(`[PluginManager] ⚠️ ${w}`));
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
const newPlugin = await this.registerPlugin(botId, localPath, 'GITHUB', repoUrl, prismaClient, {
|
|
453
|
+
sourceRefType,
|
|
454
|
+
sourceRef
|
|
455
|
+
});
|
|
456
|
+
|
|
199
457
|
reportPluginDownload(packageJson.name);
|
|
200
458
|
|
|
201
459
|
await this.loadPluginGraphs(botId, newPlugin.id, localPath);
|
|
@@ -215,7 +473,7 @@ class PluginManager {
|
|
|
215
473
|
}
|
|
216
474
|
}
|
|
217
475
|
|
|
218
|
-
async registerPlugin(botId, directoryPath, sourceType, sourceUri, prismaClient = prisma) {
|
|
476
|
+
async registerPlugin(botId, directoryPath, sourceType, sourceUri, prismaClient = prisma, extraData = {}) {
|
|
219
477
|
const packageJsonPath = path.join(directoryPath, 'package.json');
|
|
220
478
|
let packageJson;
|
|
221
479
|
try {
|
|
@@ -237,6 +495,7 @@ class PluginManager {
|
|
|
237
495
|
sourceType,
|
|
238
496
|
sourceUri: sourceUri || directoryPath,
|
|
239
497
|
manifest: JSON.stringify(packageJson.botpanel || {}),
|
|
498
|
+
...extraData,
|
|
240
499
|
};
|
|
241
500
|
|
|
242
501
|
return prismaClient.installedPlugin.upsert({
|
|
@@ -327,24 +586,76 @@ class PluginManager {
|
|
|
327
586
|
where: { botId, sourceType: 'GITHUB' }
|
|
328
587
|
});
|
|
329
588
|
const updatesAvailable = [];
|
|
330
|
-
const
|
|
589
|
+
const catalogMapByRepo = new Map();
|
|
590
|
+
const catalogMapByName = new Map();
|
|
591
|
+
const catalogMapByRepoName = new Map();
|
|
592
|
+
const latestTagCache = new Map();
|
|
593
|
+
|
|
594
|
+
for (const item of catalog) {
|
|
595
|
+
const normalizedRepoUrl = normalizeGithubRepoUrl(item.repoUrl);
|
|
596
|
+
if (normalizedRepoUrl) {
|
|
597
|
+
catalogMapByRepo.set(normalizedRepoUrl, item);
|
|
598
|
+
const repoName = getGithubRepoName(normalizedRepoUrl);
|
|
599
|
+
if (repoName && !catalogMapByRepoName.has(repoName)) {
|
|
600
|
+
catalogMapByRepoName.set(repoName, item);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
if (item?.name) {
|
|
604
|
+
catalogMapByName.set(String(item.name).toLowerCase(), item);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
331
607
|
|
|
332
608
|
for (const plugin of githubPlugins) {
|
|
333
609
|
try {
|
|
334
|
-
const
|
|
335
|
-
|
|
610
|
+
const normalizedSourceUri = normalizeGithubRepoUrl(plugin.sourceUri);
|
|
611
|
+
const repoName = getGithubRepoName(normalizedSourceUri || plugin.sourceUri);
|
|
612
|
+
const catalogInfo =
|
|
613
|
+
(normalizedSourceUri ? catalogMapByRepo.get(normalizedSourceUri) : null) ||
|
|
614
|
+
catalogMapByName.get(String(plugin.name).toLowerCase()) ||
|
|
615
|
+
(repoName ? catalogMapByRepoName.get(repoName) : null);
|
|
616
|
+
|
|
617
|
+
const targetRepoUrl = catalogInfo?.repoUrl || normalizedSourceUri || normalizeGithubRepoUrl(plugin.sourceUri) || plugin.sourceUri;
|
|
618
|
+
let latestTagRaw =
|
|
619
|
+
catalogInfo?.latestTag ||
|
|
620
|
+
catalogInfo?.recommendedVersion ||
|
|
621
|
+
catalogInfo?.version ||
|
|
622
|
+
catalogInfo?.latestVersion ||
|
|
623
|
+
catalogInfo?.tag;
|
|
624
|
+
|
|
625
|
+
if (!latestTagRaw) {
|
|
626
|
+
const cacheKey = targetRepoUrl || plugin.name;
|
|
627
|
+
if (latestTagCache.has(cacheKey)) {
|
|
628
|
+
latestTagRaw = latestTagCache.get(cacheKey);
|
|
629
|
+
} else {
|
|
630
|
+
const fetchedTag = targetRepoUrl ? await fetchLatestGithubVersionTag(targetRepoUrl) : null;
|
|
631
|
+
latestTagCache.set(cacheKey, fetchedTag);
|
|
632
|
+
latestTagRaw = fetchedTag;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
let latestVersionRaw = latestTagRaw;
|
|
637
|
+
if (!latestVersionRaw && targetRepoUrl) {
|
|
638
|
+
latestVersionRaw = await fetchGithubPackageVersion(
|
|
639
|
+
targetRepoUrl,
|
|
640
|
+
plugin.sourceRefType === 'branch' ? plugin.sourceRef : null
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
if (!latestVersionRaw) continue;
|
|
336
645
|
|
|
337
|
-
const
|
|
338
|
-
const
|
|
646
|
+
const localSemver = semver.coerce(plugin.version);
|
|
647
|
+
const remoteSemver = semver.coerce(latestVersionRaw);
|
|
648
|
+
if (!localSemver || !remoteSemver) continue;
|
|
339
649
|
|
|
340
|
-
if (semver.gt(
|
|
650
|
+
if (semver.gt(remoteSemver.version, localSemver.version)) {
|
|
341
651
|
updatesAvailable.push({
|
|
342
652
|
id: plugin.id,
|
|
343
653
|
name: plugin.name,
|
|
344
654
|
sourceUri: plugin.sourceUri,
|
|
345
|
-
currentVersion:
|
|
346
|
-
recommendedVersion:
|
|
347
|
-
latestTag: catalogInfo
|
|
655
|
+
currentVersion: localSemver.version,
|
|
656
|
+
recommendedVersion: remoteSemver.version,
|
|
657
|
+
latestTag: catalogInfo?.latestTag || latestTagRaw || null,
|
|
658
|
+
targetRepoUrl,
|
|
348
659
|
});
|
|
349
660
|
}
|
|
350
661
|
} catch (error) {
|
|
@@ -354,7 +665,7 @@ class PluginManager {
|
|
|
354
665
|
return updatesAvailable;
|
|
355
666
|
}
|
|
356
667
|
|
|
357
|
-
async updatePlugin(pluginId, targetTag = null) {
|
|
668
|
+
async updatePlugin(pluginId, targetTag = null, targetRepoUrl = null) {
|
|
358
669
|
const plugin = await prisma.installedPlugin.findUnique({ where: { id: pluginId } });
|
|
359
670
|
if (!plugin || plugin.sourceType !== 'GITHUB') {
|
|
360
671
|
throw new Error('Плагин не найден или не является GitHub-плагином.');
|
|
@@ -362,7 +673,7 @@ class PluginManager {
|
|
|
362
673
|
|
|
363
674
|
console.log(`[PluginManager] Начало обновления плагина ${plugin.name}${targetTag ? ` до версии ${targetTag}` : ''}...`);
|
|
364
675
|
|
|
365
|
-
const repoUrl = plugin.sourceUri;
|
|
676
|
+
const repoUrl = targetRepoUrl || plugin.sourceUri;
|
|
366
677
|
const botId = plugin.botId;
|
|
367
678
|
const oldVersion = plugin.version;
|
|
368
679
|
|
|
@@ -584,4 +895,4 @@ class PluginManager {
|
|
|
584
895
|
}
|
|
585
896
|
}
|
|
586
897
|
|
|
587
|
-
module.exports = PluginManager;
|
|
898
|
+
module.exports = PluginManager;
|