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
@@ -8,9 +8,10 @@ import logging
8
8
  import subprocess
9
9
  from datetime import datetime
10
10
  from pathlib import Path
11
- from typing import Any, Dict, Optional
11
+ from typing import Any, Dict, Optional, List
12
12
 
13
13
  from core.events.models import CommandDefinition, CommandCategory, CommandMode
14
+ from core.io.visual_effects import AgnosterSegment
14
15
 
15
16
  logger = logging.getLogger(__name__)
16
17
 
@@ -18,13 +19,12 @@ logger = logging.getLogger(__name__)
18
19
  class SaveConversationPlugin:
19
20
  """Plugin for saving conversations to file or clipboard."""
20
21
 
21
- def __init__(self, name: str = "save_conversation", state_manager=None, event_bus=None,
22
+ def __init__(self, name: str = "save_conversation", event_bus=None,
22
23
  renderer=None, config=None) -> None:
23
24
  """Initialize the save conversation plugin.
24
25
 
25
26
  Args:
26
27
  name: Plugin name (default: "save_conversation")
27
- state_manager: State manager instance
28
28
  event_bus: Event bus instance
29
29
  renderer: Terminal renderer instance
30
30
  config: Configuration manager instance
@@ -36,7 +36,6 @@ class SaveConversationPlugin:
36
36
  self.logger = logger
37
37
 
38
38
  # Store injected dependencies
39
- self.state_manager = state_manager
40
39
  self.event_bus = event_bus
41
40
  self.renderer = renderer
42
41
  self.config_manager = config
@@ -69,14 +68,64 @@ class SaveConversationPlugin:
69
68
  # Register the /save command
70
69
  self._register_commands()
71
70
 
71
+ # Register status view
72
+ await self._register_status_view()
73
+
72
74
  self.logger.info("Save conversation plugin initialized successfully")
73
75
 
74
76
  except Exception as e:
75
77
  self.logger.error(f"Error initializing save conversation plugin: {e}")
76
78
  raise
77
79
 
80
+ async def _register_status_view(self) -> None:
81
+ """Register save conversation status view."""
82
+ try:
83
+ if (self.renderer and
84
+ hasattr(self.renderer, 'status_renderer') and
85
+ self.renderer.status_renderer and
86
+ hasattr(self.renderer.status_renderer, 'status_registry') and
87
+ self.renderer.status_renderer.status_registry):
88
+
89
+ from core.io.status_renderer import StatusViewConfig, BlockConfig
90
+
91
+ view = StatusViewConfig(
92
+ name="Save Conversation",
93
+ plugin_source="save_conversation",
94
+ priority=300,
95
+ blocks=[BlockConfig(
96
+ width_fraction=1.0,
97
+ content_provider=self._get_status_content,
98
+ title="Save",
99
+ priority=100
100
+ )],
101
+ )
102
+
103
+ registry = self.renderer.status_renderer.status_registry
104
+ registry.register_status_view("save_conversation", view)
105
+ self.logger.info("Registered 'Save Conversation' status view")
106
+
107
+ except Exception as e:
108
+ self.logger.error(f"Failed to register status view: {e}")
109
+
110
+ def _get_status_content(self) -> List[str]:
111
+ """Get save conversation status (agnoster style)."""
112
+ try:
113
+ seg = AgnosterSegment()
114
+ seg.add_lime("Save", "dark")
115
+ seg.add_cyan("/save", "dark")
116
+ seg.add_neutral("file | clipboard | json | md", "mid")
117
+ return [seg.render()]
118
+
119
+ except Exception as e:
120
+ self.logger.error(f"Error getting status content: {e}")
121
+ seg = AgnosterSegment()
122
+ seg.add_neutral("Save: Error", "dark")
123
+ return [seg.render()]
124
+
78
125
  def _register_commands(self) -> None:
79
126
  """Register all plugin commands."""
127
+ from core.events.models import SubcommandInfo
128
+
80
129
  save_command = CommandDefinition(
81
130
  name="save",
82
131
  description="Save conversation to file or clipboard",
@@ -85,7 +134,15 @@ class SaveConversationPlugin:
85
134
  aliases=["export", "transcript"],
86
135
  mode=CommandMode.INSTANT,
87
136
  category=CommandCategory.CONVERSATION,
88
- icon="[SAVE]"
137
+ icon="[SAVE]",
138
+ subcommands=[
139
+ SubcommandInfo("transcript", "[clipboard|both|local]", "Plain text format"),
140
+ SubcommandInfo("markdown", "[clipboard|both|local]", "Markdown format"),
141
+ SubcommandInfo("jsonl", "[clipboard|both|local]", "JSON lines format"),
142
+ SubcommandInfo("clipboard", "", "Copy to clipboard (default format)"),
143
+ SubcommandInfo("both", "", "Save to file and clipboard"),
144
+ SubcommandInfo("local", "", "Save to current directory"),
145
+ ]
89
146
  )
90
147
 
91
148
  self.command_registry.register_command(save_command)
@@ -114,18 +171,30 @@ class SaveConversationPlugin:
114
171
  output_dir = self.config.get("plugins.save_conversation.output_directory", "logs/transcripts")
115
172
 
116
173
  # Parse command arguments
117
- if len(args) >= 1:
118
- save_format = args[0].lower()
119
- if len(args) >= 2:
120
- save_to = args[1].lower()
174
+ # Smart detection: if first arg is a destination, use default format
175
+ valid_formats = ["transcript", "markdown", "jsonl", "raw"]
176
+ valid_destinations = ["file", "clipboard", "both", "local"]
121
177
 
122
- # Validate format
123
- if save_format not in ["transcript", "markdown", "jsonl", "raw"]:
124
- return f"Error: Invalid format '{save_format}'. Use: transcript, markdown, jsonl, or raw"
178
+ if len(args) >= 1:
179
+ first_arg = args[0].lower()
180
+ if first_arg in valid_destinations:
181
+ # First arg is destination, keep default format
182
+ save_to = first_arg
183
+ elif first_arg in valid_formats:
184
+ save_format = first_arg
185
+ if len(args) >= 2:
186
+ save_to = args[1].lower()
187
+ else:
188
+ return f"Error: Invalid argument '{first_arg}'. Use format ({', '.join(valid_formats)}) or destination ({', '.join(valid_destinations)})"
125
189
 
126
190
  # Validate destination
127
- if save_to not in ["file", "clipboard", "both"]:
128
- return f"Error: Invalid destination '{save_to}'. Use: file, clipboard, or both"
191
+ if save_to not in valid_destinations:
192
+ return f"Error: Invalid destination '{save_to}'. Use: {', '.join(valid_destinations)}"
193
+
194
+ # Local saves to current working directory
195
+ if save_to == "local":
196
+ output_dir = "."
197
+ save_to = "file"
129
198
 
130
199
  # Get conversation content
131
200
  if not self.llm_service:
@@ -324,12 +393,13 @@ class SaveConversationPlugin:
324
393
  "content": msg.get("content")
325
394
  })
326
395
 
327
- # Get model info from config if available
396
+ # Get model info from active profile
328
397
  model = "unknown"
329
398
  temperature = 0.7
330
- if self.config:
331
- model = self.config.get("core.llm.model", "unknown")
332
- temperature = self.config.get("core.llm.temperature", 0.7)
399
+ if self.llm_service and self.llm_service.profile_manager:
400
+ profile = self.llm_service.profile_manager.get_active_profile()
401
+ model = profile.get_model() or "unknown"
402
+ temperature = profile.get_temperature()
333
403
 
334
404
  payload = {
335
405
  "model": model,
@@ -358,13 +428,18 @@ class SaveConversationPlugin:
358
428
  """
359
429
  # Create output directory
360
430
  from core.utils.config_utils import get_config_directory
361
- config_dir = get_config_directory()
362
431
 
363
- # Handle relative paths
364
- if not output_dir.startswith('/'):
365
- save_dir = config_dir / output_dir
366
- else:
432
+ # Handle paths
433
+ if output_dir == ".":
434
+ # Local: save to current working directory
435
+ save_dir = Path.cwd()
436
+ elif output_dir.startswith('/'):
437
+ # Absolute path
367
438
  save_dir = Path(output_dir)
439
+ else:
440
+ # Relative path under config directory
441
+ config_dir = get_config_directory()
442
+ save_dir = config_dir / output_dir
368
443
 
369
444
  save_dir.mkdir(parents=True, exist_ok=True)
370
445
 
@@ -475,17 +550,8 @@ class SaveConversationPlugin:
475
550
 
476
551
  async def register_hooks(self) -> None:
477
552
  """Register event hooks for the plugin."""
478
- # This plugin doesn't need hooks, just commands
479
553
  pass
480
554
 
481
- def get_status_line(self) -> str:
482
- """Get status line information for the plugin.
483
-
484
- Returns:
485
- Status line string.
486
- """
487
- return "Save: /save"
488
-
489
555
  @staticmethod
490
556
  def get_default_config() -> Dict[str, Any]:
491
557
  """Get default configuration for save conversation plugin."""
@@ -1,82 +1,99 @@
1
- """System commands plugin for core application functionality."""
1
+ """System commands plugin - provides status view for core system commands."""
2
2
 
3
3
  import logging
4
- from typing import Dict, Any
5
- from core.commands.system_commands import SystemCommandsPlugin as CoreSystemCommandsPlugin
4
+ from typing import Dict, Any, List
5
+
6
+ from core.io.visual_effects import AgnosterSegment
6
7
 
7
8
  logger = logging.getLogger(__name__)
8
9
 
9
10
 
10
11
  class SystemCommandsPlugin:
11
- """Plugin wrapper for system commands integration.
12
+ """Plugin that provides status view for system commands.
12
13
 
13
- Provides the system commands as a plugin that gets loaded
14
- during application initialization.
14
+ Note: System commands (/help, /config, /status, etc.) are registered
15
+ by core application in _initialize_slash_commands(). This plugin
16
+ only provides the status view display.
15
17
  """
16
18
 
17
- def __init__(self) -> None:
18
- """Initialize the system commands plugin wrapper."""
19
- self.name = "system_commands"
19
+ def __init__(self, name: str = "system_commands",
20
+ event_bus=None, renderer=None, config=None) -> None:
21
+ """Initialize the system commands plugin.
22
+
23
+ Args:
24
+ name: Plugin name.
25
+ event_bus: Event bus (unused).
26
+ renderer: Terminal renderer.
27
+ config: Configuration manager (unused).
28
+ """
29
+ self.name = name
20
30
  self.version = "1.0.0"
21
- self.description = "Core system commands (/help, /config, /status, etc.)"
31
+ self.description = "Status view for core system commands"
22
32
  self.enabled = True
23
- self.system_commands = None
33
+ self.renderer = renderer
24
34
  self.logger = logger
25
35
 
26
36
  async def initialize(self, event_bus, config, **kwargs) -> None:
27
- """Initialize the plugin and register system commands.
28
-
29
- Args:
30
- event_bus: Application event bus.
31
- config: Configuration manager.
32
- **kwargs: Additional initialization parameters.
33
- """
37
+ """Initialize the plugin."""
34
38
  try:
35
- # Get command registry from input handler if available
36
- command_registry = kwargs.get('command_registry')
37
- if not command_registry:
38
- self.logger.warning("No command registry provided, system commands not registered")
39
- return
40
-
41
- # Create and initialize system commands
42
- self.system_commands = CoreSystemCommandsPlugin(
43
- command_registry=command_registry,
44
- event_bus=event_bus,
45
- config_manager=config
46
- )
47
-
48
- # Register all system commands
49
- self.system_commands.register_commands()
50
-
39
+ self.renderer = kwargs.get('renderer')
40
+ await self._register_status_view()
51
41
  self.logger.info("System commands plugin initialized successfully")
52
-
53
42
  except Exception as e:
54
43
  self.logger.error(f"Error initializing system commands plugin: {e}")
55
44
  raise
56
45
 
57
- async def shutdown(self) -> None:
58
- """Shutdown the plugin and cleanup resources."""
46
+ async def _register_status_view(self) -> None:
47
+ """Register system commands status view."""
59
48
  try:
60
- if self.system_commands:
61
- # Unregister commands would happen here if needed
62
- self.logger.info("System commands plugin shutdown completed")
49
+ if (self.renderer and
50
+ hasattr(self.renderer, 'status_renderer') and
51
+ self.renderer.status_renderer and
52
+ hasattr(self.renderer.status_renderer, 'status_registry') and
53
+ self.renderer.status_renderer.status_registry):
54
+
55
+ from core.io.status_renderer import StatusViewConfig, BlockConfig
56
+
57
+ view = StatusViewConfig(
58
+ name="System Commands",
59
+ plugin_source="system_commands",
60
+ priority=400,
61
+ blocks=[BlockConfig(
62
+ width_fraction=1.0,
63
+ content_provider=self._get_status_content,
64
+ title="System Commands",
65
+ priority=100
66
+ )],
67
+ )
68
+
69
+ registry = self.renderer.status_renderer.status_registry
70
+ registry.register_status_view("system_commands", view)
71
+ self.logger.info("Registered 'System Commands' status view")
63
72
 
64
73
  except Exception as e:
65
- self.logger.error(f"Error shutting down system commands plugin: {e}")
74
+ self.logger.error(f"Failed to register status view: {e}")
66
75
 
67
- def get_status_line(self) -> str:
68
- """Get status line information for the plugin.
76
+ def _get_status_content(self) -> List[str]:
77
+ """Get system commands status (agnoster style)."""
78
+ try:
79
+ seg = AgnosterSegment()
80
+ seg.add_lime("Commands", "dark")
81
+ seg.add_cyan("Active", "dark")
82
+ seg.add_neutral("/help /config /status", "mid")
83
+ return [seg.render()]
84
+ except Exception as e:
85
+ self.logger.error(f"Error getting status content: {e}")
86
+ seg = AgnosterSegment()
87
+ seg.add_neutral("Commands: Error", "dark")
88
+ return [seg.render()]
69
89
 
70
- Returns:
71
- Status line string.
72
- """
73
- if self.system_commands:
74
- return "System commands active"
75
- return "System commands inactive"
90
+ async def shutdown(self) -> None:
91
+ """Shutdown the plugin."""
92
+ self.logger.info("System commands plugin shutdown completed")
76
93
 
77
94
  @staticmethod
78
95
  def get_default_config() -> Dict[str, Any]:
79
- """Get default configuration for system commands plugin."""
96
+ """Get default configuration."""
80
97
  return {
81
98
  "plugins": {
82
99
  "system_commands": {
@@ -84,10 +101,7 @@ class SystemCommandsPlugin:
84
101
  }
85
102
  }
86
103
  }
87
-
88
- async def register_hooks(self) -> None:
89
- """Register event hooks for the plugin.
90
104
 
91
- System commands don't need additional hooks beyond command registration.
92
- """
93
- pass
105
+ async def register_hooks(self) -> None:
106
+ """Register event hooks (none needed)."""
107
+ pass