janito 2.1.1__py3-none-any.whl → 2.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.
Files changed (137) hide show
  1. janito/__init__.py +6 -6
  2. janito/agent/setup_agent.py +14 -5
  3. janito/agent/templates/profiles/system_prompt_template_main.txt.j2 +3 -1
  4. janito/cli/chat_mode/bindings.py +6 -0
  5. janito/cli/chat_mode/session.py +16 -0
  6. janito/cli/chat_mode/shell/autocomplete.py +21 -21
  7. janito/cli/chat_mode/shell/commands/__init__.py +3 -2
  8. janito/cli/chat_mode/shell/commands/clear.py +12 -12
  9. janito/cli/chat_mode/shell/commands/exec.py +27 -0
  10. janito/cli/chat_mode/shell/commands/multi.py +51 -51
  11. janito/cli/chat_mode/shell/commands/tools.py +17 -6
  12. janito/cli/chat_mode/shell/input_history.py +62 -62
  13. janito/cli/chat_mode/shell/session/manager.py +1 -0
  14. janito/cli/chat_mode/toolbar.py +3 -1
  15. janito/cli/cli_commands/list_models.py +35 -35
  16. janito/cli/cli_commands/list_providers.py +9 -9
  17. janito/cli/cli_commands/list_tools.py +53 -53
  18. janito/cli/cli_commands/model_selection.py +50 -50
  19. janito/cli/cli_commands/model_utils.py +13 -2
  20. janito/cli/cli_commands/set_api_key.py +19 -19
  21. janito/cli/cli_commands/show_config.py +51 -51
  22. janito/cli/cli_commands/show_system_prompt.py +62 -62
  23. janito/cli/config.py +2 -1
  24. janito/cli/core/__init__.py +4 -4
  25. janito/cli/core/event_logger.py +59 -59
  26. janito/cli/core/getters.py +3 -1
  27. janito/cli/core/runner.py +27 -6
  28. janito/cli/core/setters.py +5 -1
  29. janito/cli/core/unsetters.py +54 -54
  30. janito/cli/main_cli.py +12 -1
  31. janito/cli/prompt_core.py +5 -2
  32. janito/cli/rich_terminal_reporter.py +22 -3
  33. janito/cli/single_shot_mode/__init__.py +6 -6
  34. janito/cli/single_shot_mode/handler.py +11 -1
  35. janito/cli/verbose_output.py +1 -1
  36. janito/config.py +5 -5
  37. janito/config_manager.py +2 -0
  38. janito/driver_events.py +14 -0
  39. janito/drivers/anthropic/driver.py +113 -113
  40. janito/drivers/azure_openai/driver.py +38 -3
  41. janito/drivers/driver_registry.py +0 -2
  42. janito/drivers/openai/driver.py +196 -36
  43. janito/formatting_token.py +54 -54
  44. janito/i18n/__init__.py +35 -35
  45. janito/i18n/messages.py +23 -23
  46. janito/i18n/pt.py +47 -47
  47. janito/llm/__init__.py +5 -5
  48. janito/llm/agent.py +443 -443
  49. janito/llm/auth.py +1 -0
  50. janito/llm/driver.py +7 -1
  51. janito/llm/driver_config.py +1 -0
  52. janito/llm/driver_config_builder.py +34 -34
  53. janito/llm/driver_input.py +12 -12
  54. janito/llm/message_parts.py +60 -60
  55. janito/llm/model.py +38 -38
  56. janito/llm/provider.py +196 -196
  57. janito/provider_config.py +7 -3
  58. janito/provider_registry.py +29 -5
  59. janito/providers/__init__.py +1 -0
  60. janito/providers/anthropic/model_info.py +22 -22
  61. janito/providers/anthropic/provider.py +2 -2
  62. janito/providers/azure_openai/model_info.py +7 -6
  63. janito/providers/azure_openai/provider.py +44 -2
  64. janito/providers/deepseek/__init__.py +1 -1
  65. janito/providers/deepseek/model_info.py +16 -16
  66. janito/providers/deepseek/provider.py +91 -91
  67. janito/providers/google/model_info.py +21 -29
  68. janito/providers/google/provider.py +49 -38
  69. janito/providers/mistralai/provider.py +2 -2
  70. janito/providers/openai/model_info.py +0 -11
  71. janito/providers/openai/provider.py +1 -1
  72. janito/providers/provider_static_info.py +2 -3
  73. janito/providers/registry.py +26 -26
  74. janito/tools/adapters/__init__.py +1 -1
  75. janito/tools/adapters/local/__init__.py +62 -62
  76. janito/tools/adapters/local/adapter.py +33 -11
  77. janito/tools/adapters/local/ask_user.py +102 -102
  78. janito/tools/adapters/local/copy_file.py +84 -84
  79. janito/tools/adapters/local/create_directory.py +69 -69
  80. janito/tools/adapters/local/create_file.py +82 -82
  81. janito/tools/adapters/local/delete_text_in_file.py +4 -7
  82. janito/tools/adapters/local/fetch_url.py +97 -97
  83. janito/tools/adapters/local/find_files.py +138 -140
  84. janito/tools/adapters/local/get_file_outline/__init__.py +1 -1
  85. janito/tools/adapters/local/get_file_outline/core.py +117 -151
  86. janito/tools/adapters/local/get_file_outline/java_outline.py +40 -0
  87. janito/tools/adapters/local/get_file_outline/markdown_outline.py +14 -14
  88. janito/tools/adapters/local/get_file_outline/python_outline.py +303 -303
  89. janito/tools/adapters/local/get_file_outline/python_outline_v2.py +156 -156
  90. janito/tools/adapters/local/get_file_outline/search_outline.py +33 -33
  91. janito/tools/adapters/local/move_file.py +3 -13
  92. janito/tools/adapters/local/open_html_in_browser.py +24 -29
  93. janito/tools/adapters/local/open_url.py +3 -2
  94. janito/tools/adapters/local/python_code_run.py +166 -166
  95. janito/tools/adapters/local/python_command_run.py +164 -164
  96. janito/tools/adapters/local/python_file_run.py +163 -163
  97. janito/tools/adapters/local/remove_directory.py +6 -17
  98. janito/tools/adapters/local/remove_file.py +9 -15
  99. janito/tools/adapters/local/replace_text_in_file.py +6 -9
  100. janito/tools/adapters/local/run_bash_command.py +176 -176
  101. janito/tools/adapters/local/run_powershell_command.py +219 -219
  102. janito/tools/adapters/local/search_text/__init__.py +1 -1
  103. janito/tools/adapters/local/search_text/core.py +201 -201
  104. janito/tools/adapters/local/search_text/match_lines.py +1 -1
  105. janito/tools/adapters/local/search_text/pattern_utils.py +73 -73
  106. janito/tools/adapters/local/search_text/traverse_directory.py +145 -145
  107. janito/tools/adapters/local/validate_file_syntax/__init__.py +1 -1
  108. janito/tools/adapters/local/validate_file_syntax/core.py +106 -106
  109. janito/tools/adapters/local/validate_file_syntax/css_validator.py +35 -35
  110. janito/tools/adapters/local/validate_file_syntax/html_validator.py +93 -93
  111. janito/tools/adapters/local/validate_file_syntax/js_validator.py +27 -27
  112. janito/tools/adapters/local/validate_file_syntax/json_validator.py +6 -6
  113. janito/tools/adapters/local/validate_file_syntax/markdown_validator.py +109 -109
  114. janito/tools/adapters/local/validate_file_syntax/ps1_validator.py +32 -32
  115. janito/tools/adapters/local/validate_file_syntax/python_validator.py +5 -5
  116. janito/tools/adapters/local/validate_file_syntax/xml_validator.py +11 -11
  117. janito/tools/adapters/local/validate_file_syntax/yaml_validator.py +6 -6
  118. janito/tools/adapters/local/view_file.py +167 -167
  119. janito/tools/inspect_registry.py +17 -17
  120. janito/tools/tool_base.py +105 -105
  121. janito/tools/tool_events.py +58 -58
  122. janito/tools/tool_run_exception.py +12 -12
  123. janito/tools/tool_use_tracker.py +81 -81
  124. janito/tools/tool_utils.py +45 -45
  125. janito/tools/tools_adapter.py +78 -6
  126. janito/tools/tools_schema.py +104 -104
  127. janito/version.py +4 -4
  128. {janito-2.1.1.dist-info → janito-2.3.0.dist-info}/METADATA +388 -232
  129. janito-2.3.0.dist-info/RECORD +181 -0
  130. janito-2.3.0.dist-info/licenses/LICENSE +21 -0
  131. janito/cli/chat_mode/shell/commands/last.py +0 -137
  132. janito/drivers/google_genai/driver.py +0 -54
  133. janito/drivers/google_genai/schema_generator.py +0 -67
  134. janito-2.1.1.dist-info/RECORD +0 -181
  135. {janito-2.1.1.dist-info → janito-2.3.0.dist-info}/WHEEL +0 -0
  136. {janito-2.1.1.dist-info → janito-2.3.0.dist-info}/entry_points.txt +0 -0
  137. {janito-2.1.1.dist-info → janito-2.3.0.dist-info}/top_level.txt +0 -0
