kollabor 0.4.9__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 (128) hide show
  1. core/__init__.py +18 -0
  2. core/application.py +578 -0
  3. core/cli.py +193 -0
  4. core/commands/__init__.py +43 -0
  5. core/commands/executor.py +277 -0
  6. core/commands/menu_renderer.py +319 -0
  7. core/commands/parser.py +186 -0
  8. core/commands/registry.py +331 -0
  9. core/commands/system_commands.py +479 -0
  10. core/config/__init__.py +7 -0
  11. core/config/llm_task_config.py +110 -0
  12. core/config/loader.py +501 -0
  13. core/config/manager.py +112 -0
  14. core/config/plugin_config_manager.py +346 -0
  15. core/config/plugin_schema.py +424 -0
  16. core/config/service.py +399 -0
  17. core/effects/__init__.py +1 -0
  18. core/events/__init__.py +12 -0
  19. core/events/bus.py +129 -0
  20. core/events/executor.py +154 -0
  21. core/events/models.py +258 -0
  22. core/events/processor.py +176 -0
  23. core/events/registry.py +289 -0
  24. core/fullscreen/__init__.py +19 -0
  25. core/fullscreen/command_integration.py +290 -0
  26. core/fullscreen/components/__init__.py +12 -0
  27. core/fullscreen/components/animation.py +258 -0
  28. core/fullscreen/components/drawing.py +160 -0
  29. core/fullscreen/components/matrix_components.py +177 -0
  30. core/fullscreen/manager.py +302 -0
  31. core/fullscreen/plugin.py +204 -0
  32. core/fullscreen/renderer.py +282 -0
  33. core/fullscreen/session.py +324 -0
  34. core/io/__init__.py +52 -0
  35. core/io/buffer_manager.py +362 -0
  36. core/io/config_status_view.py +272 -0
  37. core/io/core_status_views.py +410 -0
  38. core/io/input_errors.py +313 -0
  39. core/io/input_handler.py +2655 -0
  40. core/io/input_mode_manager.py +402 -0
  41. core/io/key_parser.py +344 -0
  42. core/io/layout.py +587 -0
  43. core/io/message_coordinator.py +204 -0
  44. core/io/message_renderer.py +601 -0
  45. core/io/modal_interaction_handler.py +315 -0
  46. core/io/raw_input_processor.py +946 -0
  47. core/io/status_renderer.py +845 -0
  48. core/io/terminal_renderer.py +586 -0
  49. core/io/terminal_state.py +551 -0
  50. core/io/visual_effects.py +734 -0
  51. core/llm/__init__.py +26 -0
  52. core/llm/api_communication_service.py +863 -0
  53. core/llm/conversation_logger.py +473 -0
  54. core/llm/conversation_manager.py +414 -0
  55. core/llm/file_operations_executor.py +1401 -0
  56. core/llm/hook_system.py +402 -0
  57. core/llm/llm_service.py +1629 -0
  58. core/llm/mcp_integration.py +386 -0
  59. core/llm/message_display_service.py +450 -0
  60. core/llm/model_router.py +214 -0
  61. core/llm/plugin_sdk.py +396 -0
  62. core/llm/response_parser.py +848 -0
  63. core/llm/response_processor.py +364 -0
  64. core/llm/tool_executor.py +520 -0
  65. core/logging/__init__.py +19 -0
  66. core/logging/setup.py +208 -0
  67. core/models/__init__.py +5 -0
  68. core/models/base.py +23 -0
  69. core/plugins/__init__.py +13 -0
  70. core/plugins/collector.py +212 -0
  71. core/plugins/discovery.py +386 -0
  72. core/plugins/factory.py +263 -0
  73. core/plugins/registry.py +152 -0
  74. core/storage/__init__.py +5 -0
  75. core/storage/state_manager.py +84 -0
  76. core/ui/__init__.py +6 -0
  77. core/ui/config_merger.py +176 -0
  78. core/ui/config_widgets.py +369 -0
  79. core/ui/live_modal_renderer.py +276 -0
  80. core/ui/modal_actions.py +162 -0
  81. core/ui/modal_overlay_renderer.py +373 -0
  82. core/ui/modal_renderer.py +591 -0
  83. core/ui/modal_state_manager.py +443 -0
  84. core/ui/widget_integration.py +222 -0
  85. core/ui/widgets/__init__.py +27 -0
  86. core/ui/widgets/base_widget.py +136 -0
  87. core/ui/widgets/checkbox.py +85 -0
  88. core/ui/widgets/dropdown.py +140 -0
  89. core/ui/widgets/label.py +78 -0
  90. core/ui/widgets/slider.py +185 -0
  91. core/ui/widgets/text_input.py +224 -0
  92. core/utils/__init__.py +11 -0
  93. core/utils/config_utils.py +656 -0
  94. core/utils/dict_utils.py +212 -0
  95. core/utils/error_utils.py +275 -0
  96. core/utils/key_reader.py +171 -0
  97. core/utils/plugin_utils.py +267 -0
  98. core/utils/prompt_renderer.py +151 -0
  99. kollabor-0.4.9.dist-info/METADATA +298 -0
  100. kollabor-0.4.9.dist-info/RECORD +128 -0
  101. kollabor-0.4.9.dist-info/WHEEL +5 -0
  102. kollabor-0.4.9.dist-info/entry_points.txt +2 -0
  103. kollabor-0.4.9.dist-info/licenses/LICENSE +21 -0
  104. kollabor-0.4.9.dist-info/top_level.txt +4 -0
  105. kollabor_cli_main.py +20 -0
  106. plugins/__init__.py +1 -0
  107. plugins/enhanced_input/__init__.py +18 -0
  108. plugins/enhanced_input/box_renderer.py +103 -0
  109. plugins/enhanced_input/box_styles.py +142 -0
  110. plugins/enhanced_input/color_engine.py +165 -0
  111. plugins/enhanced_input/config.py +150 -0
  112. plugins/enhanced_input/cursor_manager.py +72 -0
  113. plugins/enhanced_input/geometry.py +81 -0
  114. plugins/enhanced_input/state.py +130 -0
  115. plugins/enhanced_input/text_processor.py +115 -0
  116. plugins/enhanced_input_plugin.py +385 -0
  117. plugins/fullscreen/__init__.py +9 -0
  118. plugins/fullscreen/example_plugin.py +327 -0
  119. plugins/fullscreen/matrix_plugin.py +132 -0
  120. plugins/hook_monitoring_plugin.py +1299 -0
  121. plugins/query_enhancer_plugin.py +350 -0
  122. plugins/save_conversation_plugin.py +502 -0
  123. plugins/system_commands_plugin.py +93 -0
  124. plugins/tmux_plugin.py +795 -0
  125. plugins/workflow_enforcement_plugin.py +629 -0
  126. system_prompt/default.md +1286 -0
  127. system_prompt/default_win.md +265 -0
  128. system_prompt/example_with_trender.md +47 -0
