kollabor 0.4.9__py3-none-any.whl → 0.4.15__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 (192) hide show
  1. agents/__init__.py +2 -0
  2. agents/coder/__init__.py +0 -0
  3. agents/coder/agent.json +4 -0
  4. agents/coder/api-integration.md +2150 -0
  5. agents/coder/cli-pretty.md +765 -0
  6. agents/coder/code-review.md +1092 -0
  7. agents/coder/database-design.md +1525 -0
  8. agents/coder/debugging.md +1102 -0
  9. agents/coder/dependency-management.md +1397 -0
  10. agents/coder/git-workflow.md +1099 -0
  11. agents/coder/refactoring.md +1454 -0
  12. agents/coder/security-hardening.md +1732 -0
  13. agents/coder/system_prompt.md +1448 -0
  14. agents/coder/tdd.md +1367 -0
  15. agents/creative-writer/__init__.py +0 -0
  16. agents/creative-writer/agent.json +4 -0
  17. agents/creative-writer/character-development.md +1852 -0
  18. agents/creative-writer/dialogue-craft.md +1122 -0
  19. agents/creative-writer/plot-structure.md +1073 -0
  20. agents/creative-writer/revision-editing.md +1484 -0
  21. agents/creative-writer/system_prompt.md +690 -0
  22. agents/creative-writer/worldbuilding.md +2049 -0
  23. agents/data-analyst/__init__.py +30 -0
  24. agents/data-analyst/agent.json +4 -0
  25. agents/data-analyst/data-visualization.md +992 -0
  26. agents/data-analyst/exploratory-data-analysis.md +1110 -0
  27. agents/data-analyst/pandas-data-manipulation.md +1081 -0
  28. agents/data-analyst/sql-query-optimization.md +881 -0
  29. agents/data-analyst/statistical-analysis.md +1118 -0
  30. agents/data-analyst/system_prompt.md +928 -0
  31. agents/default/__init__.py +0 -0
  32. agents/default/agent.json +4 -0
  33. agents/default/dead-code.md +794 -0
  34. agents/default/explore-agent-system.md +585 -0
  35. agents/default/system_prompt.md +1448 -0
  36. agents/kollabor/__init__.py +0 -0
  37. agents/kollabor/analyze-plugin-lifecycle.md +175 -0
  38. agents/kollabor/analyze-terminal-rendering.md +388 -0
  39. agents/kollabor/code-review.md +1092 -0
  40. agents/kollabor/debug-mcp-integration.md +521 -0
  41. agents/kollabor/debug-plugin-hooks.md +547 -0
  42. agents/kollabor/debugging.md +1102 -0
  43. agents/kollabor/dependency-management.md +1397 -0
  44. agents/kollabor/git-workflow.md +1099 -0
  45. agents/kollabor/inspect-llm-conversation.md +148 -0
  46. agents/kollabor/monitor-event-bus.md +558 -0
  47. agents/kollabor/profile-performance.md +576 -0
  48. agents/kollabor/refactoring.md +1454 -0
  49. agents/kollabor/system_prompt copy.md +1448 -0
  50. agents/kollabor/system_prompt.md +757 -0
  51. agents/kollabor/trace-command-execution.md +178 -0
  52. agents/kollabor/validate-config.md +879 -0
  53. agents/research/__init__.py +0 -0
  54. agents/research/agent.json +4 -0
  55. agents/research/architecture-mapping.md +1099 -0
  56. agents/research/codebase-analysis.md +1077 -0
  57. agents/research/dependency-audit.md +1027 -0
  58. agents/research/performance-profiling.md +1047 -0
  59. agents/research/security-review.md +1359 -0
  60. agents/research/system_prompt.md +492 -0
  61. agents/technical-writer/__init__.py +0 -0
  62. agents/technical-writer/agent.json +4 -0
  63. agents/technical-writer/api-documentation.md +2328 -0
  64. agents/technical-writer/changelog-management.md +1181 -0
  65. agents/technical-writer/readme-writing.md +1360 -0
  66. agents/technical-writer/style-guide.md +1410 -0
  67. agents/technical-writer/system_prompt.md +653 -0
  68. agents/technical-writer/tutorial-creation.md +1448 -0
  69. core/__init__.py +0 -2
  70. core/application.py +343 -88
  71. core/cli.py +229 -10
  72. core/commands/menu_renderer.py +463 -59
  73. core/commands/registry.py +14 -9
  74. core/commands/system_commands.py +2461 -14
  75. core/config/loader.py +151 -37
  76. core/config/service.py +18 -6
  77. core/events/bus.py +29 -9
  78. core/events/executor.py +205 -75
  79. core/events/models.py +27 -8
  80. core/fullscreen/command_integration.py +20 -24
  81. core/fullscreen/components/__init__.py +10 -1
  82. core/fullscreen/components/matrix_components.py +1 -2
  83. core/fullscreen/components/space_shooter_components.py +654 -0
  84. core/fullscreen/plugin.py +5 -0
  85. core/fullscreen/renderer.py +52 -13
  86. core/fullscreen/session.py +52 -15
  87. core/io/__init__.py +29 -5
  88. core/io/buffer_manager.py +6 -1
  89. core/io/config_status_view.py +7 -29
  90. core/io/core_status_views.py +267 -347
  91. core/io/input/__init__.py +25 -0
  92. core/io/input/command_mode_handler.py +711 -0
  93. core/io/input/display_controller.py +128 -0
  94. core/io/input/hook_registrar.py +286 -0
  95. core/io/input/input_loop_manager.py +421 -0
  96. core/io/input/key_press_handler.py +502 -0
  97. core/io/input/modal_controller.py +1011 -0
  98. core/io/input/paste_processor.py +339 -0
  99. core/io/input/status_modal_renderer.py +184 -0
  100. core/io/input_errors.py +5 -1
  101. core/io/input_handler.py +211 -2452
  102. core/io/key_parser.py +7 -0
  103. core/io/layout.py +15 -3
  104. core/io/message_coordinator.py +111 -2
  105. core/io/message_renderer.py +129 -4
  106. core/io/status_renderer.py +147 -607
  107. core/io/terminal_renderer.py +97 -51
  108. core/io/terminal_state.py +21 -4
  109. core/io/visual_effects.py +816 -165
  110. core/llm/agent_manager.py +1063 -0
  111. core/llm/api_adapters/__init__.py +44 -0
  112. core/llm/api_adapters/anthropic_adapter.py +432 -0
  113. core/llm/api_adapters/base.py +241 -0
  114. core/llm/api_adapters/openai_adapter.py +326 -0
  115. core/llm/api_communication_service.py +167 -113
  116. core/llm/conversation_logger.py +322 -16
  117. core/llm/conversation_manager.py +556 -30
  118. core/llm/file_operations_executor.py +84 -32
  119. core/llm/llm_service.py +934 -103
  120. core/llm/mcp_integration.py +541 -57
  121. core/llm/message_display_service.py +135 -18
  122. core/llm/plugin_sdk.py +1 -2
  123. core/llm/profile_manager.py +1183 -0
  124. core/llm/response_parser.py +274 -56
  125. core/llm/response_processor.py +16 -3
  126. core/llm/tool_executor.py +6 -1
  127. core/logging/__init__.py +2 -0
  128. core/logging/setup.py +34 -6
  129. core/models/resume.py +54 -0
  130. core/plugins/__init__.py +4 -2
  131. core/plugins/base.py +127 -0
  132. core/plugins/collector.py +23 -161
  133. core/plugins/discovery.py +37 -3
  134. core/plugins/factory.py +6 -12
  135. core/plugins/registry.py +5 -17
  136. core/ui/config_widgets.py +128 -28
  137. core/ui/live_modal_renderer.py +2 -1
  138. core/ui/modal_actions.py +5 -0
  139. core/ui/modal_overlay_renderer.py +0 -60
  140. core/ui/modal_renderer.py +268 -7
  141. core/ui/modal_state_manager.py +29 -4
  142. core/ui/widgets/base_widget.py +7 -0
  143. core/updates/__init__.py +10 -0
  144. core/updates/version_check_service.py +348 -0
  145. core/updates/version_comparator.py +103 -0
  146. core/utils/config_utils.py +685 -526
  147. core/utils/plugin_utils.py +1 -1
  148. core/utils/session_naming.py +111 -0
  149. fonts/LICENSE +21 -0
  150. fonts/README.md +46 -0
  151. fonts/SymbolsNerdFont-Regular.ttf +0 -0
  152. fonts/SymbolsNerdFontMono-Regular.ttf +0 -0
  153. fonts/__init__.py +44 -0
  154. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/METADATA +54 -4
  155. kollabor-0.4.15.dist-info/RECORD +228 -0
  156. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/top_level.txt +2 -0
  157. plugins/agent_orchestrator/__init__.py +39 -0
  158. plugins/agent_orchestrator/activity_monitor.py +181 -0
  159. plugins/agent_orchestrator/file_attacher.py +77 -0
  160. plugins/agent_orchestrator/message_injector.py +135 -0
  161. plugins/agent_orchestrator/models.py +48 -0
  162. plugins/agent_orchestrator/orchestrator.py +403 -0
  163. plugins/agent_orchestrator/plugin.py +976 -0
  164. plugins/agent_orchestrator/xml_parser.py +191 -0
  165. plugins/agent_orchestrator_plugin.py +9 -0
  166. plugins/enhanced_input/box_styles.py +1 -0
  167. plugins/enhanced_input/color_engine.py +19 -4
  168. plugins/enhanced_input/config.py +2 -2
  169. plugins/enhanced_input_plugin.py +61 -11
  170. plugins/fullscreen/__init__.py +6 -2
  171. plugins/fullscreen/example_plugin.py +1035 -222
  172. plugins/fullscreen/setup_wizard_plugin.py +592 -0
  173. plugins/fullscreen/space_shooter_plugin.py +131 -0
  174. plugins/hook_monitoring_plugin.py +436 -78
  175. plugins/query_enhancer_plugin.py +66 -30
  176. plugins/resume_conversation_plugin.py +1494 -0
  177. plugins/save_conversation_plugin.py +98 -32
  178. plugins/system_commands_plugin.py +70 -56
  179. plugins/tmux_plugin.py +154 -78
  180. plugins/workflow_enforcement_plugin.py +94 -92
  181. system_prompt/default.md +952 -886
  182. core/io/input_mode_manager.py +0 -402
  183. core/io/modal_interaction_handler.py +0 -315
  184. core/io/raw_input_processor.py +0 -946
  185. core/storage/__init__.py +0 -5
  186. core/storage/state_manager.py +0 -84
  187. core/ui/widget_integration.py +0 -222
  188. core/utils/key_reader.py +0 -171
  189. kollabor-0.4.9.dist-info/RECORD +0 -128
  190. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/WHEEL +0 -0
  191. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/entry_points.txt +0 -0
  192. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/licenses/LICENSE +0 -0
