janito 2.1.1__py3-none-any.whl → 2.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. janito/__init__.py +6 -6
  2. janito/agent/setup_agent.py +14 -5
  3. janito/agent/templates/profiles/system_prompt_template_main.txt.j2 +3 -1
  4. janito/cli/chat_mode/bindings.py +6 -0
  5. janito/cli/chat_mode/session.py +16 -0
  6. janito/cli/chat_mode/shell/autocomplete.py +21 -21
  7. janito/cli/chat_mode/shell/commands/__init__.py +3 -2
  8. janito/cli/chat_mode/shell/commands/clear.py +12 -12
  9. janito/cli/chat_mode/shell/commands/exec.py +27 -0
  10. janito/cli/chat_mode/shell/commands/multi.py +51 -51
  11. janito/cli/chat_mode/shell/commands/tools.py +17 -6
  12. janito/cli/chat_mode/shell/input_history.py +62 -62
  13. janito/cli/chat_mode/shell/session/manager.py +1 -0
  14. janito/cli/chat_mode/toolbar.py +3 -1
  15. janito/cli/cli_commands/list_models.py +35 -35
  16. janito/cli/cli_commands/list_providers.py +9 -9
  17. janito/cli/cli_commands/list_tools.py +53 -53
  18. janito/cli/cli_commands/model_selection.py +50 -50
  19. janito/cli/cli_commands/model_utils.py +13 -2
  20. janito/cli/cli_commands/set_api_key.py +19 -19
  21. janito/cli/cli_commands/show_config.py +51 -51
  22. janito/cli/cli_commands/show_system_prompt.py +62 -62
  23. janito/cli/config.py +2 -1
  24. janito/cli/core/__init__.py +4 -4
  25. janito/cli/core/event_logger.py +59 -59
  26. janito/cli/core/getters.py +3 -1
  27. janito/cli/core/runner.py +27 -6
  28. janito/cli/core/setters.py +5 -1
  29. janito/cli/core/unsetters.py +54 -54
  30. janito/cli/main_cli.py +12 -1
  31. janito/cli/prompt_core.py +5 -2
  32. janito/cli/rich_terminal_reporter.py +22 -3
  33. janito/cli/single_shot_mode/__init__.py +6 -6
  34. janito/cli/single_shot_mode/handler.py +11 -1
  35. janito/cli/verbose_output.py +1 -1
  36. janito/config.py +5 -5
  37. janito/config_manager.py +2 -0
  38. janito/driver_events.py +14 -0
  39. janito/drivers/anthropic/driver.py +113 -113
  40. janito/drivers/azure_openai/driver.py +38 -3
  41. janito/drivers/driver_registry.py +0 -2
  42. janito/drivers/openai/driver.py +196 -36
  43. janito/formatting_token.py +54 -54
  44. janito/i18n/__init__.py +35 -35
  45. janito/i18n/messages.py +23 -23
  46. janito/i18n/pt.py +47 -47
  47. janito/llm/__init__.py +5 -5
  48. janito/llm/agent.py +443 -443
  49. janito/llm/auth.py +1 -0
  50. janito/llm/driver.py +7 -1
  51. janito/llm/driver_config.py +1 -0
  52. janito/llm/driver_config_builder.py +34 -34
  53. janito/llm/driver_input.py +12 -12
  54. janito/llm/message_parts.py +60 -60
  55. janito/llm/model.py +38 -38
  56. janito/llm/provider.py +196 -196
  57. janito/provider_config.py +7 -3
  58. janito/provider_registry.py +29 -5
  59. janito/providers/__init__.py +1 -0
  60. janito/providers/anthropic/model_info.py +22 -22
  61. janito/providers/anthropic/provider.py +2 -2
  62. janito/providers/azure_openai/model_info.py +7 -6
  63. janito/providers/azure_openai/provider.py +44 -2
  64. janito/providers/deepseek/__init__.py +1 -1
  65. janito/providers/deepseek/model_info.py +16 -16
  66. janito/providers/deepseek/provider.py +91 -91
  67. janito/providers/google/model_info.py +21 -29
  68. janito/providers/google/provider.py +49 -38
  69. janito/providers/mistralai/provider.py +2 -2
  70. janito/providers/openai/model_info.py +0 -11
  71. janito/providers/openai/provider.py +1 -1
  72. janito/providers/provider_static_info.py +2 -3
  73. janito/providers/registry.py +26 -26
  74. janito/tools/adapters/__init__.py +1 -1
  75. janito/tools/adapters/local/__init__.py +62 -62
  76. janito/tools/adapters/local/adapter.py +33 -11
  77. janito/tools/adapters/local/ask_user.py +102 -102
  78. janito/tools/adapters/local/copy_file.py +84 -84
  79. janito/tools/adapters/local/create_directory.py +69 -69
  80. janito/tools/adapters/local/create_file.py +82 -82
  81. janito/tools/adapters/local/delete_text_in_file.py +4 -7
  82. janito/tools/adapters/local/fetch_url.py +97 -97
  83. janito/tools/adapters/local/find_files.py +138 -140
  84. janito/tools/adapters/local/get_file_outline/__init__.py +1 -1
  85. janito/tools/adapters/local/get_file_outline/core.py +117 -151
  86. janito/tools/adapters/local/get_file_outline/java_outline.py +40 -0
  87. janito/tools/adapters/local/get_file_outline/markdown_outline.py +14 -14
  88. janito/tools/adapters/local/get_file_outline/python_outline.py +303 -303
  89. janito/tools/adapters/local/get_file_outline/python_outline_v2.py +156 -156
  90. janito/tools/adapters/local/get_file_outline/search_outline.py +33 -33
  91. janito/tools/adapters/local/move_file.py +3 -13
  92. janito/tools/adapters/local/open_html_in_browser.py +24 -29
  93. janito/tools/adapters/local/open_url.py +3 -2
  94. janito/tools/adapters/local/python_code_run.py +166 -166
  95. janito/tools/adapters/local/python_command_run.py +164 -164
  96. janito/tools/adapters/local/python_file_run.py +163 -163
  97. janito/tools/adapters/local/remove_directory.py +6 -17
  98. janito/tools/adapters/local/remove_file.py +9 -15
  99. janito/tools/adapters/local/replace_text_in_file.py +6 -9
  100. janito/tools/adapters/local/run_bash_command.py +176 -176
  101. janito/tools/adapters/local/run_powershell_command.py +219 -219
  102. janito/tools/adapters/local/search_text/__init__.py +1 -1
  103. janito/tools/adapters/local/search_text/core.py +201 -201
  104. janito/tools/adapters/local/search_text/match_lines.py +1 -1
  105. janito/tools/adapters/local/search_text/pattern_utils.py +73 -73
  106. janito/tools/adapters/local/search_text/traverse_directory.py +145 -145
  107. janito/tools/adapters/local/validate_file_syntax/__init__.py +1 -1
  108. janito/tools/adapters/local/validate_file_syntax/core.py +106 -106
  109. janito/tools/adapters/local/validate_file_syntax/css_validator.py +35 -35
  110. janito/tools/adapters/local/validate_file_syntax/html_validator.py +93 -93
  111. janito/tools/adapters/local/validate_file_syntax/js_validator.py +27 -27
  112. janito/tools/adapters/local/validate_file_syntax/json_validator.py +6 -6
  113. janito/tools/adapters/local/validate_file_syntax/markdown_validator.py +109 -109
  114. janito/tools/adapters/local/validate_file_syntax/ps1_validator.py +32 -32
  115. janito/tools/adapters/local/validate_file_syntax/python_validator.py +5 -5
  116. janito/tools/adapters/local/validate_file_syntax/xml_validator.py +11 -11
  117. janito/tools/adapters/local/validate_file_syntax/yaml_validator.py +6 -6
  118. janito/tools/adapters/local/view_file.py +167 -167
  119. janito/tools/inspect_registry.py +17 -17
  120. janito/tools/tool_base.py +105 -105
  121. janito/tools/tool_events.py +58 -58
  122. janito/tools/tool_run_exception.py +12 -12
  123. janito/tools/tool_use_tracker.py +81 -81
  124. janito/tools/tool_utils.py +45 -45
  125. janito/tools/tools_adapter.py +78 -6
  126. janito/tools/tools_schema.py +104 -104
  127. janito/version.py +4 -4
  128. {janito-2.1.1.dist-info → janito-2.3.0.dist-info}/METADATA +388 -232
  129. janito-2.3.0.dist-info/RECORD +181 -0
  130. janito-2.3.0.dist-info/licenses/LICENSE +21 -0
  131. janito/cli/chat_mode/shell/commands/last.py +0 -137
  132. janito/drivers/google_genai/driver.py +0 -54
  133. janito/drivers/google_genai/schema_generator.py +0 -67
  134. janito-2.1.1.dist-info/RECORD +0 -181
  135. {janito-2.1.1.dist-info → janito-2.3.0.dist-info}/WHEEL +0 -0
  136. {janito-2.1.1.dist-info → janito-2.3.0.dist-info}/entry_points.txt +0 -0
  137. {janito-2.1.1.dist-info → janito-2.3.0.dist-info}/top_level.txt +0 -0
