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.
Files changed (118) hide show
  1. janito/__init__.py +6 -7
  2. janito/__main__.py +4 -5
  3. janito/_version.py +55 -58
  4. janito/agent/setup_agent.py +308 -241
  5. janito/agent/templates/profiles/{system_prompt_template_software developer.txt.j2 → system_prompt_template_Developer_with_Python_Tools.txt.j2} +43 -39
  6. janito/agent/templates/profiles/system_prompt_template_developer.txt.j2 +3 -12
  7. janito/cli/__init__.py +9 -10
  8. janito/cli/chat_mode/bindings.py +38 -38
  9. janito/cli/chat_mode/chat_entry.py +21 -23
  10. janito/cli/chat_mode/prompt_style.py +22 -25
  11. janito/cli/chat_mode/script_runner.py +158 -154
  12. janito/cli/chat_mode/session.py +80 -35
  13. janito/cli/chat_mode/session_profile_select.py +61 -52
  14. janito/cli/chat_mode/shell/commands/__init__.py +1 -5
  15. janito/cli/chat_mode/shell/commands/_priv_check.py +1 -0
  16. janito/cli/chat_mode/shell/commands/bang.py +10 -3
  17. janito/cli/chat_mode/shell/commands/conversation_restart.py +24 -7
  18. janito/cli/chat_mode/shell/commands/execute.py +22 -7
  19. janito/cli/chat_mode/shell/commands/help.py +4 -1
  20. janito/cli/chat_mode/shell/commands/model.py +13 -5
  21. janito/cli/chat_mode/shell/commands/privileges.py +21 -0
  22. janito/cli/chat_mode/shell/commands/prompt.py +0 -2
  23. janito/cli/chat_mode/shell/commands/read.py +22 -5
  24. janito/cli/chat_mode/shell/commands/tools.py +15 -4
  25. janito/cli/chat_mode/shell/commands/write.py +22 -5
  26. janito/cli/chat_mode/shell/input_history.py +3 -1
  27. janito/cli/chat_mode/shell/session/manager.py +0 -2
  28. janito/cli/chat_mode/toolbar.py +25 -19
  29. janito/cli/cli_commands/list_models.py +1 -1
  30. janito/cli/cli_commands/list_providers.py +1 -0
  31. janito/cli/cli_commands/list_tools.py +35 -7
  32. janito/cli/cli_commands/model_utils.py +5 -3
  33. janito/cli/cli_commands/show_config.py +12 -0
  34. janito/cli/cli_commands/show_system_prompt.py +23 -9
  35. janito/cli/config.py +0 -13
  36. janito/cli/core/getters.py +2 -0
  37. janito/cli/core/runner.py +25 -8
  38. janito/cli/core/setters.py +13 -76
  39. janito/cli/main_cli.py +9 -25
  40. janito/cli/prompt_core.py +19 -18
  41. janito/cli/prompt_setup.py +6 -3
  42. janito/cli/rich_terminal_reporter.py +19 -5
  43. janito/cli/single_shot_mode/handler.py +104 -95
  44. janito/cli/verbose_output.py +5 -1
  45. janito/config_manager.py +4 -0
  46. janito/drivers/azure_openai/driver.py +27 -30
  47. janito/drivers/driver_registry.py +27 -27
  48. janito/drivers/openai/driver.py +452 -436
  49. janito/formatting_token.py +12 -4
  50. janito/llm/agent.py +15 -6
  51. janito/llm/driver.py +1 -0
  52. janito/provider_registry.py +139 -178
  53. janito/providers/__init__.py +2 -0
  54. janito/providers/anthropic/model_info.py +40 -41
  55. janito/providers/anthropic/provider.py +75 -80
  56. janito/providers/azure_openai/provider.py +9 -4
  57. janito/providers/deepseek/provider.py +5 -4
  58. janito/providers/google/model_info.py +4 -2
  59. janito/providers/google/provider.py +11 -5
  60. janito/providers/groq/__init__.py +1 -0
  61. janito/providers/groq/model_info.py +46 -0
  62. janito/providers/groq/provider.py +76 -0
  63. janito/providers/moonshotai/__init__.py +1 -0
  64. janito/providers/moonshotai/model_info.py +15 -0
  65. janito/providers/moonshotai/provider.py +89 -0
  66. janito/providers/openai/provider.py +6 -7
  67. janito/tools/__init__.py +2 -0
  68. janito/tools/adapters/local/__init__.py +67 -66
  69. janito/tools/adapters/local/adapter.py +21 -4
  70. janito/tools/adapters/local/ask_user.py +1 -0
  71. janito/tools/adapters/local/copy_file.py +1 -0
  72. janito/tools/adapters/local/create_directory.py +1 -0
  73. janito/tools/adapters/local/create_file.py +1 -0
  74. janito/tools/adapters/local/delete_text_in_file.py +2 -1
  75. janito/tools/adapters/local/fetch_url.py +1 -0
  76. janito/tools/adapters/local/find_files.py +7 -6
  77. janito/tools/adapters/local/get_file_outline/core.py +1 -0
  78. janito/tools/adapters/local/get_file_outline/java_outline.py +22 -15
  79. janito/tools/adapters/local/get_file_outline/search_outline.py +1 -0
  80. janito/tools/adapters/local/move_file.py +4 -3
  81. janito/tools/adapters/local/open_html_in_browser.py +15 -5
  82. janito/tools/adapters/local/open_url.py +1 -0
  83. janito/tools/adapters/local/python_code_run.py +1 -0
  84. janito/tools/adapters/local/python_command_run.py +1 -0
  85. janito/tools/adapters/local/python_file_run.py +1 -0
  86. janito/tools/adapters/local/read_files.py +55 -40
  87. janito/tools/adapters/local/remove_directory.py +1 -0
  88. janito/tools/adapters/local/remove_file.py +1 -0
  89. janito/tools/adapters/local/replace_text_in_file.py +4 -3
  90. janito/tools/adapters/local/run_bash_command.py +1 -0
  91. janito/tools/adapters/local/run_powershell_command.py +1 -0
  92. janito/tools/adapters/local/search_text/core.py +18 -17
  93. janito/tools/adapters/local/search_text/match_lines.py +5 -5
  94. janito/tools/adapters/local/search_text/pattern_utils.py +1 -1
  95. janito/tools/adapters/local/search_text/traverse_directory.py +7 -7
  96. janito/tools/adapters/local/validate_file_syntax/core.py +1 -1
  97. janito/tools/adapters/local/validate_file_syntax/html_validator.py +8 -1
  98. janito/tools/disabled_tools.py +68 -0
  99. janito/tools/path_security.py +18 -11
  100. janito/tools/permissions.py +6 -0
  101. janito/tools/permissions_parse.py +4 -3
  102. janito/tools/tool_base.py +11 -5
  103. janito/tools/tool_use_tracker.py +1 -4
  104. janito/tools/tool_utils.py +1 -1
  105. janito/tools/tools_adapter.py +57 -25
  106. {janito-2.6.1.dist-info → janito-2.8.0.dist-info}/METADATA +411 -417
  107. janito-2.8.0.dist-info/RECORD +202 -0
  108. janito/cli/chat_mode/shell/commands/livelogs.py +0 -49
  109. janito/drivers/mistralai/driver.py +0 -41
  110. janito/providers/mistralai/model_info.py +0 -37
  111. janito/providers/mistralai/provider.py +0 -72
  112. janito/providers/provider_static_info.py +0 -18
  113. janito-2.6.1.dist-info/RECORD +0 -199
  114. /janito/agent/templates/profiles/{system_prompt_template_assistant.txt.j2 → system_prompt_template_model_conversation_without_tools_or_context.txt.j2} +0 -0
  115. {janito-2.6.1.dist-info → janito-2.8.0.dist-info}/WHEEL +0 -0
  116. {janito-2.6.1.dist-info → janito-2.8.0.dist-info}/entry_points.txt +0 -0
  117. {janito-2.6.1.dist-info → janito-2.8.0.dist-info}/licenses/LICENSE +0 -0
  118. {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
- def get_local_tools_adapter(workdir=None):
35
- return LocalToolsAdapter(workdir=workdir or os.getcwd())
36
-
37
- # Register tools
38
- for tool_class in [
39
- AskUserTool,
40
- CopyFileTool,
41
- CreateDirectoryTool,
42
- CreateFileTool,
43
- FetchUrlTool,
44
- FindFilesTool,
45
- ViewFileTool,
46
- ReadFilesTool,
47
- MoveFileTool,
48
- OpenUrlTool,
49
- OpenHtmlInBrowserTool,
50
- PythonCodeRunTool,
51
- PythonCommandRunTool,
52
- PythonFileRunTool,
53
- RemoveDirectoryTool,
54
- RemoveFileTool,
55
- ReplaceTextInFileTool,
56
- RunBashCommandTool,
57
- RunPowershellCommandTool,
58
- GetFileOutlineTool,
59
- SearchOutlineTool,
60
- SearchTextTool,
61
- ValidateFileSyntaxTool,
62
- ]:
63
- local_tools_adapter.register_tool(tool_class)
64
-
65
- # DEBUG: Print registered tools at startup
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
- return self._tools[name]["instance"] if name in self._tools else None
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(f"Tool '{tool}' must provide a 'tool_name' (str) attribute.")
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
- # Register the tool on a *fresh* adapter instance to avoid circular
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.
@@ -27,6 +27,7 @@ class AskUserTool(ToolBase):
27
27
  - "No"
28
28
  - "Some detailed answer..."
29
29
  """
30
+
30
31
  permissions = ToolPermissions(read=True)
31
32
  tool_name = "ask_user"
32
33
 
@@ -21,6 +21,7 @@ class CopyFileTool(ToolBase):
21
21
  Returns:
22
22
  str: Status string for each copy operation.
23
23
  """
24
+
24
25
  permissions = ToolPermissions(read=True, write=True)
25
26
  tool_name = "copy_file"
26
27
 
@@ -18,6 +18,7 @@ class CreateDirectoryTool(ToolBase):
18
18
  - "5c5 Successfully created the directory at ..."
19
19
  - "5d7 Cannot create directory: ..."
20
20
  """
21
+
21
22
  permissions = ToolPermissions(write=True)
22
23
  tool_name = "create_directory"
23
24
 
@@ -25,6 +25,7 @@ class CreateFileTool(ToolBase):
25
25
 
26
26
  Note: Syntax validation is automatically performed after this operation.
27
27
  """
28
+
28
29
  permissions = ToolPermissions(write=True)
29
30
  tool_name = "create_file"
30
31
 
@@ -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)
@@ -21,6 +21,7 @@ class FetchUrlTool(ToolBase):
21
21
  - "No lines found for the provided search strings."
