claude-mpm 4.2.44__py3-none-any.whl → 4.2.51__py3-none-any.whl

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 (148) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_PM.md +43 -1
  3. claude_mpm/agents/INSTRUCTIONS.md +75 -1
  4. claude_mpm/agents/WORKFLOW.md +46 -1
  5. claude_mpm/agents/frontmatter_validator.py +20 -12
  6. claude_mpm/agents/templates/nextjs_engineer.json +277 -0
  7. claude_mpm/agents/templates/python_engineer.json +289 -0
  8. claude_mpm/agents/templates/react_engineer.json +11 -3
  9. claude_mpm/agents/templates/security.json +50 -9
  10. claude_mpm/cli/commands/agents.py +2 -2
  11. claude_mpm/cli/commands/uninstall.py +1 -2
  12. claude_mpm/cli/interactive/agent_wizard.py +3 -3
  13. claude_mpm/cli/parsers/agent_manager_parser.py +3 -3
  14. claude_mpm/cli/parsers/agents_parser.py +1 -1
  15. claude_mpm/constants.py +1 -1
  16. claude_mpm/core/error_handler.py +2 -4
  17. claude_mpm/core/file_utils.py +4 -12
  18. claude_mpm/core/log_manager.py +8 -5
  19. claude_mpm/core/logger.py +1 -1
  20. claude_mpm/core/logging_utils.py +6 -6
  21. claude_mpm/core/unified_agent_registry.py +18 -4
  22. claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +188 -0
  23. claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +156 -0
  24. claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +38 -0
  25. claude_mpm/dashboard/react/components/shared/FilterBar.module.css +92 -0
  26. claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +248 -0
  27. claude_mpm/dashboard/static/archive/activity_dashboard_test.html +61 -0
  28. claude_mpm/dashboard/static/archive/test_activity_connection.html +179 -0
  29. claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +68 -0
  30. claude_mpm/dashboard/static/archive/test_dashboard.html +409 -0
  31. claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +519 -0
  32. claude_mpm/dashboard/static/archive/test_dashboard_verification.html +181 -0
  33. claude_mpm/dashboard/static/archive/test_file_data.html +315 -0
  34. claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +243 -0
  35. claude_mpm/dashboard/static/archive/test_file_tree_fix.html +234 -0
  36. claude_mpm/dashboard/static/archive/test_file_tree_rename.html +117 -0
  37. claude_mpm/dashboard/static/archive/test_file_tree_tab.html +115 -0
  38. claude_mpm/dashboard/static/archive/test_file_viewer.html +224 -0
  39. claude_mpm/dashboard/static/archive/test_final_activity.html +220 -0
  40. claude_mpm/dashboard/static/archive/test_tab_fix.html +139 -0
  41. claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +1 -0
  42. claude_mpm/dashboard/static/built/components/activity-tree.js +1 -1
  43. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +777 -0
  44. claude_mpm/dashboard/static/built/components/agent-inference.js +1 -1
  45. claude_mpm/dashboard/static/built/components/build-tracker.js +333 -0
  46. claude_mpm/dashboard/static/built/components/code-simple.js +857 -0
  47. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +353 -0
  48. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +235 -0
  49. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +409 -0
  50. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +435 -0
  51. claude_mpm/dashboard/static/built/components/code-viewer.js +2 -1076
  52. claude_mpm/dashboard/static/built/components/connection-debug.js +654 -0
  53. claude_mpm/dashboard/static/built/components/diff-viewer.js +891 -0
  54. claude_mpm/dashboard/static/built/components/event-processor.js +1 -1
  55. claude_mpm/dashboard/static/built/components/event-viewer.js +1 -1
  56. claude_mpm/dashboard/static/built/components/export-manager.js +1 -1
  57. claude_mpm/dashboard/static/built/components/file-change-tracker.js +443 -0
  58. claude_mpm/dashboard/static/built/components/file-change-viewer.js +690 -0
  59. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +1 -1
  60. claude_mpm/dashboard/static/built/components/module-viewer.js +1 -1
  61. claude_mpm/dashboard/static/built/components/nav-bar.js +145 -0
  62. claude_mpm/dashboard/static/built/components/page-structure.js +429 -0
  63. claude_mpm/dashboard/static/built/components/session-manager.js +1 -1
  64. claude_mpm/dashboard/static/built/components/ui-state-manager.js +2 -465
  65. claude_mpm/dashboard/static/built/components/working-directory.js +1 -1
  66. claude_mpm/dashboard/static/built/connection-manager.js +536 -0
  67. claude_mpm/dashboard/static/built/dashboard.js +1 -1
  68. claude_mpm/dashboard/static/built/extension-error-handler.js +164 -0
  69. claude_mpm/dashboard/static/built/react/events.js +30 -0
  70. claude_mpm/dashboard/static/built/shared/dom-helpers.js +396 -0
  71. claude_mpm/dashboard/static/built/shared/event-bus.js +330 -0
  72. claude_mpm/dashboard/static/built/shared/event-filter-service.js +540 -0
  73. claude_mpm/dashboard/static/built/shared/logger.js +385 -0
  74. claude_mpm/dashboard/static/built/shared/page-structure.js +251 -0
  75. claude_mpm/dashboard/static/built/shared/tooltip-service.js +253 -0
  76. claude_mpm/dashboard/static/built/socket-client.js +1 -1
  77. claude_mpm/dashboard/static/built/tab-isolation-fix.js +185 -0
  78. claude_mpm/dashboard/static/css/dashboard.css +28 -5
  79. claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +1 -0
  80. claude_mpm/dashboard/static/dist/components/activity-tree.js +1 -1
  81. claude_mpm/dashboard/static/dist/components/agent-inference.js +1 -1
  82. claude_mpm/dashboard/static/dist/components/code-viewer.js +2 -0
  83. claude_mpm/dashboard/static/dist/components/event-processor.js +1 -1
  84. claude_mpm/dashboard/static/dist/components/event-viewer.js +1 -1
  85. claude_mpm/dashboard/static/dist/components/export-manager.js +1 -1
  86. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +1 -1
  87. claude_mpm/dashboard/static/dist/components/module-viewer.js +1 -1
  88. claude_mpm/dashboard/static/dist/components/session-manager.js +1 -1
  89. claude_mpm/dashboard/static/dist/components/working-directory.js +1 -1
  90. claude_mpm/dashboard/static/dist/dashboard.js +1 -1
  91. claude_mpm/dashboard/static/dist/react/events.js +30 -0
  92. claude_mpm/dashboard/static/dist/socket-client.js +1 -1
  93. claude_mpm/dashboard/static/events.html +607 -0
  94. claude_mpm/dashboard/static/index.html +713 -0
  95. claude_mpm/dashboard/static/js/components/activity-tree.js +3 -17
  96. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +4 -1
  97. claude_mpm/dashboard/static/js/components/agent-inference.js +3 -0
  98. claude_mpm/dashboard/static/js/components/build-tracker.js +8 -0
  99. claude_mpm/dashboard/static/js/components/code-viewer.js +306 -66
  100. claude_mpm/dashboard/static/js/components/event-processor.js +3 -0
  101. claude_mpm/dashboard/static/js/components/event-viewer.js +39 -2
  102. claude_mpm/dashboard/static/js/components/export-manager.js +3 -0
  103. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +30 -10
  104. claude_mpm/dashboard/static/js/components/socket-manager.js +4 -0
  105. claude_mpm/dashboard/static/js/components/ui-state-manager.js +285 -85
  106. claude_mpm/dashboard/static/js/components/working-directory.js +3 -0
  107. claude_mpm/dashboard/static/js/dashboard.js +61 -33
  108. claude_mpm/dashboard/static/js/socket-client.js +12 -8
  109. claude_mpm/dashboard/static/js/stores/dashboard-store.js +562 -0
  110. claude_mpm/dashboard/static/js/tab-isolation-fix.js +185 -0
  111. claude_mpm/dashboard/static/legacy/activity.html +736 -0
  112. claude_mpm/dashboard/static/legacy/agents.html +786 -0
  113. claude_mpm/dashboard/static/legacy/files.html +747 -0
  114. claude_mpm/dashboard/static/legacy/tools.html +831 -0
  115. claude_mpm/dashboard/static/monitors-index.html +218 -0
  116. claude_mpm/dashboard/static/monitors.html +431 -0
  117. claude_mpm/dashboard/static/production/events.html +659 -0
  118. claude_mpm/dashboard/static/production/main.html +715 -0
  119. claude_mpm/dashboard/static/production/monitors.html +483 -0
  120. claude_mpm/dashboard/static/socket.io.min.js +7 -0
  121. claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +7 -0
  122. claude_mpm/dashboard/static/test-archive/dashboard.html +635 -0
  123. claude_mpm/dashboard/static/test-archive/debug-events.html +147 -0
  124. claude_mpm/dashboard/static/test-archive/test-navigation.html +256 -0
  125. claude_mpm/dashboard/static/test-archive/test-react-exports.html +180 -0
  126. claude_mpm/dashboard/templates/index.html +79 -9
  127. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +1 -1
  128. claude_mpm/services/agents/deployment/agent_discovery_service.py +3 -0
  129. claude_mpm/services/agents/deployment/agent_template_builder.py +25 -8
  130. claude_mpm/services/agents/deployment/agent_validator.py +3 -0
  131. claude_mpm/services/agents/deployment/validation/template_validator.py +13 -4
  132. claude_mpm/services/agents/local_template_manager.py +2 -6
  133. claude_mpm/services/monitor/daemon.py +1 -2
  134. claude_mpm/services/monitor/daemon_manager.py +2 -5
  135. claude_mpm/services/monitor/event_emitter.py +2 -2
  136. claude_mpm/services/monitor/handlers/code_analysis.py +4 -6
  137. claude_mpm/services/monitor/handlers/hooks.py +2 -4
  138. claude_mpm/services/monitor/server.py +27 -4
  139. claude_mpm/tools/code_tree_analyzer.py +2 -2
  140. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/METADATA +1 -1
  141. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/RECORD +146 -81
  142. claude_mpm/dashboard/static/test-browser-monitor.html +0 -470
  143. claude_mpm/dashboard/static/test-simple.html +0 -97
  144. /claude_mpm/dashboard/static/{test_debug.html → test-archive/test_debug.html} +0 -0
  145. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/WHEEL +0 -0
  146. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/entry_points.txt +0 -0
  147. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/licenses/LICENSE +0 -0
  148. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,540 @@