@@ -15,11 +15,14 @@ demonstrating:
15
15
  Perfect for developers learning the plugin system!
16
16
  """
17
17
 
18
+ import asyncio
18
19
  import datetime
19
20
  import logging
20
21
  import time
21
22
  from typing import Any, Dict, List, Optional
22
23
 
24
+ from core.io.visual_effects import AgnosterSegment
25
+
23
26
  # Import event system components
24
27
  import sys
25
28
  from pathlib import Path
@@ -42,7 +45,7 @@ logger = logging.getLogger(__name__)
42
45
  class HookMonitoringPlugin:
43
46
  """[SHOWCASE] SHOWCASE: A comprehensive hook monitoring system demonstrating ALL plugin ecosystem features!"""
44
47
 
45
- def __init__(self, name: str, state_manager, event_bus, renderer, config) -> None:
48
+ def __init__(self, name: str, event_bus, renderer, config) -> None:
46
49
  """Initialize the hook monitoring plugin with full ecosystem integration.
47
50
 
48
51
  This initialization showcases:
@@ -53,14 +56,12 @@ class HookMonitoringPlugin:
53
56
 
54
57
  Args:
55
58
  name: Plugin name.
56
- state_manager: State management system.
57
59
  event_bus: Event bus for hook registration.
58
60
  renderer: Terminal renderer.