22
22
  - "Warning: Empty URL provided. Operation skipped."
23
23
  """
24
+
24
25
  permissions = ToolPermissions(read=True)
25
26
  tool_name = "fetch_url"
26
27
 
@@ -61,7 +61,9 @@ class FindFilesTool(ToolBase):
61
61
  break
62
62
  return dir_output
63
63
 
64
- def _handle_directory_path(self, directory, patterns, max_depth, include_gitignored):
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(directory, patterns, max_depth, include_gitignored)
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
-
@@ -20,6 +20,7 @@ class GetFileOutlineTool(ToolBase):
20
20
  Args:
21
21
  path (str): Path to the file to outline.
22
22
  """
23
+
23
24
  permissions = ToolPermissions(read=True)
24
25
  tool_name = "get_file_outline"
25
26
 
@@ -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(r"^(?:\s*(public|protected|private)\s+)?(?:static\s+)?([\w<>\[\]]+)\s+(\w+)\s*\(([^)]*)\)")
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
- "type": "class",
21
- "name": class_name,
22
- "generics": generics.strip("<>") if generics else None,
23
- "line": idx
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
- "type": "method",
34
- "class": current_class,
35
- "name": method_name,
36
- "return_type": return_type,
37
- "parameters": params.strip(),
38
- "line": idx
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
@@ -11,6 +11,7 @@ class SearchOutlineTool(ToolBase):
11
11
  Returns:
12
12
  str: Outline search result or status message.
13
13
  """
14
+
14
15
  permissions = ToolPermissions(read=True)
15
16
  tool_name = "search_outline"
16
17
 
@@ -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.CREATE,
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.MOVE,
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.MOVE,
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(('.html', '.htm')):
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 = 'file://' + os.path.abspath(path)
32
- self.report_action(tr("📖 Opening HTML file in browser: {path}", path=path), ReportAction.READ)
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(tr("❗ Error opening HTML file: {path}: {err}", path=path, err=str(err)))
37
- return tr("Warning: Error opening HTML file: {path}: {err}", path=path, err=str(err))
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)
@@ -15,6 +15,7 @@ class OpenUrlTool(ToolBase):
15
15
  Returns:
16
16
  str: Status message indicating the result.
17
17
  """
18
+
18
19
  permissions = ToolPermissions(read=True)
19
20
  tool_name = "open_url"
20
21
 
@@ -21,6 +21,7 @@ class PythonCodeRunTool(ToolBase):
21
21
  Returns:
22
22
  str: Output and status message, or file paths/line counts if output is large.
23
23
  """
24
+
24
25
  permissions = ToolPermissions(execute=True)
25
26
  tool_name = "python_code_run"
26
27
 
@@ -21,6 +21,7 @@ class PythonCommandRunTool(ToolBase):
21
21
  Returns:
22
22
  str: Output and status message, or file paths/line counts if output is large.
23
23
  """
