blockmine 1.21.0 → 1.23.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 (492) 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 +59 -0
  55. package/.claude/settings.local.json +36 -14
  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 +102 -42
  255. package/CLAUDE.md +284 -0
  256. package/README.md +315 -71
  257. package/backend/docs/SECRETS_DOCUMENTATION.md +327 -0
  258. package/backend/jest.config.js +59 -0
  259. package/backend/package-lock.json +6801 -0
  260. package/backend/package.json +24 -4
  261. package/backend/prisma/migrations/20251026104609_add_websocket_api/migration.sql +33 -0
  262. package/backend/prisma/migrations/20251116111851_add_execution_trace/migration.sql +22 -0
  263. package/backend/prisma/migrations/20251120154914_add_panel_api_keys/migration.sql +21 -0
  264. package/backend/prisma/migrations/20251121110241_add_proxy_table/migration.sql +45 -0
  265. package/backend/prisma/migrations/migration_lock.toml +2 -2
  266. package/backend/prisma/schema.prisma +103 -1
  267. package/backend/src/__tests__/core/DependencyService.test.js +336 -0
  268. package/backend/src/__tests__/core/UserService.test.js +875 -0
  269. package/backend/src/__tests__/repositories/BaseRepository.test.js +146 -0
  270. package/backend/src/__tests__/repositories/BotRepository.test.js +118 -0
  271. package/backend/src/__tests__/repositories/CommandRepository.test.js +132 -0
  272. package/backend/src/__tests__/repositories/EventGraphRepository.test.js +93 -0
  273. package/backend/src/__tests__/repositories/GroupRepository.test.js +155 -0
  274. package/backend/src/__tests__/repositories/PermissionRepository.test.js +130 -0
  275. package/backend/src/__tests__/repositories/PluginRepository.test.js +107 -0
  276. package/backend/src/__tests__/repositories/ServerRepository.test.js +80 -0
  277. package/backend/src/__tests__/repositories/UserRepository.test.js +128 -0
  278. package/backend/src/__tests__/secretsFilter.test.js +425 -0
  279. package/backend/src/__tests__/services/BotLifecycleService.test.js +416 -0
  280. package/backend/src/__tests__/services/BotProcessManager.test.js +285 -0
  281. package/backend/src/__tests__/services/CacheManager.test.js +125 -0
  282. package/backend/src/__tests__/services/CommandExecutionService.test.js +460 -0
  283. package/backend/src/__tests__/services/ResourceMonitorService.test.js +207 -0
  284. package/backend/src/__tests__/services/TelemetryService.test.js +291 -0
  285. package/backend/src/__tests__/setup.js +25 -0
  286. package/backend/src/ai/plugin-assistant-system-prompt.md +788 -0
  287. package/backend/src/api/middleware/auth.js +27 -0
  288. package/backend/src/api/middleware/botAccess.js +7 -3
  289. package/backend/src/api/middleware/panelApiAuth.js +135 -0
  290. package/backend/src/api/routes/aiAssistant.js +995 -0
  291. package/backend/src/api/routes/apiKeys.js +181 -0
  292. package/backend/src/api/routes/auth.js +669 -633
  293. package/backend/src/api/routes/botCommands.js +107 -0
  294. package/backend/src/api/routes/botGroups.js +165 -0
  295. package/backend/src/api/routes/botHistory.js +108 -0
  296. package/backend/src/api/routes/botPermissions.js +99 -0
  297. package/backend/src/api/routes/botStatus.js +36 -0
  298. package/backend/src/api/routes/botUsers.js +162 -0
  299. package/backend/src/api/routes/bots.js +2451 -2360
  300. package/backend/src/api/routes/eventGraphs.js +4 -1
  301. package/backend/src/api/routes/logs.js +13 -3
  302. package/backend/src/api/routes/panel.js +66 -66
  303. package/backend/src/api/routes/panelApiKeys.js +179 -0
  304. package/backend/src/api/routes/pluginIde.js +1715 -135
  305. package/backend/src/api/routes/plugins.js +376 -218
  306. package/backend/src/api/routes/proxies.js +130 -0
  307. package/backend/src/api/routes/search.js +4 -0
  308. package/backend/src/api/routes/servers.js +20 -3
  309. package/backend/src/api/routes/settings.js +5 -0
  310. package/backend/src/api/routes/system.js +174 -0
  311. package/backend/src/api/routes/traces.js +131 -0
  312. package/backend/src/config/debug.config.js +36 -0
  313. package/backend/src/container.js +82 -0
  314. package/backend/src/core/BotHistoryStore.js +180 -0
  315. package/backend/src/core/BotManager.js +149 -868
  316. package/backend/src/core/BotManager.old.js +1093 -0
  317. package/backend/src/core/BotProcess.js +850 -191
  318. package/backend/src/core/EventGraphManager.js +194 -198
  319. package/backend/src/core/GraphExecutionEngine.js +709 -57
  320. package/backend/src/core/MessageQueue.js +39 -12
  321. package/backend/src/core/NodeRegistry.js +37 -1134
  322. package/backend/src/core/PluginLoader.js +99 -5
  323. package/backend/src/core/PluginManager.js +126 -15
  324. package/backend/src/core/PrismaService.js +32 -0
  325. package/backend/src/core/TaskScheduler.js +1 -1
  326. package/backend/src/core/UserService.js +3 -3
  327. package/backend/src/core/__tests__/PrismaService.test.js +24 -0
  328. package/backend/src/core/commands/README.md +305 -0
  329. package/backend/src/core/commands/dev.js +13 -7
  330. package/backend/src/core/commands/ping.js +10 -4
  331. package/backend/src/core/commands/whois.js +63 -0
  332. package/backend/src/core/config/validation.js +27 -0
  333. package/backend/src/core/constants/graphTypes.js +21 -0
  334. package/backend/src/core/node-registries/actions.js +202 -0
  335. package/backend/src/core/node-registries/arrays.js +155 -0
  336. package/backend/src/core/node-registries/bot.js +23 -0
  337. package/backend/src/core/node-registries/data.js +290 -0
  338. package/backend/src/core/node-registries/debug.js +26 -0
  339. package/backend/src/core/node-registries/events.js +201 -0
  340. package/backend/src/core/node-registries/flow.js +139 -0
  341. package/backend/src/core/node-registries/logic.js +62 -0
  342. package/backend/src/core/node-registries/math.js +42 -0
  343. package/backend/src/core/node-registries/objects.js +98 -0
  344. package/backend/src/core/node-registries/strings.js +187 -0
  345. package/backend/src/core/node-registries/time.js +113 -0
  346. package/backend/src/core/node-registries/type.js +25 -0
  347. package/backend/src/core/node-registries/users.js +79 -0
  348. package/backend/src/core/nodes/{action_bot_look_at.js → actions/bot_look_at.js} +36 -36
  349. package/backend/src/core/nodes/{action_bot_set_variable.js → actions/bot_set_variable.js} +32 -32
  350. package/backend/src/core/nodes/actions/create_command.js +189 -0
  351. package/backend/src/core/nodes/actions/delete_command.js +92 -0
  352. package/backend/src/core/nodes/{action_send_log.js → actions/send_log.js} +28 -23
  353. package/backend/src/core/nodes/{action_send_message.js → actions/send_message.js} +32 -32
  354. package/backend/src/core/nodes/actions/send_websocket_response.js +33 -0
  355. package/backend/src/core/nodes/actions/update_command.js +133 -0
  356. package/backend/src/core/nodes/arrays/get_next.js +35 -0
  357. package/backend/src/core/nodes/arrays/join.js +28 -0
  358. package/backend/src/core/nodes/{data_cast.js → data/cast.js} +10 -1
  359. package/backend/src/core/nodes/data/datetime_literal.js +27 -0
  360. package/backend/src/core/nodes/data/entity_info.js +69 -0
  361. package/backend/src/core/nodes/data/get_nearby_entities.js +32 -0
  362. package/backend/src/core/nodes/data/get_nearby_players.js +64 -0
  363. package/backend/src/core/nodes/{data_get_user_field.js → data/get_user_field.js} +1 -1
  364. package/backend/src/core/nodes/data/type_check.js +53 -0
  365. package/backend/src/core/nodes/{debug_log.js → debug/log.js} +16 -16
  366. package/backend/src/core/nodes/{flow_branch.js → flow/branch.js} +15 -15
  367. package/backend/src/core/nodes/{flow_break.js → flow/break.js} +14 -14
  368. package/backend/src/core/nodes/flow/delay.js +43 -0
  369. package/backend/src/core/nodes/{flow_for_each.js → flow/for_each.js} +39 -39
  370. package/backend/src/core/nodes/{flow_sequence.js → flow/sequence.js} +16 -16
  371. package/backend/src/core/nodes/{flow_switch.js → flow/switch.js} +47 -47
  372. package/backend/src/core/nodes/{flow_while.js → flow/while.js} +1 -1
  373. package/backend/src/core/nodes/logic/__tests__/compare.test.js +83 -0
  374. package/backend/src/core/nodes/logic/not.js +22 -0
  375. package/backend/src/core/nodes/math/__tests__/operation.test.js +65 -0
  376. package/backend/src/core/nodes/strings/__tests__/concat.test.js +89 -0
  377. package/backend/src/core/nodes/{string_starts_with.js → strings/starts_with.js} +1 -1
  378. package/backend/src/core/nodes/strings/to_lower.js +22 -0
  379. package/backend/src/core/nodes/strings/to_upper.js +22 -0
  380. package/backend/src/core/nodes/time/__tests__/now.test.js +24 -0
  381. package/backend/src/core/nodes/time/add.js +33 -0
  382. package/backend/src/core/nodes/time/compare.js +35 -0
  383. package/backend/src/core/nodes/time/diff.js +29 -0
  384. package/backend/src/core/nodes/time/format.js +32 -0
  385. package/backend/src/core/nodes/time/now.js +18 -0
  386. package/backend/src/core/nodes/type/to_string.js +32 -0
  387. package/backend/src/core/nodes/{user_check_blacklist.js → users/check_blacklist.js} +37 -37
  388. package/backend/src/core/nodes/{user_get_groups.js → users/get_groups.js} +36 -36
  389. package/backend/src/core/nodes/{user_get_permissions.js → users/get_permissions.js} +36 -36
  390. package/backend/src/core/nodes/{user_set_blacklist.js → users/set_blacklist.js} +37 -37
  391. package/backend/src/core/services/BotLifecycleService.js +835 -0
  392. package/backend/src/core/services/BotProcessManager.js +163 -0
  393. package/backend/src/core/services/CacheManager.js +111 -0
  394. package/backend/src/core/services/CommandExecutionService.js +430 -0
  395. package/backend/src/core/services/DebugSessionManager.js +347 -0
  396. package/backend/src/core/services/GraphCollaborationManager.js +501 -0
  397. package/backend/src/core/services/MinecraftBotManager.js +259 -0
  398. package/backend/src/core/services/MinecraftViewerService.js +216 -0
  399. package/backend/src/core/services/ResourceMonitorService.js +90 -0
  400. package/backend/src/core/services/TelemetryService.js +124 -0
  401. package/backend/src/core/services/TraceCollectorService.js +545 -0
  402. package/backend/src/core/services/ValidationService.js +132 -0
  403. package/backend/src/core/services/__tests__/ValidationService.test.js +148 -0
  404. package/backend/src/core/services.js +20 -5
  405. package/backend/src/core/system/CommandContext.js +84 -0
  406. package/backend/src/core/system/RuntimeCommandRegistry.js +116 -0
  407. package/backend/src/core/system/Transport.js +74 -0
  408. package/backend/src/core/utils/__tests__/jsonParser.test.js +44 -0
  409. package/backend/src/core/utils/jsonParser.js +18 -0
  410. package/backend/src/core/utils/secretsFilter.js +262 -0
  411. package/backend/src/core/utils/variableParser.js +89 -0
  412. package/backend/src/core/validation/__tests__/nodeSchemas.test.js +175 -0
  413. package/backend/src/core/validation/nodeSchemas.js +112 -0
  414. package/backend/src/lib/prisma.js +2 -4
  415. package/backend/src/real-time/botApi/handlers/commandHandlers.js +28 -0
  416. package/backend/src/real-time/botApi/handlers/graphHandlers.js +99 -0
  417. package/backend/src/real-time/botApi/handlers/graphWebSocketHandlers.js +147 -0
  418. package/backend/src/real-time/botApi/handlers/index.js +43 -0
  419. package/backend/src/real-time/botApi/handlers/messageHandlers.js +66 -0
  420. package/backend/src/real-time/botApi/handlers/statusHandlers.js +17 -0
  421. package/backend/src/real-time/botApi/handlers/userHandlers.js +141 -0
  422. package/backend/src/real-time/botApi/index.js +40 -0
  423. package/backend/src/real-time/botApi/middleware.js +79 -0
  424. package/backend/src/real-time/botApi/utils.js +65 -0
  425. package/backend/src/real-time/panelNamespace.js +387 -0
  426. package/backend/src/real-time/presence.js +7 -2
  427. package/backend/src/real-time/socketHandler.js +400 -5
  428. package/backend/src/repositories/BaseRepository.js +43 -0
  429. package/backend/src/repositories/BotRepository.js +42 -0
  430. package/backend/src/repositories/CommandRepository.js +53 -0
  431. package/backend/src/repositories/EventGraphRepository.js +40 -0
  432. package/backend/src/repositories/GroupRepository.js +69 -0
  433. package/backend/src/repositories/PermissionRepository.js +48 -0
  434. package/backend/src/repositories/PluginRepository.js +42 -0
  435. package/backend/src/repositories/ServerRepository.js +27 -0
  436. package/backend/src/repositories/UserRepository.js +48 -0
  437. package/backend/src/server.js +21 -0
  438. package/backend/src/test-refactor.js +85 -0
  439. package/frontend/dist/assets/index-B1serztM.js +11210 -0
  440. package/frontend/dist/assets/index-t6K1u4OV.css +32 -0
  441. package/frontend/dist/index.html +2 -2
  442. package/frontend/package-lock.json +9437 -0
  443. package/frontend/package.json +8 -5
  444. package/package.json +3 -2
  445. package/screen/console.png +0 -0
  446. package/screen/dashboard.png +0 -0
  447. package/screen/graph_collabe.png +0 -0
  448. package/screen/graph_live_debug.png +0 -0
  449. package/screen/management_command.png +0 -0
  450. package/screen/node_debug_trace.png +0 -0
  451. package/screen/plugin_/320/276/320/261/320/267/320/276/321/200.png +0 -0
  452. package/screen/websocket.png +0 -0
  453. 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
  454. 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
  455. package/frontend/dist/assets/index-B9GedHEa.js +0 -8352
  456. package/frontend/dist/assets/index-zLiy9MDx.css +0 -1
  457. package/nul +0 -0
  458. /package/backend/src/core/nodes/{action_http_request.js → actions/http_request.js} +0 -0
  459. /package/backend/src/core/nodes/{array_add_element.js → arrays/add_element.js} +0 -0
  460. /package/backend/src/core/nodes/{array_contains.js → arrays/contains.js} +0 -0
  461. /package/backend/src/core/nodes/{array_find_index.js → arrays/find_index.js} +0 -0
  462. /package/backend/src/core/nodes/{array_get_by_index.js → arrays/get_by_index.js} +0 -0
  463. /package/backend/src/core/nodes/{array_get_random_element.js → arrays/get_random_element.js} +0 -0
  464. /package/backend/src/core/nodes/{array_remove_by_index.js → arrays/remove_by_index.js} +0 -0
  465. /package/backend/src/core/nodes/{bot_get_position.js → bot/get_position.js} +0 -0
  466. /package/backend/src/core/nodes/{data_array_literal.js → data/array_literal.js} +0 -0
  467. /package/backend/src/core/nodes/{data_boolean_literal.js → data/boolean_literal.js} +0 -0
  468. /package/backend/src/core/nodes/{data_get_argument.js → data/get_argument.js} +0 -0
  469. /package/backend/src/core/nodes/{data_get_bot_look.js → data/get_bot_look.js} +0 -0
  470. /package/backend/src/core/nodes/{data_get_entity_field.js → data/get_entity_field.js} +0 -0
  471. /package/backend/src/core/nodes/{data_get_server_players.js → data/get_server_players.js} +0 -0
  472. /package/backend/src/core/nodes/{data_get_variable.js → data/get_variable.js} +0 -0
  473. /package/backend/src/core/nodes/{data_length.js → data/length.js} +0 -0
  474. /package/backend/src/core/nodes/{data_make_object.js → data/make_object.js} +0 -0
  475. /package/backend/src/core/nodes/{data_number_literal.js → data/number_literal.js} +0 -0
  476. /package/backend/src/core/nodes/{data_string_literal.js → data/string_literal.js} +0 -0
  477. /package/backend/src/core/nodes/{logic_compare.js → logic/compare.js} +0 -0
  478. /package/backend/src/core/nodes/{logic_operation.js → logic/operation.js} +0 -0
  479. /package/backend/src/core/nodes/{math_operation.js → math/operation.js} +0 -0
  480. /package/backend/src/core/nodes/{math_random_number.js → math/random_number.js} +0 -0
  481. /package/backend/src/core/nodes/{object_create.js → objects/create.js} +0 -0
  482. /package/backend/src/core/nodes/{object_delete.js → objects/delete.js} +0 -0
  483. /package/backend/src/core/nodes/{object_get.js → objects/get.js} +0 -0
  484. /package/backend/src/core/nodes/{object_has_key.js → objects/has_key.js} +0 -0
  485. /package/backend/src/core/nodes/{object_set.js → objects/set.js} +0 -0
  486. /package/backend/src/core/nodes/{string_concat.js → strings/concat.js} +0 -0
  487. /package/backend/src/core/nodes/{string_contains.js → strings/contains.js} +0 -0
  488. /package/backend/src/core/nodes/{string_ends_with.js → strings/ends_with.js} +0 -0
  489. /package/backend/src/core/nodes/{string_equals.js → strings/equals.js} +0 -0
  490. /package/backend/src/core/nodes/{string_length.js → strings/length.js} +0 -0
  491. /package/backend/src/core/nodes/{string_matches.js → strings/matches.js} +0 -0
  492. /package/backend/src/core/nodes/{string_split.js → strings/split.js} +0 -0