59
61
  config: Configuration manager.
60
62
  """
61
63
  # [DATA] BASIC PLUGIN SETUP
62
64
  self.name = name
63
- self.state_manager = state_manager
64
65
  self.event_bus = event_bus
65
66
  self.renderer = renderer
66
67
  self.config = config
@@ -75,6 +76,11 @@ class HookMonitoringPlugin:
75
76
  self.error_log = [] # Recent errors for debugging
76
77
  self.hook_health_status = "Starting"
77
78
 
79
+ # [DATA] ENHANCED PERFORMANCE TRACKING - Detailed metrics and degradation detection
80
+ self.detailed_metrics = {} # event_type -> detailed metrics (history, percentiles)
81
+ self.performance_baseline = {} # event_type -> baseline avg_time (set after 10 executions)
82
+ self.degradation_detected = False # Flag for performance degradation
83
+
78
84
  # [FIND] PLUGIN ECOSYSTEM STATE - Showcasing service discovery
79
85
  self.discovered_plugins = {} # plugin_name -> plugin_instance
80
86
  self.available_services = {} # service_name -> plugin_info
@@ -85,11 +91,14 @@ class HookMonitoringPlugin:
85
91
  # This shows how plugins can discover and communicate with each other
86
92
  self.plugin_factory: Optional[PluginFactory] = None
87
93
  self.plugin_discovery_enabled = config.get("plugins.hook_monitoring.enable_plugin_discovery", True)
94
+ self.discovery_task = None # Background task for periodic discovery
95
+ self.last_discovery_time = None # Timestamp of last discovery
88
96
 
89
97
  # [TOOL] SDK INITIALIZATION - Demonstrating service registration
90
98
  # This shows how plugins can register services for other plugins to use
91
99
  self.sdk: Optional[KollaborPluginSDK] = None
92
100
  self.service_registration_enabled = config.get("plugins.hook_monitoring.enable_service_registration", True)
101
+ self.registered_services = [] # Track which services are actually registered
93
102
 
94
103
  if SDK_AVAILABLE and self.service_registration_enabled:
95
104
  self.sdk = KollaborPluginSDK()
@@ -99,6 +108,19 @@ class HookMonitoringPlugin:
99
108
  self.enable_cross_plugin_comm = config.get("plugins.hook_monitoring.enable_cross_plugin_communication", True)
100
109
  self.message_history_limit = config.get("plugins.hook_monitoring.message_history_limit", 20)
101
110
 
111
+ # [METRICS] METRICS COLLECTION AND RETENTION - Timestamped metrics storage
112
+ self.collected_metrics = [] # List of timestamped metric snapshots
113
+ self.service_usage_stats = { # Track SDK service call counts
114
+ "monitor_performance": {"calls": 0, "last_called": None},
115
+ "check_plugin_health": {"calls": 0, "last_called": None},
116
+ "collect_system_metrics": {"calls": 0, "last_called": None}
117
+ }
118
+ self.metrics_collection_task = None # Background task for metrics collection
119
+
120
+ # [TARGET] DASHBOARD STATE - Dashboard update throttling and caching
121
+ self.last_dashboard_update = datetime.datetime.now()
122
+ self.cached_dashboard_content = []
123
+
102
124
  # [TARGET] CREATE HOOKS - Standard hook creation for monitoring
103
125
  self.hooks = self._create_all_hooks()
104
126
 
@@ -131,7 +153,7 @@ class HookMonitoringPlugin:
131
153
  discovered_count = len(getattr(self, 'discovered_plugins', {}))
132
154
 
133
155
  # [TOOL] SHOWCASE: Service Registration Status
134
- registered_services = 3 if (self.service_registration_enabled and SDK_AVAILABLE) else 0
156
+ registered_services = len(getattr(self, 'registered_services', []))
135
157
 
136
158
  # [COMM] SHOWCASE: Cross-Plugin Communication Status
137
159
  recent_messages = len(getattr(self, 'cross_plugin_messages', []))
@@ -149,8 +171,8 @@ class HookMonitoringPlugin:
149
171
  "C": [ # Detailed ecosystem info in area C
150
172
  f"SHOWCASE: Plugin Ecosystem Demo",
151
173
  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]'}",
174
+ f"Discovery: {'[ok]' if self.plugin_discovery_enabled else '[X]'}",
175
+ f"SDK: {'[ok]' if SDK_AVAILABLE else '[X]'}",
154
176
  f"Debug: {'On' if debug_mode else 'Off'}"
155
177
  ]
156
178
  }
@@ -163,6 +185,7 @@ class HookMonitoringPlugin:
163
185
  2. SDK service registration for providing monitoring services
164
186
  3. Cross-plugin communication setup
165
187
  4. Dynamic service discovery patterns
188
+ 5. Background task management for periodic operations
166
189
  """
