blockmine 1.20.0 → 1.22.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.
Files changed (434) hide show
  1. package/.claude/agents/README.md +469 -0
  2. package/.claude/agents/auth-route-debugger.md +118 -0
  3. package/.claude/agents/auth-route-tester.md +93 -0
  4. package/.claude/agents/auto-error-resolver.md +97 -0
  5. package/.claude/agents/build-optimizer.md +236 -0
  6. package/.claude/agents/code-architecture-reviewer.md +83 -0
  7. package/.claude/agents/code-refactor-master.md +94 -0
  8. package/.claude/agents/cost-optimizer.md +134 -0
  9. package/.claude/agents/deployment-orchestrator.md +113 -0
  10. package/.claude/agents/documentation-architect.md +82 -0
  11. package/.claude/agents/frontend-error-fixer.md +77 -0
  12. package/.claude/agents/iac-code-generator.md +71 -0
  13. package/.claude/agents/incident-responder.md +346 -0
  14. package/.claude/agents/infrastructure-architect.md +31 -0
  15. package/.claude/agents/kubernetes-specialist.md +56 -0
  16. package/.claude/agents/migration-planner.md +181 -0
  17. package/.claude/agents/network-architect.md +196 -0
  18. package/.claude/agents/plan-reviewer.md +52 -0
  19. package/.claude/agents/refactor-planner.md +63 -0
  20. package/.claude/agents/security-scanner.md +102 -0
  21. package/.claude/agents/web-research-specialist.md +78 -0
  22. package/.claude/commands/cost-analysis.md +315 -0
  23. package/.claude/commands/dev-docs-update.md +55 -0
  24. package/.claude/commands/dev-docs.md +51 -0
  25. package/.claude/commands/incident-debug.md +247 -0
  26. package/.claude/commands/infra-plan.md +81 -0
  27. package/.claude/commands/migration-plan.md +478 -0
  28. package/.claude/commands/route-research-for-testing.md +37 -0
  29. package/.claude/commands/security-review.md +66 -0
  30. package/.claude/hooks/CONFIG.md +448 -0
  31. package/.claude/hooks/README.md +163 -0
  32. package/.claude/hooks/SKILL_ACTIVATION_COMPLETE.md +226 -0
  33. package/.claude/hooks/WINDOWS_HOOKS_README.md +151 -0
  34. package/.claude/hooks/add-skill-activation-banners.ts +132 -0
  35. package/.claude/hooks/comprehensive-skill-test.ts +1315 -0
  36. package/.claude/hooks/error-handling-reminder.sh +12 -0
  37. package/.claude/hooks/error-handling-reminder.ts +222 -0
  38. package/.claude/hooks/k8s-manifest-validator.sh +56 -0
  39. package/.claude/hooks/package-lock.json +556 -0
  40. package/.claude/hooks/package.json +16 -0
  41. package/.claude/hooks/post-tool-use-tracker.ps1 +174 -0
  42. package/.claude/hooks/post-tool-use-tracker.sh +183 -0
  43. package/.claude/hooks/security-policy-check.sh +247 -0
  44. package/.claude/hooks/skill-activation-prompt.ps1 +10 -0
  45. package/.claude/hooks/skill-activation-prompt.sh +10 -0
  46. package/.claude/hooks/skill-activation-prompt.ts +141 -0
  47. package/.claude/hooks/stop-build-check-enhanced.sh +130 -0
  48. package/.claude/hooks/terraform-validator.sh +53 -0
  49. package/.claude/hooks/test-input.json +7 -0
  50. package/.claude/hooks/test-skill-activation.ts +427 -0
  51. package/.claude/hooks/trigger-build-resolver.sh +79 -0
  52. package/.claude/hooks/tsc-check.sh +173 -0
  53. package/.claude/hooks/tsconfig.json +19 -0
  54. package/.claude/settings.json +55 -0
  55. package/.claude/settings.local.json +28 -3
  56. package/.claude/skills/README.md +507 -0
  57. package/.claude/skills/api-engineering/SKILL.md +63 -0
  58. package/.claude/skills/api-engineering/resources/api-versioning.md +88 -0
  59. package/.claude/skills/api-engineering/resources/graphql-patterns.md +106 -0
  60. package/.claude/skills/api-engineering/resources/rate-limiting.md +118 -0
  61. package/.claude/skills/api-engineering/resources/rest-api-design.md +105 -0
  62. package/.claude/skills/backend-dev-guidelines/SKILL.md +306 -0
  63. package/.claude/skills/backend-dev-guidelines/resources/architecture-overview.md +451 -0
  64. package/.claude/skills/backend-dev-guidelines/resources/async-and-errors.md +307 -0
  65. package/.claude/skills/backend-dev-guidelines/resources/complete-examples.md +638 -0
  66. package/.claude/skills/backend-dev-guidelines/resources/configuration.md +275 -0
  67. package/.claude/skills/backend-dev-guidelines/resources/database-patterns.md +224 -0
  68. package/.claude/skills/backend-dev-guidelines/resources/middleware-guide.md +213 -0
  69. package/.claude/skills/backend-dev-guidelines/resources/routing-and-controllers.md +756 -0
  70. package/.claude/skills/backend-dev-guidelines/resources/sentry-and-monitoring.md +336 -0
  71. package/.claude/skills/backend-dev-guidelines/resources/services-and-repositories.md +789 -0
  72. package/.claude/skills/backend-dev-guidelines/resources/testing-guide.md +235 -0
  73. package/.claude/skills/backend-dev-guidelines/resources/validation-patterns.md +754 -0
  74. package/.claude/skills/budget-and-cost-management/SKILL.md +850 -0
  75. package/.claude/skills/build-engineering/SKILL.md +431 -0
  76. package/.claude/skills/build-engineering/resources/artifact-repositories.md +72 -0
  77. package/.claude/skills/build-engineering/resources/build-caching.md +96 -0
  78. package/.claude/skills/build-engineering/resources/build-pipelines.md +105 -0
  79. package/.claude/skills/build-engineering/resources/build-security.md +95 -0
  80. package/.claude/skills/build-engineering/resources/build-systems.md +389 -0
  81. package/.claude/skills/build-engineering/resources/compilation-optimization.md +201 -0
  82. package/.claude/skills/build-engineering/resources/dependency-management.md +73 -0
  83. package/.claude/skills/build-engineering/resources/monorepo-builds.md +110 -0
  84. package/.claude/skills/build-engineering/resources/performance-optimization.md +113 -0
  85. package/.claude/skills/build-engineering/resources/reproducible-builds.md +82 -0
  86. package/.claude/skills/cloud-engineering/SKILL.md +675 -0
  87. package/.claude/skills/cloud-engineering/resources/aws-patterns.md +742 -0
  88. package/.claude/skills/cloud-engineering/resources/azure-patterns.md +714 -0
  89. package/.claude/skills/cloud-engineering/resources/cleared-cloud-environments.md +987 -0
  90. package/.claude/skills/cloud-engineering/resources/cloud-cost-optimization.md +757 -0
  91. package/.claude/skills/cloud-engineering/resources/cloud-networking.md +1058 -0
  92. package/.claude/skills/cloud-engineering/resources/cloud-security-tools.md +1530 -0
  93. package/.claude/skills/cloud-engineering/resources/cloud-security.md +990 -0
  94. package/.claude/skills/cloud-engineering/resources/gcp-patterns.md +758 -0
  95. package/.claude/skills/cloud-engineering/resources/migration-strategies.md +820 -0
  96. package/.claude/skills/cloud-engineering/resources/multi-cloud-strategies.md +670 -0
  97. package/.claude/skills/cloud-engineering/resources/oci-patterns.md +1198 -0
  98. package/.claude/skills/cloud-engineering/resources/serverless-patterns.md +795 -0
  99. package/.claude/skills/cloud-engineering/resources/well-architected-frameworks.md +966 -0
  100. package/.claude/skills/cybersecurity/SKILL.md +409 -0
  101. package/.claude/skills/cybersecurity/resources/security-architecture.md +266 -0
  102. package/.claude/skills/database-engineering/SKILL.md +61 -0
  103. package/.claude/skills/database-engineering/resources/backup-and-recovery.md +72 -0
  104. package/.claude/skills/database-engineering/resources/database-replication.md +63 -0
  105. package/.claude/skills/database-engineering/resources/postgresql-fundamentals.md +70 -0
  106. package/.claude/skills/database-engineering/resources/query-optimization.md +68 -0
  107. package/.claude/skills/devsecops/SKILL.md +374 -0
  108. package/.claude/skills/devsecops/resources/ci-cd-security.md +204 -0
  109. package/.claude/skills/devsecops/resources/compliance-automation.md +530 -0
  110. package/.claude/skills/devsecops/resources/compliance-frameworks.md +2322 -0
  111. package/.claude/skills/devsecops/resources/container-security.md +915 -0
  112. package/.claude/skills/devsecops/resources/cspm-integration.md +1440 -0
  113. package/.claude/skills/devsecops/resources/policy-enforcement.md +619 -0
  114. package/.claude/skills/devsecops/resources/secrets-management.md +755 -0
  115. package/.claude/skills/devsecops/resources/security-monitoring.md +146 -0
  116. package/.claude/skills/devsecops/resources/security-scanning.md +887 -0
  117. package/.claude/skills/devsecops/resources/security-testing.md +203 -0
  118. package/.claude/skills/devsecops/resources/supply-chain-security.md +518 -0
  119. package/.claude/skills/devsecops/resources/vulnerability-management.md +481 -0
  120. package/.claude/skills/devsecops/resources/zero-trust-architecture.md +177 -0
  121. package/.claude/skills/documentation-as-code/SKILL.md +323 -0
  122. package/.claude/skills/documentation-as-code/resources/api-documentation.md +90 -0
  123. package/.claude/skills/documentation-as-code/resources/changelog-management.md +79 -0
  124. package/.claude/skills/documentation-as-code/resources/diagram-generation.md +44 -0
  125. package/.claude/skills/documentation-as-code/resources/docs-as-code-workflow.md +99 -0
  126. package/.claude/skills/documentation-as-code/resources/documentation-automation.md +68 -0
  127. package/.claude/skills/documentation-as-code/resources/documentation-sites.md +79 -0
  128. package/.claude/skills/documentation-as-code/resources/markdown-best-practices.md +162 -0
  129. package/.claude/skills/documentation-as-code/resources/openapi-specification.md +77 -0
  130. package/.claude/skills/documentation-as-code/resources/readme-engineering.md +60 -0
  131. package/.claude/skills/documentation-as-code/resources/technical-writing-guide.md +202 -0
  132. package/.claude/skills/engineering-management/SKILL.md +356 -0
  133. package/.claude/skills/engineering-management/resources/career-ladders.md +609 -0
  134. package/.claude/skills/engineering-management/resources/hiring-and-assessment.md +555 -0
  135. package/.claude/skills/engineering-management/resources/one-on-one-guides.md +609 -0
  136. package/.claude/skills/engineering-management/resources/resource-planning.md +557 -0
  137. package/.claude/skills/engineering-management/resources/team-organization-patterns.md +491 -0
  138. package/.claude/skills/engineering-management/resources/technical-interviews.md +474 -0
  139. package/.claude/skills/engineering-operations-management/SKILL.md +817 -0
  140. package/.claude/skills/error-tracking/SKILL.md +379 -0
  141. package/.claude/skills/frontend-dev-guidelines/SKILL.md +403 -0
  142. package/.claude/skills/frontend-dev-guidelines/resources/common-patterns.md +331 -0
  143. package/.claude/skills/frontend-dev-guidelines/resources/complete-examples.md +872 -0
  144. package/.claude/skills/frontend-dev-guidelines/resources/component-patterns.md +502 -0
  145. package/.claude/skills/frontend-dev-guidelines/resources/data-fetching.md +767 -0
  146. package/.claude/skills/frontend-dev-guidelines/resources/file-organization.md +502 -0
  147. package/.claude/skills/frontend-dev-guidelines/resources/loading-and-error-states.md +501 -0
  148. package/.claude/skills/frontend-dev-guidelines/resources/performance.md +406 -0
  149. package/.claude/skills/frontend-dev-guidelines/resources/routing-guide.md +364 -0
  150. package/.claude/skills/frontend-dev-guidelines/resources/styling-guide.md +428 -0
  151. package/.claude/skills/frontend-dev-guidelines/resources/typescript-standards.md +418 -0
  152. package/.claude/skills/general-it-engineering/SKILL.md +393 -0
  153. package/.claude/skills/general-it-engineering/resources/asset-management.md +712 -0
  154. package/.claude/skills/general-it-engineering/resources/automation-orchestration.md +817 -0
  155. package/.claude/skills/general-it-engineering/resources/business-continuity.md +786 -0
  156. package/.claude/skills/general-it-engineering/resources/change-management.md +715 -0
  157. package/.claude/skills/general-it-engineering/resources/enterprise-monitoring.md +729 -0
  158. package/.claude/skills/general-it-engineering/resources/help-desk-operations.md +738 -0
  159. package/.claude/skills/general-it-engineering/resources/incident-service-management.md +834 -0
  160. package/.claude/skills/general-it-engineering/resources/it-governance.md +753 -0
  161. package/.claude/skills/general-it-engineering/resources/itil-framework.md +503 -0
  162. package/.claude/skills/general-it-engineering/resources/service-management.md +669 -0
  163. package/.claude/skills/infrastructure-architecture/SKILL.md +328 -0
  164. package/.claude/skills/infrastructure-architecture/resources/architecture-decision-records.md +505 -0
  165. package/.claude/skills/infrastructure-architecture/resources/architecture-patterns.md +528 -0
  166. package/.claude/skills/infrastructure-architecture/resources/capacity-planning.md +453 -0
  167. package/.claude/skills/infrastructure-architecture/resources/cleared-environment-architecture.md +773 -0
  168. package/.claude/skills/infrastructure-architecture/resources/cost-architecture.md +499 -0
  169. package/.claude/skills/infrastructure-architecture/resources/data-architecture.md +501 -0
  170. package/.claude/skills/infrastructure-architecture/resources/disaster-recovery.md +535 -0
  171. package/.claude/skills/infrastructure-architecture/resources/migration-architecture.md +512 -0
  172. package/.claude/skills/infrastructure-architecture/resources/multi-region-design.md +608 -0
  173. package/.claude/skills/infrastructure-architecture/resources/reference-architectures.md +562 -0
  174. package/.claude/skills/infrastructure-architecture/resources/security-architecture.md +538 -0
  175. package/.claude/skills/infrastructure-architecture/resources/system-design-principles.md +489 -0
  176. package/.claude/skills/infrastructure-architecture/resources/workload-classification.md +1000 -0
  177. package/.claude/skills/infrastructure-strategy/SKILL.md +924 -0
  178. package/.claude/skills/network-engineering/SKILL.md +385 -0
  179. package/.claude/skills/network-engineering/resources/dns-management.md +738 -0
  180. package/.claude/skills/network-engineering/resources/load-balancing.md +820 -0
  181. package/.claude/skills/network-engineering/resources/network-architecture.md +546 -0
  182. package/.claude/skills/network-engineering/resources/network-security.md +921 -0
  183. package/.claude/skills/network-engineering/resources/network-troubleshooting.md +749 -0
  184. package/.claude/skills/network-engineering/resources/routing-switching.md +373 -0
  185. package/.claude/skills/network-engineering/resources/sdn-networking.md +695 -0
  186. package/.claude/skills/network-engineering/resources/service-mesh-networking.md +777 -0
  187. package/.claude/skills/network-engineering/resources/tcp-ip-protocols.md +444 -0
  188. package/.claude/skills/network-engineering/resources/vpn-connectivity.md +672 -0
  189. package/.claude/skills/observability-engineering/SKILL.md +101 -0
  190. package/.claude/skills/observability-engineering/resources/apm-tools.md +97 -0
  191. package/.claude/skills/observability-engineering/resources/correlation-strategies.md +87 -0
  192. package/.claude/skills/observability-engineering/resources/distributed-tracing.md +98 -0
  193. package/.claude/skills/observability-engineering/resources/logs-aggregation.md +118 -0
  194. package/.claude/skills/observability-engineering/resources/observability-cost-optimization.md +141 -0
  195. package/.claude/skills/observability-engineering/resources/opentelemetry.md +110 -0
  196. package/.claude/skills/platform-engineering/SKILL.md +555 -0
  197. package/.claude/skills/platform-engineering/resources/architecture-overview.md +600 -0
  198. package/.claude/skills/platform-engineering/resources/container-orchestration.md +916 -0
  199. package/.claude/skills/platform-engineering/resources/cost-optimization.md +634 -0
  200. package/.claude/skills/platform-engineering/resources/developer-platforms.md +670 -0
  201. package/.claude/skills/platform-engineering/resources/gitops-automation.md +650 -0
  202. package/.claude/skills/platform-engineering/resources/infrastructure-as-code.md +778 -0
  203. package/.claude/skills/platform-engineering/resources/infrastructure-standards.md +708 -0
  204. package/.claude/skills/platform-engineering/resources/multi-tenancy.md +602 -0
  205. package/.claude/skills/platform-engineering/resources/platform-security.md +711 -0
  206. package/.claude/skills/platform-engineering/resources/resource-management.md +592 -0
  207. package/.claude/skills/platform-engineering/resources/service-mesh.md +628 -0
  208. package/.claude/skills/release-engineering/SKILL.md +393 -0
  209. package/.claude/skills/release-engineering/resources/artifact-management.md +108 -0
  210. package/.claude/skills/release-engineering/resources/build-optimization.md +84 -0
  211. package/.claude/skills/release-engineering/resources/ci-cd-pipelines.md +411 -0
  212. package/.claude/skills/release-engineering/resources/deployment-strategies.md +197 -0
  213. package/.claude/skills/release-engineering/resources/pipeline-security.md +62 -0
  214. package/.claude/skills/release-engineering/resources/progressive-delivery.md +83 -0
  215. package/.claude/skills/release-engineering/resources/release-automation.md +68 -0
  216. package/.claude/skills/release-engineering/resources/release-orchestration.md +77 -0
  217. package/.claude/skills/release-engineering/resources/rollback-strategies.md +66 -0
  218. package/.claude/skills/release-engineering/resources/versioning-strategies.md +59 -0
  219. package/.claude/skills/route-tester/SKILL.md +392 -0
  220. package/.claude/skills/skill-developer/ADVANCED.md +197 -0
  221. package/.claude/skills/skill-developer/HOOK_MECHANISMS.md +306 -0
  222. package/.claude/skills/skill-developer/PATTERNS_LIBRARY.md +152 -0
  223. package/.claude/skills/skill-developer/SKILL.md +430 -0
  224. package/.claude/skills/skill-developer/SKILL_RULES_REFERENCE.md +315 -0
  225. package/.claude/skills/skill-developer/TRIGGER_TYPES.md +305 -0
  226. package/.claude/skills/skill-developer/TROUBLESHOOTING.md +514 -0
  227. package/.claude/skills/skill-rules.json +2940 -0
  228. package/.claude/skills/sre/SKILL.md +464 -0
  229. package/.claude/skills/sre/resources/alerting-best-practices.md +282 -0
  230. package/.claude/skills/sre/resources/capacity-planning.md +226 -0
  231. package/.claude/skills/sre/resources/chaos-engineering.md +193 -0
  232. package/.claude/skills/sre/resources/disaster-recovery.md +232 -0
  233. package/.claude/skills/sre/resources/incident-management.md +436 -0
  234. package/.claude/skills/sre/resources/observability-stack.md +240 -0
  235. package/.claude/skills/sre/resources/on-call-runbooks.md +167 -0
  236. package/.claude/skills/sre/resources/performance-optimization.md +108 -0
  237. package/.claude/skills/sre/resources/reliability-patterns.md +183 -0
  238. package/.claude/skills/sre/resources/slo-sli-sla.md +464 -0
  239. package/.claude/skills/sre/resources/toil-reduction.md +145 -0
  240. package/.claude/skills/systems-engineering/SKILL.md +648 -0
  241. package/.claude/skills/systems-engineering/resources/automation-patterns.md +771 -0
  242. package/.claude/skills/systems-engineering/resources/configuration-management.md +998 -0
  243. package/.claude/skills/systems-engineering/resources/linux-administration.md +672 -0
  244. package/.claude/skills/systems-engineering/resources/networking-fundamentals.md +982 -0
  245. package/.claude/skills/systems-engineering/resources/performance-tuning.md +871 -0
  246. package/.claude/skills/systems-engineering/resources/powershell-scripting.md +482 -0
  247. package/.claude/skills/systems-engineering/resources/security-hardening.md +739 -0
  248. package/.claude/skills/systems-engineering/resources/shell-scripting.md +915 -0
  249. package/.claude/skills/systems-engineering/resources/storage-management.md +628 -0
  250. package/.claude/skills/systems-engineering/resources/system-monitoring.md +787 -0
  251. package/.claude/skills/systems-engineering/resources/troubleshooting-guide.md +753 -0
  252. package/.claude/skills/systems-engineering/resources/windows-administration.md +738 -0
  253. package/.claude/skills/technical-leadership/SKILL.md +728 -0
  254. package/CHANGELOG.md +90 -39
  255. package/README.md +94 -0
  256. package/backend/docs/SECRETS_DOCUMENTATION.md +327 -0
  257. package/backend/jest.config.js +59 -0
  258. package/backend/package-lock.json +6129 -0
  259. package/backend/package.json +16 -4
  260. package/backend/prisma/migrations/20251026104609_add_websocket_api/migration.sql +33 -0
  261. package/backend/prisma/schema.prisma +33 -0
  262. package/backend/src/__tests__/core/DependencyService.test.js +336 -0
  263. package/backend/src/__tests__/core/UserService.test.js +875 -0
  264. package/backend/src/__tests__/repositories/BaseRepository.test.js +146 -0
  265. package/backend/src/__tests__/repositories/BotRepository.test.js +118 -0
  266. package/backend/src/__tests__/repositories/CommandRepository.test.js +132 -0
  267. package/backend/src/__tests__/repositories/EventGraphRepository.test.js +93 -0
  268. package/backend/src/__tests__/repositories/GroupRepository.test.js +155 -0
  269. package/backend/src/__tests__/repositories/PermissionRepository.test.js +130 -0
  270. package/backend/src/__tests__/repositories/PluginRepository.test.js +107 -0
  271. package/backend/src/__tests__/repositories/ServerRepository.test.js +80 -0
  272. package/backend/src/__tests__/repositories/UserRepository.test.js +128 -0
  273. package/backend/src/__tests__/secretsFilter.test.js +425 -0
  274. package/backend/src/__tests__/services/BotLifecycleService.test.js +411 -0
  275. package/backend/src/__tests__/services/BotProcessManager.test.js +285 -0
  276. package/backend/src/__tests__/services/CacheManager.test.js +125 -0
  277. package/backend/src/__tests__/services/CommandExecutionService.test.js +460 -0
  278. package/backend/src/__tests__/services/ResourceMonitorService.test.js +207 -0
  279. package/backend/src/__tests__/services/TelemetryService.test.js +291 -0
  280. package/backend/src/__tests__/setup.js +25 -0
  281. package/backend/src/api/routes/apiKeys.js +181 -0
  282. package/backend/src/api/routes/bots.js +49 -7
  283. package/backend/src/api/routes/plugins.js +2 -1
  284. package/backend/src/api/routes/system.js +174 -0
  285. package/backend/src/container.js +82 -0
  286. package/backend/src/core/BotManager.js +142 -871
  287. package/backend/src/core/BotManager.old.js +1093 -0
  288. package/backend/src/core/BotProcess.js +1092 -850
  289. package/backend/src/core/BreakLoopSignal.js +8 -0
  290. package/backend/src/core/EventGraphManager.js +280 -193
  291. package/backend/src/core/GraphExecutionEngine.js +321 -928
  292. package/backend/src/core/MessageQueue.js +27 -6
  293. package/backend/src/core/NodeRegistry.js +37 -991
  294. package/backend/src/core/PluginManager.js +62 -12
  295. package/backend/src/core/PrismaService.js +32 -0
  296. package/backend/src/core/UserService.js +3 -3
  297. package/backend/src/core/__tests__/PrismaService.test.js +24 -0
  298. package/backend/src/core/commands/README.md +305 -0
  299. package/backend/src/core/commands/dev.js +13 -7
  300. package/backend/src/core/commands/ping.js +10 -4
  301. package/backend/src/core/commands/whois.js +63 -0
  302. package/backend/src/core/config/validation.js +27 -0
  303. package/backend/src/core/constants/graphTypes.js +21 -0
  304. package/backend/src/core/node-registries/actions.js +132 -0
  305. package/backend/src/core/node-registries/arrays.js +137 -0
  306. package/backend/src/core/node-registries/bot.js +23 -0
  307. package/backend/src/core/node-registries/data.js +290 -0
  308. package/backend/src/core/node-registries/debug.js +26 -0
  309. package/backend/src/core/node-registries/events.js +187 -0
  310. package/backend/src/core/node-registries/flow.js +139 -0
  311. package/backend/src/core/node-registries/logic.js +45 -0
  312. package/backend/src/core/node-registries/math.js +42 -0
  313. package/backend/src/core/node-registries/objects.js +98 -0
  314. package/backend/src/core/node-registries/strings.js +153 -0
  315. package/backend/src/core/node-registries/time.js +113 -0
  316. package/backend/src/core/node-registries/users.js +79 -0
  317. package/backend/src/core/nodes/actions/bot_look_at.js +36 -0
  318. package/backend/src/core/nodes/actions/bot_set_variable.js +32 -0
  319. package/backend/src/core/nodes/actions/http_request.js +98 -0
  320. package/backend/src/core/nodes/actions/send_log.js +28 -0
  321. package/backend/src/core/nodes/actions/send_message.js +32 -0
  322. package/backend/src/core/nodes/actions/send_websocket_response.js +33 -0
  323. package/backend/src/core/nodes/arrays/add_element.js +23 -0
  324. package/backend/src/core/nodes/arrays/contains.js +40 -0
  325. package/backend/src/core/nodes/arrays/find_index.js +23 -0
  326. package/backend/src/core/nodes/arrays/get_by_index.js +23 -0
  327. package/backend/src/core/nodes/arrays/get_next.js +35 -0
  328. package/backend/src/core/nodes/arrays/get_random_element.js +32 -0
  329. package/backend/src/core/nodes/arrays/remove_by_index.js +30 -0
  330. package/backend/src/core/nodes/bot/get_position.js +20 -0
  331. package/backend/src/core/nodes/data/array_literal.js +31 -0
  332. package/backend/src/core/nodes/data/boolean_literal.js +21 -0
  333. package/backend/src/core/nodes/data/cast.js +42 -0
  334. package/backend/src/core/nodes/data/datetime_literal.js +27 -0
  335. package/backend/src/core/nodes/data/entity_info.js +69 -0
  336. package/backend/src/core/nodes/data/get_argument.js +23 -0
  337. package/backend/src/core/nodes/data/get_bot_look.js +14 -0
  338. package/backend/src/core/nodes/data/get_entity_field.js +18 -0
  339. package/backend/src/core/nodes/data/get_nearby_entities.js +32 -0
  340. package/backend/src/core/nodes/data/get_nearby_players.js +64 -0
  341. package/backend/src/core/nodes/data/get_server_players.js +18 -0
  342. package/backend/src/core/nodes/data/get_user_field.js +40 -0
  343. package/backend/src/core/nodes/data/get_variable.js +23 -0
  344. package/backend/src/core/nodes/data/length.js +25 -0
  345. package/backend/src/core/nodes/data/make_object.js +31 -0
  346. package/backend/src/core/nodes/data/number_literal.js +21 -0
  347. package/backend/src/core/nodes/data/string_literal.js +34 -0
  348. package/backend/src/core/nodes/data/type_check.js +53 -0
  349. package/backend/src/core/nodes/debug/log.js +16 -0
  350. package/backend/src/core/nodes/flow/branch.js +15 -0
  351. package/backend/src/core/nodes/flow/break.js +14 -0
  352. package/backend/src/core/nodes/flow/delay.js +43 -0
  353. package/backend/src/core/nodes/flow/for_each.js +39 -0
  354. package/backend/src/core/nodes/flow/sequence.js +16 -0
  355. package/backend/src/core/nodes/flow/switch.js +47 -0
  356. package/backend/src/core/nodes/flow/while.js +64 -0
  357. package/backend/src/core/nodes/logic/__tests__/compare.test.js +83 -0
  358. package/backend/src/core/nodes/logic/compare.js +33 -0
  359. package/backend/src/core/nodes/logic/operation.js +35 -0
  360. package/backend/src/core/nodes/math/__tests__/operation.test.js +65 -0
  361. package/backend/src/core/nodes/math/operation.js +31 -0
  362. package/backend/src/core/nodes/math/random_number.js +43 -0
  363. package/backend/src/core/nodes/objects/create.js +40 -0
  364. package/backend/src/core/nodes/objects/delete.js +26 -0
  365. package/backend/src/core/nodes/objects/get.js +23 -0
  366. package/backend/src/core/nodes/objects/has_key.js +30 -0
  367. package/backend/src/core/nodes/objects/set.js +27 -0
  368. package/backend/src/core/nodes/strings/__tests__/concat.test.js +89 -0
  369. package/backend/src/core/nodes/strings/concat.js +27 -0
  370. package/backend/src/core/nodes/strings/contains.js +41 -0
  371. package/backend/src/core/nodes/strings/ends_with.js +43 -0
  372. package/backend/src/core/nodes/strings/equals.js +36 -0
  373. package/backend/src/core/nodes/strings/length.js +36 -0
  374. package/backend/src/core/nodes/strings/matches.js +39 -0
  375. package/backend/src/core/nodes/strings/split.js +37 -0
  376. package/backend/src/core/nodes/strings/starts_with.js +43 -0
  377. package/backend/src/core/nodes/time/__tests__/now.test.js +24 -0
  378. package/backend/src/core/nodes/time/add.js +33 -0
  379. package/backend/src/core/nodes/time/compare.js +35 -0
  380. package/backend/src/core/nodes/time/diff.js +29 -0
  381. package/backend/src/core/nodes/time/format.js +32 -0
  382. package/backend/src/core/nodes/time/now.js +18 -0
  383. package/backend/src/core/nodes/users/check_blacklist.js +37 -0
  384. package/backend/src/core/nodes/users/get_groups.js +36 -0
  385. package/backend/src/core/nodes/users/get_permissions.js +36 -0
  386. package/backend/src/core/nodes/users/set_blacklist.js +37 -0
  387. package/backend/src/core/services/BotLifecycleService.js +596 -0
  388. package/backend/src/core/services/BotProcessManager.js +163 -0
  389. package/backend/src/core/services/CacheManager.js +111 -0
  390. package/backend/src/core/services/CommandExecutionService.js +351 -0
  391. package/backend/src/core/services/ResourceMonitorService.js +90 -0
  392. package/backend/src/core/services/TelemetryService.js +124 -0
  393. package/backend/src/core/services/ValidationService.js +132 -0
  394. package/backend/src/core/services/__tests__/ValidationService.test.js +148 -0
  395. package/backend/src/core/services.js +20 -5
  396. package/backend/src/core/system/CommandContext.js +84 -0
  397. package/backend/src/core/system/Transport.js +78 -0
  398. package/backend/src/core/utils/__tests__/jsonParser.test.js +44 -0
  399. package/backend/src/core/utils/jsonParser.js +18 -0
  400. package/backend/src/core/utils/secretsFilter.js +262 -0
  401. package/backend/src/core/utils/variableParser.js +89 -0
  402. package/backend/src/core/validation/__tests__/nodeSchemas.test.js +175 -0
  403. package/backend/src/core/validation/nodeSchemas.js +112 -0
  404. package/backend/src/lib/prisma.js +2 -4
  405. package/backend/src/real-time/botApi/handlers/commandHandlers.js +28 -0
  406. package/backend/src/real-time/botApi/handlers/graphHandlers.js +99 -0
  407. package/backend/src/real-time/botApi/handlers/graphWebSocketHandlers.js +147 -0
  408. package/backend/src/real-time/botApi/handlers/index.js +43 -0
  409. package/backend/src/real-time/botApi/handlers/messageHandlers.js +66 -0
  410. package/backend/src/real-time/botApi/handlers/statusHandlers.js +17 -0
  411. package/backend/src/real-time/botApi/handlers/userHandlers.js +141 -0
  412. package/backend/src/real-time/botApi/index.js +40 -0
  413. package/backend/src/real-time/botApi/middleware.js +79 -0
  414. package/backend/src/real-time/botApi/utils.js +54 -0
  415. package/backend/src/real-time/socketHandler.js +6 -2
  416. package/backend/src/repositories/BaseRepository.js +43 -0
  417. package/backend/src/repositories/BotRepository.js +42 -0
  418. package/backend/src/repositories/CommandRepository.js +53 -0
  419. package/backend/src/repositories/EventGraphRepository.js +40 -0
  420. package/backend/src/repositories/GroupRepository.js +69 -0
  421. package/backend/src/repositories/PermissionRepository.js +48 -0
  422. package/backend/src/repositories/PluginRepository.js +42 -0
  423. package/backend/src/repositories/ServerRepository.js +27 -0
  424. package/backend/src/repositories/UserRepository.js +48 -0
  425. package/backend/src/server.js +3 -0
  426. package/backend/src/test-refactor.js +85 -0
  427. package/frontend/dist/assets/index-CfTo92bP.css +1 -0
  428. package/frontend/dist/assets/index-CiFD5X9Z.js +8344 -0
  429. package/frontend/dist/index.html +2 -2
  430. package/frontend/package.json +1 -5
  431. package/package.json +2 -1
  432. package/frontend/dist/assets/index-BFd7YoAj.css +0 -1
  433. package/frontend/dist/assets/index-CMMutadc.js +0 -8352
  434. package/nul +0 -0
