janito 3.1.0__py3-none-any.whl → 3.3.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/cli/chat_mode/bindings.py +0 -26
- janito/cli/chat_mode/session.py +1 -7
- janito/cli/cli_commands/list_plugins.py +8 -13
- janito/cli/prompt_core.py +9 -19
- janito/llm/agent.py +17 -30
- janito/llm/driver.py +0 -7
- janito/plugins/__init__.py +21 -29
- janito/plugins/__main__.py +85 -0
- janito/plugins/base.py +57 -0
- janito/plugins/builtin.py +1 -1
- janito/plugins/core/filemanager/tools/copy_file.py +25 -1
- janito/plugins/core/filemanager/tools/create_directory.py +28 -1
- janito/plugins/core/filemanager/tools/create_file.py +25 -1
- janito/plugins/core/filemanager/tools/delete_text_in_file.py +1 -0
- janito/plugins/core/imagedisplay/plugin.py +1 -1
- janito/plugins/core_loader.py +144 -0
- janito/plugins/discovery.py +3 -3
- janito/plugins/example_plugin.py +1 -1
- janito/plugins/manager.py +1 -1
- janito/plugins_backup_20250825_070018/__init__.py +36 -0
- janito/plugins_backup_20250825_070018/builtin.py +102 -0
- janito/plugins_backup_20250825_070018/config.py +84 -0
- janito/plugins_backup_20250825_070018/core/__init__.py +7 -0
- janito/plugins_backup_20250825_070018/core/codeanalyzer/__init__.py +43 -0
- janito/plugins_backup_20250825_070018/core/codeanalyzer/tools/get_file_outline/__init__.py +1 -0
- janito/plugins_backup_20250825_070018/core/codeanalyzer/tools/get_file_outline/core.py +122 -0
- janito/plugins_backup_20250825_070018/core/codeanalyzer/tools/search_text/__init__.py +1 -0
- janito/plugins_backup_20250825_070018/core/codeanalyzer/tools/search_text/core.py +205 -0
- janito/plugins_backup_20250825_070018/core/filemanager/__init__.py +124 -0
- janito/plugins_backup_20250825_070018/core/filemanager/tools/copy_file.py +87 -0
- janito/plugins_backup_20250825_070018/core/filemanager/tools/create_directory.py +70 -0
- janito/plugins_backup_20250825_070018/core/filemanager/tools/create_file.py +87 -0
- janito/plugins_backup_20250825_070018/core/filemanager/tools/delete_text_in_file.py +135 -0
- janito/plugins_backup_20250825_070018/core/filemanager/tools/find_files.py +143 -0
- janito/plugins_backup_20250825_070018/core/filemanager/tools/move_file.py +131 -0
- janito/plugins_backup_20250825_070018/core/filemanager/tools/read_files.py +58 -0
- janito/plugins_backup_20250825_070018/core/filemanager/tools/remove_directory.py +55 -0
- janito/plugins_backup_20250825_070018/core/filemanager/tools/remove_file.py +58 -0
- janito/plugins_backup_20250825_070018/core/filemanager/tools/replace_text_in_file.py +270 -0
- janito/plugins_backup_20250825_070018/core/filemanager/tools/validate_file_syntax/__init__.py +1 -0
- janito/plugins_backup_20250825_070018/core/filemanager/tools/validate_file_syntax/core.py +114 -0
- janito/plugins_backup_20250825_070018/core/filemanager/tools/view_file.py +172 -0
- janito/plugins_backup_20250825_070018/core/imagedisplay/__init__.py +14 -0
- janito/plugins_backup_20250825_070018/core/imagedisplay/plugin.py +51 -0
- janito/plugins_backup_20250825_070018/core/imagedisplay/tools/__init__.py +1 -0
- janito/plugins_backup_20250825_070018/core/imagedisplay/tools/show_image.py +83 -0
- janito/plugins_backup_20250825_070018/core/imagedisplay/tools/show_image_grid.py +84 -0
- janito/plugins_backup_20250825_070018/core/system/__init__.py +23 -0
- janito/plugins_backup_20250825_070018/core/system/tools/run_bash_command.py +183 -0
- janito/plugins_backup_20250825_070018/core/system/tools/run_powershell_command.py +218 -0
- janito/plugins_backup_20250825_070018/dev/__init__.py +7 -0
- janito/plugins_backup_20250825_070018/dev/pythondev/__init__.py +37 -0
- janito/plugins_backup_20250825_070018/dev/pythondev/tools/python_code_run.py +172 -0
- janito/plugins_backup_20250825_070018/dev/pythondev/tools/python_command_run.py +171 -0
- janito/plugins_backup_20250825_070018/dev/pythondev/tools/python_file_run.py +172 -0
- janito/plugins_backup_20250825_070018/dev/visualization/__init__.py +23 -0
- janito/plugins_backup_20250825_070018/dev/visualization/tools/read_chart.py +259 -0
- janito/plugins_backup_20250825_070018/discovery.py +289 -0
- janito/plugins_backup_20250825_070018/example_plugin.py +108 -0
- janito/plugins_backup_20250825_070018/manager.py +243 -0
- janito/{plugins → plugins_backup_20250825_070018}/tools/delete_text_in_file.py +1 -0
- janito/plugins_backup_20250825_070018/tools/get_file_outline/java_outline.py +47 -0
- janito/plugins_backup_20250825_070018/tools/get_file_outline/markdown_outline.py +14 -0
- janito/plugins_backup_20250825_070018/tools/get_file_outline/python_outline.py +303 -0
- janito/plugins_backup_20250825_070018/tools/get_file_outline/search_outline.py +36 -0
- janito/plugins_backup_20250825_070018/tools/search_text/match_lines.py +67 -0
- janito/plugins_backup_20250825_070018/tools/search_text/pattern_utils.py +73 -0
- janito/plugins_backup_20250825_070018/tools/search_text/traverse_directory.py +145 -0
- janito/plugins_backup_20250825_070018/tools/validate_file_syntax/css_validator.py +35 -0
- janito/plugins_backup_20250825_070018/tools/validate_file_syntax/html_validator.py +100 -0
- janito/plugins_backup_20250825_070018/tools/validate_file_syntax/jinja2_validator.py +50 -0
- janito/plugins_backup_20250825_070018/tools/validate_file_syntax/js_validator.py +27 -0
- janito/plugins_backup_20250825_070018/tools/validate_file_syntax/json_validator.py +6 -0
- janito/plugins_backup_20250825_070018/tools/validate_file_syntax/markdown_validator.py +109 -0
- janito/plugins_backup_20250825_070018/tools/validate_file_syntax/ps1_validator.py +32 -0
- janito/plugins_backup_20250825_070018/tools/validate_file_syntax/python_validator.py +5 -0
- janito/plugins_backup_20250825_070018/tools/validate_file_syntax/xml_validator.py +11 -0
- janito/plugins_backup_20250825_070018/tools/validate_file_syntax/yaml_validator.py +6 -0
- janito/plugins_backup_20250825_070018/ui/__init__.py +7 -0
- janito/plugins_backup_20250825_070018/ui/userinterface/__init__.py +16 -0
- janito/plugins_backup_20250825_070018/ui/userinterface/tools/ask_user.py +110 -0
- janito/plugins_backup_20250825_070018/web/__init__.py +7 -0
- janito/plugins_backup_20250825_070018/web/webtools/__init__.py +33 -0
- janito/plugins_backup_20250825_070018/web/webtools/tools/fetch_url.py +458 -0
- janito/plugins_backup_20250825_070018/web/webtools/tools/open_html_in_browser.py +51 -0
- janito/plugins_backup_20250825_070018/web/webtools/tools/open_url.py +37 -0
- janito/tools/base.py +31 -1
- janito/tools/cli_initializer.py +1 -1
- janito/tools/function_adapter.py +35 -1
- janito/tools/initialize.py +1 -1
- janito/tools/tool_base.py +142 -114
- janito/tools/tools_schema.py +12 -6
- {janito-3.1.0.dist-info → janito-3.3.0.dist-info}/METADATA +1 -1
- {janito-3.1.0.dist-info → janito-3.3.0.dist-info}/RECORD +154 -87
- janito/llm/cancellation_manager.py +0 -62
- janito/llm/enter_cancellation.py +0 -93
- /janito/{plugin_system → plugin_system_backup_20250825_070018}/__init__.py +0 -0
- /janito/{plugin_system → plugin_system_backup_20250825_070018}/base.py +0 -0
- /janito/{plugin_system → plugin_system_backup_20250825_070018}/core_loader.py +0 -0
- /janito/{plugin_system → plugin_system_backup_20250825_070018}/core_loader_fixed.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/auto_loader.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/auto_loader_fixed.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018/core/codeanalyzer}/tools/get_file_outline/java_outline.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018/core/codeanalyzer}/tools/get_file_outline/markdown_outline.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018/core/codeanalyzer}/tools/get_file_outline/python_outline.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018/core/codeanalyzer}/tools/get_file_outline/search_outline.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018/core/codeanalyzer}/tools/search_text/match_lines.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018/core/codeanalyzer}/tools/search_text/pattern_utils.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018/core/codeanalyzer}/tools/search_text/traverse_directory.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/css_validator.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/html_validator.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/jinja2_validator.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/js_validator.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/json_validator.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/markdown_validator.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/ps1_validator.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/python_validator.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/xml_validator.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/yaml_validator.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/core_adapter.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/discovery_core.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/__init__.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/ask_user.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/copy_file.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/core_tools_plugin.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/create_directory.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/create_file.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/decorators.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/fetch_url.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/find_files.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/get_file_outline/__init__.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/get_file_outline/core.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/move_file.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/open_html_in_browser.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/open_url.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/python_code_run.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/python_command_run.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/python_file_run.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/read_chart.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/read_files.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/remove_directory.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/remove_file.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/replace_text_in_file.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/run_bash_command.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/run_powershell_command.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/search_text/__init__.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/search_text/core.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/show_image.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/show_image_grid.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/validate_file_syntax/__init__.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/validate_file_syntax/core.py +0 -0
- /janito/{plugins → plugins_backup_20250825_070018}/tools/view_file.py +0 -0
- {janito-3.1.0.dist-info → janito-3.3.0.dist-info}/WHEEL +0 -0
- {janito-3.1.0.dist-info → janito-3.3.0.dist-info}/entry_points.txt +0 -0
- {janito-3.1.0.dist-info → janito-3.3.0.dist-info}/licenses/LICENSE +0 -0
- {janito-3.1.0.dist-info → janito-3.3.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
import webbrowser
|
2
|
+
from janito.tools.adapters.local.adapter import register_local_tool
|
3
|
+
from janito.tools.tool_base import ToolBase, ToolPermissions
|
4
|
+
from janito.report_events import ReportAction
|
5
|
+
from janito.i18n import tr
|
6
|
+
from janito.tools.loop_protection_decorator import protect_against_loops
|
7
|
+
|
8
|
+
|
9
|
+
@register_local_tool
|
10
|
+
class OpenUrlTool(ToolBase):
|
11
|
+
"""
|
12
|
+
Open the supplied URL or local file in the default web browser.
|
13
|
+
|
14
|
+
Args:
|
15
|
+
url (str): The URL or local file path (as a file:// URL) to open. Supports both web URLs (http, https) and local files (file://).
|
16
|
+
Returns:
|
17
|
+
str: Status message indicating the result.
|
18
|
+
"""
|
19
|
+
|
20
|
+
permissions = ToolPermissions(read=True)
|
21
|
+
tool_name = "open_url"
|
22
|
+
|
23
|
+
@protect_against_loops(max_calls=5, time_window=10.0, key_field="url")
|
24
|
+
def run(self, url: str) -> str:
|
25
|
+
if not url.strip():
|
26
|
+
self.report_warning(tr("ℹ️ Empty URL provided."))
|
27
|
+
return tr("Warning: Empty URL provided. Operation skipped.")
|
28
|
+
self.report_action(tr("🌐 Opening URL '{url}' ...", url=url), ReportAction.READ)
|
29
|
+
try:
|
30
|
+
webbrowser.open(url)
|
31
|
+
except Exception as err:
|
32
|
+
self.report_error(
|
33
|
+
tr("❗ Error opening URL: {url}: {err}", url=url, err=str(err))
|
34
|
+
)
|
35
|
+
return tr("Warning: Error opening URL: {url}: {err}", url=url, err=str(err))
|
36
|
+
self.report_success(tr("✅ URL opened in browser: {url}", url=url))
|
37
|
+
return tr("URL opened in browser: {url}", url=url)
|
janito/tools/base.py
CHANGED
@@ -1,5 +1,35 @@
|
|
1
1
|
class BaseTool:
|
2
|
-
"""
|
2
|
+
"""
|
3
|
+
Base class for all tools.
|
4
|
+
|
5
|
+
Parameters:
|
6
|
+
path (str): Target file path for file operations
|
7
|
+
content (str): File content to write or process
|
8
|
+
overwrite (bool): Whether to overwrite existing files (default: False)
|
9
|
+
sources (str): Source file(s) to copy from
|
10
|
+
target (str): Destination path for copy operations
|
11
|
+
recursive (bool): Whether to process directories recursively
|
12
|
+
from_line (int): Starting line number for file reading
|
13
|
+
to_line (int): Ending line number for file reading
|
14
|
+
search_text (str): Text to search for in files
|
15
|
+
replacement_text (str): Text to replace search matches with
|
16
|
+
use_regex (bool): Whether to treat search as regex pattern
|
17
|
+
case_sensitive (bool): Whether search should be case sensitive
|
18
|
+
max_depth (int): Maximum directory depth to search
|
19
|
+
include_gitignored (bool): Whether to include .gitignored files
|
20
|
+
timeout (int): Timeout in seconds for operations
|
21
|
+
require_confirmation (bool): Whether to require user confirmation
|
22
|
+
data (dict): Chart data for visualization tools
|
23
|
+
title (str): Chart title
|
24
|
+
width (int): Chart width in pixels
|
25
|
+
height (int): Chart height in pixels
|
26
|
+
query (str): Search query for text search
|
27
|
+
paths (str): Directory or file paths to search in
|
28
|
+
src_path (str): Source path for move operations
|
29
|
+
dest_path (str): Destination path for move operations
|
30
|
+
code (str): Python code to execute
|
31
|
+
pattern (str): File pattern to match (e.g., '*.py')
|
32
|
+
"""
|
3
33
|
|
4
34
|
tool_name: str = ""
|
5
35
|
|
janito/tools/cli_initializer.py
CHANGED
@@ -17,7 +17,7 @@ def initialize_cli_tools():
|
|
17
17
|
"""Initialize tools for CLI usage, avoiding circular imports."""
|
18
18
|
try:
|
19
19
|
from janito.tools.adapters.local.adapter import LocalToolsAdapter
|
20
|
-
from janito.
|
20
|
+
from janito.plugins.core_loader import load_core_plugin
|
21
21
|
from janito.tools.permissions import set_global_allowed_permissions
|
22
22
|
from janito.tools.tool_base import ToolPermissions
|
23
23
|
|
janito/tools/function_adapter.py
CHANGED
@@ -10,7 +10,41 @@ from janito.tools.tool_base import ToolBase, ToolPermissions
|
|
10
10
|
|
11
11
|
|
12
12
|
class FunctionToolAdapter(ToolBase):
|
13
|
-
"""
|
13
|
+
"""
|
14
|
+
Adapter that wraps a function into a ToolBase class.
|
15
|
+
|
16
|
+
This adapter provides a unified interface for function-based tools by wrapping
|
17
|
+
individual functions with the ToolBase protocol. It handles parameter mapping
|
18
|
+
and validation automatically.
|
19
|
+
|
20
|
+
Parameters:
|
21
|
+
path (str): Target file path for file operations
|
22
|
+
content (str): File content to write or process
|
23
|
+
overwrite (bool): Whether to overwrite existing files (default: False)
|
24
|
+
sources (str): Source file(s) to copy from
|
25
|
+
target (str): Destination path for copy operations
|
26
|
+
recursive (bool): Whether to process directories recursively
|
27
|
+
from_line (int): Starting line number for file reading
|
28
|
+
to_line (int): Ending line number for file reading
|
29
|
+
search_text (str): Text to search for in files
|
30
|
+
replacement_text (str): Text to replace search matches with
|
31
|
+
use_regex (bool): Whether to treat search as regex pattern
|
32
|
+
case_sensitive (bool): Whether search should be case sensitive
|
33
|
+
max_depth (int): Maximum directory depth to search
|
34
|
+
include_gitignored (bool): Whether to include .gitignored files
|
35
|
+
timeout (int): Timeout in seconds for operations
|
36
|
+
require_confirmation (bool): Whether to require user confirmation
|
37
|
+
data (dict): Chart data for visualization tools
|
38
|
+
title (str): Chart title
|
39
|
+
width (int): Chart width in pixels
|
40
|
+
height (int): Chart height in pixels
|
41
|
+
query (str): Search query for text search
|
42
|
+
paths (str): Directory or file paths to search in
|
43
|
+
src_path (str): Source path for move operations
|
44
|
+
dest_path (str): Destination path for move operations
|
45
|
+
code (str): Python code to execute
|
46
|
+
pattern (str): File pattern to match (e.g., '*.py')
|
47
|
+
"""
|
14
48
|
|
15
49
|
def __init__(self, func, tool_name: str = None, description: str = None):
|
16
50
|
super().__init__()
|
janito/tools/initialize.py
CHANGED
@@ -9,7 +9,7 @@ import sys
|
|
9
9
|
from pathlib import Path
|
10
10
|
from typing import List, Optional
|
11
11
|
|
12
|
-
from janito.
|
12
|
+
from janito.plugins.core_loader import load_core_plugin
|
13
13
|
from janito.tools.adapters.local.adapter import LocalToolsAdapter
|
14
14
|
|
15
15
|
|
janito/tools/tool_base.py
CHANGED
@@ -1,114 +1,142 @@
|
|
1
|
-
from janito.report_events import ReportEvent, ReportSubtype, ReportAction
|
2
|
-
from janito.event_bus.bus import event_bus as default_event_bus
|
3
|
-
|
4
|
-
|
5
|
-
from collections import namedtuple
|
6
|
-
|
7
|
-
|
8
|
-
class ToolPermissions(namedtuple("ToolPermissions", ["read", "write", "execute"])):
|
9
|
-
__slots__ = ()
|
10
|
-
|
11
|
-
def __new__(cls, read=False, write=False, execute=False):
|
12
|
-
return super().__new__(cls, read, write, execute)
|
13
|
-
|
14
|
-
def __repr__(self):
|
15
|
-
return f"ToolPermissions(read={self.read}, write={self.write}, execute={self.execute})"
|
16
|
-
|
17
|
-
|
18
|
-
class ToolBase:
|
19
|
-
"""
|
20
|
-
Base class for all tools in the janito project.
|
21
|
-
Extend this class to implement specific tool functionality.
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
):
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
def
|
70
|
-
self._event_bus
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
1
|
+
from janito.report_events import ReportEvent, ReportSubtype, ReportAction
|
2
|
+
from janito.event_bus.bus import event_bus as default_event_bus
|
3
|
+
|
4
|
+
|
5
|
+
from collections import namedtuple
|
6
|
+
|
7
|
+
|
8
|
+
class ToolPermissions(namedtuple("ToolPermissions", ["read", "write", "execute"])):
|
9
|
+
__slots__ = ()
|
10
|
+
|
11
|
+
def __new__(cls, read=False, write=False, execute=False):
|
12
|
+
return super().__new__(cls, read, write, execute)
|
13
|
+
|
14
|
+
def __repr__(self):
|
15
|
+
return f"ToolPermissions(read={self.read}, write={self.write}, execute={self.execute})"
|
16
|
+
|
17
|
+
|
18
|
+
class ToolBase:
|
19
|
+
"""
|
20
|
+
Base class for all tools in the janito project.
|
21
|
+
Extend this class to implement specific tool functionality.
|
22
|
+
|
23
|
+
Parameters:
|
24
|
+
path (str): Target file path for file operations
|
25
|
+
content (str): File content to write or process
|
26
|
+
overwrite (bool): Whether to overwrite existing files (default: False)
|
27
|
+
sources (str): Source file(s) to copy from
|
28
|
+
target (str): Destination path for copy operations
|
29
|
+
recursive (bool): Whether to process directories recursively
|
30
|
+
from_line (int): Starting line number for file reading
|
31
|
+
to_line (int): Ending line number for file reading
|
32
|
+
search_text (str): Text to search for in files
|
33
|
+
replacement_text (str): Text to replace search matches with
|
34
|
+
use_regex (bool): Whether to treat search as regex pattern
|
35
|
+
case_sensitive (bool): Whether search should be case sensitive
|
36
|
+
max_depth (int): Maximum directory depth to search
|
37
|
+
include_gitignored (bool): Whether to include .gitignored files
|
38
|
+
timeout (int): Timeout in seconds for operations
|
39
|
+
require_confirmation (bool): Whether to require user confirmation
|
40
|
+
data (dict): Chart data for visualization tools
|
41
|
+
title (str): Chart title
|
42
|
+
width (int): Chart width in pixels
|
43
|
+
height (int): Chart height in pixels
|
44
|
+
query (str): Search query for text search
|
45
|
+
paths (str): Directory or file paths to search in
|
46
|
+
src_path (str): Source path for move operations
|
47
|
+
dest_path (str): Destination path for move operations
|
48
|
+
code (str): Python code to execute
|
49
|
+
pattern (str): File pattern to match (e.g., '*.py')
|
50
|
+
"""
|
51
|
+
|
52
|
+
permissions: "ToolPermissions" = None # Required: must be set by subclasses
|
53
|
+
|
54
|
+
def __init__(self, name=None, event_bus=None):
|
55
|
+
if self.permissions is None or not isinstance(
|
56
|
+
self.permissions, ToolPermissions
|
57
|
+
):
|
58
|
+
raise ValueError(
|
59
|
+
f"Tool '{self.__class__.__name__}' must define a 'permissions' attribute of type ToolPermissions."
|
60
|
+
)
|
61
|
+
self.name = name or self.__class__.__name__
|
62
|
+
self._event_bus = event_bus or default_event_bus
|
63
|
+
|
64
|
+
@property
|
65
|
+
def event_bus(self):
|
66
|
+
return self._event_bus
|
67
|
+
|
68
|
+
@event_bus.setter
|
69
|
+
def event_bus(self, bus):
|
70
|
+
self._event_bus = bus or default_event_bus
|
71
|
+
|
72
|
+
def report_action(self, message: str, action: ReportAction, context: dict = None):
|
73
|
+
"""
|
74
|
+
Report that a tool action is starting. This should be the first reporting call for every tool action.
|
75
|
+
"""
|
76
|
+
self._event_bus.publish(
|
77
|
+
ReportEvent(
|
78
|
+
subtype=ReportSubtype.ACTION_INFO,
|
79
|
+
message=" " + message,
|
80
|
+
action=action,
|
81
|
+
tool=self.name,
|
82
|
+
context=context,
|
83
|
+
)
|
84
|
+
)
|
85
|
+
|
86
|
+
def report_error(self, message: str, context: dict = None):
|
87
|
+
self._event_bus.publish(
|
88
|
+
ReportEvent(
|
89
|
+
subtype=ReportSubtype.ERROR,
|
90
|
+
message=message,
|
91
|
+
action=None,
|
92
|
+
tool=self.name,
|
93
|
+
context=context,
|
94
|
+
)
|
95
|
+
)
|
96
|
+
|
97
|
+
def report_success(self, message: str, context: dict = None):
|
98
|
+
self._event_bus.publish(
|
99
|
+
ReportEvent(
|
100
|
+
subtype=ReportSubtype.SUCCESS,
|
101
|
+
message=message,
|
102
|
+
action=None,
|
103
|
+
tool=self.name,
|
104
|
+
context=context,
|
105
|
+
)
|
106
|
+
)
|
107
|
+
|
108
|
+
def report_warning(self, message: str, context: dict = None):
|
109
|
+
self._event_bus.publish(
|
110
|
+
ReportEvent(
|
111
|
+
subtype=ReportSubtype.WARNING,
|
112
|
+
message=message,
|
113
|
+
action=None,
|
114
|
+
tool=self.name,
|
115
|
+
context=context,
|
116
|
+
)
|
117
|
+
)
|
118
|
+
|
119
|
+
def report_stdout(self, message: str, context: dict = None):
|
120
|
+
self._event_bus.publish(
|
121
|
+
ReportEvent(
|
122
|
+
subtype=ReportSubtype.STDOUT,
|
123
|
+
message=message,
|
124
|
+
action=None,
|
125
|
+
tool=self.name,
|
126
|
+
context=context,
|
127
|
+
)
|
128
|
+
)
|
129
|
+
|
130
|
+
def report_stderr(self, message: str, context: dict = None):
|
131
|
+
self._event_bus.publish(
|
132
|
+
ReportEvent(
|
133
|
+
subtype=ReportSubtype.STDERR,
|
134
|
+
message=message,
|
135
|
+
action=None,
|
136
|
+
tool=self.name,
|
137
|
+
context=context,
|
138
|
+
)
|
139
|
+
)
|
140
|
+
|
141
|
+
def run(self, *args, **kwargs):
|
142
|
+
raise NotImplementedError("Subclasses must implement the run method.")
|
janito/tools/tools_schema.py
CHANGED
@@ -7,6 +7,8 @@ class ToolSchemaBase:
|
|
7
7
|
def parse_param_section(self, lines, param_section_headers):
|
8
8
|
param_descs = {}
|
9
9
|
in_params = False
|
10
|
+
current_param = None
|
11
|
+
|
10
12
|
for line in lines:
|
11
13
|
stripped_line = line.strip()
|
12
14
|
if any(
|
@@ -16,17 +18,21 @@ class ToolSchemaBase:
|
|
16
18
|
in_params = True
|
17
19
|
continue
|
18
20
|
if in_params:
|
21
|
+
# Check for parameter definition: "param_name (type): description"
|
19
22
|
m = re.match(
|
20
|
-
r"([a-zA-Z_][a-zA-Z0-9_]*)\s*(?:\(
|
23
|
+
r"([a-zA-Z_][a-zA-Z0-9_]*)\s*(?:\([^)]+\))?\s*:\s*(.+)",
|
21
24
|
stripped_line,
|
22
25
|
)
|
23
26
|
if m:
|
24
|
-
param,
|
27
|
+
param, desc = m.groups()
|
25
28
|
param_descs[param] = desc.strip()
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
29
|
+
current_param = param
|
30
|
+
elif current_param and stripped_line and not (
|
31
|
+
stripped_line.lower().startswith("returns:") or
|
32
|
+
stripped_line.lower() == "returns"
|
33
|
+
):
|
34
|
+
# Continuation of current parameter description
|
35
|
+
param_descs[current_param] += " " + stripped_line.strip()
|
30
36
|
if (
|
31
37
|
stripped_line.lower().startswith("returns:")
|
32
38
|
or stripped_line.lower() == "returns"
|