janito 2.5.1__py3-none-any.whl → 2.6.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 (61) hide show
  1. janito/agent/setup_agent.py +231 -223
  2. janito/agent/templates/profiles/system_prompt_template_software_developer.txt.j2 +39 -0
  3. janito/cli/chat_mode/bindings.py +1 -26
  4. janito/cli/chat_mode/session.py +282 -294
  5. janito/cli/chat_mode/session_profile_select.py +125 -55
  6. janito/cli/chat_mode/shell/commands/tools.py +51 -48
  7. janito/cli/chat_mode/toolbar.py +42 -68
  8. janito/cli/cli_commands/list_tools.py +41 -56
  9. janito/cli/cli_commands/show_system_prompt.py +70 -49
  10. janito/cli/core/runner.py +6 -1
  11. janito/cli/core/setters.py +43 -34
  12. janito/cli/main_cli.py +25 -1
  13. janito/cli/prompt_core.py +76 -69
  14. janito/cli/rich_terminal_reporter.py +22 -1
  15. janito/cli/single_shot_mode/handler.py +95 -94
  16. janito/drivers/driver_registry.py +27 -29
  17. janito/drivers/openai/driver.py +436 -494
  18. janito/llm/agent.py +54 -68
  19. janito/provider_registry.py +178 -178
  20. janito/providers/anthropic/model_info.py +41 -22
  21. janito/providers/anthropic/provider.py +80 -67
  22. janito/providers/provider_static_info.py +18 -17
  23. janito/tools/adapters/local/__init__.py +66 -65
  24. janito/tools/adapters/local/adapter.py +79 -18
  25. janito/tools/adapters/local/create_directory.py +9 -9
  26. janito/tools/adapters/local/create_file.py +12 -12
  27. janito/tools/adapters/local/delete_text_in_file.py +16 -16
  28. janito/tools/adapters/local/find_files.py +2 -2
  29. janito/tools/adapters/local/get_file_outline/core.py +5 -5
  30. janito/tools/adapters/local/get_file_outline/search_outline.py +4 -4
  31. janito/tools/adapters/local/open_html_in_browser.py +15 -15
  32. janito/tools/adapters/local/python_file_run.py +4 -4
  33. janito/tools/adapters/local/read_files.py +40 -0
  34. janito/tools/adapters/local/remove_directory.py +5 -5
  35. janito/tools/adapters/local/remove_file.py +4 -4
  36. janito/tools/adapters/local/replace_text_in_file.py +21 -21
  37. janito/tools/adapters/local/run_bash_command.py +1 -1
  38. janito/tools/adapters/local/search_text/pattern_utils.py +2 -2
  39. janito/tools/adapters/local/search_text/traverse_directory.py +10 -10
  40. janito/tools/adapters/local/validate_file_syntax/core.py +7 -7
  41. janito/tools/adapters/local/validate_file_syntax/css_validator.py +2 -2
  42. janito/tools/adapters/local/validate_file_syntax/html_validator.py +7 -7
  43. janito/tools/adapters/local/validate_file_syntax/js_validator.py +2 -2
  44. janito/tools/adapters/local/validate_file_syntax/json_validator.py +2 -2
  45. janito/tools/adapters/local/validate_file_syntax/markdown_validator.py +2 -2
  46. janito/tools/adapters/local/validate_file_syntax/ps1_validator.py +2 -2
  47. janito/tools/adapters/local/validate_file_syntax/python_validator.py +2 -2
  48. janito/tools/adapters/local/validate_file_syntax/xml_validator.py +2 -2
  49. janito/tools/adapters/local/validate_file_syntax/yaml_validator.py +2 -2
  50. janito/tools/adapters/local/view_file.py +12 -12
  51. janito/tools/path_security.py +204 -0
  52. janito/tools/tool_use_tracker.py +12 -12
  53. janito/tools/tools_adapter.py +66 -34
  54. {janito-2.5.1.dist-info → janito-2.6.0.dist-info}/METADATA +412 -412
  55. {janito-2.5.1.dist-info → janito-2.6.0.dist-info}/RECORD +59 -58
  56. janito/drivers/anthropic/driver.py +0 -113
  57. janito/tools/adapters/local/get_file_outline/python_outline_v2.py +0 -156
  58. {janito-2.5.1.dist-info → janito-2.6.0.dist-info}/WHEEL +0 -0
  59. {janito-2.5.1.dist-info → janito-2.6.0.dist-info}/entry_points.txt +0 -0
  60. {janito-2.5.1.dist-info → janito-2.6.0.dist-info}/licenses/LICENSE +0 -0
  61. {janito-2.5.1.dist-info → janito-2.6.0.dist-info}/top_level.txt +0 -0
