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
core/llm/plugin_sdk.py
ADDED
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
"""Plugin SDK for creating custom Kollabor plugins.
|
|
2
|
+
|
|
3
|
+
Provides a framework for creating custom plugins that integrate with
|
|
4
|
+
the LLM core service, separate from MCP tools.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import logging
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Any, Callable, Dict, List, Optional
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class KollaborPluginSDK:
|
|
16
|
+
"""SDK for creating and managing custom Kollabor plugins.
|
|
17
|
+
|
|
18
|
+
Provides tools for plugin creation, validation, and registration,
|
|
19
|
+
enabling developers to extend LLM functionality with custom tools.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
# Plugin template
|
|
23
|
+
PLUGIN_TEMPLATE = '''"""Custom Kollabor Plugin: {name}
|
|
24
|
+
|
|
25
|
+
{description}
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from typing import Any, Dict, List
|
|
29
|
+
from core.events import Event, EventType, Hook, HookPriority
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class {class_name}:
|
|
33
|
+
"""Custom plugin for {name}."""
|
|
34
|
+
|
|
35
|
+
@staticmethod
|
|
36
|
+
def get_default_config() -> Dict[str, Any]:
|
|
37
|
+
"""Get default configuration for this plugin."""
|
|
38
|
+
return {{
|
|
39
|
+
"plugins": {{
|
|
40
|
+
"{plugin_id}": {{
|
|
41
|
+
"enabled": True,
|
|
42
|
+
"show_status": True,
|
|
43
|
+
# Add your configuration options here
|
|
44
|
+
}}
|
|
45
|
+
}}
|
|
46
|
+
}}
|
|
47
|
+
|
|
48
|
+
def __init__(self, name: str, state_manager, event_bus, renderer, config):
|
|
49
|
+
"""Initialize the plugin."""
|
|
50
|
+
self.name = name
|
|
51
|
+
self.state_manager = state_manager
|
|
52
|
+
self.event_bus = event_bus
|
|
53
|
+
self.renderer = renderer
|
|
54
|
+
self.config = config
|
|
55
|
+
|
|
56
|
+
# Initialize your plugin state here
|
|
57
|
+
|
|
58
|
+
async def initialize(self):
|
|
59
|
+
"""Initialize plugin resources."""
|
|
60
|
+
# Setup any async resources here
|
|
61
|
+
pass
|
|
62
|
+
|
|
63
|
+
async def register_hooks(self):
|
|
64
|
+
"""Register plugin hooks with event bus."""
|
|
65
|
+
# Register your hooks here
|
|
66
|
+
# Example:
|
|
67
|
+
# hook = Hook(
|
|
68
|
+
# name="my_hook",
|
|
69
|
+
# plugin_name=self.name,
|
|
70
|
+
# event_type=EventType.USER_INPUT,
|
|
71
|
+
# priority=HookPriority.PREPROCESSING.value,
|
|
72
|
+
# callback=self._handle_input
|
|
73
|
+
# )
|
|
74
|
+
# await self.event_bus.register_hook(hook)
|
|
75
|
+
pass
|
|
76
|
+
|
|
77
|
+
def get_status_line(self) -> Dict[str, List[str]]:
|
|
78
|
+
"""Get status line for display."""
|
|
79
|
+
return {{
|
|
80
|
+
"A": [], # Area A status items
|
|
81
|
+
"B": [], # Area B status items
|
|
82
|
+
"C": [] # Area C status items
|
|
83
|
+
}}
|
|
84
|
+
|
|
85
|
+
async def shutdown(self):
|
|
86
|
+
"""Cleanup plugin resources."""
|
|
87
|
+
# Cleanup any resources here
|
|
88
|
+
pass
|
|
89
|
+
|
|
90
|
+
# Add your plugin methods here
|
|
91
|
+
async def process_command(self, command: str, params: Dict[str, Any]) -> Dict[str, Any]:
|
|
92
|
+
"""Process a custom command.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
command: Command to execute
|
|
96
|
+
params: Command parameters
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
Command result
|
|
100
|
+
"""
|
|
101
|
+
# Implement your command processing
|
|
102
|
+
return {{"status": "success", "message": "Command processed"}}
|
|
103
|
+
'''
|
|
104
|
+
|
|
105
|
+
def __init__(self):
|
|
106
|
+
"""Initialize the plugin SDK."""
|
|
107
|
+
self.registered_plugins = {}
|
|
108
|
+
self.custom_tools = {}
|
|
109
|
+
self.plugin_validators = []
|
|
110
|
+
|
|
111
|
+
# Plugin directory
|
|
112
|
+
self.plugins_dir = Path.cwd() / "plugins"
|
|
113
|
+
self.plugins_dir.mkdir(exist_ok=True)
|
|
114
|
+
|
|
115
|
+
logger.info("Kollabor Plugin SDK initialized")
|
|
116
|
+
|
|
117
|
+
def create_plugin_template(self, plugin_name: str,
|
|
118
|
+
description: str = "A custom Kollabor plugin",
|
|
119
|
+
output_dir: Optional[Path] = None) -> Path:
|
|
120
|
+
"""Generate a plugin template file.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
plugin_name: Name of the plugin
|
|
124
|
+
description: Plugin description
|
|
125
|
+
output_dir: Directory to save the plugin (defaults to plugins/)
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
Path to the created plugin file
|
|
129
|
+
"""
|
|
130
|
+
# Sanitize plugin name
|
|
131
|
+
plugin_id = plugin_name.lower().replace(" ", "_").replace("-", "_")
|
|
132
|
+
class_name = "".join(word.capitalize() for word in plugin_id.split("_")) + "Plugin"
|
|
133
|
+
|
|
134
|
+
# Generate plugin content
|
|
135
|
+
plugin_content = self.PLUGIN_TEMPLATE.format(
|
|
136
|
+
name=plugin_name,
|
|
137
|
+
description=description,
|
|
138
|
+
class_name=class_name,
|
|
139
|
+
plugin_id=plugin_id
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
# Determine output path
|
|
143
|
+
if output_dir is None:
|
|
144
|
+
output_dir = self.plugins_dir
|
|
145
|
+
output_path = output_dir / f"{plugin_id}_plugin.py"
|
|
146
|
+
|
|
147
|
+
# Write plugin file
|
|
148
|
+
with open(output_path, 'w') as f:
|
|
149
|
+
f.write(plugin_content)
|
|
150
|
+
|
|
151
|
+
logger.info(f"Created plugin template: {output_path}")
|
|
152
|
+
return output_path
|
|
153
|
+
|
|
154
|
+
def register_custom_tool(self, tool_definition: Dict[str, Any]) -> bool:
|
|
155
|
+
"""Register a custom tool for LLM use.
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
tool_definition: Tool definition including name, description, parameters
|
|
159
|
+
|
|
160
|
+
Returns:
|
|
161
|
+
True if registration successful
|
|
162
|
+
"""
|
|
163
|
+
required_fields = ["name", "description", "handler"]
|
|
164
|
+
if not all(field in tool_definition for field in required_fields):
|
|
165
|
+
logger.error(f"Tool definition missing required fields: {required_fields}")
|
|
166
|
+
return False
|
|
167
|
+
|
|
168
|
+
tool_name = tool_definition["name"]
|
|
169
|
+
|
|
170
|
+
# Validate handler is callable
|
|
171
|
+
if not callable(tool_definition["handler"]):
|
|
172
|
+
logger.error(f"Tool handler for '{tool_name}' is not callable")
|
|
173
|
+
return False
|
|
174
|
+
|
|
175
|
+
# Register the tool
|
|
176
|
+
self.custom_tools[tool_name] = {
|
|
177
|
+
"definition": tool_definition,
|
|
178
|
+
"enabled": tool_definition.get("enabled", True),
|
|
179
|
+
"plugin": tool_definition.get("plugin", "unknown")
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
logger.info(f"Registered custom tool: {tool_name}")
|
|
183
|
+
return True
|
|
184
|
+
|
|
185
|
+
async def execute_custom_tool(self, tool_name: str, params: Dict[str, Any]) -> Dict[str, Any]:
|
|
186
|
+
"""Execute a registered custom tool.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
tool_name: Name of the tool to execute
|
|
190
|
+
params: Tool parameters
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
Tool execution result
|
|
194
|
+
"""
|
|
195
|
+
if tool_name not in self.custom_tools:
|
|
196
|
+
return {
|
|
197
|
+
"error": f"Tool '{tool_name}' not found",
|
|
198
|
+
"available_tools": list(self.custom_tools.keys())
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
tool_info = self.custom_tools[tool_name]
|
|
202
|
+
if not tool_info["enabled"]:
|
|
203
|
+
return {"error": f"Tool '{tool_name}' is disabled"}
|
|
204
|
+
|
|
205
|
+
try:
|
|
206
|
+
handler = tool_info["definition"]["handler"]
|
|
207
|
+
|
|
208
|
+
# Execute handler (async or sync)
|
|
209
|
+
if asyncio.iscoroutinefunction(handler):
|
|
210
|
+
result = await handler(params)
|
|
211
|
+
else:
|
|
212
|
+
result = handler(params)
|
|
213
|
+
|
|
214
|
+
logger.info(f"Executed custom tool: {tool_name}")
|
|
215
|
+
return {"status": "success", "result": result}
|
|
216
|
+
|
|
217
|
+
except Exception as e:
|
|
218
|
+
logger.error(f"Failed to execute custom tool {tool_name}: {e}")
|
|
219
|
+
return {"error": str(e)}
|
|
220
|
+
|
|
221
|
+
def validate_plugin(self, plugin_path: str) -> Dict[str, Any]:
|
|
222
|
+
"""Validate a plugin structure and security.
|
|
223
|
+
|
|
224
|
+
Args:
|
|
225
|
+
plugin_path: Path to the plugin file
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
Validation result with any issues found
|
|
229
|
+
"""
|
|
230
|
+
validation_result = {
|
|
231
|
+
"valid": True,
|
|
232
|
+
"errors": [],
|
|
233
|
+
"warnings": [],
|
|
234
|
+
"info": []
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
plugin_file = Path(plugin_path)
|
|
238
|
+
|
|
239
|
+
# Check file exists
|
|
240
|
+
if not plugin_file.exists():
|
|
241
|
+
validation_result["valid"] = False
|
|
242
|
+
validation_result["errors"].append(f"Plugin file not found: {plugin_path}")
|
|
243
|
+
return validation_result
|
|
244
|
+
|
|
245
|
+
# Check file extension
|
|
246
|
+
if not plugin_file.suffix == ".py":
|
|
247
|
+
validation_result["valid"] = False
|
|
248
|
+
validation_result["errors"].append("Plugin must be a Python file (.py)")
|
|
249
|
+
return validation_result
|
|
250
|
+
|
|
251
|
+
try:
|
|
252
|
+
# Read plugin content
|
|
253
|
+
content = plugin_file.read_text()
|
|
254
|
+
|
|
255
|
+
# Check for required methods
|
|
256
|
+
required_methods = ["__init__", "get_default_config"]
|
|
257
|
+
for method in required_methods:
|
|
258
|
+
if f"def {method}" not in content:
|
|
259
|
+
validation_result["warnings"].append(f"Missing recommended method: {method}")
|
|
260
|
+
|
|
261
|
+
# Check for security issues
|
|
262
|
+
dangerous_imports = ["os.system", "subprocess.call", "eval", "exec", "__import__"]
|
|
263
|
+
for dangerous in dangerous_imports:
|
|
264
|
+
if dangerous in content:
|
|
265
|
+
validation_result["warnings"].append(f"Potentially dangerous code: {dangerous}")
|
|
266
|
+
|
|
267
|
+
# Check for proper class structure
|
|
268
|
+
if "class " not in content:
|
|
269
|
+
validation_result["errors"].append("No class definition found")
|
|
270
|
+
validation_result["valid"] = False
|
|
271
|
+
|
|
272
|
+
# Try to import and validate structure
|
|
273
|
+
try:
|
|
274
|
+
import importlib.util
|
|
275
|
+
spec = importlib.util.spec_from_file_location("temp_plugin", plugin_file)
|
|
276
|
+
if spec and spec.loader:
|
|
277
|
+
module = importlib.util.module_from_spec(spec)
|
|
278
|
+
spec.loader.exec_module(module)
|
|
279
|
+
|
|
280
|
+
# Find plugin class
|
|
281
|
+
plugin_class = None
|
|
282
|
+
for name in dir(module):
|
|
283
|
+
obj = getattr(module, name)
|
|
284
|
+
if isinstance(obj, type) and name.endswith("Plugin"):
|
|
285
|
+
plugin_class = obj
|
|
286
|
+
break
|
|
287
|
+
|
|
288
|
+
if plugin_class:
|
|
289
|
+
validation_result["info"].append(f"Found plugin class: {plugin_class.__name__}")
|
|
290
|
+
|
|
291
|
+
# Check for required methods
|
|
292
|
+
if hasattr(plugin_class, 'get_default_config'):
|
|
293
|
+
validation_result["info"].append("Has get_default_config method")
|
|
294
|
+
else:
|
|
295
|
+
validation_result["warnings"].append("No plugin class found (should end with 'Plugin')")
|
|
296
|
+
|
|
297
|
+
except Exception as e:
|
|
298
|
+
validation_result["errors"].append(f"Failed to import plugin: {e}")
|
|
299
|
+
validation_result["valid"] = False
|
|
300
|
+
|
|
301
|
+
except Exception as e:
|
|
302
|
+
validation_result["errors"].append(f"Failed to read plugin file: {e}")
|
|
303
|
+
validation_result["valid"] = False
|
|
304
|
+
|
|
305
|
+
# Run custom validators
|
|
306
|
+
for validator in self.plugin_validators:
|
|
307
|
+
try:
|
|
308
|
+
validator_result = validator(plugin_path)
|
|
309
|
+
if validator_result:
|
|
310
|
+
validation_result["warnings"].extend(validator_result.get("warnings", []))
|
|
311
|
+
validation_result["errors"].extend(validator_result.get("errors", []))
|
|
312
|
+
except Exception as e:
|
|
313
|
+
logger.warning(f"Custom validator failed: {e}")
|
|
314
|
+
|
|
315
|
+
return validation_result
|
|
316
|
+
|
|
317
|
+
def add_validator(self, validator: Callable) -> None:
|
|
318
|
+
"""Add a custom plugin validator.
|
|
319
|
+
|
|
320
|
+
Args:
|
|
321
|
+
validator: Validation function that takes plugin path and returns issues
|
|
322
|
+
"""
|
|
323
|
+
self.plugin_validators.append(validator)
|
|
324
|
+
logger.debug(f"Added custom plugin validator")
|
|
325
|
+
|
|
326
|
+
def list_custom_tools(self) -> List[Dict[str, Any]]:
|
|
327
|
+
"""List all registered custom tools.
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
List of custom tools with their information
|
|
331
|
+
"""
|
|
332
|
+
tools = []
|
|
333
|
+
for tool_name, tool_info in self.custom_tools.items():
|
|
334
|
+
tools.append({
|
|
335
|
+
"name": tool_name,
|
|
336
|
+
"description": tool_info["definition"].get("description", ""),
|
|
337
|
+
"enabled": tool_info["enabled"],
|
|
338
|
+
"plugin": tool_info["plugin"],
|
|
339
|
+
"parameters": tool_info["definition"].get("parameters", {})
|
|
340
|
+
})
|
|
341
|
+
return tools
|
|
342
|
+
|
|
343
|
+
def enable_tool(self, tool_name: str) -> bool:
|
|
344
|
+
"""Enable a custom tool.
|
|
345
|
+
|
|
346
|
+
Args:
|
|
347
|
+
tool_name: Name of the tool to enable
|
|
348
|
+
|
|
349
|
+
Returns:
|
|
350
|
+
True if tool was enabled
|
|
351
|
+
"""
|
|
352
|
+
if tool_name in self.custom_tools:
|
|
353
|
+
self.custom_tools[tool_name]["enabled"] = True
|
|
354
|
+
logger.info(f"Enabled custom tool: {tool_name}")
|
|
355
|
+
return True
|
|
356
|
+
return False
|
|
357
|
+
|
|
358
|
+
def disable_tool(self, tool_name: str) -> bool:
|
|
359
|
+
"""Disable a custom tool.
|
|
360
|
+
|
|
361
|
+
Args:
|
|
362
|
+
tool_name: Name of the tool to disable
|
|
363
|
+
|
|
364
|
+
Returns:
|
|
365
|
+
True if tool was disabled
|
|
366
|
+
"""
|
|
367
|
+
if tool_name in self.custom_tools:
|
|
368
|
+
self.custom_tools[tool_name]["enabled"] = False
|
|
369
|
+
logger.info(f"Disabled custom tool: {tool_name}")
|
|
370
|
+
return True
|
|
371
|
+
return False
|
|
372
|
+
|
|
373
|
+
def get_plugin_info(self, plugin_name: str) -> Optional[Dict[str, Any]]:
|
|
374
|
+
"""Get information about a registered plugin.
|
|
375
|
+
|
|
376
|
+
Args:
|
|
377
|
+
plugin_name: Name of the plugin
|
|
378
|
+
|
|
379
|
+
Returns:
|
|
380
|
+
Plugin information or None if not found
|
|
381
|
+
"""
|
|
382
|
+
return self.registered_plugins.get(plugin_name)
|
|
383
|
+
|
|
384
|
+
def register_plugin(self, plugin_name: str, plugin_info: Dict[str, Any]) -> bool:
|
|
385
|
+
"""Register a plugin with the SDK.
|
|
386
|
+
|
|
387
|
+
Args:
|
|
388
|
+
plugin_name: Name of the plugin
|
|
389
|
+
plugin_info: Plugin information
|
|
390
|
+
|
|
391
|
+
Returns:
|
|
392
|
+
True if registration successful
|
|
393
|
+
"""
|
|
394
|
+
self.registered_plugins[plugin_name] = plugin_info
|
|
395
|
+
logger.info(f"Registered plugin with SDK: {plugin_name}")
|
|
396
|
+
return True
|