@@ -1,163 +1,163 @@
1
- import subprocess
2
- import os
3
- import sys
4
- import tempfile
5
- import threading
6
- from janito.tools.tool_base import ToolBase
7
- from janito.report_events import ReportAction
8
- from janito.tools.adapters.local.adapter import register_local_tool
9
- from janito.i18n import tr
10
-
11
-
12
- @register_local_tool
13
- class PythonFileRunTool(ToolBase):
14
- """
15
- Tool to execute a specified Python script file.
16
-
17
- Parameters:
18
- file_path (str): Path to the Python script file to execute.
19
- timeout (int): Timeout in seconds for the command. Defaults to 60.
20
-
21
- Returns:
22
- str: Output and status message, or file paths/line counts if output is large.
23
- """
24
- provides_execution = True
25
- tool_name = "python_file_run"
26
-
27
- def run(self, file_path: str, timeout: int = 60) -> str:
28
- self.report_action(
29
- tr("🚀 Running: python {file_path}", file_path=file_path),
30
- ReportAction.EXECUTE,
31
- )
32
- self.report_stdout("\n")
33
- try:
34
- with (
35
- tempfile.NamedTemporaryFile(
36
- mode="w+",
37
- prefix="python_file_stdout_",
38
- delete=False,
39
- encoding="utf-8",
40
- ) as stdout_file,
41
- tempfile.NamedTemporaryFile(
42
- mode="w+",
43
- prefix="python_file_stderr_",
44
- delete=False,
45
- encoding="utf-8",
46
- ) as stderr_file,
47
- ):
48
- process = subprocess.Popen(
49
- [sys.executable, file_path],
50
- stdout=subprocess.PIPE,
51
- stderr=subprocess.PIPE,
52
- text=True,
53
- bufsize=1,
54
- universal_newlines=True,
55
- encoding="utf-8",
56
- env={**os.environ, "PYTHONIOENCODING": "utf-8"},
57
- )
58
- stdout_lines, stderr_lines = self._stream_process_output(
59
- process, stdout_file, stderr_file
60
- )
61
- return_code = self._wait_for_process(process, timeout)
62
- if return_code is None:
63
- return tr(
64
- "Code timed out after {timeout} seconds.", timeout=timeout
65
- )
66
- stdout_file.flush()
67
- stderr_file.flush()
68
- self.report_success(
69
- tr("✅ Return code {return_code}", return_code=return_code),
70
- ReportAction.EXECUTE,
71
- )
72
- return self._format_result(
73
- stdout_file.name, stderr_file.name, return_code
74
- )
75
- except Exception as e:
76
- self.report_error(tr("❌ Error: {error}", error=e), ReportAction.EXECUTE)
77
- return tr("Error running file: {error}", error=e)
78
-
79
- def _stream_process_output(self, process, stdout_file, stderr_file):
80
- stdout_lines = 0
81
- stderr_lines = 0
82
-
83
- def stream_output(stream, file_obj, report_func, count_func):
84
- nonlocal stdout_lines, stderr_lines
85
- for line in stream:
86
- file_obj.write(line)
87
- file_obj.flush()
88
- # Always supply a default action for stdout/stderr reporting
89
- from janito.report_events import ReportAction
90
-
91
- report_func(line.rstrip("\r\n"), ReportAction.EXECUTE)
92
- if count_func == "stdout":
93
- stdout_lines += 1
94
- else:
95
- stderr_lines += 1
96
-
97
- stdout_thread = threading.Thread(
98
- target=stream_output,
99
- args=(process.stdout, stdout_file, self.report_stdout, "stdout"),
100
- )
101
- stderr_thread = threading.Thread(
102
- target=stream_output,
103
- args=(process.stderr, stderr_file, self.report_stderr, "stderr"),
104
- )
105
- stdout_thread.start()
106
- stderr_thread.start()
107
- stdout_thread.join()
108
- stderr_thread.join()
109
- return stdout_lines, stderr_lines
110
-
111
- def _wait_for_process(self, process, timeout):
112
- try:
113
- return process.wait(timeout=timeout)
114
- except subprocess.TimeoutExpired:
115
- process.kill()
116
- self.report_error(
117
- tr("❌ Timed out after {timeout} seconds.", timeout=timeout),
118
- ReportAction.EXECUTE,
119
- )
120
- return None
121
-
122
- def _format_result(self, stdout_file_name, stderr_file_name, return_code):
123
- with open(stdout_file_name, "r", encoding="utf-8", errors="replace") as out_f:
124
- stdout_content = out_f.read()
125
- with open(stderr_file_name, "r", encoding="utf-8", errors="replace") as err_f:
126
- stderr_content = err_f.read()
127
- max_lines = 100
128
- stdout_lines = stdout_content.count("\n")
129
- stderr_lines = stderr_content.count("\n")
130
-
131
- def head_tail(text, n=10):
132
- lines = text.splitlines()
133
- if len(lines) <= 2 * n:
134
- return "\n".join(lines)
135
- return "\n".join(
136
- lines[:n]
137
- + ["... ({} lines omitted) ...".format(len(lines) - 2 * n)]
138
- + lines[-n:]
139
- )
140
-
141
- if stdout_lines <= max_lines and stderr_lines <= max_lines:
142
- result = f"Return code: {return_code}\n--- python_file_run: STDOUT ---\n{stdout_content}"
143
- if stderr_content.strip():
144
- result += f"\n--- python_file_run: STDERR ---\n{stderr_content}"
145
- return result
146
- else:
147
- result = f"stdout_file: {stdout_file_name} (lines: {stdout_lines})\n"
148
- if stderr_lines > 0 and stderr_content.strip():
149
- result += f"stderr_file: {stderr_file_name} (lines: {stderr_lines})\n"
150
- result += f"returncode: {return_code}\n"
151
- result += (
152
- "--- python_file_run: STDOUT (head/tail) ---\n"
153
- + head_tail(stdout_content)
154
- + "\n"
155
- )
156
- if stderr_content.strip():
157
- result += (
158
- "--- python_file_run: STDERR (head/tail) ---\n"
159
- + head_tail(stderr_content)
160
- + "\n"
161
- )
162
- result += "Use the view_file tool to inspect the contents of these files when needed."
163
- return result
1
+ import subprocess
2
+ import os
3
+ import sys
4
+ import tempfile
5
+ import threading
6
+ from janito.tools.tool_base import ToolBase
7
+ from janito.report_events import ReportAction
8
+ from janito.tools.adapters.local.adapter import register_local_tool
9
+ from janito.i18n import tr
10
+
11
+
12
+ @register_local_tool
13
+ class PythonFileRunTool(ToolBase):
14
+ """
15
+ Tool to execute a specified Python script file.
16
+
17
+ Parameters:
18
+ file_path (str): Path to the Python script file to execute.
19
+ timeout (int): Timeout in seconds for the command. Defaults to 60.
20
+
21
+ Returns:
22
+ str: Output and status message, or file paths/line counts if output is large.
23
+ """
24
+ provides_execution = True
25
+ tool_name = "python_file_run"
26
+
27
+ def run(self, file_path: str, timeout: int = 60) -> str:
28
+ self.report_action(
29
+ tr("🚀 Running: python {file_path}", file_path=file_path),
30
+ ReportAction.EXECUTE,
31
+ )
32
+ self.report_stdout("\n")
33
+ try:
34
+ with (
35
+ tempfile.NamedTemporaryFile(
36
+ mode="w+",
37
+ prefix="python_file_stdout_",
38
+ delete=False,
39
+ encoding="utf-8",
40
+ ) as stdout_file,
41
+ tempfile.NamedTemporaryFile(
42
+ mode="w+",
43
+ prefix="python_file_stderr_",
44
+ delete=False,
45
+ encoding="utf-8",
46
+ ) as stderr_file,
47
+ ):
48
+ process = subprocess.Popen(
49
+ [sys.executable, file_path],
50
+ stdout=subprocess.PIPE,
51
+ stderr=subprocess.PIPE,
52
+ text=True,
53
+ bufsize=1,
54
+ universal_newlines=True,
55
+ encoding="utf-8",
56
+ env={**os.environ, "PYTHONIOENCODING": "utf-8"},
57
+ )
58
+ stdout_lines, stderr_lines = self._stream_process_output(
59
+ process, stdout_file, stderr_file
60
+ )
61
+ return_code = self._wait_for_process(process, timeout)
62
+ if return_code is None:
63
+ return tr(
64
+ "Code timed out after {timeout} seconds.", timeout=timeout
65
+ )
66
+ stdout_file.flush()
67
+ stderr_file.flush()
68
+ self.report_success(
69
+ tr("✅ Return code {return_code}", return_code=return_code),
70
+ ReportAction.EXECUTE,
71
+ )
72
+ return self._format_result(
73
+ stdout_file.name, stderr_file.name, return_code
74
+ )
75
+ except Exception as e:
76
+ self.report_error(tr("❌ Error: {error}", error=e), ReportAction.EXECUTE)
77
+ return tr("Error running file: {error}", error=e)
78
+
79
+ def _stream_process_output(self, process, stdout_file, stderr_file):
80
+ stdout_lines = 0
81
+ stderr_lines = 0
82
+
83
+ def stream_output(stream, file_obj, report_func, count_func):
84
+ nonlocal stdout_lines, stderr_lines
85
+ for line in stream:
86
+ file_obj.write(line)
87
+ file_obj.flush()
88
+ # Always supply a default action for stdout/stderr reporting
89
+ from janito.report_events import ReportAction
90
+
91
+ report_func(line.rstrip("\r\n"), ReportAction.EXECUTE)
92
+ if count_func == "stdout":
93
+ stdout_lines += 1
94
+ else:
95
+ stderr_lines += 1
96
+
97
+ stdout_thread = threading.Thread(
98
+ target=stream_output,
99
+ args=(process.stdout, stdout_file, self.report_stdout, "stdout"),
100
+ )
101
+ stderr_thread = threading.Thread(
102
+ target=stream_output,
103
+ args=(process.stderr, stderr_file, self.report_stderr, "stderr"),
104
+ )
105
+ stdout_thread.start()
106
+ stderr_thread.start()
107
+ stdout_thread.join()
108
+ stderr_thread.join()
109
+ return stdout_lines, stderr_lines
110
+
111
+ def _wait_for_process(self, process, timeout):
112
+ try:
113
+ return process.wait(timeout=timeout)
114
+ except subprocess.TimeoutExpired:
115
+ process.kill()
116
+ self.report_error(
117
+ tr("❌ Timed out after {timeout} seconds.", timeout=timeout),
118
+ ReportAction.EXECUTE,
119
+ )
120
+ return None
121
+
122
+ def _format_result(self, stdout_file_name, stderr_file_name, return_code):
123
+ with open(stdout_file_name, "r", encoding="utf-8", errors="replace") as out_f:
124
+ stdout_content = out_f.read()
125
+ with open(stderr_file_name, "r", encoding="utf-8", errors="replace") as err_f:
126
+ stderr_content = err_f.read()
127
+ max_lines = 100
128
+ stdout_lines = stdout_content.count("\n")
129
+ stderr_lines = stderr_content.count("\n")
130
+
131
+ def head_tail(text, n=10):
132
+ lines = text.splitlines()
133
+ if len(lines) <= 2 * n:
134
+ return "\n".join(lines)
135
+ return "\n".join(
136
+ lines[:n]
137
+ + ["... ({} lines omitted) ...".format(len(lines) - 2 * n)]
138
+ + lines[-n:]
139
+ )
140
+
141
+ if stdout_lines <= max_lines and stderr_lines <= max_lines:
142
+ result = f"Return code: {return_code}\n--- python_file_run: STDOUT ---\n{stdout_content}"
143
+ if stderr_content.strip():
144
+ result += f"\n--- python_file_run: STDERR ---\n{stderr_content}"
145
+ return result
146
+ else:
147
+ result = f"stdout_file: {stdout_file_name} (lines: {stdout_lines})\n"
148
+ if stderr_lines > 0 and stderr_content.strip():
149
+ result += f"stderr_file: {stderr_file_name} (lines: {stderr_lines})\n"
150
+ result += f"returncode: {return_code}\n"
151
+ result += (
152
+ "--- python_file_run: STDOUT (head/tail) ---\n"
153
+ + head_tail(stdout_content)
154
+ + "\n"
155
+ )
156
+ if stderr_content.strip():
157
+ result += (
158
+ "--- python_file_run: STDERR (head/tail) ---\n"
159
+ + head_tail(stderr_content)
160
+ + "\n"
161
+ )
162
+ result += "Use the view_file tool to inspect the contents of these files when needed."
163
+ return result
@@ -28,36 +28,25 @@ class RemoveDirectoryTool(ToolBase):
28
28
  disp_path = display_path(file_path)