167
190
  logger.info("Starting HookMonitoringPlugin initialization...")
168
191
 
@@ -170,6 +193,14 @@ class HookMonitoringPlugin:
170
193
  if self.plugin_discovery_enabled:
171
194
  await self._discover_other_plugins()
172
195
 
196
+ # Start periodic plugin discovery if interval is configured
197
+ interval = self.config.get("plugins.hook_monitoring.discovery_interval", 30)
198
+ if interval > 0:
199
+ self.discovery_task = asyncio.create_task(
200
+ self._periodic_plugin_discovery()
201
+ )
202
+ logger.info(f"Started periodic plugin discovery task (interval: {interval}s)")
203
+
173
204
  # [TOOL] STEP 2: SERVICE REGISTRATION - Showcasing how to offer services to other plugins
174
205
  if self.service_registration_enabled and self.sdk:
175
206
  await self._register_monitoring_services()
@@ -181,6 +212,13 @@ class HookMonitoringPlugin:
181
212
  # [DATA] STEP 4: INITIALIZE PLUGIN HEALTH MONITORING
182
213
  await self._initialize_plugin_health_monitoring()
183
214
 
215
+ # [METRICS] STEP 5: START METRICS COLLECTION - Periodic metrics gathering
216
+ if self.config.get("plugins.hook_monitoring.collect_plugin_metrics", True):
217
+ self.metrics_collection_task = asyncio.create_task(
218
+ self._periodic_metrics_collection()
219
+ )
220
+ logger.info("Started periodic metrics collection task (interval: 60s)")
221
+
184
222
  logger.info("HookMonitoringPlugin initialization complete - all ecosystem features active!")
185
223
 
186
224
  async def _discover_other_plugins(self) -> None:
@@ -248,6 +286,114 @@ class HookMonitoringPlugin:
248
286
 
249
287
  logger.debug(f"Analyzed {plugin_name}: {capabilities}")
250
288
 
289
+ async def _periodic_plugin_discovery(self) -> None:
290
+ """[FIND] SHOWCASE: Periodically discover plugins at configured interval.
291
+
292
+ This demonstrates background task patterns for plugin ecosystem monitoring:
293
+ - Periodic task execution with configurable interval
294
+ - Auto-capability analysis based on configuration
295
+ - Proper exception handling and cleanup
296
+ - Task cancellation support
297
+ """
298
+ interval = self.config.get("plugins.hook_monitoring.discovery_interval", 30)
299
+ auto_analyze = self.config.get("plugins.hook_monitoring.auto_analyze_capabilities", True)
300
+
301
+ logger.info(f"Starting periodic plugin discovery (interval: {interval}s, auto_analyze: {auto_analyze})")
302
+
303
+ while True:
304
+ try:
305
+ await asyncio.sleep(interval)
306
+
307
+ # Discover plugins
308
+ if hasattr(self.renderer, 'plugin_instances'):
309
+ plugin_instances = getattr(self.renderer, 'plugin_instances', {})
310
+ self.discovered_plugins = plugin_instances
311
+
312
+ # Auto-analyze capabilities if enabled
313
+ if auto_analyze:
314
+ for plugin_name, plugin_instance in plugin_instances.items():
315
+ if plugin_name != self.name:
316
+ await self._analyze_plugin_capabilities(plugin_name, plugin_instance)
317
+
318
+ self.last_discovery_time = datetime.datetime.now()
319
+ logger.debug(f"Plugin discovery complete: {len(self.discovered_plugins)} plugins found")
320
+
321
+ except asyncio.CancelledError:
322
+ logger.info("Plugin discovery task cancelled")
323
+ break
324
+ except Exception as e:
325
+ logger.error(f"Plugin discovery error: {e}")
326
+ await asyncio.sleep(interval)
327
+
328
+ async def _periodic_metrics_collection(self) -> None:
329
+ """[METRICS] SHOWCASE: Periodically collect and store metrics.
330
+
331
+ This demonstrates:
332
+ - Periodic metrics gathering with retention policies
333
+ - Time-series data collection patterns
334
+ - Memory-efficient metrics storage with automatic cleanup
335
+ - Configuration-driven collection intervals
336
+ """
337
+ logger.info("Starting periodic metrics collection")
338
+
339
+ while True:
340
+ try:
341
+ await asyncio.sleep(60) # Collect every 60 seconds
342
+
343
+ # Gather metrics snapshot
344
+ snapshot = {
345
+ "timestamp": datetime.datetime.now(),
346
+ "hook_executions": self.hook_executions,
347
+ "failed_hooks": self.failed_hooks,
348
+ "timeout_hooks": self.timeout_hooks,
349
+ "health_status": self.hook_health_status,
350
+ "discovered_plugins": len(self.discovered_plugins),
351
+ "service_usage": dict(self.service_usage_stats),
352
+ "performance_summary": {
353
+ event: {
354
+ "count": metrics["count"],
355
+ "avg_time": metrics["avg_time"]
356
+ }
357
+ for event, metrics in self.hook_performance.items()
358
+ }
359
+ }
360
+
361
+ self.collected_metrics.append(snapshot)
362
+
363
+ # Cleanup old metrics
364
+ self._cleanup_old_metrics()
365
+
366
+ logger.debug(f"Metrics collected: {len(self.collected_metrics)} snapshots retained")
367
+
368
+ except asyncio.CancelledError:
369
+ logger.info("Metrics collection task cancelled")
370
+ break
371
+ except Exception as e:
372
+ logger.error(f"Metrics collection error: {e}")
373
+ await asyncio.sleep(60)
374
+
375
+ def _cleanup_old_metrics(self) -> None:
376
+ """[METRICS] SHOWCASE: Remove metrics older than retention period.
377
+
378
+ This demonstrates memory management for time-series data:
379
+ - Configuration-driven retention policies
380
+ - Efficient list comprehension for cleanup
381
+ - Automatic old data removal
382
+ """
383
+ retention_hours = self.config.get("plugins.hook_monitoring.metrics_retention_hours", 24)
384
+ cutoff_time = datetime.datetime.now() - datetime.timedelta(hours=retention_hours)
385
+
386
+ # Remove old metrics
387
+ original_count = len(self.collected_metrics)
388
+ self.collected_metrics = [
389
+ m for m in self.collected_metrics
390
+ if m["timestamp"] > cutoff_time
391
+ ]
392
+
393
+ removed_count = original_count - len(self.collected_metrics)
394
+ if removed_count > 0:
395
+ logger.debug(f"Cleaned up {removed_count} old metrics (retention: {retention_hours}h)")
396
+
251
397
  async def _register_monitoring_services(self) -> None:
