blockmine 1.25.0 → 1.27.1

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 (165) hide show
  1. package/CHANGELOG.md +46 -1
  2. package/backend/cli.js +1 -1
  3. package/backend/package.json +2 -2
  4. package/backend/prisma/migrations/20260328173000_add_plugin_source_ref/migration.sql +2 -0
  5. package/backend/prisma/migrations/migration_lock.toml +2 -2
  6. package/backend/prisma/schema.prisma +2 -0
  7. package/backend/src/api/routes/apiKeys.js +8 -0
  8. package/backend/src/api/routes/bots.js +258 -9
  9. package/backend/src/api/routes/eventGraphs.js +151 -1
  10. package/backend/src/api/routes/health.js +38 -0
  11. package/backend/src/api/routes/nodeRegistry.js +63 -0
  12. package/backend/src/api/routes/plugins.js +254 -29
  13. package/backend/src/container.js +11 -8
  14. package/backend/src/core/BotCommandLoader.js +161 -0
  15. package/backend/src/core/BotConnection.js +125 -0
  16. package/backend/src/core/BotEventHandlers.js +234 -0
  17. package/backend/src/core/BotIPCHandler.js +445 -0
  18. package/backend/src/core/BotManager.js +15 -7
  19. package/backend/src/core/BotProcess.js +75 -142
  20. package/backend/src/core/EventGraphManager.js +7 -3
  21. package/backend/src/core/GraphDebugHandler.js +229 -0
  22. package/backend/src/core/GraphDebugIPC.js +117 -0
  23. package/backend/src/core/GraphExecutionEngine.js +545 -978
  24. package/backend/src/core/GraphTraversal.js +80 -0
  25. package/backend/src/core/GraphValidation.js +73 -0
  26. package/backend/src/core/NodeDefinition.js +138 -0
  27. package/backend/src/core/NodeRegistry.js +153 -141
  28. package/backend/src/core/PluginManager.js +272 -31
  29. package/backend/src/core/RewindSignal.js +9 -0
  30. package/backend/src/core/config/ConfigValidator.js +72 -0
  31. package/backend/src/core/config/FeatureFlags.js +52 -0
  32. package/backend/src/core/config/__tests__/ConfigValidator.test.js +232 -0
  33. package/backend/src/core/domain/entities/Bot.js +39 -0
  34. package/backend/src/core/domain/entities/Command.js +41 -0
  35. package/backend/src/core/domain/entities/EventGraph.js +39 -0
  36. package/backend/src/core/domain/entities/Plugin.js +45 -0
  37. package/backend/src/core/domain/entities/User.js +40 -0
  38. package/backend/src/core/domain/services/DependencyResolver.js +168 -0
  39. package/backend/src/core/domain/services/GraphValidator.js +117 -0
  40. package/backend/src/core/domain/services/PermissionChecker.js +34 -0
  41. package/backend/src/core/domain/services/__tests__/DependencyResolver.test.js +126 -0
  42. package/backend/src/core/domain/valueObjects/BotConfig.js +27 -0
  43. package/backend/src/core/domain/valueObjects/DependencyGraph.js +86 -0
  44. package/backend/src/core/domain/valueObjects/PluginManifest.js +36 -0
  45. package/backend/src/core/errors/BaseError.js +29 -0
  46. package/backend/src/core/errors/ErrorHandler.js +81 -0
  47. package/backend/src/core/errors/__tests__/ErrorHandler.test.js +188 -0
  48. package/backend/src/core/errors/index.js +68 -0
  49. package/backend/src/core/infrastructure/BatchingUtility.js +66 -0
  50. package/backend/src/core/infrastructure/CircuitBreaker.js +103 -0
  51. package/backend/src/core/infrastructure/ConnectionPool.js +81 -0
  52. package/backend/src/core/infrastructure/RateLimiter.js +64 -0
  53. package/backend/src/core/infrastructure/__tests__/BatchingUtility.test.js +86 -0
  54. package/backend/src/core/infrastructure/__tests__/CircuitBreaker.test.js +156 -0
  55. package/backend/src/core/infrastructure/__tests__/ConnectionPool.test.js +146 -0
  56. package/backend/src/core/infrastructure/__tests__/RateLimiter.test.js +171 -0
  57. package/backend/src/core/ipc/botApiFactory.js +72 -0
  58. package/backend/src/core/ipc/ipcMessageTypes.js +115 -0
  59. package/backend/src/core/logging/AuditLogger.js +61 -0
  60. package/backend/src/core/logging/StructuredLogger.js +80 -0
  61. package/backend/src/core/logging/__tests__/StructuredLogger.test.js +213 -0
  62. package/backend/src/core/logging/index.js +7 -0
  63. package/backend/src/core/metrics/MetricsCollector.js +104 -0
  64. package/backend/src/core/metrics/__tests__/MetricsCollector.test.js +131 -0
  65. package/backend/src/core/node-registries/actionsNodes.js +191 -0
  66. package/backend/src/core/node-registries/arraysNodes.js +152 -0
  67. package/backend/src/core/node-registries/botNodes.js +48 -0
  68. package/backend/src/core/node-registries/containerNodes.js +141 -0
  69. package/backend/src/core/node-registries/dataNodes.js +284 -0
  70. package/backend/src/core/node-registries/debugNodes.js +23 -0
  71. package/backend/src/core/node-registries/eventsNodes.js +223 -0
  72. package/backend/src/core/node-registries/flowNodes.js +151 -0
  73. package/backend/src/core/node-registries/furnaceNodes.js +123 -0
  74. package/backend/src/core/node-registries/index.js +108 -0
  75. package/backend/src/core/node-registries/inventory.js +102 -106
  76. package/backend/src/core/node-registries/logicNodes.js +54 -0
  77. package/backend/src/core/node-registries/mathNodes.js +38 -0
  78. package/backend/src/core/node-registries/navigationNodes.js +109 -0
  79. package/backend/src/core/node-registries/objectsNodes.js +90 -0
  80. package/backend/src/core/node-registries/stringsNodes.js +165 -0
  81. package/backend/src/core/node-registries/timeNodes.js +105 -0
  82. package/backend/src/core/node-registries/typeNodes.js +22 -0
  83. package/backend/src/core/node-registries/usersNodes.js +126 -0
  84. package/backend/src/core/nodes/arrays/shuffle.js +14 -0
  85. package/backend/src/core/nodes/bot/get_name.js +8 -0
  86. package/backend/src/core/nodes/bot/stop_bot.js +5 -0
  87. package/backend/src/core/nodes/container/open.js +101 -111
  88. package/backend/src/core/nodes/data/store_read.js +26 -0
  89. package/backend/src/core/nodes/data/store_write.js +23 -0
  90. package/backend/src/core/nodes/event/call_event.js +31 -0
  91. package/backend/src/core/nodes/event/custom_event.js +8 -0
  92. package/backend/src/core/nodes/flow/timer.js +35 -0
  93. package/backend/src/core/nodes/inventory/drop.js +73 -65
  94. package/backend/src/core/nodes/inventory/equip.js +54 -45
  95. package/backend/src/core/nodes/inventory/select_slot.js +48 -46
  96. package/backend/src/core/nodes/navigation/follow.js +54 -51
  97. package/backend/src/core/nodes/navigation/go_to.js +41 -53
  98. package/backend/src/core/nodes/navigation/go_to_entity.js +65 -69
  99. package/backend/src/core/nodes/navigation/go_to_player.js +65 -70
  100. package/backend/src/core/nodes/navigation/stop.js +17 -26
  101. package/backend/src/core/nodes/users/add_to_group.js +24 -0
  102. package/backend/src/core/nodes/users/check_permission.js +26 -0
  103. package/backend/src/core/nodes/users/remove_from_group.js +24 -0
  104. package/backend/src/core/services/BotIPCMessageRouter.js +337 -0
  105. package/backend/src/core/services/BotLifecycleService.js +41 -632
  106. package/backend/src/core/services/CacheManager.js +83 -23
  107. package/backend/src/core/services/CrashRestartManager.js +42 -0
  108. package/backend/src/core/services/DebugSessionManager.js +114 -12
  109. package/backend/src/core/services/EventGraphService.js +69 -0
  110. package/backend/src/core/services/MinecraftBotManager.js +9 -1
  111. package/backend/src/core/services/PluginManagementService.js +84 -0
  112. package/backend/src/core/services/TestModeContext.js +65 -0
  113. package/backend/src/core/services/__tests__/CacheManager.test.js +168 -0
  114. package/backend/src/core/services.js +1 -11
  115. package/backend/src/core/validation/InputValidator.js +167 -0
  116. package/backend/src/core/validation/__tests__/InputValidator.test.js +296 -0
  117. package/backend/src/real-time/botApi/index.js +1 -1
  118. package/backend/src/real-time/socketHandler.js +26 -0
  119. package/backend/src/server.js +10 -5
  120. package/frontend/dist/assets/{browser-ponyfill-DN7pwmHT.js → browser-ponyfill-D8y0Ty7C.js} +1 -1
  121. package/frontend/dist/assets/index-CFJLS0dk.css +32 -0
  122. package/frontend/dist/assets/{index-LSy71uwm.js → index-D91UGNMG.js} +1880 -1881
  123. package/frontend/dist/index.html +2 -2
  124. package/frontend/dist/locales/en/bots.json +4 -1
  125. package/frontend/dist/locales/en/common.json +7 -1
  126. package/frontend/dist/locales/en/login.json +2 -0
  127. package/frontend/dist/locales/en/management.json +79 -1
  128. package/frontend/dist/locales/en/nodes.json +59 -4
  129. package/frontend/dist/locales/en/plugin-detail.json +24 -4
  130. package/frontend/dist/locales/en/plugins.json +226 -7
  131. package/frontend/dist/locales/en/setup.json +2 -0
  132. package/frontend/dist/locales/en/sidebar.json +171 -3
  133. package/frontend/dist/locales/en/visual-editor.json +230 -31
  134. package/frontend/dist/locales/ru/bots.json +4 -1
  135. package/frontend/dist/locales/ru/login.json +2 -0
  136. package/frontend/dist/locales/ru/management.json +79 -1
  137. package/frontend/dist/locales/ru/minecraft-viewer.json +3 -0
  138. package/frontend/dist/locales/ru/nodes.json +105 -51
  139. package/frontend/dist/locales/ru/plugins.json +103 -4
  140. package/frontend/dist/locales/ru/setup.json +2 -0
  141. package/frontend/dist/locales/ru/sidebar.json +171 -3
  142. package/frontend/dist/locales/ru/visual-editor.json +232 -33
  143. package/frontend/package.json +2 -0
  144. package/nul +12 -0
  145. package/package.json +3 -3
  146. package/scripts/postinstall.js +38 -0
  147. package/backend/package-lock.json +0 -6801
  148. package/backend/src/core/node-registries/actions.js +0 -202
  149. package/backend/src/core/node-registries/arrays.js +0 -155
  150. package/backend/src/core/node-registries/bot.js +0 -23
  151. package/backend/src/core/node-registries/container.js +0 -162
  152. package/backend/src/core/node-registries/data.js +0 -290
  153. package/backend/src/core/node-registries/debug.js +0 -26
  154. package/backend/src/core/node-registries/events.js +0 -201
  155. package/backend/src/core/node-registries/flow.js +0 -139
  156. package/backend/src/core/node-registries/furnace.js +0 -143
  157. package/backend/src/core/node-registries/logic.js +0 -62
  158. package/backend/src/core/node-registries/math.js +0 -42
  159. package/backend/src/core/node-registries/navigation.js +0 -111
  160. package/backend/src/core/node-registries/objects.js +0 -98
  161. package/backend/src/core/node-registries/strings.js +0 -187
  162. package/backend/src/core/node-registries/time.js +0 -113
  163. package/backend/src/core/node-registries/type.js +0 -25
  164. package/backend/src/core/node-registries/users.js +0 -79
  165. package/frontend/dist/assets/index-SfhKxI4-.css +0 -32