29
29
  self.report_action(
30
30
  tr("🗃️ Remove directory '{disp_path}' ...", disp_path=disp_path),
31
- ReportAction.CREATE,
31
+ ReportAction.DELETE,
32
32
  )
33
- backup_zip = None
33
+
34
34
  try:
35
35
  if recursive:
36
- # Backup before recursive removal
37
- if os.path.exists(file_path) and os.path.isdir(file_path):
38
- backup_zip = file_path.rstrip("/\\") + ".bak.zip"
39
- with zipfile.ZipFile(backup_zip, "w", zipfile.ZIP_DEFLATED) as zipf:
40
- for root, dirs, files in os.walk(file_path):
41
- for file in files:
42
- abs_path = os.path.join(root, file)
43
- rel_path = os.path.relpath(
44
- abs_path, os.path.dirname(file_path)
45
- )
46
- zipf.write(abs_path, rel_path)
36
+
47
37
  shutil.rmtree(file_path)
48
38
  else:
49
39
  os.rmdir(file_path)
50
40
  self.report_success(
51
41
  tr("✅ 1 {dir_word}", dir_word=pluralize("directory", 1)),
52
- ReportAction.CREATE,
42
+ ReportAction.DELETE,
53
43
  )
54
44
  msg = tr("Directory removed: {disp_path}", disp_path=disp_path)