252
398
  """[TOOL] SHOWCASE: Register monitoring services for other plugins to use.
253
399
 
@@ -262,50 +408,62 @@ class HookMonitoringPlugin:
262
408
  logger.warning("SDK not available - cannot register services")
263
409
  return
264
410
 
411
+ # Reset registered services list
412
+ self.registered_services = []
413
+
265
414
  try:
266
415
  # [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
- })
416
+ if self.config.get("plugins.hook_monitoring.register_performance_service", True):
417
+ self.sdk.register_custom_tool({
418
+ "name": "monitor_performance",
419
+ "description": "Monitor plugin performance and hook execution times",
420
+ "handler": self._provide_performance_monitoring,
421
+ "parameters": {
422
+ "plugin_name": {"type": "string", "description": "Plugin to monitor"},
423
+ "metric_type": {"type": "string", "description": "Type of metric to collect"}
424
+ },
425
+ "plugin": self.name,
426
+ "enabled": True,
427
+ "category": "monitoring"
428
+ })
429
+ self.registered_services.append("monitor_performance")
430
+ logger.debug("Registered performance monitoring service")
279
431
 
280
432
  # [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
- })
433
+ if self.config.get("plugins.hook_monitoring.register_health_service", True):
434
+ self.sdk.register_custom_tool({
435
+ "name": "check_plugin_health",
436
+ "description": "Check the health status of any plugin in the system",
437
+ "handler": self._provide_health_check,
438
+ "parameters": {
439
+ "plugin_name": {"type": "string", "description": "Plugin to check"},
440
+ "detailed": {"type": "boolean", "description": "Return detailed health info"}
441
+ },
442
+ "plugin": self.name,
443
+ "enabled": True,
444
+ "category": "health"
445
+ })
446
+ self.registered_services.append("check_plugin_health")
447
+ logger.debug("Registered health check service")
293
448
 
294
449
  # [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
- })
450
+ if self.config.get("plugins.hook_monitoring.register_metrics_service", True):
451
+ self.sdk.register_custom_tool({
452
+ "name": "collect_system_metrics",
453
+ "description": "Collect comprehensive system and plugin metrics",
454
+ "handler": self._provide_metrics_collection,
455
+ "parameters": {
456
+ "time_range": {"type": "string", "description": "Time range for metrics"},
457
+ "include_performance": {"type": "boolean", "description": "Include performance data"}
458
+ },
459
+ "plugin": self.name,
460
+ "enabled": True,
461
+ "category": "analytics"
462
+ })
463
+ self.registered_services.append("collect_system_metrics")
464
+ logger.debug("Registered metrics collection service")
307
465
 
308
- logger.debug("Registered 3 monitoring services - other plugins can now use our services!")
466
+ logger.info(f"Registered {len(self.registered_services)} monitoring services: {', '.join(self.registered_services)}")
309
467
 
310
468
  except Exception as e:
311
469
  logger.error(f"Service registration failed: {e}")
@@ -407,7 +565,7 @@ class HookMonitoringPlugin:
407
565
 
408
566
  registry = self.renderer.status_renderer.status_registry
409
567
  registry.register_status_view("hook_monitoring", developer_view)
410
- logger.info("[OK] Registered 'Developer Metrics' status view")
568
+ logger.info("[ok] Registered 'Developer Metrics' status view")
411
569
 
412
570
  else:
413
571
  logger.warning("Status registry not available - cannot register status view")
@@ -416,38 +574,136 @@ class HookMonitoringPlugin:
416
574
  logger.error(f"Failed to register status view: {e}")
417
575
 
418
576
  def _get_developer_metrics_content(self) -> List[str]:
419
- """Get developer metrics content for status view."""
577
+ """[TARGET] SHOWCASE: Get developer metrics with conditional display and throttling.
578
+
579
+ This demonstrates:
580
+ - Configuration-driven dashboard visibility
581
+ - Update throttling for performance optimization
582
+ - Multi-line dashboard with plugin interactions and service usage
583
+ - Content caching with configurable refresh intervals
584
+ """
420
585
  try:
586
+ # Check if dashboard is enabled
587
+ dashboard_enabled = self.config.get('plugins.hook_monitoring.enable_health_dashboard', True)
588
+ if not dashboard_enabled:
589
+ return [] # Don't show anything when disabled
590
+
591
+ # Check if plugin is enabled
421
592
  enabled = self.config.get('plugins.hook_monitoring.enabled', False)
422
593
  if not enabled:
423
- return ["Hook Monitor: - Off"]
594
+ seg = AgnosterSegment()
595
+ seg.add_neutral("Hooks: Off", "dark")
596
+ return [seg.render()]
597
+
598
+ # Check dashboard update interval (throttling)
599
+ update_interval = self.config.get('plugins.hook_monitoring.dashboard_update_interval', 10)
600
+ now = datetime.datetime.now()
601
+ seconds_since_update = (now - self.last_dashboard_update).total_seconds()
602
+
603
+ if seconds_since_update < update_interval and self.cached_dashboard_content:
604
+ return self.cached_dashboard_content # Return cached content
605
+
606
+ # Regenerate dashboard content
607
+ self.last_dashboard_update = now
424
608
 
425
- # Calculate failure rate for health display
609
+ # Build main metrics line
610
+ seg = AgnosterSegment()
611
+
612
+ # Calculate failure rate
426
613
  failure_rate = 0
427
614
  if self.hook_executions > 0:
428
615
  failure_rate = (self.failed_hooks + self.timeout_hooks) / self.hook_executions
429
616
 
430
- # Plugin discovery status
617
+ # Plugin discovery
431
618
  discovered_count = len(getattr(self, 'discovered_plugins', {}))
432
619
 
433
- # Service registration status
434
- registered_services = 3 if (self.service_registration_enabled and SDK_AVAILABLE) else 0
620
+ # Services
621
+ registered_services = len(getattr(self, 'registered_services', []))
435
622
 
436
- # Cross-plugin communication status
437
- recent_messages = len(getattr(self, 'cross_plugin_messages', []))
623
+ # Build agnoster bar
624
+ seg.add_lime(f"Hooks: {self.hook_health_status}", "dark")
625
+ seg.add_cyan(f"Exec: {self.hook_executions}", "dark")
626
+ seg.add_lime(f"Plugins: {discovered_count}")
438
627
 
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
- ]
628
+ if self.hook_executions > 0:
629
+ seg.add_cyan(f"Fail: {failure_rate:.1%}")
630
+ else:
631
+ seg.add_cyan("Fail: N/A")
632
+
633
+ seg.add_neutral(f"Services: {registered_services}", "mid")
634
+
635
+ result = [seg.render()]
636
+
637
+ # Add plugin interactions line if enabled
638
+ show_interactions = self.config.get('plugins.hook_monitoring.show_plugin_interactions', True)
639
+ if show_interactions and hasattr(self, 'cross_plugin_messages'):
640
+ recent_messages = len(self.cross_plugin_messages)
641
+ if recent_messages > 0:
642
+ int_seg = AgnosterSegment()
643
+ int_seg.add_neutral(f"Interactions: {recent_messages}", "dark")
644
+
645
+ # Show top communicators
646
+ senders = {}
647
+ for msg in self.cross_plugin_messages:
648
+ sender = msg.get("sender", "unknown")
649
+ senders[sender] = senders.get(sender, 0) + 1
650
+
651
+ for sender, count in list(senders.items())[:3]: # Top 3
652
+ int_seg.add_cyan(f"{sender}: {count}")
653
+
654
+ result.append(int_seg.render())
655
+
656
+ # Add service usage line if enabled
657
+ show_service_usage = self.config.get('plugins.hook_monitoring.show_service_usage', True)
658
+ if show_service_usage and hasattr(self, 'service_usage_stats'):
659
+ svc_seg = AgnosterSegment()
660
+
661
+ total_calls = sum(s["calls"] for s in self.service_usage_stats.values())
662
+ svc_seg.add_neutral(f"Service Calls: {total_calls}", "dark")
663
+
664
+ for service_name, stats in self.service_usage_stats.items():
665
+ if stats["calls"] > 0:
666
+ # Shorten service names for display
667
+ short_name = service_name.replace("monitor_", "").replace("check_plugin_", "").replace("collect_system_", "")
668
+ svc_seg.add_lime(f"{short_name}: {stats['calls']}")
669
+
670
+ if total_calls > 0: # Only show if there are service calls
671
+ result.append(svc_seg.render())
672
+
673
+ # Cache the result
674
+ self.cached_dashboard_content = result
675
+ return result
443
676
 
444
677
  except Exception as e:
445
678
  logger.error(f"Error getting developer metrics content: {e}")
446
- return ["Developer Metrics: Error"]
679
+ seg = AgnosterSegment()
680
+ seg.add_neutral("Hooks: Error", "dark")
681
+ return [seg.render()]
447
682
 
448
683
  async def shutdown(self) -> None:
449
- """Shutdown the hook monitoring plugin."""
684
+ """Shutdown the hook monitoring plugin with proper task cleanup."""
450
685
  logger.info(f"Hook Monitor: Shutting down - processed {self.hook_executions} events, {self.failed_hooks} failures")
686
+
687
+ # Cancel discovery task if running
688
+ if self.discovery_task and not self.discovery_task.done():
689
+ self.discovery_task.cancel()
690
+ try:
691
+ await asyncio.wait_for(self.discovery_task, timeout=2.0)
692
+ except (asyncio.TimeoutError, asyncio.CancelledError):
693
+ logger.debug("Discovery task cancelled during shutdown")
694
+ except Exception as e:
695
+ logger.warning(f"Error cancelling discovery task: {e}")
696
+
697
+ # Cancel metrics collection task if running
698
+ if self.metrics_collection_task and not self.metrics_collection_task.done():
699
+ self.metrics_collection_task.cancel()
700
+ try:
701
+ await asyncio.wait_for(self.metrics_collection_task, timeout=2.0)
702
+ except (asyncio.TimeoutError, asyncio.CancelledError):
703
+ logger.debug("Metrics collection task cancelled during shutdown")
704
+ except Exception as e:
705
+ logger.warning(f"Error cancelling metrics collection task: {e}")
706
+
451
707
  self._log_final_report()
452
708
  # Only show shutdown message if not in pipe mode
453
709
  # if not getattr(self.renderer, 'pipe_mode', False):
@@ -859,6 +1115,10 @@ class HookMonitoringPlugin:
859
1115
  "metric_type": "execution_time"
860
1116
  })
861
1117
  """