@@ -0,0 +1,229 @@
1
+ const { getGlobalDebugManager } = require('./services/DebugSessionManager');
2
+ const RewindSignal = require('./RewindSignal');
3
+ const { MAX_RECURSION_DEPTH } = require('./config/validation');
4
+
5
+ class GraphDebugHandler {
6
+ constructor(context) {
7
+ this.context = context;
8
+ this._inputOverrides = new Map();
9
+ }
10
+
11
+ async checkBreakpoint(node, captureNodeInputs, captureNodeOutputs, currentTraceId, traceCollector) {
12
+ try {
13
+ if (process.send) {
14
+ const debugIPC = require('./GraphDebugIPC');
15
+ return await debugIPC.checkBreakpointViaIpc(
16
+ node, this.context, captureNodeInputs, currentTraceId, traceCollector
17
+ );
18
+ }
19
+
20
+ const debugManager = getGlobalDebugManager();
21
+ const graphId = this.context.graphId;
22
+
23
+ if (!graphId) return null;
24
+
25
+ const debugState = debugManager.get(graphId);
26
+ if (!debugState) return null;
27
+
28
+ const breakpoint = debugState.breakpoints.get(node.id);
29
+ if (!breakpoint || !breakpoint.enabled) return null;
30
+
31
+ const shouldPause = await this.evaluateBreakpointCondition(breakpoint);
32
+ if (!shouldPause) return null;
33
+
34
+ console.log(`[Debug] Hit breakpoint at node ${node.id}, pausing execution`);
35
+
36
+ breakpoint.hitCount++;
37
+
38
+ const inputs = await captureNodeInputs(node);
39
+ const executedSteps = currentTraceId ? await traceCollector.getTrace(currentTraceId) : null;
40
+
41
+ const overrides = await debugState.pause({
42
+ nodeId: node.id,
43
+ nodeType: node.type,
44
+ inputs,
45
+ executedSteps,
46
+ context: {
47
+ user: this.context.user,
48
+ variables: this.context.variables,
49
+ commandArguments: this.context.commandArguments,
50
+ },
51
+ breakpoint: {
52
+ condition: breakpoint.condition,
53
+ hitCount: breakpoint.hitCount
54
+ }
55
+ });
56
+
57
+ return this.processOverrides(overrides);
58
+
59
+ } catch (error) {
60
+ if (error instanceof RewindSignal) throw error;
61
+ if (error.message === 'Execution stopped by debugger') throw error;
62
+ if (error.message === 'DebugSessionManager not initialized! Call initializeDebugManager(io) first.') {
63
+ return null;
64
+ }
65
+ console.error(`[checkBreakpoint] ERROR:`, error.message);
66
+ return null;
67
+ }
68
+ }
69
+
70
+ async checkStepMode(node, captureNodeInputs, currentTraceId, traceCollector) {
71
+ try {
72
+ if (process.send) {
73
+ const debugIPC = require('./GraphDebugIPC');
74
+ return await debugIPC.checkStepModeViaIpc(
75
+ node, this.context, captureNodeInputs, currentTraceId, traceCollector
76
+ );
77
+ }
78
+
79
+ const debugManager = getGlobalDebugManager();
80
+ const graphId = this.context.graphId;
81
+
82
+ if (!graphId) return null;
83
+
84
+ const debugState = debugManager.get(graphId);
85
+ if (!debugState || !debugState.shouldStepPause(node.id)) return null;
86
+
87
+ console.log(`[Debug] Step mode: pausing after executing node ${node.id}`);
88
+
89
+ const inputs = await captureNodeInputs(node);
90
+ const executedSteps = currentTraceId ? await traceCollector.getTrace(currentTraceId) : null;
91
+
92
+ const overrides = await debugState.pause({
93
+ nodeId: node.id,
94
+ nodeType: node.type,
95
+ inputs,
96
+ executedSteps,
97
+ context: {
98
+ user: this.context.user,
99
+ variables: this.context.variables,
100
+ commandArguments: this.context.commandArguments,
101
+ }
102
+ });
103
+
104
+ return this.processOverrides(overrides);
105
+
106
+ } catch (error) {
107
+ if (error instanceof RewindSignal) throw error;
108
+ if (error.message === 'DebugSessionManager not initialized! Call initializeDebugManager(io) first.') {
109
+ return null;
110
+ }
111
+ throw error;
112
+ }
113
+ }
114
+
115
+ async evaluateBreakpointCondition(breakpoint) {
116
+ if (!breakpoint.condition || breakpoint.condition.trim() === '') {
117
+ return true;
118
+ }
119
+
120
+ try {
121
+ const sandbox = {
122
+ user: this.context.user || {},
123
+ args: this.context.commandArguments || {},
124
+ variables: this.context.variables || {},
125
+ context: this.context
126
+ };
127
+
128
+ const fn = new Function(
129
+ ...Object.keys(sandbox),
130
+ `return (${breakpoint.condition})`
131
+ );
132
+
133
+ return Boolean(fn(...Object.values(sandbox)));
134
+ } catch (error) {
135
+ console.error(`[Debug] Error evaluating breakpoint condition: ${error.message}`);
136
+ return false;
137
+ }
138
+ }
139
+
140
+ processOverrides(overrides) {
141
+ if (!overrides) return null;
142
+
143
+ if (overrides.__stopped) {
144
+ throw new Error('Execution stopped by debugger');
145
+ }
146
+
147
+ if (overrides.__rewind) {
148
+ throw new RewindSignal(overrides.target);
149
+ }
150
+
151
+ this.applyWhatIfOverrides(overrides);
152
+ return overrides;
153
+ }
154
+
155
+ applyWhatIfOverrides(node, overrides) {
156
+ if (!overrides || typeof overrides !== 'object') return;
157
+
158
+ console.log(`[Debug] Applying what-if overrides to node ${node.id}:`, overrides);
159
+
160
+ for (const [key, value] of Object.entries(overrides)) {
161
+ if (key === '__stopped' || key === '__rewind' || key === 'target') continue;
162
+
163
+ if (key.startsWith('var.')) {
164
+ const varName = key.substring(4);
165
+ if (!this.context.variables) this.context.variables = {};
166
+ this.context.variables[varName] = value;
167
+ continue;
168
+ }
169
+
170
+ const outIdx = key.indexOf('.out.');
171
+ if (outIdx > 0) {
172
+ const targetNodeId = key.substring(0, outIdx);
173
+ const pinName = key.substring(outIdx + 5);
174
+ this._inputOverrides.set(`${targetNodeId}:${pinName}`, value);
175
+ continue;
176
+ }
177
+
178
+ const inIdx = key.indexOf('.in.');
179
+ if (inIdx > 0) {
180
+ const targetNodeId = key.substring(0, inIdx);
181
+ const pinName = key.substring(inIdx + 4);
182
+ this._inputOverrides.set(`${targetNodeId}:${pinName}`, value);
183
+ continue;
184
+ }
185
+
186
+ this._inputOverrides.set(`${node.id}:${key}`, value);
187
+ if (!node.data) node.data = {};
188
+ node.data[key] = value;
189
+ }
190
+ }
191
+
192
+ getInputOverride(nodeId, pinId) {
193
+ if (!this._inputOverrides) return undefined;
194
+ const k = `${nodeId}:${pinId}`;
195
+ return this._inputOverrides.has(k) ? this._inputOverrides.get(k) : undefined;
196
+ }
197
+
198
+ isNodeVolatile(node, activeGraph) {
199
+ return GraphDebugHandler.checkVolatility(node, activeGraph);
200
+ }
201
+
202
+ static checkVolatility(node, activeGraph, visited = new Set(), depth = 0) {
203
+ if (!node) return false;
204
+
205
+ if (depth > MAX_RECURSION_DEPTH) {
206
+ console.warn(`[GraphDebugHandler] isNodeVolatile reached max recursion (${MAX_RECURSION_DEPTH})`);
207
+ return false;
208
+ }
209
+
210
+ if (visited.has(node.id)) return false;
211
+ visited.add(node.id);
212
+
213
+ if (node.type === 'data:get_variable') return true;
214
+
215
+ if (!activeGraph || !activeGraph.connections) return false;
216
+
217
+ const connections = activeGraph.connections.filter(c => c.targetNodeId === node.id);
218
+ for (const conn of connections) {
219
+ const sourceNode = activeGraph.nodes.find(n => n.id === conn.sourceNodeId);
220
+ if (GraphDebugHandler.checkVolatility(sourceNode, activeGraph, visited, depth + 1)) {
221
+ return true;
222
+ }
223
+ }
224
+
225
+ return false;
226
+ }
227
+ }
228
+
229
+ module.exports = GraphDebugHandler;
@@ -0,0 +1,117 @@
1
+ const debugConfig = require('../config/debug.config');
2
+
3
+ const pendingDebugRequests = new Map();
4
+
5
+ function handleDebugResponse(message) {
6
+ const { requestId, overrides } = message;
7
+ const resolve = pendingDebugRequests.get(requestId);
8
+
9
+ if (resolve) {
10
+ const timeoutId = pendingDebugRequests.get(`${requestId}_timeout`);
11
+ if (timeoutId) {
12
+ clearTimeout(timeoutId);
13
+ pendingDebugRequests.delete(`${requestId}_timeout`);
14
+ }
15
+
16
+ pendingDebugRequests.delete(requestId);
17
+ resolve(overrides);
18
+ }
19
+ }
20
+
21
+ function attachDebugIpcHandler() {
22
+ if (process.on && !attachDebugIpcHandler._attached) {
23
+ process.on('message', (message) => {
24
+ if (message.type === 'debug:breakpoint_response' || message.type === 'debug:step_response') {
25
+ handleDebugResponse(message);
26
+ }
27
+ });
28
+ attachDebugIpcHandler._attached = true;
29
+ }
30
+ }
31
+
32
+ async function checkBreakpointViaIpc(node, context, captureNodeInputs, currentTraceId, traceCollector) {
33
+ const { randomUUID } = require('crypto');
34
+ const requestId = randomUUID();
35
+
36
+ const inputs = await captureNodeInputs(node);
37
+ const executedSteps = currentTraceId
38
+ ? await traceCollector.getTrace(currentTraceId)
39
+ : null;
40
+
41
+ process.send({
42
+ type: 'debug:check_breakpoint',
43
+ requestId,
44
+ payload: {
45
+ graphId: context.graphId,
46
+ nodeId: node.id,
47
+ nodeType: node.type,
48
+ inputs,
49
+ executedSteps,
50
+ context: {
51
+ user: context.user,
52
+ variables: context.variables,
53
+ commandArguments: context.commandArguments,
54
+ }
55
+ }
56
+ });
57
+
58
+ return new Promise((resolve) => {
59
+ pendingDebugRequests.set(requestId, resolve);
60
+
61
+ const timeoutId = setTimeout(() => {
62
+ if (pendingDebugRequests.has(requestId)) {
63
+ pendingDebugRequests.delete(requestId);
64
+ resolve(null);
65
+ }
66
+ }, debugConfig.BREAKPOINT_TIMEOUT);
67
+
68
+ pendingDebugRequests.set(`${requestId}_timeout`, timeoutId);
69
+ });
70
+ }
71
+
72
+ async function checkStepModeViaIpc(node, context, captureNodeInputs, currentTraceId, traceCollector) {
73
+ const { randomUUID } = require('crypto');
74
+ const requestId = randomUUID();
75
+
76
+ const inputs = await captureNodeInputs(node);
77
+ const executedSteps = currentTraceId
78
+ ? await traceCollector.getTrace(currentTraceId)
79
+ : null;
80
+
81
+ process.send({
82
+ type: 'debug:check_step_mode',
83
+ requestId,
84
+ payload: {
85
+ graphId: context.graphId,
86
+ nodeId: node.id,
87
+ nodeType: node.type,
88
+ inputs,
89
+ executedSteps,
90
+ context: {
91
+ user: context.user,
92
+ variables: context.variables,
93
+ commandArguments: context.commandArguments,
94
+ }
95
+ }
96
+ });
97
+
98
+ return new Promise((resolve) => {
99
+ pendingDebugRequests.set(requestId, resolve);
100
+
101
+ const timeoutId = setTimeout(() => {
102
+ if (pendingDebugRequests.has(requestId)) {
103
+ pendingDebugRequests.delete(requestId);
104
+ resolve(null);
105
+ }
106
+ }, debugConfig.STEP_MODE_TIMEOUT);
107
+
108
+ pendingDebugRequests.set(`${requestId}_timeout`, timeoutId);
109
+ });
110
+ }
111
+
112
+ module.exports = {
113
+ attachDebugIpcHandler,
114
+ checkBreakpointViaIpc,
115
+ checkStepModeViaIpc,
116
+ pendingDebugRequests
117
+ };