blockmine 1.22.0 → 1.23.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 (108) hide show
  1. package/.claude/agents/code-architect.md +34 -0
  2. package/.claude/agents/code-explorer.md +51 -0
  3. package/.claude/agents/code-reviewer.md +46 -0
  4. package/.claude/commands/feature-dev.md +125 -0
  5. package/.claude/settings.json +5 -1
  6. package/.claude/settings.local.json +12 -1
  7. package/.claude/skills/frontend-design/SKILL.md +42 -0
  8. package/CHANGELOG.md +32 -1
  9. package/README.md +302 -152
  10. package/backend/package-lock.json +681 -9
  11. package/backend/package.json +8 -0
  12. package/backend/prisma/migrations/20251116111851_add_execution_trace/migration.sql +22 -0
  13. package/backend/prisma/migrations/20251120154914_add_panel_api_keys/migration.sql +21 -0
  14. package/backend/prisma/migrations/20251121110241_add_proxy_table/migration.sql +45 -0
  15. package/backend/prisma/schema.prisma +70 -1
  16. package/backend/src/__tests__/services/BotLifecycleService.test.js +9 -4
  17. package/backend/src/ai/plugin-assistant-system-prompt.md +788 -0
  18. package/backend/src/api/middleware/auth.js +27 -0
  19. package/backend/src/api/middleware/botAccess.js +7 -3
  20. package/backend/src/api/middleware/panelApiAuth.js +135 -0
  21. package/backend/src/api/routes/aiAssistant.js +995 -0
  22. package/backend/src/api/routes/auth.js +90 -54
  23. package/backend/src/api/routes/botCommands.js +107 -0
  24. package/backend/src/api/routes/botGroups.js +165 -0
  25. package/backend/src/api/routes/botHistory.js +108 -0
  26. package/backend/src/api/routes/botPermissions.js +99 -0
  27. package/backend/src/api/routes/botStatus.js +36 -0
  28. package/backend/src/api/routes/botUsers.js +162 -0
  29. package/backend/src/api/routes/bots.js +108 -59
  30. package/backend/src/api/routes/eventGraphs.js +4 -1
  31. package/backend/src/api/routes/logs.js +13 -3
  32. package/backend/src/api/routes/panel.js +3 -3
  33. package/backend/src/api/routes/panelApiKeys.js +179 -0
  34. package/backend/src/api/routes/pluginIde.js +1715 -135
  35. package/backend/src/api/routes/plugins.js +170 -13
  36. package/backend/src/api/routes/proxies.js +130 -0
  37. package/backend/src/api/routes/search.js +4 -0
  38. package/backend/src/api/routes/servers.js +20 -3
  39. package/backend/src/api/routes/settings.js +5 -0
  40. package/backend/src/api/routes/system.js +3 -3
  41. package/backend/src/api/routes/traces.js +131 -0
  42. package/backend/src/config/debug.config.js +36 -0
  43. package/backend/src/core/BotHistoryStore.js +180 -0
  44. package/backend/src/core/BotManager.js +14 -4
  45. package/backend/src/core/BotProcess.js +1517 -1092
  46. package/backend/src/core/EventGraphManager.js +194 -280
  47. package/backend/src/core/GraphExecutionEngine.js +1004 -321
  48. package/backend/src/core/MessageQueue.js +12 -6
  49. package/backend/src/core/PluginLoader.js +99 -5
  50. package/backend/src/core/PluginManager.js +74 -13
  51. package/backend/src/core/TaskScheduler.js +1 -1
  52. package/backend/src/core/commands/whois.js +1 -1
  53. package/backend/src/core/node-registries/actions.js +72 -2
  54. package/backend/src/core/node-registries/arrays.js +18 -0
  55. package/backend/src/core/node-registries/data.js +1 -1
  56. package/backend/src/core/node-registries/events.js +14 -0
  57. package/backend/src/core/node-registries/logic.js +17 -0
  58. package/backend/src/core/node-registries/strings.js +34 -0
  59. package/backend/src/core/node-registries/type.js +25 -0
  60. package/backend/src/core/nodes/actions/bot_look_at.js +1 -1
  61. package/backend/src/core/nodes/actions/create_command.js +189 -0
  62. package/backend/src/core/nodes/actions/delete_command.js +92 -0
  63. package/backend/src/core/nodes/actions/http_request.js +23 -4
  64. package/backend/src/core/nodes/actions/send_message.js +2 -12
  65. package/backend/src/core/nodes/actions/update_command.js +133 -0
  66. package/backend/src/core/nodes/arrays/join.js +28 -0
  67. package/backend/src/core/nodes/data/cast.js +2 -1
  68. package/backend/src/core/nodes/data/string_literal.js +2 -13
  69. package/backend/src/core/nodes/logic/not.js +22 -0
  70. package/backend/src/core/nodes/strings/starts_with.js +1 -1
  71. package/backend/src/core/nodes/strings/to_lower.js +22 -0
  72. package/backend/src/core/nodes/strings/to_upper.js +22 -0
  73. package/backend/src/core/nodes/type/to_string.js +32 -0
  74. package/backend/src/core/services/BotLifecycleService.js +835 -596
  75. package/backend/src/core/services/CommandExecutionService.js +430 -351
  76. package/backend/src/core/services/DebugSessionManager.js +347 -0
  77. package/backend/src/core/services/GraphCollaborationManager.js +501 -0
  78. package/backend/src/core/services/MinecraftBotManager.js +259 -0
  79. package/backend/src/core/services/MinecraftViewerService.js +216 -0
  80. package/backend/src/core/services/TraceCollectorService.js +545 -0
  81. package/backend/src/core/system/RuntimeCommandRegistry.js +116 -0
  82. package/backend/src/core/system/Transport.js +0 -4
  83. package/backend/src/core/validation/nodeSchemas.js +6 -6
  84. package/backend/src/real-time/botApi/handlers/graphHandlers.js +2 -2
  85. package/backend/src/real-time/botApi/handlers/graphWebSocketHandlers.js +1 -1
  86. package/backend/src/real-time/botApi/utils.js +11 -0
  87. package/backend/src/real-time/panelNamespace.js +387 -0
  88. package/backend/src/real-time/presence.js +7 -2
  89. package/backend/src/real-time/socketHandler.js +395 -4
  90. package/backend/src/server.js +18 -0
  91. package/frontend/dist/assets/index-DqzDkFsP.js +11210 -0
  92. package/frontend/dist/assets/index-t6K1u4OV.css +32 -0
  93. package/frontend/dist/index.html +2 -2
  94. package/frontend/package-lock.json +9437 -0
  95. package/frontend/package.json +8 -0
  96. package/package.json +2 -2
  97. package/screen/console.png +0 -0
  98. package/screen/dashboard.png +0 -0
  99. package/screen/graph_collabe.png +0 -0
  100. package/screen/graph_live_debug.png +0 -0
  101. package/screen/management_command.png +0 -0
  102. package/screen/node_debug_trace.png +0 -0
  103. package/screen/plugin_/320/276/320/261/320/267/320/276/321/200.png +0 -0
  104. package/screen/websocket.png +0 -0
  105. 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
  106. 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
  107. package/frontend/dist/assets/index-CfTo92bP.css +0 -1
  108. package/frontend/dist/assets/index-CiFD5X9Z.js +0 -8344
