mgbam commited on
Commit
4179782
·
verified ·
1 Parent(s): 5b7a2a2

Create plugins.py

Browse files
Files changed (1) hide show
  1. plugins.py +115 -0
plugins.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from abc import ABC, abstractmethod
2
+ import importlib
3
+ import os
4
+ from typing import Dict, List, Type
5
+
6
+ # Base interface for all plugins
7
+ defined
8
+ class Plugin(ABC):
9
+ """
10
+ Base class for Shasha AI plugins.
11
+ """
12
+ name: str
13
+ description: str
14
+
15
+ @abstractmethod
16
+ def initialize(self, config: Dict) -> None:
17
+ """Perform any setup required by the plugin."""
18
+ pass
19
+
20
+ @abstractmethod
21
+ def execute(self, **kwargs) -> Dict:
22
+ """Run the plugin action and return a dict of results."""
23
+ pass
24
+
25
+
26
+ class PluginManager:
27
+ """
28
+ Manages discovery, registration, and invocation of plugins.
29
+ """
30
+ def __init__(self, plugins_dir: str = 'plugins'):
31
+ self.plugins_dir = plugins_dir
32
+ self._registry: Dict[str, Type[Plugin]] = {}
33
+ self._instances: Dict[str, Plugin] = {}
34
+
35
+ def discover(self) -> None:
36
+ """
37
+ Auto-import all modules in the plugins directory.
38
+ """
39
+ if not os.path.isdir(self.plugins_dir):
40
+ return
41
+ for filename in os.listdir(self.plugins_dir):
42
+ if not filename.endswith('.py') or filename.startswith('_'):
43
+ continue
44
+ module_name = filename[:-3]
45
+ module_path = f"{self.plugins_dir}.{module_name}"
46
+ try:
47
+ module = importlib.import_module(module_path)
48
+ for attr in dir(module):
49
+ obj = getattr(module, attr)
50
+ if isinstance(obj, type) and issubclass(obj, Plugin) and obj is not Plugin:
51
+ self.register(obj)
52
+ except Exception as e:
53
+ print(f"Failed to load plugin module {module_path}: {e}")
54
+
55
+ def register(self, plugin_cls: Type[Plugin]) -> None:
56
+ """
57
+ Register a plugin class by its .name attribute.
58
+ """
59
+ key = plugin_cls.name
60
+ self._registry[key] = plugin_cls
61
+
62
+ def initialize_all(self, config: Dict = None) -> None:
63
+ """
64
+ Instantiate and initialize all registered plugins.
65
+ """
66
+ for name, cls in self._registry.items():
67
+ try:
68
+ instance = cls()
69
+ instance.initialize(config or {})
70
+ self._instances[name] = instance
71
+ except Exception as e:
72
+ print(f"Failed to initialize plugin {name}: {e}")
73
+
74
+ def list_plugins(self) -> List[str]:
75
+ """
76
+ Return the list of registered plugin names.
77
+ """
78
+ return list(self._registry.keys())
79
+
80
+ def execute(self, name: str, **kwargs) -> Dict:
81
+ """
82
+ Execute a named plugin.
83
+ """
84
+ plugin = self._instances.get(name)
85
+ if not plugin:
86
+ raise ValueError(f"Plugin '{name}' is not initialized.")
87
+ return plugin.execute(**kwargs)
88
+
89
+
90
+ # Example plugin for VSCode snippets
91
+ class VSCodeSnippetPlugin(Plugin):
92
+ name = "vscode_snippets"
93
+ description = "Provides VSCode snippet generation and insertion into editor."
94
+
95
+ def initialize(self, config: Dict) -> None:
96
+ # e.g., set snippet directory from config
97
+ self.snippet_dir = config.get('snippet_dir', './snippets')
98
+
99
+ def execute(self, **kwargs) -> Dict:
100
+ # Generate or fetch a snippet
101
+ language = kwargs.get('language', 'python')
102
+ snippet_name = kwargs.get('snippet_name')
103
+ # Load snippet from disk or generate dynamically
104
+ path = os.path.join(self.snippet_dir, f"{language}.{snippet_name}.json")
105
+ if os.path.exists(path):
106
+ with open(path, 'r') as f:
107
+ content = f.read()
108
+ else:
109
+ content = '{ "prefix": "todo", "body": ["// add your snippet here"] }'
110
+ return { 'plugin': self.name, 'snippet': content }
111
+
112
+ # Initialize default manager for import
113
+ plugin_manager = PluginManager()
114
+ plugin_manager.discover()
115
+ plugin_manager.initialize_all()