blockmine 1.22.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.
- package/.claude/settings.json +5 -1
- package/.claude/settings.local.json +10 -1
- package/CHANGELOG.md +27 -3
- package/CLAUDE.md +284 -0
- package/README.md +302 -152
- package/backend/package-lock.json +681 -9
- package/backend/package.json +8 -0
- package/backend/prisma/migrations/20251116111851_add_execution_trace/migration.sql +22 -0
- package/backend/prisma/migrations/20251120154914_add_panel_api_keys/migration.sql +21 -0
- package/backend/prisma/migrations/20251121110241_add_proxy_table/migration.sql +45 -0
- package/backend/prisma/migrations/migration_lock.toml +2 -2
- package/backend/prisma/schema.prisma +70 -1
- package/backend/src/__tests__/services/BotLifecycleService.test.js +9 -4
- package/backend/src/ai/plugin-assistant-system-prompt.md +788 -0
- package/backend/src/api/middleware/auth.js +27 -0
- package/backend/src/api/middleware/botAccess.js +7 -3
- package/backend/src/api/middleware/panelApiAuth.js +135 -0
- package/backend/src/api/routes/aiAssistant.js +995 -0
- package/backend/src/api/routes/auth.js +669 -633
- package/backend/src/api/routes/botCommands.js +107 -0
- package/backend/src/api/routes/botGroups.js +165 -0
- package/backend/src/api/routes/botHistory.js +108 -0
- package/backend/src/api/routes/botPermissions.js +99 -0
- package/backend/src/api/routes/botStatus.js +36 -0
- package/backend/src/api/routes/botUsers.js +162 -0
- package/backend/src/api/routes/bots.js +2451 -2402
- package/backend/src/api/routes/eventGraphs.js +4 -1
- package/backend/src/api/routes/logs.js +13 -3
- package/backend/src/api/routes/panel.js +66 -66
- package/backend/src/api/routes/panelApiKeys.js +179 -0
- package/backend/src/api/routes/pluginIde.js +1715 -135
- package/backend/src/api/routes/plugins.js +376 -219
- package/backend/src/api/routes/proxies.js +130 -0
- package/backend/src/api/routes/search.js +4 -0
- package/backend/src/api/routes/servers.js +20 -3
- package/backend/src/api/routes/settings.js +5 -0
- package/backend/src/api/routes/system.js +174 -174
- package/backend/src/api/routes/traces.js +131 -0
- package/backend/src/config/debug.config.js +36 -0
- package/backend/src/core/BotHistoryStore.js +180 -0
- package/backend/src/core/BotManager.js +14 -4
- package/backend/src/core/BotProcess.js +1517 -1092
- package/backend/src/core/EventGraphManager.js +37 -123
- package/backend/src/core/GraphExecutionEngine.js +977 -321
- package/backend/src/core/MessageQueue.js +12 -6
- package/backend/src/core/PluginLoader.js +99 -5
- package/backend/src/core/PluginManager.js +74 -13
- package/backend/src/core/TaskScheduler.js +1 -1
- package/backend/src/core/commands/whois.js +1 -1
- package/backend/src/core/node-registries/actions.js +70 -0
- package/backend/src/core/node-registries/arrays.js +18 -0
- package/backend/src/core/node-registries/data.js +1 -1
- package/backend/src/core/node-registries/events.js +14 -0
- package/backend/src/core/node-registries/logic.js +17 -0
- package/backend/src/core/node-registries/strings.js +34 -0
- package/backend/src/core/node-registries/type.js +25 -0
- package/backend/src/core/nodes/actions/bot_look_at.js +1 -1
- package/backend/src/core/nodes/actions/create_command.js +189 -0
- package/backend/src/core/nodes/actions/delete_command.js +92 -0
- package/backend/src/core/nodes/actions/update_command.js +133 -0
- package/backend/src/core/nodes/arrays/join.js +28 -0
- package/backend/src/core/nodes/data/cast.js +2 -1
- package/backend/src/core/nodes/logic/not.js +22 -0
- package/backend/src/core/nodes/strings/starts_with.js +1 -1
- package/backend/src/core/nodes/strings/to_lower.js +22 -0
- package/backend/src/core/nodes/strings/to_upper.js +22 -0
- package/backend/src/core/nodes/type/to_string.js +32 -0
- package/backend/src/core/services/BotLifecycleService.js +255 -16
- package/backend/src/core/services/CommandExecutionService.js +430 -351
- package/backend/src/core/services/DebugSessionManager.js +347 -0
- package/backend/src/core/services/GraphCollaborationManager.js +501 -0
- package/backend/src/core/services/MinecraftBotManager.js +259 -0
- package/backend/src/core/services/MinecraftViewerService.js +216 -0
- package/backend/src/core/services/TraceCollectorService.js +545 -0
- package/backend/src/core/system/RuntimeCommandRegistry.js +116 -0
- package/backend/src/core/system/Transport.js +0 -4
- package/backend/src/core/validation/nodeSchemas.js +6 -6
- package/backend/src/real-time/botApi/handlers/graphHandlers.js +2 -2
- package/backend/src/real-time/botApi/handlers/graphWebSocketHandlers.js +1 -1
- package/backend/src/real-time/botApi/utils.js +11 -0
- package/backend/src/real-time/panelNamespace.js +387 -0
- package/backend/src/real-time/presence.js +7 -2
- package/backend/src/real-time/socketHandler.js +395 -4
- package/backend/src/server.js +18 -0
- package/frontend/dist/assets/index-B1serztM.js +11210 -0
- package/frontend/dist/assets/index-t6K1u4OV.css +32 -0
- package/frontend/dist/index.html +2 -2
- package/frontend/package-lock.json +9437 -0
- package/frontend/package.json +8 -0
- package/package.json +2 -2
- package/screen/console.png +0 -0
- package/screen/dashboard.png +0 -0
- package/screen/graph_collabe.png +0 -0
- package/screen/graph_live_debug.png +0 -0
- package/screen/management_command.png +0 -0
- package/screen/node_debug_trace.png +0 -0
- package/screen/plugin_/320/276/320/261/320/267/320/276/321/200.png +0 -0
- package/screen/websocket.png +0 -0
- package/screen//320/275/320/260/321/201/321/202/321/200/320/276/320/271/320/272/320/270_/320/276/321/202/320/264/320/265/320/273/321/214/320/275/321/213/321/205_/320/272/320/276/320/274/320/260/320/275/320/264_/320/272/320/260/320/266/320/264/321/203_/320/272/320/276/320/274/320/260/320/275/320/273/320/264/321/203_/320/274/320/276/320/266/320/275/320/276_/320/275/320/260/321/201/321/202/321/200/320/260/320/270/320/262/320/260/321/202/321/214.png +0 -0
- package/screen//320/277/320/273/320/260/320/275/320/270/321/200/320/276/320/262/321/211/320/270/320/272_/320/274/320/276/320/266/320/275/320/276_/320/267/320/260/320/264/320/260/320/262/320/260/321/202/321/214_/320/264/320/265/320/271/321/201/321/202/320/262/320/270/321/217_/320/277/320/276_/320/262/321/200/320/265/320/274/320/265/320/275/320/270.png +0 -0
- package/frontend/dist/assets/index-CfTo92bP.css +0 -1
- package/frontend/dist/assets/index-CiFD5X9Z.js +0 -8344
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const { authenticate, authorize } = require('../middleware/auth');
|
|
3
|
+
const router = express.Router();
|
|
4
|
+
const { getTraceCollector } = require('../../core/services/TraceCollectorService');
|
|
5
|
+
|
|
6
|
+
router.use(authenticate);
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* GET /api/traces/:botId
|
|
10
|
+
* Получить трассировки для бота
|
|
11
|
+
*/
|
|
12
|
+
router.get('/:botId', authorize('management:view'), async (req, res) => {
|
|
13
|
+
try {
|
|
14
|
+
const botId = parseInt(req.params.botId);
|
|
15
|
+
const { limit, status, graphId } = req.query;
|
|
16
|
+
|
|
17
|
+
const options = {
|
|
18
|
+
limit: limit ? parseInt(limit) : 150,
|
|
19
|
+
status: status || null,
|
|
20
|
+
graphId: graphId ? parseInt(graphId) : null,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const traceCollector = getTraceCollector();
|
|
24
|
+
const traces = traceCollector.getTracesForBot(botId, options);
|
|
25
|
+
|
|
26
|
+
res.json({
|
|
27
|
+
success: true,
|
|
28
|
+
traces,
|
|
29
|
+
});
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.error('[API /traces/:botId] Ошибка:', error);
|
|
32
|
+
res.status(500).json({
|
|
33
|
+
success: false,
|
|
34
|
+
error: error.message,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* GET /api/traces/:botId/:traceId
|
|
41
|
+
* Получить конкретную трассировку по ID
|
|
42
|
+
*/
|
|
43
|
+
router.get('/:botId/:traceId', authorize('management:view'), async (req, res) => {
|
|
44
|
+
try {
|
|
45
|
+
const { traceId } = req.params;
|
|
46
|
+
|
|
47
|
+
const traceCollector = getTraceCollector();
|
|
48
|
+
let trace = traceCollector.getTrace(traceId);
|
|
49
|
+
|
|
50
|
+
// Если не нашли в памяти, пытаемся загрузить из БД
|
|
51
|
+
if (!trace) {
|
|
52
|
+
trace = await traceCollector.loadTraceFromDb(traceId);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!trace) {
|
|
56
|
+
return res.status(404).json({
|
|
57
|
+
success: false,
|
|
58
|
+
error: 'Трассировка не найдена',
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
res.json({
|
|
63
|
+
success: true,
|
|
64
|
+
trace,
|
|
65
|
+
});
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error('[API /traces/:botId/:traceId] Ошибка:', error);
|
|
68
|
+
res.status(500).json({
|
|
69
|
+
success: false,
|
|
70
|
+
error: error.message,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* GET /api/traces/:botId/graph/:graphId/last
|
|
77
|
+
* Получить последнюю трассировку для графа
|
|
78
|
+
* Query params: eventType (опционально) - фильтр по типу события
|
|
79
|
+
*/
|
|
80
|
+
router.get('/:botId/graph/:graphId/last', authorize('management:view'), async (req, res) => {
|
|
81
|
+
try {
|
|
82
|
+
const botId = parseInt(req.params.botId);
|
|
83
|
+
const graphId = parseInt(req.params.graphId);
|
|
84
|
+
const { eventType } = req.query;
|
|
85
|
+
|
|
86
|
+
const traceCollector = getTraceCollector();
|
|
87
|
+
const trace = await traceCollector.getLastTraceForGraph(botId, graphId, eventType);
|
|
88
|
+
|
|
89
|
+
if (!trace) {
|
|
90
|
+
return res.status(404).json({
|
|
91
|
+
success: false,
|
|
92
|
+
error: 'Трассировка не найдена',
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
res.json({
|
|
97
|
+
success: true,
|
|
98
|
+
trace,
|
|
99
|
+
});
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.error('[API /traces/:botId/graph/:graphId/last] Ошибка:', error);
|
|
102
|
+
res.status(500).json({
|
|
103
|
+
success: false,
|
|
104
|
+
error: error.message,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* GET /api/traces/stats
|
|
111
|
+
* Получить статистику трассировок
|
|
112
|
+
*/
|
|
113
|
+
router.get('/stats', authorize('management:view'), async (req, res) => {
|
|
114
|
+
try {
|
|
115
|
+
const traceCollector = getTraceCollector();
|
|
116
|
+
const stats = traceCollector.getStats();
|
|
117
|
+
|
|
118
|
+
res.json({
|
|
119
|
+
success: true,
|
|
120
|
+
stats,
|
|
121
|
+
});
|
|
122
|
+
} catch (error) {
|
|
123
|
+
console.error('[API /traces/stats] Ошибка:', error);
|
|
124
|
+
res.status(500).json({
|
|
125
|
+
success: false,
|
|
126
|
+
error: error.message,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
module.exports = router;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Конфигурация для Live Debug системы
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
// Таймауты (в миллисекундах)
|
|
7
|
+
BREAKPOINT_TIMEOUT: 30000, // 30 секунд - максимальное время ожидания breakpoint response
|
|
8
|
+
STEP_MODE_TIMEOUT: 30000, // 30 секунд - максимальное время ожидания step mode response
|
|
9
|
+
TRACE_CLEANUP_DELAY: 5000, // 5 секунд - задержка перед удалением completed trace
|
|
10
|
+
|
|
11
|
+
// Лимиты
|
|
12
|
+
MAX_TRACE_STEPS: 10000, // Максимальное количество шагов в одном trace
|
|
13
|
+
MAX_COMPLETED_TRACES: 100, // Максимальное количество хранимых completed traces
|
|
14
|
+
MAX_OUTPUT_LENGTH: 30000, // Максимальная длина output при передаче через IPC
|
|
15
|
+
|
|
16
|
+
// IPC Message Types (для type safety)
|
|
17
|
+
IPC_TYPES: {
|
|
18
|
+
EXECUTE_EVENT_GRAPH: 'execute_event_graph',
|
|
19
|
+
EXECUTE_HANDLER: 'execute_handler',
|
|
20
|
+
EXECUTE_COMMAND_REQUEST: 'execute_command_request',
|
|
21
|
+
|
|
22
|
+
DEBUG_CHECK_BREAKPOINT: 'debug:check_breakpoint',
|
|
23
|
+
DEBUG_CHECK_STEP_MODE: 'debug:check_step_mode',
|
|
24
|
+
DEBUG_BREAKPOINT_RESPONSE: 'debug:breakpoint_response',
|
|
25
|
+
|
|
26
|
+
TRACE_COMPLETED: 'trace:completed',
|
|
27
|
+
TRACE_ERROR: 'trace:error',
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
// Debug Session
|
|
31
|
+
DEBUG_SESSION_IDLE_TIMEOUT: 300000, // 5 минут - таймаут неактивной debug сессии
|
|
32
|
+
|
|
33
|
+
// Trace Storage
|
|
34
|
+
TRACE_RETENTION_TIME: 3600000, // 1 час - время хранения completed traces
|
|
35
|
+
ACTIVE_TRACE_MAX_AGE: 600000, // 10 минут - максимальный возраст active trace
|
|
36
|
+
};
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory хранилище истории чатов и команд ботов
|
|
3
|
+
* Хранит последние N сообщений/команд для каждого бота
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class BotHistoryStore {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.chatHistory = new Map();
|
|
9
|
+
this.commandLogs = new Map();
|
|
10
|
+
|
|
11
|
+
this.MAX_CHAT_MESSAGES = 1000;
|
|
12
|
+
this.MAX_COMMAND_LOGS = 500;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Добавить сообщение чата
|
|
17
|
+
*/
|
|
18
|
+
addChatMessage(botId, data) {
|
|
19
|
+
if (!this.chatHistory.has(botId)) {
|
|
20
|
+
this.chatHistory.set(botId, []);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const messages = this.chatHistory.get(botId);
|
|
24
|
+
|
|
25
|
+
const entry = {
|
|
26
|
+
type: data.type || 'chat',
|
|
27
|
+
username: data.username,
|
|
28
|
+
message: data.message,
|
|
29
|
+
timestamp: data.timestamp || new Date().toISOString()
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
messages.push(entry);
|
|
33
|
+
|
|
34
|
+
if (messages.length > this.MAX_CHAT_MESSAGES) {
|
|
35
|
+
messages.shift();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Получить историю чата с фильтрами
|
|
41
|
+
*/
|
|
42
|
+
getChatHistory(botId, filters = {}) {
|
|
43
|
+
const messages = this.chatHistory.get(botId) || [];
|
|
44
|
+
|
|
45
|
+
let filtered = [...messages];
|
|
46
|
+
|
|
47
|
+
if (filters.type) {
|
|
48
|
+
filtered = filtered.filter(m => m.type === filters.type);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (filters.username) {
|
|
52
|
+
filtered = filtered.filter(m => m.username.toLowerCase() === filters.username.toLowerCase());
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (filters.search) {
|
|
56
|
+
const searchLower = filters.search.toLowerCase();
|
|
57
|
+
filtered = filtered.filter(m => m.message.toLowerCase().includes(searchLower));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (filters.from) {
|
|
61
|
+
const fromDate = new Date(filters.from);
|
|
62
|
+
filtered = filtered.filter(m => new Date(m.timestamp) >= fromDate);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (filters.to) {
|
|
66
|
+
const toDate = new Date(filters.to);
|
|
67
|
+
filtered = filtered.filter(m => new Date(m.timestamp) <= toDate);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const limit = parseInt(filters.limit) || 100;
|
|
71
|
+
const offset = parseInt(filters.offset) || 0;
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
messages: filtered.slice(offset, offset + limit).reverse(),
|
|
75
|
+
total: filtered.length
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Добавить лог команды
|
|
81
|
+
*/
|
|
82
|
+
addCommandLog(botId, data) {
|
|
83
|
+
if (!this.commandLogs.has(botId)) {
|
|
84
|
+
this.commandLogs.set(botId, []);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const logs = this.commandLogs.get(botId);
|
|
88
|
+
|
|
89
|
+
const entry = {
|
|
90
|
+
username: data.username,
|
|
91
|
+
command: data.command,
|
|
92
|
+
args: data.args || [],
|
|
93
|
+
success: data.success !== undefined ? data.success : true,
|
|
94
|
+
error: data.error || null,
|
|
95
|
+
timestamp: data.timestamp || new Date().toISOString()
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
logs.push(entry);
|
|
99
|
+
|
|
100
|
+
if (logs.length > this.MAX_COMMAND_LOGS) {
|
|
101
|
+
logs.shift();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Получить логи команд с фильтрами
|
|
107
|
+
*/
|
|
108
|
+
getCommandLogs(botId, filters = {}) {
|
|
109
|
+
const logs = this.commandLogs.get(botId) || [];
|
|
110
|
+
|
|
111
|
+
let filtered = [...logs];
|
|
112
|
+
|
|
113
|
+
if (filters.username) {
|
|
114
|
+
filtered = filtered.filter(l => l.username.toLowerCase() === filters.username.toLowerCase());
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (filters.command) {
|
|
118
|
+
filtered = filtered.filter(l => l.command === filters.command);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (filters.success !== undefined) {
|
|
122
|
+
const successValue = filters.success === 'true' || filters.success === true;
|
|
123
|
+
filtered = filtered.filter(l => l.success === successValue);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (filters.from) {
|
|
127
|
+
const fromDate = new Date(filters.from);
|
|
128
|
+
filtered = filtered.filter(l => new Date(l.timestamp) >= fromDate);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (filters.to) {
|
|
132
|
+
const toDate = new Date(filters.to);
|
|
133
|
+
filtered = filtered.filter(l => new Date(l.timestamp) <= toDate);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const limit = parseInt(filters.limit) || 100;
|
|
137
|
+
const offset = parseInt(filters.offset) || 0;
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
logs: filtered.slice(offset, offset + limit).reverse(),
|
|
141
|
+
total: filtered.length
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Очистить историю бота
|
|
147
|
+
*/
|
|
148
|
+
clearBot(botId) {
|
|
149
|
+
this.chatHistory.delete(botId);
|
|
150
|
+
this.commandLogs.delete(botId);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Получить статистику
|
|
155
|
+
*/
|
|
156
|
+
getStats(botId) {
|
|
157
|
+
const chatMessages = this.chatHistory.get(botId) || [];
|
|
158
|
+
const commandLogs = this.commandLogs.get(botId) || [];
|
|
159
|
+
|
|
160
|
+
const byType = {};
|
|
161
|
+
chatMessages.forEach(msg => {
|
|
162
|
+
const type = msg.type || 'unknown';
|
|
163
|
+
byType[type] = (byType[type] || 0) + 1;
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
return {
|
|
167
|
+
chat: {
|
|
168
|
+
total: chatMessages.length,
|
|
169
|
+
byType
|
|
170
|
+
},
|
|
171
|
+
commands: {
|
|
172
|
+
total: commandLogs.length,
|
|
173
|
+
successful: commandLogs.filter(l => l.success).length,
|
|
174
|
+
failed: commandLogs.filter(l => !l.success).length
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
module.exports = new BotHistoryStore();
|
|
@@ -159,8 +159,11 @@ class BotManager {
|
|
|
159
159
|
// === Resource monitoring ===
|
|
160
160
|
async updateAllResourceUsage() {
|
|
161
161
|
const usageData = await this.resourceMonitor.updateAllResourceUsage();
|
|
162
|
-
const {
|
|
163
|
-
|
|
162
|
+
const { getIOSafe } = require('../real-time/socketHandler');
|
|
163
|
+
const io = getIOSafe();
|
|
164
|
+
if (io) {
|
|
165
|
+
io.emit('bots:usage', usageData);
|
|
166
|
+
}
|
|
164
167
|
}
|
|
165
168
|
|
|
166
169
|
getBotIdByPid(pid) {
|
|
@@ -195,11 +198,14 @@ class BotManager {
|
|
|
195
198
|
|
|
196
199
|
syncBotStatuses() {
|
|
197
200
|
const processes = this.processManager.getAllProcesses();
|
|
198
|
-
const {
|
|
201
|
+
const { getIOSafe } = require('../real-time/socketHandler');
|
|
202
|
+
const io = getIOSafe();
|
|
203
|
+
|
|
204
|
+
if (!io) return;
|
|
199
205
|
|
|
200
206
|
for (const [botId, child] of processes.entries()) {
|
|
201
207
|
const actualStatus = child.killed ? 'stopped' : 'running';
|
|
202
|
-
|
|
208
|
+
io.emit('bot:status', { botId, status: actualStatus });
|
|
203
209
|
}
|
|
204
210
|
}
|
|
205
211
|
|
|
@@ -209,6 +215,10 @@ class BotManager {
|
|
|
209
215
|
this.lifecycleService.eventGraphManager = manager;
|
|
210
216
|
}
|
|
211
217
|
|
|
218
|
+
getChildProcess(botId) {
|
|
219
|
+
return this.lifecycleService.getChildProcess(botId);
|
|
220
|
+
}
|
|
221
|
+
|
|
212
222
|
// === Legacy async methods для migration ===
|
|
213
223
|
async _syncSystemPermissions(botId) {
|
|
214
224
|
return this.lifecycleService._syncSystemPermissions(botId);
|