janito 2.31.0__py3-none-any.whl → 2.32.0__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.
@@ -293,8 +293,6 @@ class ChatSession:
293
293
  print_token_message_summary(
294
294
  self.console, self.msg_count, usage, elapsed=elapsed
295
295
  )
296
- # Send terminal bell character to trigger TUI bell after printing token summary
297
- print("\a", end="", flush=True)
298
296
  if final_event and hasattr(final_event, "metadata"):
299
297
  exit_reason = (
300
298
  final_event.metadata.get("exit_reason")
@@ -4,10 +4,15 @@ CLI command to list available and loaded plugins.
4
4
 
5
5
  import argparse
6
6
  from typing import List, Dict, Any
7
- from janito.plugins.discovery import list_available_plugins, discover_plugins
7
+ from janito.plugins.discovery import list_available_plugins
8
8
  import os
9
9
  from janito.plugins.manager import PluginManager
10
10
  from janito.plugins.builtin import BuiltinPluginRegistry
11
+ from janito.plugins.auto_loader_fixed import load_core_plugins, get_loaded_core_plugins, is_core_plugin
12
+ from rich.console import Console
13
+ from rich.table import Table
14
+ from rich.panel import Panel
15
+ from rich.text import Text
11
16
 
12
17
 
13
18
  def handle_list_plugins(args: argparse.Namespace) -> None:
@@ -22,19 +27,49 @@ def handle_list_plugins(args: argparse.Namespace) -> None:
22
27
 
23
28
 
24
29
  def _list_available_plugins():
25
- """List available plugins."""
30
+ """List available plugins using rich formatting."""
31
+ console = Console()
26
32
  available = list_available_plugins()
27
33
  builtin_plugins = BuiltinPluginRegistry.list_builtin_plugins()
28
34
 
29
35
  if available or builtin_plugins:
30
- print("Available plugins:")
31
- _print_builtin_plugins(builtin_plugins)
32
- _print_external_plugins(available, builtin_plugins)
36
+ # Create main table
37
+ table = Table(title="Available Plugins")
38
+ table.add_column("Plugin Name", style="cyan", no_wrap=True)
39
+ table.add_column("Type", style="magenta")
40
+ table.add_column("Status", style="green")
41
+
42
+ # Add builtin plugins
43
+ for plugin in builtin_plugins:
44
+ table.add_row(plugin, "Builtin", "📦")
45
+
46
+ # Add external plugins
47
+ other_plugins = [p for p in available if p not in builtin_plugins]
48
+ for plugin in other_plugins:
49
+ table.add_row(plugin, "External", "🔌")
50
+
51
+ console.print(table)
52
+
53
+ # Show core plugins
54
+ from janito.plugins.core_loader_fixed import get_core_plugins
55
+ core_plugins = get_core_plugins()
56
+ core_table = Table(title="Core Plugins (Enabled by Default)")
57
+ core_table.add_column("Plugin Name", style="cyan", no_wrap=True)
58
+ core_table.add_column("Status", style="yellow")
59
+
60
+ for plugin in core_plugins:
61
+ core_table.add_row(plugin, "✅ Available")
62
+
63
+ console.print(core_table)
33
64
  else:
34
- print("No plugins found in search paths")
35
- print("Search paths:")
36
- print(f" - {os.getcwd()}/plugins")
37
- print(f" - {os.path.expanduser('~')}/.janito/plugins")
65
+ console.print(Panel(
66
+ "No plugins found in search paths\n"
67
+ f"[dim]Search paths:[/dim]\n"
68
+ f" {os.getcwd()}/plugins\n"
69
+ f" • {os.path.expanduser('~')}/.janito/plugins",
70
+ title="No Plugins Found",
71
+ style="yellow"
72
+ ))
38
73
 
39
74
 
40
75
  def _print_builtin_plugins(builtin_plugins):
@@ -55,18 +90,51 @@ def _print_external_plugins(available, builtin_plugins):
55
90
 
56
91
 
57
92
  def _list_plugin_resources():
58
- """List all resources from loaded plugins."""
59
- manager = PluginManager()
93
+ """List all resources from loaded plugins using rich formatting."""
94
+ from janito.plugins.auto_loader_fixed import get_plugin_manager
95
+
96
+ console = Console()
97
+ manager = get_plugin_manager()
60
98
  all_resources = manager.list_all_resources()
61
99
 
62
100
  if all_resources:
63
- print("Plugin Resources:")
64
101
  for plugin_name, resources in all_resources.items():
65
102
  metadata = manager.get_plugin_metadata(plugin_name)
66
- print(f"\n{plugin_name} v{metadata.version if metadata else 'unknown'}:")
67
- _print_resources_by_type(resources)
103
+ version = metadata.version if metadata else 'unknown'
104
+
105
+ # Create panel for each plugin
106
+ panel_content = []
107
+
108
+ tools = [r for r in resources if r["type"] == "tool"]
109
+ commands = [r for r in resources if r["type"] == "command"]
110
+ configs = [r for r in resources if r["type"] == "config"]
111
+
112
+ if tools:
113
+ panel_content.append("[bold blue]Tools:[/bold blue]")
114
+ for tool in tools:
115
+ panel_content.append(f" • {tool['name']}: {tool['description']}")
116
+
117
+ if commands:
118
+ panel_content.append("[bold green]Commands:[/bold green]")
119
+ for cmd in commands:
120
+ panel_content.append(f" • {cmd['name']}: {cmd['description']}")
121
+
122
+ if configs:
123
+ panel_content.append("[bold yellow]Configuration:[/bold yellow]")
124
+ for config in configs:
125
+ panel_content.append(f" • {config['name']}: {config['description']}")
126
+
127
+ console.print(Panel(
128
+ "\n".join(panel_content),
129
+ title=f"{plugin_name} v{version}",
130
+ style="cyan"
131
+ ))
68
132
  else:
69
- print("No plugins loaded")
133
+ console.print(Panel(
134
+ "No plugins are currently loaded.",
135
+ title="No Plugin Resources",
136
+ style="yellow"
137
+ ))
70
138
 
71
139
 
72
140
  def _print_resources_by_type(resources):
@@ -92,16 +160,59 @@ def _print_resources_by_type(resources):
92
160
 
93
161
 
94
162
  def _list_loaded_plugins():
95
- """List loaded plugins."""
96
- manager = PluginManager()
163
+ """List loaded plugins using rich formatting."""
164
+ from janito.plugins.auto_loader_fixed import get_plugin_manager
165
+
166
+ console = Console()
167
+ manager = get_plugin_manager()
97
168
  loaded = manager.list_plugins()
98
169
 
99
170
  if loaded:
100
- print("Loaded plugins:")
171
+ # Create main table
172
+ table = Table(title="Loaded Plugins")
173
+ table.add_column("Plugin Name", style="cyan", no_wrap=True)
174
+ table.add_column("Version", style="magenta")
175
+ table.add_column("Description", style="green", max_width=50)
176
+ table.add_column("Type", style="yellow")
177
+
178
+ core_plugins = []
179
+ other_plugins = []
180
+
101
181
  for plugin_name in loaded:
102
- _print_plugin_details(manager, plugin_name)
182
+ if is_core_plugin(plugin_name):
183
+ core_plugins.append(plugin_name)
184
+ else:
185
+ other_plugins.append(plugin_name)
186
+
187
+ # Add core plugins
188
+ for plugin_name in core_plugins:
189
+ metadata = manager.get_plugin_metadata(plugin_name)
190
+ if metadata:
191
+ table.add_row(
192
+ metadata.name,
193
+ metadata.version,
194
+ metadata.description,
195
+ "🔵 Core"
196
+ )
197
+
198
+ # Add other plugins
199
+ for plugin_name in other_plugins:
200
+ metadata = manager.get_plugin_metadata(plugin_name)
201
+ if metadata:
202
+ table.add_row(
203
+ metadata.name,
204
+ metadata.version,
205
+ metadata.description,
206
+ "🔶 External"
207
+ )
208
+
209
+ console.print(table)
103
210
  else:
104
- print("No plugins loaded")
211
+ console.print(Panel(
212
+ "No plugins are currently loaded.",
213
+ title="No Plugins Loaded",
214
+ style="yellow"
215
+ ))
105
216
 
106
217
 
107
218
  def _print_plugin_details(manager, plugin_name):
janito/cli/prompt_core.py CHANGED
@@ -216,8 +216,6 @@ class PromptHandler:
216
216
  if on_event and final_event is not None:
217
217
  on_event(final_event)
218
218
  global_event_bus.publish(final_event)
219
- # Terminal bell moved to token summary printing in session.py and handler.py
220
- pass # print('\a', end='', flush=True)
221
219
  except KeyboardInterrupt:
222
220
  # Capture user interrupt / cancellation
223
221
  self.console.print("[red]Interrupted by the user.[/red]")
@@ -161,7 +161,7 @@ class RichTerminalReporter(EventHandlerBase):
161
161
  self.console.print(msg)
162
162
  self.console.file.flush()
163
163
  elif subtype == ReportSubtype.STDOUT:
164
- self.console.print(Text(msg, style="on dark_green"))
164
+ self.console.print(msg)
165
165
  self.console.file.flush()
166
166
  elif subtype == ReportSubtype.STDERR:
167
167
  self.console.print(Text(msg, style="on red"))
@@ -125,8 +125,6 @@ class PromptHandler:
125
125
  print_token_message_summary(
126
126
  shared_console, msg_count=1, usage=usage, elapsed=elapsed
127
127
  )
128
- # Send terminal bell character to trigger TUI bell after printing token summary
129
- print("\a", end="", flush=True)
130
128
  self._cleanup_driver_and_console()
131
129
 
132
130
  def _cleanup_driver_and_console(self):
@@ -0,0 +1,91 @@
1
+ """
2
+ Auto-loader for core plugins.
3
+
4
+ This module automatically loads core plugins when the plugin system is initialized.
5
+ """
6
+
7
+ import os
8
+ from pathlib import Path
9
+ from typing import List
10
+ from janito.plugins.manager import PluginManager
11
+ from janito.plugins.discovery import list_available_plugins
12
+
13
+ # List of core plugins that should be enabled by default
14
+ CORE_PLUGINS = [
15
+ "core.filemanager",
16
+ "core.codeanalyzer",
17
+ "core.system",
18
+ "core.imagedisplay",
19
+ "dev.pythondev",
20
+ "dev.visualization",
21
+ "ui.userinterface",
22
+ "web.webtools",
23
+ ]
24
+
25
+
26
+ def load_core_plugins(pm: PluginManager = None) -> List[str]:
27
+ """
28
+ Load all core plugins.
29
+
30
+ Args:
31
+ pm: PluginManager instance. If None, creates a new one.
32
+
33
+ Returns:
34
+ List of successfully loaded plugin names
35
+ """
36
+ if pm is None:
37
+ pm = PluginManager()
38
+
39
+ # Ensure plugins directory is in search path
40
+ plugins_dir = Path.cwd() / "plugins"
41
+ if plugins_dir.exists():
42
+ pm.add_plugin_path(str(plugins_dir))
43
+
44
+ loaded = []
45
+
46
+ # Load core plugins
47
+ for plugin_name in CORE_PLUGINS:
48
+ try:
49
+ if pm.load_plugin(plugin_name):
50
+ loaded.append(plugin_name)
51
+ except Exception as e:
52
+ print(f"Warning: Failed to load core plugin {plugin_name}: {e}")
53
+
54
+ return loaded
55
+
56
+
57
+ def get_loaded_core_plugins() -> List[str]:
58
+ """
59
+ Get list of currently loaded core plugins.
60
+
61
+ Returns:
62
+ List of loaded core plugin names
63
+ """
64
+ pm = PluginManager()
65
+ loaded = pm.list_plugins()
66
+ return [p for p in loaded if p in CORE_PLUGINS]
67
+
68
+
69
+ def is_core_plugin(plugin_name: str) -> bool:
70
+ """
71
+ Check if a plugin is a core plugin.
72
+
73
+ Args:
74
+ plugin_name: Name of the plugin to check
75
+
76
+ Returns:
77
+ True if it's a core plugin
78
+ """
79
+ return plugin_name in CORE_PLUGINS
80
+
81
+
82
+ # Auto-load core plugins when module is imported
83
+ _plugin_manager = None
84
+
85
+ def get_plugin_manager() -> PluginManager:
86
+ """Get the global plugin manager with core plugins loaded."""
87
+ global _plugin_manager
88
+ if _plugin_manager is None:
89
+ _plugin_manager = PluginManager()
90
+ load_core_plugins(_plugin_manager)
91
+ return _plugin_manager
@@ -0,0 +1,90 @@
1
+ """
2
+ Fixed auto-loader for core plugins.
3
+
4
+ This module provides a working implementation to load core plugins
5
+ without the complex discovery mechanism.
6
+ """
7
+
8
+ import os
9
+ from pathlib import Path
10
+ from typing import List
11
+ from janito.plugins.manager import PluginManager
12
+ from janito.plugins.core_loader_fixed import load_core_plugin, get_core_plugins
13
+
14
+ # List of core plugins that should be enabled by default
15
+ CORE_PLUGINS = [
16
+ "core.filemanager",
17
+ "core.codeanalyzer",
18
+ "core.system",
19
+ "core.imagedisplay",
20
+ "dev.pythondev",
21
+ "dev.visualization",
22
+ "ui.userinterface",
23
+ "web.webtools",
24
+ ]
25
+
26
+
27
+ def load_core_plugins(pm: PluginManager = None) -> List[str]:
28
+ """
29
+ Load all core plugins.
30
+
31
+ Args:
32
+ pm: PluginManager instance. If None, creates a new one.
33
+
34
+ Returns:
35
+ List of successfully loaded plugin names
36
+ """
37
+ if pm is None:
38
+ pm = PluginManager()
39
+
40
+ loaded = []
41
+
42
+ # Load core plugins
43
+ for plugin_name in CORE_PLUGINS:
44
+ try:
45
+ plugin = load_core_plugin(plugin_name)
46
+ if plugin:
47
+ # Manually register the plugin
48
+ pm.plugins[plugin_name] = plugin
49
+ loaded.append(plugin_name)
50
+ except Exception as e:
51
+ print(f"Warning: Failed to load core plugin {plugin_name}: {e}")
52
+
53
+ return loaded
54
+
55
+
56
+ def get_loaded_core_plugins() -> List[str]:
57
+ """
58
+ Get list of currently loaded core plugins.
59
+
60
+ Returns:
61
+ List of loaded core plugin names
62
+ """
63
+ pm = PluginManager()
64
+ loaded = pm.list_plugins()
65
+ return [p for p in loaded if p in CORE_PLUGINS]
66
+
67
+
68
+ def is_core_plugin(plugin_name: str) -> bool:
69
+ """
70
+ Check if a plugin is a core plugin.
71
+
72
+ Args:
73
+ plugin_name: Name of the plugin to check
74
+
75
+ Returns:
76
+ True if it's a core plugin
77
+ """
78
+ return plugin_name in CORE_PLUGINS
79
+
80
+
81
+ # Auto-load core plugins when module is imported
82
+ _plugin_manager = None
83
+
84
+ def get_plugin_manager() -> PluginManager:
85
+ """Get the global plugin manager with core plugins loaded."""
86
+ global _plugin_manager
87
+ if _plugin_manager is None:
88
+ _plugin_manager = PluginManager()
89
+ load_core_plugins(_plugin_manager)
90
+ return _plugin_manager
@@ -0,0 +1,53 @@
1
+ """
2
+ Core plugin adapter for legacy plugin system.
3
+
4
+ This module provides proper Plugin class implementations for core plugins
5
+ that use the function-based approach instead of class-based.
6
+ """
7
+
8
+ from janito.plugins.base import Plugin, PluginMetadata
9
+ from typing import List, Type
10
+ from janito.tools.tool_base import ToolBase
11
+ from janito.tools.function_adapter import create_function_tool
12
+
13
+
14
+ class CorePluginAdapter(Plugin):
15
+ """Adapter for core plugins using function-based tools."""
16
+
17
+ def __init__(self, plugin_name: str, description: str, tools_module):
18
+ super().__init__()
19
+ self._plugin_name = plugin_name
20
+ self._description = description
21
+ self._tools_module = tools_module
22
+ self._tool_classes = []
23
+
24
+ # Set the metadata attribute that Plugin expects
25
+ self.metadata = self.get_metadata()
26
+
27
+ def get_metadata(self) -> PluginMetadata:
28
+ return PluginMetadata(
29
+ name=self._plugin_name,
30
+ version="1.0.0",
31
+ description=self._description,
32
+ author="Janito",
33
+ license="MIT",
34
+ )
35
+
36
+ def get_tools(self) -> List[Type[ToolBase]]:
37
+ return self._tool_classes
38
+
39
+ def initialize(self):
40
+ """Initialize the plugin by creating tool classes."""
41
+ # Get tools from the module
42
+ tools = getattr(self._tools_module, "__plugin_tools__", [])
43
+
44
+ self._tool_classes = []
45
+ for tool_func in tools:
46
+ if callable(tool_func):
47
+ tool_class = create_function_tool(tool_func)
48
+ self._tool_classes.append(tool_class)
49
+
50
+
51
+ def create_core_plugin(plugin_name: str, description: str, tools_module) -> CorePluginAdapter:
52
+ """Create a core plugin adapter."""
53
+ return CorePluginAdapter(plugin_name, description, tools_module)
@@ -0,0 +1,120 @@
1
+ """
2
+ Core plugin loader that properly handles function-based plugins.
3
+
4
+ This module provides a simplified approach to load core plugins
5
+ without the complex discovery mechanism.
6
+ """
7
+
8
+ import importlib.util
9
+ import sys
10
+ from pathlib import Path
11
+ from typing import Optional
12
+
13
+ from janito.plugins.base import Plugin, PluginMetadata
14
+ from janito.tools.function_adapter import create_function_tool
15
+ from janito.tools.tool_base import ToolBase
16
+
17
+
18
+ class CorePlugin(Plugin):
19
+ """Simple core plugin implementation."""
20
+
21
+ def __init__(self, name: str, description: str, tools: list):
22
+ super().__init__()
23
+ self._plugin_name = name
24
+ self._description = description
25
+ self._tools = tools
26
+ self._tool_classes = []
27
+
28
+ def get_metadata(self) -> PluginMetadata:
29
+ return PluginMetadata(
30
+ name=self._plugin_name,
31
+ version="1.0.0",
32
+ description=self._description,
33
+ author="Janito",
34
+ license="MIT",
35
+ )
36
+
37
+ def get_tools(self) -> list:
38
+ return self._tool_classes
39
+
40
+ def initialize(self):
41
+ """Initialize by creating tool classes."""
42
+ self._tool_classes = []
43
+ for tool_func in self._tools:
44
+ if callable(tool_func):
45
+ tool_class = create_function_tool(tool_func)
46
+ self._tool_classes.append(tool_class)
47
+
48
+
49
+ def load_core_plugin(plugin_name: str) -> Optional[Plugin]:
50
+ """
51
+ Load a core plugin by name.
52
+
53
+ Args:
54
+ plugin_name: Name of the plugin (e.g., 'core.filemanager')
55
+
56
+ Returns:
57
+ Plugin instance if loaded successfully
58
+ """
59
+ try:
60
+ # Parse plugin name
61
+ if "." not in plugin_name:
62
+ return None
63
+
64
+ parts = plugin_name.split(".")
65
+ if len(parts) != 2:
66
+ return None
67
+
68
+ package_name, submodule_name = parts
69
+
70
+ # Build path to plugin
71
+ plugin_path = Path("plugins") / package_name / submodule_name / "__init__.py"
72
+ if not plugin_path.exists():
73
+ return None
74
+
75
+ # Load the module
76
+ spec = importlib.util.spec_from_file_location(plugin_name, plugin_path)
77
+ if spec is None or spec.loader is None:
78
+ return None
79
+
80
+ module = importlib.util.module_from_spec(spec)
81
+ spec.loader.exec_module(module)
82
+
83
+ # Get plugin info
84
+ name = getattr(module, "__plugin_name__", plugin_name)
85
+ description = getattr(module, "__plugin_description__", f"Core plugin: {plugin_name}")
86
+ tools = getattr(module, "__plugin_tools__", [])
87
+
88
+ if not tools:
89
+ return None
90
+
91
+ # Create plugin
92
+ plugin = CorePlugin(name, description, tools)
93
+ plugin.initialize()
94
+ return plugin
95
+
96
+ except Exception as e:
97
+ print(f"Error loading core plugin {plugin_name}: {e}")
98
+ return None
99
+
100
+
101
+ def get_core_plugins() -> list:
102
+ """Get list of all available core plugins."""
103
+ core_plugins = [
104
+ "core.filemanager",
105
+ "core.codeanalyzer",
106
+ "core.system",
107
+ "core.imagedisplay",
108
+ "dev.pythondev",
109
+ "dev.visualization",
110
+ "ui.userinterface",
111
+ "web.webtools",
112
+ ]
113
+
114
+ available = []
115
+ for plugin_name in core_plugins:
116
+ plugin = load_core_plugin(plugin_name)
117
+ if plugin:
118
+ available.append(plugin_name)
119
+
120
+ return available