1118
+ # Track service usage
1119
+ self.service_usage_stats["monitor_performance"]["calls"] += 1
1120
+ self.service_usage_stats["monitor_performance"]["last_called"] = datetime.datetime.now()
1121
+
862
1122
  plugin_name = params.get("plugin_name", "all")
863
1123
  metric_type = params.get("metric_type", "summary")
864
1124
 
@@ -896,6 +1156,10 @@ class HookMonitoringPlugin:
896
1156
  "detailed": True
897
1157
  })
898
1158
  """
1159
+ # Track service usage
1160
+ self.service_usage_stats["check_plugin_health"]["calls"] += 1
1161
+ self.service_usage_stats["check_plugin_health"]["last_called"] = datetime.datetime.now()
1162
+
899
1163
  plugin_name = params.get("plugin_name", "system")
900
1164
  detailed = params.get("detailed", False)
901
1165
 
@@ -936,6 +1200,10 @@ class HookMonitoringPlugin:
936
1200
  "include_performance": True
937
1201
  })
938
1202
  """
1203
+ # Track service usage
1204
+ self.service_usage_stats["collect_system_metrics"]["calls"] += 1
1205
+ self.service_usage_stats["collect_system_metrics"]["last_called"] = datetime.datetime.now()
1206
+
939
1207
  time_range = params.get("time_range", "current")