@@ -1,951 +1,222 @@
1
- const { fork } = require('child_process');
2
- const path = require('path');
3
- const prisma = require('../lib/prisma');
4
- const pidusage = require('pidusage');
5
- const DependencyService = require('./DependencyService');
6
- const config = require('../config');
7
- const fs = require('fs');
8
- const os = require('os');
9
- const { v4: uuidv4 } = require('uuid');
10
- const crypto = require('crypto');
11
- const { decrypt } = require('./utils/crypto');
12
- const EventGraphManager = require('./EventGraphManager');
13
- const nodeRegistry = require('./NodeRegistry');
14
- const UserService = require('./UserService');
15
-
16
- const cooldowns = new Map();
17
- const warningCache = new Map();
18
- const WARNING_COOLDOWN = 10 * 1000;
19
-
20
- const STATS_SERVER_URL = 'http://185.65.200.184:3000';
21
- let instanceId = null;
22
- const DATA_DIR = path.join(os.homedir(), '.blockmine');
23
- const INSTANCE_ID_PATH = path.join(DATA_DIR, '.instance_id');
24
-
25
- function getInstanceId() {
26
- if (instanceId) return instanceId;
27
- try {
28
- if (fs.existsSync(INSTANCE_ID_PATH)) {
29
- instanceId = fs.readFileSync(INSTANCE_ID_PATH, 'utf-8');
30
- } else {
31
- instanceId = uuidv4();
32
- if (!fs.existsSync(DATA_DIR)) {
33
- fs.mkdirSync(DATA_DIR, { recursive: true });
34
- }
35
- fs.writeFileSync(INSTANCE_ID_PATH, instanceId, 'utf-8');
36
- }
37
- } catch (error) {
38
- console.error('[Telemetry] Ошибка при загрузке/создании Instance ID:', error);
39
- return null;
1
+ /**
2
+ * BotManager Facade - делегирует вызовы специализированным сервисам
3
+ * Этот класс - точка входа для обратной совместимости со старым кодом
4
+ */
5
+ class BotManager {
6
+ constructor({
7
+ botLifecycleService,
8
+ commandExecutionService,
9
+ botProcessManager,
10
+ resourceMonitorService,
11
+ telemetryService,
12
+ cacheManager,
13
+ eventGraphManager,
14
+ logger
15
+ }) {
16
+ this.lifecycleService = botLifecycleService;
17
+ this.commandService = commandExecutionService;
18
+ this.processManager = botProcessManager;
19
+ this.resourceMonitor = resourceMonitorService;
20
+ this.telemetry = telemetryService;
21
+ this.cache = cacheManager;
22
+ this.eventGraphManager = eventGraphManager;
23
+ this.logger = logger;
24
+
25
+ // Геттеры для обратной совместимости
26
+ this.bots = this.processManager.getAllProcesses();
27
+ this.nodeRegistry = require('./NodeRegistry');
28
+
29
+ // Массив для хранения ссылок на интервалы
30
+ this.intervals = [];
31
+
32
+ this._startBackgroundTasks();
40
33
  }
41
- return instanceId;
42
- }
43
34
 
44
- class BotManager {
45
- constructor() {
46
- this.bots = new Map();
47
- this.logCache = new Map();
48
- this.resourceUsage = new Map();
49
- this.botConfigs = new Map();
50
- this.nodeRegistry = nodeRegistry;
51
- this.pendingPlayerListRequests = new Map();
52
- this.playerListCache = new Map();
53
- this.eventGraphManager = null;
54
- this.uiSubscriptions = new Map();
55
- this.crashCounters = new Map();
56
-
57
- getInstanceId();
58
- setInterval(() => this.updateAllResourceUsage(), 5000);
59
- setInterval(() => this.syncBotStatuses(), 10000);
60
- if (config.telemetry?.enabled) {
61
- setInterval(() => this.sendHeartbeat(), 5 * 60 * 1000);
62
- }
35
+ _startBackgroundTasks() {
36
+ this.resourceMonitor.startMonitoring(5000);
37
+ this.telemetry.startHeartbeat(5 * 60 * 1000);
38
+
39
+ this.intervals.push(setInterval(() => this.updateAllResourceUsage(), 5000));
40
+ this.intervals.push(setInterval(() => this.syncBotStatuses(), 10000));
41
+ }
42
+
43
+ /**
44
+ * Очистка интервалов при завершении работы
45
+ */
46
+ cleanup() {
47
+ this.intervals.forEach(interval => clearInterval(interval));
48
+ this.intervals = [];
63
49
  }
64
50
 
65
51
  initialize() {
66
- if (!this.eventGraphManager) {
67
- this.eventGraphManager = new EventGraphManager(this);
52
+ if (!this.lifecycleService.eventGraphManager) {
53
+ this.lifecycleService.eventGraphManager = this.eventGraphManager;
68
54
  }
69
55
  }
70
56
 
71
- subscribeToPluginUi(botId, pluginName, socket) {
72
- if (!this.uiSubscriptions.has(botId)) {
73
- this.uiSubscriptions.set(botId, new Map());
74
- }
75
- const botSubscriptions = this.uiSubscriptions.get(botId);
76
-
77
- if (!botSubscriptions.has(pluginName)) {
78
- botSubscriptions.set(pluginName, new Set());
79
- }
80
- const pluginSubscribers = botSubscriptions.get(pluginName);
81
-
82
- pluginSubscribers.add(socket);
83
- console.log(`[UI Sub] Сокет ${socket.id} подписался на ${pluginName} для бота ${botId}. Всего подписчиков: ${pluginSubscribers.size}`);
84
-
85
- const botProcess = this.bots.get(botId);
86
- if (botProcess && !botProcess.killed) {
87
- botProcess.send({ type: 'plugin:ui:start-updates', pluginName });
88
- }
57
+ // === Lifecycle methods ===
58
+ async startBot(botConfig) {
59
+ return this.lifecycleService.startBot(botConfig);
89
60
  }
90
61
 
91
- unsubscribeFromPluginUi(botId, pluginName, socket) {
92
- const botSubscriptions = this.uiSubscriptions.get(botId);
93
- if (!botSubscriptions) return;
94
-
95
- const pluginSubscribers = botSubscriptions.get(pluginName);
96
- if (!pluginSubscribers) return;
97
-
98
- pluginSubscribers.delete(socket);
99
- console.log(`[UI Sub] Сокет ${socket.id} отписался от ${pluginName} для бота ${botId}. Осталось: ${pluginSubscribers.size}`);
62
+ stopBot(botId) {
63
+ return this.lifecycleService.stopBot(botId);
64
+ }
100
65
 
101
- if (pluginSubscribers.size === 0) {
102
- const botProcess = this.bots.get(botId);
103
- if (botProcess && !botProcess.killed) {
104
- botProcess.send({ type: 'plugin:ui:stop-updates', pluginName });
105
- }
106
- botSubscriptions.delete(pluginName);
107
- }
66
+ async restartBot(botId) {
67
+ return this.lifecycleService.restartBot(botId);
108
68
  }
109
69
 
110
- handleSocketDisconnect(socket) {
111
- this.uiSubscriptions.forEach((botSubscriptions, botId) => {
112
- botSubscriptions.forEach((pluginSubscribers, pluginName) => {
113
- if (pluginSubscribers.has(socket)) {
114
- this.unsubscribeFromPluginUi(botId, pluginName, socket);
115
- }
116
- });
117
- });
70
+ isBotRunning(botId) {
71
+ return this.lifecycleService.isBotRunning(botId);
118
72
  }
119
73
 
74
+ // === Configuration ===
120
75
  async loadConfigForBot(botId) {
121
- console.log(`[BotManager] Caching configuration for bot ID ${botId}...`);
122
- try {
123
- const [commands, permissions] = await Promise.all([
124
- prisma.command.findMany({ where: { botId } }),
125
- prisma.permission.findMany({ where: { botId } }),
126
- ]);
127
- const config = {
128
- commands: new Map(commands.map(cmd => [cmd.name, cmd])),
129
- permissionsById: new Map(permissions.map(p => [p.id, p])),
130
- commandAliases: new Map()
131
- };
132
- for (const cmd of commands) {
133
- const aliases = JSON.parse(cmd.aliases || '[]');
134
- for (const alias of aliases) {
135
- config.commandAliases.set(alias, cmd.name);
136
- }
137
- }
138
- this.botConfigs.set(botId, config);
139
- console.log(`[BotManager] Configuration for bot ID ${botId} cached successfully.`);
140
- return config;
141
- } catch (error) {
142
- console.error(`[BotManager] Failed to cache configuration for bot ${botId}:`, error);
143
- throw new Error(`Failed to load/cache bot configuration for botId ${botId}: ${error.message}`);
144
- }
145
- }
146
-
147
- async _ensureDefaultEventGraphs(botId) {
148
- return;
76
+ return this.lifecycleService.loadConfigForBot(botId);
149
77
  }
150
78
 
151
79
  invalidateConfigCache(botId) {
152
- if (this.botConfigs.has(botId)) {
153
- this.botConfigs.delete(botId);
154
- console.log(`[BotManager] Invalidated config cache for bot ID ${botId}. It will be reloaded on next command.`);
155
- }
80
+ this.lifecycleService.invalidateConfigCache(botId);
156
81
  }
157
82
 
158
83
  reloadBotConfigInRealTime(botId) {
159
- const { getIO } = require('../real-time/socketHandler');
160
- this.invalidateConfigCache(botId);
161
- const child = this.bots.get(botId);
162
- if (child && !child.killed) {
163
- child.send({ type: 'config:reload' });
164
- console.log(`[BotManager] Sent config:reload to bot process ${botId}`);
165
- getIO().emit('bot:config_reloaded', { botId });
166
- }
84
+ this.lifecycleService.reloadBotConfigInRealTime(botId);
167
85
  }
168
86
 
169
- triggerHeartbeat() {
170
- if (!config.telemetry?.enabled) return;
171
- if (this.heartbeatDebounceTimer) {
172
- clearTimeout(this.heartbeatDebounceTimer);
173
- }
174
- this.heartbeatDebounceTimer = setTimeout(() => {
175
- this.sendHeartbeat();
176
- }, 3000);
87
+ // === Command execution ===
88
+ async handleCommandValidation(botConfig, message) {
89
+ return this.commandService.handleCommandValidation(botConfig, message);
177
90
  }
178
91
 
179
- async sendHeartbeat() {
180
- if (!config.telemetry?.enabled || !instanceId) return;
181
- try {
182
- const runningBots = Array.from(this.bots.values())
183
- .filter(p => p.botConfig)
184
- .map(p => ({
185
- username: p.botConfig.username,
186
- serverHost: p.botConfig.server.host,
187
- serverPort: p.botConfig.server.port
188
- }));
189
-
190
- if (runningBots.length === 0) return;
191
-
192
- const challengeRes = await fetch(`${STATS_SERVER_URL}/api/challenge?uuid=${instanceId}`);
193
- if (!challengeRes.ok) throw new Error(`Challenge server error: ${challengeRes.statusText}`);
194
-
195
- const { challenge, difficulty, prefix } = await challengeRes.json();
196
- let nonce = 0;
197
- let hash = '';
198
- do {
199
- nonce++;
200
- hash = crypto.createHash('sha256').update(prefix + challenge + nonce).digest('hex');
201
- } while (!hash.startsWith('0'.repeat(difficulty)));
202
-
203
- const packageJson = require('../../../package.json');
204
- await fetch(`${STATS_SERVER_URL}/api/heartbeat`, {
205
- method: 'POST',
206
- headers: { 'Content-Type': 'application/json' },
207
- body: JSON.stringify({
208
- instanceUuid: instanceId,
209
- appVersion: packageJson.version,
210
- bots: runningBots,
211
- nonce: nonce
212
- })
213
- });
214
- } catch (error) {
215
- console.error(`[Telemetry] Не удалось отправить heartbeat: ${error.message}`);
216
- }
92
+ async validateAndExecuteCommandForApi(botId, username, commandName, args) {
93
+ return this.commandService.validateAndExecuteCommandForApi(botId, username, commandName, args);
217
94
  }
218
95
 
219
- async _syncSystemPermissions(botId) {
220
- const systemPermissions = [
221
- { name: "admin.*", description: "Все права администратора" },
222
- { name: "admin.cooldown.bypass", description: "Обход кулдауна для админ-команд" },
223
- { name: "user.*", description: "Все права обычного пользователя" },
224
- { name: "user.say", description: "Доступ к простым командам" },
225
- { name: "user.cooldown.bypass", description: "Обход кулдауна для юзер-команд" },
226
- ];
227
- const systemGroups = ["User", "Admin"];
228
- const systemGroupPermissions = {
229
- "User": ["user.say"],
230
- "Admin": ["admin.*", "admin.cooldown.bypass", "user.cooldown.bypass", "user.*"]
231
- };
232
- console.log(`[Permission Sync] Синхронизация системных прав для бота ID ${botId}...`);
233
- for (const perm of systemPermissions) {
234
- await prisma.permission.upsert({
235
- where: { botId_name: { botId, name: perm.name } },
236
- update: { description: perm.description },
237
- create: { ...perm, botId, owner: 'system' }
238
- });
239
- }
240
- for (const groupName of systemGroups) {
241
- await prisma.group.upsert({
242
- where: { botId_name: { botId, name: groupName } },
243
- update: {},
244
- create: { name: groupName, botId, owner: 'system' }
245
- });
246
- }
247
- for (const [groupName, permNames] of Object.entries(systemGroupPermissions)) {
248
- const group = await prisma.group.findUnique({ where: { botId_name: { botId, name: groupName } } });
249
- if (group) {
250
- for (const permName of permNames) {
251
- const permission = await prisma.permission.findUnique({ where: { botId_name: { botId, name: permName } } });
252
- if (permission) {
253
- await prisma.groupPermission.upsert({
254
- where: { groupId_permissionId: { groupId: group.id, permissionId: permission.id } },
255
- update: {},
256
- create: { groupId: group.id, permissionId: permission.id }
257
- });
258
- }
259
- }
260
- }
261
- }
262
- console.log(`[Permission Sync] Синхронизация для бота ID ${botId} завершена.`);
96
+ async handleCommandRegistration(botId, commandConfig) {
97
+ return this.commandService.handleCommandRegistration(botId, commandConfig);
263
98
  }
264
99
 
265
- async updateAllResourceUsage() {
266
- const { getIO } = require('../real-time/socketHandler');
267
- if (this.bots.size === 0) {
268
- if (this.resourceUsage.size > 0) {
269
- this.resourceUsage.clear();
270
- getIO().emit('bots:usage', []);
271
- }
272
- return;
273
- }
274
- const pids = Array.from(this.bots.values()).map(child => child.pid).filter(Boolean);
275
- if (pids.length === 0) return;
276
- try {
277
- const stats = await pidusage(pids);
278
- const usageData = [];
279
- for (const pid in stats) {
280
- if (!stats[pid]) continue;
281
- const botId = this.getBotIdByPid(parseInt(pid, 10));
282
- if (botId) {
283
- const usage = {
284
- botId: botId,
285
- cpu: parseFloat(stats[pid].cpu.toFixed(1)),
286
- memory: parseFloat((stats[pid].memory / 1024 / 1024).toFixed(1)),
287
- };
288
- this.resourceUsage.set(botId, usage);
289
- usageData.push(usage);
290
- }
291
- }
292
- getIO().emit('bots:usage', usageData);
293
- } catch (error) {}
100
+ async handleGroupRegistration(botId, groupConfig) {
101
+ return this.commandService.handleGroupRegistration(botId, groupConfig);
294
102
  }
295
103
 
296
- getBotIdByPid(pid) {
297
- for (const [botId, child] of this.bots.entries()) {
298
- if (child.pid === pid) {
299
- return botId;
300
- }
301
- }
302
- return null;
104
+ async handlePermissionsRegistration(botId, message) {
105
+ return this.commandService.handlePermissionsRegistration(botId, message.permissions);
303
106
  }
304
107
 
305
- getFullState() {
306
- const statuses = {};
307
- for (const [id, child] of this.bots.entries()) {
308
- statuses[id] = child.killed ? 'stopped' : 'running';
309
- }
108
+ async handleAddPermissionsToGroup(botId, message) {
109
+ return this.commandService.handleAddPermissionsToGroup(botId, message);
110
+ }
310
111
 
311
- const logs = {};
312
- for (const [botId, logArray] of this.logCache.entries()) {
313
- logs[botId] = logArray;
314
- }
112
+ // === Process management ===
113
+ subscribeToPluginUi(botId, pluginName, socket) {
114
+ this.processManager.subscribeToPluginUi(botId, pluginName, socket);
115
+ }
315
116
 
316
- return {
317
- statuses,
318
- logs,
319
- };
117
+ unsubscribeFromPluginUi(botId, pluginName, socket) {
118
+ this.processManager.unsubscribeFromPluginUi(botId, pluginName, socket);
320
119
  }
321
120
 
322
- emitStatusUpdate(botId, status, message = null) {
323
- const { getIO } = require('../real-time/socketHandler');
324
- if (message) this.appendLog(botId, `[SYSTEM] ${message}`);
325
- getIO().emit('bot:status', { botId, status, message });
121
+ handleSocketDisconnect(socket) {
122
+ this.processManager.handleSocketDisconnect(socket);
326
123
  }
327
124
 
328
- syncBotStatuses() {
329
- for (const [botId, child] of this.bots.entries()) {
330
- const actualStatus = child.killed ? 'stopped' : 'running';
331
- const { getIO } = require('../real-time/socketHandler');
332
- getIO().emit('bot:status', { botId, status: actualStatus });
333
- }
125
+ // === Bot actions ===
126
+ sendMessageToBot(botId, message, chatType = 'command', username = null) {
127
+ return this.lifecycleService.sendMessageToBot(botId, message, chatType, username);
334
128
  }
335
-
336
- appendLog(botId, logContent) {
337
- const { getIO } = require('../real-time/socketHandler');
338
- const logEntry = {
339
- id: Date.now() + Math.random(),
340
- content: logContent,
341
- };
342
- const currentLogs = this.logCache.get(botId) || [];
343
- const newLogs = [...currentLogs.slice(-199), logEntry];
344
- this.logCache.set(botId, newLogs);
345
- getIO().emit('bot:log', { botId, log: logEntry });
129
+
130
+ lookAt(botId, position) {
131
+ return this.lifecycleService.lookAt(botId, position);
346
132
  }
347
133
 
348
- getBotLogs(botId) {
349
- return this.logCache.get(botId) || [];
134
+ async reloadPlugins(botId) {
135
+ return this.lifecycleService.reloadPlugins(botId);
350
136
  }
351
137
 
352
- async startBot(botConfig) {
353
- if (this.bots.has(botConfig.id) && !this.bots.get(botConfig.id).killed) {
354
- this.appendLog(botConfig.id, `[SYSTEM-ERROR] Попытка повторного запуска. Запуск отменен.`);
355
- return { success: false, message: 'Бот уже запущен или запускается.' };
356
- }
138
+ sendServerCommandToBot(botId, command) {
139
+ this.lifecycleService.sendServerCommandToBot(botId, command);
140
+ }
357
141
 
358
- await this._syncSystemPermissions(botConfig.id);
359
- await this.loadConfigForBot(botConfig.id);
360
- this.logCache.set(botConfig.id, []);
361
- this.emitStatusUpdate(botConfig.id, 'starting', '');
142
+ async getPlayerList(botId) {
143
+ return this.lifecycleService.getPlayerList(botId);
144
+ }
362
145
 
363
- const allPluginsForBot = await prisma.installedPlugin.findMany({ where: { botId: botConfig.id, isEnabled: true } });
364
- const { sortedPlugins, hasCriticalIssues, pluginInfo } = DependencyService.resolveDependencies(allPluginsForBot, allPluginsForBot);
365
-
366
- if (hasCriticalIssues) {
367
- this.appendLog(botConfig.id, '[DependencyManager] Обнаружены критические проблемы с зависимостями, запуск отменен.');
368
-
369
- const criticalIssueTypes = new Set(['missing_dependency', 'version_mismatch', 'circular_dependency']);
370
-
371
- for (const pluginId in pluginInfo) {
372
- const info = pluginInfo[pluginId];
373
- if (info.issues.length === 0) continue;
374
-
375
- const criticalIssues = info.issues.filter(issue => criticalIssueTypes.has(issue.type));
376
-
377
- if (criticalIssues.length > 0) {
378
- this.appendLog(botConfig.id, `* Плагин "${info.name}":`);
379
- for (const issue of criticalIssues) {
380
- this.appendLog(botConfig.id, ` - ${issue.message}`);
381
- }
382
- }
383
- }
384
-
385
- this.emitStatusUpdate(botConfig.id, 'stopped', 'Ошибка зависимостей плагинов.');
386
- return { success: false, message: 'Критические ошибки в зависимостях плагинов.' };
387
- }
388
-
389
- const decryptedConfig = { ...botConfig };
390
- if (decryptedConfig.password) decryptedConfig.password = decrypt(decryptedConfig.password);
391
- if (decryptedConfig.proxyPassword) decryptedConfig.proxyPassword = decrypt(decryptedConfig.proxyPassword);
392
-
393
- if (decryptedConfig.proxyUsername) decryptedConfig.proxyUsername = decryptedConfig.proxyUsername.trim();
394
-
395
- const fullBotConfig = { ...decryptedConfig, plugins: sortedPlugins };
396
- const botProcessPath = path.resolve(__dirname, 'BotProcess.js');
397
- const child = fork(botProcessPath, [], {
398
- stdio: ['pipe', 'pipe', 'pipe', 'ipc'],
399
- env: {
400
- ...process.env,
401
- NODE_PATH: path.resolve(__dirname, '../../../node_modules')
402
- }
403
- });
404
-
405
- child.botConfig = botConfig;
406
-
407
- child.api = {
408
- sendMessage: (type, message, username) => {
409
- if (!child.killed) {
410
- child.send({ type: 'chat', payload: { message, chatType: type, username } });
411
- }
412
- },
413
- sendLog: (message) => {
414
- this.appendLog(botConfig.id, message);
415
- }
416
- };
417
-
418
- child.on('message', async (message) => {
419
- const botId = botConfig.id;
420
- try {
421
- switch (message.type) {
422
- case 'event':
423
- if (this.eventGraphManager) {
424
- this.eventGraphManager.handleEvent(botId, message.eventType, message.args);
425
- }
426
- break;
427
- case 'plugin:data': {
428
- const { plugin: pluginName, payload } = message;
429
- const botSubscriptions = this.uiSubscriptions.get(botId);
430
- if (!botSubscriptions) break;
431
-
432
- const pluginSubscribers = botSubscriptions.get(pluginName);
433
- if (pluginSubscribers && pluginSubscribers.size > 0) {
434
- pluginSubscribers.forEach(socket => {
435
- socket.emit('plugin:ui:dataUpdate', payload);
436
- });
437
- }
438
- break;
439
- }
440
- case 'plugin:stopped':
441
- break;
442
- case 'log':
443
- this.appendLog(botId, message.content);
444
- break;
445
- case 'status':
446
- this.emitStatusUpdate(botId, message.status);
447
- break;
448
- case 'bot_ready':
449
- this.emitStatusUpdate(botId, 'running', 'Бот успешно подключился к серверу.');
450
- this.crashCounters.delete(botId);
451
- break;
452
- case 'validate_and_run_command':
453
- await this.handleCommandValidation(botConfig, message);
454
- break;
455
- case 'register_command':
456
- await this.handleCommandRegistration(botId, message.commandConfig);
457
- break;
458
- case 'register_group':
459
- await this.handleGroupRegistration(botId, message.groupConfig);
460
- break;
461
- case 'register_permissions':
462
- await this.handlePermissionsRegistration(botId, message);
463
- break;
464
- case 'add_permissions_to_group':
465
- await this.handleAddPermissionsToGroup(botId, message);
466
- break;
467
- case 'request_user_action':
468
- const { requestId, payload } = message;
469
- const { targetUsername, action, data } = payload;
470
-
471
- try {
472
- const user = await UserService.getUser(targetUsername, botConfig.id);
473
- if (!user) throw new Error(`Пользователь ${targetUsername} не найден.`);
474
-
475
- let result;
476
-
477
- switch (action) {
478
- case 'addGroup':
479
- result = await user.addGroup(data.group);
480
- break;
481
- case 'removeGroup':
482
- result = await user.removeGroup(data.group);
483
- break;
484
- case 'addPermission':
485
- break;
486
- case 'removePermission':
487
- break;
488
- case 'getGroups':
489
- result = user.groups ? user.groups.map(g => g.group.name) : [];
490
- break;
491
- case 'getPermissions':
492
- result = Array.from(user.permissionsSet);
493
- break;
494
- case 'isBlacklisted':
495
- result = user.isBlacklisted;
496
- break;
497
- case 'setBlacklisted':
498
- result = await user.setBlacklist(data.value);
499
- break;
500
- default:
501
- throw new Error(`Неизвестное действие: ${action}`);
502
- }
503
-
504
- child.send({ type: 'user_action_response', requestId, payload: result });
505
- } catch (error) {
506
- console.error(`[BotManager] Ошибка выполнения действия '${action}' для пользователя '${targetUsername}':`, error);
507
- child.send({ type: 'user_action_response', requestId, error: error.message });
508
- }
509
- break;
510
- case 'playerListUpdate':
511
- break;
512
- case 'get_player_list_response': {
513
- const { requestId, payload } = message;
514
- const request = this.pendingPlayerListRequests.get(requestId);
515
- if (request) {
516
- clearTimeout(request.timeout);
517
- request.resolve(payload.players);
518
- this.pendingPlayerListRequests.delete(requestId);
519
- }
520
- break;
521
- }
522
- }
523
- } catch (error) {
524
- this.appendLog(botId, `[SYSTEM-ERROR] Критическая ошибка в обработчике сообщений от бота: ${error.stack}`);
525
- console.error(`[BotManager] Критическая ошибка в обработчике сообщений от бота ${botId}:`, error);
526
- }
527
- });
528
-
529
- child.on('error', (err) => this.appendLog(botConfig.id, `[PROCESS FATAL] ${err.stack}`));
530
- child.stdout.on('data', (data) => console.log(data.toString()));
531
- child.stderr.on('data', (data) => this.appendLog(botConfig.id, `[STDERR] ${data.toString()}`));
532
-
533
- child.on('exit', (code, signal) => {
534
- const botId = botConfig.id;
535
- this.bots.delete(botId);
536
- this.resourceUsage.delete(botId);
537
- this.botConfigs.delete(botId);
538
-
539
- this.emitStatusUpdate(botId, 'stopped', `Процесс завершился с кодом ${code} (сигнал: ${signal || 'none'}).`);
540
- this.updateAllResourceUsage();
541
-
542
- if (code === 1) {
543
- const MAX_RESTART_ATTEMPTS = 5;
544
- const RESTART_COOLDOWN = 60000;
545
-
546
- const counter = this.crashCounters.get(botId) || { count: 0, firstCrash: Date.now() };
547
- const timeSinceFirstCrash = Date.now() - counter.firstCrash;
548
-
549
- if (timeSinceFirstCrash > RESTART_COOLDOWN) {
550
- counter.count = 0;
551
- counter.firstCrash = Date.now();
552
- }
553
-
554
- counter.count++;
555
- this.crashCounters.set(botId, counter);
556
-
557
- if (counter.count >= MAX_RESTART_ATTEMPTS) {
558
- console.log(`[BotManager] Бот ${botId} упал ${counter.count} раз подряд. Автоперезапуск остановлен.`);
559
- this.appendLog(botId, `[SYSTEM] ❌ Обнаружено ${counter.count} критических ошибок подряд.`);
560
- this.appendLog(botId, `[SYSTEM] 💡 Исправьте проблему и запустите бота вручную.`);
561
- this.crashCounters.delete(botId);
562
- return;
563
- }
564
-
565
- console.log(`[BotManager] Обнаружена ошибка с кодом 1 для бота ${botId}. Попытка ${counter.count}/${MAX_RESTART_ATTEMPTS}. Перезапуск через 5 секунд...`);
566
- this.appendLog(botId, `[SYSTEM] Обнаружена критическая ошибка, перезапуск через 5 секунд... (попытка ${counter.count}/${MAX_RESTART_ATTEMPTS})`);
567
- setTimeout(() => {
568
- console.log(`[BotManager] Перезапуск бота ${botId}...`);
569
- this.startBot(botConfig);
570
- }, 5000);
571
- }
572
- });
573
-
574
- this.bots.set(botConfig.id, child);
575
- child.send({ type: 'start', config: fullBotConfig });
576
-
577
- await this.eventGraphManager.loadGraphsForBot(botConfig.id);
578
-
579
- this.triggerHeartbeat();
580
- const { getIO } = require('../real-time/socketHandler');
581
- getIO().emit('bot:status', { botId: botConfig.id, status: 'starting' });
582
- return child;
146
+ async getNearbyEntities(botId, position = null, radius = 32) {
147
+ return this.lifecycleService.getNearbyEntities(botId, position, radius);
583
148
  }
584
149
 
585
- async handleCommandValidation(botConfig, message) {
586
- const { commandName, username, args, typeChat } = message;
587
- const botId = botConfig.id;
588
-
589
- try {
590
- let botConfigCache = this.botConfigs.get(botId);
591
- if (!botConfigCache) {
592
- console.log(`[BotManager] No cache for ${botId}, loading...`);
593
- botConfigCache = await this.loadConfigForBot(botId);
594
- }
595
-
596
- const user = await UserService.getUser(username, botId, botConfig);
597
-
598
- const child = this.bots.get(botId);
599
- if (!child) return;
600
-
601
- if (user.isBlacklisted) {
602
- child.send({
603
- type: 'handle_blacklist',
604
- commandName: commandName,
605
- username,
606
- typeChat
607
- });
608
- return;
609
- }
610
-
611
- const mainCommandName = botConfigCache.commandAliases.get(commandName) || commandName;
612
- const dbCommand = botConfigCache.commands.get(mainCommandName);
613
-
614
- if (!dbCommand || (!dbCommand.isEnabled && !user.isOwner)) {
615
- return;
616
- }
617
-
618
- const allowedTypes = JSON.parse(dbCommand.allowedChatTypes || '[]');
619
- if (!allowedTypes.includes(typeChat) && !user.isOwner) {
620
- if (typeChat === 'global') return;
621
- child.send({
622
- type: 'handle_wrong_chat',
623
- commandName: dbCommand.name,
624
- username,
625
- typeChat
626
- });
627
- return;
628
- }
629
-
630
- const permission = dbCommand.permissionId ? botConfigCache.permissionsById.get(dbCommand.permissionId) : null;
631
- if (permission && !user.hasPermission(permission.name)) {
632
- child.send({
633
- type: 'handle_permission_error',
634
- commandName: dbCommand.name,
635
- username,
636
- typeChat
637
- });
638
- return;
639
- }
640
-
641
- const domain = (permission?.name || '').split('.')[0] || 'user';
642
- const bypassCooldownPermission = `${domain}.cooldown.bypass`;
643
-
644
- if (dbCommand.cooldown > 0 && !user.isOwner && !user.hasPermission(bypassCooldownPermission)) {
645
- const cooldownKey = `${botId}:${dbCommand.name}:${user.id}`;
646
- const now = Date.now();
647
- const lastUsed = cooldowns.get(cooldownKey);
648
-
649
- if (lastUsed && (now - lastUsed < dbCommand.cooldown * 1000)) {
650
- const timeLeft = Math.ceil((dbCommand.cooldown * 1000 - (now - lastUsed)) / 1000);
651
- child.send({
652
- type: 'handle_cooldown',
653
- commandName: dbCommand.name,
654
- username,
655
- typeChat,
656
- timeLeft
657
- });
658
- return;
659
- }
660
- cooldowns.set(cooldownKey, now);
661
- }
662
-
663
- if (this.eventGraphManager) {
664
- this.eventGraphManager.handleEvent(botId, 'command', {
665
- commandName: dbCommand.name,
666
- user: { username },
667
- args,
668
- typeChat
669
- });
670
- }
671
-
672
- child.send({ type: 'execute_handler', commandName: dbCommand.name, username, args, typeChat });
673
-
674
- } catch (error) {
675
- console.error(`[BotManager] Command validation error for botId: ${botId}`, {
676
- command: commandName, user: username, error: error.message, stack: error.stack
677
- });
678
- this.sendMessageToBot(botId, `Произошла внутренняя ошибка при выполнении команды.`, 'private', username);
679
- }
150
+ // === User cache ===
151
+ invalidateUserCache(botId, username) {
152
+ return this.lifecycleService.invalidateUserCache(botId, username);
680
153
  }
681
154
 
682
- async handleCommandRegistration(botId, commandConfig) {
683
- try {
684
- let permissionId = null;
685
- if (commandConfig.permissions) {
686
- let permission = await prisma.permission.findUnique({
687
- where: { botId_name: { botId, name: commandConfig.permissions } }
688
- });
689
- if (!permission) {
690
- permission = await prisma.permission.create({
691
- data: {
692
- botId,
693
- name: commandConfig.permissions,
694
- description: `Автоматически создано для команды ${commandConfig.name}`,
695
- owner: commandConfig.owner,
696
- }
697
- });
698
- }
699
- permissionId = permission.id;
700
- }
701
- const createData = {
702
- botId,
703
- name: commandConfig.name,
704
- description: commandConfig.description,
705
- aliases: JSON.stringify(commandConfig.aliases || []),
706
- owner: commandConfig.owner,
707
- permissionId: permissionId,
708
- allowedChatTypes: JSON.stringify(commandConfig.allowedChatTypes || []),
709
- cooldown: commandConfig.cooldown || 0,
710
- };
711
- const updateData = {
712
- description: commandConfig.description,
713
- owner: commandConfig.owner,
714
- };
715
- await prisma.command.upsert({
716
- where: { botId_name: { botId, name: commandConfig.name } },
717
- update: updateData,
718
- create: createData,
719
- });
720
- this.invalidateConfigCache(botId);
721
- } catch (error) {
722
- console.error(`[BotManager] Ошибка при регистрации команды '${commandConfig.name}':`, error);
723
- }
155
+ invalidateAllUserCache(botId) {
156
+ return this.lifecycleService.invalidateAllUserCache(botId);
724
157
  }
725
158
 
726
- async handleGroupRegistration(botId, groupConfig) {
727
- try {
728
- await prisma.group.upsert({
729
- where: { botId_name: { botId, name: groupConfig.name } },
730
- update: {
731
- owner: groupConfig.owner,
732
- },
733
- create: {
734
- botId,
735
- name: groupConfig.name,
736
- owner: groupConfig.owner,
737
- },
738
- });
739
- this.invalidateConfigCache(botId);
740
- } catch (error) {
741
- console.error(`[BotManager] Ошибка при регистрации группы '${groupConfig.name}':`, error);
742
- }
159
+ // === Resource monitoring ===
160
+ async updateAllResourceUsage() {
161
+ const usageData = await this.resourceMonitor.updateAllResourceUsage();
162
+ const { getIO } = require('../real-time/socketHandler');
163
+ getIO().emit('bots:usage', usageData);
743
164
  }
744
165
 
745
- async handlePermissionsRegistration(botId, message) {
746
- try {
747
- const { permissions } = message;
748
- for (const perm of permissions) {
749
- if (!perm.name || !perm.owner) {
750
- console.warn(`[BotManager] Пропущено право без имени или владельца для бота ${botId}:`, perm);
751
- continue;
752
- }
753
- await prisma.permission.upsert({
754
- where: { botId_name: { botId, name: perm.name } },
755
- update: { description: perm.description },
756
- create: {
757
- botId,
758
- name: perm.name,
759
- description: perm.description || '',
760
- owner: perm.owner,
761
- },
762
- });
763
- }
764
- this.invalidateConfigCache(botId);
765
- } catch (error) {
766
- console.error(`[BotManager] Ошибка при регистрации прав для бота ${botId}:`, error);
767
- }
166
+ getBotIdByPid(pid) {
167
+ return this.resourceMonitor.getBotIdByPid(pid);
768
168
  }
769
169
 
770
- async handleAddPermissionsToGroup(botId, message) {
771
- try {
772
- const { groupName, permissionNames } = message;
773
-
774
- const group = await prisma.group.findUnique({
775
- where: { botId_name: { botId, name: groupName } }
776
- });
777
-
778
- if (!group) {
779
- console.warn(`[BotManager] Попытка добавить права в несуществующую группу "${groupName}" для бота ID ${botId}.`);
780
- return;
781
- }
782
-
783
- for (const permName of permissionNames) {
784
- const permission = await prisma.permission.findUnique({
785
- where: { botId_name: { botId, name: permName } }
786
- });
787
-
788
- if (permission) {
789
- await prisma.groupPermission.upsert({
790
- where: { groupId_permissionId: { groupId: group.id, permissionId: permission.id } },
791
- update: {},
792
- create: { groupId: group.id, permissionId: permission.id },
793
- });
794
- } else {
795
- console.warn(`[BotManager] Право "${permName}" не найдено для бота ID ${botId} при добавлении в группу "${groupName}".`);
796
- }
797
- }
798
-
799
- this.invalidateConfigCache(botId);
800
- } catch (error) {
801
- console.error(`[BotManager] Ошибка при добавлении прав в группу "${message.groupName}" для бота ${botId}:`, error);
802
- }
170
+ // === Telemetry ===
171
+ triggerHeartbeat() {
172
+ this.telemetry.triggerHeartbeat();
803
173
  }
804
174
 
805
- stopBot(botId) {
806
- const child = this.bots.get(botId);
807
- if (child) {
808
- this.eventGraphManager.unloadGraphsForBot(botId);
809
-
810
- child.send({ type: 'stop' });
811
-
812
- setTimeout(() => {
813
- if (!child.killed) {
814
- console.log(`[BotManager] Принудительное завершение процесса бота ${botId}`);
815
- try {
816
- child.kill('SIGKILL');
817
- } catch (error) {
818
- console.error(`[BotManager] Ошибка при принудительном завершении бота ${botId}:`, error);
819
- }
820
- }
821
- }, 5000);
822
-
823
- this.botConfigs.delete(botId);
824
- return { success: true };
825
- }
826
- return { success: false, message: 'Бот не найден или уже остановлен' };
175
+ async sendHeartbeat() {
176
+ return this.telemetry.sendHeartbeat();
827
177
  }
828
-
829
- sendMessageToBot(botId, message, chatType = 'command', username = null) {
830
- const child = this.bots.get(botId);
831
- if (child) {
832
- child.api.sendMessage(chatType, message, username);
833
- return { success: true };
834
- }
835
- return { success: false, message: 'Бот не найден или не запущен' };
178
+
179
+ // === Logging & state ===
180
+ appendLog(botId, logContent) {
181
+ this.lifecycleService.appendLog(botId, logContent);
836
182
  }
837
183
 
838
- invalidateUserCache(botId, username) {
839
- UserService.clearCache(username, botId);
840
- const child = this.bots.get(botId);
841
- if (child) {
842
- child.send({ type: 'invalidate_user_cache', username });
843
- }
844
- return { success: true };
184
+ getBotLogs(botId) {
185
+ return this.lifecycleService.getBotLogs(botId);
845
186
  }
846
187
 
847
- invalidateAllUserCache(botId) {
848
- for (const [cacheKey, user] of UserService.cache.entries()) {
849
- if (cacheKey.startsWith(`${botId}:`)) {
850
- UserService.cache.delete(cacheKey);
851
- }
852
- }
853
- console.log(`[BotManager] Кэш пользователей очищен для бота ${botId}`);
854
-
855
- const child = this.bots.get(botId);
856
- if (child && !child.killed) {
857
- child.send({ type: 'invalidate_all_user_cache' });
858
- console.log(`[BotManager] Отправлено сообщение об очистке кэша в процесс бота ${botId}`);
859
- }
860
-
861
- return { success: true };
188
+ getFullState() {
189
+ return this.lifecycleService.getFullState();
862
190
  }
863
191
 
864
- async getPlayerList(botId) {
865
- const PLAYER_LIST_CACHE_TTL = 2000;
192
+ emitStatusUpdate(botId, status, message = null) {
193
+ this.lifecycleService.emitStatusUpdate(botId, status, message);
194
+ }
866
195
 
867
- const child = this.bots.get(botId);
868
- if (!child || child.killed) {
869
- return [];
870
- }
196
+ syncBotStatuses() {
197
+ const processes = this.processManager.getAllProcesses();
198
+ const { getIO } = require('../real-time/socketHandler');
871
199
 
872
- const cachedEntry = this.playerListCache.get(botId);
873
- if (cachedEntry && (Date.now() - cachedEntry.timestamp < PLAYER_LIST_CACHE_TTL)) {
874
- return cachedEntry.promise;
200
+ for (const [botId, child] of processes.entries()) {
201
+ const actualStatus = child.killed ? 'stopped' : 'running';
202
+ getIO().emit('bot:status', { botId, status: actualStatus });
875
203
  }
876
-
877
- const newPromise = new Promise((resolve) => {
878
- const requestId = uuidv4();
879
- const timeout = setTimeout(() => {
880
- this.pendingPlayerListRequests.delete(requestId);
881
- if (this.playerListCache.get(botId)?.promise === newPromise) {
882
- this.playerListCache.delete(botId);
883
- }
884
- resolve([]);
885
- }, 5000);
886
-
887
- this.pendingPlayerListRequests.set(requestId, {
888
- resolve: (playerList) => {
889
- clearTimeout(timeout);
890
- this.pendingPlayerListRequests.delete(requestId);
891
- this.playerListCache.set(botId, {
892
- promise: Promise.resolve(playerList),
893
- timestamp: Date.now()
894
- });
895
- resolve(playerList);
896
- },
897
- reject: (error) => {
898
- clearTimeout(timeout);
899
- this.pendingPlayerListRequests.delete(requestId);
900
- if (this.playerListCache.get(botId)?.promise === newPromise) {
901
- this.playerListCache.delete(botId);
902
- }
903
- resolve([]);
904
- },
905
- });
906
-
907
- child.send({ type: 'system:get_player_list', requestId });
908
- });
909
-
910
- this.playerListCache.set(botId, {
911
- promise: newPromise,
912
- timestamp: Date.now()
913
- });
914
-
915
- return newPromise;
916
204
  }
917
205
 
206
+ // === EventGraph ===
918
207
  setEventGraphManager(manager) {
919
208
  this.eventGraphManager = manager;
209
+ this.lifecycleService.eventGraphManager = manager;
920
210
  }
921
211
 
922
- lookAt(botId, position) {
923
- const botProcess = this.bots.get(botId);
924
- if (botProcess && !botProcess.killed) {
925
- botProcess.send({ type: 'action', name: 'lookAt', payload: { position } });
926
- } else {
927
- console.error(`[BotManager] Не удалось найти запущенный процесс для бота ${botId}, чтобы выполнить lookAt.`);
928
- }
929
- }
930
-
931
- async reloadPlugins(botId) {
932
- const child = this.bots.get(botId);
933
- if (child && !child.killed) {
934
- child.send({ type: 'plugins:reload' });
935
- console.log(`[BotManager] Sent plugins:reload to bot process ${botId}`);
936
- const { getIO } = require('../real-time/socketHandler');
937
- getIO().emit('bot:plugins_reloaded', { botId });
938
- return { success: true, message: 'Команда на перезагрузку плагинов отправлена.' };
939
- }
940
- return { success: false, message: 'Бот не запущен.' };
212
+ // === Legacy async methods для migration ===
213
+ async _syncSystemPermissions(botId) {
214
+ return this.lifecycleService._syncSystemPermissions(botId);
941
215
  }
942
216
 
943
- sendServerCommandToBot(botId, command) {
944
- const child = this.bots.get(botId);
945
- if (child) {
946
- child.send({ type: 'server_command', payload: { command } });
947
- }
217
+ async _ensureDefaultEventGraphs(botId) {
218
+ return;
948
219
  }
949
220
  }
950
221
 
951
- module.exports = new BotManager();
222
+ module.exports = BotManager;