@@ -4,8 +4,18 @@ const config = require('../config');
4
4
  const { botManager } = require('../core/services');
5
5
  const presence = require('./presence');
6
6
  const { initializeBotApiNamespace } = require('./botApi');
7
+ const { initializePanelNamespace, broadcastToPanelNamespace } = require('./panelNamespace');
8
+ const { getTraceCollector } = require('../core/services/TraceCollectorService');
9
+ const { initializeDebugManager, getGlobalDebugManager } = require('../core/services/DebugSessionManager');
10
+ const { initializeCollaborationManager, getGlobalCollaborationManager } = require('../core/services/GraphCollaborationManager');
11
+ const MinecraftViewerService = require('../core/services/MinecraftViewerService');
7
12
 
8
13
  let io;
14
+ let minecraftViewerService;
15
+
16
+ // Буфер логов для каждого плагина (последние 100 логов)
17
+ const pluginLogsBuffer = new Map(); // key: 'botId:pluginName', value: array of logs
18
+ const MAX_LOGS_PER_PLUGIN = 100;
9
19
 
10
20
  function initializeSocket(httpServer) {
11
21
  const corsOptions = {
@@ -19,22 +29,376 @@ function initializeSocket(httpServer) {
19
29
  transports: ['websocket', 'polling']
20
30
  });
21
31
 
22
- // Инициализируем /bot-api namespace для WebSocket API
32
+ // Инициализируем TraceCollector с Socket.IO
33
+ const traceCollector = getTraceCollector();
34
+ traceCollector.setSocketIO(io);
35
+
36
+ initializeDebugManager(io);
37
+ initializeCollaborationManager(io);
38
+
39
+ // Инициализируем Panel WebSocket namespace
40
+ initializePanelNamespace(io);
41
+
23
42
  initializeBotApiNamespace(io);
24
43
 
44
+ // Инициализируем Minecraft Viewer Service
45
+ const logger = {
46
+ debug: (...args) => console.log('[DEBUG]', ...args),
47
+ info: (...args) => console.log('[INFO]', ...args),
48
+ warn: (...args) => console.warn('[WARN]', ...args),
49
+ error: (...args) => console.error('[ERROR]', ...args),
50
+ };
51
+
52
+ minecraftViewerService = new MinecraftViewerService({
53
+ io,
54
+ botProcessManager: botManager.processManager,
55
+ logger
56
+ });
57
+
25
58
  io.on('connection', (socket) => {
59
+ // Сохраняем decoded информацию о пользователе из токена
60
+ const token = socket.handshake?.auth?.token;
61
+ if (token) {
62
+ const jwt = require('jsonwebtoken');
63
+ const config = require('../config');
64
+ try {
65
+ socket.decoded = jwt.verify(token, config.security.jwtSecret, { algorithms: ['HS256'] });
66
+ } catch (e) {
67
+ console.warn('[Socket] Failed to decode token:', e.message);
68
+ }
69
+ }
70
+
26
71
  presence.handleConnection(io, socket);
27
72
 
28
73
  socket.on('disconnect', () => {
29
74
  botManager.handleSocketDisconnect(socket);
75
+
76
+ // Удаляем пользователя из всех debug комнат
77
+ const debugManager = getGlobalDebugManager();
78
+ for (const [graphId, debugState] of debugManager.graphDebugStates) {
79
+ if (debugState.connectedUsers.has(socket.id)) {
80
+ debugState.removeUser(socket.id);
81
+ const room = debugState.getRoomName();
82
+ io.to(room).emit('debug:user-left', {
83
+ userCount: debugState.connectedUsers.size,
84
+ users: Array.from(debugState.connectedUsers.values())
85
+ });
86
+ }
87
+ }
30
88
  });
31
89
 
32
90
  socket.on('plugin:ui:subscribe', ({ botId, pluginName }) => {
33
91
  botManager.subscribeToPluginUi(botId, pluginName, socket);
34
92
  });
35
93
 
36
- socket.on('plugin:ui:unsubscribe', ({ botId, pluginName }) => {
37
- botManager.unsubscribeFromPluginUi(botId, pluginName, socket);
94
+ socket.on('debug:join', ({ botId, graphId }) => {
95
+ try {
96
+ const debugManager = getGlobalDebugManager();
97
+ const username = socket.decoded?.username || 'Anonymous';
98
+ const userId = socket.decoded?.userId || null;
99
+
100
+ console.log(`[Debug] User ${username} joining debug session for graph ${graphId} (bot ${botId})`);
101
+
102
+ const debugState = debugManager.getOrCreate(botId, graphId);
103
+
104
+ debugState.addUser(socket.id, { userId, username, socketId: socket.id });
105
+
106
+ const room = debugState.getRoomName();
107
+ socket.join(room);
108
+
109
+ socket.emit('debug:state', {
110
+ breakpoints: Array.from(debugState.breakpoints.entries()).map(([nodeId, bp]) => ({
111
+ nodeId,
112
+ enabled: bp.enabled,
113
+ condition: bp.condition
114
+ })),
115
+ connectedUsers: Array.from(debugState.connectedUsers.values())
116
+ });
117
+
118
+
119
+ socket.to(room).emit('debug:user-joined', {
120
+ username,
121
+ socketId: socket.id,
122
+ userCount: debugState.connectedUsers.size
123
+ });
124
+
125
+ } catch (error) {
126
+ console.error('[Debug] Error joining debug session:', error);
127
+ socket.emit('debug:error', { message: 'Failed to join debug session' });
128
+ }
129
+ });
130
+
131
+ socket.on('debug:leave', ({ botId, graphId }) => {
132
+ const debugManager = getGlobalDebugManager();
133
+ const debugState = debugManager.get(graphId);
134
+
135
+ if (!debugState) {
136
+ return;
137
+ }
138
+
139
+ const room = debugState.getRoomName();
140
+ debugState.removeUser(socket.id);
141
+
142
+ // Если это был последний пользователь - очищаем breakpoints
143
+ if (debugState.connectedUsers.size === 0) {
144
+ debugState.clearAllBreakpoints();
145
+
146
+ // Если есть активное выполнение на паузе - останавливаем его
147
+ if (debugState.activeExecution) {
148
+ debugState.stop();
149
+ }
150
+ }
151
+
152
+ socket.leave(room);
153
+
154
+ socket.to(room).emit('debug:user-left', {
155
+ userCount: debugState.connectedUsers.size,
156
+ users: Array.from(debugState.connectedUsers.values())
157
+ });
158
+ });
159
+
160
+ socket.on('debug:set-breakpoint', ({ graphId, nodeId, condition }) => {
161
+ const debugManager = getGlobalDebugManager();
162
+ const debugState = debugManager.get(graphId);
163
+ if (!debugState) {
164
+ return;
165
+ }
166
+
167
+ debugState.addBreakpoint(nodeId, condition, socket.id);
168
+ });
169
+
170
+ socket.on('debug:remove-breakpoint', ({ graphId, nodeId }) => {
171
+ const debugManager = getGlobalDebugManager();
172
+ const debugState = debugManager.get(graphId);
173
+ if (!debugState) {
174
+ return;
175
+ }
176
+
177
+ debugState.removeBreakpoint(nodeId);
178
+ });
179
+
180
+ socket.on('debug:toggle-breakpoint', ({ graphId, nodeId, enabled }) => {
181
+ const debugManager = getGlobalDebugManager();
182
+ const debugState = debugManager.get(graphId);
183
+ if (!debugState) {
184
+ return;
185
+ }
186
+
187
+ debugState.toggleBreakpoint(nodeId, enabled);
188
+ });
189
+
190
+ socket.on('debug:continue', ({ sessionId, overrides, stepMode }) => {
191
+ const debugManager = getGlobalDebugManager();
192
+ const debugState = debugManager.getBySessionId(sessionId);
193
+ if (!debugState) {
194
+ return;
195
+ }
196
+
197
+ debugState.resume(overrides, stepMode || false);
198
+ });
199
+
200
+ socket.on('debug:stop', ({ sessionId }) => {
201
+ const debugManager = getGlobalDebugManager();
202
+ const debugState = debugManager.getBySessionId(sessionId);
203
+ if (!debugState) {
204
+ return;
205
+ }
206
+
207
+ debugState.stop();
208
+ });
209
+
210
+ socket.on('debug:update-value', ({ botId, graphId, key, value }) => {
211
+ const debugManager = getGlobalDebugManager();
212
+ const debugState = debugManager.get(graphId);
213
+ if (!debugState) {
214
+ return;
215
+ }
216
+
217
+ console.log(`[Debug] Value updated by ${socket.decoded?.username || 'Unknown'}: ${key} =`, value);
218
+
219
+ // Сохраняем изменение в pendingOverrides
220
+ debugState.setValue(key, value);
221
+
222
+ // Транслируем изменение всем подключенным пользователям
223
+ debugState.broadcast('debug:value-updated', {
224
+ key,
225
+ value,
226
+ updatedBy: socket.decoded?.username || 'Unknown'
227
+ });
228
+ });
229
+
230
+ // Hot reload графов при сохранении
231
+ socket.on('graph:updated', async ({ botId, graphId }) => {
232
+
233
+ try {
234
+ const eventGraphManager = botManager.eventGraphManager;
235
+
236
+ if (eventGraphManager) {
237
+ // Перезагружаем графы для бота
238
+ await eventGraphManager.loadGraphsForBot(botId);
239
+
240
+
241
+ // Уведомляем всех пользователей о перезагрузке через collaboration manager
242
+ const collabManager = getGlobalCollaborationManager();
243
+ collabManager.broadcastGraphReloaded(botId, graphId);
244
+ } else {
245
+ console.warn(`[Graph Hot Reload] EventGraphManager not found!`);
246
+ }
247
+ } catch (error) {
248
+ console.error(`[Graph Hot Reload] Error reloading graphs for bot ${botId}:`, error);
249
+ }
250
+ });
251
+
252
+ // ========== COLLABORATIVE EDITING EVENTS ==========
253
+
254
+ // Присоединение к графу для совместного редактирования
255
+ socket.on('collab:join', ({ botId, graphId, debugMode }) => {
256
+ try {
257
+ const collabManager = getGlobalCollaborationManager();
258
+ const username = socket.decoded?.username || 'Anonymous';
259
+ const userId = socket.decoded?.userId || null;
260
+
261
+ collabManager.joinGraph(socket, { botId, graphId, username, userId, debugMode });
262
+ } catch (error) {
263
+ console.error('[Collab] Error joining graph:', error);
264
+ }
265
+ });
266
+
267
+ // Покидание графа
268
+ socket.on('collab:leave', ({ botId, graphId }) => {
269
+ try {
270
+ const collabManager = getGlobalCollaborationManager();
271
+ collabManager.leaveGraph(socket, { botId, graphId });
272
+ } catch (error) {
273
+ console.error('[Collab] Error leaving graph:', error);
274
+ }
275
+ });
276
+
277
+ // Обновление позиции курсора
278
+ socket.on('collab:cursor', ({ botId, graphId, x, y }) => {
279
+ try {
280
+ const collabManager = getGlobalCollaborationManager();
281
+ collabManager.updateCursor(socket, { botId, graphId, x, y });
282
+ } catch (error) {
283
+ console.error('[Collab] Error updating cursor:', error);
284
+ }
285
+ });
286
+
287
+ // Обновление выбранных нод
288
+ socket.on('collab:selection', ({ botId, graphId, nodeIds }) => {
289
+ try {
290
+ const collabManager = getGlobalCollaborationManager();
291
+ collabManager.updateSelectedNodes(socket, { botId, graphId, nodeIds });
292
+ } catch (error) {
293
+ console.error('[Collab] Error updating selection:', error);
294
+ }
295
+ });
296
+
297
+ // Изменение режима отладки
298
+ socket.on('collab:mode-change', ({ botId, graphId, debugMode }) => {
299
+ try {
300
+ const collabManager = getGlobalCollaborationManager();
301
+ collabManager.updateDebugMode(socket, { botId, graphId, debugMode });
302
+ } catch (error) {
303
+ console.error('[Collab] Error updating debug mode:', error);
304
+ }
305
+ });
306
+
307
+ // Инициализация состояния графа (вызывается первым пользователем после загрузки)
308
+ socket.on('collab:init-graph-state', ({ botId, graphId, nodes, edges }) => {
309
+ try {
310
+ const collabManager = getGlobalCollaborationManager();
311
+ collabManager.initializeGraphState(socket, { botId, graphId, nodes, edges });
312
+ } catch (error) {
313
+ console.error('[Collab] Error initializing graph state:', error);
314
+ }
315
+ });
316
+
317
+ // Изменение нод (движение, создание, удаление, обновление)
318
+ socket.on('collab:nodes', ({ botId, graphId, type, data }) => {
319
+ try {
320
+ const collabManager = getGlobalCollaborationManager();
321
+ collabManager.broadcastNodeChange(socket, { botId, graphId, type, data });
322
+ } catch (error) {
323
+ console.error('[Collab] Error broadcasting node change:', error);
324
+ }
325
+ });
326
+
327
+ // Изменение связей (создание, удаление)
328
+ socket.on('collab:edges', ({ botId, graphId, type, data }) => {
329
+ try {
330
+ const collabManager = getGlobalCollaborationManager();
331
+ collabManager.broadcastEdgeChange(socket, { botId, graphId, type, data });
332
+ } catch (error) {
333
+ console.error('[Collab] Error broadcasting edge change:', error);
334
+ }
335
+ });
336
+
337
+ // Начало создания соединения (пользователь начал тянуть линию)
338
+ socket.on('collab:connection-start', ({ botId, graphId, fromX, fromY, fromNodeId, fromHandleId }) => {
339
+ try {
340
+ const collabManager = getGlobalCollaborationManager();
341
+ collabManager.startConnection(socket, { botId, graphId, fromX, fromY, fromNodeId, fromHandleId });
342
+ } catch (error) {
343
+ console.error('[Collab] Error starting connection:', error);
344
+ }
345
+ });
346
+
347
+ // Обновление позиции соединения (пользователь двигает мышью с зажатой линией)
348
+ socket.on('collab:connection-update', ({ botId, graphId, toX, toY }) => {
349
+ try {
350
+ const collabManager = getGlobalCollaborationManager();
351
+ collabManager.updateConnection(socket, { botId, graphId, toX, toY });
352
+ } catch (error) {
353
+ console.error('[Collab] Error updating connection:', error);
354
+ }
355
+ });
356
+
357
+ // Завершение создания соединения (пользователь отпустил линию)
358
+ socket.on('collab:connection-end', ({ botId, graphId }) => {
359
+ try {
360
+ const collabManager = getGlobalCollaborationManager();
361
+ collabManager.endConnection(socket, { botId, graphId });
362
+ } catch (error) {
363
+ console.error('[Collab] Error ending connection:', error);
364
+ }
365
+ });
366
+
367
+ // Plugin Logs - подписка на логи плагина
368
+ socket.on('subscribe-plugin-logs', ({ botId, pluginName }) => {
369
+ const room = `plugin-logs:${botId}:${pluginName}`;
370
+ socket.join(room);
371
+
372
+ // Отправляем буфер логов при подключении (одним массивом)
373
+ const bufferKey = `${botId}:${pluginName}`;
374
+ const bufferedLogs = pluginLogsBuffer.get(bufferKey) || [];
375
+
376
+ // Отправляем буфер отдельным событием, чтобы фронтенд мог сбросить state
377
+ socket.emit('plugin-logs-buffer', bufferedLogs);
378
+ });
379
+
380
+ // Plugin Logs - отписка от логов плагина
381
+ socket.on('unsubscribe-plugin-logs', ({ botId, pluginName }) => {
382
+ const room = `plugin-logs:${botId}:${pluginName}`;
383
+ socket.leave(room);
384
+ });
385
+
386
+ // Plugin Logs - очистка буфера логов плагина
387
+ socket.on('clear-plugin-logs', ({ botId, pluginName }) => {
388
+ const bufferKey = `${botId}:${pluginName}`;
389
+ pluginLogsBuffer.delete(bufferKey);
390
+ });
391
+
392
+ // При отключении удаляем пользователя из всех комнат
393
+ socket.on('disconnect', () => {
394
+ try {
395
+ const collabManager = getGlobalCollaborationManager();
396
+ collabManager.removeUserFromAllRooms(socket);
397
+ } catch (error) {
398
+ if (error.message !== 'GraphCollaborationManager not initialized! Call initializeCollaborationManager(io) first.') {
399
+ console.error('[Collab] Error on disconnect:', error);
400
+ }
401
+ }
38
402
  });
39
403
  });
40
404
 
@@ -48,4 +412,31 @@ function getIO() {
48
412
  return io;
49
413
  }
50
414
 
51
- module.exports = { initializeSocket, getIO };
415
+ function getIOSafe() {
416
+ if (!io) {
417
+ return {
418
+ emit: () => {},
419
+ to: () => ({ emit: () => {} }),
420
+ on: () => {},
421
+ off: () => {},
422
+ };
423
+ }
424
+ return io;
425
+ }
426
+
427
+ function addPluginLogToBuffer(botId, pluginName, logEntry) {
428
+ const bufferKey = `${botId}:${pluginName}`;
429
+
430
+ if (!pluginLogsBuffer.has(bufferKey)) {
431
+ pluginLogsBuffer.set(bufferKey, []);
432
+ }
433
+
434
+ const buffer = pluginLogsBuffer.get(bufferKey);
435
+ buffer.push(logEntry);
436
+
437
+ if (buffer.length > MAX_LOGS_PER_PLUGIN) {
438
+ buffer.shift();
439
+ }
440
+ }
441
+
442
+ module.exports = { initializeSocket, getIO, getIOSafe, addPluginLogToBuffer, broadcastToPanelNamespace };
@@ -12,9 +12,11 @@ const { botManager, pluginManager } = require('./core/services');
12
12
  const botRoutes = require('./api/routes/bots');
13
13
  const pluginRoutes = require('./api/routes/plugins');
14
14
  const serverRoutes = require('./api/routes/servers');
15
+ const proxiesRoutes = require('./api/routes/proxies');
15
16
  const permissionsRoutes = require('./api/routes/permissions');
16
17
  const taskRoutes = require('./api/routes/tasks');
17
18
  const { router: authRoutes, ALL_PERMISSIONS, VIEWER_PERMISSIONS } = require('./api/routes/auth');
19
+ const panelApiKeysRoutes = require('./api/routes/panelApiKeys');
18
20
  const searchRoutes = require('./api/routes/search');
19
21
  const eventGraphsRouter = require('./api/routes/eventGraphs');
20
22
  const TaskScheduler = require('./core/TaskScheduler');
@@ -22,6 +24,13 @@ const panelRoutes = require('./api/routes/panel');
22
24
  const changelogRoutes = require('./api/routes/changelog');
23
25
  const logsRoutes = require('./api/routes/logs');
24
26
  const systemRoutes = require('./api/routes/system');
27
+ const tracesRoutes = require('./api/routes/traces');
28
+ const botHistoryRoutes = require('./api/routes/botHistory');
29
+ const botUsersRoutes = require('./api/routes/botUsers');
30
+ const botCommandsRoutes = require('./api/routes/botCommands');
31
+ const botGroupsRoutes = require('./api/routes/botGroups');
32
+ const botPermissionsRoutes = require('./api/routes/botPermissions');
33
+ const botStatusRoutes = require('./api/routes/botStatus');
25
34
 
26
35
  const app = express();
27
36
  const server = http.createServer(app);
@@ -41,6 +50,7 @@ const frontendPath = path.resolve(__dirname, '..', '..', 'frontend', 'dist');
41
50
  const rootPath = path.resolve(__dirname, '..', '..');
42
51
 
43
52
  app.use('/api/auth', authRoutes);
53
+ app.use('/api/panel/api-keys', panelApiKeysRoutes);
44
54
 
45
55
  app.use('/api/version', (req, res, next) => {
46
56
  async function getVersion() {
@@ -57,15 +67,23 @@ app.use('/api/version', (req, res, next) => {
57
67
  getVersion();
58
68
  });
59
69
  app.use('/api/tasks', taskRoutes);
70
+ app.use('/api/bots', botUsersRoutes);
71
+ app.use('/api/bots', botCommandsRoutes);
72
+ app.use('/api/bots', botGroupsRoutes);
73
+ app.use('/api/bots', botPermissionsRoutes);
74
+ app.use('/api/bots', botStatusRoutes);
60
75
  app.use('/api/bots', botRoutes);
76
+ app.use('/api/bot-history', botHistoryRoutes);
61
77
  app.use('/api/plugins', pluginRoutes);
62
78
  app.use('/api/servers', serverRoutes);
79
+ app.use('/api/proxies', proxiesRoutes);
63
80
  app.use('/api/permissions', permissionsRoutes);
64
81
  app.use('/api/search', searchRoutes);
65
82
  app.use('/api/panel', panelRoutes);
66
83
  app.use('/api/changelog', changelogRoutes);
67
84
  app.use('/api/logs', logsRoutes);
68
85
  app.use('/api/system', systemRoutes);
86
+ app.use('/api/traces', tracesRoutes);
69
87
 
70
88
  app.use(express.static(frontendPath));
71
89