940
1208
  include_performance = params.get("include_performance", True)
941
1209
 
@@ -961,10 +1229,13 @@ class HookMonitoringPlugin:
961
1229
 
962
1230
  # [COMM] CROSS-PLUGIN COMMUNICATION HANDLERS
963
1231
 
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.
1232
+ async def _handle_health_check_request(self, message: Dict[str, Any], sender: str) -> Dict[str, Any]:
1233
+ """[COMM] SHOWCASE: Handle health check requests from other plugins with optional auto-response.
966
1234
 
967
- This demonstrates direct plugin-to-plugin communication.
1235
+ This demonstrates:
1236
+ - Direct plugin-to-plugin communication
1237
+ - Automatic service response based on configuration
1238
+ - Message tracking and statistics
968
1239
  """
969
1240
  logger.info(f"[COMM] Health check request received from {sender}")
970
1241
 
@@ -985,6 +1256,18 @@ class HookMonitoringPlugin:
985
1256
  self.plugin_health_stats[sender]["message_count"] += 1
986
1257
  self.plugin_health_stats[sender]["last_seen"] = datetime.datetime.now()
987
1258
 
1259
+ # Auto-respond if configured
1260
+ auto_respond = self.config.get("plugins.hook_monitoring.auto_respond_to_health_checks", True)
1261
+ if auto_respond:
1262
+ response = await self._provide_health_check({
1263
+ "plugin_name": message.get("plugin_name", "system"),
1264
+ "detailed": message.get("detailed", False)
1265
+ })
1266
+ logger.debug(f"[COMM] Auto-responded to {sender} with health check")
1267
+ return response
1268
+
1269
+ return {"status": "acknowledged", "auto_respond": False}
1270
+
988
1271
  async def _handle_performance_data_request(self, message: Dict[str, Any], sender: str) -> Dict[str, Any]:
989
1272
  """[COMM] SHOWCASE: Handle performance data requests from other plugins."""
990
1273
  logger.info(f"[DATA] Performance data request from {sender}")
@@ -1063,7 +1346,7 @@ class HookMonitoringPlugin:
1063
1346
  }
1064
1347
 
1065
1348
  def _update_performance_metrics(self, event_type: str, start_time: float) -> None:
1066
- """Update performance metrics for hook monitoring.
1349
+ """Update performance metrics with optional detailed tracking.
1067
1350
 
1068
1351
  Args:
1069
1352
  event_type: The event type being monitored.