@@ -50,7 +50,7 @@ class FindFilesTool(ToolBase):
50
50
  dir_output.add(os.path.join(root, d))
51
51
  return dir_output
52
52
 
53
- def _handle_file_path(self, directory, patterns):
53
+ def _handle_path(self, directory, patterns):
54
54
  dir_output = set()
55
55
  filename = os.path.basename(directory)
56
56
  for pat in patterns:
@@ -129,7 +129,7 @@ class FindFilesTool(ToolBase):
129
129
  self._report_search(pattern, disp_path, depth_msg)
130
130
  dir_output = set()
131
131
  if os.path.isfile(directory):
132
- dir_output = self._handle_file_path(directory, patterns)
132
+ dir_output = self._handle_path(directory, patterns)
133
133
  elif os.path.isdir(directory):
134
134
  dir_output = self._handle_directory_path(directory, patterns, max_depth, include_gitignored)
135
135
  self._report_success(len(dir_output))
@@ -18,22 +18,22 @@ class GetFileOutlineTool(ToolBase):
18
18
  Get an outline of a file's structure. Supports Python and Markdown files.
19
19
 
20
20
  Args:
21
- file_path (str): Path to the file to outline.
21
+ path (str): Path to the file to outline.
22
22
  """
23
23
  permissions = ToolPermissions(read=True)
24
24
  tool_name = "get_file_outline"
25
25
 
26
- def run(self, file_path: str) -> str:
26
+ def run(self, path: str) -> str:
27
27
  try:
28
28
  self.report_action(
29
29
  tr(
30
30
  "📄 Outline file '{disp_path}' ...",
31
- disp_path=display_path(file_path),
31
+ disp_path=display_path(path),
32
32
  ),
33
33
  ReportAction.READ,
34
34
  )
35
- ext = os.path.splitext(file_path)[1].lower()
36
- with open(file_path, "r", encoding="utf-8", errors="replace") as f:
35
+ ext = os.path.splitext(path)[1].lower()
36
+ with open(path, "r", encoding="utf-8", errors="replace") as f:
37
37
  lines = f.readlines()
38
38
  return self._outline_by_extension(ext, lines)
39
39
  except Exception as e:
@@ -7,27 +7,27 @@ class SearchOutlineTool(ToolBase):
7
7
  Tool for searching outlines in files.
8
8
 
9
9
  Args:
10
- file_path (str): Path to the file for which to generate an outline.
10
+ path (str): Path to the file for which to generate an outline.
11
11
  Returns:
12
12
  str: Outline search result or status message.
13
13
  """
14
14
  permissions = ToolPermissions(read=True)
15
15
  tool_name = "search_outline"
16
16
 
17
- def run(self, file_path: str) -> str:
17
+ def run(self, path: str) -> str:
18
18
  from janito.tools.tool_utils import display_path
19
19
  from janito.i18n import tr
20
20
 
21
21
  self.report_action(
22
22
  tr(
23
23
  "🔍 Searching for outline in '{disp_path}'",
24
- disp_path=display_path(file_path),
24
+ disp_path=display_path(path),
25
25
  ),
26
26
  ReportAction.READ,
27
27
  )