55
- if backup_zip:
56
- msg += tr(" (backup at {backup_zip})", backup_zip=backup_zip)
45
+
57
46
  return msg
58
47
  except Exception as e:
59
48
  self.report_error(
60
49
  tr(" ❌ Error removing directory: {error}", error=e),
61
- ReportAction.REMOVE,
50
+ ReportAction.DELETE,
62
51
  )
63
52
  return tr("Error removing directory: {error}", error=e)
@@ -15,7 +15,7 @@ class RemoveFileTool(ToolBase):
15
15
 
16
16
  Args:
17
17
  file_path (str): Path to the file to remove.
18
- backup (bool, optional): If True, create a backup (.bak) before removing. Recommend using backup=True only in the first call to avoid redundant backups. Defaults to False.
18
+ backup (bool, optional): Deprecated. Backups are no longer created. Flag ignored.
19
19
  Returns:
20
20
  str: Status message indicating the result. Example:
21
21
  - " Successfully removed the file at ..."
@@ -28,36 +28,30 @@ class RemoveFileTool(ToolBase):
28
28
  original_path = file_path
29
29
  path = file_path # Using file_path as is
30
30
  disp_path = display_path(original_path)
31
- backup_path = None
31
+
32
32
  # Report initial info about what is going to be removed
33
33
  self.report_action(
34
34
  tr("🗑️ Remove file '{disp_path}' ...", disp_path=disp_path),
35
- ReportAction.CREATE,
35
+ ReportAction.DELETE,
36
36
  )