@@ -1,167 +1,167 @@
1
- from janito.tools.tool_base import ToolBase
2
- from janito.report_events import ReportAction
3
- from janito.tools.adapters.local.adapter import register_local_tool
4
- from janito.tools.tool_utils import pluralize
5
- from janito.i18n import tr
6
-
7
-
8
- @register_local_tool
9
- class ViewFileTool(ToolBase):
10
- """
11
- Read lines from a file. You can specify a line range, or read the entire file by simply omitting the from_line and to_line parameters.
12
-
13
- Args:
14
- file_path (str): Path to the file to read lines from.
15
- from_line (int, optional): Starting line number (1-based). Omit to start from the first line.
16
- to_line (int, optional): Ending line number (1-based). Omit to read to the end of the file.
17
-
18
- To read the full file, just provide file_path and leave from_line and to_line unset.
19
-
20
- Returns:
21
- str: File content with a header indicating the file name and line range. Example:
22
- - "---\nFile: /path/to/file.py | Lines: 1-10 (of 100)\n---\n<lines...>"
23
- - "---\nFile: /path/to/file.py | All lines (total: 100 (all))\n---\n<all lines...>"
24
- - "Error reading file: <error message>"
25
- - "❗ not found"
26
- """
27
-
28
- tool_name = "view_file"
29
-
30
- def run(self, file_path: str, from_line: int = None, to_line: int = None) -> str:
31
- import os
32
- from janito.tools.tool_utils import display_path
33
-
34
- disp_path = display_path(file_path)
35
- self.report_action(
36
- tr("📖 View '{disp_path}'", disp_path=disp_path),
37
- ReportAction.READ,
38
- )
39
- try:
40
- if os.path.isdir(file_path):
41
- return self._list_directory(file_path, disp_path)
42
- lines = self._read_file_lines(file_path)
43
- selected, selected_len, total_lines = self._select_lines(
44
- lines, from_line, to_line
45
- )
46
- self._report_success(selected_len, from_line, to_line, total_lines)
47
- header = self._format_header(
48
- disp_path, from_line, to_line, selected_len, total_lines
49
- )
50
- return header + "".join(selected)
51
- except FileNotFoundError as e:
52
- self.report_warning(tr("❗ not found"))
53
- return f"Error reading file: {e}"
54
- except Exception as e:
55
- self.report_error(tr(" ❌ Error: {error}", error=e))
56
- return tr("Error reading file: {error}", error=e)
57
-
58
- def _list_directory(self, file_path, disp_path):
59
- import os
60
-
61
- try:
62
- entries = os.listdir(file_path)
63
- entries.sort()
64
- # Suffix subdirectories with '/'
65
- formatted_entries = []
66
- for entry in entries:
67
- full_path = os.path.join(file_path, entry)
68
- if os.path.isdir(full_path):
69
- formatted_entries.append(entry + "/")
70
- else:
71
- formatted_entries.append(entry)
72
- header = (
73
- f"--- view_file: {disp_path} [directory, {len(entries)} entries] ---\n"
74
- )
75
- listing = "\n".join(formatted_entries)
76
- self.report_success(tr("📁 Directory ({count} items)", count=len(entries)))
77
- return header + listing + "\n"
78
- except Exception as e:
79
- self.report_error(tr(" ❌ Error listing directory: {error}", error=e))
80
- return tr("Error listing directory: {error}", error=e)
81
-
82
- def _read_file_lines(self, file_path):
83
- """Read all lines from the file."""
84
- with open(file_path, "r", encoding="utf-8", errors="replace") as f:
85
- return f.readlines()
86
-
87
- def _select_lines(self, lines, from_line, to_line):
88
- """Select the requested lines and return them with their count and total lines."""
89
- selected = lines[
90
- (from_line - 1 if from_line else 0) : (to_line if to_line else None)
91
- ]
92
- selected_len = len(selected)
93
- total_lines = len(lines)
94
- return selected, selected_len, total_lines
95
-
96
- def _report_success(self, selected_len, from_line, to_line, total_lines):
97
- """Report the success message after reading lines."""
98
- if from_line and to_line:
99
- requested = to_line - from_line + 1
100
- at_end = to_line >= total_lines or selected_len < requested
101
- if at_end:
102
- self.report_success(
103
- tr(
104
- " ✅ {selected_len} {line_word} (end)",
105
- selected_len=selected_len,
106
- line_word=pluralize("line", selected_len),
107
- )
108
- )
109
- elif to_line < total_lines:
110
- self.report_success(
111
- tr(
112
- " ✅ {selected_len} {line_word} ({remaining} to end)",
113
- selected_len=selected_len,
114
- line_word=pluralize("line", selected_len),
115
- remaining=total_lines - to_line,
116
- )
117
- )
118
- else:
119
- self.report_success(
120
- tr(
121
- " ✅ {selected_len} {line_word} (all)",
122
- selected_len=selected_len,
123
- line_word=pluralize("line", selected_len),
124
- )
125
- )
126
-
127
- def _format_header(self, disp_path, from_line, to_line, selected_len, total_lines):
128
- """Format the header for the output."""
129
- if from_line and to_line:
130
- requested = to_line - from_line + 1
131
- at_end = selected_len < requested or to_line >= total_lines
132
- if at_end:
133
- return tr(
134
- "---\n{disp_path} {from_line}-{to_line} (end)\n---\n",
135
- disp_path=disp_path,
136
- from_line=from_line,
137
- to_line=to_line,
138
- )
139
- else:
140
- return tr(
141
- "---\n{disp_path} {from_line}-{to_line} (of {total_lines})\n---\n",
142
- disp_path=disp_path,
143
- from_line=from_line,
144
- to_line=to_line,
145
- total_lines=total_lines,
146
- )
147
- elif from_line:
148
- return tr(
149
- "---\n{disp_path} {from_line}-END (of {total_lines})\n---\n",
150
- disp_path=disp_path,
151
- from_line=from_line,
152
- total_lines=total_lines,
153
- )
154
- else:
155
- return tr(
156
- "---\n{disp_path} All lines (total: {total_lines} (all))\n---\n",
157
- disp_path=disp_path,
158
- total_lines=total_lines,
159
- )
160
-
161
- def _handle_read_error(self, e):
162
- """Handle file read errors and report appropriately."""
163
- if isinstance(e, FileNotFoundError):
164
- self.report_error(tr("❗ not found"), ReportAction.READ)
165
- return tr("❗ not found")
166
- self.report_error(tr(" ❌ Error: {error}", error=e), ReportAction.READ)
167
- return tr("Error reading file: {error}", error=e)
1
+ from janito.tools.tool_base import ToolBase
2
+ from janito.report_events import ReportAction
3
+ from janito.tools.adapters.local.adapter import register_local_tool
4
+ from janito.tools.tool_utils import pluralize
5
+ from janito.i18n import tr
6
+
7
+
8
+ @register_local_tool
9
+ class ViewFileTool(ToolBase):
10
+ """
11
+ Read lines from a file. You can specify a line range, or read the entire file by simply omitting the from_line and to_line parameters.
12
+
13
+ Args:
14
+ file_path (str): Path to the file to read lines from.
15
+ from_line (int, optional): Starting line number (1-based). Omit to start from the first line.
16
+ to_line (int, optional): Ending line number (1-based). Omit to read to the end of the file.
17
+
18
+ To read the full file, just provide file_path and leave from_line and to_line unset.
19
+
20
+ Returns:
21
+ str: File content with a header indicating the file name and line range. Example:
22
+ - "---\nFile: /path/to/file.py | Lines: 1-10 (of 100)\n---\n<lines...>"
23
+ - "---\nFile: /path/to/file.py | All lines (total: 100 (all))\n---\n<all lines...>"
24
+ - "Error reading file: <error message>"
25
+ - "❗ not found"
26
+ """
27
+
28
+ tool_name = "view_file"
29
+
30
+ def run(self, file_path: str, from_line: int = None, to_line: int = None) -> str:
31
+ import os
32
+ from janito.tools.tool_utils import display_path
33
+
34
+ disp_path = display_path(file_path)
35
+ self.report_action(
36
+ tr("📖 View '{disp_path}'", disp_path=disp_path),
37
+ ReportAction.READ,
38
+ )
39
+ try:
40
+ if os.path.isdir(file_path):
41
+ return self._list_directory(file_path, disp_path)
42
+ lines = self._read_file_lines(file_path)
43
+ selected, selected_len, total_lines = self._select_lines(
44
+ lines, from_line, to_line
45
+ )
46
+ self._report_success(selected_len, from_line, to_line, total_lines)
47
+ header = self._format_header(
48
+ disp_path, from_line, to_line, selected_len, total_lines
49
+ )
50
+ return header + "".join(selected)
51
+ except FileNotFoundError as e:
52
+ self.report_warning(tr("❗ not found"))
53
+ return f"Error reading file: {e}"
54
+ except Exception as e:
55
+ self.report_error(tr(" ❌ Error: {error}", error=e))
56
+ return tr("Error reading file: {error}", error=e)
57
+
58
+ def _list_directory(self, file_path, disp_path):
59
+ import os
60
+
61
+ try:
62
+ entries = os.listdir(file_path)
63
+ entries.sort()
64
+ # Suffix subdirectories with '/'
65
+ formatted_entries = []
66
+ for entry in entries:
67
+ full_path = os.path.join(file_path, entry)
68
+ if os.path.isdir(full_path):
69
+ formatted_entries.append(entry + "/")
70
+ else:
71
+ formatted_entries.append(entry)
72
+ header = (
73
+ f"--- view_file: {disp_path} [directory, {len(entries)} entries] ---\n"
74
+ )
75
+ listing = "\n".join(formatted_entries)
76
+ self.report_success(tr("📁 Directory ({count} items)", count=len(entries)))
77
+ return header + listing + "\n"
78
+ except Exception as e:
79
+ self.report_error(tr(" ❌ Error listing directory: {error}", error=e))
80
+ return tr("Error listing directory: {error}", error=e)
81
+
82
+ def _read_file_lines(self, file_path):
83
+ """Read all lines from the file."""
84
+ with open(file_path, "r", encoding="utf-8", errors="replace") as f:
85
+ return f.readlines()
86
+
87
+ def _select_lines(self, lines, from_line, to_line):
88
+ """Select the requested lines and return them with their count and total lines."""
89
+ selected = lines[
90
+ (from_line - 1 if from_line else 0) : (to_line if to_line else None)
91
+ ]
92
+ selected_len = len(selected)
93
+ total_lines = len(lines)
94
+ return selected, selected_len, total_lines
95
+
96
+ def _report_success(self, selected_len, from_line, to_line, total_lines):
97
+ """Report the success message after reading lines."""
98
+ if from_line and to_line:
99
+ requested = to_line - from_line + 1
100
+ at_end = to_line >= total_lines or selected_len < requested
101
+ if at_end:
102
+ self.report_success(
103
+ tr(
104
+ " ✅ {selected_len} {line_word} (end)",
105
+ selected_len=selected_len,
106
+ line_word=pluralize("line", selected_len),
107
+ )
108
+ )
109
+ elif to_line < total_lines:
110
+ self.report_success(
111
+ tr(
112
+ " ✅ {selected_len} {line_word} ({remaining} to end)",
113
+ selected_len=selected_len,
114
+ line_word=pluralize("line", selected_len),
115
+ remaining=total_lines - to_line,
116
+ )
117
+ )
118
+ else:
119
+ self.report_success(
120
+ tr(
121
+ " ✅ {selected_len} {line_word} (all)",
122
+ selected_len=selected_len,
123
+ line_word=pluralize("line", selected_len),
124
+ )
125
+ )
126
+
127
+ def _format_header(self, disp_path, from_line, to_line, selected_len, total_lines):
128
+ """Format the header for the output."""
129
+ if from_line and to_line:
130
+ requested = to_line - from_line + 1
131
+ at_end = selected_len < requested or to_line >= total_lines
132
+ if at_end:
133
+ return tr(
134
+ "---\n{disp_path} {from_line}-{to_line} (end)\n---\n",
135
+ disp_path=disp_path,
136
+ from_line=from_line,
137
+ to_line=to_line,
138
+ )
139
+ else:
140
+ return tr(
141
+ "---\n{disp_path} {from_line}-{to_line} (of {total_lines})\n---\n",
142
+ disp_path=disp_path,
143
+ from_line=from_line,
144
+ to_line=to_line,
145
+ total_lines=total_lines,
146
+ )
147
+ elif from_line:
148
+ return tr(
149
+ "---\n{disp_path} {from_line}-END (of {total_lines})\n---\n",
150
+ disp_path=disp_path,
151
+ from_line=from_line,
152
+ total_lines=total_lines,
153
+ )
154
+ else:
155
+ return tr(
156
+ "---\n{disp_path} All lines (total: {total_lines} (all))\n---\n",
157
+ disp_path=disp_path,
158
+ total_lines=total_lines,
159
+ )
160
+
161
+ def _handle_read_error(self, e):
162
+ """Handle file read errors and report appropriately."""
163
+ if isinstance(e, FileNotFoundError):
164
+ self.report_error(tr("❗ not found"), ReportAction.READ)
165
+ return tr("❗ not found")
166
+ self.report_error(tr(" ❌ Error: {error}", error=e), ReportAction.READ)
167
+ return tr("Error reading file: {error}", error=e)
@@ -1,17 +1,17 @@
1
- def check_tools_registry():
2
- # Import and use the singleton tools adapter instance
3
- from janito.tools.adapters.local import local_tools_adapter
4
-
5
- print("Available tool names:", local_tools_adapter.list_tools())
6
- print(
7
- "Available tool classes:",
8
- [cls.__name__ for cls in local_tools_adapter.get_tool_classes()],
9
- )
10
- print(
11
- "Available tool instances:",
12
- [tool.name for tool in local_tools_adapter.get_tools()],
13
- )
14
-
15
-
16
- if __name__ == "__main__":
17
- check_tools_registry()
1
+ def check_tools_registry():
2
+ # Import and use the singleton tools adapter instance
3
+ from janito.tools.adapters.local import local_tools_adapter
4
+
5
+ print("Available tool names:", local_tools_adapter.list_tools())
6
+ print(
7
+ "Available tool classes:",
8
+ [cls.__name__ for cls in local_tools_adapter.get_tool_classes()],
9
+ )
10
+ print(
11
+ "Available tool instances:",
12
+ [tool.name for tool in local_tools_adapter.get_tools()],
13
+ )
14
+
15
+
16
+ if __name__ == "__main__":
17
+ check_tools_registry()
janito/tools/tool_base.py CHANGED
@@ -1,105 +1,105 @@
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
- class ToolBase:
6
- """
7
- Base class for all tools in the janito project.
8
- Extend this class to implement specific tool functionality.
9
- """
10
- provides_execution = False # Indicates if the tool provides execution capability (default: False)
11
-
12
- def __init__(self, name=None, event_bus=None):
13
- self.name = name or self.__class__.__name__
14
- self._event_bus = event_bus or default_event_bus
15
-
16
- @property
17
- def event_bus(self):
18
- return self._event_bus
19
-
20
- @event_bus.setter
21
- def event_bus(self, bus):
22
- self._event_bus = bus or default_event_bus
23
-
24
- def report_action(self, message: str, action: ReportAction, context: dict = None):
25
- """
26
- Report that a tool action is starting. This should be the first reporting call for every tool action.
27
- """
28
- self._event_bus.publish(
29
- ReportEvent(
30
- subtype=ReportSubtype.ACTION_INFO,
31
- message=" " + message,
32
- action=action,
33
- tool=self.name,
34
- context=context,
35
- )
36
- )
37
-
38
- def report_info(self, message: str, context: dict = None):
39
- self._event_bus.publish(
40
- ReportEvent(
41
- subtype=ReportSubtype.ACTION_INFO,
42
- message=message,
43
- action=None,
44
- tool=self.name,
45
- context=context,
46
- )
47
- )
48
-
49
- def report_error(self, message: str, context: dict = None):
50
- self._event_bus.publish(
51
- ReportEvent(
52
- subtype=ReportSubtype.ERROR,
53
- message=message,
54
- action=None,
55
- tool=self.name,
56
- context=context,
57
- )
58
- )
59
-
60
- def report_success(self, message: str, context: dict = None):
61
- self._event_bus.publish(
62
- ReportEvent(
63
- subtype=ReportSubtype.SUCCESS,
64
- message=message,
65
- action=None,
66
- tool=self.name,
67
- context=context,
68
- )
69
- )
70
-
71
- def report_warning(self, message: str, context: dict = None):
72
- self._event_bus.publish(
73
- ReportEvent(
74
- subtype=ReportSubtype.WARNING,
75
- message=message,
76
- action=None,
77
- tool=self.name,
78
- context=context,
79
- )
80
- )
81
-
82
- def report_stdout(self, message: str, context: dict = None):
83
- self._event_bus.publish(
84
- ReportEvent(
85
- subtype=ReportSubtype.STDOUT,
86
- message=message,
87
- action=None,
88
- tool=self.name,
89
- context=context,
90
- )
91
- )
92
-
93
- def report_stderr(self, message: str, context: dict = None):
94
- self._event_bus.publish(
95
- ReportEvent(
96
- subtype=ReportSubtype.STDERR,
97
- message=message,
98
- action=None,
99
- tool=self.name,
100
- context=context,
101
- )
102
- )
103
-
104
- def run(self, *args, **kwargs):
105
- 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
+ class ToolBase:
6
+ """
7
+ Base class for all tools in the janito project.
8
+ Extend this class to implement specific tool functionality.
9
+ """
10
+ provides_execution = False # Indicates if the tool provides execution capability (default: False)
11
+
12
+ def __init__(self, name=None, event_bus=None):
13
+ self.name = name or self.__class__.__name__
14
+ self._event_bus = event_bus or default_event_bus
15
+
16
+ @property
17
+ def event_bus(self):
18
+ return self._event_bus
19
+
20
+ @event_bus.setter
21
+ def event_bus(self, bus):
22
+ self._event_bus = bus or default_event_bus
23
+
24
+ def report_action(self, message: str, action: ReportAction, context: dict = None):
25
+ """
26
+ Report that a tool action is starting. This should be the first reporting call for every tool action.
27
+ """
28
+ self._event_bus.publish(
29
+ ReportEvent(
30
+ subtype=ReportSubtype.ACTION_INFO,
31
+ message=" " + message,
32
+ action=action,
33
+ tool=self.name,
34
+ context=context,
35
+ )
36
+ )
37
+
38
+ def report_info(self, message: str, context: dict = None):
39
+ self._event_bus.publish(
40
+ ReportEvent(
41
+ subtype=ReportSubtype.ACTION_INFO,
42
+ message=message,
43
+ action=None,
44
+ tool=self.name,
45
+ context=context,
46
+ )
47
+ )
48
+
49
+ def report_error(self, message: str, context: dict = None):
50
+ self._event_bus.publish(
51
+ ReportEvent(
52
+ subtype=ReportSubtype.ERROR,
53
+ message=message,
54
+ action=None,
55
+ tool=self.name,
56
+ context=context,
57
+ )
58
+ )
59
+
60
+ def report_success(self, message: str, context: dict = None):
61
+ self._event_bus.publish(
62
+ ReportEvent(
63
+ subtype=ReportSubtype.SUCCESS,
64
+ message=message,
65
+ action=None,
66
+ tool=self.name,
67
+ context=context,
68
+ )
69
+ )
70
+
71
+ def report_warning(self, message: str, context: dict = None):
72
+ self._event_bus.publish(
73
+ ReportEvent(
74
+ subtype=ReportSubtype.WARNING,
75
+ message=message,
76
+ action=None,
77
+ tool=self.name,
78
+ context=context,
79
+ )
80
+ )
81
+
82
+ def report_stdout(self, message: str, context: dict = None):
83
+ self._event_bus.publish(
84
+ ReportEvent(
85
+ subtype=ReportSubtype.STDOUT,
86
+ message=message,
87
+ action=None,
88
+ tool=self.name,
89
+ context=context,
90
+ )
91
+ )
92
+
93
+ def report_stderr(self, message: str, context: dict = None):
94
+ self._event_bus.publish(
95
+ ReportEvent(
96
+ subtype=ReportSubtype.STDERR,
97
+ message=message,
98
+ action=None,
99
+ tool=self.name,
100
+ context=context,
101
+ )
102
+ )
103
+
104
+ def run(self, *args, **kwargs):
105
+ raise NotImplementedError("Subclasses must implement the run method.")