@@ -5,6 +5,7 @@ const { v4: uuidv4 } = require('uuid');
5
5
  const { Vec3 } = require('vec3');
6
6
  const { PrismaClient } = require('@prisma/client');
7
7
  const { loadCommands } = require('./system/CommandRegistry');
8
+ const { getRuntimeCommandRegistry } = require('./system/RuntimeCommandRegistry');
8
9
  const { initializePlugins } = require('./PluginLoader');
9
10
  const MessageQueue = require('./MessageQueue');
10
11
  const Command = require('./system/Command');
@@ -14,6 +15,8 @@ const NodeRegistry = require('./NodeRegistry');
14
15
 
15
16
  const UserService = require('./UserService');
16
17
  const PermissionManager = require('./ipc/PermissionManager.stub.js');
18
+ const Transport = require('./system/Transport');
19
+ const CommandContext = require('./system/CommandContext');
17
20
 
18
21
  let bot = null;
19
22
  const prisma = new PrismaClient();
@@ -21,16 +24,18 @@ const pluginUiState = new Map();
21
24
  const pendingRequests = new Map();
22
25
  const entityMoveThrottles = new Map();
23
26
  let connectionTimeout = null;
27
+ let botReadySent = false;
28
+ let viewerRenderDistance = 24; // Динамический радиус отображения для viewer
24
29
 