37
37
  if not os.path.exists(path):
38
- self.report_error(tr("❌ File does not exist."), ReportAction.REMOVE)
38
+ self.report_error(tr("❌ File does not exist."), ReportAction.DELETE)
39
39
  return tr("❌ File does not exist.")
40
40
  if not os.path.isfile(path):
41
- self.report_error(tr("❌ Path is not a file."), ReportAction.REMOVE)
41
+ self.report_error(tr("❌ Path is not a file."), ReportAction.DELETE)
42
42
  return tr("❌ Path is not a file.")
43
43
  try:
44
- if backup:
45
- backup_path = path + ".bak"
46
- shutil.copy2(path, backup_path)
44
+
47
45
  os.remove(path)
48
- self.report_success(tr("✅ File removed"), ReportAction.CREATE)
46
+ self.report_success(tr("✅ File removed"), ReportAction.DELETE)
49
47
  msg = tr(
50
48
  "✅ Successfully removed the file at '{disp_path}'.",
51
49
  disp_path=disp_path,
52
50
  )
53
- if backup_path:
54
- msg += tr(
55
- " (backup at {backup_disp})",
56
- backup_disp=display_path(original_path + ".bak"),
57
- )
51
+
58
52
  return msg
59
53
  except Exception as e:
60
54
  self.report_error(
61
- tr("❌ Error removing file: {error}", error=e), ReportAction.REMOVE
55
+ tr("❌ Error removing file: {error}", error=e), ReportAction.DELETE
62
56
  )
