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.
- core/__init__.py +18 -0
- core/application.py +578 -0
- core/cli.py +193 -0
- core/commands/__init__.py +43 -0
- core/commands/executor.py +277 -0
- core/commands/menu_renderer.py +319 -0
- core/commands/parser.py +186 -0
- core/commands/registry.py +331 -0
- core/commands/system_commands.py +479 -0
- core/config/__init__.py +7 -0
- core/config/llm_task_config.py +110 -0
- core/config/loader.py +501 -0
- core/config/manager.py +112 -0
- core/config/plugin_config_manager.py +346 -0
- core/config/plugin_schema.py +424 -0
- core/config/service.py +399 -0
- core/effects/__init__.py +1 -0
- core/events/__init__.py +12 -0
- core/events/bus.py +129 -0
- core/events/executor.py +154 -0
- core/events/models.py +258 -0
- core/events/processor.py +176 -0
- core/events/registry.py +289 -0
- core/fullscreen/__init__.py +19 -0
- core/fullscreen/command_integration.py +290 -0
- core/fullscreen/components/__init__.py +12 -0
- core/fullscreen/components/animation.py +258 -0
- core/fullscreen/components/drawing.py +160 -0
- core/fullscreen/components/matrix_components.py +177 -0
- core/fullscreen/manager.py +302 -0
- core/fullscreen/plugin.py +204 -0
- core/fullscreen/renderer.py +282 -0
- core/fullscreen/session.py +324 -0
- core/io/__init__.py +52 -0
- core/io/buffer_manager.py +362 -0
- core/io/config_status_view.py +272 -0
- core/io/core_status_views.py +410 -0
- core/io/input_errors.py +313 -0
- core/io/input_handler.py +2655 -0
- core/io/input_mode_manager.py +402 -0
- core/io/key_parser.py +344 -0
- core/io/layout.py +587 -0
- core/io/message_coordinator.py +204 -0
- core/io/message_renderer.py +601 -0
- core/io/modal_interaction_handler.py +315 -0
- core/io/raw_input_processor.py +946 -0
- core/io/status_renderer.py +845 -0
- core/io/terminal_renderer.py +586 -0
- core/io/terminal_state.py +551 -0
- core/io/visual_effects.py +734 -0
- core/llm/__init__.py +26 -0
- core/llm/api_communication_service.py +863 -0
- core/llm/conversation_logger.py +473 -0
- core/llm/conversation_manager.py +414 -0
- core/llm/file_operations_executor.py +1401 -0
- core/llm/hook_system.py +402 -0
- core/llm/llm_service.py +1629 -0
- core/llm/mcp_integration.py +386 -0
- core/llm/message_display_service.py +450 -0
- core/llm/model_router.py +214 -0
- core/llm/plugin_sdk.py +396 -0
- core/llm/response_parser.py +848 -0
- core/llm/response_processor.py +364 -0
- core/llm/tool_executor.py +520 -0
- core/logging/__init__.py +19 -0
- core/logging/setup.py +208 -0
- core/models/__init__.py +5 -0
- core/models/base.py +23 -0
- core/plugins/__init__.py +13 -0
- core/plugins/collector.py +212 -0
- core/plugins/discovery.py +386 -0
- core/plugins/factory.py +263 -0
- core/plugins/registry.py +152 -0
- core/storage/__init__.py +5 -0
- core/storage/state_manager.py +84 -0
- core/ui/__init__.py +6 -0
- core/ui/config_merger.py +176 -0
- core/ui/config_widgets.py +369 -0
- core/ui/live_modal_renderer.py +276 -0
- core/ui/modal_actions.py +162 -0
- core/ui/modal_overlay_renderer.py +373 -0
- core/ui/modal_renderer.py +591 -0
- core/ui/modal_state_manager.py +443 -0
- core/ui/widget_integration.py +222 -0
- core/ui/widgets/__init__.py +27 -0
- core/ui/widgets/base_widget.py +136 -0
- core/ui/widgets/checkbox.py +85 -0
- core/ui/widgets/dropdown.py +140 -0
- core/ui/widgets/label.py +78 -0
- core/ui/widgets/slider.py +185 -0
- core/ui/widgets/text_input.py +224 -0
- core/utils/__init__.py +11 -0
- core/utils/config_utils.py +656 -0
- core/utils/dict_utils.py +212 -0
- core/utils/error_utils.py +275 -0
- core/utils/key_reader.py +171 -0
- core/utils/plugin_utils.py +267 -0
- core/utils/prompt_renderer.py +151 -0
- kollabor-0.4.9.dist-info/METADATA +298 -0
- kollabor-0.4.9.dist-info/RECORD +128 -0
- kollabor-0.4.9.dist-info/WHEEL +5 -0
- kollabor-0.4.9.dist-info/entry_points.txt +2 -0
- kollabor-0.4.9.dist-info/licenses/LICENSE +21 -0
- kollabor-0.4.9.dist-info/top_level.txt +4 -0
- kollabor_cli_main.py +20 -0
- plugins/__init__.py +1 -0
- plugins/enhanced_input/__init__.py +18 -0
- plugins/enhanced_input/box_renderer.py +103 -0
- plugins/enhanced_input/box_styles.py +142 -0
- plugins/enhanced_input/color_engine.py +165 -0
- plugins/enhanced_input/config.py +150 -0
- plugins/enhanced_input/cursor_manager.py +72 -0
- plugins/enhanced_input/geometry.py +81 -0
- plugins/enhanced_input/state.py +130 -0
- plugins/enhanced_input/text_processor.py +115 -0
- plugins/enhanced_input_plugin.py +385 -0
- plugins/fullscreen/__init__.py +9 -0
- plugins/fullscreen/example_plugin.py +327 -0
- plugins/fullscreen/matrix_plugin.py +132 -0
- plugins/hook_monitoring_plugin.py +1299 -0
- plugins/query_enhancer_plugin.py +350 -0
- plugins/save_conversation_plugin.py +502 -0
- plugins/system_commands_plugin.py +93 -0
- plugins/tmux_plugin.py +795 -0
- plugins/workflow_enforcement_plugin.py +629 -0
- system_prompt/default.md +1286 -0
- system_prompt/default_win.md +265 -0
- system_prompt/example_with_trender.md +47 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
"""Plugin configuration manager for dynamic schema registration and widget generation."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from typing import Any, Dict, List, Optional, Type
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from .plugin_schema import PluginConfigSchema, ConfigField, WidgetType
|
|
8
|
+
from ..plugins.discovery import PluginDiscovery
|
|
9
|
+
from ..utils.plugin_utils import get_plugin_config_safely, has_method
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PluginConfigManager:
|
|
15
|
+
"""Manages dynamic plugin configuration schemas and widget generation.
|
|
16
|
+
|
|
17
|
+
This manager coordinates between the plugin discovery system and the
|
|
18
|
+
configuration UI system to automatically generate widgets for plugin
|
|
19
|
+
configuration based on plugin-defined schemas.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, plugin_discovery: PluginDiscovery):
|
|
23
|
+
"""Initialize the plugin config manager.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
plugin_discovery: Plugin discovery instance for accessing loaded plugins.
|
|
27
|
+
"""
|
|
28
|
+
self.plugin_discovery = plugin_discovery
|
|
29
|
+
self.plugin_schemas: Dict[str, PluginConfigSchema] = {}
|
|
30
|
+
self.widget_definitions: List[Dict[str, Any]] = []
|
|
31
|
+
logger.info("PluginConfigManager initialized")
|
|
32
|
+
|
|
33
|
+
def register_plugin_schema(self, plugin_name: str, schema: PluginConfigSchema) -> None:
|
|
34
|
+
"""Register a plugin's configuration schema.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
plugin_name: Name of the plugin.
|
|
38
|
+
schema: Plugin configuration schema.
|
|
39
|
+
"""
|
|
40
|
+
self.plugin_schemas[plugin_name] = schema
|
|
41
|
+
logger.info(f"Registered config schema for plugin: {plugin_name}")
|
|
42
|
+
|
|
43
|
+
# Update widget definitions
|
|
44
|
+
self._rebuild_widget_definitions()
|
|
45
|
+
|
|
46
|
+
def discover_plugin_schemas(self) -> None:
|
|
47
|
+
"""Discover and register schemas from all loaded plugins."""
|
|
48
|
+
logger.info("Discovering plugin configuration schemas...")
|
|
49
|
+
|
|
50
|
+
for plugin_name, plugin_class in self.plugin_discovery.loaded_classes.items():
|
|
51
|
+
try:
|
|
52
|
+
# Check if plugin has a get_config_schema method
|
|
53
|
+
if has_method(plugin_class, "get_config_schema"):
|
|
54
|
+
logger.debug(f"Plugin {plugin_name} has get_config_schema method")
|
|
55
|
+
|
|
56
|
+
# Get schema from plugin
|
|
57
|
+
schema = plugin_class.get_config_schema()
|
|
58
|
+
|
|
59
|
+
if isinstance(schema, PluginConfigSchema):
|
|
60
|
+
self.register_plugin_schema(plugin_name, schema)
|
|
61
|
+
else:
|
|
62
|
+
logger.warning(f"Plugin {plugin_name} returned invalid schema type: {type(schema)}")
|
|
63
|
+
|
|
64
|
+
# Fallback: try to create schema from get_default_config
|
|
65
|
+
elif has_method(plugin_class, "get_default_config"):
|
|
66
|
+
logger.debug(f"Creating schema from default config for plugin: {plugin_name}")
|
|
67
|
+
schema = self._create_schema_from_default_config(plugin_name, plugin_class)
|
|
68
|
+
if schema:
|
|
69
|
+
self.register_plugin_schema(plugin_name, schema)
|
|
70
|
+
else:
|
|
71
|
+
logger.debug(f"Plugin {plugin_name} has no configuration schema")
|
|
72
|
+
|
|
73
|
+
except Exception as e:
|
|
74
|
+
logger.error(f"Failed to discover schema for plugin {plugin_name}: {e}")
|
|
75
|
+
|
|
76
|
+
logger.info(f"Discovered schemas for {len(self.plugin_schemas)} plugins")
|
|
77
|
+
|
|
78
|
+
def _create_schema_from_default_config(self, plugin_name: str, plugin_class: Type) -> Optional[PluginConfigSchema]:
|
|
79
|
+
"""Create a basic schema from a plugin's default config.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
plugin_name: Name of the plugin.
|
|
83
|
+
plugin_class: Plugin class.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
Basic schema if successful, None otherwise.
|
|
87
|
+
"""
|
|
88
|
+
try:
|
|
89
|
+
default_config = get_plugin_config_safely(plugin_class)
|
|
90
|
+
if not default_config:
|
|
91
|
+
return None
|
|
92
|
+
|
|
93
|
+
from .plugin_schema import ConfigSchemaBuilder, WidgetType, ValidationType
|
|
94
|
+
|
|
95
|
+
builder = ConfigSchemaBuilder(plugin_name, f"Auto-generated schema for {plugin_name}")
|
|
96
|
+
|
|
97
|
+
# Add 'enabled' field if present
|
|
98
|
+
if 'enabled' in default_config:
|
|
99
|
+
builder.add_checkbox(
|
|
100
|
+
key="enabled",
|
|
101
|
+
label="Enabled",
|
|
102
|
+
default=default_config['enabled'],
|
|
103
|
+
help_text="Enable or disable this plugin"
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
# Add other fields with basic type inference
|
|
107
|
+
for key, value in default_config.items():
|
|
108
|
+
if key == 'enabled':
|
|
109
|
+
continue # Already handled
|
|
110
|
+
|
|
111
|
+
if isinstance(value, bool):
|
|
112
|
+
builder.add_checkbox(
|
|
113
|
+
key=key,
|
|
114
|
+
label=key.replace('_', ' ').title(),
|
|
115
|
+
default=value,
|
|
116
|
+
help_text=f"Configuration option: {key}"
|
|
117
|
+
)
|
|
118
|
+
elif isinstance(value, (int, float)):
|
|
119
|
+
if isinstance(value, int):
|
|
120
|
+
builder.add_slider(
|
|
121
|
+
key=key,
|
|
122
|
+
label=key.replace('_', ' ').title(),
|
|
123
|
+
default=value,
|
|
124
|
+
min_value=0,
|
|
125
|
+
max_value=max(100, value * 2),
|
|
126
|
+
help_text=f"Numeric configuration: {key}"
|
|
127
|
+
)
|
|
128
|
+
else:
|
|
129
|
+
builder.add_slider(
|
|
130
|
+
key=key,
|
|
131
|
+
label=key.replace('_', ' ').title(),
|
|
132
|
+
default=value,
|
|
133
|
+
min_value=0.0,
|
|
134
|
+
max_value=max(1.0, value * 2),
|
|
135
|
+
step=0.1,
|
|
136
|
+
help_text=f"Float configuration: {key}"
|
|
137
|
+
)
|
|
138
|
+
elif isinstance(value, str):
|
|
139
|
+
builder.add_text_input(
|
|
140
|
+
key=key,
|
|
141
|
+
label=key.replace('_', ' ').title(),
|
|
142
|
+
default=value,
|
|
143
|
+
help_text=f"Text configuration: {key}"
|
|
144
|
+
)
|
|
145
|
+
elif isinstance(value, list):
|
|
146
|
+
# For lists, assume it's a dropdown of options
|
|
147
|
+
if len(value) <= 10: # Reasonable limit for dropdown
|
|
148
|
+
builder.add_dropdown(
|
|
149
|
+
key=key,
|
|
150
|
+
label=key.replace('_', ' ').title(),
|
|
151
|
+
options=value,
|
|
152
|
+
default=value[0] if value else "",
|
|
153
|
+
help_text=f"Select from options: {key}"
|
|
154
|
+
)
|
|
155
|
+
else:
|
|
156
|
+
builder.add_text_input(
|
|
157
|
+
key=key,
|
|
158
|
+
label=key.replace('_', ' ').title(),
|
|
159
|
+
default=str(value),
|
|
160
|
+
help_text=f"List configuration: {key}"
|
|
161
|
+
)
|
|
162
|
+
elif isinstance(value, dict):
|
|
163
|
+
# For nested dicts, create a text input with JSON
|
|
164
|
+
builder.add_text_input(
|
|
165
|
+
key=key,
|
|
166
|
+
label=key.replace('_', ' ').title(),
|
|
167
|
+
default=str(value),
|
|
168
|
+
validation_type=ValidationType.JSON,
|
|
169
|
+
help_text=f"JSON configuration: {key}"
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
return builder.build()
|
|
173
|
+
|
|
174
|
+
except Exception as e:
|
|
175
|
+
logger.error(f"Failed to create schema from default config for {plugin_name}: {e}")
|
|
176
|
+
return None
|
|
177
|
+
|
|
178
|
+
def get_plugin_schema(self, plugin_name: str) -> Optional[PluginConfigSchema]:
|
|
179
|
+
"""Get the configuration schema for a specific plugin.
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
plugin_name: Name of the plugin.
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
Plugin schema if found, None otherwise.
|
|
186
|
+
"""
|
|
187
|
+
return self.plugin_schemas.get(plugin_name)
|
|
188
|
+
|
|
189
|
+
def get_all_schemas(self) -> Dict[str, PluginConfigSchema]:
|
|
190
|
+
"""Get all registered plugin schemas.
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
Dictionary mapping plugin names to their schemas.
|
|
194
|
+
"""
|
|
195
|
+
return self.plugin_schemas.copy()
|
|
196
|
+
|
|
197
|
+
def _rebuild_widget_definitions(self) -> None:
|
|
198
|
+
"""Rebuild the complete widget definitions list."""
|
|
199
|
+
self.widget_definitions = []
|
|
200
|
+
|
|
201
|
+
for plugin_name, schema in self.plugin_schemas.items():
|
|
202
|
+
plugin_widgets = schema.to_widget_definitions()
|
|
203
|
+
self.widget_definitions.extend(plugin_widgets)
|
|
204
|
+
logger.debug(f"Added {len(plugin_widgets)} widgets for plugin: {plugin_name}")
|
|
205
|
+
|
|
206
|
+
logger.info(f"Rebuilt widget definitions: {len(self.widget_definitions)} total widgets")
|
|
207
|
+
|
|
208
|
+
def get_widget_definitions(self) -> List[Dict[str, Any]]:
|
|
209
|
+
"""Get all widget definitions for all registered plugins.
|
|
210
|
+
|
|
211
|
+
Returns:
|
|
212
|
+
List of widget definition dictionaries.
|
|
213
|
+
"""
|
|
214
|
+
if not self.widget_definitions:
|
|
215
|
+
self._rebuild_widget_definitions()
|
|
216
|
+
|
|
217
|
+
return self.widget_definitions.copy()
|
|
218
|
+
|
|
219
|
+
def get_plugin_config_sections(self) -> List[Dict[str, Any]]:
|
|
220
|
+
"""Get UI sections for plugin configuration.
|
|
221
|
+
|
|
222
|
+
Returns:
|
|
223
|
+
List of section definitions for the configuration UI.
|
|
224
|
+
"""
|
|
225
|
+
sections = []
|
|
226
|
+
|
|
227
|
+
# Group plugins by category
|
|
228
|
+
plugins_by_category = {}
|
|
229
|
+
for plugin_name, schema in self.plugin_schemas.items():
|
|
230
|
+
for category in schema.categories:
|
|
231
|
+
if category not in plugins_by_category:
|
|
232
|
+
plugins_by_category[category] = []
|
|
233
|
+
plugins_by_category[category].append((plugin_name, schema))
|
|
234
|
+
|
|
235
|
+
# Create sections for each category
|
|
236
|
+
for category, plugins in plugins_by_category.items():
|
|
237
|
+
category_widgets = []
|
|
238
|
+
|
|
239
|
+
for plugin_name, schema in plugins:
|
|
240
|
+
plugin_widgets = schema.to_widget_definitions()
|
|
241
|
+
# Add plugin name to each widget for identification
|
|
242
|
+
for widget in plugin_widgets:
|
|
243
|
+
widget["plugin_name"] = plugin_name
|
|
244
|
+
category_widgets.extend(plugin_widgets)
|
|
245
|
+
|
|
246
|
+
if category_widgets:
|
|
247
|
+
sections.append({
|
|
248
|
+
"title": f"{category} Plugins",
|
|
249
|
+
"widgets": category_widgets
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
return sections
|
|
253
|
+
|
|
254
|
+
def validate_plugin_config(self, plugin_name: str, config: Dict[str, Any]) -> Dict[str, Any]:
|
|
255
|
+
"""Validate a plugin's configuration against its schema.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
plugin_name: Name of the plugin.
|
|
259
|
+
config: Configuration to validate.
|
|
260
|
+
|
|
261
|
+
Returns:
|
|
262
|
+
Validation result dictionary.
|
|
263
|
+
"""
|
|
264
|
+
schema = self.get_plugin_schema(plugin_name)
|
|
265
|
+
if not schema:
|
|
266
|
+
return {
|
|
267
|
+
"valid": False,
|
|
268
|
+
"errors": {"schema": f"No schema found for plugin: {plugin_name}"}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return schema.validate_config(config)
|
|
272
|
+
|
|
273
|
+
def get_plugin_default_config(self, plugin_name: str) -> Dict[str, Any]:
|
|
274
|
+
"""Get the default configuration for a plugin.
|
|
275
|
+
|
|
276
|
+
Args:
|
|
277
|
+
plugin_name: Name of the plugin.
|
|
278
|
+
|
|
279
|
+
Returns:
|
|
280
|
+
Default configuration dictionary.
|
|
281
|
+
"""
|
|
282
|
+
schema = self.get_plugin_schema(plugin_name)
|
|
283
|
+
if not schema:
|
|
284
|
+
return {}
|
|
285
|
+
|
|
286
|
+
return schema.get_default_config()
|
|
287
|
+
|
|
288
|
+
def merge_plugin_configs(self) -> Dict[str, Any]:
|
|
289
|
+
"""Merge all plugin configurations into a single dictionary.
|
|
290
|
+
|
|
291
|
+
Returns:
|
|
292
|
+
Merged configuration dictionary with all plugin configs.
|
|
293
|
+
"""
|
|
294
|
+
merged_config = {}
|
|
295
|
+
|
|
296
|
+
for plugin_name, schema in self.plugin_schemas.items():
|
|
297
|
+
plugin_config = schema.get_default_config()
|
|
298
|
+
if plugin_config:
|
|
299
|
+
merged_config[plugin_name] = plugin_config
|
|
300
|
+
|
|
301
|
+
return merged_config
|
|
302
|
+
|
|
303
|
+
def get_stats(self) -> Dict[str, Any]:
|
|
304
|
+
"""Get statistics about the plugin configuration system.
|
|
305
|
+
|
|
306
|
+
Returns:
|
|
307
|
+
Statistics dictionary.
|
|
308
|
+
"""
|
|
309
|
+
total_fields = sum(len(schema.fields) for schema in self.plugin_schemas.values())
|
|
310
|
+
total_widgets = len(self.widget_definitions)
|
|
311
|
+
|
|
312
|
+
widget_type_counts = {}
|
|
313
|
+
for widget_def in self.widget_definitions:
|
|
314
|
+
widget_type = widget_def.get("type", "unknown")
|
|
315
|
+
widget_type_counts[widget_type] = widget_type_counts.get(widget_type, 0) + 1
|
|
316
|
+
|
|
317
|
+
return {
|
|
318
|
+
"registered_plugins": len(self.plugin_schemas),
|
|
319
|
+
"total_fields": total_fields,
|
|
320
|
+
"total_widgets": total_widgets,
|
|
321
|
+
"widget_types": widget_type_counts,
|
|
322
|
+
"categories": list(set(
|
|
323
|
+
category
|
|
324
|
+
for schema in self.plugin_schemas.values()
|
|
325
|
+
for category in schema.categories
|
|
326
|
+
))
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
# Global instance for easy access
|
|
331
|
+
_plugin_config_manager: Optional[PluginConfigManager] = None
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def get_plugin_config_manager(plugin_discovery: PluginDiscovery) -> PluginConfigManager:
|
|
335
|
+
"""Get or create the global plugin config manager instance.
|
|
336
|
+
|
|
337
|
+
Args:
|
|
338
|
+
plugin_discovery: Plugin discovery instance.
|
|
339
|
+
|
|
340
|
+
Returns:
|
|
341
|
+
PluginConfigManager instance.
|
|
342
|
+
"""
|
|
343
|
+
global _plugin_config_manager
|
|
344
|
+
if _plugin_config_manager is None:
|
|
345
|
+
_plugin_config_manager = PluginConfigManager(plugin_discovery)
|
|
346
|
+
return _plugin_config_manager
|