@@ -1071,6 +1354,7 @@ class HookMonitoringPlugin:
1071
1354
  """
1072
1355
  execution_time = (time.time() - start_time) * 1000 # Convert to milliseconds
1073
1356
 
1357
+ # Standard metrics (always tracked)
1074
1358
  if event_type not in self.hook_performance:
1075
1359
  self.hook_performance[event_type] = {
1076
1360
  "total_time": 0,
@@ -1087,8 +1371,82 @@ class HookMonitoringPlugin:
1087
1371
  metrics["max_time"] = max(metrics["max_time"], execution_time)
1088
1372
  metrics["min_time"] = min(metrics["min_time"], execution_time)
1089
1373
 
1374
+ # Set baseline after 10 executions
1375
+ if metrics["count"] == 10 and event_type not in self.performance_baseline:
1376
+ self.performance_baseline[event_type] = metrics["avg_time"]
1377
+ logger.debug(f"Set performance baseline for {event_type}: {metrics['avg_time']:.2f}ms")
1378
+
1379
+ # Detailed tracking (optional)
1380
+ detailed_tracking = self.config.get("plugins.hook_monitoring.detailed_performance_tracking", True)
1381
+ if detailed_tracking:
1382
+ if event_type not in self.detailed_metrics:
1383
+ self.detailed_metrics[event_type] = {
1384
+ "execution_history": [], # Last 100 executions
1385
+ "percentile_95": 0,
1386
+ "percentile_99": 0,
1387
+ }
1388
+
1389
+ detail = self.detailed_metrics[event_type]
1390
+ detail["execution_history"].append(execution_time)
1391
+
1392
+ # Keep only last 100 executions
1393
+ if len(detail["execution_history"]) > 100:
1394
+ detail["execution_history"] = detail["execution_history"][-100:]
1395
+
1396
+ # Calculate percentiles (require at least 20 samples)
1397
+ if len(detail["execution_history"]) >= 20:
1398
+ sorted_times = sorted(detail["execution_history"])
1399
+ p95_idx = int(len(sorted_times) * 0.95)
1400
+ p99_idx = int(len(sorted_times) * 0.99)
1401
+ detail["percentile_95"] = sorted_times[p95_idx]
1402
+ detail["percentile_99"] = sorted_times[p99_idx]
1403
+
1404
+ def _check_performance_degradation(self) -> bool:
1405
+ """[DATA] SHOWCASE: Check if performance has degraded beyond threshold.
1406
+
1407
+ This demonstrates:
1408
+ - Performance baseline comparison
1409
+ - Configuration-driven degradation thresholds
1410
+ - Automatic performance degradation detection
1411
+ - Warning logging for degraded performance
1412
+
1413
+ Returns:
1414
+ True if degradation detected, False otherwise
1415
+ """
1416
+ threshold = self.config.get("plugins.hook_monitoring.performance_degradation_threshold", 0.15)
1417
+ degraded_events = []
1418
+
1419
+ for event_type, baseline_time in self.performance_baseline.items():
1420
+ if event_type in self.hook_performance:
1421
+ current_time = self.hook_performance[event_type]["avg_time"]
1422
+ # Only check degradation if baseline is meaningful (> 0.1ms)
1423
+ # This avoids false positives from sub-millisecond execution times
1424
+ if baseline_time > 0.1:
1425
+ degradation = (current_time - baseline_time) / baseline_time
1426
+
1427
+ if degradation > threshold:
1428
+ degraded_events.append({
1429
+ "event_type": event_type,
1430
+ "baseline_ms": baseline_time,
1431
+ "current_ms": current_time,
1432
+ "degradation_pct": degradation * 100
1433
+ })
1434
+
1435
+ if degraded_events:
1436
+ self.degradation_detected = True
1437
+ for event in degraded_events:
1438
+ logger.warning(
1439
+ f"Performance degradation detected: {event['event_type']} "
1440
+ f"baseline={event['baseline_ms']:.1f}ms current={event['current_ms']:.1f}ms "
1441
+ f"({event['degradation_pct']:.1f}% slower)"
1442
+ )
1443
+ return True
1444
+
1445
+ self.degradation_detected = False
1446
+ return False
1447
+
1090
1448
  def _update_health_status(self) -> None:
1091
- """Update the overall health status of the hook system."""
1449
+ """Update health status including performance degradation check."""
1092
1450
  total_hooks = self.hook_executions
1093
1451
  if total_hooks == 0:
1094
1452
  self.hook_health_status = "Starting"
@@ -1096,11 +1454,15 @@ class HookMonitoringPlugin:
1096
1454
 
1097
1455
  failure_rate = (self.failed_hooks + self.timeout_hooks) / total_hooks
1098
1456
 
1099
- if failure_rate == 0:
1457
+ # Check performance degradation
1458
+ degraded = self._check_performance_degradation()
1459
+
1460
+ # Determine health status (degradation affects status)
1461
+ if failure_rate == 0 and not degraded:
1100
1462
  self.hook_health_status = "Healthy"
1101
- elif failure_rate < self.config.get("performance.failure_rate_warning", 0.05):
1463
+ elif failure_rate < self.config.get("performance.failure_rate_warning", 0.05) and not degraded:
1102
1464
  self.hook_health_status = "Good"
1103
- elif failure_rate < self.config.get("performance.failure_rate_critical", 0.15):
1465
+ elif failure_rate < self.config.get("performance.failure_rate_critical", 0.15) or degraded:
1104
1466
  self.hook_health_status = "Warning"
1105
1467
  else:
1106
1468
  self.hook_health_status = "Critical"
@@ -1204,7 +1566,7 @@ class HookMonitoringPlugin:
1204
1566
  "summary": {
1205
1567
  "total_plugins": total_plugins,
1206
1568
  "active_plugins": active_plugins,
1207
- "registered_services": 3 if (self.service_registration_enabled and SDK_AVAILABLE) else 0,
1569
+ "registered_services": len(getattr(self, 'registered_services', [])),
1208
1570
  "system_health": self.hook_health_status,
1209
1571
  "overall_failure_rate": failure_rate,
1210
1572
  "last_updated": datetime.datetime.now().isoformat()
@@ -1226,11 +1588,7 @@ class HookMonitoringPlugin:
1226
1588
  "service_registration": {
1227
1589
  "sdk_available": SDK_AVAILABLE,
1228
1590
  "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 []
1591
+ "available_services": getattr(self, 'registered_services', [])
1234
1592
  },
1235
1593
 
1236
1594
  "cross_plugin_communication": {
@@ -1241,12 +1599,12 @@ class HookMonitoringPlugin:
1241
1599
  },
1242
1600
 
1243
1601
  "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"
1602
+ "[FIND] Plugin Discovery": "[ok] Active" if self.plugin_discovery_enabled else "Disabled",
1603
+ "[TOOL] Service Registration": "[ok] Active" if (self.service_registration_enabled and SDK_AVAILABLE) else "Disabled",
1604
+ "[COMM] Cross-Plugin Comm": "[ok] Active" if self.enable_cross_plugin_comm else "Disabled",
1605
+ "[DATA] Performance Monitoring": "[ok] Active",
1606
+ "[HEALTH] Health Monitoring": "[ok] Active",
1607
+ "[METRICS] Metrics Collection": "[ok] Active"
1250
1608
  }
1251
1609
  }
1252
1610