janito 1.14.3__py3-none-any.whl → 2.0.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.
- janito/__init__.py +6 -1
- janito/__main__.py +1 -1
- janito/agent/setup_agent.py +139 -0
- janito/agent/templates/profiles/{system_prompt_template_base.txt.j2 → system_prompt_template_main.txt.j2} +1 -1
- janito/cli/__init__.py +9 -0
- janito/cli/chat_mode/bindings.py +37 -0
- janito/cli/chat_mode/chat_entry.py +23 -0
- janito/cli/chat_mode/prompt_style.py +19 -0
- janito/cli/chat_mode/session.py +272 -0
- janito/{shell/prompt/completer.py → cli/chat_mode/shell/autocomplete.py} +7 -6
- janito/cli/chat_mode/shell/commands/__init__.py +55 -0
- janito/cli/chat_mode/shell/commands/base.py +9 -0
- janito/cli/chat_mode/shell/commands/clear.py +12 -0
- janito/{shell → cli/chat_mode/shell}/commands/conversation_restart.py +34 -30
- janito/cli/chat_mode/shell/commands/edit.py +25 -0
- janito/cli/chat_mode/shell/commands/help.py +16 -0
- janito/cli/chat_mode/shell/commands/history_view.py +93 -0
- janito/cli/chat_mode/shell/commands/lang.py +25 -0
- janito/cli/chat_mode/shell/commands/last.py +137 -0
- janito/cli/chat_mode/shell/commands/livelogs.py +49 -0
- janito/cli/chat_mode/shell/commands/multi.py +51 -0
- janito/cli/chat_mode/shell/commands/prompt.py +64 -0
- janito/cli/chat_mode/shell/commands/role.py +36 -0
- janito/cli/chat_mode/shell/commands/session.py +40 -0
- janito/{shell → cli/chat_mode/shell}/commands/session_control.py +2 -2
- janito/cli/chat_mode/shell/commands/termweb_log.py +92 -0
- janito/cli/chat_mode/shell/commands/tools.py +32 -0
- janito/{shell → cli/chat_mode/shell}/commands/utility.py +4 -7
- janito/{shell → cli/chat_mode/shell}/commands/verbose.py +5 -5
- janito/cli/chat_mode/shell/session/__init__.py +1 -0
- janito/{shell → cli/chat_mode/shell}/session/manager.py +9 -1
- janito/cli/chat_mode/toolbar.py +90 -0
- janito/cli/cli_commands/list_models.py +35 -0
- janito/cli/cli_commands/list_providers.py +9 -0
- janito/cli/cli_commands/list_tools.py +53 -0
- janito/cli/cli_commands/model_selection.py +50 -0
- janito/cli/cli_commands/model_utils.py +84 -0
- janito/cli/cli_commands/set_api_key.py +19 -0
- janito/cli/cli_commands/show_config.py +51 -0
- janito/cli/cli_commands/show_system_prompt.py +62 -0
- janito/cli/config.py +28 -0
- janito/cli/console.py +3 -0
- janito/cli/core/__init__.py +4 -0
- janito/cli/core/event_logger.py +59 -0
- janito/cli/core/getters.py +31 -0
- janito/cli/core/runner.py +141 -0
- janito/cli/core/setters.py +174 -0
- janito/cli/core/unsetters.py +54 -0
- janito/cli/main.py +8 -196
- janito/cli/main_cli.py +312 -0
- janito/cli/prompt_core.py +230 -0
- janito/cli/prompt_handler.py +6 -0
- janito/cli/rich_terminal_reporter.py +101 -0
- janito/cli/single_shot_mode/__init__.py +6 -0
- janito/cli/single_shot_mode/handler.py +137 -0
- janito/cli/termweb_starter.py +73 -24
- janito/cli/utils.py +25 -0
- janito/cli/verbose_output.py +196 -0
- janito/config.py +5 -0
- janito/config_manager.py +110 -0
- janito/conversation_history.py +30 -0
- janito/{agent/tools_utils/dir_walk_utils.py → dir_walk_utils.py} +3 -2
- janito/driver_events.py +98 -0
- janito/drivers/anthropic/driver.py +113 -0
- janito/drivers/azure_openai/driver.py +36 -0
- janito/drivers/driver_registry.py +33 -0
- janito/drivers/google_genai/driver.py +54 -0
- janito/drivers/google_genai/schema_generator.py +67 -0
- janito/drivers/mistralai/driver.py +41 -0
- janito/drivers/openai/driver.py +334 -0
- janito/event_bus/__init__.py +2 -0
- janito/event_bus/bus.py +68 -0
- janito/event_bus/event.py +15 -0
- janito/event_bus/handler.py +31 -0
- janito/event_bus/queue_bus.py +57 -0
- janito/exceptions.py +23 -0
- janito/formatting_token.py +54 -0
- janito/i18n/pt.py +1 -0
- janito/llm/__init__.py +5 -0
- janito/llm/agent.py +443 -0
- janito/llm/auth.py +62 -0
- janito/llm/driver.py +239 -0
- janito/llm/driver_config.py +34 -0
- janito/llm/driver_config_builder.py +34 -0
- janito/llm/driver_input.py +12 -0
- janito/llm/message_parts.py +60 -0
- janito/llm/model.py +38 -0
- janito/llm/provider.py +187 -0
- janito/perf_singleton.py +3 -0
- janito/performance_collector.py +167 -0
- janito/provider_config.py +98 -0
- janito/provider_registry.py +152 -0
- janito/providers/__init__.py +7 -0
- janito/providers/anthropic/model_info.py +22 -0
- janito/providers/anthropic/provider.py +65 -0
- janito/providers/azure_openai/model_info.py +15 -0
- janito/providers/azure_openai/provider.py +72 -0
- janito/providers/deepseek/__init__.py +1 -0
- janito/providers/deepseek/model_info.py +16 -0
- janito/providers/deepseek/provider.py +91 -0
- janito/providers/google/__init__.py +1 -0
- janito/providers/google/model_info.py +40 -0
- janito/providers/google/provider.py +69 -0
- janito/providers/mistralai/model_info.py +37 -0
- janito/providers/mistralai/provider.py +69 -0
- janito/providers/openai/__init__.py +1 -0
- janito/providers/openai/model_info.py +137 -0
- janito/providers/openai/provider.py +107 -0
- janito/providers/openai/schema_generator.py +63 -0
- janito/providers/provider_static_info.py +21 -0
- janito/providers/registry.py +26 -0
- janito/report_events.py +38 -0
- janito/termweb/app.py +1 -1
- janito/tools/__init__.py +16 -0
- janito/tools/adapters/__init__.py +1 -0
- janito/tools/adapters/local/__init__.py +54 -0
- janito/tools/adapters/local/adapter.py +92 -0
- janito/{agent/tools → tools/adapters/local}/ask_user.py +30 -13
- janito/tools/adapters/local/copy_file.py +84 -0
- janito/{agent/tools → tools/adapters/local}/create_directory.py +11 -10
- janito/tools/adapters/local/create_file.py +82 -0
- janito/tools/adapters/local/delete_text_in_file.py +136 -0
- janito/{agent/tools → tools/adapters/local}/fetch_url.py +18 -19
- janito/tools/adapters/local/find_files.py +140 -0
- janito/tools/adapters/local/get_file_outline/core.py +151 -0
- janito/{agent/tools → tools/adapters/local}/get_file_outline/python_outline.py +125 -0
- janito/tools/adapters/local/get_file_outline/python_outline_v2.py +156 -0
- janito/{agent/tools → tools/adapters/local}/get_file_outline/search_outline.py +12 -7
- janito/{agent/tools → tools/adapters/local}/move_file.py +13 -9
- janito/{agent/tools → tools/adapters/local}/open_url.py +7 -5
- janito/tools/adapters/local/python_code_run.py +165 -0
- janito/tools/adapters/local/python_command_run.py +163 -0
- janito/tools/adapters/local/python_file_run.py +162 -0
- janito/{agent/tools → tools/adapters/local}/remove_directory.py +15 -9
- janito/{agent/tools → tools/adapters/local}/remove_file.py +17 -14
- janito/{agent/tools → tools/adapters/local}/replace_text_in_file.py +27 -22
- janito/tools/adapters/local/run_bash_command.py +176 -0
- janito/tools/adapters/local/run_powershell_command.py +219 -0
- janito/{agent/tools → tools/adapters/local}/search_text/core.py +32 -12
- janito/{agent/tools → tools/adapters/local}/search_text/match_lines.py +13 -4
- janito/{agent/tools → tools/adapters/local}/search_text/pattern_utils.py +12 -4
- janito/{agent/tools → tools/adapters/local}/search_text/traverse_directory.py +15 -2
- janito/{agent/tools → tools/adapters/local}/validate_file_syntax/core.py +12 -11
- janito/{agent/tools → tools/adapters/local}/validate_file_syntax/css_validator.py +1 -1
- janito/{agent/tools → tools/adapters/local}/validate_file_syntax/html_validator.py +1 -1
- janito/{agent/tools → tools/adapters/local}/validate_file_syntax/js_validator.py +1 -1
- janito/{agent/tools → tools/adapters/local}/validate_file_syntax/json_validator.py +1 -1
- janito/{agent/tools → tools/adapters/local}/validate_file_syntax/markdown_validator.py +1 -1
- janito/{agent/tools → tools/adapters/local}/validate_file_syntax/ps1_validator.py +1 -1
- janito/{agent/tools → tools/adapters/local}/validate_file_syntax/python_validator.py +1 -1
- janito/{agent/tools → tools/adapters/local}/validate_file_syntax/xml_validator.py +1 -1
- janito/{agent/tools → tools/adapters/local}/validate_file_syntax/yaml_validator.py +1 -1
- janito/{agent/tools/get_lines.py → tools/adapters/local/view_file.py} +45 -27
- janito/tools/inspect_registry.py +17 -0
- janito/tools/tool_base.py +105 -0
- janito/tools/tool_events.py +58 -0
- janito/tools/tool_run_exception.py +12 -0
- janito/{agent → tools}/tool_use_tracker.py +2 -4
- janito/{agent/tools_utils/utils.py → tools/tool_utils.py} +18 -9
- janito/tools/tools_adapter.py +207 -0
- janito/tools/tools_schema.py +104 -0
- janito/utils.py +11 -0
- janito/version.py +4 -0
- janito-2.0.0.dist-info/METADATA +232 -0
- janito-2.0.0.dist-info/RECORD +180 -0
- janito/agent/__init__.py +0 -0
- janito/agent/api_exceptions.py +0 -4
- janito/agent/config.py +0 -147
- janito/agent/config_defaults.py +0 -12
- janito/agent/config_utils.py +0 -0
- janito/agent/content_handler.py +0 -0
- janito/agent/conversation.py +0 -238
- janito/agent/conversation_api.py +0 -306
- janito/agent/conversation_exceptions.py +0 -18
- janito/agent/conversation_tool_calls.py +0 -39
- janito/agent/conversation_ui.py +0 -17
- janito/agent/event.py +0 -24
- janito/agent/event_dispatcher.py +0 -24
- janito/agent/event_handler_protocol.py +0 -5
- janito/agent/event_system.py +0 -15
- janito/agent/llm_conversation_history.py +0 -82
- janito/agent/message_handler.py +0 -20
- janito/agent/message_handler_protocol.py +0 -5
- janito/agent/openai_client.py +0 -149
- janito/agent/openai_schema_generator.py +0 -187
- janito/agent/profile_manager.py +0 -96
- janito/agent/queued_message_handler.py +0 -50
- janito/agent/rich_live.py +0 -32
- janito/agent/rich_message_handler.py +0 -115
- janito/agent/runtime_config.py +0 -36
- janito/agent/test_handler_protocols.py +0 -47
- janito/agent/test_openai_schema_generator.py +0 -93
- janito/agent/tests/__init__.py +0 -1
- janito/agent/tool_base.py +0 -63
- janito/agent/tool_executor.py +0 -122
- janito/agent/tool_registry.py +0 -49
- janito/agent/tools/__init__.py +0 -47
- janito/agent/tools/create_file.py +0 -59
- janito/agent/tools/delete_text_in_file.py +0 -97
- janito/agent/tools/find_files.py +0 -106
- janito/agent/tools/get_file_outline/core.py +0 -81
- janito/agent/tools/present_choices.py +0 -64
- janito/agent/tools/python_command_runner.py +0 -201
- janito/agent/tools/python_file_runner.py +0 -199
- janito/agent/tools/python_stdin_runner.py +0 -208
- janito/agent/tools/replace_file.py +0 -72
- janito/agent/tools/run_bash_command.py +0 -218
- janito/agent/tools/run_powershell_command.py +0 -251
- janito/agent/tools_utils/__init__.py +0 -1
- janito/agent/tools_utils/action_type.py +0 -7
- janito/agent/tools_utils/test_gitignore_utils.py +0 -46
- janito/cli/_livereload_log_utils.py +0 -13
- janito/cli/_print_config.py +0 -96
- janito/cli/_termweb_log_utils.py +0 -17
- janito/cli/_utils.py +0 -9
- janito/cli/arg_parser.py +0 -272
- janito/cli/cli_main.py +0 -281
- janito/cli/config_commands.py +0 -211
- janito/cli/config_runner.py +0 -35
- janito/cli/formatting_runner.py +0 -12
- janito/cli/livereload_starter.py +0 -60
- janito/cli/logging_setup.py +0 -38
- janito/cli/one_shot.py +0 -80
- janito/livereload/app.py +0 -25
- janito/rich_utils.py +0 -59
- janito/shell/__init__.py +0 -0
- janito/shell/commands/__init__.py +0 -61
- janito/shell/commands/config.py +0 -22
- janito/shell/commands/edit.py +0 -24
- janito/shell/commands/history_view.py +0 -18
- janito/shell/commands/lang.py +0 -19
- janito/shell/commands/livelogs.py +0 -42
- janito/shell/commands/prompt.py +0 -62
- janito/shell/commands/termweb_log.py +0 -94
- janito/shell/commands/tools.py +0 -26
- janito/shell/commands/track.py +0 -36
- janito/shell/main.py +0 -326
- janito/shell/prompt/load_prompt.py +0 -57
- janito/shell/prompt/session_setup.py +0 -57
- janito/shell/session/config.py +0 -109
- janito/shell/session/history.py +0 -0
- janito/shell/ui/interactive.py +0 -226
- janito/termweb/static/editor.css +0 -158
- janito/termweb/static/editor.css.bak +0 -145
- janito/termweb/static/editor.html +0 -46
- janito/termweb/static/editor.html.bak +0 -46
- janito/termweb/static/editor.js +0 -265
- janito/termweb/static/editor.js.bak +0 -259
- janito/termweb/static/explorer.html.bak +0 -59
- janito/termweb/static/favicon.ico +0 -0
- janito/termweb/static/favicon.ico.bak +0 -0
- janito/termweb/static/index.html +0 -53
- janito/termweb/static/index.html.bak +0 -54
- janito/termweb/static/index.html.bak.bak +0 -175
- janito/termweb/static/landing.html.bak +0 -36
- janito/termweb/static/termicon.svg +0 -1
- janito/termweb/static/termweb.css +0 -214
- janito/termweb/static/termweb.css.bak +0 -237
- janito/termweb/static/termweb.js +0 -162
- janito/termweb/static/termweb.js.bak +0 -168
- janito/termweb/static/termweb.js.bak.bak +0 -157
- janito/termweb/static/termweb_quickopen.js +0 -135
- janito/termweb/static/termweb_quickopen.js.bak +0 -125
- janito/tests/test_rich_utils.py +0 -44
- janito/web/__init__.py +0 -0
- janito/web/__main__.py +0 -25
- janito/web/app.py +0 -145
- janito-1.14.3.dist-info/METADATA +0 -313
- janito-1.14.3.dist-info/RECORD +0 -162
- janito-1.14.3.dist-info/licenses/LICENSE +0 -21
- /janito/{shell → cli/chat_mode/shell}/input_history.py +0 -0
- /janito/{shell/commands/session.py → cli/chat_mode/shell/session/history.py} +0 -0
- /janito/{agent/tools_utils/formatting.py → formatting.py} +0 -0
- /janito/{agent/tools_utils/gitignore_utils.py → gitignore_utils.py} +0 -0
- /janito/{agent/platform_discovery.py → platform_discovery.py} +0 -0
- /janito/{agent/tools → tools/adapters/local}/get_file_outline/__init__.py +0 -0
- /janito/{agent/tools → tools/adapters/local}/get_file_outline/markdown_outline.py +0 -0
- /janito/{agent/tools → tools/adapters/local}/search_text/__init__.py +0 -0
- /janito/{agent/tools → tools/adapters/local}/validate_file_syntax/__init__.py +0 -0
- {janito-1.14.3.dist-info → janito-2.0.0.dist-info}/WHEEL +0 -0
- {janito-1.14.3.dist-info → janito-2.0.0.dist-info}/entry_points.txt +0 -0
- {janito-1.14.3.dist-info → janito-2.0.0.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,7 @@
|
|
1
|
-
from janito.
|
2
|
-
from janito.
|
3
|
-
from janito.
|
4
|
-
from janito.
|
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, display_path
|
5
5
|
from janito.i18n import tr
|
6
6
|
import os
|
7
7
|
from .pattern_utils import prepare_pattern, format_result, summarize_total
|
@@ -9,7 +9,10 @@ from .match_lines import read_file_lines
|
|
9
9
|
from .traverse_directory import traverse_directory
|
10
10
|
|
11
11
|
|
12
|
-
|
12
|
+
from janito.tools.adapters.local.adapter import register_local_tool as register_tool
|
13
|
+
|
14
|
+
|
15
|
+
@register_tool
|
13
16
|
class SearchTextTool(ToolBase):
|
14
17
|
"""
|
15
18
|
Search for a text pattern (regex or plain string) in all files within one or more directories or file paths and return matching lines or counts. Respects .gitignore.
|
@@ -17,6 +20,7 @@ class SearchTextTool(ToolBase):
|
|
17
20
|
paths (str): String of one or more paths (space-separated) to search in. Each path can be a directory or a file.
|
18
21
|
pattern (str): Regex pattern or plain text substring to search for in files. Must not be empty. Tries regex first, falls back to substring if regex is invalid.
|
19
22
|
is_regex (bool): If True, treat pattern as a regular expression. If False, treat as plain text (default).
|
23
|
+
case_sensitive (bool): If False, perform a case-insensitive search. Default is True (case sensitive).
|
20
24
|
max_depth (int, optional): Maximum directory depth to search. If 0 (default), search is recursive with no depth limit. If >0, limits recursion to that depth. Setting max_depth=1 disables recursion (only top-level directory). Ignored for file paths.
|
21
25
|
max_results (int, optional): Maximum number of results to return. Defaults to 100. 0 means no limit.
|
22
26
|
count_only (bool): If True, return only the count of matches per file and total, not the matching lines. Default is False.
|
@@ -26,12 +30,15 @@ class SearchTextTool(ToolBase):
|
|
26
30
|
If max_results is reached, appends a note to the output.
|
27
31
|
"""
|
28
32
|
|
33
|
+
tool_name = "search_text"
|
34
|
+
|
29
35
|
def _handle_file(
|
30
36
|
self,
|
31
37
|
search_path,
|
32
38
|
pattern,
|
33
39
|
regex,
|
34
40
|
use_regex,
|
41
|
+
case_sensitive,
|
35
42
|
max_results,
|
36
43
|
total_results,
|
37
44
|
count_only,
|
@@ -42,6 +49,7 @@ class SearchTextTool(ToolBase):
|
|
42
49
|
pattern,
|
43
50
|
regex,
|
44
51
|
use_regex,
|
52
|
+
case_sensitive,
|
45
53
|
True,
|
46
54
|
max_results,
|
47
55
|
total_results,
|
@@ -54,6 +62,7 @@ class SearchTextTool(ToolBase):
|
|
54
62
|
pattern,
|
55
63
|
regex,
|
56
64
|
use_regex,
|
65
|
+
case_sensitive,
|
57
66
|
False,
|
58
67
|
max_results,
|
59
68
|
total_results,
|
@@ -71,13 +80,14 @@ class SearchTextTool(ToolBase):
|
|
71
80
|
pattern,
|
72
81
|
regex,
|
73
82
|
use_regex,
|
83
|
+
case_sensitive,
|
74
84
|
max_depth,
|
75
85
|
max_results,
|
76
86
|
total_results,
|
77
87
|
count_only,
|
78
88
|
):
|
79
89
|
info_str = tr(
|
80
|
-
"
|
90
|
+
"🔍 Search {search_type} '{pattern}' in '{disp_path}'",
|
81
91
|
search_type=("regex" if use_regex else "text"),
|
82
92
|
pattern=pattern,
|
83
93
|
disp_path=display_path(search_path),
|
@@ -86,13 +96,14 @@ class SearchTextTool(ToolBase):
|
|
86
96
|
info_str += tr(" [max_depth={max_depth}]", max_depth=max_depth)
|
87
97
|
if count_only:
|
88
98
|
info_str += " [count]"
|
89
|
-
self.
|
99
|
+
self.report_action(info_str, ReportAction.READ)
|
90
100
|
if os.path.isfile(search_path):
|
91
101
|
dir_output, dir_limit_reached, per_file_counts = self._handle_file(
|
92
102
|
search_path,
|
93
103
|
pattern,
|
94
104
|
regex,
|
95
105
|
use_regex,
|
106
|
+
case_sensitive,
|
96
107
|
max_results,
|
97
108
|
total_results,
|
98
109
|
count_only,
|
@@ -104,6 +115,7 @@ class SearchTextTool(ToolBase):
|
|
104
115
|
pattern,
|
105
116
|
regex,
|
106
117
|
use_regex,
|
118
|
+
case_sensitive,
|
107
119
|
max_depth,
|
108
120
|
max_results,
|
109
121
|
total_results,
|
@@ -116,6 +128,7 @@ class SearchTextTool(ToolBase):
|
|
116
128
|
pattern,
|
117
129
|
regex,
|
118
130
|
use_regex,
|
131
|
+
case_sensitive,
|
119
132
|
max_depth,
|
120
133
|
max_results,
|
121
134
|
total_results,
|
@@ -123,13 +136,18 @@ class SearchTextTool(ToolBase):
|
|
123
136
|
)
|
124
137
|
count = sum(count for _, count in per_file_counts)
|
125
138
|
file_word = pluralize("match", count)
|
139
|
+
num_files = len(per_file_counts)
|
140
|
+
file_label = pluralize("file", num_files)
|
141
|
+
file_word_max = file_word + (" (max)" if dir_limit_reached else "")
|
126
142
|
self.report_success(
|
127
143
|
tr(
|
128
|
-
" ✅ {count} {file_word}{
|
144
|
+
" ✅ {count} {file_word} from {num_files} {file_label}",
|
129
145
|
count=count,
|
130
|
-
file_word=
|
131
|
-
|
132
|
-
|
146
|
+
file_word=file_word_max,
|
147
|
+
num_files=num_files,
|
148
|
+
file_label=file_label,
|
149
|
+
),
|
150
|
+
ReportAction.READ,
|
133
151
|
)
|
134
152
|
return info_str, dir_output, dir_limit_reached, per_file_counts
|
135
153
|
|
@@ -138,12 +156,13 @@ class SearchTextTool(ToolBase):
|
|
138
156
|
paths: str,
|
139
157
|
pattern: str,
|
140
158
|
is_regex: bool = False,
|
159
|
+
case_sensitive: bool = False,
|
141
160
|
max_depth: int = 0,
|
142
161
|
max_results: int = 100,
|
143
162
|
count_only: bool = False,
|
144
163
|
) -> str:
|
145
164
|
regex, use_regex, error_msg = prepare_pattern(
|
146
|
-
pattern, is_regex, self.report_error, self.report_warning
|
165
|
+
pattern, is_regex, case_sensitive, self.report_error, self.report_warning
|
147
166
|
)
|
148
167
|
if error_msg:
|
149
168
|
return error_msg
|
@@ -157,6 +176,7 @@ class SearchTextTool(ToolBase):
|
|
157
176
|
pattern,
|
158
177
|
regex,
|
159
178
|
use_regex,
|
179
|
+
case_sensitive,
|
160
180
|
max_depth,
|
161
181
|
max_results,
|
162
182
|
0,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import re
|
2
|
-
from janito.
|
2
|
+
from janito.gitignore_utils import GitignoreFilter
|
3
3
|
import os
|
4
4
|
|
5
5
|
|
@@ -20,9 +20,11 @@ def is_binary_file(path, blocksize=1024):
|
|
20
20
|
return False
|
21
21
|
|
22
22
|
|
23
|
-
def match_line(line, pattern, regex, use_regex):
|
23
|
+
def match_line(line, pattern, regex, use_regex, case_sensitive):
|
24
24
|
if use_regex:
|
25
25
|
return regex and regex.search(line)
|
26
|
+
if not case_sensitive:
|
27
|
+
return pattern in line.lower()
|
26
28
|
return pattern in line
|
27
29
|
|
28
30
|
|
@@ -34,7 +36,14 @@ def should_limit(max_results, total_results, match_count, count_only, dir_output
|
|
34
36
|
|
35
37
|
|
36
38
|
def read_file_lines(
|
37
|
-
path,
|
39
|
+
path,
|
40
|
+
pattern,
|
41
|
+
regex,
|
42
|
+
use_regex,
|
43
|
+
case_sensitive,
|
44
|
+
count_only,
|
45
|
+
max_results,
|
46
|
+
total_results,
|
38
47
|
):
|
39
48
|
dir_output = []
|
40
49
|
dir_limit_reached = False
|
@@ -44,7 +53,7 @@ def read_file_lines(
|
|
44
53
|
open_kwargs = {"mode": "r", "encoding": "utf-8"}
|
45
54
|
with open(path, **open_kwargs) as f:
|
46
55
|
for lineno, line in enumerate(f, 1):
|
47
|
-
if match_line(line, pattern, regex, use_regex):
|
56
|
+
if match_line(line, pattern, regex, use_regex, case_sensitive):
|
48
57
|
match_count += 1
|
49
58
|
if not count_only:
|
50
59
|
dir_output.append(f"{path}:{lineno}: {line.rstrip()}")
|
@@ -1,11 +1,14 @@
|
|
1
1
|
import re
|
2
2
|
from janito.i18n import tr
|
3
|
-
from janito.
|
3
|
+
from janito.tools.tool_utils import pluralize
|
4
4
|
|
5
5
|
|
6
|
-
def prepare_pattern(pattern, is_regex, report_error, report_warning):
|
6
|
+
def prepare_pattern(pattern, is_regex, case_sensitive, report_error, report_warning):
|
7
7
|
if not pattern:
|
8
|
-
report_error(
|
8
|
+
report_error(
|
9
|
+
tr("Error: Empty search pattern provided. Operation aborted."),
|
10
|
+
ReportAction.SEARCH,
|
11
|
+
)
|
9
12
|
return (
|
10
13
|
None,
|
11
14
|
False,
|
@@ -15,7 +18,10 @@ def prepare_pattern(pattern, is_regex, report_error, report_warning):
|
|
15
18
|
use_regex = False
|
16
19
|
if is_regex:
|
17
20
|
try:
|
18
|
-
|
21
|
+
flags = 0
|
22
|
+
if not case_sensitive:
|
23
|
+
flags |= re.IGNORECASE
|
24
|
+
regex = re.compile(pattern, flags=flags)
|
19
25
|
use_regex = True
|
20
26
|
except re.error as e:
|
21
27
|
report_warning(tr("⚠️ Invalid regex pattern."))
|
@@ -30,6 +36,8 @@ def prepare_pattern(pattern, is_regex, report_error, report_warning):
|
|
30
36
|
# Do not compile as regex if is_regex is False; treat as plain text
|
31
37
|
regex = None
|
32
38
|
use_regex = False
|
39
|
+
if not case_sensitive:
|
40
|
+
pattern = pattern.lower()
|
33
41
|
return regex, use_regex, None
|
34
42
|
|
35
43
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import os
|
2
|
-
from janito.
|
2
|
+
from janito.gitignore_utils import GitignoreFilter
|
3
3
|
from .match_lines import match_line, should_limit, read_file_lines
|
4
4
|
|
5
5
|
|
@@ -24,13 +24,21 @@ def filter_dirs(dirs, root, gitignore_filter):
|
|
24
24
|
|
25
25
|
|
26
26
|
def process_file_count_only(
|
27
|
-
file_path,
|
27
|
+
file_path,
|
28
|
+
per_file_counts,
|
29
|
+
pattern,
|
30
|
+
regex,
|
31
|
+
use_regex,
|
32
|
+
case_sensitive,
|
33
|
+
max_results,
|
34
|
+
total_results,
|
28
35
|
):
|
29
36
|
match_count, file_limit_reached, _ = read_file_lines(
|
30
37
|
file_path,
|
31
38
|
pattern,
|
32
39
|
regex,
|
33
40
|
use_regex,
|
41
|
+
case_sensitive,
|
34
42
|
True,
|
35
43
|
max_results,
|
36
44
|
total_results + sum(count for _, count in per_file_counts),
|
@@ -47,6 +55,7 @@ def process_file_collect(
|
|
47
55
|
pattern,
|
48
56
|
regex,
|
49
57
|
use_regex,
|
58
|
+
case_sensitive,
|
50
59
|
max_results,
|
51
60
|
total_results,
|
52
61
|
):
|
@@ -55,6 +64,7 @@ def process_file_collect(
|
|
55
64
|
pattern,
|
56
65
|
regex,
|
57
66
|
use_regex,
|
67
|
+
case_sensitive,
|
58
68
|
False,
|
59
69
|
max_results,
|
60
70
|
total_results + len(dir_output),
|
@@ -79,6 +89,7 @@ def traverse_directory(
|
|
79
89
|
pattern,
|
80
90
|
regex,
|
81
91
|
use_regex,
|
92
|
+
case_sensitive,
|
82
93
|
max_depth,
|
83
94
|
max_results,
|
84
95
|
total_results,
|
@@ -103,6 +114,7 @@ def traverse_directory(
|
|
103
114
|
pattern,
|
104
115
|
regex,
|
105
116
|
use_regex,
|
117
|
+
case_sensitive,
|
106
118
|
max_results,
|
107
119
|
total_results,
|
108
120
|
)
|
@@ -117,6 +129,7 @@ def traverse_directory(
|
|
117
129
|
pattern,
|
118
130
|
regex,
|
119
131
|
use_regex,
|
132
|
+
case_sensitive,
|
120
133
|
max_results,
|
121
134
|
total_results,
|
122
135
|
)
|
@@ -1,9 +1,10 @@
|
|
1
1
|
import os
|
2
2
|
from janito.i18n import tr
|
3
|
-
from janito.
|
4
|
-
from janito.
|
5
|
-
from janito.
|
6
|
-
from janito.
|
3
|
+
from janito.tools.tool_base import ToolBase
|
4
|
+
from janito.report_events import ReportAction
|
5
|
+
from janito.tools.adapters.local.adapter import register_local_tool
|
6
|
+
from janito.tools.tool_utils import display_path
|
7
|
+
from janito.tools.adapters.local.adapter import register_local_tool as register_tool
|
7
8
|
|
8
9
|
from .python_validator import validate_python
|
9
10
|
from .json_validator import validate_json
|
@@ -59,7 +60,6 @@ def validate_file_syntax(
|
|
59
60
|
return _handle_validation_error(e, report_warning)
|
60
61
|
|
61
62
|
|
62
|
-
@register_tool(name="validate_file_syntax")
|
63
63
|
class ValidateFileSyntaxTool(ToolBase):
|
64
64
|
"""
|
65
65
|
Validate a file for syntax issues.
|
@@ -83,14 +83,16 @@ class ValidateFileSyntaxTool(ToolBase):
|
|
83
83
|
- "⚠️ Warning: Unsupported file extension: <ext>"
|
84
84
|
"""
|
85
85
|
|
86
|
+
tool_name = "validate_file_syntax"
|
87
|
+
|
86
88
|
def run(self, file_path: str) -> str:
|
87
89
|
disp_path = display_path(file_path)
|
88
|
-
self.
|
89
|
-
ActionType.READ,
|
90
|
+
self.report_action(
|
90
91
|
tr(
|
91
|
-
"
|
92
|
+
"🔎 Validate syntax for file '{disp_path}' ...",
|
92
93
|
disp_path=disp_path,
|
93
94
|
),
|
95
|
+
ReportAction.READ,
|
94
96
|
)
|
95
97
|
result = validate_file_syntax(
|
96
98
|
file_path,
|
@@ -99,7 +101,6 @@ class ValidateFileSyntaxTool(ToolBase):
|
|
99
101
|
report_success=self.report_success,
|
100
102
|
)
|
101
103
|
if result.startswith("✅"):
|
102
|
-
self.report_success(result)
|
103
|
-
|
104
|
-
self.report_warning(tr("⚠️ ") + result.lstrip("⚠️ "))
|
104
|
+
self.report_success(result, ReportAction.READ)
|
105
|
+
|
105
106
|
return result
|
@@ -1,12 +1,12 @@
|
|
1
|
-
from janito.
|
2
|
-
from janito.
|
3
|
-
from janito.
|
4
|
-
from janito.
|
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
5
|
from janito.i18n import tr
|
6
6
|
|
7
7
|
|
8
|
-
@
|
9
|
-
class
|
8
|
+
@register_local_tool
|
9
|
+
class ViewFileTool(ToolBase):
|
10
10
|
"""
|
11
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
12
|
|
@@ -25,12 +25,20 @@ class GetLinesTool(ToolBase):
|
|
25
25
|
- "❗ not found"
|
26
26
|
"""
|
27
27
|
|
28
|
+
tool_name = "view_file"
|
29
|
+
|
28
30
|
def run(self, file_path: str, from_line: int = None, to_line: int = None) -> str:
|
29
|
-
|
31
|
+
import os
|
32
|
+
from janito.tools.tool_utils import display_path
|
30
33
|
|
31
34
|
disp_path = display_path(file_path)
|
32
|
-
self.
|
35
|
+
self.report_action(
|
36
|
+
tr("📖 View '{disp_path}'", disp_path=disp_path),
|
37
|
+
ReportAction.READ,
|
38
|
+
)
|
33
39
|
try:
|
40
|
+
if os.path.isdir(file_path):
|
41
|
+
return self._list_directory(file_path, disp_path)
|
34
42
|
lines = self._read_file_lines(file_path)
|
35
43
|
selected, selected_len, total_lines = self._select_lines(
|
36
44
|
lines, from_line, to_line
|
@@ -40,26 +48,36 @@ class GetLinesTool(ToolBase):
|
|
40
48
|
disp_path, from_line, to_line, selected_len, total_lines
|
41
49
|
)
|
42
50
|
return header + "".join(selected)
|
51
|
+
except FileNotFoundError as e:
|
52
|
+
self.report_warning(tr("❗ not found"))
|
53
|
+
return f"Error reading file: {e}"
|
43
54
|
except Exception as e:
|
44
|
-
|
55
|
+
self.report_error(tr(" ❌ Error: {error}", error=e))
|
56
|
+
return tr("Error reading file: {error}", error=e)
|
45
57
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
)
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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"
|
62
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)
|
63
81
|
|
64
82
|
def _read_file_lines(self, file_path):
|
65
83
|
"""Read all lines from the file."""
|
@@ -143,7 +161,7 @@ class GetLinesTool(ToolBase):
|
|
143
161
|
def _handle_read_error(self, e):
|
144
162
|
"""Handle file read errors and report appropriately."""
|
145
163
|
if isinstance(e, FileNotFoundError):
|
146
|
-
self.report_error(tr("❗ not found"))
|
164
|
+
self.report_error(tr("❗ not found"), ReportAction.READ)
|
147
165
|
return tr("❗ not found")
|
148
|
-
self.report_error(tr(" ❌ Error: {error}", error=e))
|
166
|
+
self.report_error(tr(" ❌ Error: {error}", error=e), ReportAction.READ)
|
149
167
|
return tr("Error reading file: {error}", error=e)
|
@@ -0,0 +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()
|
@@ -0,0 +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.")
|