1
+ /**
2
+ * EventFilterService - Comprehensive event filtering and normalization
3
+ * Handles all event types across the Claude MPM dashboard
4
+ */
5
+
6
+ class EventFilterService {
7
+ constructor() {
8
+ // Event type configurations for comprehensive detection
9
+ this.eventConfigs = {
10
+ agent: {
11
+ // Direct type patterns
12
+ typePatterns: [
13
+ /agent/i,
14
+ /subagent/i,
15
+ /pm_/i,
16
+ /engineer/i,
17
+ /qa/i,
18
+ /devops/i
19
+ ],
20
+ // Hook event patterns
21
+ hookPatterns: [
22
+ 'SubagentStart',
23
+ 'SubagentStop',
24
+ 'AgentInference',
25
+ 'agent_inference',
26
+ 'agent_start',
27
+ 'agent_stop',
28
+ 'agent_update',
29
+ 'agent_complete',
30
+ 'agent_error',
31
+ 'agent_activity'
32
+ ],
33
+ // Field detection for nested data
34
+ dataFields: [
35
+ 'agent_name',
36
+ 'agent_id',
37
+ 'agent_type',
38
+ 'agent',
39
+ 'subagent',
40
+ 'agent_role'
41
+ ],
42
+ // Subtype patterns
43
+ subtypes: [
44
+ 'agent_deployment',
45
+ 'agent_initialization',
46
+ 'agent_task'
47
+ ]
48
+ },
49
+ tool: {
50
+ typePatterns: [
51
+ /tool/i,
52
+ /bash/i,
53
+ /read/i,
54
+ /write/i,
55
+ /edit/i,
56
+ /search/i,
57
+ /grep/i,
58
+ /glob/i,
59
+ /webfetch/i,
60
+ /multiedit/i,
61
+ /notebookedit/i
62
+ ],
63
+ hookPatterns: [
64
+ 'ToolStart',
65
+ 'ToolStop',
66
+ 'tool_start',
67
+ 'tool_complete',
68
+ 'tool_error',
69
+ 'tool_execution',
70
+ 'BashCommand',
71
+ 'FileOperation'
72
+ ],
73
+ dataFields: [
74
+ 'tool',
75
+ 'tool_name',
76
+ 'tool_id',
77
+ 'command',
78
+ 'operation',
79
+ 'tool_type'
80
+ ],
81
+ subtypes: [
82
+ 'bash_command',
83
+ 'file_operation',
84
+ 'search_operation'
85
+ ]
86
+ },
87
+ file: {
88
+ typePatterns: [
89
+ /file/i,
90
+ /read/i,
91
+ /write/i,
92
+ /edit/i,
93
+ /delete/i,
94
+ /create/i,
95
+ /modify/i
96
+ ],
97
+ hookPatterns: [
98
+ 'FileRead',
99
+ 'FileWrite',
100
+ 'FileEdit',
101
+ 'FileDelete',
102
+ 'file_read',
103
+ 'file_write',
104
+ 'file_edit',
105
+ 'file_delete',
106
+ 'file_operation',
107
+ 'file_change'
108
+ ],
109
+ dataFields: [
110
+ 'file',
111
+ 'file_path',
112
+ 'path',
113
+ 'filename',
114
+ 'file_name',
115
+ 'target_file'
116
+ ],
117
+ subtypes: [
118
+ 'file_created',
119
+ 'file_modified',
120
+ 'file_removed'
121
+ ]
122
+ }
123
+ };
124
+
125
+ // Cache for performance
126
+ this.eventTypeCache = new Map();
127
+ this.debug = false;
128
+ }
129
+
130
+ /**
131
+ * Enable/disable debug logging
132
+ */
133
+ setDebug(enabled) {
134
+ this.debug = enabled;
135
+ }
136
+
137
+ /**
138
+ * Main filtering method - determines if an event matches a category
139
+ */
140
+ isEventType(event, category) {
141
+ if (!event || !category) return false;
142
+
143
+ // Check cache first
144
+ const cacheKey = `${JSON.stringify(event)}_${category}`;
145
+ if (this.eventTypeCache.has(cacheKey)) {
146
+ return this.eventTypeCache.get(cacheKey);
147
+ }
148
+
149
+ const config = this.eventConfigs[category];
150
+ if (!config) {
151
+ console.warn(`Unknown event category: ${category}`);
152
+ return false;
153
+ }
154
+
155
+ // Comprehensive detection
156
+ let matches = false;
157
+
158
+ // 1. Check direct type field
159
+ const eventType = this.getEventType(event);
160
+ if (eventType) {
161
+ // Check type patterns
162
+ matches = config.typePatterns.some(pattern => {
163
+ if (pattern instanceof RegExp) {
164
+ return pattern.test(eventType);
165
+ }
166
+ return eventType.toLowerCase().includes(pattern.toLowerCase());
167
+ });
168
+
169
+ // Check hook patterns
170
+ if (!matches) {
171
+ matches = config.hookPatterns.some(pattern =>
172
+ eventType.includes(pattern) || eventType === pattern
173
+ );
174
+ }
175
+
176
+ // Check subtypes
177
+ if (!matches && config.subtypes) {
178
+ matches = config.subtypes.some(subtype =>
179
+ eventType.toLowerCase().includes(subtype.toLowerCase())
180
+ );
181
+ }
182
+ }
183
+
184
+ // 2. Check hook_event_name field
185
+ if (!matches && event.hook_event_name) {
186
+ matches = config.hookPatterns.includes(event.hook_event_name);
187
+ }
188
+
189
+ // 3. Check data fields for category-specific fields
190
+ if (!matches && event.data) {
191
+ matches = config.dataFields.some(field => {
192
+ const value = this.getNestedValue(event.data, field);
193
+ return value !== undefined && value !== null && value !== '';
194
+ });
195
+ }
196
+
197
+ // 4. Check root level fields
198
+ if (!matches) {
199
+ matches = config.dataFields.some(field => {
200
+ const value = event[field];
201
+ return value !== undefined && value !== null && value !== '';
202
+ });
203
+ }
204
+
205
+ // 5. Special case: Check for tool names in tool category
206
+ if (!matches && category === 'tool') {
207
+ matches = this.isToolEvent(event);
208
+ }
209
+
210
+ // 6. Special case: Check for file paths in file category
211
+ if (!matches && category === 'file') {
212
+ matches = this.isFileEvent(event);
213
+ }
214
+
215
+ // Cache the result
216
+ this.eventTypeCache.set(cacheKey, matches);
217
+
218
+ if (this.debug) {
219
+ console.log(`Event ${matches ? 'MATCHES' : 'does not match'} category ${category}:`, {
220
+ event,
221
+ eventType,
222
+ matches
223
+ });
224
+ }
225
+
226
+ return matches;
227
+ }
228
+
229
+ /**
230
+ * Special detection for tool events
231
+ */
232
+ isToolEvent(event) {
233
+ // Known tool names
234
+ const toolNames = [
235
+ 'Bash', 'Read', 'Write', 'Edit', 'MultiEdit',
236
+ 'Search', 'Grep', 'Glob', 'WebFetch', 'NotebookEdit',
237
+ 'TodoWrite', 'WebSearch', 'BashOutput', 'KillShell'
238
+ ];
239
+
240
+ // Check if event contains any tool name
241
+ const eventStr = JSON.stringify(event).toLowerCase();
242
+ return toolNames.some(tool => eventStr.includes(tool.toLowerCase()));
243
+ }
244
+
245
+ /**
246
+ * Special detection for file events
247
+ */
248
+ isFileEvent(event) {
249
+ // Check for file path patterns
250
+ const eventStr = JSON.stringify(event);
251
+ const pathPatterns = [
252
+ /\/[\w\-\.]+\/[\w\-\.]+/, // Unix paths
253
+ /[a-zA-Z]:\\[\w\-\.\\]+/, // Windows paths
254
+ /\.(js|py|md|json|txt|html|css|jsx|ts|tsx|yml|yaml)(\s|"|'|$)/i
255
+ ];
256
+
257
+ return pathPatterns.some(pattern => pattern.test(eventStr));
258
+ }
259
+
260
+ /**
261
+ * Get the event type from various possible fields
262
+ */
263
+ getEventType(event) {
264
+ if (!event) return null;
265
+
266
+ // Priority order for type detection
267
+ const typeFields = [
268
+ 'type',
269
+ 'event_type',
270
+ 'eventType',
271
+ 'hook_event_name',
272
+ 'event_name',
273
+ 'name'
274
+ ];
275
+
276
+ for (const field of typeFields) {
277
+ const value = event[field];
278
+ if (value && typeof value === 'string') {
279
+ return value;
280
+ }
281
+ }
282
+
283
+ // Check nested data.type
284
+ if (event.data) {
285
+ for (const field of typeFields) {
286
+ const value = event.data[field];
287
+ if (value && typeof value === 'string') {
288
+ return value;
289
+ }
290
+ }
291
+ }
292
+
293
+ return null;
294
+ }
295
+
296
+ /**
297
+ * Normalize event data for consistent access
298
+ */
299
+ normalizeEvent(event, category) {
300
+ if (!event) return null;
301
+
302
+ const normalized = {
303
+ // Core fields
304
+ type: this.getEventType(event) || 'unknown',
305
+ timestamp: event.timestamp || event.data?.timestamp || Date.now(),
306
+ category: category,
307
+
308
+ // Original event
309
+ raw: event
310
+ };
311
+
312
+ // Category-specific normalization
313
+ switch (category) {
314
+ case 'agent':
315
+ normalized.agent = this.extractAgentInfo(event);
316
+ break;
317
+ case 'tool':
318
+ normalized.tool = this.extractToolInfo(event);
319
+ break;
320
+ case 'file':
321
+ normalized.file = this.extractFileInfo(event);
322
+ break;
323
+ }
324
+
325
+ return normalized;
326
+ }
327
+
328
+ /**
329
+ * Extract agent information from event
330
+ */
331
+ extractAgentInfo(event) {
332
+ const info = {
333
+ id: null,
334
+ name: null,
335
+ type: null,
336
+ status: null,
337
+ message: null
338
+ };
339
+
340
+ // Extract from various possible locations
341
+ const data = event.data || event;
342
+
343
+ // ID extraction
344
+ info.id = data.agent_id || data.agent_name || data.agent ||
345
+ event.agent_id || event.agent || null;
346
+
347
+ // Name extraction
348
+ info.name = data.agent_name || data.agent || data.name ||
349
+ event.agent_name || event.agent || event.name || 'Unknown';
350
+
351
+ // Type extraction
352
+ info.type = data.agent_type || data.type || event.agent_type || 'Agent';
353
+
354
+ // Status extraction
355
+ const eventType = this.getEventType(event);
356
+ if (eventType) {
357
+ if (eventType.includes('complete') || eventType.includes('Complete')) {
358
+ info.status = 'complete';
359
+ } else if (eventType.includes('error') || eventType.includes('Error')) {
360
+ info.status = 'error';
361
+ } else if (eventType.includes('start') || eventType.includes('Start')) {
362
+ info.status = 'active';
363
+ } else {
364
+ info.status = data.status || event.status || 'active';
365
+ }
366
+ } else {
367
+ info.status = data.status || event.status || 'unknown';
368
+ }
369
+
370
+ // Message extraction
371
+ info.message = data.message || data.task || event.message || '';
372
+
373
+ return info;
374
+ }
375
+
376
+ /**
377
+ * Extract tool information from event
378
+ */
379
+ extractToolInfo(event) {
380
+ const info = {
381
+ name: null,
382
+ type: null,
383
+ status: null,
384
+ description: null,
385
+ command: null
386
+ };
387
+
388
+ const data = event.data || event;
389
+
390
+ // Name extraction
391
+ info.name = data.tool || data.tool_name || event.tool ||
392
+ event.tool_name || this.getEventType(event) || 'Unknown';
393
+
394
+ // Clean up tool name (remove prefixes like "tool_")
395
+ if (info.name.startsWith('tool_')) {
396
+ info.name = info.name.substring(5);
397
+ }
398
+
399
+ // Type extraction
400
+ info.type = data.tool_type || data.type || event.tool_type || 'Tool';
401
+
402
+ // Status extraction
403
+ const eventType = this.getEventType(event);
404
+ if (eventType) {
405
+ if (eventType.includes('complete') || eventType.includes('success')) {
406
+ info.status = 'completed';
407
+ } else if (eventType.includes('error')) {
408
+ info.status = 'error';
409
+ } else if (eventType.includes('start')) {
410
+ info.status = 'running';
411
+ } else {
412
+ info.status = data.status || event.status || 'running';
413
+ }
414
+ } else {
415
+ info.status = data.status || event.status || 'unknown';
416
+ }
417
+
418
+ // Description extraction
419
+ info.description = data.description || data.message ||
420
+ event.description || event.message || '';
421
+
422
+ // Command extraction (for Bash tool)
423
+ info.command = data.command || event.command || null;
424
+
425
+ return info;
426
+ }
427
+
428
+ /**
429
+ * Extract file information from event
430
+ */
431
+ extractFileInfo(event) {
432
+ const info = {
433
+ path: null,
434
+ name: null,
435
+ operation: null,
436
+ size: null
437
+ };
438
+
439
+ const data = event.data || event;
440
+
441
+ // Path extraction
442
+ info.path = data.path || data.file_path || data.file || data.filename ||
443
+ event.path || event.file_path || event.file || 'Unknown';
444
+
445
+ // Name extraction
446
+ if (info.path && info.path !== 'Unknown') {
447
+ const parts = info.path.split('/');
448
+ info.name = parts[parts.length - 1] || info.path;
449
+ } else {
450
+ info.name = 'Unknown';
451
+ }
452
+
453
+ // Operation extraction
454
+ const eventType = this.getEventType(event);
455
+ if (eventType) {
456
+ if (eventType.includes('read') || eventType.includes('Read')) {
457
+ info.operation = 'read';
458
+ } else if (eventType.includes('write') || eventType.includes('Write')) {
459
+ info.operation = 'write';
460
+ } else if (eventType.includes('edit') || eventType.includes('Edit')) {
461
+ info.operation = 'edit';
462
+ } else if (eventType.includes('delete') || eventType.includes('Delete')) {
463
+ info.operation = 'delete';
464
+ } else {
465
+ info.operation = data.operation || event.operation || 'unknown';
466
+ }
467
+ } else {
468
+ info.operation = data.operation || event.operation || 'unknown';
469
+ }
470
+
471
+ // Size extraction
472
+ info.size = data.size || event.size || 0;
473
+
474
+ return info;
475
+ }
476
+
477
+ /**
478
+ * Get nested value from object using dot notation
479
+ */
480
+ getNestedValue(obj, path) {
481
+ if (!obj || !path) return undefined;
482
+
483
+ const keys = path.split('.');
484
+ let value = obj;
485
+
486
+ for (const key of keys) {
487
+ if (value && typeof value === 'object' && key in value) {
488
+ value = value[key];
489
+ } else {
490
+ return undefined;
491
+ }
492
+ }
493
+
494
+ return value;
495
+ }
496
+
497
+ /**
498
+ * Clear the cache (useful when debug mode changes)
499
+ */
500
+ clearCache() {
501
+ this.eventTypeCache.clear();
502
+ }
503
+
504
+ /**
505
+ * Get statistics about filtered events
506
+ */
507
+ getFilterStats(events) {
508
+ const stats = {
509
+ total: events.length,
510
+ agent: 0,
511
+ tool: 0,
512
+ file: 0,
513
+ unknown: 0
514
+ };
515
+
516
+ for (const event of events) {
517
+ if (this.isEventType(event, 'agent')) {
518
+ stats.agent++;
519
+ } else if (this.isEventType(event, 'tool')) {
520
+ stats.tool++;
521
+ } else if (this.isEventType(event, 'file')) {
522
+ stats.file++;
523
+ } else {
524
+ stats.unknown++;
525
+ }
526
+ }
527
+
528
+ return stats;
529
+ }
530
+ }
531
+
532
+ // Export for use in other modules
533
+ if (typeof module !== 'undefined' && module.exports) {
534
+ module.exports = EventFilterService;
535
+ }
536
+
537
+ // Make available globally in browser
538
+ if (typeof window !== 'undefined') {
539
+ window.EventFilterService = EventFilterService;
540
+ }