24
+
24
25
  permissions = ToolPermissions(execute=True)
25
26
  tool_name = "python_command_run"
26
27
 
@@ -21,6 +21,7 @@ class PythonFileRunTool(ToolBase):
21
21
  Returns:
22
22
  str: Output and status message, or file paths/line counts if output is large.
23
23
  """
24
+
24
25
  permissions = ToolPermissions(execute=True)
25
26
  tool_name = "python_file_run"
26
27
 
@@ -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
- @register_local_tool
8
- class ReadFilesTool(ToolBase):
9
- """
10
- Read all text content from multiple files.
11
-
12
- Args:
13
- paths (list[str]): List of file paths to read.
14
-
15
- Returns:
16
- 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.
17
- """
18
- permissions = ToolPermissions(read=True)
19
- tool_name = "read_files"
20
-
21
- def run(self, paths: list[str]) -> str:
22
- from janito.tools.tool_utils import display_path
23
- import os
24
- results = []
25
- for path in paths:
26
- disp_path = display_path(path)
27
- self.report_action(tr("📖 Read '{disp_path}'", disp_path=disp_path), ReportAction.READ)
28
- if not os.path.isfile(path):
29
- self.report_warning(tr("❗ not found: {disp_path}", disp_path=disp_path))
30
- results.append(f"--- File: {disp_path} (not found) ---\n")
31
- continue
32
- try:
33
- with open(path, "r", encoding="utf-8", errors="replace") as f:
34
- content = f.read()
35
- results.append(f"--- File: {disp_path} ---\n{content}\n")
36
- self.report_success(tr("✅ Read {disp_path}", disp_path=disp_path))
37
- except Exception as e:
38
- self.report_error(tr(" ❌ Error reading {disp_path}: {error}", disp_path=disp_path, error=e))
39
- results.append(f"--- File: {disp_path} (error) ---\nError reading file: {e}\n")
40
- return "\n".join(results)
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)
@@ -21,6 +21,7 @@ class RemoveDirectoryTool(ToolBase):
21
21
  - "Directory removed: /path/to/dir"
22
22
  - "Error removing directory: <error message>"
23
23
  """
24
+
24
25
  permissions = ToolPermissions(write=True)
25
26
  tool_name = "remove_directory"
26
27
 
@@ -21,6 +21,7 @@ class RemoveFileTool(ToolBase):
21
21
  - " Successfully removed the file at ..."
22
22
  - " Cannot remove file: ..."
23
23
  """
24
+
24
25
  permissions = ToolPermissions(write=True)
25
26
  tool_name = "remove_file"
26
27
 
@@ -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
- path, warning, match_info, details
90
- ) + (f"\n{validation_result}" if validation_result else "")
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)