28
28
  # ... rest of implementation ...
29
29
  # Example warnings and successes:
30
30
  # self.report_warning(tr("No files found with supported extensions."))
31
- # self.report_warning(tr("Error reading {file_path}: {error}", file_path=file_path, error=e))
31
+ # self.report_warning(tr("Error reading {path}: {error}", path=path, error=e))
32
32
  # self.report_success(tr("✅ {count} {match_word} found", count=len(output), match_word=pluralize('match', len(output))))
33
33
  pass
@@ -11,29 +11,29 @@ class OpenHtmlInBrowserTool(ToolBase):
11
11
  Open the supplied HTML file in the default web browser.
12
12
 
13
13
  Args:
14
- file_path (str): Path to the HTML file to open.
14
+ path (str): Path to the HTML file to open.
15
15
  Returns:
16
16
  str: Status message indicating the result.
17
17
  """
18
18
  permissions = ToolPermissions(read=True)
19
19
  tool_name = "open_html_in_browser"
20
20
 
21
- def run(self, file_path: str) -> str:
22
- if not file_path.strip():
21
+ def run(self, path: str) -> str:
22
+ if not path.strip():
23
23
  self.report_warning(tr("ℹ️ Empty file path provided."))
24
24
  return tr("Warning: Empty file path provided. Operation skipped.")
25
- if not os.path.isfile(file_path):
26
- self.report_error(tr("❗ File does not exist: {file_path}", file_path=file_path))
27
- return tr("Warning: File does not exist: {file_path}", file_path=file_path)
28
- if not file_path.lower().endswith(('.html', '.htm')):
29
- self.report_warning(tr("⚠️ Not an HTML file: {file_path}", file_path=file_path))
30
- return tr("Warning: Not an HTML file: {file_path}", file_path=file_path)
31
- url = 'file://' + os.path.abspath(file_path)
32
- self.report_action(tr("📖 Opening HTML file in browser: {file_path}", file_path=file_path), ReportAction.READ)
25
+ if not os.path.isfile(path):
26
+ self.report_error(tr("❗ File does not exist: {path}", path=path))
27
+ return tr("Warning: File does not exist: {path}", path=path)
28
+ if not path.lower().endswith(('.html', '.htm')):
29
+ self.report_warning(tr("⚠️ Not an HTML file: {path}", path=path))
30
+ 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
33
  try:
34
34
  webbrowser.open(url)
35
35
  except Exception as err:
36
- self.report_error(tr("❗ Error opening HTML file: {file_path}: {err}", file_path=file_path, err=str(err)))
37
- return tr("Warning: Error opening HTML file: {file_path}: {err}", file_path=file_path, err=str(err))
38
- self.report_success(tr("✅ HTML file opened in browser: {file_path}", file_path=file_path))
39
- return tr("HTML file opened in browser: {file_path}", file_path=file_path)
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))
38
+ self.report_success(tr("✅ HTML file opened in browser: {path}", path=path))
39
+ return tr("HTML file opened in browser: {path}", path=path)
@@ -15,7 +15,7 @@ class PythonFileRunTool(ToolBase):
15
15
  Tool to execute a specified Python script file.
16
16
 
17
17
  Args:
18
- file_path (str): Path to the Python script file to execute.
18
+ path (str): Path to the Python script file to execute.
19
19
  timeout (int): Timeout in seconds for the command. Defaults to 60.
20
20
 
21
21
  Returns:
@@ -24,9 +24,9 @@ class PythonFileRunTool(ToolBase):
24
24
  permissions = ToolPermissions(execute=True)
25
25
  tool_name = "python_file_run"
26
26
 
27
- def run(self, file_path: str, timeout: int = 60) -> str:
27
+ def run(self, path: str, timeout: int = 60) -> str:
28
28
  self.report_action(
29
- tr("🚀 Running: python {file_path}", file_path=file_path),
29
+ tr("🚀 Running: python {path}", path=path),
30
30
  ReportAction.EXECUTE,
31
31
  )
32
32
  self.report_stdout("\n")
@@ -46,7 +46,7 @@ class PythonFileRunTool(ToolBase):
46
46
  ) as stderr_file,
47
47
  ):
48
48
  process = subprocess.Popen(
49
- [sys.executable, file_path],
49
+ [sys.executable, path],
50
50
  stdout=subprocess.PIPE,
51
51
  stderr=subprocess.PIPE,
52
52
  text=True,
@@ -0,0 +1,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
+ @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)
@@ -14,7 +14,7 @@ class RemoveDirectoryTool(ToolBase):
14
14
  Remove a directory.
15
15
 
16
16
  Args:
17
- file_path (str): Path to the directory to remove.
17
+ path (str): Path to the directory to remove.
18
18
  recursive (bool, optional): If True, remove non-empty directories recursively (with backup). If False, only remove empty directories. Defaults to False.
19
19
  Returns:
20
20
  str: Status message indicating result. Example:
@@ -24,8 +24,8 @@ class RemoveDirectoryTool(ToolBase):
24
24
  permissions = ToolPermissions(write=True)
25
25
  tool_name = "remove_directory"
26
26
 
27
- def run(self, file_path: str, recursive: bool = False) -> str:
28
- disp_path = display_path(file_path)
27
+ def run(self, path: str, recursive: bool = False) -> str:
28
+ disp_path = display_path(path)
29
29
  self.report_action(
30
30
  tr("🗃️ Remove directory '{disp_path}' ...", disp_path=disp_path),
31
31
  ReportAction.DELETE,
@@ -34,9 +34,9 @@ class RemoveDirectoryTool(ToolBase):
34
34
  try:
35
35
  if recursive:
36
36
 
37
- shutil.rmtree(file_path)
37
+ shutil.rmtree(path)
38
38
  else:
39
- os.rmdir(file_path)
39
+ os.rmdir(path)
40
40
  self.report_success(
41
41
  tr("✅ 1 {dir_word}", dir_word=pluralize("directory", 1)),
42
42
  ReportAction.DELETE,
@@ -14,7 +14,7 @@ class RemoveFileTool(ToolBase):
14
14
  Remove a file at the specified path.
15
15
 
16
16
  Args:
17
- file_path (str): Path to the file to remove.
17
+ path (str): Path to the file to remove.
18
18
  backup (bool, optional): Deprecated. Backups are no longer created. Flag ignored.
19
19
  Returns:
20
20
  str: Status message indicating the result. Example:
@@ -24,9 +24,9 @@ class RemoveFileTool(ToolBase):
24
24
  permissions = ToolPermissions(write=True)
25
25
  tool_name = "remove_file"
26
26
 
27
- def run(self, file_path: str, backup: bool = False) -> str:
28
- original_path = file_path
29
- path = file_path # Using file_path as is
27
+ def run(self, path: str, backup: bool = False) -> str:
28
+ original_path = path
29
+ path = path # Using path as is
30
30
  disp_path = display_path(original_path)
31
31
 
32
32
  # Report initial info about what is going to be removed
@@ -17,7 +17,7 @@ class ReplaceTextInFileTool(ToolBase):
17
17
  search text in its original location.
18
18
 
19
19
  Args:
20
- file_path (str): Path to the file to modify.
20
+ path (str): Path to the file to modify.
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.
@@ -33,7 +33,7 @@ class ReplaceTextInFileTool(ToolBase):
33
33
 
34
34
  def run(
35
35
  self,
36
- file_path: str,
36
+ path: str,
37
37
  search_text: str,
38
38
  replacement_text: str,
39
39
  replace_all: bool = False,
@@ -41,7 +41,7 @@ class ReplaceTextInFileTool(ToolBase):
41
41
  ) -> str:
42
42
  from janito.tools.tool_utils import display_path
43
43
 
44
- disp_path = display_path(file_path)
44
+ disp_path = display_path(path)
45
45
  action = "(all)" if replace_all else ""
46
46
  search_lines = len(search_text.splitlines())
47
47
  replace_lines = len(replacement_text.splitlines())
@@ -52,11 +52,11 @@ class ReplaceTextInFileTool(ToolBase):
52
52
  action,
53
53
  search_text,
54
54
  replacement_text,
55
- file_path,
55
+ path,
56
56
  )
57
57
  self.report_action(info_msg, ReportAction.CREATE)
58
58
  try:
59
- content = self._read_file_content(file_path)
59
+ content = self._read_file_content(path)
60
60
  match_lines = self._find_match_lines(content, search_text)
61
61
  occurrences = content.count(search_text)
62
62
  replaced_count, new_content = self._replace_content(
@@ -66,9 +66,9 @@ class ReplaceTextInFileTool(ToolBase):
66
66
  backup_path = None
67
67
  validation_result = ""
68
68
  if file_changed:
69
- self._write_file_content(file_path, new_content)
69
+ self._write_file_content(path, new_content)
70
70
  # Perform syntax validation and append result
71
- validation_result = validate_file_syntax(file_path)
71
+ validation_result = validate_file_syntax(path)
72
72
  warning, concise_warning = self._handle_warnings(
73
73
  replaced_count, file_changed, occurrences
74
74
  )
@@ -86,15 +86,15 @@ class ReplaceTextInFileTool(ToolBase):
86
86
  replace_all,
87
87
  )
88
88
  return self._format_final_msg(
89
- file_path, warning, match_info, details
89
+ path, warning, match_info, details
90
90
  ) + (f"\n{validation_result}" if validation_result else "")
91
91
  except Exception as e:
92
92
  self.report_error(tr(" ❌ Error"), ReportAction.REPLACE)
93
93
  return tr("Error replacing text: {error}", error=e)
94
94
 
95
- def _read_file_content(self, file_path):
95
+ def _read_file_content(self, path):
96
96
  """Read the entire content of the file."""
97
- with open(file_path, "r", encoding="utf-8", errors="replace") as f:
97
+ with open(path, "r", encoding="utf-8", errors="replace") as f:
98
98
  return f.read()
99
99
 
100
100
  def _find_match_lines(self, content, search_text):
@@ -127,13 +127,13 @@ class ReplaceTextInFileTool(ToolBase):
127
127
  new_content = content.replace(search_text, replacement_text, 1)
128
128
  return replaced_count, new_content
129
129
 
130
- def _backup_file(self, file_path, backup_path):
130
+ def _backup_file(self, path, backup_path):
131
131
  """Create a backup of the file."""
132
- shutil.copy2(file_path, backup_path)
132
+ shutil.copy2(path, backup_path)
133
133
 
134
- def _write_file_content(self, file_path, content):
134
+ def _write_file_content(self, path, content):
135
135
  """Write content to the file."""
136
- with open(file_path, "w", encoding="utf-8", errors="replace") as f:
136
+ with open(path, "w", encoding="utf-8", errors="replace") as f:
137
137
  f.write(content)
138
138
 
139
139
  def _handle_warnings(self, replaced_count, file_changed, occurrences):
@@ -144,14 +144,14 @@ class ReplaceTextInFileTool(ToolBase):
144
144
  warning = tr(" [Warning: Search text not found in file]")
145
145
  if not file_changed:
146
146
  self.report_warning(
147
- tr(" ℹ️ No changes made. (not found)"), ReportAction.CREATE
147
+ tr(" ℹ️ No changes made. (not found)"), ReportAction.CREATE
148
148
  )
149
149
  concise_warning = tr(
150
150
  "No changes made. The search text was not found. Expand your search context with surrounding lines if needed."
151
151
  )
152
152
  if occurrences > 1 and replaced_count == 0:
153
153
  self.report_warning(
154
- tr(" ℹ️ No changes made. (not unique)"), ReportAction.CREATE
154
+ tr(" ℹ️ No changes made. (not unique)"), ReportAction.CREATE
155
155
  )
156
156
  concise_warning = tr(
157
157
  "No changes made. The search text is not unique. Expand your search context with surrounding lines to ensure uniqueness."
@@ -189,7 +189,7 @@ class ReplaceTextInFileTool(ToolBase):
189
189
  action,
190
190
  search_text,
191
191
  replacement_text,
192
- file_path,
192
+ path,
193
193
  ):
194
194
  """Format the info message for the operation."""
195
195
  if replace_lines == 0:
@@ -201,7 +201,7 @@ class ReplaceTextInFileTool(ToolBase):
201
201
  )
202
202
  else:
203
203
  try:
204
- with open(file_path, "r", encoding="utf-8", errors="replace") as f:
204
+ with open(path, "r", encoding="utf-8", errors="replace") as f:
205
205
  _content = f.read()
206
206
  _new_content = _content.replace(
207
207
  search_text, replacement_text, -1 if action else 1
@@ -258,11 +258,11 @@ class ReplaceTextInFileTool(ToolBase):
258
258
  details = ""
259
259
  return match_info, details
260
260
 
261
- def _format_final_msg(self, file_path, warning, match_info, details):
261
+ def _format_final_msg(self, path, warning, match_info, details):
262
262
  """Format the final status message."""
263
263
  return tr(
264
- "Text replaced in {file_path}{warning}. {match_info}{details}",
265
- file_path=file_path,
264
+ "Text replaced in {path}{warning}. {match_info}{details}",
265
+ path=path,
266
266
  warning=warning,
267
267
  match_info=match_info,
268
268
  details=details,
@@ -48,7 +48,7 @@ class RunBashCommandTool(ToolBase):
48
48
  self.report_warning(tr("ℹ️ Empty command provided."), ReportAction.EXECUTE)
49
49
  return tr("Warning: Empty command provided. Operation skipped.")
50
50
  self.report_action(
51
- tr("🖥️ Run bash command: {command} ...\n", command=command),
51
+ tr("🖥️ Run bash command: {command} ...\n", command=command),
52
52
  ReportAction.EXECUTE,
53
53
  )
54
54
  if requires_user_input:
@@ -51,8 +51,8 @@ def format_result(
51
51
  lines = []
52
52
  total = 0
53
53
  if per_file_counts:
54
- for file_path, count in per_file_counts:
55
- lines.append(f"{file_path}: {count}")
54
+ for path, count in per_file_counts:
55
+ lines.append(f"{path}: {count}")
56
56
  total += count
57
57
  lines.append(f"Total matches: {total}")
58
58
  if limit_reached:
@@ -24,7 +24,7 @@ def filter_dirs(dirs, root, gitignore_filter):
24
24
 
25
25
 
26
26
  def process_file_count_only(
27
- file_path,
27
+ path,
28
28
  per_file_counts,
29
29
  pattern,
30
30
  regex,
@@ -34,7 +34,7 @@ def process_file_count_only(
34
34
  total_results,
35
35
  ):
36
36
  match_count, file_limit_reached, _ = read_file_lines(
37
- file_path,
37
+ path,
38
38
  pattern,
39
39
  regex,
40
40
  use_regex,
@@ -44,12 +44,12 @@ def process_file_count_only(
44
44
  total_results + sum(count for _, count in per_file_counts),
45
45
  )
46
46
  if match_count > 0:
47
- per_file_counts.append((file_path, match_count))
47
+ per_file_counts.append((path, match_count))
48
48
  return file_limit_reached
49
49
 
50
50
 
51
51
  def process_file_collect(
52
- file_path,
52
+ path,
53
53
  dir_output,
54
54
  per_file_counts,
55
55
  pattern,
@@ -60,7 +60,7 @@ def process_file_collect(
60
60
  total_results,
61
61
  ):
62
62
  actual_match_count, file_limit_reached, file_lines_output = read_file_lines(
63
- file_path,
63
+ path,
64
64
  pattern,
65
65
  regex,
66
66
  use_regex,
@@ -71,7 +71,7 @@ def process_file_collect(
71
71
  )
72
72
  dir_output.extend(file_lines_output)
73
73
  if actual_match_count > 0:
74
- per_file_counts.append((file_path, actual_match_count))
74
+ per_file_counts.append((path, actual_match_count))
75
75
  return file_limit_reached
76
76
 
77
77
 
@@ -104,12 +104,12 @@ def traverse_directory(
104
104
  for root, dirs, files in walker:
105
105
  dirs[:] = filter_dirs(dirs, root, gitignore_filter)
106
106
  for file in files:
107
- file_path = os.path.join(root, file)
108
- if gitignore_filter.is_ignored(file_path):
107
+ path = os.path.join(root, file)
108
+ if gitignore_filter.is_ignored(path):
109
109
  continue
110
110
  if count_only:
111
111
  file_limit_reached = process_file_count_only(
112
- file_path,
112
+ path,
113
113
  per_file_counts,
114
114
  pattern,
115
115
  regex,
@@ -123,7 +123,7 @@ def traverse_directory(
123
123
  break
124
124
  else:
125
125
  file_limit_reached = process_file_collect(
126
- file_path,
126
+ path,
127
127
  dir_output,
128
128
  per_file_counts,
129
129
  pattern,
@@ -44,13 +44,13 @@ def _handle_validation_error(e, report_warning):
44
44
 
45
45
 
46
46
  def validate_file_syntax(
47
- file_path: str, report_info=None, report_warning=None, report_success=None
47
+ path: str, report_info=None, report_warning=None, report_success=None
48
48
  ) -> str:
49
- ext = os.path.splitext(file_path)[1].lower()
49
+ ext = os.path.splitext(path)[1].lower()
50
50
  validator = _get_validator(ext)
51
51
  try:
52
52
  if validator:
53
- return validator(file_path)
53
+ return validator(path)
54
54
  else:
55
55
  msg = tr("⚠️ Warning: Unsupported file extension: {ext}", ext=ext)
56
56
  if report_warning:
@@ -75,7 +75,7 @@ class ValidateFileSyntaxTool(ToolBase):
75
75
  - JavaScript (.js)
76
76
 
77
77
  Args:
78
- file_path (str): Path to the file to validate.
78
+ path (str): Path to the file to validate.
79
79
  Returns:
80
80
  str: Validation status message. Example:
81
81
  - "✅ Syntax OK"
@@ -85,8 +85,8 @@ class ValidateFileSyntaxTool(ToolBase):
85
85
  permissions = ToolPermissions(read=True)
86
86
  tool_name = "validate_file_syntax"
87
87
 
88
- def run(self, file_path: str) -> str:
89
- disp_path = display_path(file_path)
88
+ def run(self, path: str) -> str:
89
+ disp_path = display_path(path)
90
90
  self.report_action(
91
91
  tr(
92
92
  "🔎 Validate syntax for file '{disp_path}' ...",
@@ -95,7 +95,7 @@ class ValidateFileSyntaxTool(ToolBase):
95
95
  ReportAction.READ,
96
96
  )
97
97
  result = validate_file_syntax(
98
- file_path,
98
+ path,
99
99
 
100
100
  report_warning=self.report_warning,
101
101
  report_success=self.report_success,
@@ -2,8 +2,8 @@ from janito.i18n import tr
2
2
  import re
3
3
 
4
4
 
5
- def validate_css(file_path: str) -> str:
6
- with open(file_path, "r", encoding="utf-8") as f:
5
+ def validate_css(path: str) -> str:
6
+ with open(path, "r", encoding="utf-8") as f:
7
7
  content = f.read()
8
8
  errors = []
9
9
  # Check for unmatched curly braces
@@ -3,16 +3,16 @@ import re
3
3
  from lxml import etree
4
4
 
5
5
 
6
- def validate_html(file_path: str) -> str:
7
- html_content = _read_html_content(file_path)
6
+ def validate_html(path: str) -> str:
7
+ html_content = _read_html_content(path)
8
8
  warnings = _find_js_outside_script(html_content)
9
- lxml_error = _parse_html_and_collect_errors(file_path)
9
+ lxml_error = _parse_html_and_collect_errors(path)
10
10
  msg = _build_result_message(warnings, lxml_error)
11
11
  return msg
12
12
 
13
13
 
14
- def _read_html_content(file_path):
15
- with open(file_path, "r", encoding="utf-8") as f:
14
+ def _read_html_content(path):
15
+ with open(path, "r", encoding="utf-8") as f:
16
16
  return f.read()
17
17
 
18
18
 
@@ -46,11 +46,11 @@ def _find_js_outside_script(html_content):
46
46
  return warnings
47
47
 
48
48
 
49
- def _parse_html_and_collect_errors(file_path):
49
+ def _parse_html_and_collect_errors(path):
50
50
  lxml_error = None
51
51
  try:
52
52
  parser = etree.HTMLParser(recover=False)
53
- with open(file_path, "rb") as f:
53
+ with open(path, "rb") as f:
54
54
  etree.parse(f, parser=parser)
55
55
  error_log = parser.error_log
56
56
  syntax_errors = []
@@ -2,8 +2,8 @@ from janito.i18n import tr
2
2
  import re
3
3
 
4
4
 
5
- def validate_js(file_path: str) -> str:
6
- with open(file_path, "r", encoding="utf-8") as f:
5
+ def validate_js(path: str) -> str:
6
+ with open(path, "r", encoding="utf-8") as f:
7
7
  content = f.read()
8
8
  errors = []
9
9
  if content.count("{") != content.count("}"):
@@ -1,6 +1,6 @@
1
- def validate_json(file_path: str) -> str:
1
+ def validate_json(path: str) -> str:
2
2
  import json
3
3
 
4
- with open(file_path, "r", encoding="utf-8") as f:
4
+ with open(path, "r", encoding="utf-8") as f:
5
5
  json.load(f)
6
6
  return "✅ OK"
@@ -2,8 +2,8 @@ from janito.i18n import tr
2
2
  import re
3
3
 
4
4
 
5
- def validate_markdown(file_path: str) -> str:
6
- with open(file_path, "r", encoding="utf-8") as f:
5
+ def validate_markdown(path: str) -> str:
6
+ with open(path, "r", encoding="utf-8") as f:
7
7
  content = f.read()
8
8
  lines = content.splitlines()
9
9
  errors = []
@@ -2,8 +2,8 @@ from janito.i18n import tr
2
2
  import re
3
3
 
4
4
 
5
- def validate_ps1(file_path: str) -> str:
6
- with open(file_path, "r", encoding="utf-8") as f:
5
+ def validate_ps1(path: str) -> str:
6
+ with open(path, "r", encoding="utf-8") as f:
7
7
  content = f.read()
8
8
  errors = []
9
9
  # Unmatched curly braces
@@ -1,5 +1,5 @@
1
- def validate_python(file_path: str) -> str:
1
+ def validate_python(path: str) -> str:
2
2
  import py_compile
3
3
 
4
- py_compile.compile(file_path, doraise=True)
4
+ py_compile.compile(path, doraise=True)
5
5
  return "✅ OK"
@@ -1,11 +1,11 @@
1
1
  from janito.i18n import tr
2
2
 
3
3
 
4
- def validate_xml(file_path: str) -> str:
4
+ def validate_xml(path: str) -> str:
5
5
  try:
6
6
  from lxml import etree
7
7
  except ImportError:
8
8
  return tr("⚠️ lxml not installed. Cannot validate XML.")
9
- with open(file_path, "rb") as f:
9
+ with open(path, "rb") as f:
10
10
  etree.parse(f)
11
11
  return "✅ OK"