25
30
  const originalJSONParse = JSON.parse
26
- JSON.parse = function(text, reviver) {
27
- if (typeof text !== 'string') return originalJSONParse(text, reviver)
28
- try {
29
- return originalJSONParse(text, reviver)
30
- } catch (e) {
31
- const fixed = text.replace(/([{,])\s*([a-zA-Z0-9_]+)\s*:/g, '$1"$2":')
32
- return originalJSONParse(fixed, reviver)
33
- }
31
+ JSON.parse = function (text, reviver) {
32
+ if (typeof text !== 'string') return originalJSONParse(text, reviver)
33
+ try {
34
+ return originalJSONParse(text, reviver)
35
+ } catch (e) {
36
+ const fixed = text.replace(/([{,])\s*([a-zA-Z0-9_]+)\s*:/g, '$1"$2":')
37
+ return originalJSONParse(fixed, reviver)
38
+ }
34
39
  }
35
40
 
36
41
  function sendLog(content) {
@@ -44,7 +49,16 @@ function sendLog(content) {
44
49
 
45
50
  function sendEvent(eventName, eventArgs) {
46
51
  if (process.send) {
47
- process.send({ type: 'event', eventType: eventName, args: eventArgs });
52
+ // Добавляем информацию о боте (позицию) во все события
53
+ const enrichedArgs = {
54
+ ...eventArgs,
55
+ botEntity: bot && bot.entity ? {
56
+ position: bot.entity.position,
57
+ yaw: bot.entity.yaw,
58
+ pitch: bot.entity.pitch
59
+ } : null
60
+ };
61
+ process.send({ type: 'event', eventType: eventName, args: enrichedArgs });
48
62
  }
49
63
  }
50
64
 
@@ -79,17 +93,27 @@ function handleIncomingCommand(type, username, message) {
79
93
  const commandName = commandParts.shift().toLowerCase();
80
94
  const restOfMessage = commandParts.join(' ');
81
95
 
82
- const commandInstance = bot.commands.get(commandName) ||
83
- Array.from(bot.commands.values()).find(cmd => cmd.aliases.includes(commandName));
96
+ // Сначала проверяем стандартные команды
97
+ let commandInstance = bot.commands.get(commandName) ||
98
+ Array.from(bot.commands.values()).find(cmd => cmd.aliases.includes(commandName));
99
+
100
+ if (!commandInstance) {
101
+ // Если не найдена, проверяем временные команды из runtime registry
102
+ const runtimeRegistry = getRuntimeCommandRegistry();
103
+ commandInstance = runtimeRegistry.get(bot.config.id, commandName);
104
+ }
84
105
 
85
- if (!commandInstance) return;
106
+ if (!commandInstance) {
107
+ return;
108
+ }
86
109
 
87
110
  try {
88
111
  const processedArgs = {};
89
112
  const parsedArgs = parseArguments(restOfMessage);
90
113
  let currentArgIndex = 0;
91
114
 
92
- for (const argDef of commandInstance.isVisual ? JSON.parse(dbCommand.argumentsJson || '[]') : commandInstance.args) {
115
+ const argsDef = commandInstance.isVisual && commandInstance.args ? commandInstance.args : (commandInstance.args || []);
116
+ for (const argDef of argsDef) {
93
117
  if (argDef.type === 'greedy_string') {
94
118
  if (currentArgIndex < parsedArgs.length) {
95
119
  processedArgs[argDef.name] = parsedArgs.slice(currentArgIndex).join(' ');
@@ -110,28 +134,22 @@ function handleIncomingCommand(type, username, message) {
110
134
  }
111
135
 
112
136
  if (processedArgs[argDef.name] === undefined) {
113
- if (argDef.required) {
114
- const usage = commandInstance.args.map(arg => {
115
- return arg.required ? `<${arg.description || arg.name}>` : `[${arg.description || arg.name}]`;
116
- }).join(' ');
117
-
118
- bot.api.sendMessage(type, `Ошибка: Необходимо указать: ${argDef.description || argDef.name}`, username);
119
- bot.api.sendMessage(type, `Использование: ${bot.config.prefix}${commandInstance.name} ${usage}`, username);
120
- return;
121
- }
137
+ // Не проверяем required здесь - это будет сделано в CommandExecutionService
138
+ // после проверки типа чата и прав владельца
122
139
  if (argDef.default !== undefined) {
123
140
  processedArgs[argDef.name] = argDef.default;
124
141
  }
125
142
  }
126
143
  }
127
-
144
+
128
145
  if (process.send) {
129
146
  process.send({
130
147
  type: 'validate_and_run_command',
131
148
  commandName: commandInstance.name,
132
149
  username,
133
150
  args: processedArgs,
134
- typeChat: type
151
+ typeChat: type,
152
+ commandArgs: argsDef // Передаем определение аргументов для валидации
135
153
  });
136
154
  }
137
155
  } catch (e) {
@@ -140,17 +158,17 @@ function handleIncomingCommand(type, username, message) {
140
158
  }
141
159
 
142
160
  process.on('message', async (message) => {
143
- if (message.type === 'plugin:ui:start-updates') {
144
- const { pluginName } = message;
145
- const state = pluginUiState.get(pluginName);
146
- if (state && process.send) {
147
- process.send({
148
- type: 'plugin:data',
149
- plugin: pluginName,
150
- payload: state
151
- });
152
- }
153
- } else if (message.type === 'user_action_response') {
161
+ if (message.type === 'plugin:ui:start-updates') {
162
+ const { pluginName } = message;
163
+ const state = pluginUiState.get(pluginName);
164
+ if (state && process.send) {
165
+ process.send({
166
+ type: 'plugin:data',
167
+ plugin: pluginName,
168
+ payload: state
169
+ });
170
+ }
171
+ } else if (message.type === 'user_action_response') {
154
172
  if (pendingRequests.has(message.requestId)) {
155
173
  const { resolve, reject } = pendingRequests.get(message.requestId);
156
174
  if (message.error) {
@@ -169,6 +187,246 @@ process.on('message', async (message) => {
169
187
  payload: { players: playerList }
170
188
  });
171
189
  }
190
+ } else if (message.type === 'system:get_nearby_entities') {
191
+ const entities = [];
192
+ if (bot && bot.entities) {
193
+ const centerPos = message.payload?.position || bot.entity?.position;
194
+ const radius = message.payload?.radius || 32;
195
+
196
+ if (centerPos) {
197
+ // Перебираем все сущности
198
+ for (const entity of Object.values(bot.entities)) {
199
+ if (entity && entity.position && entity.isValid) {
200
+ // Вычисляем расстояние
201
+ const dx = entity.position.x - centerPos.x;
202
+ const dy = entity.position.y - centerPos.y;
203
+ const dz = entity.position.z - centerPos.z;
204
+ const distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
205
+
206
+ // Если существо в радиусе, добавляем в список
207
+ if (distance <= radius) {
208
+ entities.push(serializeEntity(entity));
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
214
+
215
+ if (process.send) {
216
+ process.send({
217
+ type: 'get_nearby_entities_response',
218
+ requestId: message.requestId,
219
+ payload: { entities }
220
+ });
221
+ }
222
+ } else if (message.type === 'viewer:get_state') {
223
+ if (bot && process.send) {
224
+ let blocks = undefined;
225
+
226
+ if (message.includeBlocks && bot.entity?.position) {
227
+ blocks = [];
228
+ const pos = bot.entity.position;
229
+ const horizontalRange = viewerRenderDistance;
230
+ const verticalRangeDown = Math.min(viewerRenderDistance / 2, 16);
231
+ const verticalRangeUp = viewerRenderDistance;
232
+
233
+ for (let x = Math.floor(pos.x - horizontalRange); x <= Math.floor(pos.x + horizontalRange); x++) {
234
+ for (let y = Math.floor(pos.y - verticalRangeDown); y <= Math.floor(pos.y + verticalRangeUp); y++) {
235
+ for (let z = Math.floor(pos.z - horizontalRange); z <= Math.floor(pos.z + horizontalRange); z++) {
236
+ const block = bot.blockAt(new Vec3(x, y, z));
237
+ if (block && block.type !== 0) {
238
+ blocks.push({
239
+ x, y, z,
240
+ type: block.type,
241
+ name: block.name
242
+ });
243
+ }
244
+ }
245
+ }
246
+ }
247
+ }
248
+
249
+ const state = {
250
+ status: bot._client ? 'online' : 'offline',
251
+ health: bot.health || 20,
252
+ food: bot.food || 20,
253
+ position: bot.entity?.position ? {
254
+ x: bot.entity.position.x,
255
+ y: bot.entity.position.y,
256
+ z: bot.entity.position.z
257
+ } : null,
258
+ yaw: bot.entity?.yaw || 0,
259
+ pitch: bot.entity?.pitch || 0,
260
+ gameMode: bot.game?.gameMode,
261
+ dimension: bot.game?.dimension,
262
+ blocks,
263
+ inventory: bot.inventory ? bot.inventory.items().map(item => ({
264
+ name: item.name,
265
+ displayName: item.displayName,
266
+ count: item.count,
267
+ slot: item.slot
268
+ })) : [],
269
+ nearbyPlayers: bot.entities ? Object.values(bot.entities)
270
+ .filter(e => e.type === 'player' && e.username !== bot.username)
271
+ .map(e => ({
272
+ username: e.username,
273
+ position: { x: e.position.x, y: e.position.y, z: e.position.z },
274
+ yaw: e.yaw || 0,
275
+ pitch: e.pitch || 0,
276
+ distance: bot.entity ? bot.entity.position.distanceTo(e.position) : 0
277
+ })) : [],
278
+ nearbyMobs: bot.entities ? Object.values(bot.entities)
279
+ .filter(e => e.type === 'mob')
280
+ .map(e => ({
281
+ name: e.name || e.displayName,
282
+ mobType: e.mobType,
283
+ position: { x: e.position.x, y: e.position.y, z: e.position.z },
284
+ distance: bot.entity ? bot.entity.position.distanceTo(e.position) : 0
285
+ })) : []
286
+ };
287
+
288
+ process.send({
289
+ type: 'viewer:state_response',
290
+ requestId: message.requestId,
291
+ payload: state
292
+ });
293
+ }
294
+ } else if (message.type === 'viewer:control') {
295
+ const { command } = message;
296
+ if (!bot) return;
297
+
298
+ try {
299
+ switch (command.type) {
300
+ case 'move':
301
+ bot.setControlState(command.direction, command.active);
302
+ break;
303
+
304
+ case 'look':
305
+ if (command.yaw !== undefined) bot.entity.yaw = command.yaw;
306
+ if (command.pitch !== undefined) bot.entity.pitch = command.pitch;
307
+ break;
308
+
309
+ case 'chat':
310
+ bot.chat(command.message);
311
+ break;
312
+
313
+ case 'dig':
314
+ if (command.position) {
315
+ const block = bot.blockAt(new Vec3(command.position.x, command.position.y, command.position.z));
316
+ if (block) bot.dig(block).catch(err => sendLog(`[Viewer] Dig error: ${err.message}`));
317
+ }
318
+ break;
319
+
320
+ case 'place':
321
+ if (command.position && command.blockType) {
322
+ const referenceBlock = bot.blockAt(new Vec3(command.position.x, command.position.y, command.position.z));
323
+ if (referenceBlock) {
324
+ const itemToPlace = bot.inventory.items().find(item => item.name === command.blockType);
325
+ if (itemToPlace) {
326
+ bot.equip(itemToPlace, 'hand')
327
+ .then(() => bot.placeBlock(referenceBlock, new Vec3(0, 1, 0)))
328
+ .catch(err => sendLog(`[Viewer] Place error: ${err.message}`));
329
+ }
330
+ }
331
+ }
332
+ break;
333
+
334
+ case 'sync_position':
335
+ if (command.position && bot.entity) {
336
+ bot.entity.position.x = command.position.x;
337
+ bot.entity.position.y = command.position.y;
338
+ bot.entity.position.z = command.position.z;
339
+ }
340
+ break;
341
+
342
+ case 'set_render_distance':
343
+ if (command.distance && command.distance >= 8 && command.distance <= 64) {
344
+ viewerRenderDistance = command.distance;
345
+ sendLog(`[Viewer] Render distance set to ${viewerRenderDistance}`);
346
+ }
347
+ break;
348
+ }
349
+ } catch (error) {
350
+ sendLog(`[Viewer] Control error: ${error.message}`);
351
+ }
352
+ } else if (message.type === 'execute_event_graph') {
353
+ // Выполнение event графа в child process
354
+ const { botId, graph, eventType, eventArgs } = message;
355
+
356
+ try {
357
+
358
+ const playerList = bot ? Object.keys(bot.players) : [];
359
+ const botApi = {
360
+ sendMessage: (chatType, message, recipient) => {
361
+ if (!bot || !bot.messageQueue) {
362
+ sendLog('[EventGraph] Bot not ready');
363
+ return;
364
+ }
365
+
366
+ bot.messageQueue.enqueue(chatType, message, recipient);
367
+ },
368
+ executeCommand: (command) => {
369
+ if (!bot || !bot.messageQueue) {
370
+ sendLog('[EventGraph] Bot not ready');
371
+ return;
372
+ }
373
+ bot.messageQueue.enqueue('command', command);
374
+ },
375
+ lookAt: async (x, y, z) => {
376
+ if (!bot) return;
377
+ const target = new Vec3(x, y, z);
378
+ await bot.lookAt(target);
379
+ },
380
+ navigate: async (x, y, z) => {
381
+ if (!bot || !bot.pathfinder) return;
382
+ const goal = new (require('mineflayer-pathfinder').goals.GoalBlock)(x, y, z);
383
+ await bot.pathfinder.goto(goal);
384
+ },
385
+ attack: (entityId) => {
386
+ if (!bot) return;
387
+ const entity = bot.entities[entityId];
388
+ if (entity) bot.attack(entity);
389
+ },
390
+ follow: (username) => {
391
+ if (!bot || !bot.pathfinder) return;
392
+ const player = bot.players[username];
393
+ if (player && player.entity) {
394
+ const goal = new (require('mineflayer-pathfinder').goals.GoalFollow)(player.entity, 3);
395
+ bot.pathfinder.setGoal(goal, true);
396
+ }
397
+ },
398
+ stopFollow: () => {
399
+ if (bot && bot.pathfinder) {
400
+ bot.pathfinder.setGoal(null);
401
+ }
402
+ }
403
+ };
404
+
405
+ const context = {
406
+ bot: botApi,
407
+ eventArgs: eventArgs || {},
408
+ players: playerList,
409
+ botState: bot ? {
410
+ health: bot.health,
411
+ food: bot.food,
412
+ position: bot.entity?.position,
413
+ gameMode: bot.game?.gameMode
414
+ } : {},
415
+ botEntity: bot && bot.entity ? serializeEntity(bot.entity) : null,
416
+ botId: botId,
417
+ graphId: graph.id,
418
+ eventType: eventType,
419
+ eventArgs: eventArgs
420
+ };
421
+
422
+ const engine = new GraphExecutionEngine(NodeRegistry, botApi);
423
+ await engine.execute(graph, context, eventType);
424
+
425
+
426
+ } catch (error) {
427
+ sendLog(`[EventGraph] Error executing ${eventType} graph: ${error.message}`);
428
+ sendLog(`[EventGraph] Stack: ${error.stack}`);
429
+ }
172
430
  } else if (message.type === 'start') {
173
431
  const config = message.config;
174
432
  sendLog(`[System] Получена команда на запуск бота ${config.username}...`);
@@ -186,34 +444,34 @@ process.on('message', async (message) => {
186
444
 
187
445
  if (config.proxyHost && config.proxyPort) {
188
446
  sendLog(`[System] Используется прокси: ${config.proxyHost}:${config.proxyPort}`);
189
-
447
+
190
448
  const cleanProxyUsername = config.proxyUsername ? config.proxyUsername.trim() : null;
191
449
  const cleanProxyPassword = config.proxyPassword || null;
192
-
450
+
193
451
  botOptions.connect = (client) => {
194
- SocksClient.createConnection({
195
- proxy: {
196
- host: config.proxyHost,
197
- port: config.proxyPort,
198
- type: 5,
199
- userId: cleanProxyUsername,
200
- password: cleanProxyPassword
201
- },
202
- command: 'connect',
203
- destination: {
204
- host: config.server.host,
205
- port: config.server.port
206
- }
207
- }).then(info => {
208
- client.setSocket(info.socket);
209
- client.emit('connect');
210
- }).catch(err => {
211
- sendLog(`[Proxy Error] ${err.message}`);
212
- sendLog(`[Debug] Full proxy error: ${JSON.stringify(err)}`);
213
- client.emit('error', err);
214
- });
215
- }
216
- } else {
452
+ SocksClient.createConnection({
453
+ proxy: {
454
+ host: config.proxyHost,
455
+ port: config.proxyPort,
456
+ type: 5,
457
+ userId: cleanProxyUsername,
458
+ password: cleanProxyPassword
459
+ },
460
+ command: 'connect',
461
+ destination: {
462
+ host: config.server.host,
463
+ port: config.server.port
464
+ }
465
+ }).then(info => {
466
+ client.setSocket(info.socket);
467
+ client.emit('connect');
468
+ }).catch(err => {
469
+ sendLog(`[Proxy Error] SOCKS connection failed: ${err.message}. Bot will attempt to restart.`);
470
+ client.emit('error', err);
471
+ process.exit(1);
472
+ });
473
+ }
474
+ } else {
217
475
  sendLog(`[System] Прокси не настроен, используется прямое подключение.`);
218
476
  }
219
477
 
@@ -240,7 +498,21 @@ process.on('message', async (message) => {
240
498
  bot.api = {
241
499
  Command: Command,
242
500
  events: bot.events,
243
- sendMessage: (type, message, username) => bot.messageQueue.enqueue(type, message, username),
501
+ sendMessage: (type, message, username) => {
502
+ if (type === 'websocket') {
503
+ if (process.send) {
504
+ process.send({
505
+ type: 'send_websocket_message',
506
+ payload: {
507
+ botId: bot.config.id,
508
+ message: message,
509
+ }
510
+ });
511
+ }
512
+ } else {
513
+ bot.messageQueue.enqueue(type, message, username);
514
+ }
515
+ },
244
516
  sendMessageAndWaitForReply: (command, patterns, timeout) => bot.messageQueue.enqueueAndWait(command, patterns, timeout),
245
517
  getUser: async (username) => {
246
518
  return await UserService.getUser(username, bot.config.id, bot.config);
@@ -249,96 +521,116 @@ process.on('message', async (message) => {
249
521
  registerGroup: (groupConfig) => PermissionManager.registerGroup(bot.config.id, groupConfig),
250
522
  addPermissionsToGroup: (groupName, permissionNames) => PermissionManager.addPermissionsToGroup(bot.config.id, groupName, permissionNames),
251
523
  installedPlugins: installedPluginNames,
252
- registerCommand: async (command) => {
524
+ registerCommand: async (command) => {
253
525
  try {
254
- let permissionId = null;
255
- if (command.permissions) {
256
- const permission = await prisma.permission.findUnique({
257
- where: {
258
- botId_name: {
526
+ const existingCommand = await prisma.command.findUnique({
527
+ where: {
528
+ botId_name: {
529
+ botId: bot.config.id,
530
+ name: command.name,
531
+ }
532
+ }
533
+ });
534
+
535
+ if (existingCommand) {
536
+ if (existingCommand.permissionId === null && command.permissions) {
537
+ const permission = await prisma.permission.upsert({
538
+ where: {
539
+ botId_name: {
540
+ botId: bot.config.id,
541
+ name: command.permissions,
542
+ },
543
+ },
544
+ update: {},
545
+ create: {
259
546
  botId: bot.config.id,
260
547
  name: command.permissions,
548
+ description: `Автоматически создано для команды ${command.name}`,
549
+ owner: command.owner || 'system',
261
550
  },
262
- },
263
- });
551
+ });
264
552
 
265
- if (permission) {
553
+ await prisma.command.update({
554
+ where: { id: existingCommand.id },
555
+ data: { permissionId: permission.id }
556
+ });
557
+ }
558
+ } else {
559
+ let permissionId = null;
560
+ if (command.permissions) {
561
+ const permission = await prisma.permission.upsert({
562
+ where: {
563
+ botId_name: {
564
+ botId: bot.config.id,
565
+ name: command.permissions,
566
+ },
567
+ },
568
+ update: {},
569
+ create: {
570
+ botId: bot.config.id,
571
+ name: command.permissions,
572
+ description: `Автоматически создано для команды ${command.name}`,
573
+ owner: command.owner || 'system',
574
+ },
575
+ });
266
576
  permissionId = permission.id;
267
- } else {
268
- sendLog(`[API] Внимание: право \"${command.permissions}\" не найдено для команды \"${command.name}\". Команда будет создана без привязанного права.`);
269
577
  }
270
- }
271
578
 
272
- let pluginOwnerId = null;
273
- if (command.owner && command.owner.startsWith('plugin:')) {
274
- const pluginName = command.owner.replace('plugin:', '');
275
- const plugin = await prisma.installedPlugin.findFirst({
276
- where: {
277
- botId: bot.config.id,
278
- name: pluginName
579
+ let pluginOwnerId = null;
580
+ if (command.owner && command.owner.startsWith('plugin:')) {
581
+ const pluginName = command.owner.replace('plugin:', '');
582
+ const plugin = await prisma.installedPlugin.findFirst({
583
+ where: {
584
+ botId: bot.config.id,
585
+ name: pluginName
586
+ }
587
+ });
588
+ if (plugin) {
589
+ pluginOwnerId = plugin.id;
279
590
  }
280
- });
281
- if (plugin) {
282
- pluginOwnerId = plugin.id;
283
591
  }
284
- }
285
592
 
286
- const commandData = {
287
- botId: bot.config.id,
288
- name: command.name,
289
- description: command.description || '',
290
- owner: command.owner || 'unknown',
291
- permissionId: permissionId,
292
- cooldown: command.cooldown || 0,
293
- isEnabled: command.isActive !== undefined ? command.isActive : true,
294
- aliases: JSON.stringify(command.aliases || []),
295
- allowedChatTypes: JSON.stringify(command.allowedChatTypes || ['chat', 'private']),
296
- argumentsJson: JSON.stringify(command.args || []),
297
- pluginOwnerId: pluginOwnerId,
298
- };
593
+ const commandData = {
594
+ botId: bot.config.id,
595
+ name: command.name,
596
+ description: command.description || '',
597
+ owner: command.owner || 'unknown',
598
+ permissionId: permissionId,
599
+ cooldown: command.cooldown || 0,
600
+ isEnabled: command.isActive !== undefined ? command.isActive : true,
601
+ aliases: JSON.stringify(command.aliases || []),
602
+ allowedChatTypes: JSON.stringify(command.allowedChatTypes || ['chat', 'private']),
603
+ argumentsJson: JSON.stringify(command.args || []),
604
+ pluginOwnerId: pluginOwnerId,
605
+ };
606
+
607
+ await prisma.command.create({
608
+ data: commandData,
609
+ });
610
+ }
299
611
 
300
- await prisma.command.upsert({
301
- where: {
302
- botId_name: {
303
- botId: commandData.botId,
304
- name: commandData.name,
612
+ if (process.send) {
613
+ process.send({
614
+ type: 'register_command',
615
+ commandConfig: {
616
+ name: command.name,
617
+ description: command.description,
618
+ aliases: command.aliases,
619
+ owner: command.owner,
620
+ permissions: command.permissions,
621
+ cooldown: command.cooldown,
622
+ allowedChatTypes: command.allowedChatTypes,
305
623
  }
306
- },
307
- update: {
308
- description: commandData.description,
309
- aliases: commandData.aliases,
310
- allowedChatTypes: commandData.allowedChatTypes,
311
- cooldown: commandData.cooldown,
312
- isEnabled: commandData.isEnabled,
313
- argumentsJson: commandData.argumentsJson,
314
- permissionId: commandData.permissionId,
315
- },
316
- create: commandData,
317
- });
624
+ });
625
+ }
318
626
 
319
- if (process.send) {
320
- process.send({
321
- type: 'register_command',
322
- commandConfig: {
323
- name: command.name,
324
- description: command.description,
325
- aliases: command.aliases,
326
- owner: command.owner,
327
- permissions: command.permissions,
328
- cooldown: command.cooldown,
329
- allowedChatTypes: command.allowedChatTypes,
330
- }
331
- });
332
- }
333
- sendLog(`[API] Команда \"${command.name}\" от плагина \"${command.owner}\" зарегистрирована в процессе.`);
334
-
335
- if (!bot.commands) bot.commands = new Map();
336
- bot.commands.set(command.name, command);
337
- if (Array.isArray(command.aliases)) {
338
- for (const alias of command.aliases) {
339
- bot.commands.set(alias, command);
340
- }
341
- }
627
+ if (!bot.commands) bot.commands = new Map();
628
+ bot.commands.set(command.name, command);
629
+ if (Array.isArray(command.aliases)) {
630
+ for (const alias of command.aliases) {
631
+ bot.commands.set(alias, command);
632
+ }
633
+ }
342
634
  } catch (error) {
343
635
  sendLog(`[API] Ошибка при регистрации команды: ${error.message}`);
344
636
  }
@@ -347,7 +639,7 @@ process.on('message', async (message) => {
347
639
  return new Promise((resolve, reject) => {
348
640
  const requestId = uuidv4();
349
641
  pendingRequests.set(requestId, { resolve, reject });
350
-
642
+
351
643
  if (process.send) {
352
644
  process.send({
353
645
  type: 'request_user_action',
@@ -361,7 +653,7 @@ process.on('message', async (message) => {
361
653
  } else {
362
654
  reject(new Error('IPC channel is not available.'));
363
655
  }
364
-
656
+
365
657
  setTimeout(() => {
366
658
  if (pendingRequests.has(requestId)) {
367
659
  reject(new Error('Request to main process timed out.'));
@@ -435,18 +727,45 @@ process.on('message', async (message) => {
435
727
  },
436
728
  executeCommand: (command) => {
437
729
  sendLog(`[Graph] Выполнение серверной команды: ${command}`);
438
- bot.chat(command);
730
+ if (bot && bot.messageQueue) {
731
+ bot.messageQueue.enqueue('command', command);
732
+ }
439
733
  },
440
734
  lookAt: (position) => {
441
735
  if (bot && position) {
442
736
  bot.lookAt(position);
443
737
  }
444
738
  },
739
+ getNearbyEntities: (position = null, radius = 32) => {
740
+ const entities = [];
741
+ if (bot && bot.entities) {
742
+ const centerPos = position || bot.entity?.position;
743
+
744
+ if (centerPos) {
745
+ for (const entity of Object.values(bot.entities)) {
746
+ if (entity && entity.position && entity.isValid) {
747
+ const dx = entity.position.x - centerPos.x;
748
+ const dy = entity.position.y - centerPos.y;
749
+ const dz = entity.position.z - centerPos.z;
750
+ const distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
751
+
752
+ if (distance <= radius) {
753
+ entities.push(serializeEntity(entity));
754
+ }
755
+ }
756
+ }
757
+ }
758
+ }
759
+ return entities;
760
+ },
761
+ sendLog: (message) => {
762
+ sendLog(message);
763
+ },
445
764
  sendUiUpdate: (pluginName, stateUpdate) => {
446
765
  const currentState = pluginUiState.get(pluginName) || {};
447
766
  const newState = { ...currentState, ...stateUpdate };
448
767
  pluginUiState.set(pluginName, newState);
449
-
768
+
450
769
 
451
770
  if (process.send) {
452
771
  process.send({
@@ -458,6 +777,14 @@ process.on('message', async (message) => {
458
777
  }
459
778
  };
460
779
 
780
+ // Упрощенный alias для отправки сообщений (используется в командах и нодах)
781
+ bot.sendMessage = (type, message, username) => {
782
+ bot.api.sendMessage(type, message, username);
783
+ };
784
+
785
+ // Добавляем bot.sendLog для команд
786
+ bot.sendLog = (message) => sendLog(message);
787
+
461
788
  const processApi = {
462
789
  appendLog: (botId, message) => {
463
790
  if (process.send) {
@@ -473,21 +800,24 @@ process.on('message', async (message) => {
473
800
  const dbCommands = await prisma.command.findMany({ where: { botId: config.id } });
474
801
 
475
802
  for (const dbCommand of dbCommands) {
476
- if (!dbCommand.isEnabled) {
477
- if (bot.commands.has(dbCommand.name)) {
478
- bot.commands.delete(dbCommand.name);
479
- }
480
- continue;
481
- }
482
-
483
803
  const existingCommand = bot.commands.get(dbCommand.name);
484
804
 
805
+ // Не удаляем выключенные команды, а помечаем их
806
+ // Владельцы смогут использовать выключенные команды через проверку в CommandExecutionService
807
+
485
808
  if (existingCommand) {
809
+ existingCommand.isEnabled = dbCommand.isEnabled;
486
810
  existingCommand.description = dbCommand.description;
487
811
  existingCommand.cooldown = dbCommand.cooldown;
488
812
  existingCommand.aliases = JSON.parse(dbCommand.aliases || '[]');
489
813
  existingCommand.permissionId = dbCommand.permissionId;
490
814
  existingCommand.allowedChatTypes = JSON.parse(dbCommand.allowedChatTypes || '[]');
815
+
816
+ // Добавляем алиасы в bot.commands для быстрого доступа
817
+ const aliases = JSON.parse(dbCommand.aliases || '[]');
818
+ for (const alias of aliases) {
819
+ bot.commands.set(alias, existingCommand);
820
+ }
491
821
  } else if (dbCommand.isVisual) {
492
822
  const visualCommand = new Command({
493
823
  name: dbCommand.name,
@@ -502,12 +832,53 @@ process.on('message', async (message) => {
502
832
  visualCommand.graphJson = dbCommand.graphJson;
503
833
  visualCommand.owner = 'visual_editor';
504
834
  visualCommand.handler = (botInstance, typeChat, user, args) => {
505
- const playerList = bot ? Object.keys(bot.players) : [];
506
- const botState = bot ? { yaw: bot.entity.yaw, pitch: bot.entity.pitch } : {};
507
- const context = { bot: botInstance.api, user, args, typeChat, players: playerList, botState };
508
- return bot.graphExecutionEngine.execute(visualCommand.graphJson, context);
835
+ const playerList = botInstance ? Object.keys(botInstance.players) : [];
836
+ const botState = botInstance ? { yaw: botInstance.entity.yaw, pitch: botInstance.entity.pitch } : {};
837
+ const botEntity = botInstance && botInstance.entity ? {
838
+ position: botInstance.entity.position,
839
+ yaw: botInstance.entity.yaw,
840
+ pitch: botInstance.entity.pitch
841
+ } : null;
842
+
843
+ const context = {
844
+ bot: botInstance.api,
845
+ user,
846
+ args,
847
+ typeChat,
848
+ players: playerList,
849
+ botState,
850
+ botEntity,
851
+ botId: botInstance.config.id,
852
+ graphId: dbCommand.id,
853
+ eventType: 'command',
854
+ eventArgs: {
855
+ commandName: dbCommand.name,
856
+ user: { username: user?.username },
857
+ args,
858
+ typeChat
859
+ }
860
+ };
861
+
862
+ return botInstance.graphExecutionEngine.execute(visualCommand.graphJson, context);
509
863
  };
510
864
  bot.commands.set(visualCommand.name, visualCommand);
865
+
866
+ // Добавляем алиасы визуальных команд
867
+ const visualAliases = JSON.parse(dbCommand.aliases || '[]');
868
+ for (const alias of visualAliases) {
869
+ bot.commands.set(alias, visualCommand);
870
+ }
871
+ }
872
+ }
873
+
874
+ // Добавляем алиасы для всех загруженных команд (системных и плагинов)
875
+ for (const cmd of bot.commands.values()) {
876
+ if (cmd.aliases && Array.isArray(cmd.aliases)) {
877
+ for (const alias of cmd.aliases) {
878
+ if (!bot.commands.has(alias)) {
879
+ bot.commands.set(alias, cmd);
880
+ }
881
+ }
511
882
  }
512
883
  }
513
884
 
@@ -516,7 +887,7 @@ process.on('message', async (message) => {
516
887
  process.send({
517
888
  type: 'register_command',
518
889
  commandConfig: {
519
- name: cmd.name,
890
+ name: cmd.name,
520
891
  description: cmd.description,
521
892
  aliases: cmd.aliases,
522
893
  owner: cmd.owner,
@@ -527,25 +898,37 @@ process.on('message', async (message) => {
527
898
  });
528
899
  }
529
900
  }
530
-
901
+
531
902
  await initializePlugins(bot, config.plugins, prisma);
532
903
  sendLog('[System] Все системы инициализированы.');
533
904
 
534
905
  let messageHandledByCustomParser = false;
535
906
 
536
907
  bot.on('message', (jsonMsg) => {
537
- const ansiMessage = jsonMsg.toAnsi();
538
- if (ansiMessage.trim()) {
539
- sendLog(ansiMessage);
908
+ const logContent = jsonMsg.toAnsi();
909
+
910
+ if (logContent.trim()) {
911
+ sendLog(logContent);
540
912
  }
541
-
913
+
542
914
  messageHandledByCustomParser = false;
543
915
  const rawMessageText = jsonMsg.toString();
544
916
  bot.events.emit('core:raw_message', rawMessageText, jsonMsg);
545
-
917
+
546
918
  sendEvent('raw_message', {
547
- rawText: rawMessageText
919
+ rawText: rawMessageText,
920
+ json: jsonMsg
548
921
  });
922
+
923
+ if (process.send && rawMessageText.trim()) {
924
+ process.send({
925
+ type: 'viewer:chat',
926
+ payload: {
927
+ rawText: rawMessageText,
928
+ timestamp: Date.now()
929
+ }
930
+ });
931
+ }
549
932
  });
550
933
 
551
934
  bot.events.on('chat:message', (data) => {
@@ -589,16 +972,17 @@ process.on('message', async (message) => {
589
972
  sendLog(`Ошибка при обработке userAction: ${error.message}`);
590
973
  }
591
974
  });
592
-
975
+
593
976
  bot.on('login', () => {
594
977
  if (connectionTimeout) {
595
978
  clearTimeout(connectionTimeout);
596
979
  connectionTimeout = null;
597
980
  }
598
981
  sendLog('[Event: login] Успешно залогинился!');
599
- if (process.send) {
982
+ if (process.send && !botReadySent) {
600
983
  process.send({ type: 'bot_ready' });
601
984
  process.send({ type: 'status', status: 'running' });
985
+ botReadySent = true;
602
986
  }
603
987
  });
604
988
 
@@ -628,7 +1012,7 @@ process.on('message', async (message) => {
628
1012
  }
629
1013
  sendLog(`[Event: error] Произошла ошибка: ${err.stack || err.message}`);
630
1014
  });
631
-
1015
+
632
1016
  bot.on('end', (reason) => {
633
1017
  if (connectionTimeout) {
634
1018
  clearTimeout(connectionTimeout);
@@ -674,11 +1058,55 @@ process.on('message', async (message) => {
674
1058
  });
675
1059
 
676
1060
  bot.on('spawn', () => {
677
- sendLog('[Event: spawn] Бот заспавнился в мире.');
1061
+ try {
1062
+ if (bot._client && bot._client.options) {
1063
+ bot._client.options.chat = 'enabled';
1064
+ }
1065
+ if (bot.chatEnabled !== undefined) {
1066
+ bot.chatEnabled = true;
1067
+ }
1068
+ } catch (err) {
1069
+ }
678
1070
  setTimeout(() => {
679
1071
  isReady = true;
680
- sendLog('[BotProcess] Бот готов к приему событий.');
681
1072
  }, 3000);
1073
+
1074
+ // Отправка события для viewer
1075
+ if (process.send) {
1076
+ process.send({
1077
+ type: 'viewer:spawn',
1078
+ payload: {
1079
+ position: bot.entity?.position,
1080
+ yaw: bot.entity?.yaw,
1081
+ pitch: bot.entity?.pitch
1082
+ }
1083
+ });
1084
+ }
1085
+ });
1086
+
1087
+ bot.on('health', () => {
1088
+ if (process.send) {
1089
+ process.send({
1090
+ type: 'viewer:health',
1091
+ payload: {
1092
+ health: bot.health,
1093
+ food: bot.food
1094
+ }
1095
+ });
1096
+ }
1097
+ });
1098
+
1099
+ bot.on('move', () => {
1100
+ if (process.send) {
1101
+ process.send({
1102
+ type: 'viewer:move',
1103
+ payload: {
1104
+ position: bot.entity?.position,
1105
+ yaw: bot.entity?.yaw,
1106
+ pitch: bot.entity?.pitch
1107
+ }
1108
+ });
1109
+ }
682
1110
  });
683
1111
  } catch (err) {
684
1112
  sendLog(`[CRITICAL] Критическая ошибка при создании бота: ${err.stack}`);
@@ -706,6 +1134,7 @@ process.on('message', async (message) => {
706
1134
  clearTimeout(connectionTimeout);
707
1135
  connectionTimeout = null;
708
1136
  }
1137
+ botReadySent = false;
709
1138
  if (bot) bot.quit();
710
1139
  else process.exit(0);
711
1140
  } else if (message.type === 'chat') {
@@ -713,15 +1142,151 @@ process.on('message', async (message) => {
713
1142
  const { message: msg, chatType, username } = message.payload;
714
1143
  bot.messageQueue.enqueue(chatType, msg, username);
715
1144
  }
1145
+ } else if (message.type === 'register_temp_command') {
1146
+ // Регистрация временной команды из главного процесса
1147
+ const { commandData } = message;
1148
+
1149
+ try {
1150
+ const tempCommand = new Command({
1151
+ name: commandData.name,
1152
+ description: commandData.description || '',
1153
+ aliases: commandData.aliases || [],
1154
+ cooldown: commandData.cooldown || 0,
1155
+ allowedChatTypes: commandData.allowedChatTypes || ['chat', 'private'],
1156
+ args: [],
1157
+ owner: 'runtime',
1158
+ });
1159
+
1160
+ tempCommand.permissionId = commandData.permissionId || null;
1161
+ tempCommand.isTemporary = true;
1162
+ tempCommand.tempId = commandData.tempId;
1163
+ tempCommand.isVisual = false;
1164
+ tempCommand.handler = () => { };
1165
+
1166
+ // Регистрируем команду в bot.commands
1167
+ bot.commands.set(commandData.name, tempCommand);
1168
+
1169
+ if (Array.isArray(commandData.aliases)) {
1170
+ for (const alias of commandData.aliases) {
1171
+ bot.commands.set(alias, tempCommand);
1172
+ }
1173
+ }
1174
+ } catch (error) {
1175
+ sendLog(`[BotProcess] Ошибка регистрации временной команды: ${error.message}`);
1176
+ }
1177
+ } else if (message.type === 'unregister_temp_command') {
1178
+ const { commandName, aliases } = message;
1179
+
1180
+ try {
1181
+ if (bot.commands.has(commandName)) {
1182
+ bot.commands.delete(commandName);
1183
+ }
1184
+
1185
+ if (Array.isArray(aliases)) {
1186
+ for (const alias of aliases) {
1187
+ if (bot.commands.has(alias)) {
1188
+ bot.commands.delete(alias);
1189
+ }
1190
+ }
1191
+ }
1192
+ } catch (error) {
1193
+ sendLog(`[BotProcess] Ошибка удаления временной команды: ${error.message}`);
1194
+ }
716
1195
  } else if (message.type === 'execute_handler') {
717
1196
  const { commandName, username, args, typeChat } = message;
718
1197
  const commandInstance = bot.commands.get(commandName);
719
1198
  if (commandInstance) {
720
- const fakeUser = { username };
721
- commandInstance.handler(bot, typeChat, fakeUser, args).catch(e => {
722
- sendLog(`[Handler Error] Ошибка в handler-е команды ${commandName}: ${e.message}`);
723
- });
1199
+ (async () => {
1200
+ try {
1201
+ const user = await UserService.getUser(username, bot.config.id, bot.config);
1202
+
1203
+ const handlerParamCount = commandInstance.handler.length;
1204
+
1205
+ if (handlerParamCount === 1) {
1206
+ const transport = new Transport(typeChat, bot);
1207
+ const context = new CommandContext(bot, user, args, transport);
1208
+ await commandInstance.handler(context);
1209
+ } else {
1210
+ await commandInstance.handler(bot, typeChat, user, args);
1211
+ }
1212
+ } catch (e) {
1213
+ sendLog(`[Handler Error] Ошибка в handler-е команды ${commandName}: ${e.message}`);
1214
+ sendLog(`[Handler Error] Stack trace: ${e.stack}`);
1215
+ }
1216
+ })();
724
1217
  }
1218
+ } else if (message.type === 'execute_command_request') {
1219
+ const { requestId, payload } = message;
1220
+ const { commandName, args, username, typeChat } = payload;
1221
+
1222
+ (async () => {
1223
+ try {
1224
+ const commandInstance = bot.commands.get(commandName);
1225
+ if (!commandInstance) {
1226
+ throw new Error(`Command '${commandName}' not found.`);
1227
+ }
1228
+
1229
+ const user = await UserService.getUser(username, bot.config.id, bot.config);
1230
+
1231
+ let result;
1232
+
1233
+ const handlerParamCount = commandInstance.handler.length;
1234
+
1235
+ if (handlerParamCount === 1) {
1236
+ const transport = new Transport(typeChat, bot);
1237
+ const context = new CommandContext(bot, user, args, transport);
1238
+
1239
+ if (typeChat === 'websocket') {
1240
+ result = await commandInstance.handler(context);
1241
+ if (process.send) {
1242
+ process.send({ type: 'execute_command_response', requestId, result });
1243
+ }
1244
+ } else {
1245
+ commandInstance.handler(context).catch(e => {
1246
+ sendLog(`[Handler Error] Ошибка в handler-е команды ${commandName}: ${e.message}`);
1247
+ });
1248
+ }
1249
+ } else {
1250
+ // Старая сигнатура: handler(bot, typeChat, user, args)
1251
+ if (typeChat === 'websocket') {
1252
+ // Для websocket перехватываем bot.sendMessage
1253
+ const originalSendMessage = bot.sendMessage;
1254
+ let resultFromSendMessage = null;
1255
+ let sendMessageCalled = false;
1256
+
1257
+ bot.sendMessage = (type, message, username) => {
1258
+ if (type === 'websocket') {
1259
+ resultFromSendMessage = message;
1260
+ sendMessageCalled = true;
1261
+ } else {
1262
+ originalSendMessage.call(bot, type, message, username);
1263
+ }
1264
+ };
1265
+
1266
+ try {
1267
+ const returnValue = await commandInstance.handler(bot, typeChat, user, args);
1268
+ result = sendMessageCalled ? resultFromSendMessage : returnValue;
1269
+
1270
+ if (process.send) {
1271
+ process.send({ type: 'execute_command_response', requestId, result });
1272
+ }
1273
+ } finally {
1274
+ bot.sendMessage = originalSendMessage;
1275
+ }
1276
+ } else {
1277
+ // Для игровых команд просто выполняем
1278
+ commandInstance.handler(bot, typeChat, user, args).catch(e => {
1279
+ sendLog(`[Handler Error] Ошибка в handler-е команды ${commandName}: ${e.message}`);
1280
+ });
1281
+ }
1282
+ }
1283
+
1284
+ } catch (error) {
1285
+ if (process.send) {
1286
+ process.send({ type: 'execute_command_response', requestId, error: error.message });
1287
+ }
1288
+ }
1289
+ })();
725
1290
  } else if (message.type === 'invalidate_user_cache') {
726
1291
  if (message.username && bot && bot.config) {
727
1292
  UserService.clearCache(message.username, bot.config.id);
@@ -773,6 +1338,11 @@ process.on('message', async (message) => {
773
1338
  commandInstance.onBlacklisted(bot, typeChat, { username });
774
1339
  }
775
1340
  }
1341
+ } else if (message.type === 'send_message') {
1342
+ const { typeChat, message: msg, username } = message;
1343
+ if (bot && bot.api) {
1344
+ bot.api.sendMessage(typeChat, msg, username);
1345
+ }
776
1346
  } else if (message.type === 'action') {
777
1347
  if (message.name === 'lookAt' && bot && message.payload.position) {
778
1348
  const { x, y, z } = message.payload.position;
@@ -784,19 +1354,108 @@ process.on('message', async (message) => {
784
1354
  }
785
1355
  } else if (message.type === 'plugins:reload') {
786
1356
  sendLog('[System] Получена команда на перезагрузку плагинов...');
787
- const newConfig = await fetchNewConfig(bot.config.id, prisma);
788
- if (newConfig) {
789
- bot.config.plugins = newConfig.installedPlugins;
790
- bot.commands.clear();
791
- await loadCommands(bot, newConfig.commands);
792
- await initializePlugins(bot, newConfig.installedPlugins, prisma);
793
- sendLog('[System] Плагины успешно перезагружены.');
794
- } else {
1357
+ const newConfig = await fetchNewConfig(bot.config.id, prisma);
1358
+ if (newConfig) {
1359
+ bot.config.plugins = newConfig.installedPlugins;
1360
+ bot.commands.clear();
1361
+ await loadCommands(bot, newConfig.commands);
1362
+ await initializePlugins(bot, newConfig.installedPlugins, prisma);
1363
+ sendLog('[System] Плагины успешно перезагружены.');
1364
+ } else {
795
1365
  sendLog('[System] Не удалось получить новую конфигурацию для перезагрузки плагинов.');
796
1366
  }
797
1367
  } else if (message.type === 'server_command') {
798
- if (bot && message.payload && message.payload.command) {
799
- bot.chat(message.payload.command);
1368
+ if (bot && bot.messageQueue && message.payload && message.payload.command) {
1369
+ bot.messageQueue.enqueue('command', message.payload.command);
1370
+ }
1371
+ } else if (message.type === 'execute_event_graph') {
1372
+ // Выполнение event графа в child process
1373
+ const { graph, eventType, eventArgs } = message;
1374
+
1375
+ try {
1376
+ if (!graph || !graph.nodes || graph.nodes.length === 0) {
1377
+ return;
1378
+ }
1379
+
1380
+ const config = bot?.config || bot?.botConfig || message.botConfig;
1381
+
1382
+ if (!config) {
1383
+ sendLog('[ERROR] Bot config not available for event graph execution');
1384
+ return;
1385
+ }
1386
+
1387
+ const botApi = {
1388
+ sendMessage: (chatType, messageText, recipient) => {
1389
+ if (!bot || !bot.messageQueue) return;
1390
+ bot.messageQueue.enqueue(chatType, messageText, recipient);
1391
+ },
1392
+ executeCommand: (command) => {
1393
+ if (!bot || !bot.messageQueue) return;
1394
+ bot.messageQueue.enqueue('command', command);
1395
+ },
1396
+ lookAt: async (x, y, z) => {
1397
+ if (!bot) return;
1398
+ const target = new Vec3(x, y, z);
1399
+ await bot.lookAt(target);
1400
+ },
1401
+ navigate: async (x, y, z) => {
1402
+ if (!bot || !bot.pathfinder) return;
1403
+ const goal = new (require('mineflayer-pathfinder').goals.GoalBlock)(x, y, z);
1404
+ await bot.pathfinder.goto(goal);
1405
+ },
1406
+ attack: (entityId) => {
1407
+ if (!bot) return;
1408
+ const entity = bot.entities[entityId];
1409
+ if (entity) bot.attack(entity);
1410
+ },
1411
+ follow: (username) => {
1412
+ if (!bot || !bot.pathfinder) return;
1413
+ const player = bot.players[username];
1414
+ if (player && player.entity) {
1415
+ const goal = new (require('mineflayer-pathfinder').goals.GoalFollow)(player.entity, 3);
1416
+ bot.pathfinder.setGoal(goal, true);
1417
+ }
1418
+ },
1419
+ stopFollow: () => {
1420
+ if (bot && bot.pathfinder) {
1421
+ bot.pathfinder.setGoal(null);
1422
+ }
1423
+ }
1424
+ };
1425
+
1426
+ const players = bot ? Object.keys(bot.players) : [];
1427
+
1428
+ const context = {
1429
+ bot: botApi,
1430
+ players,
1431
+ botState: {
1432
+ health: bot?.health,
1433
+ food: bot?.food,
1434
+ position: bot?.entity?.position
1435
+ },
1436
+ botEntity: bot && bot.entity ? {
1437
+ position: bot.entity.position,
1438
+ velocity: bot.entity.velocity,
1439
+ yaw: bot.entity.yaw,
1440
+ pitch: bot.entity.pitch,
1441
+ onGround: bot.entity.onGround,
1442
+ height: bot.entity.height,
1443
+ width: bot.entity.width
1444
+ } : null,
1445
+ eventArgs,
1446
+ botId: config.id,
1447
+ graphId: graph.id,
1448
+ eventType: eventType,
1449
+ eventArgs: eventArgs
1450
+ };
1451
+
1452
+ const engine = new GraphExecutionEngine(NodeRegistry, botApi);
1453
+
1454
+ await engine.execute(graph, context, eventType);
1455
+
1456
+ } catch (error) {
1457
+ sendLog(`[ERROR] Error executing event graph for '${eventType}': ${error.message}`);
1458
+ console.error(error);
800
1459
  }
801
1460
  }
802
1461
  });
@@ -841,18 +1500,18 @@ process.on('SIGINT', () => {
841
1500
  function serializeEntity(entity) {
842
1501
  if (!entity) return null;
843
1502
  return {
844
- id: entity.id,
845
- type: entity.type,
846
- username: entity.username,
847
- displayName: entity.displayName,
848
- position: entity.position,
849
- yaw: entity.yaw,
850
- pitch: entity.pitch,
851
- onGround: entity.onGround,
852
- isValid: entity.isValid,
853
- heldItem: entity.heldItem,
854
- equipment: entity.equipment,
855
- metadata: entity.metadata
1503
+ id: entity.id,
1504
+ type: entity.type,
1505
+ username: entity.username,
1506
+ displayName: entity.displayName,
1507
+ position: entity.position,
1508
+ yaw: entity.yaw,
1509
+ pitch: entity.pitch,
1510
+ onGround: entity.onGround,
1511
+ isValid: entity.isValid,
1512
+ heldItem: entity.heldItem,
1513
+ equipment: entity.equipment,
1514
+ metadata: entity.metadata
856
1515
  };
857
1516
  }
858
1517