@@ -0,0 +1,1299 @@
1
+ """Hook Monitoring Plugin for development and debugging.
2
+
3
+ [SHOWCASE] SHOWCASE PLUGIN: Demonstrates ALL plugin ecosystem features! [SHOWCASE]
4
+
5
+ This plugin serves as a comprehensive example of the Kollabor CLI plugin ecosystem,
6
+ demonstrating:
7
+ - Hook monitoring and performance tracking
8
+ - Plugin discovery via PluginFactory
9
+ - Cross-plugin service registration via KollaborPluginSDK
10
+ - Direct plugin-to-plugin communication
11
+ - Event bus messaging
12
+ - Dynamic service discovery patterns
13
+ - Plugin health dashboard functionality
14
+
15
+ Perfect for developers learning the plugin system!
16
+ """
17
+
18
+ import datetime
19
+ import logging
20
+ import time
21
+ from typing import Any, Dict, List, Optional
22
+
23
+ # Import event system components
24
+ import sys
25
+ from pathlib import Path
26
+ sys.path.insert(0, str(Path(__file__).parent.parent))
27
+
28
+ from core.events import Event, EventType, Hook, HookPriority
29
+
30
+ # [TOOL] PLUGIN ECOSYSTEM IMPORTS - Showcasing factory and SDK integration
31
+ try:
32
+ from core.llm.plugin_sdk import KollaborPluginSDK
33
+ from core.plugins.factory import PluginFactory
34
+ SDK_AVAILABLE = True
35
+ except ImportError:
36
+ # Graceful degradation if SDK not available
37
+ SDK_AVAILABLE = False
38
+
39
+ logger = logging.getLogger(__name__)
40
+
41
+
42
+ class HookMonitoringPlugin:
43
+ """[SHOWCASE] SHOWCASE: A comprehensive hook monitoring system demonstrating ALL plugin ecosystem features!"""
44
+
45
+ def __init__(self, name: str, state_manager, event_bus, renderer, config) -> None:
46
+ """Initialize the hook monitoring plugin with full ecosystem integration.
47
+
48
+ This initialization showcases:
49
+ - Basic plugin setup
50
+ - Plugin factory access for service discovery
51
+ - SDK initialization for service registration
52
+ - Cross-plugin communication setup
53
+
54
+ Args:
55
+ name: Plugin name.
56
+ state_manager: State management system.
57
+ event_bus: Event bus for hook registration.
58
+ renderer: Terminal renderer.
59
+ config: Configuration manager.
60
+ """
61
+ # [DATA] BASIC PLUGIN SETUP
62
+ self.name = name
63
+ self.state_manager = state_manager
64
+ self.event_bus = event_bus
65
+ self.renderer = renderer
66
+ self.config = config
67
+ logger.info(f"[INIT] Initializing HookMonitoringPlugin: {name}")
68
+
69
+ # [DATA] HOOK MONITORING STATE - Core monitoring functionality
70
+ self.hook_executions = 0
71
+ self.last_hook_event = "None"
72
+ self.failed_hooks = 0
73
+ self.timeout_hooks = 0
74
+ self.hook_performance = {} # event_type -> {total_time, count, avg_time}
75
+ self.error_log = [] # Recent errors for debugging
76
+ self.hook_health_status = "Starting"
77
+
78
+ # [FIND] PLUGIN ECOSYSTEM STATE - Showcasing service discovery
79
+ self.discovered_plugins = {} # plugin_name -> plugin_instance
80
+ self.available_services = {} # service_name -> plugin_info
81
+ self.plugin_health_stats = {} # plugin_name -> health_metrics
82
+ self.cross_plugin_messages = [] # Recent inter-plugin communications
83
+
84
+ # [TOOL] PLUGIN FACTORY ACCESS - Demonstrating plugin discovery
85
+ # This shows how plugins can discover and communicate with each other
86
+ self.plugin_factory: Optional[PluginFactory] = None
87
+ self.plugin_discovery_enabled = config.get("plugins.hook_monitoring.enable_plugin_discovery", True)
88
+
89
+ # [TOOL] SDK INITIALIZATION - Demonstrating service registration
90
+ # This shows how plugins can register services for other plugins to use
91
+ self.sdk: Optional[KollaborPluginSDK] = None
92
+ self.service_registration_enabled = config.get("plugins.hook_monitoring.enable_service_registration", True)
93
+
94
+ if SDK_AVAILABLE and self.service_registration_enabled:
95
+ self.sdk = KollaborPluginSDK()
96
+ logger.info("SDK initialized - ready for service registration")
97
+
98
+ # [COMM] CROSS-PLUGIN COMMUNICATION - Setup for plugin messaging
99
+ self.enable_cross_plugin_comm = config.get("plugins.hook_monitoring.enable_cross_plugin_communication", True)
100
+ self.message_history_limit = config.get("plugins.hook_monitoring.message_history_limit", 20)
101
+
102
+ # [TARGET] CREATE HOOKS - Standard hook creation for monitoring
103
+ self.hooks = self._create_all_hooks()
104
+
105
+ logger.debug(f"HookMonitoringPlugin fully initialized with ecosystem features!")
106
+
107
+ def get_status_lines(self) -> Dict[str, List[str]]:
108
+ """Get status lines for the hook monitoring plugin organized by area.
109
+
110
+ Returns:
111
+ Dictionary with status lines organized by areas A, B, C.
112
+ """
113
+ # Check if status display is enabled for this plugin
114
+ show_status = self.config.get('plugins.hook_monitoring.show_status', True)
115
+ if not show_status:
116
+ return {"A": [], "B": [], "C": []}
117
+
118
+ enabled = self.config.get('plugins.hook_monitoring.enabled', False)
119
+ debug_mode = self.config.get('plugins.hook_monitoring.debug_logging', False)
120
+
121
+ # Hook monitoring status goes to area B (system monitoring)
122
+ if not enabled:
123
+ return {"A": [], "B": ["Hook Monitor: Off"], "C": []}
124
+
125
+ # Calculate failure rate for health display
126
+ failure_rate = 0
127
+ if self.hook_executions > 0:
128
+ failure_rate = (self.failed_hooks + self.timeout_hooks) / self.hook_executions
129
+
130
+ # [FIND] SHOWCASE: Plugin Discovery Status
131
+ discovered_count = len(getattr(self, 'discovered_plugins', {}))
132
+
133
+ # [TOOL] SHOWCASE: Service Registration Status
134
+ registered_services = 3 if (self.service_registration_enabled and SDK_AVAILABLE) else 0
135
+
136
+ # [COMM] SHOWCASE: Cross-Plugin Communication Status
137
+ recent_messages = len(getattr(self, 'cross_plugin_messages', []))
138
+
139
+ return {
140
+ "A": [], # No area A content for hook monitoring
141
+ "B": [ # System monitoring goes in area B
142
+ f"Monitor: {self.hook_health_status}",
143
+ f"Executions: {self.hook_executions}",
144
+ f"Plugins: {discovered_count}",
145
+ f"Services: {registered_services}",
146
+ f"Messages: {recent_messages}",
147
+ f"Rate: {failure_rate:.1%}" if self.hook_executions > 0 else "[FAST] Rate: N/A"
148
+ ],
149
+ "C": [ # Detailed ecosystem info in area C
150
+ f"SHOWCASE: Plugin Ecosystem Demo",
151
+ f"Last Event: {self.last_hook_event[:20]}",
152
+ f"Discovery: {'[OK]' if self.plugin_discovery_enabled else '[X]'}",
153
+ f"SDK: {'[OK]' if SDK_AVAILABLE else '[X]'}",
154
+ f"Debug: {'On' if debug_mode else 'Off'}"
155
+ ]
156
+ }
157
+
158
+ async def initialize(self) -> None:
159
+ """[INIT] SHOWCASE: Initialize with full plugin ecosystem integration!
160
+
161
+ This method demonstrates:
162
+ 1. Plugin factory access for discovering other plugins
163
+ 2. SDK service registration for providing monitoring services
164
+ 3. Cross-plugin communication setup
165
+ 4. Dynamic service discovery patterns
166
+ """
167
+ logger.info("Starting HookMonitoringPlugin initialization...")
168
+
169
+ # [FIND] STEP 1: PLUGIN DISCOVERY - Demonstrating how to find other plugins
170
+ if self.plugin_discovery_enabled:
171
+ await self._discover_other_plugins()
172
+
173
+ # [TOOL] STEP 2: SERVICE REGISTRATION - Showcasing how to offer services to other plugins
174
+ if self.service_registration_enabled and self.sdk:
175
+ await self._register_monitoring_services()
176
+
177
+ # [COMM] STEP 3: CROSS-PLUGIN COMMUNICATION SETUP
178
+ if self.enable_cross_plugin_comm:
179
+ await self._setup_cross_plugin_communication()
180
+
181
+ # [DATA] STEP 4: INITIALIZE PLUGIN HEALTH MONITORING
182
+ await self._initialize_plugin_health_monitoring()
183
+
184
+ logger.info("HookMonitoringPlugin initialization complete - all ecosystem features active!")
185
+
186
+ async def _discover_other_plugins(self) -> None:
187
+ """[FIND] SHOWCASE: Discover other plugins using PluginFactory.
188
+
189
+ This demonstrates the core pattern for plugin discovery:
190
+ - Access the plugin factory (would typically be injected)
191
+ - Get all plugin instances
192
+ - Analyze their capabilities
193
+ - Store references for later communication
194
+ """
195
+ logger.debug("Discovering other plugins in the ecosystem...")
196
+
197
+ try:
198
+ # [TOOL] ACCESS PLUGIN FACTORY - In real implementation, this would be injected
199
+ # For demonstration, we simulate what the factory discovery looks like
200
+ if hasattr(self.renderer, 'plugin_instances'):
201
+ # This simulates getting access to the factory through the renderer
202
+ plugin_instances = getattr(self.renderer, 'plugin_instances', {})
203
+ else:
204
+ # Fallback demonstration data
205
+ plugin_instances = {
206
+ "EnhancedInputPlugin": "simulated_input_plugin",
207
+ "WorkflowEnforcementPlugin": "simulated_workflow_plugin",
208
+ # This would be populated by: factory.get_all_instances()
209
+ }
210
+
211
+ self.discovered_plugins = plugin_instances
212
+
213
+ # [DATA] ANALYZE DISCOVERED PLUGINS - Check their capabilities
214
+ for plugin_name, plugin_instance in plugin_instances.items():
215
+ if plugin_name != self.name: # Don't analyze ourselves
216
+ await self._analyze_plugin_capabilities(plugin_name, plugin_instance)
217
+
218
+ logger.info(f"Discovered {len(self.discovered_plugins)} plugins: {list(self.discovered_plugins.keys())}")
219
+
220
+ except Exception as e:
221
+ logger.warning(f"Plugin discovery failed (demonstration mode): {e}")
222
+ # In production, this would use: factory.get_all_instances()
223
+
224
+ async def _analyze_plugin_capabilities(self, plugin_name: str, plugin_instance: Any) -> None:
225
+ """[FIND] SHOWCASE: Analyze what services a plugin provides.
226
+
227
+ This demonstrates how to discover plugin capabilities:
228
+ - Check for service methods
229
+ - Analyze configuration options
230
+ - Determine communication interfaces
231
+ """
232
+ capabilities = {
233
+ "has_get_services": hasattr(plugin_instance, 'get_services'),
234
+ "has_status_lines": hasattr(plugin_instance, 'get_status_lines'),
235
+ "has_initialize": hasattr(plugin_instance, 'initialize'),
236
+ "has_register_hooks": hasattr(plugin_instance, 'register_hooks'),
237
+ "supports_messaging": hasattr(plugin_instance, 'handle_message'),
238
+ "plugin_type": type(plugin_instance).__name__ if plugin_instance != "simulated_input_plugin" else "EnhancedInputPlugin"
239
+ }
240
+
241
+ # [NOTE] STORE PLUGIN INFORMATION - For later use in health monitoring
242
+ self.plugin_health_stats[plugin_name] = {
243
+ "capabilities": capabilities,
244
+ "last_seen": datetime.datetime.now(),
245
+ "status": "discovered",
246
+ "message_count": 0
247
+ }
248
+
249
+ logger.debug(f"Analyzed {plugin_name}: {capabilities}")
250
+
251
+ async def _register_monitoring_services(self) -> None:
252
+ """[TOOL] SHOWCASE: Register monitoring services for other plugins to use.
253
+
254
+ This demonstrates how plugins offer services to the ecosystem:
255
+ - Register performance monitoring service
256
+ - Register health check service
257
+ - Register metrics collection service
258
+ """
259
+ logger.debug("Registering monitoring services for other plugins...")
260
+
261
+ if not self.sdk:
262
+ logger.warning("SDK not available - cannot register services")
263
+ return
264
+
265
+ try:
266
+ # [DATA] SERVICE 1: Performance Monitoring
267
+ self.sdk.register_custom_tool({
268
+ "name": "monitor_performance",
269
+ "description": "Monitor plugin performance and hook execution times",
270
+ "handler": self._provide_performance_monitoring,
271
+ "parameters": {
272
+ "plugin_name": {"type": "string", "description": "Plugin to monitor"},
273
+ "metric_type": {"type": "string", "description": "Type of metric to collect"}
274
+ },
275
+ "plugin": self.name,
276
+ "enabled": True,
277
+ "category": "monitoring"
278
+ })
279
+
280
+ # [HEALTH] SERVICE 2: Health Checking
281
+ self.sdk.register_custom_tool({
282
+ "name": "check_plugin_health",
283
+ "description": "Check the health status of any plugin in the system",
284
+ "handler": self._provide_health_check,
285
+ "parameters": {
286
+ "plugin_name": {"type": "string", "description": "Plugin to check"},
287
+ "detailed": {"type": "boolean", "description": "Return detailed health info"}
288
+ },
289
+ "plugin": self.name,
290
+ "enabled": True,
291
+ "category": "health"
292
+ })
293
+
294
+ # [METRICS] SERVICE 3: Metrics Collection
295
+ self.sdk.register_custom_tool({
296
+ "name": "collect_system_metrics",
297
+ "description": "Collect comprehensive system and plugin metrics",
298
+ "handler": self._provide_metrics_collection,
299
+ "parameters": {
300
+ "time_range": {"type": "string", "description": "Time range for metrics"},
301
+ "include_performance": {"type": "boolean", "description": "Include performance data"}
302
+ },
303
+ "plugin": self.name,
304
+ "enabled": True,
305
+ "category": "analytics"
306
+ })
307
+
308
+ logger.debug("Registered 3 monitoring services - other plugins can now use our services!")
309
+
310
+ except Exception as e:
311
+ logger.error(f"Service registration failed: {e}")
312
+
313
+ async def _setup_cross_plugin_communication(self) -> None:
314
+ """[COMM] SHOWCASE: Setup cross-plugin communication channels.
315
+
316
+ This demonstrates how to:
317
+ - Set up message handlers for plugin-to-plugin communication
318
+ - Register for event bus notifications
319
+ - Create communication protocols
320
+ """
321
+ logger.debug("Setting up cross-plugin communication...")
322
+
323
+ # [COMM] REGISTER MESSAGE HANDLER - For receiving messages from other plugins
324
+ # In a real implementation, this would integrate with the event bus
325
+ self.message_handlers = {
326
+ "health_check_request": self._handle_health_check_request,
327
+ "performance_data_request": self._handle_performance_data_request,
328
+ "plugin_status_update": self._handle_plugin_status_update
329
+ }
330
+
331
+ logger.debug("Cross-plugin communication setup complete!")
332
+
333
+ async def _initialize_plugin_health_monitoring(self) -> None:
334
+ """[DATA] SHOWCASE: Initialize comprehensive plugin health monitoring.
335
+
336
+ This sets up monitoring for:
337
+ - Plugin performance metrics
338
+ - Communication patterns
339
+ - Service usage statistics
340
+ - System health indicators
341
+ """
342
+ logger.debug("Initializing plugin health monitoring...")
343
+
344
+ # [TARGET] HEALTH MONITORING CONFIGURATION
345
+ self.health_monitoring = {
346
+ "enabled": True,
347
+ "check_interval": self.config.get("plugins.hook_monitoring.health_check_interval", 30),
348
+ "performance_threshold": self.config.get("plugins.hook_monitoring.performance_threshold_ms", 100),
349
+ "memory_threshold": self.config.get("plugins.hook_monitoring.memory_threshold_mb", 50)
350
+ }
351
+
352
+ # [METRICS] METRICS COLLECTION SETUP
353
+ self.metrics_collection = {
354
+ "hook_performance": {},
355
+ "plugin_communications": [],
356
+ "service_usage": {},
357
+ "error_patterns": []
358
+ }
359
+
360
+ logger.debug("Plugin health monitoring initialized - comprehensive monitoring active!")
361
+
362
+ async def register_hooks(self) -> None:
363
+ """Register hook monitoring plugin hooks for all event types."""
364
+ if not self.config.get('plugins.hook_monitoring.enabled', True):
365
+ logger.info("Hook monitoring plugin disabled, not registering hooks")
366
+ return
367
+
368
+ logger.info(f"Hook Monitor: Registering {len(self.hooks)} monitoring hooks for system health tracking")
369
+
370
+ for hook in self.hooks:
371
+ try:
372
+ await self.event_bus.register_hook(hook)
373
+ logger.debug(f"Hook Monitor: Registered {hook.name} for {hook.event_type.value}")
374
+ except Exception as e:
375
+ logger.error(f"Hook Monitor: Failed to register {hook.name}: {e}")
376
+
377
+ logger.info("Hook Monitor: Registration completed - monitoring system active")
378
+
379
+ # [DATA] REGISTER STATUS VIEW - Register custom status view for developer metrics
380
+ await self._register_status_view()
381
+
382
+ async def _register_status_view(self) -> None:
383
+ """Register developer metrics status view."""
384
+ try:
385
+ # Check if renderer has status registry
386
+ if (hasattr(self.renderer, 'status_renderer') and
387
+ self.renderer.status_renderer and
388
+ hasattr(self.renderer.status_renderer, 'status_registry') and
389
+ self.renderer.status_renderer.status_registry):
390
+
391
+ from core.io.status_renderer import StatusViewConfig, BlockConfig
392
+
393
+ # Create developer metrics view
394
+ developer_view = StatusViewConfig(
395
+ name="Developer Metrics",
396
+ plugin_source="hook_monitoring",
397
+ priority=400, # Lower than core views
398
+ blocks=[
399
+ BlockConfig(
400
+ width_fraction=1.0,
401
+ content_provider=self._get_developer_metrics_content,
402
+ title="Developer Metrics",
403
+ priority=100
404
+ )
405
+ ]
406
+ )
407
+
408
+ registry = self.renderer.status_renderer.status_registry
409
+ registry.register_status_view("hook_monitoring", developer_view)
410
+ logger.info("[OK] Registered 'Developer Metrics' status view")
411
+
412
+ else:
413
+ logger.warning("Status registry not available - cannot register status view")
414
+
415
+ except Exception as e:
416
+ logger.error(f"Failed to register status view: {e}")
417
+
418
+ def _get_developer_metrics_content(self) -> List[str]:
419
+ """Get developer metrics content for status view."""
420
+ try:
421
+ enabled = self.config.get('plugins.hook_monitoring.enabled', False)
422
+ if not enabled:
423
+ return ["Hook Monitor: - Off"]
424
+
425
+ # Calculate failure rate for health display
426
+ failure_rate = 0
427
+ if self.hook_executions > 0:
428
+ failure_rate = (self.failed_hooks + self.timeout_hooks) / self.hook_executions
429
+
430
+ # Plugin discovery status
431
+ discovered_count = len(getattr(self, 'discovered_plugins', {}))
432
+
433
+ # Service registration status
434
+ registered_services = 3 if (self.service_registration_enabled and SDK_AVAILABLE) else 0
435
+
436
+ # Cross-plugin communication status
437
+ recent_messages = len(getattr(self, 'cross_plugin_messages', []))
438
+
439
+ return [
440
+ f"√ Monitor: {self.hook_health_status} ··· Executions: {self.hook_executions}",
441
+ f"+ Plugins: {discovered_count} ··· × Services: {registered_services} ··· Rate: {failure_rate:.1%}" if self.hook_executions > 0 else f"+ Plugins: {discovered_count} ··· × Services: {registered_services} ··· Rate: N/A"
442
+ ]
443
+
444
+ except Exception as e:
445
+ logger.error(f"Error getting developer metrics content: {e}")
446
+ return ["Developer Metrics: Error"]
447
+
448
+ async def shutdown(self) -> None:
449
+ """Shutdown the hook monitoring plugin."""
450
+ logger.info(f"Hook Monitor: Shutting down - processed {self.hook_executions} events, {self.failed_hooks} failures")
451
+ self._log_final_report()
452
+ # Only show shutdown message if not in pipe mode
453
+ # if not getattr(self.renderer, 'pipe_mode', False):
454
+ # print("\rHook Monitor shut down")
455
+
456
+ @staticmethod
457
+ def get_default_config() -> Dict[str, Any]:
458
+ """[TOOL] SHOWCASE: Comprehensive configuration for hook monitoring plugin.
459
+
460
+ This configuration demonstrates all available plugin ecosystem features:
461
+ - Basic monitoring settings
462
+ - Plugin discovery configuration
463
+ - Service registration settings
464
+ - Cross-plugin communication options
465
+ - Health monitoring parameters
466
+ """
467
+ return {
468
+ "plugins": {
469
+ "hook_monitoring": {
470
+ # [DATA] BASIC MONITORING CONFIGURATION
471
+ "enabled": True,
472
+ "debug_logging": True,
473
+ "show_status": True,
474
+ "hook_timeout": 5,
475
+ "log_all_events": True,
476
+ "log_event_data": False,
477
+ "log_performance": True,
478
+ "log_failures_only": False,
479
+ "performance_threshold_ms": 100,
480
+ "max_error_log_size": 50,
481
+
482
+ # [FIND] PLUGIN DISCOVERY CONFIGURATION - Showcase feature
483
+ "enable_plugin_discovery": True,
484
+ "discovery_interval": 30, # seconds
485
+ "auto_analyze_capabilities": True,
486
+
487
+ # [TOOL] SERVICE REGISTRATION CONFIGURATION - Showcase feature
488
+ "enable_service_registration": True,
489
+ "register_performance_service": True,
490
+ "register_health_service": True,
491
+ "register_metrics_service": True,
492
+
493
+ # [COMM] CROSS-PLUGIN COMMUNICATION - Showcase feature
494
+ "enable_cross_plugin_communication": True,
495
+ "message_history_limit": 20,
496
+ "auto_respond_to_health_checks": True,
497
+
498
+ # [HEALTH] HEALTH MONITORING CONFIGURATION - Showcase feature
499
+ "health_check_interval": 30, # seconds
500
+ "memory_threshold_mb": 50,
501
+ "performance_degradation_threshold": 0.15,
502
+
503
+ # [METRICS] METRICS COLLECTION - Showcase feature
504
+ "collect_plugin_metrics": True,
505
+ "metrics_retention_hours": 24,
506
+ "detailed_performance_tracking": True,
507
+
508
+ # [TARGET] DASHBOARD FEATURES - Showcase feature
509
+ "enable_health_dashboard": True,
510
+ "dashboard_update_interval": 10, # seconds
511
+ "show_plugin_interactions": True,
512
+ "show_service_usage": True
513
+ }
514
+ }
515
+ }
516
+
517
+ @staticmethod
518
+ def get_startup_info(config) -> List[str]:
519
+ """[INIT] SHOWCASE: Startup information displaying all ecosystem features.
520
+
521
+ Args:
522
+ config: Configuration manager instance.
523
+
524
+ Returns:
525
+ List of strings to display during startup.
526
+ """
527
+ return [
528
+ f"[SHOWCASE] HOOK MONITORING SHOWCASE PLUGIN",
529
+ f"Monitor: {config.get('plugins.hook_monitoring.enabled')}",
530
+ f"Plugin Discovery: {config.get('plugins.hook_monitoring.enable_plugin_discovery')}",
531
+ f"Service Registration: {config.get('plugins.hook_monitoring.enable_service_registration')}",
532
+ f"Cross-Plugin Comm: {config.get('plugins.hook_monitoring.enable_cross_plugin_communication')}",
533
+ f"Health Dashboard: {config.get('plugins.hook_monitoring.enable_health_dashboard')}",
534
+ f"Performance Threshold: {config.get('plugins.hook_monitoring.performance_threshold_ms')}ms",
535
+ f"[TARGET] Demonstrates ALL plugin ecosystem features!"
536
+ ]
537
+
538
+ @staticmethod
539
+ def get_config_widgets() -> Dict[str, Any]:
540
+ """Get configuration widgets for this plugin.
541
+
542
+ Returns:
543
+ Widget section definition for the config modal.
544
+ """
545
+ return {
546
+ "title": "Hook Monitoring Plugin",
547
+ "widgets": [
548
+ {"type": "checkbox", "label": "Debug Logging", "config_path": "plugins.hook_monitoring.debug_logging", "help": "Enable detailed debug logging for hooks"},
549
+ {"type": "checkbox", "label": "Show Status", "config_path": "plugins.hook_monitoring.show_status", "help": "Display hook monitoring status"},
550
+ {"type": "slider", "label": "Hook Timeout", "config_path": "plugins.hook_monitoring.hook_timeout", "min_value": 1, "max_value": 30, "step": 1, "help": "Timeout for hook execution in seconds"},
551
+ {"type": "checkbox", "label": "Log All Events", "config_path": "plugins.hook_monitoring.log_all_events", "help": "Log every hook event"},
552
+ {"type": "checkbox", "label": "Log Event Data", "config_path": "plugins.hook_monitoring.log_event_data", "help": "Include event data in logs"},
553
+ {"type": "checkbox", "label": "Log Performance", "config_path": "plugins.hook_monitoring.log_performance", "help": "Log performance metrics for hooks"},
554
+ {"type": "checkbox", "label": "Log Failures Only", "config_path": "plugins.hook_monitoring.log_failures_only", "help": "Only log failed hook executions"},
555
+ {"type": "slider", "label": "Performance Threshold", "config_path": "plugins.hook_monitoring.performance_threshold_ms", "min_value": 10, "max_value": 1000, "step": 10, "help": "Performance warning threshold in milliseconds"},
556
+ {"type": "slider", "label": "Max Error Log Size", "config_path": "plugins.hook_monitoring.max_error_log_size", "min_value": 10, "max_value": 500, "step": 10, "help": "Maximum error log entries to keep"},
557
+ {"type": "checkbox", "label": "Enable Plugin Discovery", "config_path": "plugins.hook_monitoring.enable_plugin_discovery", "help": "Automatically discover new plugins"},
558
+ {"type": "slider", "label": "Discovery Interval", "config_path": "plugins.hook_monitoring.discovery_interval", "min_value": 5, "max_value": 300, "step": 5, "help": "Plugin discovery interval in seconds"},
559
+ {"type": "checkbox", "label": "Auto Analyze Capabilities", "config_path": "plugins.hook_monitoring.auto_analyze_capabilities", "help": "Automatically analyze plugin capabilities"},
560
+ {"type": "checkbox", "label": "Enable Service Registration", "config_path": "plugins.hook_monitoring.enable_service_registration", "help": "Register monitoring services with event bus"},
561
+ {"type": "checkbox", "label": "Register Performance Service", "config_path": "plugins.hook_monitoring.register_performance_service", "help": "Register performance monitoring service"},
562
+ {"type": "checkbox", "label": "Register Health Service", "config_path": "plugins.hook_monitoring.register_health_service", "help": "Register health monitoring service"},
563
+ {"type": "checkbox", "label": "Register Metrics Service", "config_path": "plugins.hook_monitoring.register_metrics_service", "help": "Register metrics collection service"},
564
+ {"type": "checkbox", "label": "Enable Cross Plugin Communication", "config_path": "plugins.hook_monitoring.enable_cross_plugin_communication", "help": "Allow plugins to communicate with each other"},
565
+ {"type": "slider", "label": "Message History Limit", "config_path": "plugins.hook_monitoring.message_history_limit", "min_value": 5, "max_value": 100, "step": 5, "help": "Maximum message history entries"},
566
+ {"type": "checkbox", "label": "Auto Respond to Health Checks", "config_path": "plugins.hook_monitoring.auto_respond_to_health_checks", "help": "Automatically respond to health check requests"},
567
+ {"type": "slider", "label": "Health Check Interval", "config_path": "plugins.hook_monitoring.health_check_interval", "min_value": 10, "max_value": 300, "step": 10, "help": "Health check interval in seconds"},
568
+ {"type": "slider", "label": "Memory Threshold MB", "config_path": "plugins.hook_monitoring.memory_threshold_mb", "min_value": 10, "max_value": 500, "step": 10, "help": "Memory usage warning threshold in MB"},
569
+ {"type": "slider", "label": "Performance Degradation Threshold", "config_path": "plugins.hook_monitoring.performance_degradation_threshold", "min_value": 0.05, "max_value": 0.5, "step": 0.05, "help": "Performance degradation warning threshold"},
570
+ {"type": "checkbox", "label": "Collect Plugin Metrics", "config_path": "plugins.hook_monitoring.collect_plugin_metrics", "help": "Collect detailed metrics for all plugins"},
571
+ {"type": "slider", "label": "Metrics Retention Hours", "config_path": "plugins.hook_monitoring.metrics_retention_hours", "min_value": 1, "max_value": 168, "step": 1, "help": "How long to retain metrics data (hours)"},
572
+ {"type": "checkbox", "label": "Detailed Performance Tracking", "config_path": "plugins.hook_monitoring.detailed_performance_tracking", "help": "Enable detailed performance tracking"},
573
+ {"type": "checkbox", "label": "Enable Health Dashboard", "config_path": "plugins.hook_monitoring.enable_health_dashboard", "help": "Show health monitoring dashboard"},
574
+ {"type": "slider", "label": "Dashboard Update Interval", "config_path": "plugins.hook_monitoring.dashboard_update_interval", "min_value": 1, "max_value": 60, "step": 1, "help": "Dashboard refresh interval in seconds"},
575
+ {"type": "checkbox", "label": "Show Plugin Interactions", "config_path": "plugins.hook_monitoring.show_plugin_interactions", "help": "Display plugin interaction information"},
576
+ {"type": "checkbox", "label": "Show Service Usage", "config_path": "plugins.hook_monitoring.show_service_usage", "help": "Display service usage statistics"}
577
+ ]
578
+ }
579
+
580
+ def _create_all_hooks(self) -> List[Hook]:
581
+ """[TOOL] SHOWCASE: Create comprehensive hooks for monitoring all event types.
582
+
583
+ This demonstrates complete system monitoring by hooking into all
584
+ available event types to provide full visibility into system behavior.
585
+
586
+ Returns:
587
+ List of hooks covering all event types for comprehensive monitoring.
588
+ """
589
+ hooks = []
590
+ timeout = self.config.get('plugins.hook_monitoring.hook_timeout', 5)
591
+
592
+ # User input events
593
+ hooks.extend([
594
+ Hook(
595
+ name="monitor_user_input_pre",
596
+ plugin_name=self.name,
597
+ event_type=EventType.USER_INPUT_PRE,
598
+ priority=HookPriority.POSTPROCESSING.value,
599
+ callback=self._log_hook_execution,
600
+ timeout=timeout
601
+ ),
602
+ Hook(
603
+ name="monitor_user_input",
604
+ plugin_name=self.name,
605
+ event_type=EventType.USER_INPUT,
606
+ priority=HookPriority.POSTPROCESSING.value,
607
+ callback=self._log_hook_execution,
608
+ timeout=timeout
609
+ ),
610
+ Hook(
611
+ name="monitor_user_input_post",
612
+ plugin_name=self.name,
613
+ event_type=EventType.USER_INPUT_POST,
614
+ priority=HookPriority.POSTPROCESSING.value,
615
+ callback=self._log_hook_execution,
616
+ timeout=timeout
617
+ )
618
+ ])
619
+
620
+ # Key press events
621
+ hooks.extend([
622
+ Hook(
623
+ name="test_key_press_pre",
624
+ plugin_name=self.name,
625
+ event_type=EventType.KEY_PRESS_PRE,
626
+ priority=HookPriority.PREPROCESSING.value,
627
+ callback=self._log_hook_execution,
628
+ timeout=timeout
629
+ ),
630
+ Hook(
631
+ name="test_key_press",
632
+ plugin_name=self.name,
633
+ event_type=EventType.KEY_PRESS,
634
+ priority=HookPriority.PREPROCESSING.value,
635
+ callback=self._log_hook_execution,
636
+ timeout=timeout
637
+ ),
638
+ Hook(
639
+ name="test_key_press_post",
640
+ plugin_name=self.name,
641
+ event_type=EventType.KEY_PRESS_POST,
642
+ priority=HookPriority.POSTPROCESSING.value,
643
+ callback=self._log_hook_execution,
644
+ timeout=timeout
645
+ )
646
+ ])
647
+
648
+ # Paste events
649
+ hooks.append(
650
+ Hook(
651
+ name="test_paste_detected",
652
+ plugin_name=self.name,
653
+ event_type=EventType.PASTE_DETECTED,
654
+ priority=HookPriority.PREPROCESSING.value,
655
+ callback=self._log_hook_execution,
656
+ timeout=timeout
657
+ )
658
+ )
659
+
660
+ # LLM events
661
+ hooks.extend([
662
+ Hook(
663
+ name="test_llm_request_pre",
664
+ plugin_name=self.name,
665
+ event_type=EventType.LLM_REQUEST_PRE,
666
+ priority=HookPriority.PREPROCESSING.value,
667
+ callback=self._log_hook_execution,
668
+ timeout=timeout
669
+ ),
670
+ Hook(
671
+ name="test_llm_request",
672
+ plugin_name=self.name,
673
+ event_type=EventType.LLM_REQUEST,
674
+ priority=HookPriority.LLM.value,
675
+ callback=self._log_hook_execution,
676
+ timeout=timeout
677
+ ),
678
+ Hook(
679
+ name="test_llm_request_post",
680
+ plugin_name=self.name,
681
+ event_type=EventType.LLM_REQUEST_POST,
682
+ priority=HookPriority.POSTPROCESSING.value,
683
+ callback=self._log_hook_execution,
684
+ timeout=timeout
685
+ ),
686
+ Hook(
687
+ name="test_llm_response_pre",
688
+ plugin_name=self.name,
689
+ event_type=EventType.LLM_RESPONSE_PRE,
690
+ priority=HookPriority.PREPROCESSING.value,
691
+ callback=self._log_hook_execution,
692
+ timeout=timeout
693
+ ),
694
+ Hook(
695
+ name="test_llm_response",
696
+ plugin_name=self.name,
697
+ event_type=EventType.LLM_RESPONSE,
698
+ priority=HookPriority.LLM.value,
699
+ callback=self._log_hook_execution,
700
+ timeout=timeout
701
+ ),
702
+ Hook(
703
+ name="test_llm_response_post",
704
+ plugin_name=self.name,
705
+ event_type=EventType.LLM_RESPONSE_POST,
706
+ priority=HookPriority.POSTPROCESSING.value,
707
+ callback=self._log_hook_execution,
708
+ timeout=timeout
709
+ ),
710
+ Hook(
711
+ name="test_llm_thinking",
712
+ plugin_name=self.name,
713
+ event_type=EventType.LLM_THINKING,
714
+ priority=HookPriority.LLM.value,
715
+ callback=self._log_hook_execution,
716
+ timeout=timeout
717
+ ),
718
+ Hook(
719
+ name="test_cancel_request",
720
+ plugin_name=self.name,
721
+ event_type=EventType.CANCEL_REQUEST,
722
+ priority=HookPriority.LLM.value,
723
+ callback=self._log_hook_execution,
724
+ timeout=timeout
725
+ )
726
+ ])
727
+
728
+ # Tool events
729
+ hooks.extend([
730
+ Hook(
731
+ name="test_tool_call_pre",
732
+ plugin_name=self.name,
733
+ event_type=EventType.TOOL_CALL_PRE,
734
+ priority=HookPriority.PREPROCESSING.value,
735
+ callback=self._log_hook_execution,
736
+ timeout=timeout
737
+ ),
738
+ Hook(
739
+ name="test_tool_call",
740
+ plugin_name=self.name,
741
+ event_type=EventType.TOOL_CALL,
742
+ priority=HookPriority.LLM.value,
743
+ callback=self._log_hook_execution,
744
+ timeout=timeout
745
+ ),
746
+ Hook(
747
+ name="test_tool_call_post",
748
+ plugin_name=self.name,
749
+ event_type=EventType.TOOL_CALL_POST,
750
+ priority=HookPriority.POSTPROCESSING.value,
751
+ callback=self._log_hook_execution,
752
+ timeout=timeout
753
+ )
754
+ ])
755
+
756
+ # System events
757
+ hooks.extend([
758
+ Hook(
759
+ name="test_system_startup",
760
+ plugin_name=self.name,
761
+ event_type=EventType.SYSTEM_STARTUP,
762
+ priority=HookPriority.SYSTEM.value,
763
+ callback=self._log_hook_execution,
764
+ timeout=timeout
765
+ ),
766
+ Hook(
767
+ name="test_system_shutdown",
768
+ plugin_name=self.name,
769
+ event_type=EventType.SYSTEM_SHUTDOWN,
770
+ priority=HookPriority.SYSTEM.value,
771
+ callback=self._log_hook_execution,
772
+ timeout=timeout
773
+ ),
774
+ Hook(
775
+ name="test_render_frame",
776
+ plugin_name=self.name,
777
+ event_type=EventType.RENDER_FRAME,
778
+ priority=HookPriority.DISPLAY.value,
779
+ callback=self._log_hook_execution,
780
+ timeout=timeout
781
+ )
782
+ ])
783
+
784
+ # Input rendering events
785
+ hooks.extend([
786
+ Hook(
787
+ name="test_input_render_pre",
788
+ plugin_name=self.name,
789
+ event_type=EventType.INPUT_RENDER_PRE,
790
+ priority=HookPriority.PREPROCESSING.value,
791
+ callback=self._log_hook_execution,
792
+ timeout=timeout
793
+ ),
794
+ Hook(
795
+ name="test_input_render",
796
+ plugin_name=self.name,
797
+ event_type=EventType.INPUT_RENDER,
798
+ priority=HookPriority.DISPLAY.value,
799
+ callback=self._log_hook_execution,
800
+ timeout=timeout
801
+ ),
802
+ Hook(
803
+ name="test_input_render_post",
804
+ plugin_name=self.name,
805
+ event_type=EventType.INPUT_RENDER_POST,
806
+ priority=HookPriority.POSTPROCESSING.value,
807
+ callback=self._log_hook_execution,
808
+ timeout=timeout
809
+ )
810
+ ])
811
+
812
+ # Command menu events
813
+ hooks.extend([
814
+ Hook(
815
+ name="test_command_menu_show",
816
+ plugin_name=self.name,
817
+ event_type=EventType.COMMAND_MENU_SHOW,
818
+ priority=HookPriority.DISPLAY.value,
819
+ callback=self._log_hook_execution,
820
+ timeout=timeout
821
+ ),
822
+ Hook(
823
+ name="test_command_menu_navigate",
824
+ plugin_name=self.name,
825
+ event_type=EventType.COMMAND_MENU_NAVIGATE,
826
+ priority=HookPriority.DISPLAY.value,
827
+ callback=self._log_hook_execution,
828
+ timeout=timeout
829
+ ),
830
+ Hook(
831
+ name="test_command_menu_select",
832
+ plugin_name=self.name,
833
+ event_type=EventType.COMMAND_MENU_SELECT,
834
+ priority=HookPriority.DISPLAY.value,
835
+ callback=self._log_hook_execution,
836
+ timeout=timeout
837
+ ),
838
+ Hook(
839
+ name="test_command_menu_hide",
840
+ plugin_name=self.name,
841
+ event_type=EventType.COMMAND_MENU_HIDE,
842
+ priority=HookPriority.DISPLAY.value,
843
+ callback=self._log_hook_execution,
844
+ timeout=timeout
845
+ )
846
+ ])
847
+
848
+ logger.info(f"Hook Monitor: Created {len(hooks)} monitoring hooks for system health tracking")
849
+ return hooks
850
+
851
+ # [TOOL] SERVICE IMPLEMENTATION METHODS - These are called by other plugins via SDK
852
+
853
+ async def _provide_performance_monitoring(self, params: Dict[str, Any]) -> Dict[str, Any]:
854
+ """[TOOL] SHOWCASE: Performance monitoring service for other plugins.
855
+
856
+ This service can be called by other plugins like:
857
+ result = await sdk.execute_custom_tool("monitor_performance", {
858
+ "plugin_name": "EnhancedInputPlugin",
859
+ "metric_type": "execution_time"
860
+ })
861
+ """
862
+ plugin_name = params.get("plugin_name", "all")
863
+ metric_type = params.get("metric_type", "summary")
864
+
865
+ logger.info(f"[DATA] Performance monitoring requested for {plugin_name}, metric: {metric_type}")
866
+
867
+ if plugin_name == "all":
868
+ # Return performance data for all plugins
869
+ return {
870
+ "status": "success",
871
+ "data": {
872
+ "total_executions": self.hook_executions,
873
+ "performance_metrics": self.hook_performance,
874
+ "health_status": self.hook_health_status,
875
+ "timestamp": datetime.datetime.now().isoformat()
876
+ }
877
+ }
878
+ else:
879
+ # Return specific plugin performance
880
+ plugin_perf = self.plugin_health_stats.get(plugin_name, {})
881
+ return {
882
+ "status": "success",
883
+ "data": {
884
+ "plugin_name": plugin_name,
885
+ "performance": plugin_perf,
886
+ "timestamp": datetime.datetime.now().isoformat()
887
+ }
888
+ }
889
+
890
+ async def _provide_health_check(self, params: Dict[str, Any]) -> Dict[str, Any]:
891
+ """[HEALTH] SHOWCASE: Health check service for other plugins.
892
+
893
+ Other plugins can call this to check system health:
894
+ health = await sdk.execute_custom_tool("check_plugin_health", {
895
+ "plugin_name": "system",
896
+ "detailed": True
897
+ })
898
+ """
899
+ plugin_name = params.get("plugin_name", "system")
900
+ detailed = params.get("detailed", False)
901
+
902
+ logger.info(f"[HEALTH] Health check requested for {plugin_name}, detailed: {detailed}")
903
+
904
+ if plugin_name == "system":
905
+ # System-wide health check
906
+ failure_rate = 0
907
+ if self.hook_executions > 0:
908
+ failure_rate = (self.failed_hooks + self.timeout_hooks) / self.hook_executions
909
+
910
+ health_data = {
911
+ "overall_health": self.hook_health_status,
912
+ "failure_rate": failure_rate,
913
+ "total_plugins": len(self.discovered_plugins),
914
+ "active_plugins": len([p for p in self.plugin_health_stats.values() if p.get("status") == "active"])
915
+ }
916
+
917
+ if detailed:
918
+ health_data.update({
919
+ "plugin_details": self.plugin_health_stats,
920
+ "recent_errors": self.error_log[-5:] if self.error_log else [],
921
+ "performance_summary": self.hook_performance
922
+ })
923
+
924
+ return {"status": "success", "health": health_data}
925
+ else:
926
+ # Specific plugin health check
927
+ plugin_health = self.plugin_health_stats.get(plugin_name, {"status": "unknown"})
928
+ return {"status": "success", "health": plugin_health}
929
+
930
+ async def _provide_metrics_collection(self, params: Dict[str, Any]) -> Dict[str, Any]:
931
+ """[METRICS] SHOWCASE: Metrics collection service for analytics.
932
+
933
+ Other plugins can request comprehensive metrics:
934
+ metrics = await sdk.execute_custom_tool("collect_system_metrics", {
935
+ "time_range": "last_hour",
936
+ "include_performance": True
937
+ })
938
+ """
939
+ time_range = params.get("time_range", "current")
940
+ include_performance = params.get("include_performance", True)
941
+
942
+ logger.info(f"[METRICS] Metrics collection requested for {time_range}, performance: {include_performance}")
943
+
944
+ metrics = {
945
+ "collection_timestamp": datetime.datetime.now().isoformat(),
946
+ "time_range": time_range,
947
+ "system_metrics": {
948
+ "total_hook_executions": self.hook_executions,
949
+ "failed_hooks": self.failed_hooks,
950
+ "timeout_hooks": self.timeout_hooks,
951
+ "health_status": self.hook_health_status,
952
+ "discovered_plugins": len(self.discovered_plugins),
953
+ "active_services": len(self.available_services)
954
+ }
955
+ }
956
+
957
+ if include_performance:
958
+ metrics["performance_metrics"] = self.hook_performance
959
+
960
+ return {"status": "success", "metrics": metrics}
961
+
962
+ # [COMM] CROSS-PLUGIN COMMUNICATION HANDLERS
963
+
964
+ async def _handle_health_check_request(self, message: Dict[str, Any], sender: str) -> None:
965
+ """[COMM] SHOWCASE: Handle health check requests from other plugins.
966
+
967
+ This demonstrates direct plugin-to-plugin communication.
968
+ """
969
+ logger.info(f"[COMM] Health check request received from {sender}")
970
+
971
+ # Record the communication
972
+ self.cross_plugin_messages.append({
973
+ "timestamp": datetime.datetime.now(),
974
+ "sender": sender,
975
+ "message_type": "health_check_request",
976
+ "data": message
977
+ })
978
+
979
+ # Keep message history limited
980
+ if len(self.cross_plugin_messages) > self.message_history_limit:
981
+ self.cross_plugin_messages = self.cross_plugin_messages[-self.message_history_limit:]
982
+
983
+ # Update sender's plugin stats
984
+ if sender in self.plugin_health_stats:
985
+ self.plugin_health_stats[sender]["message_count"] += 1
986
+ self.plugin_health_stats[sender]["last_seen"] = datetime.datetime.now()
987
+
988
+ async def _handle_performance_data_request(self, message: Dict[str, Any], sender: str) -> Dict[str, Any]:
989
+ """[COMM] SHOWCASE: Handle performance data requests from other plugins."""
990
+ logger.info(f"[DATA] Performance data request from {sender}")
991
+
992
+ # This would typically send data back via event bus
993
+ performance_data = {
994
+ "hook_executions": self.hook_executions,
995
+ "performance_metrics": self.hook_performance,
996
+ "timestamp": datetime.datetime.now().isoformat()
997
+ }
998
+
999
+ return performance_data
1000
+
1001
+ async def _handle_plugin_status_update(self, message: Dict[str, Any], sender: str) -> None:
1002
+ """[COMM] SHOWCASE: Handle status updates from other plugins."""
1003
+ logger.info(f"[CLIP] Status update received from {sender}")
1004
+
1005
+ # Update our records about the sender plugin
1006
+ if sender not in self.plugin_health_stats:
1007
+ self.plugin_health_stats[sender] = {}
1008
+
1009
+ self.plugin_health_stats[sender].update({
1010
+ "last_status_update": datetime.datetime.now(),
1011
+ "reported_status": message.get("status", "unknown"),
1012
+ "additional_data": message.get("data", {})
1013
+ })
1014
+
1015
+ async def _log_hook_execution(self, data: Dict[str, Any], event: Event) -> Dict[str, Any]:
1016
+ """Log hook execution details.
1017
+
1018
+ Args:
1019
+ data: Event data.
1020
+ event: Event object.
1021
+
1022
+ Returns:
1023
+ Hook result with logging information.
1024
+ """
1025
+ self.hook_executions += 1
1026
+ self.last_hook_event = event.type.value
1027
+
1028
+ start_time = time.time()
1029
+
1030
+ # Update performance tracking
1031
+ self._update_performance_metrics(event.type.value, start_time)
1032
+
1033
+ # Determine if this should be logged based on configuration
1034
+ log_all = self.config.get('plugins.hook_monitoring.log_all_events', True)
1035
+ log_failures_only = self.config.get('plugins.hook_monitoring.log_failures_only', False)
1036
+
1037
+ if log_all and not log_failures_only:
1038
+ # Filter out excessive render and key press events to reduce log spam
1039
+ if event.type.value not in ['input_render', 'render', 'key_press', 'key_press_pre', 'key_press_post']:
1040
+ logger.debug(f"HOOK MONITOR [{self.hook_executions}]: {event.type.value} from {event.source}")
1041
+
1042
+ # Log event data if configured
1043
+ if self.config.get('plugins.hook_monitoring.log_event_data', False):
1044
+ logger.debug(f"Hook Monitor - Event data keys: {list(data.keys()) if isinstance(data, dict) else type(data).__name__}")
1045
+
1046
+ # Check for performance issues
1047
+ execution_time_ms = (time.time() - start_time) * 1000
1048
+ threshold_ms = self.config.get('plugins.hook_monitoring.performance_threshold_ms', 100)
1049
+
1050
+ if execution_time_ms > threshold_ms:
1051
+ logger.warning(f"Hook Monitor - SLOW HOOK: {event.type.value} took {execution_time_ms:.1f}ms (threshold: {threshold_ms}ms)")
1052
+
1053
+ # Update health status
1054
+ self._update_health_status()
1055
+
1056
+ return {
1057
+ "status": "monitored",
1058
+ "execution_count": self.hook_executions,
1059
+ "event_type": event.type.value,
1060
+ "plugin_name": self.name,
1061
+ "execution_time_ms": execution_time_ms,
1062
+ "health_status": self.hook_health_status
1063
+ }
1064
+
1065
+ def _update_performance_metrics(self, event_type: str, start_time: float) -> None:
1066
+ """Update performance metrics for hook monitoring.
1067
+
1068
+ Args:
1069
+ event_type: The event type being monitored.
1070
+ start_time: Start time of the hook execution.
1071
+ """
1072
+ execution_time = (time.time() - start_time) * 1000 # Convert to milliseconds
1073
+
1074
+ if event_type not in self.hook_performance:
1075
+ self.hook_performance[event_type] = {
1076
+ "total_time": 0,
1077
+ "count": 0,
1078
+ "avg_time": 0,
1079
+ "max_time": 0,
1080
+ "min_time": float('inf')
1081
+ }
1082
+
1083
+ metrics = self.hook_performance[event_type]
1084
+ metrics["total_time"] += execution_time
1085
+ metrics["count"] += 1
1086
+ metrics["avg_time"] = metrics["total_time"] / metrics["count"]
1087
+ metrics["max_time"] = max(metrics["max_time"], execution_time)
1088
+ metrics["min_time"] = min(metrics["min_time"], execution_time)
1089
+
1090
+ def _update_health_status(self) -> None:
1091
+ """Update the overall health status of the hook system."""
1092
+ total_hooks = self.hook_executions
1093
+ if total_hooks == 0:
1094
+ self.hook_health_status = "Starting"
1095
+ return
1096
+
1097
+ failure_rate = (self.failed_hooks + self.timeout_hooks) / total_hooks
1098
+
1099
+ if failure_rate == 0:
1100
+ self.hook_health_status = "Healthy"
1101
+ elif failure_rate < self.config.get("performance.failure_rate_warning", 0.05):
1102
+ self.hook_health_status = "Good"
1103
+ elif failure_rate < self.config.get("performance.failure_rate_critical", 0.15):
1104
+ self.hook_health_status = "Warning"
1105
+ else:
1106
+ self.hook_health_status = "Critical"
1107
+
1108
+ def _log_error(self, error_msg: str, event_type: str) -> None:
1109
+ """Log an error with rotation to prevent memory bloat.
1110
+
1111
+ Args:
1112
+ error_msg: Error message to log.
1113
+ event_type: Event type where error occurred.
1114
+ """
1115
+ error_entry = {
1116
+ "timestamp": datetime.datetime.now().strftime('%H:%M:%S.%f')[:-3],
1117
+ "event_type": event_type,
1118
+ "message": error_msg
1119
+ }
1120
+
1121
+ self.error_log.append(error_entry)
1122
+
1123
+ # Rotate error log to prevent memory bloat
1124
+ max_size = self.config.get('plugins.hook_monitoring.max_error_log_size', 50)
1125
+ if len(self.error_log) > max_size:
1126
+ self.error_log = self.error_log[-max_size:]
1127
+
1128
+ def _log_final_report(self) -> None:
1129
+ """Log a comprehensive final report of hook monitoring."""
1130
+ if not self.config.get('plugins.hook_monitoring.log_performance', True):
1131
+ return
1132
+
1133
+ logger.info("=== HOOK MONITOR FINAL REPORT ===")
1134
+ logger.info(f"Total Hook Executions: {self.hook_executions}")
1135
+ logger.info(f"Failed Hooks: {self.failed_hooks}")
1136
+ logger.info(f"Timeout Hooks: {self.timeout_hooks}")
1137
+ logger.info(f"Final Health Status: {self.hook_health_status}")
1138
+
1139
+ if self.hook_performance:
1140
+ logger.info("=== PERFORMANCE METRICS ===")
1141
+ for event_type, metrics in self.hook_performance.items():
1142
+ if metrics["count"] > 0:
1143
+ logger.info(f"{event_type}: {metrics['count']} executions, "
1144
+ f"avg: {metrics['avg_time']:.1f}ms, "
1145
+ f"max: {metrics['max_time']:.1f}ms, "
1146
+ f"min: {metrics['min_time']:.1f}ms")
1147
+
1148
+ if self.error_log:
1149
+ logger.info("=== RECENT ERRORS ===")
1150
+ for error in self.error_log[-10:]: # Show last 10 errors
1151
+ logger.info(f"[{error['timestamp']}] {error['event_type']}: {error['message']}")
1152
+
1153
+ logger.info("=== END HOOK MONITOR REPORT ===")
1154
+
1155
+ def get_monitoring_stats(self) -> Dict[str, Any]:
1156
+ """Get current monitoring statistics.
1157
+
1158
+ Returns:
1159
+ Dictionary with comprehensive monitoring statistics.
1160
+ """
1161
+ return {
1162
+ "total_executions": self.hook_executions,
1163
+ "failed_hooks": self.failed_hooks,
1164
+ "timeout_hooks": self.timeout_hooks,
1165
+ "health_status": self.hook_health_status,
1166
+ "last_event": self.last_hook_event,
1167
+ "performance_metrics": self.hook_performance,
1168
+ "recent_errors": self.error_log[-5:] if self.error_log else [],
1169
+ "failure_rate": (self.failed_hooks + self.timeout_hooks) / max(1, self.hook_executions)
1170
+ }
1171
+
1172
+ # [TARGET] PUBLIC API METHODS - For other plugins to use
1173
+
1174
+ def get_plugin_ecosystem_dashboard(self) -> Dict[str, Any]:
1175
+ """[TARGET] SHOWCASE: Public API - Plugin Ecosystem Dashboard.
1176
+
1177
+ This method can be called by other plugins to get a comprehensive
1178
+ view of the entire plugin ecosystem. Perfect demonstration of how
1179
+ plugins can provide services to each other!
1180
+
1181
+ Example usage from another plugin:
1182
+ ```python
1183
+ # Get the hook monitoring plugin instance
1184
+ factory = self.get_factory()
1185
+ monitor = factory.get_instance("HookMonitoringPlugin")
1186
+
1187
+ # Get ecosystem dashboard
1188
+ dashboard = monitor.get_plugin_ecosystem_dashboard()
1189
+ print(f"Total plugins: {dashboard['summary']['total_plugins']}")
1190
+ ```
1191
+ """
1192
+ # Calculate comprehensive ecosystem metrics
1193
+ total_plugins = len(getattr(self, 'discovered_plugins', {}))
1194
+ active_plugins = len([p for p in getattr(self, 'plugin_health_stats', {}).values()
1195
+ if p.get("status") != "error"])
1196
+
1197
+ failure_rate = 0
1198
+ if self.hook_executions > 0:
1199
+ failure_rate = (self.failed_hooks + self.timeout_hooks) / self.hook_executions
1200
+
1201
+ dashboard = {
1202
+ "[TARGET] PLUGIN ECOSYSTEM DASHBOARD": "Live Status",
1203
+
1204
+ "summary": {
1205
+ "total_plugins": total_plugins,
1206
+ "active_plugins": active_plugins,
1207
+ "registered_services": 3 if (self.service_registration_enabled and SDK_AVAILABLE) else 0,
1208
+ "system_health": self.hook_health_status,
1209
+ "overall_failure_rate": failure_rate,
1210
+ "last_updated": datetime.datetime.now().isoformat()
1211
+ },
1212
+
1213
+ "hook_monitoring": {
1214
+ "total_executions": self.hook_executions,
1215
+ "failed_hooks": self.failed_hooks,
1216
+ "timeout_hooks": self.timeout_hooks,
1217
+ "performance_metrics": dict(list(self.hook_performance.items())[:5]) # Top 5
1218
+ },
1219
+
1220
+ "plugin_discovery": {
1221
+ "discovery_enabled": self.plugin_discovery_enabled,
1222
+ "discovered_plugins": list(getattr(self, 'discovered_plugins', {}).keys()),
1223
+ "plugin_capabilities": getattr(self, 'plugin_health_stats', {})
1224
+ },
1225
+
1226
+ "service_registration": {
1227
+ "sdk_available": SDK_AVAILABLE,
1228
+ "services_enabled": self.service_registration_enabled,
1229
+ "available_services": [
1230
+ "monitor_performance",
1231
+ "check_plugin_health",
1232
+ "collect_system_metrics"
1233
+ ] if (self.service_registration_enabled and SDK_AVAILABLE) else []
1234
+ },
1235
+
1236
+ "cross_plugin_communication": {
1237
+ "communication_enabled": self.enable_cross_plugin_comm,
1238
+ "recent_messages": len(getattr(self, 'cross_plugin_messages', [])),
1239
+ "message_history": getattr(self, 'cross_plugin_messages', [])[-3:], # Last 3
1240
+ "message_handlers": list(getattr(self, 'message_handlers', {}).keys())
1241
+ },
1242
+
1243
+ "showcase_features": {
1244
+ "[FIND] Plugin Discovery": "[OK] Active" if self.plugin_discovery_enabled else "Disabled",
1245
+ "[TOOL] Service Registration": "[OK] Active" if (self.service_registration_enabled and SDK_AVAILABLE) else "Disabled",
1246
+ "[COMM] Cross-Plugin Comm": "[OK] Active" if self.enable_cross_plugin_comm else "Disabled",
1247
+ "[DATA] Performance Monitoring": "[OK] Active",
1248
+ "[HEALTH] Health Monitoring": "[OK] Active",
1249
+ "[METRICS] Metrics Collection": "[OK] Active"
1250
+ }
1251
+ }
1252
+
1253
+ return dashboard
1254
+
1255
+ async def send_demo_message_to_plugin(self, target_plugin: str, message_type: str = "demo") -> Dict[str, Any]:
1256
+ """[COMM] SHOWCASE: Send a demonstration message to another plugin.
1257
+
1258
+ This showcases cross-plugin communication patterns.
1259
+
1260
+ Args:
1261
+ target_plugin: Name of the plugin to send message to
1262
+ message_type: Type of message to send
1263
+
1264
+ Returns:
1265
+ Result of the message sending attempt
1266
+ """
1267
+ logger.info(f"[COMM] DEMO: Sending {message_type} message to {target_plugin}")
1268
+
1269
+ demo_message = {
1270
+ "sender": self.name,
1271
+ "message_type": message_type,
1272
+ "timestamp": datetime.datetime.now().isoformat(),
1273
+ "data": {
1274
+ "demo": True,
1275
+ "system_health": self.hook_health_status,
1276
+ "hook_executions": self.hook_executions,
1277
+ "message": f"Hello from {self.name}! This demonstrates cross-plugin communication."
1278
+ }
1279
+ }
1280
+
1281
+ # Record the outgoing message
1282
+ if hasattr(self, 'cross_plugin_messages'):
1283
+ self.cross_plugin_messages.append({
1284
+ "timestamp": datetime.datetime.now(),
1285
+ "direction": "outgoing",
1286
+ "target": target_plugin,
1287
+ "message_type": message_type,
1288
+ "data": demo_message
1289
+ })
1290
+
1291
+ # In a real implementation, this would use the event bus:
1292
+ # await self.event_bus.send_message(target_plugin=target_plugin, data=demo_message)
1293
+
1294
+ return {
1295
+ "status": "demo_sent",
1296
+ "target": target_plugin,
1297
+ "message": demo_message,
1298
+ "note": "In production, this would use the event bus for actual delivery"
1299
+ }