63
57
  return tr("❌ Error removing file: {error}", error=e)
@@ -21,10 +21,10 @@ class ReplaceTextInFileTool(ToolBase):
21
21
  search_text (str): The exact text to search for (including indentation).
22
22
  replacement_text (str): The text to replace with (including indentation).
23
23
  replace_all (bool): If True, replace all occurrences; otherwise, only the first occurrence.
24
- backup (bool, optional): If True, create a backup (.bak) before replacing. Recommend using backup=True only in the first call to avoid redundant backups. Defaults to False.
24
+ backup (bool, optional): Deprecated. No backups are created anymore and this flag is ignored. Defaults to False.
25
25
  Returns:
26
26
  str: Status message. Example:
27
- - "Text replaced in /path/to/file (backup at /path/to/file.bak)"
27
+ - "Text replaced in /path/to/file"
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
  """
@@ -63,9 +63,7 @@ class ReplaceTextInFileTool(ToolBase):
63
63
  content, search_text, replacement_text, replace_all, occurrences
64
64
  )
65
65
  file_changed = new_content != content
66
- backup_path = file_path + ".bak"
67
- if backup and file_changed:
68
- self._backup_file(file_path, backup_path)
66
+ backup_path = None
69
67
  validation_result = ""
70
68
  if file_changed:
71
69
  self._write_file_content(file_path, new_content)
@@ -88,7 +86,7 @@ class ReplaceTextInFileTool(ToolBase):
88
86
  replace_all,
89
87
  )
90
88
  return self._format_final_msg(
91
- file_path, warning, backup_path, match_info, details
89
+ file_path, warning, match_info, details
92
90
  ) + (f"\n{validation_result}" if validation_result else "")
93
91
  except Exception as e:
94
92
  self.report_error(tr(" ❌ Error"), ReportAction.REPLACE)
@@ -260,13 +258,12 @@ class ReplaceTextInFileTool(ToolBase):
260
258
  details = ""
261
259
  return match_info, details
262
260
 
263
- def _format_final_msg(self, file_path, warning, backup_path, match_info, details):
261
+ def _format_final_msg(self, file_path, warning, match_info, details):
264
262
  """Format the final status message."""
265
263
  return tr(
266
- "Text replaced in {file_path}{warning} (backup at {backup_path}). {match_info}{details}",
264
+ "Text replaced in {file_path}{warning}. {match_info}{details}",
267
265
  file_path=file_path,
268
266
  warning=warning,
269
- backup_path=backup_path,
270
267
  match_info=match_info,
271
268
  details=details,
272
269
  )