janito 3.1.0__py3-none-any.whl → 3.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 (156) hide show
  1. janito/cli/chat_mode/bindings.py +0 -26
  2. janito/cli/chat_mode/session.py +1 -7
  3. janito/cli/cli_commands/list_plugins.py +8 -13
  4. janito/cli/prompt_core.py +9 -19
  5. janito/llm/agent.py +17 -30
  6. janito/llm/driver.py +0 -7
  7. janito/plugins/__init__.py +21 -29
  8. janito/plugins/__main__.py +85 -0
  9. janito/plugins/base.py +57 -0
  10. janito/plugins/builtin.py +1 -1
  11. janito/plugins/core/filemanager/tools/copy_file.py +25 -1
  12. janito/plugins/core/filemanager/tools/create_directory.py +28 -1
  13. janito/plugins/core/filemanager/tools/create_file.py +25 -1
  14. janito/plugins/core/filemanager/tools/delete_text_in_file.py +1 -0
  15. janito/plugins/core/imagedisplay/plugin.py +1 -1
  16. janito/plugins/core_loader.py +144 -0
  17. janito/plugins/discovery.py +3 -3
  18. janito/plugins/example_plugin.py +1 -1
  19. janito/plugins/manager.py +1 -1
  20. janito/plugins_backup_20250825_070018/__init__.py +36 -0
  21. janito/plugins_backup_20250825_070018/builtin.py +102 -0
  22. janito/plugins_backup_20250825_070018/config.py +84 -0
  23. janito/plugins_backup_20250825_070018/core/__init__.py +7 -0
  24. janito/plugins_backup_20250825_070018/core/codeanalyzer/__init__.py +43 -0
  25. janito/plugins_backup_20250825_070018/core/codeanalyzer/tools/get_file_outline/__init__.py +1 -0
  26. janito/plugins_backup_20250825_070018/core/codeanalyzer/tools/get_file_outline/core.py +122 -0
  27. janito/plugins_backup_20250825_070018/core/codeanalyzer/tools/search_text/__init__.py +1 -0
  28. janito/plugins_backup_20250825_070018/core/codeanalyzer/tools/search_text/core.py +205 -0
  29. janito/plugins_backup_20250825_070018/core/filemanager/__init__.py +124 -0
  30. janito/plugins_backup_20250825_070018/core/filemanager/tools/copy_file.py +87 -0
  31. janito/plugins_backup_20250825_070018/core/filemanager/tools/create_directory.py +70 -0
  32. janito/plugins_backup_20250825_070018/core/filemanager/tools/create_file.py +87 -0
  33. janito/plugins_backup_20250825_070018/core/filemanager/tools/delete_text_in_file.py +135 -0
  34. janito/plugins_backup_20250825_070018/core/filemanager/tools/find_files.py +143 -0
  35. janito/plugins_backup_20250825_070018/core/filemanager/tools/move_file.py +131 -0
  36. janito/plugins_backup_20250825_070018/core/filemanager/tools/read_files.py +58 -0
  37. janito/plugins_backup_20250825_070018/core/filemanager/tools/remove_directory.py +55 -0
  38. janito/plugins_backup_20250825_070018/core/filemanager/tools/remove_file.py +58 -0
  39. janito/plugins_backup_20250825_070018/core/filemanager/tools/replace_text_in_file.py +270 -0
  40. janito/plugins_backup_20250825_070018/core/filemanager/tools/validate_file_syntax/__init__.py +1 -0
  41. janito/plugins_backup_20250825_070018/core/filemanager/tools/validate_file_syntax/core.py +114 -0
  42. janito/plugins_backup_20250825_070018/core/filemanager/tools/view_file.py +172 -0
  43. janito/plugins_backup_20250825_070018/core/imagedisplay/__init__.py +14 -0
  44. janito/plugins_backup_20250825_070018/core/imagedisplay/plugin.py +51 -0
  45. janito/plugins_backup_20250825_070018/core/imagedisplay/tools/__init__.py +1 -0
  46. janito/plugins_backup_20250825_070018/core/imagedisplay/tools/show_image.py +83 -0
  47. janito/plugins_backup_20250825_070018/core/imagedisplay/tools/show_image_grid.py +84 -0
  48. janito/plugins_backup_20250825_070018/core/system/__init__.py +23 -0
  49. janito/plugins_backup_20250825_070018/core/system/tools/run_bash_command.py +183 -0
  50. janito/plugins_backup_20250825_070018/core/system/tools/run_powershell_command.py +218 -0
  51. janito/plugins_backup_20250825_070018/dev/__init__.py +7 -0
  52. janito/plugins_backup_20250825_070018/dev/pythondev/__init__.py +37 -0
  53. janito/plugins_backup_20250825_070018/dev/pythondev/tools/python_code_run.py +172 -0
  54. janito/plugins_backup_20250825_070018/dev/pythondev/tools/python_command_run.py +171 -0
  55. janito/plugins_backup_20250825_070018/dev/pythondev/tools/python_file_run.py +172 -0
  56. janito/plugins_backup_20250825_070018/dev/visualization/__init__.py +23 -0
  57. janito/plugins_backup_20250825_070018/dev/visualization/tools/read_chart.py +259 -0
  58. janito/plugins_backup_20250825_070018/discovery.py +289 -0
  59. janito/plugins_backup_20250825_070018/example_plugin.py +108 -0
  60. janito/plugins_backup_20250825_070018/manager.py +243 -0
  61. janito/{plugins → plugins_backup_20250825_070018}/tools/delete_text_in_file.py +1 -0
  62. janito/plugins_backup_20250825_070018/tools/get_file_outline/java_outline.py +47 -0
  63. janito/plugins_backup_20250825_070018/tools/get_file_outline/markdown_outline.py +14 -0
  64. janito/plugins_backup_20250825_070018/tools/get_file_outline/python_outline.py +303 -0
  65. janito/plugins_backup_20250825_070018/tools/get_file_outline/search_outline.py +36 -0
  66. janito/plugins_backup_20250825_070018/tools/search_text/match_lines.py +67 -0
  67. janito/plugins_backup_20250825_070018/tools/search_text/pattern_utils.py +73 -0
  68. janito/plugins_backup_20250825_070018/tools/search_text/traverse_directory.py +145 -0
  69. janito/plugins_backup_20250825_070018/tools/validate_file_syntax/css_validator.py +35 -0
  70. janito/plugins_backup_20250825_070018/tools/validate_file_syntax/html_validator.py +100 -0
  71. janito/plugins_backup_20250825_070018/tools/validate_file_syntax/jinja2_validator.py +50 -0
  72. janito/plugins_backup_20250825_070018/tools/validate_file_syntax/js_validator.py +27 -0
  73. janito/plugins_backup_20250825_070018/tools/validate_file_syntax/json_validator.py +6 -0
  74. janito/plugins_backup_20250825_070018/tools/validate_file_syntax/markdown_validator.py +109 -0
  75. janito/plugins_backup_20250825_070018/tools/validate_file_syntax/ps1_validator.py +32 -0
  76. janito/plugins_backup_20250825_070018/tools/validate_file_syntax/python_validator.py +5 -0
  77. janito/plugins_backup_20250825_070018/tools/validate_file_syntax/xml_validator.py +11 -0
  78. janito/plugins_backup_20250825_070018/tools/validate_file_syntax/yaml_validator.py +6 -0
  79. janito/plugins_backup_20250825_070018/ui/__init__.py +7 -0
  80. janito/plugins_backup_20250825_070018/ui/userinterface/__init__.py +16 -0
  81. janito/plugins_backup_20250825_070018/ui/userinterface/tools/ask_user.py +110 -0
  82. janito/plugins_backup_20250825_070018/web/__init__.py +7 -0
  83. janito/plugins_backup_20250825_070018/web/webtools/__init__.py +33 -0
  84. janito/plugins_backup_20250825_070018/web/webtools/tools/fetch_url.py +458 -0
  85. janito/plugins_backup_20250825_070018/web/webtools/tools/open_html_in_browser.py +51 -0
  86. janito/plugins_backup_20250825_070018/web/webtools/tools/open_url.py +37 -0
  87. janito/tools/base.py +31 -1
  88. janito/tools/cli_initializer.py +1 -1
  89. janito/tools/function_adapter.py +35 -1
  90. janito/tools/initialize.py +1 -1
  91. janito/tools/tool_base.py +142 -114
  92. janito/tools/tools_schema.py +12 -6
  93. {janito-3.1.0.dist-info → janito-3.3.0.dist-info}/METADATA +1 -1
  94. {janito-3.1.0.dist-info → janito-3.3.0.dist-info}/RECORD +154 -87
  95. janito/llm/cancellation_manager.py +0 -62
  96. janito/llm/enter_cancellation.py +0 -93
  97. /janito/{plugin_system → plugin_system_backup_20250825_070018}/__init__.py +0 -0
  98. /janito/{plugin_system → plugin_system_backup_20250825_070018}/base.py +0 -0
  99. /janito/{plugin_system → plugin_system_backup_20250825_070018}/core_loader.py +0 -0
  100. /janito/{plugin_system → plugin_system_backup_20250825_070018}/core_loader_fixed.py +0 -0
  101. /janito/{plugins → plugins_backup_20250825_070018}/auto_loader.py +0 -0
  102. /janito/{plugins → plugins_backup_20250825_070018}/auto_loader_fixed.py +0 -0
  103. /janito/{plugins → plugins_backup_20250825_070018/core/codeanalyzer}/tools/get_file_outline/java_outline.py +0 -0
  104. /janito/{plugins → plugins_backup_20250825_070018/core/codeanalyzer}/tools/get_file_outline/markdown_outline.py +0 -0
  105. /janito/{plugins → plugins_backup_20250825_070018/core/codeanalyzer}/tools/get_file_outline/python_outline.py +0 -0
  106. /janito/{plugins → plugins_backup_20250825_070018/core/codeanalyzer}/tools/get_file_outline/search_outline.py +0 -0
  107. /janito/{plugins → plugins_backup_20250825_070018/core/codeanalyzer}/tools/search_text/match_lines.py +0 -0
  108. /janito/{plugins → plugins_backup_20250825_070018/core/codeanalyzer}/tools/search_text/pattern_utils.py +0 -0
  109. /janito/{plugins → plugins_backup_20250825_070018/core/codeanalyzer}/tools/search_text/traverse_directory.py +0 -0
  110. /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/css_validator.py +0 -0
  111. /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/html_validator.py +0 -0
  112. /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/jinja2_validator.py +0 -0
  113. /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/js_validator.py +0 -0
  114. /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/json_validator.py +0 -0
  115. /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/markdown_validator.py +0 -0
  116. /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/ps1_validator.py +0 -0
  117. /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/python_validator.py +0 -0
  118. /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/xml_validator.py +0 -0
  119. /janito/{plugins → plugins_backup_20250825_070018/core/filemanager}/tools/validate_file_syntax/yaml_validator.py +0 -0
  120. /janito/{plugins → plugins_backup_20250825_070018}/core_adapter.py +0 -0
  121. /janito/{plugins → plugins_backup_20250825_070018}/discovery_core.py +0 -0
  122. /janito/{plugins → plugins_backup_20250825_070018}/tools/__init__.py +0 -0
  123. /janito/{plugins → plugins_backup_20250825_070018}/tools/ask_user.py +0 -0
  124. /janito/{plugins → plugins_backup_20250825_070018}/tools/copy_file.py +0 -0
  125. /janito/{plugins → plugins_backup_20250825_070018}/tools/core_tools_plugin.py +0 -0
  126. /janito/{plugins → plugins_backup_20250825_070018}/tools/create_directory.py +0 -0
  127. /janito/{plugins → plugins_backup_20250825_070018}/tools/create_file.py +0 -0
  128. /janito/{plugins → plugins_backup_20250825_070018}/tools/decorators.py +0 -0
  129. /janito/{plugins → plugins_backup_20250825_070018}/tools/fetch_url.py +0 -0
  130. /janito/{plugins → plugins_backup_20250825_070018}/tools/find_files.py +0 -0
  131. /janito/{plugins → plugins_backup_20250825_070018}/tools/get_file_outline/__init__.py +0 -0
  132. /janito/{plugins → plugins_backup_20250825_070018}/tools/get_file_outline/core.py +0 -0
  133. /janito/{plugins → plugins_backup_20250825_070018}/tools/move_file.py +0 -0
  134. /janito/{plugins → plugins_backup_20250825_070018}/tools/open_html_in_browser.py +0 -0
  135. /janito/{plugins → plugins_backup_20250825_070018}/tools/open_url.py +0 -0
  136. /janito/{plugins → plugins_backup_20250825_070018}/tools/python_code_run.py +0 -0
  137. /janito/{plugins → plugins_backup_20250825_070018}/tools/python_command_run.py +0 -0
  138. /janito/{plugins → plugins_backup_20250825_070018}/tools/python_file_run.py +0 -0
  139. /janito/{plugins → plugins_backup_20250825_070018}/tools/read_chart.py +0 -0
  140. /janito/{plugins → plugins_backup_20250825_070018}/tools/read_files.py +0 -0
  141. /janito/{plugins → plugins_backup_20250825_070018}/tools/remove_directory.py +0 -0
  142. /janito/{plugins → plugins_backup_20250825_070018}/tools/remove_file.py +0 -0
  143. /janito/{plugins → plugins_backup_20250825_070018}/tools/replace_text_in_file.py +0 -0
  144. /janito/{plugins → plugins_backup_20250825_070018}/tools/run_bash_command.py +0 -0
  145. /janito/{plugins → plugins_backup_20250825_070018}/tools/run_powershell_command.py +0 -0
  146. /janito/{plugins → plugins_backup_20250825_070018}/tools/search_text/__init__.py +0 -0
  147. /janito/{plugins → plugins_backup_20250825_070018}/tools/search_text/core.py +0 -0
  148. /janito/{plugins → plugins_backup_20250825_070018}/tools/show_image.py +0 -0
  149. /janito/{plugins → plugins_backup_20250825_070018}/tools/show_image_grid.py +0 -0
  150. /janito/{plugins → plugins_backup_20250825_070018}/tools/validate_file_syntax/__init__.py +0 -0
  151. /janito/{plugins → plugins_backup_20250825_070018}/tools/validate_file_syntax/core.py +0 -0
  152. /janito/{plugins → plugins_backup_20250825_070018}/tools/view_file.py +0 -0
  153. {janito-3.1.0.dist-info → janito-3.3.0.dist-info}/WHEEL +0 -0
  154. {janito-3.1.0.dist-info → janito-3.3.0.dist-info}/entry_points.txt +0 -0
  155. {janito-3.1.0.dist-info → janito-3.3.0.dist-info}/licenses/LICENSE +0 -0
  156. {janito-3.1.0.dist-info → janito-3.3.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,37 @@
1
+ import webbrowser
2
+ from janito.tools.adapters.local.adapter import register_local_tool
3
+ from janito.tools.tool_base import ToolBase, ToolPermissions
4
+ from janito.report_events import ReportAction
5
+ from janito.i18n import tr
6
+ from janito.tools.loop_protection_decorator import protect_against_loops
7
+
8
+
9
+ @register_local_tool
10
+ class OpenUrlTool(ToolBase):
11
+ """
12
+ Open the supplied URL or local file in the default web browser.
13
+
14
+ Args:
15
+ url (str): The URL or local file path (as a file:// URL) to open. Supports both web URLs (http, https) and local files (file://).
16
+ Returns:
17
+ str: Status message indicating the result.
18
+ """
19
+
20
+ permissions = ToolPermissions(read=True)
21
+ tool_name = "open_url"
22
+
23
+ @protect_against_loops(max_calls=5, time_window=10.0, key_field="url")
24
+ def run(self, url: str) -> str:
25
+ if not url.strip():
26
+ self.report_warning(tr("ℹ️ Empty URL provided."))
27
+ return tr("Warning: Empty URL provided. Operation skipped.")
28
+ self.report_action(tr("🌐 Opening URL '{url}' ...", url=url), ReportAction.READ)
29
+ try:
30
+ webbrowser.open(url)
31
+ except Exception as err:
32
+ self.report_error(
33
+ tr("❗ Error opening URL: {url}: {err}", url=url, err=str(err))
34
+ )
35
+ return tr("Warning: Error opening URL: {url}: {err}", url=url, err=str(err))
36
+ self.report_success(tr("✅ URL opened in browser: {url}", url=url))
37
+ return tr("URL opened in browser: {url}", url=url)
janito/tools/base.py CHANGED
@@ -1,5 +1,35 @@
1
1
  class BaseTool:
2
- """Base class for all tools."""
2
+ """
3
+ Base class for all tools.
4
+
5
+ Parameters:
6
+ path (str): Target file path for file operations
7
+ content (str): File content to write or process
8
+ overwrite (bool): Whether to overwrite existing files (default: False)
9
+ sources (str): Source file(s) to copy from
10
+ target (str): Destination path for copy operations
11
+ recursive (bool): Whether to process directories recursively
12
+ from_line (int): Starting line number for file reading
13
+ to_line (int): Ending line number for file reading
14
+ search_text (str): Text to search for in files
15
+ replacement_text (str): Text to replace search matches with
16
+ use_regex (bool): Whether to treat search as regex pattern
17
+ case_sensitive (bool): Whether search should be case sensitive
18
+ max_depth (int): Maximum directory depth to search
19
+ include_gitignored (bool): Whether to include .gitignored files
20
+ timeout (int): Timeout in seconds for operations
21
+ require_confirmation (bool): Whether to require user confirmation
22
+ data (dict): Chart data for visualization tools
23
+ title (str): Chart title
24
+ width (int): Chart width in pixels
25
+ height (int): Chart height in pixels
26
+ query (str): Search query for text search
27
+ paths (str): Directory or file paths to search in
28
+ src_path (str): Source path for move operations
29
+ dest_path (str): Destination path for move operations
30
+ code (str): Python code to execute
31
+ pattern (str): File pattern to match (e.g., '*.py')
32
+ """
3
33
 
4
34
  tool_name: str = ""
5
35
 
@@ -17,7 +17,7 @@ def initialize_cli_tools():
17
17
  """Initialize tools for CLI usage, avoiding circular imports."""
18
18
  try:
19
19
  from janito.tools.adapters.local.adapter import LocalToolsAdapter
20
- from janito.plugin_system.core_loader_fixed import load_core_plugin
20
+ from janito.plugins.core_loader import load_core_plugin
21
21
  from janito.tools.permissions import set_global_allowed_permissions
22
22
  from janito.tools.tool_base import ToolPermissions
23
23
 
@@ -10,7 +10,41 @@ from janito.tools.tool_base import ToolBase, ToolPermissions
10
10
 
11
11
 
12
12
  class FunctionToolAdapter(ToolBase):
13
- """Adapter that wraps a function into a ToolBase class."""
13
+ """
14
+ Adapter that wraps a function into a ToolBase class.
15
+
16
+ This adapter provides a unified interface for function-based tools by wrapping
17
+ individual functions with the ToolBase protocol. It handles parameter mapping
18
+ and validation automatically.
19
+
20
+ Parameters:
21
+ path (str): Target file path for file operations
22
+ content (str): File content to write or process
23
+ overwrite (bool): Whether to overwrite existing files (default: False)
24
+ sources (str): Source file(s) to copy from
25
+ target (str): Destination path for copy operations
26
+ recursive (bool): Whether to process directories recursively
27
+ from_line (int): Starting line number for file reading
28
+ to_line (int): Ending line number for file reading
29
+ search_text (str): Text to search for in files
30
+ replacement_text (str): Text to replace search matches with
31
+ use_regex (bool): Whether to treat search as regex pattern
32
+ case_sensitive (bool): Whether search should be case sensitive
33
+ max_depth (int): Maximum directory depth to search
34
+ include_gitignored (bool): Whether to include .gitignored files
35
+ timeout (int): Timeout in seconds for operations
36
+ require_confirmation (bool): Whether to require user confirmation
37
+ data (dict): Chart data for visualization tools
38
+ title (str): Chart title
39
+ width (int): Chart width in pixels
40
+ height (int): Chart height in pixels
41
+ query (str): Search query for text search
42
+ paths (str): Directory or file paths to search in
43
+ src_path (str): Source path for move operations
44
+ dest_path (str): Destination path for move operations
45
+ code (str): Python code to execute
46
+ pattern (str): File pattern to match (e.g., '*.py')
47
+ """
14
48
 
15
49
  def __init__(self, func, tool_name: str = None, description: str = None):
16
50
  super().__init__()
@@ -9,7 +9,7 @@ import sys
9
9
  from pathlib import Path
10
10
  from typing import List, Optional
11
11
 
12
- from janito.plugin_system.core_loader_fixed import load_core_plugin
12
+ from janito.plugins.core_loader import load_core_plugin
13
13
  from janito.tools.adapters.local.adapter import LocalToolsAdapter
14
14
 
15
15
 
janito/tools/tool_base.py CHANGED
@@ -1,114 +1,142 @@
1
- from janito.report_events import ReportEvent, ReportSubtype, ReportAction
2
- from janito.event_bus.bus import event_bus as default_event_bus
3
-
4
-
5
- from collections import namedtuple
6
-
7
-
8
- class ToolPermissions(namedtuple("ToolPermissions", ["read", "write", "execute"])):
9
- __slots__ = ()
10
-
11
- def __new__(cls, read=False, write=False, execute=False):
12
- return super().__new__(cls, read, write, execute)
13
-
14
- def __repr__(self):
15
- return f"ToolPermissions(read={self.read}, write={self.write}, execute={self.execute})"
16
-
17
-
18
- class ToolBase:
19
- """
20
- Base class for all tools in the janito project.
21
- Extend this class to implement specific tool functionality.
22
- """
23
-
24
- permissions: "ToolPermissions" = None # Required: must be set by subclasses
25
-
26
- def __init__(self, name=None, event_bus=None):
27
- if self.permissions is None or not isinstance(
28
- self.permissions, ToolPermissions
29
- ):
30
- raise ValueError(
31
- f"Tool '{self.__class__.__name__}' must define a 'permissions' attribute of type ToolPermissions."
32
- )
33
- self.name = name or self.__class__.__name__
34
- self._event_bus = event_bus or default_event_bus
35
-
36
- @property
37
- def event_bus(self):
38
- return self._event_bus
39
-
40
- @event_bus.setter
41
- def event_bus(self, bus):
42
- self._event_bus = bus or default_event_bus
43
-
44
- def report_action(self, message: str, action: ReportAction, context: dict = None):
45
- """
46
- Report that a tool action is starting. This should be the first reporting call for every tool action.
47
- """
48
- self._event_bus.publish(
49
- ReportEvent(
50
- subtype=ReportSubtype.ACTION_INFO,
51
- message=" " + message,
52
- action=action,
53
- tool=self.name,
54
- context=context,
55
- )
56
- )
57
-
58
- def report_error(self, message: str, context: dict = None):
59
- self._event_bus.publish(
60
- ReportEvent(
61
- subtype=ReportSubtype.ERROR,
62
- message=message,
63
- action=None,
64
- tool=self.name,
65
- context=context,
66
- )
67
- )
68
-
69
- def report_success(self, message: str, context: dict = None):
70
- self._event_bus.publish(
71
- ReportEvent(
72
- subtype=ReportSubtype.SUCCESS,
73
- message=message,
74
- action=None,
75
- tool=self.name,
76
- context=context,
77
- )
78
- )
79
-
80
- def report_warning(self, message: str, context: dict = None):
81
- self._event_bus.publish(
82
- ReportEvent(
83
- subtype=ReportSubtype.WARNING,
84
- message=message,
85
- action=None,
86
- tool=self.name,
87
- context=context,
88
- )
89
- )
90
-
91
- def report_stdout(self, message: str, context: dict = None):
92
- self._event_bus.publish(
93
- ReportEvent(
94
- subtype=ReportSubtype.STDOUT,
95
- message=message,
96
- action=None,
97
- tool=self.name,
98
- context=context,
99
- )
100
- )
101
-
102
- def report_stderr(self, message: str, context: dict = None):
103
- self._event_bus.publish(
104
- ReportEvent(
105
- subtype=ReportSubtype.STDERR,
106
- message=message,
107
- action=None,
108
- tool=self.name,
109
- context=context,
110
- )
111
- )
112
-
113
- def run(self, *args, **kwargs):
114
- raise NotImplementedError("Subclasses must implement the run method.")
1
+ from janito.report_events import ReportEvent, ReportSubtype, ReportAction
2
+ from janito.event_bus.bus import event_bus as default_event_bus
3
+
4
+
5
+ from collections import namedtuple
6
+
7
+
8
+ class ToolPermissions(namedtuple("ToolPermissions", ["read", "write", "execute"])):
9
+ __slots__ = ()
10
+
11
+ def __new__(cls, read=False, write=False, execute=False):
12
+ return super().__new__(cls, read, write, execute)
13
+
14
+ def __repr__(self):
15
+ return f"ToolPermissions(read={self.read}, write={self.write}, execute={self.execute})"
16
+
17
+
18
+ class ToolBase:
19
+ """
20
+ Base class for all tools in the janito project.
21
+ Extend this class to implement specific tool functionality.
22
+
23
+ Parameters:
24
+ path (str): Target file path for file operations
25
+ content (str): File content to write or process
26
+ overwrite (bool): Whether to overwrite existing files (default: False)
27
+ sources (str): Source file(s) to copy from
28
+ target (str): Destination path for copy operations
29
+ recursive (bool): Whether to process directories recursively
30
+ from_line (int): Starting line number for file reading
31
+ to_line (int): Ending line number for file reading
32
+ search_text (str): Text to search for in files
33
+ replacement_text (str): Text to replace search matches with
34
+ use_regex (bool): Whether to treat search as regex pattern
35
+ case_sensitive (bool): Whether search should be case sensitive
36
+ max_depth (int): Maximum directory depth to search
37
+ include_gitignored (bool): Whether to include .gitignored files
38
+ timeout (int): Timeout in seconds for operations
39
+ require_confirmation (bool): Whether to require user confirmation
40
+ data (dict): Chart data for visualization tools
41
+ title (str): Chart title
42
+ width (int): Chart width in pixels
43
+ height (int): Chart height in pixels
44
+ query (str): Search query for text search
45
+ paths (str): Directory or file paths to search in
46
+ src_path (str): Source path for move operations
47
+ dest_path (str): Destination path for move operations
48
+ code (str): Python code to execute
49
+ pattern (str): File pattern to match (e.g., '*.py')
50
+ """
51
+
52
+ permissions: "ToolPermissions" = None # Required: must be set by subclasses
53
+
54
+ def __init__(self, name=None, event_bus=None):
55
+ if self.permissions is None or not isinstance(
56
+ self.permissions, ToolPermissions
57
+ ):
58
+ raise ValueError(
59
+ f"Tool '{self.__class__.__name__}' must define a 'permissions' attribute of type ToolPermissions."
60
+ )
61
+ self.name = name or self.__class__.__name__
62
+ self._event_bus = event_bus or default_event_bus
63
+
64
+ @property
65
+ def event_bus(self):
66
+ return self._event_bus
67
+
68
+ @event_bus.setter
69
+ def event_bus(self, bus):
70
+ self._event_bus = bus or default_event_bus
71
+
72
+ def report_action(self, message: str, action: ReportAction, context: dict = None):
73
+ """
74
+ Report that a tool action is starting. This should be the first reporting call for every tool action.
75
+ """
76
+ self._event_bus.publish(
77
+ ReportEvent(
78
+ subtype=ReportSubtype.ACTION_INFO,
79
+ message=" " + message,
80
+ action=action,
81
+ tool=self.name,
82
+ context=context,
83
+ )
84
+ )
85
+
86
+ def report_error(self, message: str, context: dict = None):
87
+ self._event_bus.publish(
88
+ ReportEvent(
89
+ subtype=ReportSubtype.ERROR,
90
+ message=message,
91
+ action=None,
92
+ tool=self.name,
93
+ context=context,
94
+ )
95
+ )
96
+
97
+ def report_success(self, message: str, context: dict = None):
98
+ self._event_bus.publish(
99
+ ReportEvent(
100
+ subtype=ReportSubtype.SUCCESS,
101
+ message=message,
102
+ action=None,
103
+ tool=self.name,
104
+ context=context,
105
+ )
106
+ )
107
+
108
+ def report_warning(self, message: str, context: dict = None):
109
+ self._event_bus.publish(
110
+ ReportEvent(
111
+ subtype=ReportSubtype.WARNING,
112
+ message=message,
113
+ action=None,
114
+ tool=self.name,
115
+ context=context,
116
+ )
117
+ )
118
+
119
+ def report_stdout(self, message: str, context: dict = None):
120
+ self._event_bus.publish(
121
+ ReportEvent(
122
+ subtype=ReportSubtype.STDOUT,
123
+ message=message,
124
+ action=None,
125
+ tool=self.name,
126
+ context=context,
127
+ )
128
+ )
129
+
130
+ def report_stderr(self, message: str, context: dict = None):
131
+ self._event_bus.publish(
132
+ ReportEvent(
133
+ subtype=ReportSubtype.STDERR,
134
+ message=message,
135
+ action=None,
136
+ tool=self.name,
137
+ context=context,
138
+ )
139
+ )
140
+
141
+ def run(self, *args, **kwargs):
142
+ raise NotImplementedError("Subclasses must implement the run method.")
@@ -7,6 +7,8 @@ class ToolSchemaBase:
7
7
  def parse_param_section(self, lines, param_section_headers):
8
8
  param_descs = {}
9
9
  in_params = False
10
+ current_param = None
11
+
10
12
  for line in lines:
11
13
  stripped_line = line.strip()
12
14
  if any(
@@ -16,17 +18,21 @@ class ToolSchemaBase:
16
18
  in_params = True
17
19
  continue
18
20
  if in_params:
21
+ # Check for parameter definition: "param_name (type): description"
19
22
  m = re.match(
20
- r"([a-zA-Z_][a-zA-Z0-9_]*)\s*(?:\(([^)]+)\))?\s*[:\-]?\s*(.+)",
23
+ r"([a-zA-Z_][a-zA-Z0-9_]*)\s*(?:\([^)]+\))?\s*:\s*(.+)",
21
24
  stripped_line,
22
25
  )
23
26
  if m:
24
- param, _, desc = m.groups()
27
+ param, desc = m.groups()
25
28
  param_descs[param] = desc.strip()
26
- elif stripped_line and stripped_line[0] != "-":
27
- if param_descs:
28
- last = list(param_descs)[-1]
29
- param_descs[last] += " " + stripped_line
29
+ current_param = param
30
+ elif current_param and stripped_line and not (
31
+ stripped_line.lower().startswith("returns:") or
32
+ stripped_line.lower() == "returns"
33
+ ):
34
+ # Continuation of current parameter description
35
+ param_descs[current_param] += " " + stripped_line.strip()
30
36
  if (
31
37
  stripped_line.lower().startswith("returns:")
32
38
  or stripped_line.lower() == "returns"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: janito
3
- Version: 3.1.0
3
+ Version: 3.3.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