janito 3.8.0__py3-none-any.whl → 3.9.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 (67) hide show
  1. janito/cli/cli_commands/list_tools.py +1 -1
  2. janito/cli/prompt_core.py +48 -3
  3. janito/cli/rich_terminal_reporter.py +10 -2
  4. janito/llm/agent.py +6 -0
  5. janito/{tools/adapters/local → plugins/core/filemanager/tools}/validate_file_syntax/core.py +7 -2
  6. janito/plugins/core/filemanager/tools/validate_file_syntax/txt_validator.py +28 -0
  7. janito/plugins/manager.py +1 -1
  8. janito/{tools/adapters → plugins/tools}/local/adapter.py +1 -1
  9. janito/{tools/adapters → plugins/tools}/local/ask_user.py +1 -1
  10. janito/{tools/adapters → plugins/tools}/local/copy_file.py +1 -1
  11. janito/{tools/adapters → plugins/tools}/local/create_directory.py +1 -1
  12. janito/{tools/adapters → plugins/tools}/local/create_file.py +10 -6
  13. janito/{tools/adapters → plugins/tools}/local/delete_text_in_file.py +2 -2
  14. janito/{tools/adapters → plugins/tools}/local/fetch_url.py +3 -3
  15. janito/{tools/adapters → plugins/tools}/local/find_files.py +1 -1
  16. janito/{tools/adapters → plugins/tools}/local/get_file_outline/core.py +2 -2
  17. janito/{tools/adapters → plugins/tools}/local/move_file.py +1 -1
  18. janito/{tools/adapters → plugins/tools}/local/open_html_in_browser.py +1 -1
  19. janito/{tools/adapters → plugins/tools}/local/open_url.py +1 -1
  20. janito/{tools/adapters → plugins/tools}/local/python_code_run.py +1 -1
  21. janito/{tools/adapters → plugins/tools}/local/python_command_run.py +1 -1
  22. janito/{tools/adapters → plugins/tools}/local/python_file_run.py +1 -1
  23. janito/{tools/adapters → plugins/tools}/local/read_chart.py +1 -1
  24. janito/{tools/adapters → plugins/tools}/local/read_files.py +1 -1
  25. janito/{tools/adapters → plugins/tools}/local/remove_directory.py +1 -1
  26. janito/{tools/adapters → plugins/tools}/local/remove_file.py +1 -1
  27. janito/{tools/adapters → plugins/tools}/local/replace_text_in_file.py +2 -2
  28. janito/{tools/adapters → plugins/tools}/local/run_bash_command.py +1 -1
  29. janito/{tools/adapters → plugins/tools}/local/run_powershell_command.py +1 -1
  30. janito/{tools/adapters → plugins/tools}/local/search_text/core.py +2 -2
  31. janito/{tools/adapters → plugins/tools}/local/show_image.py +1 -1
  32. janito/{tools/adapters → plugins/tools}/local/show_image_grid.py +1 -1
  33. janito/plugins/tools/local/validate_file_syntax/__init__.py +1 -0
  34. janito/plugins/tools/local/validate_file_syntax/core.py +119 -0
  35. janito/plugins/tools/local/validate_file_syntax/txt_validator.py +28 -0
  36. janito/{tools/adapters → plugins/tools}/local/view_file.py +1 -1
  37. janito/tools/__init__.py +2 -2
  38. janito/tools/inspect_registry.py +1 -1
  39. janito/tools/tool_base.py +8 -1
  40. {janito-3.8.0.dist-info → janito-3.9.0.dist-info}/METADATA +14 -14
  41. {janito-3.8.0.dist-info → janito-3.9.0.dist-info}/RECORD +67 -63
  42. /janito/{tools/adapters/local → plugins/core/filemanager/tools}/validate_file_syntax/__init__.py +0 -0
  43. /janito/{tools/adapters → plugins/tools}/__init__.py +0 -0
  44. /janito/{tools/adapters → plugins/tools}/local/__init__.py +0 -0
  45. /janito/{tools/adapters → plugins/tools}/local/get_file_outline/__init__.py +0 -0
  46. /janito/{tools/adapters → plugins/tools}/local/get_file_outline/java_outline.py +0 -0
  47. /janito/{tools/adapters → plugins/tools}/local/get_file_outline/markdown_outline.py +0 -0
  48. /janito/{tools/adapters → plugins/tools}/local/get_file_outline/python_outline.py +0 -0
  49. /janito/{tools/adapters → plugins/tools}/local/get_file_outline/search_outline.py +0 -0
  50. /janito/{tools/adapters → plugins/tools}/local/search_text/__init__.py +0 -0
  51. /janito/{tools/adapters → plugins/tools}/local/search_text/match_lines.py +0 -0
  52. /janito/{tools/adapters → plugins/tools}/local/search_text/pattern_utils.py +0 -0
  53. /janito/{tools/adapters → plugins/tools}/local/search_text/traverse_directory.py +0 -0
  54. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/css_validator.py +0 -0
  55. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/html_validator.py +0 -0
  56. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/jinja2_validator.py +0 -0
  57. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/js_validator.py +0 -0
  58. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/json_validator.py +0 -0
  59. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/markdown_validator.py +0 -0
  60. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/ps1_validator.py +0 -0
  61. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/python_validator.py +0 -0
  62. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/xml_validator.py +0 -0
  63. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/yaml_validator.py +0 -0
  64. {janito-3.8.0.dist-info → janito-3.9.0.dist-info}/WHEEL +0 -0
  65. {janito-3.8.0.dist-info → janito-3.9.0.dist-info}/entry_points.txt +0 -0
  66. {janito-3.8.0.dist-info → janito-3.9.0.dist-info}/licenses/LICENSE +0 -0
  67. {janito-3.8.0.dist-info → janito-3.9.0.dist-info}/top_level.txt +0 -0
@@ -53,7 +53,7 @@ def _print_tools_table(console, title, tools_info):
53
53
 
54
54
 
55
55
  def handle_list_tools(args=None):
56
- from janito.tools.adapters.local.adapter import LocalToolsAdapter
56
+ from janito.plugins.tools.local.adapter import LocalToolsAdapter
57
57
  import janito.tools # Ensure all tools are registered
58
58
  from janito.tools.tool_base import ToolPermissions
59
59
 
janito/cli/prompt_core.py CHANGED
@@ -14,7 +14,7 @@ from janito.driver_events import (
14
14
  RequestStatus,
15
15
  RateLimitRetry,
16
16
  )
17
- from janito.tools.tool_events import ToolCallError
17
+ from janito.tools.tool_events import ToolCallError, ToolCallStarted
18
18
  import threading
19
19
  from janito.cli.verbose_output import print_verbose_header
20
20
  from janito.event_bus import event_bus as global_event_bus
@@ -52,8 +52,10 @@ class PromptHandler:
52
52
  def _handle_inner_event(self, inner_event, on_event, status):
53
53
  if on_event:
54
54
  on_event(inner_event)
55
- from janito.tools.tool_events import ToolCallFinished
55
+ from janito.tools.tool_events import ToolCallFinished, ToolCallStarted
56
56
 
57
+ if isinstance(inner_event, ToolCallStarted):
58
+ return self._handle_tool_call_started(inner_event, status)
57
59
  if isinstance(inner_event, ToolCallFinished):
58
60
  return self._handle_tool_call_finished(inner_event)
59
61
  if isinstance(inner_event, RateLimitRetry):
@@ -76,6 +78,14 @@ class PromptHandler:
76
78
  )
77
79
  return None
78
80
 
81
+ def _handle_tool_call_started(self, inner_event, status):
82
+ """Handle ToolCallStarted event - pause the timer when ask_user tool is called."""
83
+ if hasattr(inner_event, 'tool_name') and inner_event.tool_name == 'ask_user':
84
+ # Pause the status timer by clearing the status
85
+ if status:
86
+ status.update("")
87
+ return None
88
+
79
89
  def _handle_tool_call_finished(self, inner_event):
80
90
  if hasattr(self.args, "verbose_tools") and self.args.verbose_tools:
81
91
  self.console.print(
@@ -207,7 +217,42 @@ class PromptHandler:
207
217
  """
208
218
  try:
209
219
  self._print_verbose_debug("Calling agent.chat()...")
210
- final_event = self.agent.chat(prompt=user_prompt)
220
+
221
+ # Show waiting status with elapsed time
222
+ start_time = time.time()
223
+
224
+ # Get provider and model info for status display
225
+ provider_name = self.agent.get_provider_name() if hasattr(self.agent, 'get_provider_name') else 'LLM'
226
+ model_name = self.agent.get_model_name() if hasattr(self.agent, 'get_model_name') else 'unknown'
227
+
228
+ status = Status(f"[bold blue]Waiting for {provider_name} (model: {model_name})...[/bold blue]")
229
+
230
+ # Thread coordination event
231
+ stop_updater = threading.Event()
232
+
233
+ def update_status():
234
+ elapsed = time.time() - start_time
235
+ status.update(f"[bold blue]Waiting for {provider_name} (model: {model_name})... ({elapsed:.1f}s)[/bold blue]")
236
+
237
+ # Start status display and update timer
238
+ with status:
239
+ # Update status every second in a separate thread
240
+ def status_updater():
241
+ while not stop_updater.is_set():
242
+ update_status()
243
+ stop_updater.wait(1.0) # Wait for 1 second or until stopped
244
+
245
+ updater_thread = threading.Thread(target=status_updater, daemon=True)
246
+ updater_thread.start()
247
+
248
+ try:
249
+ final_event = self.agent.chat(prompt=user_prompt)
250
+ finally:
251
+ # Signal the updater thread to stop
252
+ stop_updater.set()
253
+ # Wait a bit for the thread to clean up
254
+ updater_thread.join(timeout=0.1)
255
+
211
256
  if hasattr(self.agent, "set_latest_event"):
212
257
  self.agent.set_latest_event(final_event)
213
258
  self.agent.last_event = final_event
@@ -74,8 +74,16 @@ class RichTerminalReporter(EventHandlerBase):
74
74
  """
75
75
  Clears the entire current line in the terminal and returns the cursor to column 1.
76
76
  """
77
- sys.stdout.write("\033[2K\r")
78
- sys.stdout.flush()
77
+ # Use raw ANSI escape sequences but write directly to the underlying file
78
+ # to bypass Rich's escaping/interpretation
79
+ if hasattr(self.console, 'file') and hasattr(self.console.file, 'write'):
80
+ self.console.file.write("\r\033[2K")
81
+ self.console.file.flush()
82
+ else:
83
+ # Fallback to sys.stdout if console.file is not available
84
+ import sys
85
+ sys.stdout.write("\r\033[2K")
86
+ sys.stdout.flush()
79
87
 
80
88
  def on_RequestFinished(self, event):
81
89
  self.delete_current_line()
janito/llm/agent.py CHANGED
@@ -183,6 +183,9 @@ class LLMAgent:
183
183
  elapsed = 0.0
184
184
  if getattr(self, "verbose_agent", False):
185
185
  print("[agent] [DEBUG] Waiting for event from output_queue...")
186
+ # Show initial wait message
187
+ if getattr(self, "verbose_agent", False):
188
+ print(f"[agent] [DEBUG] Starting to wait for LLM response... (timeout: {max_wait_time}s)")
186
189
  # Let KeyboardInterrupt propagate to caller
187
190
  return self._poll_for_event(poll_timeout, max_wait_time)
188
191
 
@@ -197,6 +200,9 @@ class LLMAgent:
197
200
  print(error_msg)
198
201
  print("[DEBUG] Exiting _process_next_response due to timeout")
199
202
  return None, False
203
+ # Show elapsed time info while waiting
204
+ if getattr(self, "verbose_agent", False):
205
+ print(f"[agent] [DEBUG] Waiting for LLM response... ({elapsed:.1f}s elapsed)")
200
206
  continue
201
207
  if getattr(self, "verbose_agent", False):
202
208
  print(f"[agent] [DEBUG] Received event from output_queue: {event}")
@@ -3,9 +3,9 @@ from janito.tools.path_utils import expand_path
3
3
  from janito.i18n import tr
4
4
  from janito.tools.tool_base import ToolBase, ToolPermissions
5
5
  from janito.report_events import ReportAction
6
- from janito.tools.adapters.local.adapter import register_local_tool
6
+ from janito.plugins.tools.local.adapter import register_local_tool
7
7
  from janito.tools.tool_utils import display_path
8
- from janito.tools.adapters.local.adapter import register_local_tool as register_tool
8
+ from janito.plugins.tools.local.adapter import register_local_tool as register_tool
9
9
 
10
10
  from .python_validator import validate_python
11
11
  from .json_validator import validate_json
@@ -17,6 +17,7 @@ from .markdown_validator import validate_markdown
17
17
  from .js_validator import validate_js
18
18
  from .css_validator import validate_css
19
19
  from .jinja2_validator import validate_jinja2
20
+ from .txt_validator import validate_txt
20
21
  from janito.tools.loop_protection_decorator import protect_against_loops
21
22
 
22
23
 
@@ -37,6 +38,8 @@ def _get_validator(ext):
37
38
  ".css": validate_css,
38
39
  ".j2": validate_jinja2,
39
40
  ".jinja2": validate_jinja2,
41
+ ".txt": validate_txt,
42
+ ".text": validate_txt,
40
43
  }
41
44
  return mapping.get(ext)
42
45
 
@@ -79,6 +82,7 @@ class ValidateFileSyntaxTool(ToolBase):
79
82
  - Markdown (.md)
80
83
  - JavaScript (.js)
81
84
  - Jinja2 templates (.j2, .jinja2)
85
+ - Text files (.txt, .text) [UTF-8 validation]
82
86
 
83
87
  Args:
84
88
  path (str): Path to the file to validate.
@@ -86,6 +90,7 @@ class ValidateFileSyntaxTool(ToolBase):
86
90
  str: Validation status message. Example:
87
91
  - "✅ Syntax OK"
88
92
  - "⚠️ Warning: Syntax error: <error message>"
93
+ - "⚠️ Warning: UTF-8 decoding error: <error details>"
89
94
  - "⚠️ Warning: Unsupported file extension: <ext>"
90
95
  """
91
96
 
@@ -0,0 +1,28 @@
1
+ """Text file validator for UTF-8 encoding validation."""
2
+
3
+ import codecs
4
+ from pathlib import Path
5
+
6
+
7
+ def validate_txt(path: str) -> str:
8
+ """
9
+ Validate a text file for UTF-8 encoding issues.
10
+
11
+ Args:
12
+ path (str): Path to the text file to validate
13
+
14
+ Returns:
15
+ str: Validation status message
16
+ - "✅ Syntax OK" if file is valid UTF-8
17
+ - "⚠️ Warning: UTF-8 decoding error: <error details>" if invalid
18
+ """
19
+ try:
20
+ # Try to read the file with UTF-8 encoding
21
+ with codecs.open(path, 'r', encoding='utf-8') as f:
22
+ # Read the entire file to trigger any decoding errors
23
+ f.read()
24
+ return "✅ Syntax OK"
25
+ except UnicodeDecodeError as e:
26
+ return f"⚠️ Warning: UTF-8 decoding error: {e}"
27
+ except Exception as e:
28
+ return f"⚠️ Warning: File read error: {e}"
janito/plugins/manager.py CHANGED
@@ -14,7 +14,7 @@ from .base import Plugin, PluginMetadata
14
14
  from .discovery import discover_plugins
15
15
  from .config import load_plugins_config, get_user_plugins_dir
16
16
  from .builtin import BuiltinPluginRegistry, load_builtin_plugin
17
- from janito.tools.adapters.local import LocalToolsAdapter
17
+ from janito.plugins.tools.local import LocalToolsAdapter
18
18
 
19
19
  logger = logging.getLogger(__name__)
20
20
 
@@ -207,7 +207,7 @@ def register_local_tool(tool=None):
207
207
  # Register the tool on a *fresh* adapter instance to avoid circular
208
208
  # import issues during package initialisation. This keeps behaviour
209
209
  # identical to the original implementation while still allowing
210
- # immediate use via the singleton in janito.tools.adapters.local.
210
+ # immediate use via the singleton in janito.plugins.tools.local.
211
211
  LocalToolsAdapter().register_tool(cls)
212
212
  return cls
213
213
 
@@ -1,5 +1,5 @@
1
1
  from janito.tools.tool_base import ToolBase, ToolPermissions
2
- from janito.tools.adapters.local.adapter import register_local_tool
2
+ from janito.plugins.tools.local.adapter import register_local_tool
3
3
  from janito.tools.loop_protection_decorator import protect_against_loops
4
4
 
5
5
  from rich import print as rich_print
@@ -2,7 +2,7 @@ import os
2
2
  from janito.tools.path_utils import expand_path
3
3
  import shutil
4
4
  from typing import List, Union
5
- from janito.tools.adapters.local.adapter import register_local_tool
5
+ from janito.plugins.tools.local.adapter import register_local_tool
6
6
  from janito.tools.tool_base import ToolBase, ToolPermissions
7
7
  from janito.tools.tool_utils import display_path
8
8
  from janito.report_events import ReportAction
@@ -1,4 +1,4 @@
1
- from janito.tools.adapters.local.adapter import register_local_tool
1
+ from janito.plugins.tools.local.adapter import register_local_tool
2
2
 
3
3
  from janito.tools.tool_utils import display_path
4
4
  from janito.tools.tool_base import ToolBase, ToolPermissions
@@ -1,6 +1,6 @@
1
1
  import os
2
2
  from janito.tools.path_utils import expand_path
3
- from janito.tools.adapters.local.adapter import register_local_tool
3
+ from janito.plugins.tools.local.adapter import register_local_tool
4
4
 
5
5
  from janito.tools.tool_utils import display_path
6
6
  from janito.tools.tool_base import ToolBase, ToolPermissions
@@ -8,7 +8,7 @@ from janito.report_events import ReportAction
8
8
  from janito.i18n import tr
9
9
  from janito.tools.loop_protection_decorator import protect_against_loops
10
10
 
11
- from janito.tools.adapters.local.validate_file_syntax.core import validate_file_syntax
11
+ from janito.plugins.tools.local.validate_file_syntax.core import validate_file_syntax
12
12
 
13
13
 
14
14
  @register_local_tool
@@ -30,12 +30,12 @@ class CreateFileTool(ToolBase):
30
30
  - Cross-platform path handling (Windows, macOS, Linux)
31
31
 
32
32
  Args:
33
- path (str): Target file path. Supports relative and absolute paths, with automatic
33
+ path (str, required): Target file path. Supports relative and absolute paths, with automatic
34
34
  expansion of user home directory (~) and environment variables.
35
35
  Examples: "src/main.py", "~/Documents/config.json", "$HOME/.env"
36
- content (str): File content to write. Empty string creates empty file.
36
+ content (str, optional): File content to write. Empty string creates empty file.
37
37
  Supports any text content including Unicode characters, newlines,
38
- and binary-safe text representation.
38
+ and binary-safe text representation. Default: "" (empty file)
39
39
  overwrite (bool, optional): If True, allows overwriting existing files. Default: False.
40
40
  When False, prevents accidental overwrites by checking
41
41
  file existence and showing current content. Always review
@@ -71,6 +71,10 @@ class CreateFileTool(ToolBase):
71
71
  ✅ Created file 2 lines.
72
72
  ✅ Syntax OK
73
73
 
74
+ Creating empty file:
75
+ >>> create_file("empty.txt", "")
76
+ ✅ Created file 0 lines.
77
+
74
78
  Overwrite protection:
75
79
  >>> create_file("existing.txt", "new content")
76
80
  ❗ Cannot create file: file already exists at 'existing.txt'.
@@ -85,7 +89,7 @@ class CreateFileTool(ToolBase):
85
89
  tool_name = "create_file"
86
90
 
87
91
  @protect_against_loops(max_calls=5, time_window=10.0, key_field="path")
88
- def run(self, path: str, content: str, overwrite: bool = False) -> str:
92
+ def run(self, path: str, content: str = "", overwrite: bool = False) -> str:
89
93
  path = expand_path(path)
90
94
  disp_path = display_path(path)
91
95
  if os.path.exists(path) and not overwrite:
@@ -1,9 +1,9 @@
1
1
  from janito.tools.tool_base import ToolBase, ToolPermissions
2
2
  from janito.report_events import ReportAction
3
- from janito.tools.adapters.local.adapter import register_local_tool
3
+ from janito.plugins.tools.local.adapter import register_local_tool
4
4
  from janito.i18n import tr
5
5
  import shutil
6
- from janito.tools.adapters.local.validate_file_syntax.core import validate_file_syntax
6
+ from janito.plugins.tools.local.validate_file_syntax.core import validate_file_syntax
7
7
 
8
8
 
9
9
  @register_local_tool
@@ -5,7 +5,7 @@ import json
5
5
  from pathlib import Path
6
6
  from bs4 import BeautifulSoup
7
7
  from typing import Dict, Any, Optional
8
- from janito.tools.adapters.local.adapter import register_local_tool
8
+ from janito.plugins.tools.local.adapter import register_local_tool
9
9
  from janito.tools.tool_base import ToolBase, ToolPermissions
10
10
  from janito.report_events import ReportAction
11
11
  from janito.i18n import tr
@@ -33,7 +33,7 @@ class FetchUrlTool(ToolBase):
33
33
 
34
34
  **Error Cache Behavior:**
35
35
  - HTTP 403 errors: Cached for 24 hours (more permanent)
36
- - HTTP 404 errors: Cached for 1 hour (temporary)
36
+ - HTTP 404 errors: Cached for 1 hour (shorter duration)
37
37
  - Other 4xx errors: Cached for 30 minutes
38
38
  - 5xx errors: Not cached (retried on each request)
39
39
 
@@ -151,7 +151,7 @@ class FetchUrlTool(ToolBase):
151
151
  # Cache 403 errors for 24 hours (more permanent)
152
152
  expiration_time = 24 * 3600
153
153
  elif entry["status_code"] == 404:
154
- # Cache 404 errors for 1 hour (more temporary)
154
+ # Cache 404 errors for 1 hour (shorter duration)
155
155
  expiration_time = 3600
156
156
  else:
157
157
  # Cache other 4xx errors for 30 minutes
@@ -1,6 +1,6 @@
1
1
  from janito.tools.tool_base import ToolBase, ToolPermissions
2
2
  from janito.report_events import ReportAction
3
- from janito.tools.adapters.local.adapter import register_local_tool
3
+ from janito.plugins.tools.local.adapter import register_local_tool
4
4
  from janito.tools.tool_utils import pluralize, display_path
5
5
  from janito.dir_walk_utils import walk_dir_with_gitignore
6
6
  from janito.i18n import tr
@@ -1,4 +1,4 @@
1
- from janito.tools.adapters.local.adapter import register_local_tool
1
+ from janito.plugins.tools.local.adapter import register_local_tool
2
2
  from .python_outline import parse_python_outline
3
3
  from .markdown_outline import parse_markdown_outline
4
4
  from janito.formatting import OutlineFormatter
@@ -10,7 +10,7 @@ from janito.report_events import ReportAction
10
10
  from janito.tools.tool_utils import display_path, pluralize
11
11
  from janito.i18n import tr
12
12
 
13
- from janito.tools.adapters.local.adapter import register_local_tool as register_tool
13
+ from janito.plugins.tools.local.adapter import register_local_tool as register_tool
14
14
  from janito.tools.loop_protection_decorator import protect_against_loops
15
15
 
16
16
 
@@ -1,7 +1,7 @@
1
1
  import os
2
2
  from janito.tools.path_utils import expand_path
3
3
  import shutil
4
- from janito.tools.adapters.local.adapter import register_local_tool
4
+ from janito.plugins.tools.local.adapter import register_local_tool
5
5
  from janito.tools.tool_utils import display_path
6
6
  from janito.tools.tool_base import ToolBase, ToolPermissions
7
7
  from janito.report_events import ReportAction
@@ -1,6 +1,6 @@
1
1
  import os
2
2
  import webbrowser
3
- from janito.tools.adapters.local.adapter import register_local_tool
3
+ from janito.plugins.tools.local.adapter import register_local_tool
4
4
  from janito.tools.tool_base import ToolBase, ToolPermissions
5
5
  from janito.report_events import ReportAction
6
6
  from janito.i18n import tr
@@ -1,5 +1,5 @@
1
1
  import webbrowser
2
- from janito.tools.adapters.local.adapter import register_local_tool
2
+ from janito.plugins.tools.local.adapter import register_local_tool
3
3
  from janito.tools.tool_base import ToolBase, ToolPermissions
4
4
  from janito.report_events import ReportAction
5
5
  from janito.i18n import tr
@@ -5,7 +5,7 @@ import tempfile
5
5
  import threading
6
6
  from janito.tools.tool_base import ToolBase, ToolPermissions
7
7
  from janito.report_events import ReportAction
8
- from janito.tools.adapters.local.adapter import register_local_tool
8
+ from janito.plugins.tools.local.adapter import register_local_tool
9
9
  from janito.i18n import tr
10
10
 
11
11
 
@@ -5,7 +5,7 @@ import tempfile
5
5
  import threading
6
6
  from janito.tools.tool_base import ToolBase, ToolPermissions
7
7
  from janito.report_events import ReportAction
8
- from janito.tools.adapters.local.adapter import register_local_tool
8
+ from janito.plugins.tools.local.adapter import register_local_tool
9
9
  from janito.i18n import tr
10
10
 
11
11
 
@@ -5,7 +5,7 @@ import tempfile
5
5
  import threading
6
6
  from janito.tools.tool_base import ToolBase, ToolPermissions
7
7
  from janito.report_events import ReportAction
8
- from janito.tools.adapters.local.adapter import register_local_tool
8
+ from janito.plugins.tools.local.adapter import register_local_tool
9
9
  from janito.i18n import tr
10
10
 
11
11
 
@@ -1,6 +1,6 @@
1
1
  from janito.tools.tool_base import ToolBase, ToolPermissions
2
2
  from janito.report_events import ReportAction
3
- from janito.tools.adapters.local.adapter import register_local_tool
3
+ from janito.plugins.tools.local.adapter import register_local_tool
4
4
  from janito.tools.tool_utils import display_path
5
5
  from janito.i18n import tr
6
6
  import json
@@ -1,6 +1,6 @@
1
1
  from janito.tools.tool_base import ToolBase, ToolPermissions
2
2
  from janito.report_events import ReportAction
3
- from janito.tools.adapters.local.adapter import register_local_tool
3
+ from janito.plugins.tools.local.adapter import register_local_tool
4
4
  from janito.tools.tool_utils import pluralize
5
5
  from janito.i18n import tr
6
6
  from janito.tools.loop_protection_decorator import protect_against_loops
@@ -1,6 +1,6 @@
1
1
  from janito.tools.tool_base import ToolBase, ToolPermissions
2
2
  from janito.report_events import ReportAction
3
- from janito.tools.adapters.local.adapter import register_local_tool
3
+ from janito.plugins.tools.local.adapter import register_local_tool
4
4
  from janito.tools.tool_utils import pluralize, display_path
5
5
  from janito.i18n import tr
6
6
  import shutil
@@ -1,7 +1,7 @@
1
1
  import os
2
2
  from janito.tools.path_utils import expand_path
3
3
  import shutil
4
- from janito.tools.adapters.local.adapter import register_local_tool
4
+ from janito.plugins.tools.local.adapter import register_local_tool
5
5
 
6
6
  from janito.tools.tool_utils import display_path
7
7
  from janito.tools.tool_base import ToolBase, ToolPermissions
@@ -1,10 +1,10 @@
1
1
  from janito.tools.tool_base import ToolBase, ToolPermissions
2
2
  from janito.report_events import ReportAction
3
- from janito.tools.adapters.local.adapter import register_local_tool
3
+ from janito.plugins.tools.local.adapter import register_local_tool
4
4
  from janito.i18n import tr
5
5
  import shutil
6
6
  import re
7
- from janito.tools.adapters.local.validate_file_syntax.core import validate_file_syntax
7
+ from janito.plugins.tools.local.validate_file_syntax.core import validate_file_syntax
8
8
 
9
9
 
10
10
  @register_local_tool
@@ -1,6 +1,6 @@
1
1
  from janito.tools.tool_base import ToolBase, ToolPermissions
2
2
  from janito.report_events import ReportAction
3
- from janito.tools.adapters.local.adapter import register_local_tool
3
+ from janito.plugins.tools.local.adapter import register_local_tool
4
4
  from janito.i18n import tr
5
5
  import subprocess
6
6
  import tempfile
@@ -1,6 +1,6 @@
1
1
  from janito.tools.tool_base import ToolBase, ToolPermissions
2
2
  from janito.report_events import ReportAction
3
- from janito.tools.adapters.local.adapter import register_local_tool
3
+ from janito.plugins.tools.local.adapter import register_local_tool
4
4
  from janito.i18n import tr
5
5
  import subprocess
6
6
  import os
@@ -1,6 +1,6 @@
1
1
  from janito.tools.tool_base import ToolBase, ToolPermissions
2
2
  from janito.report_events import ReportAction
3
- from janito.tools.adapters.local.adapter import register_local_tool
3
+ from janito.plugins.tools.local.adapter import register_local_tool
4
4
  from janito.tools.tool_utils import pluralize, display_path
5
5
  from janito.i18n import tr
6
6
  import os
@@ -11,7 +11,7 @@ from .traverse_directory import traverse_directory
11
11
  from janito.tools.loop_protection_decorator import protect_against_loops
12
12
 
13
13
 
14
- from janito.tools.adapters.local.adapter import register_local_tool as register_tool
14
+ from janito.plugins.tools.local.adapter import register_local_tool as register_tool
15
15
 
16
16
 
17
17
  @register_tool
@@ -1,6 +1,6 @@
1
1
  from janito.tools.tool_base import ToolBase, ToolPermissions
2
2
  from janito.report_events import ReportAction
3
- from janito.tools.adapters.local.adapter import register_local_tool
3
+ from janito.plugins.tools.local.adapter import register_local_tool
4
4
  from janito.i18n import tr
5
5
  from janito.tools.loop_protection_decorator import protect_against_loops
6
6
 
@@ -1,6 +1,6 @@
1
1
  from janito.tools.tool_base import ToolBase, ToolPermissions
2
2
  from janito.report_events import ReportAction
3
- from janito.tools.adapters.local.adapter import register_local_tool
3
+ from janito.plugins.tools.local.adapter import register_local_tool
4
4
  from janito.i18n import tr
5
5
  from janito.tools.loop_protection_decorator import protect_against_loops
6
6
  from typing import Sequence
@@ -0,0 +1 @@
1
+ # Validation syntax package
@@ -0,0 +1,119 @@
1
+ import os
2
+ from janito.tools.path_utils import expand_path
3
+ from janito.i18n import tr
4
+ from janito.tools.tool_base import ToolBase, ToolPermissions
5
+ from janito.report_events import ReportAction
6
+ from janito.plugins.tools.local.adapter import register_local_tool
7
+ from janito.tools.tool_utils import display_path
8
+ from janito.plugins.tools.local.adapter import register_local_tool as register_tool
9
+
10
+ from .python_validator import validate_python
11
+ from .json_validator import validate_json
12
+ from .yaml_validator import validate_yaml
13
+ from .ps1_validator import validate_ps1
14
+ from .xml_validator import validate_xml
15
+ from .html_validator import validate_html
16
+ from .markdown_validator import validate_markdown
17
+ from .js_validator import validate_js
18
+ from .css_validator import validate_css
19
+ from .jinja2_validator import validate_jinja2
20
+ from .txt_validator import validate_txt
21
+ from janito.tools.loop_protection_decorator import protect_against_loops
22
+
23
+
24
+ def _get_validator(ext):
25
+ """Return the appropriate validator function for the file extension."""
26
+ mapping = {
27
+ ".py": validate_python,
28
+ ".pyw": validate_python,
29
+ ".json": validate_json,
30
+ ".yml": validate_yaml,
31
+ ".yaml": validate_yaml,
32
+ ".ps1": validate_ps1,
33
+ ".xml": validate_xml,
34
+ ".html": validate_html,
35
+ ".htm": validate_html,
36
+ ".md": validate_markdown,
37
+ ".js": validate_js,
38
+ ".css": validate_css,
39
+ ".j2": validate_jinja2,
40
+ ".jinja2": validate_jinja2,
41
+ ".txt": validate_txt,
42
+ ".text": validate_txt,
43
+ }
44
+ return mapping.get(ext)
45
+
46
+
47
+ def _handle_validation_error(e, report_warning):
48
+ msg = tr("⚠️ Warning: Syntax error: {error}", error=e)
49
+ if report_warning:
50
+ report_warning(msg)
51
+ return msg
52
+
53
+
54
+ def validate_file_syntax(
55
+ path: str, report_info=None, report_warning=None, report_success=None
56
+ ) -> str:
57
+ ext = os.path.splitext(path)[1].lower()
58
+ validator = _get_validator(ext)
59
+ try:
60
+ if validator:
61
+ return validator(path)
62
+ else:
63
+ msg = tr("⚠️ Warning: Unsupported file extension: {ext}", ext=ext)
64
+ if report_warning:
65
+ report_warning(msg)
66
+ return msg
67
+ except Exception as e:
68
+ return _handle_validation_error(e, report_warning)
69
+
70
+
71
+ class ValidateFileSyntaxTool(ToolBase):
72
+ """
73
+ Validate a file for syntax issues.
74
+
75
+ Supported types:
76
+ - Python (.py, .pyw)
77
+ - JSON (.json)
78
+ - YAML (.yml, .yaml)
79
+ - PowerShell (.ps1)
80
+ - XML (.xml)
81
+ - HTML (.html, .htm) [lxml]
82
+ - Markdown (.md)
83
+ - JavaScript (.js)
84
+ - Jinja2 templates (.j2, .jinja2)
85
+ - Text files (.txt, .text) [UTF-8 validation]
86
+
87
+ Args:
88
+ path (str): Path to the file to validate.
89
+ Returns:
90
+ str: Validation status message. Example:
91
+ - "✅ Syntax OK"
92
+ - "⚠️ Warning: Syntax error: <error message>"
93
+ - "⚠️ Warning: UTF-8 decoding error: <error details>"
94
+ - "⚠️ Warning: Unsupported file extension: <ext>"
95
+ """
96
+
97
+ permissions = ToolPermissions(read=True)
98
+ tool_name = "validate_file_syntax"
99
+
100
+ @protect_against_loops(max_calls=5, time_window=10.0, key_field="path")
101
+ def run(self, path: str) -> str:
102
+ path = expand_path(path)
103
+ disp_path = display_path(path)
104
+ self.report_action(
105
+ tr(
106
+ "🔎 Validate syntax for file '{disp_path}' ...",
107
+ disp_path=disp_path,
108
+ ),
109
+ ReportAction.READ,
110
+ )
111
+ result = validate_file_syntax(
112
+ path,
113
+ report_warning=self.report_warning,
114
+ report_success=self.report_success,
115
+ )
116
+ if result.startswith("✅"):
117
+ self.report_success(result, ReportAction.READ)
118
+
119
+ return result
@@ -0,0 +1,28 @@
1
+ """Text file validator for UTF-8 encoding validation."""
2
+
3
+ import codecs
4
+ from pathlib import Path
5
+
6
+
7
+ def validate_txt(path: str) -> str:
8
+ """
9
+ Validate a text file for UTF-8 encoding issues.
10
+
11
+ Args:
12
+ path (str): Path to the text file to validate
13
+
14
+ Returns:
15
+ str: Validation status message
16
+ - "✅ Syntax OK" if file is valid UTF-8
17
+ - "⚠️ Warning: UTF-8 decoding error: <error details>" if invalid
18
+ """
19
+ try:
20
+ # Try to read the file with UTF-8 encoding
21
+ with codecs.open(path, 'r', encoding='utf-8') as f:
22
+ # Read the entire file to trigger any decoding errors
23
+ f.read()
24
+ return "✅ Syntax OK"
25
+ except UnicodeDecodeError as e:
26
+ return f"⚠️ Warning: UTF-8 decoding error: {e}"
27
+ except Exception as e:
28
+ return f"⚠️ Warning: File read error: {e}"
@@ -1,6 +1,6 @@
1
1
  from janito.tools.tool_base import ToolBase, ToolPermissions
2
2
  from janito.report_events import ReportAction
3
- from janito.tools.adapters.local.adapter import register_local_tool
3
+ from janito.plugins.tools.local.adapter import register_local_tool
4
4
  from janito.tools.tool_utils import pluralize
5
5
  from janito.i18n import tr
6
6
  from janito.tools.loop_protection_decorator import protect_against_loops
janito/tools/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- from janito.tools.adapters.local import (
1
+ from janito.plugins.tools.local import (
2
2
  local_tools_adapter as _internal_local_tools_adapter,
3
3
  LocalToolsAdapter,
4
4
  )
@@ -11,7 +11,7 @@ def get_local_tools_adapter(workdir=None, allowed_permissions=None):
11
11
  if workdir is not None and not os.path.exists(workdir):
12
12
  os.makedirs(workdir, exist_ok=True)
13
13
  # Permissions are now managed globally; ignore allowed_permissions argument except for backward compatibility
14
- # Reuse the singleton adapter defined in janito.tools.adapters.local to maintain tool registrations
14
+ # Reuse the singleton adapter defined in janito.plugins.tools.local to maintain tool registrations
15
15
  registry = _internal_local_tools_adapter
16
16
  # Change workdir if requested
17
17
  if workdir is not None:
@@ -1,6 +1,6 @@
1
1
  def check_tools_registry():
2
2
  # Import and use the singleton tools adapter instance
3
- from janito.tools.adapters.local import local_tools_adapter
3
+ from janito.plugins.tools.local import local_tools_adapter
4
4
 
5
5
  print("Available tool names:", local_tools_adapter.list_tools())
6
6
  print(
janito/tools/tool_base.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from janito.report_events import ReportEvent, ReportSubtype, ReportAction
2
2
  from janito.event_bus.bus import event_bus as default_event_bus
3
3
 
4
-
4
+ import inspect
5
5
  from collections import namedtuple
6
6
 
7
7
 
@@ -112,3 +112,10 @@ class ToolBase:
112
112
 
113
113
  def run(self, *args, **kwargs):
114
114
  raise NotImplementedError("Subclasses must implement the run method.")
115
+
116
+ def get_signature(self):
117
+ """
118
+ Return the function signature for this tool's run method.
119
+ This is used for introspection and validation.
120
+ """
121
+ return inspect.signature(self.run)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: janito
3
- Version: 3.8.0
3
+ Version: 3.9.0
4
4
  Summary: A new Python package called janito.
5
5
  Author-email: João Pinto <janito@ikignosis.org>
6
6
  Project-URL: Homepage, https://github.com/ikignosis/janito
@@ -33,30 +33,30 @@ Provides-Extra: coder
33
33
  Requires-Dist: janito-coder; extra == "coder"
34
34
  Dynamic: license-file
35
35
 
36
- # nctl
36
+ # Janito
37
37
 
38
38
  ```bash
39
- $ nctl --help
40
- Usage: nctl <command>
39
+ $ janito --help
40
+ Usage: janito <command>
41
41
 
42
42
  Interact with Nine API resources. See https://docs.nineapis.ch for the full API docs.
43
43
 
44
- Run "nctl <command> --help" for more information on a command.
44
+ Run "janito <command> --help" for more information on a command.
45
45
  ```
46
46
 
47
47
  ## Setup
48
48
 
49
49
  ```bash
50
50
  # If you have go already installed
51
- go install github.com/ninech/nctl@latest
51
+ go install github.com/ninech/janito@latest
52
52
 
53
53
  # Homebrew
54
- brew install ninech/taps/nctl
54
+ brew install ninech/taps/janito
55
55
 
56
56
  # Debian/Ubuntu
57
57
  echo "deb [trusted=yes] https://repo.nine.ch/deb/ /" | sudo tee /etc/apt/sources.list.d/repo.nine.ch.list
58
58
  sudo apt-get update
59
- sudo apt-get install nctl
59
+ sudo apt-get install janito
60
60
 
61
61
  # Fedora/RHEL
62
62
  cat <<EOF > /etc/yum.repos.d/repo.nine.ch.repo
@@ -66,19 +66,19 @@ baseurl=https://repo.nine.ch/yum/
66
66
  enabled=1
67
67
  gpgcheck=0
68
68
  EOF
69
- dnf install nctl
69
+ dnf install janito
70
70
 
71
71
  # Arch
72
72
  # Install yay: https://github.com/Jguer/yay#binary
73
73
  yay --version
74
- yay -S nctl-bin
74
+ yay -S janito-bin
75
75
  ```
76
76
 
77
- For Windows users, nctl is also built for arm64 and amd64. You can download the
78
- latest exe file from the [releases](https://github.com/ninech/nctl/releases) and
77
+ For Windows users, janito is also built for arm64 and amd64. You can download the
78
+ latest exe file from the [releases](https://github.com/ninech/janito/releases) and
79
79
  install it.
80
80
 
81
81
  ## Getting started
82
82
 
83
- * login to the API using `nctl auth login`
84
- * run `nctl --help` to get a list of all available commands
83
+ * login to the API using `janito auth login`
84
+ * run `janito --help` to get a list of all available commands
@@ -31,10 +31,10 @@ janito/cli/config.py,sha256=HkZ14701HzIqrvaNyDcDhGlVHfpX_uHlLp2rHmhRm_k,872
31
31
  janito/cli/console.py,sha256=gJolqzWL7jEPLxeuH-CwBDRFpXt976KdZOEAB2tdBDs,64
32
32
  janito/cli/main.py,sha256=s5odou0txf8pzTf1ADk2yV7T5m8B6cejJ81e7iu776U,312
33
33
  janito/cli/main_cli.py,sha256=FXpoybaEbDRlK5-oMOMlcdM7TpVfnOdr6-mOkgJHeTo,16648
34
- janito/cli/prompt_core.py,sha256=F68J4Xl6jZMYFN4oBBYZFj15Jp-HTYoLub4bw2XpNRU,11648
34
+ janito/cli/prompt_core.py,sha256=wXUddUm2Us0D3k6xBNqiE4JjyAUdZuDivZirBRFyb5g,13880
35
35
  janito/cli/prompt_handler.py,sha256=SnPTlL64noeAMGlI08VBDD5IDD8jlVMIYA4-fS8zVLg,215
36
36
  janito/cli/prompt_setup.py,sha256=s48gvNfZhKjsEhf4EzL1tKIGm4wDidPMDvlM6TAPYes,2116
37
- janito/cli/rich_terminal_reporter.py,sha256=Hitf5U13gncad4GPVAcDMfdSwlfzQzOn9KdeX4TjTWU,6806
37
+ janito/cli/rich_terminal_reporter.py,sha256=UILH8LmPUl7Ss9-PVYMFlb16dBpnDLVsf8hctS5-Vv0,7231
38
38
  janito/cli/utils.py,sha256=plCQiDKIf3V8mFhhX5H9-MF2W86i-xRdWf8Xi117Z0w,677
39
39
  janito/cli/verbose_output.py,sha256=wY_B4of5e8Vv7w1fRwOZzNGU2JqbMdcFnGjtEr4hLus,7686
40
40
  janito/cli/chat_mode/bindings.py,sha256=odjc5_-YW1t2FRhBUNRNoBMoQIg5sMz3ktV7xG0ADFU,975
@@ -86,7 +86,7 @@ janito/cli/cli_commands/list_plugins.py,sha256=Lv-M6EAFiqnj0tl9Bq23s162t--81AIs2
86
86
  janito/cli/cli_commands/list_profiles.py,sha256=O4k6U9iCEeNH3lM-NP_XX_E9W0h__hheLSn23241dkA,3538
87
87
  janito/cli/cli_commands/list_providers.py,sha256=oilrBjNL5mot1nz45XQQY6oeiSxoNvphhQYspNcEJpw,391
88
88
  janito/cli/cli_commands/list_providers_region.py,sha256=qrMj_gtgEMty8UH0P_O5SgWCVJ9ZKxGUp_GdsE4_EH4,2548
89
- janito/cli/cli_commands/list_tools.py,sha256=JFRdlhPeA3BzhJ2PkjIt3u137IJoNc-vYSjUuPlaOXw,3593
89
+ janito/cli/cli_commands/list_tools.py,sha256=lHPbwXxPysxnDqatZtFOD7S49nYinE5GGgav2UT_x0E,3592
90
90
  janito/cli/cli_commands/model_selection.py,sha256=ANWtwC5glZkGMdaNtARDbEG3QmuBUcDLVxzzC5jeBNo,1643
91
91
  janito/cli/cli_commands/model_utils.py,sha256=4t2ZN8DYA8jxluXHiiliV8gMbF_90nKGtgU9VO4-gMg,5088
92
92
  janito/cli/cli_commands/ping_providers.py,sha256=hetZAKKZzQYRpRDT5OvRTOe4jYUVNZGjo8gFoyeRA3I,1921
@@ -122,7 +122,7 @@ janito/i18n/messages.py,sha256=fBuwOTFoygyHPkYphm6Y0r1iE8497Z4iryVAmPhMEkg,1851
122
122
  janito/i18n/pt.py,sha256=NlTgpDSftUfFG7FGbs7TK54vQlJVMyaZDHGcWjelwMc,4168
123
123
  janito/llm/README.md,sha256=6GRqCu_a9va5HCB1YqNqbshyWKFyAGlnXugrjom-xj8,1213
124
124
  janito/llm/__init__.py,sha256=dpyVH51qVRCw-PDyAFLAxq0zd4jl5MDcuV6Cri0D-dQ,134
125
- janito/llm/agent.py,sha256=T0JfeMoOudTWsHwWCcaocrHyq9k0TvkL4_YePlXvZfo,21269
125
+ janito/llm/agent.py,sha256=Jlpr3_j4K3xv1MztPPHEbmpvmlUpQPnhY_ewYioGG8U,21676
126
126
  janito/llm/auth.py,sha256=8Dl_orUEPhn2X6XjkO2Nr-j1HFT2YDxk1qJl9hSFI88,2286
127
127
  janito/llm/auth_utils.py,sha256=7GH7bIScKhVWJW6ugcDrJLcYRamj5dl_l8N1rrvR4Ws,663
128
128
  janito/llm/driver.py,sha256=stiicPe_MXTuWW4q6MSwK7PCj8UZcA_30pGACu6xYUQ,10039
@@ -143,7 +143,60 @@ janito/plugins/core_loader.py,sha256=VcIwuKUaR2bvRZIFEiUHaS8YulTOKrYtvO_VhKHRpGI
143
143
  janito/plugins/core_loader_fixed.py,sha256=ZjBOU-aQCMnRXxQfFSI5caUR_IqaI0HdqOJSt-G-Lkc,3909
144
144
  janito/plugins/discovery.py,sha256=JKaoROD4Ci-k8HN1hns130mXq28ZZhQsWfTBSJoOqYc,10106
145
145
  janito/plugins/discovery_core.py,sha256=O5OccNWNyrSXGeeTk5xSG0qbsjNsajclNNCiHljFRpI,1613
146
- janito/plugins/manager.py,sha256=OyqGiZubcPgogs2u_rIV2cs_r4HNPwFZH9U25Z9g5cI,8135
146
+ janito/plugins/manager.py,sha256=eSpMjXcyNBrom-hJ-_QaaJ4Mrr_qG395-NNcK_wPk3I,8134
147
+ janito/plugins/core/filemanager/tools/validate_file_syntax/__init__.py,sha256=P53RHmas4BbHL90cMxH9m-RpMCJI8JquoJb0rpkPVVk,29
148
+ janito/plugins/core/filemanager/tools/validate_file_syntax/core.py,sha256=EoBMJ_A5mJJs7BMhOJ4gpxBd_p8q1e4597k_V5bJNjk,3940
149
+ janito/plugins/core/filemanager/tools/validate_file_syntax/txt_validator.py,sha256=5GbO_IhbOUjHM-klorS3dUKeEOfKXXIuK3T-1JjSIeU,909
150
+ janito/plugins/tools/__init__.py,sha256=XKixOKtUJs1R-rGwGDXSLVLg5-Kp090gvWbsseWT4LI,92
151
+ janito/plugins/tools/local/__init__.py,sha256=I6LtLnDTyApZrSlKcihSQqZv3gADVX781Mcj46LH7ac,2362
152
+ janito/plugins/tools/local/adapter.py,sha256=LENtKWnoHrDSnPid195R_9mSgKieNQKyH6XzaQjh7uY,8706
153
+ janito/plugins/tools/local/ask_user.py,sha256=RJGPYHUL4tbpjpkfnickJxl_KotBLTqT75JntpOXjCY,4059
154
+ janito/plugins/tools/local/copy_file.py,sha256=j7isTujW0z0zUMh3QXQES8RdWO7RhE-IHhq7oh6e1q8,3681
155
+ janito/plugins/tools/local/create_directory.py,sha256=Nkrg4a9BEdB3EE1AkjypYLKNpYoMROfZ1DvS0pOFKOs,2583
156
+ janito/plugins/tools/local/create_file.py,sha256=rWFj9M7-C8Dl4br_1ooDbabb7Q6oKwbBvUSUO9sPabA,6542
157
+ janito/plugins/tools/local/delete_text_in_file.py,sha256=K0nry8fsk4ZNjWE-nDNpYYUpumZwo9m4nND8C8TFfOQ,5085
158
+ janito/plugins/tools/local/fetch_url.py,sha256=cYOSnjiaVo9pTpGDkFKb4lUsP3x_fB2nHStf-CmZuCE,18220
159
+ janito/plugins/tools/local/find_files.py,sha256=esFwkmJN_d-GkknSjkuBRr_DOsXFQQana-o08Y7YXts,6249
160
+ janito/plugins/tools/local/move_file.py,sha256=ddl3Jj3Uq7NQ19gsT8oRX_l0qjL6c7kVcH9Qg0VCNi8,4694
161
+ janito/plugins/tools/local/open_html_in_browser.py,sha256=RUD6QOs5CjEXdFEkIhk4W4m2txI_MJw0CbO4z5t4kL0,2100
162
+ janito/plugins/tools/local/open_url.py,sha256=BBcUPBo7kyIXPsQj5xB_2dlLiSABYwEpGPLX8NNpZ6A,1551
163
+ janito/plugins/tools/local/python_code_run.py,sha256=oVU3XCuUD5lJE3SrMnslCr_zBE6HBVA1pWVjqHLQ5mM,6980
164
+ janito/plugins/tools/local/python_command_run.py,sha256=UJB5Ac0WXvzPDavYd7PC2S2U0qA_OvIkJnf2J_XPr7I,6934
165
+ janito/plugins/tools/local/python_file_run.py,sha256=wX-R4lP66LCEjFyc5hkrxI9wJgAmwI1oINP5azxxLlw,6858
166
+ janito/plugins/tools/local/read_chart.py,sha256=H4-fcgHQweAOJsvktJ7XYs39UIVJdXRZK-xhrZEX69E,10410
167
+ janito/plugins/tools/local/read_files.py,sha256=Rcke8QHU1NebNnaLsvaS81m4ZSBH0uhRGbezYN00X0E,2328
168
+ janito/plugins/tools/local/remove_directory.py,sha256=_P1VgC-bSttN-a2-VlEZ2inphG4me91jXe1OZi7bqR4,1912
169
+ janito/plugins/tools/local/remove_file.py,sha256=YbTByXAnnvlQ57y-2B2qcblmOgEJpeBrGhi4Te4-QlA,2092
170
+ janito/plugins/tools/local/replace_text_in_file.py,sha256=OIiXsqaoVOg_umHoPnDECzY7yDCG5ZrU6zHTM1lZhfc,10964
171
+ janito/plugins/tools/local/run_bash_command.py,sha256=cKE0VUJc_qefrU-VcTk_3ipViKZDLlbfGS8D0cEAHMg,7954
172
+ janito/plugins/tools/local/run_powershell_command.py,sha256=nA-8rbf2NNG6eWSUwB5YkNOpCADLa_APC9y-ouk1DMc,9312
173
+ janito/plugins/tools/local/show_image.py,sha256=mxw9UJdSrmVsznFck__X4jizya2H8-HAWndO75jNY_U,2931
174
+ janito/plugins/tools/local/show_image_grid.py,sha256=HbFJwSQonHXFnW3_URk45q4S7fS-opnojscoSe3_QGQ,2999
175
+ janito/plugins/tools/local/view_file.py,sha256=5VugCv4xBNeHNqDfUq3nE0y7Ylqg5pZAHe2i0TbNfes,7378
176
+ janito/plugins/tools/local/get_file_outline/__init__.py,sha256=OKV_BHnoD9h-vkcVoW6AHmsuDjjauHPCKNK0nVFl4sU,37
177
+ janito/plugins/tools/local/get_file_outline/core.py,sha256=E8nV5Qx7DuslRTwhONlBS1LxJJLWsE1TWeOSXMFKtFs,4609
178
+ janito/plugins/tools/local/get_file_outline/java_outline.py,sha256=_UeUY5JoQEUdlHcK8aqGTqYJl0T2KxIFXPTdwum9gKQ,1825
179
+ janito/plugins/tools/local/get_file_outline/markdown_outline.py,sha256=bXEBg0D93tEBDNy8t-wh4i7WxsxfpQ2C3dX1_rmtj08,434
180
+ janito/plugins/tools/local/get_file_outline/python_outline.py,sha256=RAcf9Vxec08lA06drYaNre5HCJ2lTzrRAskZ3rlyE-U,10326
181
+ janito/plugins/tools/local/get_file_outline/search_outline.py,sha256=bski24TpnJVf3L0TNzkx3HfvaXwttQl4EVkwk2POQOw,1348
182
+ janito/plugins/tools/local/search_text/__init__.py,sha256=FEYpF5tTtf0fiAyRGIGSn-kV-MJDkhdFIbus16mYW8Y,34
183
+ janito/plugins/tools/local/search_text/core.py,sha256=Ded2lHocjRMreq6OcXDTdgQGD4KRyI55mjeHJSeecrg,7875
184
+ janito/plugins/tools/local/search_text/match_lines.py,sha256=RLR8fZFP-Q57rY0fTENbMItmt3dJZiYX0otmGHVRjfw,2131
185
+ janito/plugins/tools/local/search_text/pattern_utils.py,sha256=D7vtAr8oT0tGV0C_UUarAXS9XQtP-MTYmmc8Yg8iVTg,2362
186
+ janito/plugins/tools/local/search_text/traverse_directory.py,sha256=EpL1qywAV0H29pm8-QsHrjKchKP4i4sRUOENVuNptCo,4000
187
+ janito/plugins/tools/local/validate_file_syntax/__init__.py,sha256=P53RHmas4BbHL90cMxH9m-RpMCJI8JquoJb0rpkPVVk,29
188
+ janito/plugins/tools/local/validate_file_syntax/core.py,sha256=EoBMJ_A5mJJs7BMhOJ4gpxBd_p8q1e4597k_V5bJNjk,3940
189
+ janito/plugins/tools/local/validate_file_syntax/css_validator.py,sha256=jE5d26C_fU9k9azujbGVISn2WIRL-Ys6de4dsCq30bo,1351
190
+ janito/plugins/tools/local/validate_file_syntax/html_validator.py,sha256=VV93BRcAeUraXHc9dUyH1cs9gRwRwO84K1-L5zbJnYU,3207
191
+ janito/plugins/tools/local/validate_file_syntax/jinja2_validator.py,sha256=lfM0SsKsFygiEp1IuLNr5jdS7XJyjCLOPw2yo9vl-pY,1763
192
+ janito/plugins/tools/local/validate_file_syntax/js_validator.py,sha256=42LvgyMVhG9c2EAaSz3J9pu-yuh1oyIvRp0wN2rHiDQ,998
193
+ janito/plugins/tools/local/validate_file_syntax/json_validator.py,sha256=muCB0-bdxk9zNulzH1It3hWpYzJC3hD8LbxCnE0P5is,150
194
+ janito/plugins/tools/local/validate_file_syntax/markdown_validator.py,sha256=k4UT88fXvtclygz-nFhCMHJL5sk5WlGD-fP_cWqWMyU,3511
195
+ janito/plugins/tools/local/validate_file_syntax/ps1_validator.py,sha256=TeIkPt08t_-w2JiKksXHHK9lJNT348ZDkWoSTzMtRrI,1152
196
+ janito/plugins/tools/local/validate_file_syntax/python_validator.py,sha256=BfCO_K18qy92m-2ZVvHsbEU5e11OPo1pO9Vz4G4616E,130
197
+ janito/plugins/tools/local/validate_file_syntax/txt_validator.py,sha256=5GbO_IhbOUjHM-klorS3dUKeEOfKXXIuK3T-1JjSIeU,909
198
+ janito/plugins/tools/local/validate_file_syntax/xml_validator.py,sha256=AijlsP_PgNuC8ZbGsC5vOTt3Jur76otQzkd_7qR0QFY,284
199
+ janito/plugins/tools/local/validate_file_syntax/yaml_validator.py,sha256=TgyI0HRL6ug_gBcWEm5TGJJuA4E34ZXcIzMpAbv3oJs,155
147
200
  janito/providers/__init__.py,sha256=EvOFeiqucAY9tgCosJ81p0QA6wQwMT1cR3EeIGrhSQQ,528
148
201
  janito/providers/dashscope.bak.zip,sha256=BwXxRmZreEivvRtmqbr5BR62IFVlNjAf4y6DrF2BVJo,5998
149
202
  janito/providers/registry.py,sha256=Ygwv9eVrTXOKhv0EKxSWQXO5WMHvajWE2Q_Lc3p7dKo,730
@@ -187,11 +240,11 @@ janito/regions/geo_utils.py,sha256=nLJ2x0tx1xMNI0_cMEiji-X8denynsaPYmXR9gGg8uk,5
187
240
  janito/regions/provider_regions.py,sha256=QJdbsdgjg-WcTRqPLGtm3pHJAm2o0-Y9MgE_vNzENEk,4619
188
241
  janito/tools/DOCSTRING_STANDARD.txt,sha256=VLPwNgjxRVD_xZSSVvUZ4H-4bBwM-VKh_RyfzYQsYSs,1735
189
242
  janito/tools/README.md,sha256=5HkLpF5k4PENJER7SlDPRXj0yo9mpHvAHW4uuzhq4ak,115
190
- janito/tools/__init__.py,sha256=W1B39PztC2UF7PS2WyLH6el32MFOETMlN1-LurOROCg,1171
243
+ janito/tools/__init__.py,sha256=8Dmc23B-OancdQsUK4xzKj9wsopsNa5bwm_6sYU63wE,1169
191
244
  janito/tools/base.py,sha256=R38A9xWYh3JRYZMDSom2d1taNDy9J7HpLbZo9X2wH_o,316
192
245
  janito/tools/disabled_tools.py,sha256=Tx__16wtMWZ9z34cYLdH1gukwot5MCL-9kLjd5MPX6Y,2110
193
246
  janito/tools/function_adapter.py,sha256=A_-5pA5Y3v0TAYMA-vq3A-Cawg75kH5XWcUEkNHSOoI,2267
194
- janito/tools/inspect_registry.py,sha256=Jo7PrMPRKLuR-j_mBAk9PBcTzeJf1eQrS1ChGofgQk0,538
247
+ janito/tools/inspect_registry.py,sha256=95vFn9dZVv9J0JO4SSunduI2AVnVkCMDHbOZ_XQaAxc,537
195
248
  janito/tools/loop_protection.py,sha256=WQ2Cqt459vXvrO0T1EqkEHynHlRkPzfaC83RSmXzjkM,4718
196
249
  janito/tools/loop_protection_decorator.py,sha256=R1j2ouscKbVcDm2wlxRZ6zQuKExgj633ijeDq4j0oO0,6457
197
250
  janito/tools/outline_file.bak.zip,sha256=EeI2cBXCwTdWVgJDNiroxKeYlkjwo6NLKeXz3J-2iZI,15607
@@ -199,7 +252,7 @@ janito/tools/path_security.py,sha256=40b0hV0X3449Dht93A04Q3c9AYSsBQsBFy2BjzM83lA
199
252
  janito/tools/path_utils.py,sha256=Rg5GE4kiu7rky6I2KTtivW6wPXzc9Qmq0_lOjwkPYlI,832
200
253
  janito/tools/permissions.py,sha256=_viTVXyetZC01HjI2s5c3klIJ8-RkWB1ShdOaV__loY,1508
201
254
  janito/tools/permissions_parse.py,sha256=LHadt0bWglm9Q2BbbVVbKePg4oa7QLeRQ-ChQZsE_dI,384
202
- janito/tools/tool_base.py,sha256=TSrXDknqIqOtY3xzuvtsxZ3qwbvmGzUruBiqVzzICfc,3689
255
+ janito/tools/tool_base.py,sha256=OGbj4dkWpWaFkWOUWyl0LGh03_GKS_-V2IzRnxiwy8s,3928
203
256
  janito/tools/tool_events.py,sha256=czRtC2TYakAySBZvfHS_Q6_NY_7_krxzAzAL1ggRFWA,1527
204
257
  janito/tools/tool_run_exception.py,sha256=43yWgTaGBGEtRteo6FvTrane6fEVGo9FU1uOdjMRWJE,525
205
258
  janito/tools/tool_use_tracker.py,sha256=IaEmA22D6RuL1xMUCScOMGv0crLPwEJVGmj49cydIaM,2662
@@ -207,58 +260,9 @@ janito/tools/tool_utils.py,sha256=alPm9DvtXSw_zPRKvP5GjbebPRf_nfvmWk2TNlL5Cws,12
207
260
  janito/tools/tools_adapter.py,sha256=F1Wkji222dY53HMaZWf3vqVas1Bimm3UXERKvxF54Ew,21687
208
261
  janito/tools/tools_schema.py,sha256=rGrKrmpPNR07VXHAJ_haGBRRO-YGLOF51BlYRep9AAQ,4415
209
262
  janito/tools/url_whitelist.py,sha256=0CPLkHTp5HgnwgjxwgXnJmwPeZQ30q4j3YjW59hiUUE,4295
210
- janito/tools/adapters/__init__.py,sha256=XKixOKtUJs1R-rGwGDXSLVLg5-Kp090gvWbsseWT4LI,92
211
- janito/tools/adapters/local/__init__.py,sha256=I6LtLnDTyApZrSlKcihSQqZv3gADVX781Mcj46LH7ac,2362
212
- janito/tools/adapters/local/adapter.py,sha256=u4nLHTaYdwZXMi1J8lsKvlG6rOmdq9xjey_3zeyCG4k,8707
213
- janito/tools/adapters/local/ask_user.py,sha256=-shjMRKrRe7HNHM2w_6YAl7eEgl8QXaIV6LKrUDEBxU,4060
214
- janito/tools/adapters/local/copy_file.py,sha256=SBJm19Ipe5dqRE1Mxl6JSrn4bNmfObVnDr5b1mcEu6c,3682
215
- janito/tools/adapters/local/create_directory.py,sha256=LxwqQEsnOrEphCIoaMRRx9P9bu0MzidP3Fc5q6letxc,2584
216
- janito/tools/adapters/local/create_file.py,sha256=fLTVnMpDnHzzIVK3nS0DtawBT-I18Is-qa0Hg8y6TXY,6385
217
- janito/tools/adapters/local/delete_text_in_file.py,sha256=uEeedRxXAR7_CqUc_qhbEdM0OzRi_pgnP-iDjs2Zvjk,5087
218
- janito/tools/adapters/local/fetch_url.py,sha256=QjoOZj06PjsU8uFjJ6O8Fy-WUvS4GhSaHAJQx2rAzoE,18212
219
- janito/tools/adapters/local/find_files.py,sha256=Zbag3aP34vc7ffJh8bOqAwXj3KiZhV--uzTVHtNb-fI,6250
220
- janito/tools/adapters/local/move_file.py,sha256=LMGm8bn3NNyIPJG4vrlO09smXQcgzA09EwoooZxkIA8,4695
221
- janito/tools/adapters/local/open_html_in_browser.py,sha256=XqICIwVx5vEE77gHkaNAC-bAeEEy0DBmDksATiL-sRY,2101
222
- janito/tools/adapters/local/open_url.py,sha256=V3Sv7iLynUreLjVl5-bl-XFH_LzpTeBrS8-cvzp_7rM,1552
223
- janito/tools/adapters/local/python_code_run.py,sha256=HdDuiRb7Fd7WC6bFS292XnSI1EYhn9XKlh8Hs_4Cz8E,6981
224
- janito/tools/adapters/local/python_command_run.py,sha256=BT9emL3PsNGupkENNfUymPECiQEAm9tBhniCaOuatj0,6935
225
- janito/tools/adapters/local/python_file_run.py,sha256=p0iOoxByCoKqW7QqfxTdHbPbRzEd_KWyZqnzrSb1qLQ,6859
226
- janito/tools/adapters/local/read_chart.py,sha256=qQebp_MEE_x2AL_pl85uA58A4lbhLQsyGl7wiG_Cjhc,10411
227
- janito/tools/adapters/local/read_files.py,sha256=LzlNrQEadYF8dF97Wm8AHde2nuqbMkN5vVskQLhvFdA,2329
228
- janito/tools/adapters/local/remove_directory.py,sha256=DEhHdmwJRl5Yp9eEukIIooMrpATCtXcv5HmaDRn8vH8,1913
229
- janito/tools/adapters/local/remove_file.py,sha256=Imra4jGkBfAd6pnUAmbUsjN0exj2vzZWuNRXq_GOMsI,2093
230
- janito/tools/adapters/local/replace_text_in_file.py,sha256=zJIDecviF2YRpWxbvhtka4Iaje-QYhcaqQX1PxWolzE,10966
231
- janito/tools/adapters/local/run_bash_command.py,sha256=7fABqAeAu7WJwzzwHmT54_m5OSwPMcgpQ74lQhPG7TA,7955
232
- janito/tools/adapters/local/run_powershell_command.py,sha256=uQSJVQe40wSGbesyvZxDmIKJthAbDJFaxXm1dEN3gBs,9313
233
- janito/tools/adapters/local/show_image.py,sha256=OkdiIkaRhjqPMSF5QFcqjLK-fN1oljo_YQM9TH2ZK_A,2932
234
- janito/tools/adapters/local/show_image_grid.py,sha256=w_U04_K0qmCcX8ac6KUcs-UsnfCb-qsXT3-kasr17dM,3000
235
- janito/tools/adapters/local/view_file.py,sha256=cBKcbwbfH-UMyvQ7PmYTgsshcFmorjWtyH1kaYi7oNY,7379
236
- janito/tools/adapters/local/get_file_outline/__init__.py,sha256=OKV_BHnoD9h-vkcVoW6AHmsuDjjauHPCKNK0nVFl4sU,37
237
- janito/tools/adapters/local/get_file_outline/core.py,sha256=25k6a8PaDYxAfxnEAvZvOWg2BgUcgKU_BkzJmZKUMEA,4611
238
- janito/tools/adapters/local/get_file_outline/java_outline.py,sha256=_UeUY5JoQEUdlHcK8aqGTqYJl0T2KxIFXPTdwum9gKQ,1825
239
- janito/tools/adapters/local/get_file_outline/markdown_outline.py,sha256=bXEBg0D93tEBDNy8t-wh4i7WxsxfpQ2C3dX1_rmtj08,434
240
- janito/tools/adapters/local/get_file_outline/python_outline.py,sha256=RAcf9Vxec08lA06drYaNre5HCJ2lTzrRAskZ3rlyE-U,10326
241
- janito/tools/adapters/local/get_file_outline/search_outline.py,sha256=bski24TpnJVf3L0TNzkx3HfvaXwttQl4EVkwk2POQOw,1348
242
- janito/tools/adapters/local/search_text/__init__.py,sha256=FEYpF5tTtf0fiAyRGIGSn-kV-MJDkhdFIbus16mYW8Y,34
243
- janito/tools/adapters/local/search_text/core.py,sha256=Qoid7FESJGVIsFm5oasgv9vZDy0aSzqeJPBWAF2_Edo,7877
244
- janito/tools/adapters/local/search_text/match_lines.py,sha256=RLR8fZFP-Q57rY0fTENbMItmt3dJZiYX0otmGHVRjfw,2131
245
- janito/tools/adapters/local/search_text/pattern_utils.py,sha256=D7vtAr8oT0tGV0C_UUarAXS9XQtP-MTYmmc8Yg8iVTg,2362
246
- janito/tools/adapters/local/search_text/traverse_directory.py,sha256=EpL1qywAV0H29pm8-QsHrjKchKP4i4sRUOENVuNptCo,4000
247
- janito/tools/adapters/local/validate_file_syntax/__init__.py,sha256=P53RHmas4BbHL90cMxH9m-RpMCJI8JquoJb0rpkPVVk,29
248
- janito/tools/adapters/local/validate_file_syntax/core.py,sha256=oYCpk_kyCbseKG_xX5xQjW91bPSpzzl18TPm7mMpwPI,3714
249
- janito/tools/adapters/local/validate_file_syntax/css_validator.py,sha256=jE5d26C_fU9k9azujbGVISn2WIRL-Ys6de4dsCq30bo,1351
250
- janito/tools/adapters/local/validate_file_syntax/html_validator.py,sha256=VV93BRcAeUraXHc9dUyH1cs9gRwRwO84K1-L5zbJnYU,3207
251
- janito/tools/adapters/local/validate_file_syntax/jinja2_validator.py,sha256=lfM0SsKsFygiEp1IuLNr5jdS7XJyjCLOPw2yo9vl-pY,1763
252
- janito/tools/adapters/local/validate_file_syntax/js_validator.py,sha256=42LvgyMVhG9c2EAaSz3J9pu-yuh1oyIvRp0wN2rHiDQ,998
253
- janito/tools/adapters/local/validate_file_syntax/json_validator.py,sha256=muCB0-bdxk9zNulzH1It3hWpYzJC3hD8LbxCnE0P5is,150
254
- janito/tools/adapters/local/validate_file_syntax/markdown_validator.py,sha256=k4UT88fXvtclygz-nFhCMHJL5sk5WlGD-fP_cWqWMyU,3511
255
- janito/tools/adapters/local/validate_file_syntax/ps1_validator.py,sha256=TeIkPt08t_-w2JiKksXHHK9lJNT348ZDkWoSTzMtRrI,1152
256
- janito/tools/adapters/local/validate_file_syntax/python_validator.py,sha256=BfCO_K18qy92m-2ZVvHsbEU5e11OPo1pO9Vz4G4616E,130
257
- janito/tools/adapters/local/validate_file_syntax/xml_validator.py,sha256=AijlsP_PgNuC8ZbGsC5vOTt3Jur76otQzkd_7qR0QFY,284
258
- janito/tools/adapters/local/validate_file_syntax/yaml_validator.py,sha256=TgyI0HRL6ug_gBcWEm5TGJJuA4E34ZXcIzMpAbv3oJs,155
259
- janito-3.8.0.dist-info/licenses/LICENSE,sha256=dXV4fOF2ZErugtN8l_Nrj5tsRTYgtjE3cgiya0UfBio,11356
260
- janito-3.8.0.dist-info/METADATA,sha256=KojxYonxnLshxFtvWLAInVYyzmO2WpRhmgTu6dt8jFM,2312
261
- janito-3.8.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
262
- janito-3.8.0.dist-info/entry_points.txt,sha256=wIo5zZxbmu4fC-ZMrsKD0T0vq7IqkOOLYhrqRGypkx4,48
263
- janito-3.8.0.dist-info/top_level.txt,sha256=m0NaVCq0-ivxbazE2-ND0EA9Hmuijj_OGkmCbnBcCig,7
264
- janito-3.8.0.dist-info/RECORD,,
263
+ janito-3.9.0.dist-info/licenses/LICENSE,sha256=dXV4fOF2ZErugtN8l_Nrj5tsRTYgtjE3cgiya0UfBio,11356
264
+ janito-3.9.0.dist-info/METADATA,sha256=l6BQBjEWyv87kqVVDgSgauNo3fjfvg6dL9lVp53CdDI,2338
265
+ janito-3.9.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
266
+ janito-3.9.0.dist-info/entry_points.txt,sha256=wIo5zZxbmu4fC-ZMrsKD0T0vq7IqkOOLYhrqRGypkx4,48
267
+ janito-3.9.0.dist-info/top_level.txt,sha256=m0NaVCq0-ivxbazE2-ND0EA9Hmuijj_OGkmCbnBcCig,7
268
+ janito-3.9.0.dist-info/RECORD,,
File without changes
File without changes