janito 2.6.1__py3-none-any.whl → 2.8.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/__init__.py +6 -7
- janito/__main__.py +4 -5
- janito/_version.py +55 -58
- janito/agent/setup_agent.py +308 -241
- janito/agent/templates/profiles/{system_prompt_template_software developer.txt.j2 → system_prompt_template_Developer_with_Python_Tools.txt.j2} +43 -39
- janito/agent/templates/profiles/system_prompt_template_developer.txt.j2 +3 -12
- janito/cli/__init__.py +9 -10
- janito/cli/chat_mode/bindings.py +38 -38
- janito/cli/chat_mode/chat_entry.py +21 -23
- janito/cli/chat_mode/prompt_style.py +22 -25
- janito/cli/chat_mode/script_runner.py +158 -154
- janito/cli/chat_mode/session.py +80 -35
- janito/cli/chat_mode/session_profile_select.py +61 -52
- janito/cli/chat_mode/shell/commands/__init__.py +1 -5
- janito/cli/chat_mode/shell/commands/_priv_check.py +1 -0
- janito/cli/chat_mode/shell/commands/bang.py +10 -3
- janito/cli/chat_mode/shell/commands/conversation_restart.py +24 -7
- janito/cli/chat_mode/shell/commands/execute.py +22 -7
- janito/cli/chat_mode/shell/commands/help.py +4 -1
- janito/cli/chat_mode/shell/commands/model.py +13 -5
- janito/cli/chat_mode/shell/commands/privileges.py +21 -0
- janito/cli/chat_mode/shell/commands/prompt.py +0 -2
- janito/cli/chat_mode/shell/commands/read.py +22 -5
- janito/cli/chat_mode/shell/commands/tools.py +15 -4
- janito/cli/chat_mode/shell/commands/write.py +22 -5
- janito/cli/chat_mode/shell/input_history.py +3 -1
- janito/cli/chat_mode/shell/session/manager.py +0 -2
- janito/cli/chat_mode/toolbar.py +25 -19
- janito/cli/cli_commands/list_models.py +1 -1
- janito/cli/cli_commands/list_providers.py +1 -0
- janito/cli/cli_commands/list_tools.py +35 -7
- janito/cli/cli_commands/model_utils.py +5 -3
- janito/cli/cli_commands/show_config.py +12 -0
- janito/cli/cli_commands/show_system_prompt.py +23 -9
- janito/cli/config.py +0 -13
- janito/cli/core/getters.py +2 -0
- janito/cli/core/runner.py +25 -8
- janito/cli/core/setters.py +13 -76
- janito/cli/main_cli.py +9 -25
- janito/cli/prompt_core.py +19 -18
- janito/cli/prompt_setup.py +6 -3
- janito/cli/rich_terminal_reporter.py +19 -5
- janito/cli/single_shot_mode/handler.py +104 -95
- janito/cli/verbose_output.py +5 -1
- janito/config_manager.py +4 -0
- janito/drivers/azure_openai/driver.py +27 -30
- janito/drivers/driver_registry.py +27 -27
- janito/drivers/openai/driver.py +452 -436
- janito/formatting_token.py +12 -4
- janito/llm/agent.py +15 -6
- janito/llm/driver.py +1 -0
- janito/provider_registry.py +139 -178
- janito/providers/__init__.py +2 -0
- janito/providers/anthropic/model_info.py +40 -41
- janito/providers/anthropic/provider.py +75 -80
- janito/providers/azure_openai/provider.py +9 -4
- janito/providers/deepseek/provider.py +5 -4
- janito/providers/google/model_info.py +4 -2
- janito/providers/google/provider.py +11 -5
- janito/providers/groq/__init__.py +1 -0
- janito/providers/groq/model_info.py +46 -0
- janito/providers/groq/provider.py +76 -0
- janito/providers/moonshotai/__init__.py +1 -0
- janito/providers/moonshotai/model_info.py +15 -0
- janito/providers/moonshotai/provider.py +89 -0
- janito/providers/openai/provider.py +6 -7
- janito/tools/__init__.py +2 -0
- janito/tools/adapters/local/__init__.py +67 -66
- janito/tools/adapters/local/adapter.py +21 -4
- janito/tools/adapters/local/ask_user.py +1 -0
- janito/tools/adapters/local/copy_file.py +1 -0
- janito/tools/adapters/local/create_directory.py +1 -0
- janito/tools/adapters/local/create_file.py +1 -0
- janito/tools/adapters/local/delete_text_in_file.py +2 -1
- janito/tools/adapters/local/fetch_url.py +1 -0
- janito/tools/adapters/local/find_files.py +7 -6
- janito/tools/adapters/local/get_file_outline/core.py +1 -0
- janito/tools/adapters/local/get_file_outline/java_outline.py +22 -15
- janito/tools/adapters/local/get_file_outline/search_outline.py +1 -0
- janito/tools/adapters/local/move_file.py +4 -3
- janito/tools/adapters/local/open_html_in_browser.py +15 -5
- janito/tools/adapters/local/open_url.py +1 -0
- janito/tools/adapters/local/python_code_run.py +1 -0
- janito/tools/adapters/local/python_command_run.py +1 -0
- janito/tools/adapters/local/python_file_run.py +1 -0
- janito/tools/adapters/local/read_files.py +55 -40
- janito/tools/adapters/local/remove_directory.py +1 -0
- janito/tools/adapters/local/remove_file.py +1 -0
- janito/tools/adapters/local/replace_text_in_file.py +4 -3
- janito/tools/adapters/local/run_bash_command.py +1 -0
- janito/tools/adapters/local/run_powershell_command.py +1 -0
- janito/tools/adapters/local/search_text/core.py +18 -17
- janito/tools/adapters/local/search_text/match_lines.py +5 -5
- janito/tools/adapters/local/search_text/pattern_utils.py +1 -1
- janito/tools/adapters/local/search_text/traverse_directory.py +7 -7
- janito/tools/adapters/local/validate_file_syntax/core.py +1 -1
- janito/tools/adapters/local/validate_file_syntax/html_validator.py +8 -1
- janito/tools/disabled_tools.py +68 -0
- janito/tools/path_security.py +18 -11
- janito/tools/permissions.py +6 -0
- janito/tools/permissions_parse.py +4 -3
- janito/tools/tool_base.py +11 -5
- janito/tools/tool_use_tracker.py +1 -4
- janito/tools/tool_utils.py +1 -1
- janito/tools/tools_adapter.py +57 -25
- {janito-2.6.1.dist-info → janito-2.8.0.dist-info}/METADATA +411 -417
- janito-2.8.0.dist-info/RECORD +202 -0
- janito/cli/chat_mode/shell/commands/livelogs.py +0 -49
- janito/drivers/mistralai/driver.py +0 -41
- janito/providers/mistralai/model_info.py +0 -37
- janito/providers/mistralai/provider.py +0 -72
- janito/providers/provider_static_info.py +0 -18
- janito-2.6.1.dist-info/RECORD +0 -199
- /janito/agent/templates/profiles/{system_prompt_template_assistant.txt.j2 → system_prompt_template_model_conversation_without_tools_or_context.txt.j2} +0 -0
- {janito-2.6.1.dist-info → janito-2.8.0.dist-info}/WHEEL +0 -0
- {janito-2.6.1.dist-info → janito-2.8.0.dist-info}/entry_points.txt +0 -0
- {janito-2.6.1.dist-info → janito-2.8.0.dist-info}/licenses/LICENSE +0 -0
- {janito-2.6.1.dist-info → janito-2.8.0.dist-info}/top_level.txt +0 -0
@@ -1,66 +1,67 @@
|
|
1
|
-
from .adapter import LocalToolsAdapter
|
2
|
-
|
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
|
-
|
27
|
-
from janito.tools.tool_base import ToolPermissions
|
28
|
-
import os
|
29
|
-
from janito.tools.permissions import get_global_allowed_permissions
|
30
|
-
|
31
|
-
# Singleton tools adapter with all standard tools registered
|
32
|
-
local_tools_adapter = LocalToolsAdapter(workdir=os.getcwd())
|
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
|
-
|
1
|
+
from .adapter import LocalToolsAdapter
|
2
|
+
|
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
|
+
|
27
|
+
from janito.tools.tool_base import ToolPermissions
|
28
|
+
import os
|
29
|
+
from janito.tools.permissions import get_global_allowed_permissions
|
30
|
+
|
31
|
+
# Singleton tools adapter with all standard tools registered
|
32
|
+
local_tools_adapter = LocalToolsAdapter(workdir=os.getcwd())
|
33
|
+
|
34
|
+
|
35
|
+
def get_local_tools_adapter(workdir=None):
|
36
|
+
return LocalToolsAdapter(workdir=workdir or os.getcwd())
|
37
|
+
|
38
|
+
|
39
|
+
# Register tools
|
40
|
+
for tool_class in [
|
41
|
+
AskUserTool,
|
42
|
+
CopyFileTool,
|
43
|
+
CreateDirectoryTool,
|
44
|
+
CreateFileTool,
|
45
|
+
FetchUrlTool,
|
46
|
+
FindFilesTool,
|
47
|
+
ViewFileTool,
|
48
|
+
ReadFilesTool,
|
49
|
+
MoveFileTool,
|
50
|
+
OpenUrlTool,
|
51
|
+
OpenHtmlInBrowserTool,
|
52
|
+
PythonCodeRunTool,
|
53
|
+
PythonCommandRunTool,
|
54
|
+
PythonFileRunTool,
|
55
|
+
RemoveDirectoryTool,
|
56
|
+
RemoveFileTool,
|
57
|
+
ReplaceTextInFileTool,
|
58
|
+
RunBashCommandTool,
|
59
|
+
RunPowershellCommandTool,
|
60
|
+
GetFileOutlineTool,
|
61
|
+
SearchOutlineTool,
|
62
|
+
SearchTextTool,
|
63
|
+
ValidateFileSyntaxTool,
|
64
|
+
]:
|
65
|
+
local_tools_adapter.register_tool(tool_class)
|
66
|
+
|
67
|
+
# DEBUG: Print registered tools at startup
|
@@ -40,6 +40,7 @@ class LocalToolsAdapter(ToolsAdapter):
|
|
40
40
|
# to UI components even if the caller did not supply a custom bus.
|
41
41
|
if event_bus is None:
|
42
42
|
from janito.event_bus.bus import event_bus as global_event_bus
|
43
|
+
|
43
44
|
event_bus = global_event_bus
|
44
45
|
|
45
46
|
super().__init__(tools=tools, event_bus=event_bus)
|
@@ -48,6 +49,7 @@ class LocalToolsAdapter(ToolsAdapter):
|
|
48
49
|
self._tools: Dict[str, Dict[str, Any]] = {}
|
49
50
|
|
50
51
|
import os
|
52
|
+
|
51
53
|
self.workdir = workdir or os.getcwd()
|
52
54
|
# Ensure *some* workdir is set – fallback to CWD.
|
53
55
|
if not self.workdir:
|
@@ -93,27 +95,39 @@ class LocalToolsAdapter(ToolsAdapter):
|
|
93
95
|
# Lookup helpers used by ToolsAdapterBase
|
94
96
|
# ------------------------------------------------------------------
|
95
97
|
def get_tool(self, name: str):
|
96
|
-
|
98
|
+
from janito.tools.disabled_tools import is_tool_disabled
|
99
|
+
|
100
|
+
if name in self._tools and not is_tool_disabled(name):
|
101
|
+
return self._tools[name]["instance"]
|
102
|
+
return None
|
97
103
|
|
98
104
|
def list_tools(self):
|
105
|
+
from janito.tools.disabled_tools import is_tool_disabled
|
106
|
+
|
99
107
|
return [
|
100
108
|
name
|
101
109
|
for name, entry in self._tools.items()
|
102
|
-
if self.is_tool_allowed(entry["instance"])
|
110
|
+
if self.is_tool_allowed(entry["instance"]) and not is_tool_disabled(name)
|
103
111
|
]
|
104
112
|
|
105
113
|
def get_tool_classes(self):
|
114
|
+
from janito.tools.disabled_tools import is_tool_disabled
|
115
|
+
|
106
116
|
return [
|
107
117
|
entry["class"]
|
108
118
|
for entry in self._tools.values()
|
109
119
|
if self.is_tool_allowed(entry["instance"])
|
120
|
+
and not is_tool_disabled(entry["instance"].tool_name)
|
110
121
|
]
|
111
122
|
|
112
123
|
def get_tools(self):
|
124
|
+
from janito.tools.disabled_tools import is_tool_disabled
|
125
|
+
|
113
126
|
return [
|
114
127
|
entry["instance"]
|
115
128
|
for entry in self._tools.values()
|
116
129
|
if self.is_tool_allowed(entry["instance"])
|
130
|
+
and not is_tool_disabled(entry["instance"].tool_name)
|
117
131
|
]
|
118
132
|
|
119
133
|
# ------------------------------------------------------------------
|
@@ -125,7 +139,9 @@ class LocalToolsAdapter(ToolsAdapter):
|
|
125
139
|
raise TypeError(f"Tool '{tool}' must implement a callable 'run' method.")
|
126
140
|
tool_name = getattr(tool, "tool_name", None)
|
127
141
|
if not tool_name or not isinstance(tool_name, str):
|
128
|
-
raise ValueError(
|
142
|
+
raise ValueError(
|
143
|
+
f"Tool '{tool}' must provide a 'tool_name' (str) attribute."
|
144
|
+
)
|
129
145
|
if tool_name in self._tools:
|
130
146
|
raise ValueError(f"Tool '{tool_name}' is already registered.")
|
131
147
|
self._tools[tool_name] = {
|
@@ -139,6 +155,7 @@ class LocalToolsAdapter(ToolsAdapter):
|
|
139
155
|
# Decorator helper for quick registration of local tools
|
140
156
|
# -------------------------------------------------------------------------
|
141
157
|
|
158
|
+
|
142
159
|
def register_local_tool(tool=None):
|
143
160
|
"""Class decorator that registers the tool on the *singleton* adapter.
|
144
161
|
|
@@ -150,7 +167,7 @@ def register_local_tool(tool=None):
|
|
150
167
|
"""
|
151
168
|
|
152
169
|
def decorator(cls):
|
153
|
-
|
170
|
+
# Register the tool on a *fresh* adapter instance to avoid circular
|
154
171
|
# import issues during package initialisation. This keeps behaviour
|
155
172
|
# identical to the original implementation while still allowing
|
156
173
|
# immediate use via the singleton in janito.tools.adapters.local.
|
@@ -19,6 +19,7 @@ class DeleteTextInFileTool(ToolBase):
|
|
19
19
|
Returns:
|
20
20
|
str: Status message indicating the result.
|
21
21
|
"""
|
22
|
+
|
22
23
|
permissions = ToolPermissions(read=True, write=True)
|
23
24
|
tool_name = "delete_text_in_file"
|
24
25
|
|
@@ -62,7 +63,7 @@ class DeleteTextInFileTool(ToolBase):
|
|
62
63
|
return tr(
|
63
64
|
"Deleted {count} block(s) between markers in {path}. ",
|
64
65
|
count=deleted_blocks,
|
65
|
-
path=path
|
66
|
+
path=path,
|
66
67
|
) + (f"\n{validation_result}" if validation_result else "")
|
67
68
|
except Exception as e:
|
68
69
|
self.report_error(tr(" ❌ Error: {error}", error=e), ReportAction.REPLACE)
|
@@ -61,7 +61,9 @@ class FindFilesTool(ToolBase):
|
|
61
61
|
break
|
62
62
|
return dir_output
|
63
63
|
|
64
|
-
def _handle_directory_path(
|
64
|
+
def _handle_directory_path(
|
65
|
+
self, directory, patterns, max_depth, include_gitignored
|
66
|
+
):
|
65
67
|
dir_output = set()
|
66
68
|
for root, dirs, files in walk_dir_with_gitignore(
|
67
69
|
directory,
|
@@ -73,9 +75,7 @@ class FindFilesTool(ToolBase):
|
|
73
75
|
dir_output.update(self._match_directories(root, dirs, pat))
|
74
76
|
else:
|
75
77
|
dir_output.update(self._match_files(root, files, pat))
|
76
|
-
dir_output.update(
|
77
|
-
self._match_dirs_without_slash(root, dirs, pat)
|
78
|
-
)
|
78
|
+
dir_output.update(self._match_dirs_without_slash(root, dirs, pat))
|
79
79
|
return dir_output
|
80
80
|
|
81
81
|
def _report_search(self, pattern, disp_path, depth_msg):
|
@@ -131,9 +131,10 @@ class FindFilesTool(ToolBase):
|
|
131
131
|
if os.path.isfile(directory):
|
132
132
|
dir_output = self._handle_path(directory, patterns)
|
133
133
|
elif os.path.isdir(directory):
|
134
|
-
dir_output = self._handle_directory_path(
|
134
|
+
dir_output = self._handle_directory_path(
|
135
|
+
directory, patterns, max_depth, include_gitignored
|
136
|
+
)
|
135
137
|
self._report_success(len(dir_output))
|
136
138
|
results.extend(self._format_output(directory, dir_output))
|
137
139
|
result = "\n".join(results)
|
138
140
|
return result
|
139
|
-
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import re
|
2
2
|
from typing import List, Dict
|
3
3
|
|
4
|
+
|
4
5
|
def parse_java_outline(lines: List[str]) -> List[Dict]:
|
5
6
|
"""
|
6
7
|
Parses Java source code lines and extracts classes and methods with their signatures.
|
@@ -9,19 +10,23 @@ def parse_java_outline(lines: List[str]) -> List[Dict]:
|
|
9
10
|
outline = []
|
10
11
|
class_pattern = re.compile(r"\bclass\s+(\w+)(\s*<[^>]+>)?")
|
11
12
|
# Match methods with or without visibility modifiers (including package-private)
|
12
|
-
method_pattern = re.compile(
|
13
|
+
method_pattern = re.compile(
|
14
|
+
r"^(?:\s*(public|protected|private)\s+)?(?:static\s+)?([\w<>\[\]]+)\s+(\w+)\s*\(([^)]*)\)"
|
15
|
+
)
|
13
16
|
current_class = None
|
14
17
|
for idx, line in enumerate(lines, 1):
|
15
18
|
class_match = class_pattern.search(line)
|
16
19
|
if class_match:
|
17
20
|
class_name = class_match.group(1)
|
18
21
|
generics = class_match.group(2) or ""
|
19
|
-
outline.append(
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
outline.append(
|
23
|
+
{
|
24
|
+
"type": "class",
|
25
|
+
"name": class_name,
|
26
|
+
"generics": generics.strip("<>") if generics else None,
|
27
|
+
"line": idx,
|
28
|
+
}
|
29
|
+
)
|
25
30
|
current_class = class_name
|
26
31
|
else:
|
27
32
|
method_match = method_pattern.search(line)
|
@@ -29,12 +34,14 @@ def parse_java_outline(lines: List[str]) -> List[Dict]:
|
|
29
34
|
return_type = method_match.group(2)
|
30
35
|
method_name = method_match.group(3)
|
31
36
|
params = method_match.group(4)
|
32
|
-
outline.append(
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
outline.append(
|
38
|
+
{
|
39
|
+
"type": "method",
|
40
|
+
"class": current_class,
|
41
|
+
"name": method_name,
|
42
|
+
"return_type": return_type,
|
43
|
+
"parameters": params.strip(),
|
44
|
+
"line": idx,
|
45
|
+
}
|
46
|
+
)
|
40
47
|
return outline
|
@@ -20,6 +20,7 @@ class MoveFileTool(ToolBase):
|
|
20
20
|
Returns:
|
21
21
|
str: Status message indicating the result.
|
22
22
|
"""
|
23
|
+
|
23
24
|
permissions = ToolPermissions(read=True, write=True)
|
24
25
|
tool_name = "move_file"
|
25
26
|
|
@@ -55,7 +56,7 @@ class MoveFileTool(ToolBase):
|
|
55
56
|
disp_src=disp_src,
|
56
57
|
disp_dest=disp_dest,
|
57
58
|
),
|
58
|
-
ReportAction.
|
59
|
+
ReportAction.UPDATE,
|
59
60
|
)
|
60
61
|
shutil.move(src, dest)
|
61
62
|
self.report_success(tr("✅ Move complete."))
|
@@ -106,7 +107,7 @@ class MoveFileTool(ToolBase):
|
|
106
107
|
"❗ Destination '{disp_dest}' exists and overwrite is False.",
|
107
108
|
disp_dest=disp_dest,
|
108
109
|
),
|
109
|
-
ReportAction.
|
110
|
+
ReportAction.UPDATE,
|
110
111
|
)
|
111
112
|
return None, tr(
|
112
113
|
"❗ Destination '{disp_dest}' already exists and overwrite is False.",
|
@@ -121,7 +122,7 @@ class MoveFileTool(ToolBase):
|
|
121
122
|
except Exception as e:
|
122
123
|
self.report_error(
|
123
124
|
tr("❌ Error removing destination before move: {error}", error=e),
|
124
|
-
ReportAction.
|
125
|
+
ReportAction.UPDATE,
|
125
126
|
)
|
126
127
|
return None, tr(
|
127
128
|
"❌ Error removing destination before move: {error}", error=e
|
@@ -5,6 +5,7 @@ from janito.tools.tool_base import ToolBase, ToolPermissions
|
|
5
5
|
from janito.report_events import ReportAction
|
6
6
|
from janito.i18n import tr
|
7
7
|
|
8
|
+
|
8
9
|
@register_local_tool
|
9
10
|
class OpenHtmlInBrowserTool(ToolBase):
|
10
11
|
"""
|
@@ -15,6 +16,7 @@ class OpenHtmlInBrowserTool(ToolBase):
|
|
15
16
|
Returns:
|
16
17
|
str: Status message indicating the result.
|
17
18
|
"""
|
19
|
+
|
18
20
|
permissions = ToolPermissions(read=True)
|
19
21
|
tool_name = "open_html_in_browser"
|
20
22
|
|
@@ -25,15 +27,23 @@ class OpenHtmlInBrowserTool(ToolBase):
|
|
25
27
|
if not os.path.isfile(path):
|
26
28
|
self.report_error(tr("❗ File does not exist: {path}", path=path))
|
27
29
|
return tr("Warning: File does not exist: {path}", path=path)
|
28
|
-
if not path.lower().endswith((
|
30
|
+
if not path.lower().endswith((".html", ".htm")):
|
29
31
|
self.report_warning(tr("⚠️ Not an HTML file: {path}", path=path))
|
30
32
|
return tr("Warning: Not an HTML file: {path}", path=path)
|
31
|
-
url =
|
32
|
-
self.report_action(
|
33
|
+
url = "file://" + os.path.abspath(path)
|
34
|
+
self.report_action(
|
35
|
+
tr("📖 Opening HTML file in browser: {path}", path=path), ReportAction.READ
|
36
|
+
)
|
33
37
|
try:
|
34
38
|
webbrowser.open(url)
|
35
39
|
except Exception as err:
|
36
|
-
self.report_error(
|
37
|
-
|
40
|
+
self.report_error(
|
41
|
+
tr("❗ Error opening HTML file: {path}: {err}", path=path, err=str(err))
|
42
|
+
)
|
43
|
+
return tr(
|
44
|
+
"Warning: Error opening HTML file: {path}: {err}",
|
45
|
+
path=path,
|
46
|
+
err=str(err),
|
47
|
+
)
|
38
48
|
self.report_success(tr("✅ HTML file opened in browser: {path}", path=path))
|
39
49
|
return tr("HTML file opened in browser: {path}", path=path)
|
@@ -1,40 +1,55 @@
|
|
1
|
-
from janito.tools.tool_base import ToolBase, ToolPermissions
|
2
|
-
from janito.report_events import ReportAction
|
3
|
-
from janito.tools.adapters.local.adapter import register_local_tool
|
4
|
-
from janito.tools.tool_utils import pluralize
|
5
|
-
from janito.i18n import tr
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
1
|
+
from janito.tools.tool_base import ToolBase, ToolPermissions
|
2
|
+
from janito.report_events import ReportAction
|
3
|
+
from janito.tools.adapters.local.adapter import register_local_tool
|
4
|
+
from janito.tools.tool_utils import pluralize
|
5
|
+
from janito.i18n import tr
|
6
|
+
|
7
|
+
|
8
|
+
@register_local_tool
|
9
|
+
class ReadFilesTool(ToolBase):
|
10
|
+
"""
|
11
|
+
Read all text content from multiple files.
|
12
|
+
|
13
|
+
Args:
|
14
|
+
paths (list[str]): List of file paths to read.
|
15
|
+
|
16
|
+
Returns:
|
17
|
+
str: Concatenated content of all files, each prefixed by a header with the file name. If a file cannot be read, an error message is included for that file.
|
18
|
+
"""
|
19
|
+
|
20
|
+
permissions = ToolPermissions(read=True)
|
21
|
+
tool_name = "read_files"
|
22
|
+
|
23
|
+
def run(self, paths: list[str]) -> str:
|
24
|
+
from janito.tools.tool_utils import display_path
|
25
|
+
import os
|
26
|
+
|
27
|
+
results = []
|
28
|
+
for path in paths:
|
29
|
+
disp_path = display_path(path)
|
30
|
+
self.report_action(
|
31
|
+
tr("📖 Read '{disp_path}'", disp_path=disp_path), ReportAction.READ
|
32
|
+
)
|
33
|
+
if not os.path.isfile(path):
|
34
|
+
self.report_warning(
|
35
|
+
tr("❗ not found: {disp_path}", disp_path=disp_path)
|
36
|
+
)
|
37
|
+
results.append(f"--- File: {disp_path} (not found) ---\n")
|
38
|
+
continue
|
39
|
+
try:
|
40
|
+
with open(path, "r", encoding="utf-8", errors="replace") as f:
|
41
|
+
content = f.read()
|
42
|
+
results.append(f"--- File: {disp_path} ---\n{content}\n")
|
43
|
+
self.report_success(tr("✅ Read {disp_path}", disp_path=disp_path))
|
44
|
+
except Exception as e:
|
45
|
+
self.report_error(
|
46
|
+
tr(
|
47
|
+
" ❌ Error reading {disp_path}: {error}",
|
48
|
+
disp_path=disp_path,
|
49
|
+
error=e,
|
50
|
+
)
|
51
|
+
)
|
52
|
+
results.append(
|
53
|
+
f"--- File: {disp_path} (error) ---\nError reading file: {e}\n"
|
54
|
+
)
|
55
|
+
return "\n".join(results)
|
@@ -28,6 +28,7 @@ class ReplaceTextInFileTool(ToolBase):
|
|
28
28
|
- "No changes made. [Warning: Search text not found in file] Please review the original file."
|
29
29
|
- "Error replacing text: <error message>"
|
30
30
|
"""
|
31
|
+
|
31
32
|
permissions = ToolPermissions(read=True, write=True)
|
32
33
|
tool_name = "replace_text_in_file"
|
33
34
|
|
@@ -85,9 +86,9 @@ class ReplaceTextInFileTool(ToolBase):
|
|
85
86
|
line_delta_str,
|
86
87
|
replace_all,
|
87
88
|
)
|
88
|
-
return self._format_final_msg(
|
89
|
-
|
90
|
-
)
|
89
|
+
return self._format_final_msg(path, warning, match_info, details) + (
|
90
|
+
f"\n{validation_result}" if validation_result else ""
|
91
|
+
)
|
91
92
|
except Exception as e:
|
92
93
|
self.report_error(tr(" ❌ Error"), ReportAction.REPLACE)
|
93
94
|
return tr("Error replacing text: {error}", error=e)
|