janito 3.2.0__py3-none-any.whl → 3.4.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.
- janito/README.md +0 -3
- janito/cli/chat_mode/bindings.py +0 -26
- janito/cli/chat_mode/session.py +1 -12
- janito/cli/chat_mode/shell/commands/security/allowed_sites.py +33 -47
- janito/cli/cli_commands/list_plugins.py +43 -52
- janito/cli/core/getters.py +0 -3
- janito/cli/core/model_guesser.py +24 -40
- janito/cli/main_cli.py +12 -9
- janito/cli/prompt_core.py +9 -20
- janito/drivers/openai/driver.py +0 -1
- janito/drivers/zai/driver.py +0 -1
- janito/hello.txt +0 -0
- janito/i18n/it.py +46 -46
- janito/llm/agent.py +16 -32
- janito/llm/auth_utils.py +5 -14
- janito/llm/driver.py +0 -8
- janito/plugins/__init__.py +12 -31
- janito/plugins/auto_loader.py +11 -12
- janito/plugins/auto_loader_fixed.py +11 -12
- janito/{plugin_system → plugins}/base.py +2 -5
- janito/plugins/builtin.py +1 -15
- janito/plugins/core_adapter.py +11 -89
- janito/plugins/core_loader.py +120 -0
- janito/plugins/core_loader_fixed.py +125 -0
- janito/plugins/discovery.py +5 -5
- janito/plugins/discovery_core.py +9 -14
- janito/plugins/manager.py +1 -1
- janito/providers/__init__.py +0 -1
- janito/tools/__init__.py +7 -31
- janito/tools/adapters/__init__.py +1 -6
- janito/tools/adapters/local/__init__.py +70 -7
- janito/{plugins/tools → tools/adapters/local}/ask_user.py +3 -3
- janito/{plugins/tools → tools/adapters/local}/create_file.py +6 -6
- janito/{plugins/tools → tools/adapters/local}/fetch_url.py +3 -3
- janito/{plugins/tools → tools/adapters/local}/replace_text_in_file.py +4 -4
- janito/{plugins/tools → tools/adapters/local}/show_image.py +6 -15
- janito/{plugins/core/imagedisplay/tools → tools/adapters/local}/show_image_grid.py +5 -13
- janito/tools/function_adapter.py +65 -0
- janito/tools/loop_protection_decorator.py +117 -114
- {janito-3.2.0.dist-info → janito-3.4.0.dist-info}/METADATA +2 -1
- {janito-3.2.0.dist-info → janito-3.4.0.dist-info}/RECORD +85 -156
- janito/cli/cli_commands/check_tools.py +0 -212
- janito/llm/cancellation_manager.py +0 -63
- janito/llm/enter_cancellation.py +0 -107
- janito/plugin_system/__init__.py +0 -10
- janito/plugin_system/core_loader.py +0 -217
- janito/plugin_system/core_loader_fixed.py +0 -225
- janito/plugins/core/__init__.py +0 -7
- janito/plugins/core/codeanalyzer/__init__.py +0 -43
- janito/plugins/core/filemanager/__init__.py +0 -124
- janito/plugins/core/filemanager/tools/create_file.py +0 -87
- janito/plugins/core/filemanager/tools/replace_text_in_file.py +0 -270
- janito/plugins/core/imagedisplay/__init__.py +0 -14
- janito/plugins/core/imagedisplay/plugin.py +0 -51
- janito/plugins/core/imagedisplay/tools/__init__.py +0 -1
- janito/plugins/core/imagedisplay/tools/show_image.py +0 -83
- janito/plugins/core/system/__init__.py +0 -23
- janito/plugins/dev/__init__.py +0 -7
- janito/plugins/dev/pythondev/__init__.py +0 -37
- janito/plugins/dev/visualization/__init__.py +0 -23
- janito/plugins/example_plugin.py +0 -108
- janito/plugins/tools/__init__.py +0 -10
- janito/plugins/tools/copy_file.py +0 -87
- janito/plugins/tools/core_tools_plugin.py +0 -87
- janito/plugins/tools/create_directory.py +0 -70
- janito/plugins/tools/decorators.py +0 -19
- janito/plugins/tools/delete_text_in_file.py +0 -134
- janito/plugins/tools/find_files.py +0 -143
- janito/plugins/tools/get_file_outline/__init__.py +0 -7
- janito/plugins/tools/get_file_outline/core.py +0 -122
- janito/plugins/tools/get_file_outline/java_outline.py +0 -47
- janito/plugins/tools/get_file_outline/markdown_outline.py +0 -14
- janito/plugins/tools/get_file_outline/python_outline.py +0 -303
- janito/plugins/tools/get_file_outline/search_outline.py +0 -36
- janito/plugins/tools/move_file.py +0 -131
- janito/plugins/tools/open_html_in_browser.py +0 -51
- janito/plugins/tools/open_url.py +0 -37
- janito/plugins/tools/python_code_run.py +0 -172
- janito/plugins/tools/python_command_run.py +0 -171
- janito/plugins/tools/python_file_run.py +0 -172
- janito/plugins/tools/read_chart.py +0 -259
- janito/plugins/tools/read_files.py +0 -58
- janito/plugins/tools/remove_directory.py +0 -55
- janito/plugins/tools/remove_file.py +0 -58
- janito/plugins/tools/run_bash_command.py +0 -183
- janito/plugins/tools/run_powershell_command.py +0 -218
- janito/plugins/tools/search_text/__init__.py +0 -7
- janito/plugins/tools/search_text/core.py +0 -205
- janito/plugins/tools/search_text/match_lines.py +0 -67
- janito/plugins/tools/search_text/pattern_utils.py +0 -73
- janito/plugins/tools/search_text/traverse_directory.py +0 -145
- janito/plugins/tools/show_image_grid.py +0 -85
- janito/plugins/tools/validate_file_syntax/__init__.py +0 -7
- janito/plugins/tools/validate_file_syntax/core.py +0 -114
- janito/plugins/tools/validate_file_syntax/css_validator.py +0 -35
- janito/plugins/tools/validate_file_syntax/html_validator.py +0 -100
- janito/plugins/tools/validate_file_syntax/jinja2_validator.py +0 -50
- janito/plugins/tools/validate_file_syntax/js_validator.py +0 -27
- janito/plugins/tools/validate_file_syntax/json_validator.py +0 -6
- janito/plugins/tools/validate_file_syntax/markdown_validator.py +0 -109
- janito/plugins/tools/validate_file_syntax/ps1_validator.py +0 -32
- janito/plugins/tools/validate_file_syntax/python_validator.py +0 -5
- janito/plugins/tools/validate_file_syntax/xml_validator.py +0 -11
- janito/plugins/tools/validate_file_syntax/yaml_validator.py +0 -6
- janito/plugins/tools/view_file.py +0 -172
- janito/plugins/ui/__init__.py +0 -7
- janito/plugins/ui/userinterface/__init__.py +0 -16
- janito/plugins/ui/userinterface/tools/ask_user.py +0 -110
- janito/plugins/web/__init__.py +0 -7
- janito/plugins/web/webtools/__init__.py +0 -33
- janito/plugins/web/webtools/tools/fetch_url.py +0 -458
- janito/providers/together/__init__.py +0 -1
- janito/providers/together/model_info.py +0 -69
- janito/providers/together/provider.py +0 -108
- janito/tools/cli_initializer.py +0 -88
- janito/tools/initialize.py +0 -70
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/copy_file.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/create_directory.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/delete_text_in_file.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/find_files.py +0 -0
- /janito/{plugins/core/codeanalyzer/tools → tools/adapters/local}/get_file_outline/__init__.py +0 -0
- /janito/{plugins/core/codeanalyzer/tools → tools/adapters/local}/get_file_outline/core.py +0 -0
- /janito/{plugins/core/codeanalyzer/tools → tools/adapters/local}/get_file_outline/java_outline.py +0 -0
- /janito/{plugins/core/codeanalyzer/tools → tools/adapters/local}/get_file_outline/markdown_outline.py +0 -0
- /janito/{plugins/core/codeanalyzer/tools → tools/adapters/local}/get_file_outline/python_outline.py +0 -0
- /janito/{plugins/core/codeanalyzer/tools → tools/adapters/local}/get_file_outline/search_outline.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/move_file.py +0 -0
- /janito/{plugins/web/webtools/tools → tools/adapters/local}/open_html_in_browser.py +0 -0
- /janito/{plugins/web/webtools/tools → tools/adapters/local}/open_url.py +0 -0
- /janito/{plugins/dev/pythondev/tools → tools/adapters/local}/python_code_run.py +0 -0
- /janito/{plugins/dev/pythondev/tools → tools/adapters/local}/python_command_run.py +0 -0
- /janito/{plugins/dev/pythondev/tools → tools/adapters/local}/python_file_run.py +0 -0
- /janito/{plugins/dev/visualization/tools → tools/adapters/local}/read_chart.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/read_files.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/remove_directory.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/remove_file.py +0 -0
- /janito/{plugins/core/system/tools → tools/adapters/local}/run_bash_command.py +0 -0
- /janito/{plugins/core/system/tools → tools/adapters/local}/run_powershell_command.py +0 -0
- /janito/{plugins/core/codeanalyzer/tools → tools/adapters/local}/search_text/__init__.py +0 -0
- /janito/{plugins/core/codeanalyzer/tools → tools/adapters/local}/search_text/core.py +0 -0
- /janito/{plugins/core/codeanalyzer/tools → tools/adapters/local}/search_text/match_lines.py +0 -0
- /janito/{plugins/core/codeanalyzer/tools → tools/adapters/local}/search_text/pattern_utils.py +0 -0
- /janito/{plugins/core/codeanalyzer/tools → tools/adapters/local}/search_text/traverse_directory.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/validate_file_syntax/__init__.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/validate_file_syntax/core.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/validate_file_syntax/css_validator.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/validate_file_syntax/html_validator.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/validate_file_syntax/jinja2_validator.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/validate_file_syntax/js_validator.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/validate_file_syntax/json_validator.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/validate_file_syntax/markdown_validator.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/validate_file_syntax/ps1_validator.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/validate_file_syntax/python_validator.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/validate_file_syntax/xml_validator.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/validate_file_syntax/yaml_validator.py +0 -0
- /janito/{plugins/core/filemanager/tools → tools/adapters/local}/view_file.py +0 -0
- {janito-3.2.0.dist-info → janito-3.4.0.dist-info}/WHEEL +0 -0
- {janito-3.2.0.dist-info → janito-3.4.0.dist-info}/entry_points.txt +0 -0
- {janito-3.2.0.dist-info → janito-3.4.0.dist-info}/licenses/LICENSE +0 -0
- {janito-3.2.0.dist-info → janito-3.4.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,125 @@
|
|
1
|
+
"""
|
2
|
+
Fixed core plugin loader.
|
3
|
+
|
4
|
+
This module provides a working implementation to load core plugins
|
5
|
+
by directly using the Plugin base class properly.
|
6
|
+
"""
|
7
|
+
|
8
|
+
import importlib.util
|
9
|
+
import sys
|
10
|
+
from pathlib import Path
|
11
|
+
from typing import Optional, List, Type
|
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
|
+
"""Working core plugin implementation."""
|
20
|
+
|
21
|
+
def __init__(self, name: str, description: str, tools: list):
|
22
|
+
self._plugin_name = name
|
23
|
+
self._description = description
|
24
|
+
self._tools = tools
|
25
|
+
self._tool_classes = []
|
26
|
+
super().__init__() # Call super after setting attributes
|
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[Type[ToolBase]]:
|
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
|
+
# Handle imagedisplay specially
|
71
|
+
if plugin_name == "core.imagedisplay":
|
72
|
+
# Import the actual plugin class
|
73
|
+
try:
|
74
|
+
from plugins.core.imagedisplay.plugin import ImageDisplayPlugin
|
75
|
+
return ImageDisplayPlugin()
|
76
|
+
except ImportError:
|
77
|
+
# If import fails, return None - don't return True
|
78
|
+
return None
|
79
|
+
|
80
|
+
# Build path to plugin
|
81
|
+
plugin_path = Path("plugins") / package_name / submodule_name / "__init__.py"
|
82
|
+
if not plugin_path.exists():
|
83
|
+
return None
|
84
|
+
|
85
|
+
# Load the module
|
86
|
+
spec = importlib.util.spec_from_file_location(plugin_name, plugin_path)
|
87
|
+
if spec is None or spec.loader is None:
|
88
|
+
return None
|
89
|
+
|
90
|
+
module = importlib.util.module_from_spec(spec)
|
91
|
+
spec.loader.exec_module(module)
|
92
|
+
|
93
|
+
# Get plugin info
|
94
|
+
name = getattr(module, "__plugin_name__", plugin_name)
|
95
|
+
description = getattr(module, "__plugin_description__", f"Core plugin: {plugin_name}")
|
96
|
+
tools = getattr(module, "__plugin_tools__", [])
|
97
|
+
|
98
|
+
if not tools:
|
99
|
+
return None
|
100
|
+
|
101
|
+
# Create plugin
|
102
|
+
plugin = CorePlugin(name, description, tools)
|
103
|
+
plugin.initialize()
|
104
|
+
return plugin
|
105
|
+
|
106
|
+
except Exception as e:
|
107
|
+
print(f"Error loading core plugin {plugin_name}: {e}")
|
108
|
+
return None
|
109
|
+
|
110
|
+
|
111
|
+
def get_core_plugins() -> list:
|
112
|
+
"""Get list of all available core plugins."""
|
113
|
+
core_plugins = [
|
114
|
+
"core.filemanager",
|
115
|
+
"core.codeanalyzer",
|
116
|
+
"core.system",
|
117
|
+
"core.imagedisplay",
|
118
|
+
"dev.pythondev",
|
119
|
+
"dev.visualization",
|
120
|
+
"ui.userinterface",
|
121
|
+
"web.webtools",
|
122
|
+
]
|
123
|
+
|
124
|
+
# All core plugins are always available
|
125
|
+
return core_plugins
|
janito/plugins/discovery.py
CHANGED
@@ -31,9 +31,9 @@ from pathlib import Path
|
|
31
31
|
from typing import Optional, List
|
32
32
|
import logging
|
33
33
|
|
34
|
-
from
|
34
|
+
from .base import Plugin
|
35
35
|
from .builtin import load_builtin_plugin, BuiltinPluginRegistry
|
36
|
-
from
|
36
|
+
from .core_loader import load_core_plugin
|
37
37
|
|
38
38
|
logger = logging.getLogger(__name__)
|
39
39
|
|
@@ -75,13 +75,13 @@ def discover_plugins(
|
|
75
75
|
parts = plugin_name.split(".")
|
76
76
|
if len(parts) == 2:
|
77
77
|
package_name, submodule_name = parts
|
78
|
-
|
78
|
+
|
79
79
|
# Handle core plugins with dedicated loader
|
80
80
|
if plugin_name.startswith(("core.", "dev.", "ui.", "web.")):
|
81
81
|
plugin = load_core_plugin(plugin_name)
|
82
82
|
if plugin:
|
83
83
|
return plugin
|
84
|
-
|
84
|
+
|
85
85
|
for base_path in all_paths:
|
86
86
|
package_path = base_path / package_name / submodule_name / "__init__.py"
|
87
87
|
if package_path.exists():
|
@@ -157,7 +157,7 @@ def _load_plugin_from_file(
|
|
157
157
|
|
158
158
|
# Check for package-based plugin with __plugin_name__ metadata
|
159
159
|
if hasattr(module, "__plugin_name__"):
|
160
|
-
from janito.
|
160
|
+
from janito.plugins.base import PluginMetadata
|
161
161
|
|
162
162
|
# Create a dynamic plugin class
|
163
163
|
class PackagePlugin(Plugin):
|
janito/plugins/discovery_core.py
CHANGED
@@ -17,11 +17,11 @@ from .core_adapter import CorePluginAdapter
|
|
17
17
|
def _load_core_plugin(package_path: Path, plugin_name: str) -> Optional[Plugin]:
|
18
18
|
"""
|
19
19
|
Load a core plugin from a package directory.
|
20
|
-
|
20
|
+
|
21
21
|
Args:
|
22
22
|
package_path: Path to the __init__.py file
|
23
23
|
plugin_name: Full plugin name (e.g., core.filemanager)
|
24
|
-
|
24
|
+
|
25
25
|
Returns:
|
26
26
|
Plugin instance if loaded successfully
|
27
27
|
"""
|
@@ -30,25 +30,20 @@ def _load_core_plugin(package_path: Path, plugin_name: str) -> Optional[Plugin]:
|
|
30
30
|
spec = importlib.util.spec_from_file_location(plugin_name, package_path)
|
31
31
|
if spec is None or spec.loader is None:
|
32
32
|
return None
|
33
|
-
|
33
|
+
|
34
34
|
module = importlib.util.module_from_spec(spec)
|
35
35
|
spec.loader.exec_module(module)
|
36
|
-
|
36
|
+
|
37
37
|
# Get plugin metadata
|
38
38
|
plugin_name_attr = getattr(module, "__plugin_name__", plugin_name)
|
39
|
-
description = getattr(
|
40
|
-
|
41
|
-
)
|
42
|
-
|
39
|
+
description = getattr(module, "__plugin_description__", f"Core plugin: {plugin_name}")
|
40
|
+
|
43
41
|
# Create and return the core plugin adapter
|
44
42
|
plugin = CorePluginAdapter(plugin_name_attr, description, module)
|
45
43
|
plugin.initialize() # Initialize to set up tools
|
46
44
|
return plugin
|
47
|
-
|
45
|
+
|
48
46
|
except Exception as e:
|
49
47
|
import logging
|
50
|
-
|
51
|
-
|
52
|
-
f"Failed to load core plugin {plugin_name}: {e}"
|
53
|
-
)
|
54
|
-
return None
|
48
|
+
logging.getLogger(__name__).error(f"Failed to load core plugin {plugin_name}: {e}")
|
49
|
+
return None
|
janito/plugins/manager.py
CHANGED
@@ -10,7 +10,7 @@ from pathlib import Path
|
|
10
10
|
from typing import Dict, List, Optional, Any
|
11
11
|
import logging
|
12
12
|
|
13
|
-
from
|
13
|
+
from .base import Plugin, PluginMetadata
|
14
14
|
from .discovery import discover_plugins
|
15
15
|
from .config import load_plugins_config, get_user_plugins_dir
|
16
16
|
from .builtin import BuiltinPluginRegistry, load_builtin_plugin
|
janito/providers/__init__.py
CHANGED
janito/tools/__init__.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
from janito.tools.adapters.local import
|
2
|
-
|
3
|
-
LocalToolsAdapter
|
1
|
+
from janito.tools.adapters.local import (
|
2
|
+
local_tools_adapter as _internal_local_tools_adapter,
|
3
|
+
LocalToolsAdapter,
|
4
4
|
)
|
5
5
|
|
6
6
|
|
@@ -11,10 +11,8 @@ def get_local_tools_adapter(workdir=None, allowed_permissions=None):
|
|
11
11
|
if workdir is not None and not os.path.exists(workdir):
|
12
12
|
os.makedirs(workdir, exist_ok=True)
|
13
13
|
# Permissions are now managed globally; ignore allowed_permissions argument except for backward compatibility
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
registry = initialize_tools(LocalToolsAdapter(workdir=workdir))
|
14
|
+
# Reuse the singleton adapter defined in janito.tools.adapters.local to maintain tool registrations
|
15
|
+
registry = _internal_local_tools_adapter
|
18
16
|
# Change workdir if requested
|
19
17
|
if workdir is not None:
|
20
18
|
try:
|
@@ -29,32 +27,10 @@ def get_local_tools_adapter(workdir=None, allowed_permissions=None):
|
|
29
27
|
return registry
|
30
28
|
|
31
29
|
|
32
|
-
|
33
|
-
local_tools_adapter = None
|
34
|
-
|
35
|
-
|
36
|
-
def get_local_tools_adapter(workdir=None, allowed_permissions=None):
|
37
|
-
"""Get the global tools adapter, initializing on first use."""
|
38
|
-
global local_tools_adapter
|
39
|
-
if local_tools_adapter is None:
|
40
|
-
from janito.tools.initialize import initialize_tools
|
41
|
-
|
42
|
-
adapter = LocalToolsAdapter(workdir=workdir)
|
43
|
-
local_tools_adapter = initialize_tools(adapter)
|
44
|
-
|
45
|
-
# Handle workdir if provided
|
46
|
-
if workdir is not None and local_tools_adapter is not None:
|
47
|
-
import os
|
48
|
-
|
49
|
-
if not os.path.exists(workdir):
|
50
|
-
os.makedirs(workdir, exist_ok=True)
|
51
|
-
os.chdir(workdir)
|
52
|
-
local_tools_adapter.workdir = workdir
|
53
|
-
|
54
|
-
return local_tools_adapter
|
55
|
-
|
30
|
+
local_tools_adapter = _internal_local_tools_adapter
|
56
31
|
|
57
32
|
__all__ = [
|
58
33
|
"LocalToolsAdapter",
|
59
34
|
"get_local_tools_adapter",
|
35
|
+
"local_tools_adapter",
|
60
36
|
]
|
@@ -1,6 +1 @@
|
|
1
|
-
|
2
|
-
Tools providers package: for plug-and-play tool collections, integrations, and adapters.
|
3
|
-
|
4
|
-
This package contains the core adapter infrastructure for managing tools,
|
5
|
-
while the actual tool implementations have been moved to the plugins system.
|
6
|
-
"""
|
1
|
+
# Tools providers package: for plug-and-play tool collections, integrations, and adapters.
|
@@ -1,10 +1,73 @@
|
|
1
|
-
|
2
|
-
Local tools adapter for janito.
|
1
|
+
from .adapter import LocalToolsAdapter
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
from .ask_user import AskUserTool
|
4
|
+
from .copy_file import CopyFileTool
|
5
|
+
from .create_directory import CreateDirectoryTool
|
6
|
+
from .create_file import CreateFileTool
|
7
|
+
from .fetch_url import FetchUrlTool
|
8
|
+
from .find_files import FindFilesTool
|
9
|
+
from .view_file import ViewFileTool
|
10
|
+
from .read_files import ReadFilesTool
|
11
|
+
from .move_file import MoveFileTool
|
12
|
+
from .open_url import OpenUrlTool
|
13
|
+
from .open_html_in_browser import OpenHtmlInBrowserTool
|
14
|
+
from .python_code_run import PythonCodeRunTool
|
15
|
+
from .python_command_run import PythonCommandRunTool
|
16
|
+
from .python_file_run import PythonFileRunTool
|
17
|
+
from .remove_directory import RemoveDirectoryTool
|
18
|
+
from .remove_file import RemoveFileTool
|
19
|
+
from .replace_text_in_file import ReplaceTextInFileTool
|
20
|
+
from .run_bash_command import RunBashCommandTool
|
21
|
+
from .run_powershell_command import RunPowershellCommandTool
|
22
|
+
from .get_file_outline.core import GetFileOutlineTool
|
23
|
+
from .get_file_outline.search_outline import SearchOutlineTool
|
24
|
+
from .search_text.core import SearchTextTool
|
25
|
+
from .validate_file_syntax.core import ValidateFileSyntaxTool
|
26
|
+
from .read_chart import ReadChartTool
|
27
|
+
from .show_image import ShowImageTool
|
28
|
+
from .show_image_grid import ShowImageGridTool
|
7
29
|
|
8
|
-
from .
|
30
|
+
from janito.tools.tool_base import ToolPermissions
|
31
|
+
import os
|
32
|
+
from janito.tools.permissions import get_global_allowed_permissions
|
33
|
+
|
34
|
+
# Singleton tools adapter with all standard tools registered
|
35
|
+
local_tools_adapter = LocalToolsAdapter(workdir=os.getcwd())
|
36
|
+
|
37
|
+
|
38
|
+
def get_local_tools_adapter(workdir=None):
|
39
|
+
return LocalToolsAdapter(workdir=workdir or os.getcwd())
|
40
|
+
|
41
|
+
|
42
|
+
# Register tools
|
43
|
+
for tool_class in [
|
44
|
+
AskUserTool,
|
45
|
+
CopyFileTool,
|
46
|
+
CreateDirectoryTool,
|
47
|
+
CreateFileTool,
|
48
|
+
FetchUrlTool,
|
49
|
+
FindFilesTool,
|
50
|
+
ViewFileTool,
|
51
|
+
ReadFilesTool,
|
52
|
+
MoveFileTool,
|
53
|
+
OpenUrlTool,
|
54
|
+
OpenHtmlInBrowserTool,
|
55
|
+
PythonCodeRunTool,
|
56
|
+
PythonCommandRunTool,
|
57
|
+
PythonFileRunTool,
|
58
|
+
RemoveDirectoryTool,
|
59
|
+
RemoveFileTool,
|
60
|
+
ReplaceTextInFileTool,
|
61
|
+
RunBashCommandTool,
|
62
|
+
RunPowershellCommandTool,
|
63
|
+
GetFileOutlineTool,
|
64
|
+
SearchOutlineTool,
|
65
|
+
SearchTextTool,
|
66
|
+
ValidateFileSyntaxTool,
|
67
|
+
ReadChartTool,
|
68
|
+
ShowImageTool,
|
69
|
+
ShowImageGridTool,
|
70
|
+
]:
|
71
|
+
local_tools_adapter.register_tool(tool_class)
|
9
72
|
|
10
|
-
|
73
|
+
# DEBUG: Print registered tools at startup
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from janito.tools.tool_base import ToolBase, ToolPermissions
|
2
|
-
from janito.
|
2
|
+
from janito.tools.adapters.local.adapter import register_local_tool
|
3
3
|
from janito.tools.loop_protection_decorator import protect_against_loops
|
4
4
|
|
5
5
|
from rich import print as rich_print
|
@@ -16,8 +16,8 @@ from prompt_toolkit.styles import Style
|
|
16
16
|
toolbar_style = Style.from_dict({"bottom-toolbar": "fg:yellow bg:darkred"})
|
17
17
|
|
18
18
|
|
19
|
-
@
|
20
|
-
class
|
19
|
+
@register_local_tool
|
20
|
+
class AskUserTool(ToolBase):
|
21
21
|
"""
|
22
22
|
Prompts the user for clarification or input with a question.
|
23
23
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import os
|
2
2
|
from janito.tools.path_utils import expand_path
|
3
|
-
from janito.
|
3
|
+
from janito.tools.adapters.local.adapter import register_local_tool
|
4
4
|
|
5
5
|
from janito.tools.tool_utils import display_path
|
6
6
|
from janito.tools.tool_base import ToolBase, ToolPermissions
|
@@ -8,11 +8,11 @@ from janito.report_events import ReportAction
|
|
8
8
|
from janito.i18n import tr
|
9
9
|
from janito.tools.loop_protection_decorator import protect_against_loops
|
10
10
|
|
11
|
-
from janito.
|
11
|
+
from janito.tools.adapters.local.validate_file_syntax.core import validate_file_syntax
|
12
12
|
|
13
13
|
|
14
|
-
@
|
15
|
-
class
|
14
|
+
@register_local_tool
|
15
|
+
class CreateFileTool(ToolBase):
|
16
16
|
"""
|
17
17
|
Create a new file with specified content at the given path.
|
18
18
|
|
@@ -55,7 +55,7 @@ class CreateFile(ToolBase):
|
|
55
55
|
or file exists (when overwrite=False).
|
56
56
|
|
57
57
|
Security Features:
|
58
|
-
- Loop protection:
|
58
|
+
- Loop protection: Maximum 5 calls per 10 seconds for the same file path
|
59
59
|
- Path traversal prevention: Validates and sanitizes file paths
|
60
60
|
- Permission checking: Respects file system permissions
|
61
61
|
- Atomic writes: Prevents partial file creation on errors
|
@@ -84,7 +84,7 @@ class CreateFile(ToolBase):
|
|
84
84
|
permissions = ToolPermissions(write=True)
|
85
85
|
tool_name = "create_file"
|
86
86
|
|
87
|
-
@protect_against_loops(max_calls=
|
87
|
+
@protect_against_loops(max_calls=5, time_window=10.0, key_field="path")
|
88
88
|
def run(self, path: str, content: str, overwrite: bool = False) -> str:
|
89
89
|
path = expand_path(path)
|
90
90
|
disp_path = display_path(path)
|
@@ -5,7 +5,7 @@ import json
|
|
5
5
|
from pathlib import Path
|
6
6
|
from bs4 import BeautifulSoup
|
7
7
|
from typing import Dict, Any, Optional
|
8
|
-
from janito.
|
8
|
+
from janito.tools.adapters.local.adapter import register_local_tool
|
9
9
|
from janito.tools.tool_base import ToolBase, ToolPermissions
|
10
10
|
from janito.report_events import ReportAction
|
11
11
|
from janito.i18n import tr
|
@@ -13,8 +13,8 @@ from janito.tools.tool_utils import pluralize
|
|
13
13
|
from janito.tools.loop_protection_decorator import protect_against_loops
|
14
14
|
|
15
15
|
|
16
|
-
@
|
17
|
-
class
|
16
|
+
@register_local_tool
|
17
|
+
class FetchUrlTool(ToolBase):
|
18
18
|
"""
|
19
19
|
Fetch the content of a web page and extract its text.
|
20
20
|
|
@@ -1,14 +1,14 @@
|
|
1
1
|
from janito.tools.tool_base import ToolBase, ToolPermissions
|
2
2
|
from janito.report_events import ReportAction
|
3
|
-
from janito.
|
3
|
+
from janito.tools.adapters.local.adapter import register_local_tool
|
4
4
|
from janito.i18n import tr
|
5
5
|
import shutil
|
6
6
|
import re
|
7
|
-
from janito.
|
7
|
+
from janito.tools.adapters.local.validate_file_syntax.core import validate_file_syntax
|
8
8
|
|
9
9
|
|
10
|
-
@
|
11
|
-
class
|
10
|
+
@register_local_tool
|
11
|
+
class ReplaceTextInFileTool(ToolBase):
|
12
12
|
"""
|
13
13
|
Replace exact occurrences of a given text in a file.
|
14
14
|
|
@@ -1,12 +1,12 @@
|
|
1
1
|
from janito.tools.tool_base import ToolBase, ToolPermissions
|
2
2
|
from janito.report_events import ReportAction
|
3
|
-
from janito.
|
3
|
+
from janito.tools.adapters.local.adapter import register_local_tool
|
4
4
|
from janito.i18n import tr
|
5
5
|
from janito.tools.loop_protection_decorator import protect_against_loops
|
6
6
|
|
7
7
|
|
8
|
-
@
|
9
|
-
class
|
8
|
+
@register_local_tool
|
9
|
+
class ShowImageTool(ToolBase):
|
10
10
|
"""Display an image inline in the terminal using the rich library.
|
11
11
|
|
12
12
|
Args:
|
@@ -44,9 +44,7 @@ class ShowImage(ToolBase):
|
|
44
44
|
|
45
45
|
path = expand_path(path)
|
46
46
|
disp_path = display_path(path)
|
47
|
-
self.report_action(
|
48
|
-
tr("🖼️ Show image '{disp_path}'", disp_path=disp_path), ReportAction.READ
|
49
|
-
)
|
47
|
+
self.report_action(tr("🖼️ Show image '{disp_path}'", disp_path=disp_path), ReportAction.READ)
|
50
48
|
|
51
49
|
if not os.path.exists(path):
|
52
50
|
msg = tr("❗ not found")
|
@@ -57,14 +55,9 @@ class ShowImage(ToolBase):
|
|
57
55
|
console = Console()
|
58
56
|
from rich.console import Console
|
59
57
|
from rich.text import Text
|
60
|
-
|
61
58
|
console = Console()
|
62
59
|
img = PILImage.open(path)
|
63
|
-
console.print(
|
64
|
-
Text(
|
65
|
-
f"Image: {disp_path} ({img.width}x{img.height})", style="bold green"
|
66
|
-
)
|
67
|
-
)
|
60
|
+
console.print(Text(f"Image: {disp_path} ({img.width}x{img.height})", style="bold green"))
|
68
61
|
console.print(img)
|
69
62
|
self.report_success(tr("✅ Displayed"))
|
70
63
|
details = []
|
@@ -75,9 +68,7 @@ class ShowImage(ToolBase):
|
|
75
68
|
if not preserve_aspect:
|
76
69
|
details.append("preserve_aspect=False")
|
77
70
|
info = ("; ".join(details)) if details else "auto-fit"
|
78
|
-
return tr(
|
79
|
-
"Image displayed: {disp_path} ({info})", disp_path=disp_path, info=info
|
80
|
-
)
|
71
|
+
return tr("Image displayed: {disp_path} ({info})", disp_path=disp_path, info=info)
|
81
72
|
except Exception as e:
|
82
73
|
self.report_error(tr(" ❌ Error: {error}", error=e))
|
83
74
|
return tr("Error displaying image: {error}", error=e)
|
@@ -1,10 +1,12 @@
|
|
1
1
|
from janito.tools.tool_base import ToolBase, ToolPermissions
|
2
2
|
from janito.report_events import ReportAction
|
3
|
+
from janito.tools.adapters.local.adapter import register_local_tool
|
3
4
|
from janito.i18n import tr
|
4
5
|
from janito.tools.loop_protection_decorator import protect_against_loops
|
5
6
|
from typing import Sequence
|
6
7
|
|
7
8
|
|
9
|
+
@register_local_tool
|
8
10
|
class ShowImageGridTool(ToolBase):
|
9
11
|
"""Display multiple images in a grid inline in the terminal using rich.
|
10
12
|
|
@@ -48,9 +50,7 @@ class ShowImageGridTool(ToolBase):
|
|
48
50
|
if not paths:
|
49
51
|
return tr("No images provided")
|
50
52
|
|
51
|
-
self.report_action(
|
52
|
-
tr("🖼️ Show image grid ({n} images)", n=len(paths)), ReportAction.READ
|
53
|
-
)
|
53
|
+
self.report_action(tr("🖼️ Show image grid ({n} images)", n=len(paths)), ReportAction.READ)
|
54
54
|
|
55
55
|
console = Console()
|
56
56
|
images = []
|
@@ -63,9 +63,7 @@ class ShowImageGridTool(ToolBase):
|
|
63
63
|
try:
|
64
64
|
img = PILImage.open(fp)
|
65
65
|
title = f"{display_path(fp)} ({img.width}x{img.height})"
|
66
|
-
images.append(
|
67
|
-
Panel.fit(title, title=display_path(fp), border_style="dim")
|
68
|
-
)
|
66
|
+
images.append(Panel.fit(title, title=display_path(fp), border_style="dim"))
|
69
67
|
shown += 1
|
70
68
|
except Exception as e:
|
71
69
|
self.report_warning(tr("⚠️ Skipped {p}: {e}", p=display_path(fp), e=e))
|
@@ -73,12 +71,6 @@ class ShowImageGridTool(ToolBase):
|
|
73
71
|
if not images:
|
74
72
|
return tr("No images could be displayed")
|
75
73
|
|
76
|
-
# Render in columns (grid-like)
|
77
74
|
console.print(Columns(images, equal=True, expand=True, columns=columns))
|
78
75
|
self.report_success(tr("✅ Displayed {n} images", n=shown))
|
79
|
-
return tr(
|
80
|
-
"Displayed {shown}/{total} images in a {cols}x? grid",
|
81
|
-
shown=shown,
|
82
|
-
total=len(paths),
|
83
|
-
cols=columns,
|
84
|
-
)
|
76
|
+
return tr("Displayed {shown}/{total} images in a {cols}x? grid", shown=shown, total=len(paths), cols=columns)
|
@@ -0,0 +1,65 @@
|
|
1
|
+
"""
|
2
|
+
Function-to-Tool adapter for core plugins.
|
3
|
+
|
4
|
+
This module provides a way to wrap function-based tools into proper ToolBase classes.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import inspect
|
8
|
+
from typing import Any, Dict, List, Optional, get_type_hints
|
9
|
+
from janito.tools.tool_base import ToolBase, ToolPermissions
|
10
|
+
|
11
|
+
|
12
|
+
class FunctionToolAdapter(ToolBase):
|
13
|
+
"""Adapter that wraps a function into a ToolBase class."""
|
14
|
+
|
15
|
+
def __init__(self, func, tool_name: str = None, description: str = None):
|
16
|
+
super().__init__()
|
17
|
+
self._func = func
|
18
|
+
self.tool_name = tool_name or func.__name__
|
19
|
+
self._description = description or func.__doc__ or f"Tool: {self.tool_name}"
|
20
|
+
self.permissions = ToolPermissions(read=True, write=True, execute=True)
|
21
|
+
|
22
|
+
def run(self, **kwargs) -> Any:
|
23
|
+
"""Execute the wrapped function."""
|
24
|
+
return self._func(**kwargs)
|
25
|
+
|
26
|
+
def get_signature(self) -> Dict[str, Any]:
|
27
|
+
"""Get function signature for documentation."""
|
28
|
+
sig = inspect.signature(self._func)
|
29
|
+
type_hints = get_type_hints(self._func)
|
30
|
+
|
31
|
+
params = {}
|
32
|
+
for name, param in sig.parameters.items():
|
33
|
+
param_info = {
|
34
|
+
"type": str(type_hints.get(name, Any)),
|
35
|
+
"default": param.default if param.default != inspect.Parameter.empty else None,
|
36
|
+
"required": param.default == inspect.Parameter.empty,
|
37
|
+
}
|
38
|
+
params[name] = param_info
|
39
|
+
|
40
|
+
return {
|
41
|
+
"name": self.tool_name,
|
42
|
+
"description": self._description,
|
43
|
+
"parameters": params,
|
44
|
+
"return_type": str(type_hints.get("return", Any))
|
45
|
+
}
|
46
|
+
|
47
|
+
|
48
|
+
def create_function_tool(func, tool_name: str = None, description: str = None) -> type:
|
49
|
+
"""
|
50
|
+
Create a ToolBase class from a function.
|
51
|
+
|
52
|
+
Args:
|
53
|
+
func: The function to wrap
|
54
|
+
tool_name: Optional custom tool name
|
55
|
+
description: Optional custom description
|
56
|
+
|
57
|
+
Returns:
|
58
|
+
A ToolBase subclass that wraps the function
|
59
|
+
"""
|
60
|
+
|
61
|
+
class DynamicFunctionTool(FunctionToolAdapter):
|
62
|
+
def __init__(self):
|
63
|
+
super().__init__(func, tool_name, description)
|
64
|
+
|
65
|
+
return DynamicFunctionTool
|