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,97 +0,0 @@
|
|
1
|
-
from janito.agent.tool_base import ToolBase
|
2
|
-
from janito.agent.tool_registry import register_tool
|
3
|
-
from janito.i18n import tr
|
4
|
-
|
5
|
-
|
6
|
-
@register_tool(name="delete_text_in_file")
|
7
|
-
class DeleteTextInFileTool(ToolBase):
|
8
|
-
"""
|
9
|
-
Delete all occurrences of text between start_marker and end_marker (inclusive) in a file, using exact string markers.
|
10
|
-
|
11
|
-
Args:
|
12
|
-
file_path (str): Path to the file to modify.
|
13
|
-
start_marker (str): The starting delimiter string.
|
14
|
-
end_marker (str): The ending delimiter string.
|
15
|
-
backup (bool, optional): If True, create a backup (.bak) before deleting. Defaults to False.
|
16
|
-
Returns:
|
17
|
-
str: Status message indicating the result.
|
18
|
-
"""
|
19
|
-
|
20
|
-
def run(
|
21
|
-
self,
|
22
|
-
file_path: str,
|
23
|
-
start_marker: str,
|
24
|
-
end_marker: str,
|
25
|
-
backup: bool = False,
|
26
|
-
) -> str:
|
27
|
-
import shutil
|
28
|
-
from janito.agent.tools_utils.utils import display_path
|
29
|
-
|
30
|
-
disp_path = display_path(file_path)
|
31
|
-
backup_path = file_path + ".bak"
|
32
|
-
backup_msg = ""
|
33
|
-
try:
|
34
|
-
with open(file_path, "r", encoding="utf-8", errors="replace") as f:
|
35
|
-
content = f.read()
|
36
|
-
except Exception as e:
|
37
|
-
self.report_error(tr(" ❌ Error reading file: {error}", error=e))
|
38
|
-
return tr("Error reading file: {error}", error=e)
|
39
|
-
|
40
|
-
start_count = content.count(start_marker)
|
41
|
-
if start_count > 1:
|
42
|
-
self.report_error("Need more context for start_marker")
|
43
|
-
return (
|
44
|
-
f"Error: start_marker is not unique in {disp_path}. "
|
45
|
-
"Try including the next line(s) for more context."
|
46
|
-
)
|
47
|
-
|
48
|
-
end_count = content.count(end_marker)
|
49
|
-
if end_count > 1:
|
50
|
-
self.report_error("Need more context for end_marker")
|
51
|
-
return (
|
52
|
-
f"Error: end_marker is not unique in {disp_path}. "
|
53
|
-
"Try including the previous line(s) for more context."
|
54
|
-
)
|
55
|
-
|
56
|
-
count = 0
|
57
|
-
new_content = content
|
58
|
-
while True:
|
59
|
-
start_idx = new_content.find(start_marker)
|
60
|
-
if start_idx == -1:
|
61
|
-
break
|
62
|
-
end_idx = new_content.find(end_marker, start_idx + len(start_marker))
|
63
|
-
if end_idx == -1:
|
64
|
-
break
|
65
|
-
# Remove from start_marker to end_marker (inclusive)
|
66
|
-
new_content = (
|
67
|
-
new_content[:start_idx] + new_content[end_idx + len(end_marker) :]
|
68
|
-
)
|
69
|
-
count += 1
|
70
|
-
|
71
|
-
if count == 0:
|
72
|
-
self.report_warning(tr("ℹ️ No blocks found between markers."))
|
73
|
-
return tr(
|
74
|
-
"No blocks found between markers in {file_path}.", file_path=file_path
|
75
|
-
)
|
76
|
-
|
77
|
-
if backup:
|
78
|
-
shutil.copy2(file_path, backup_path)
|
79
|
-
backup_msg = f" (A backup was saved to {backup_path})"
|
80
|
-
with open(file_path, "w", encoding="utf-8", errors="replace") as f:
|
81
|
-
f.write(new_content)
|
82
|
-
|
83
|
-
self.report_success(
|
84
|
-
tr(
|
85
|
-
"Deleted {count} block(s) between markers in {disp_path}.",
|
86
|
-
count=count,
|
87
|
-
disp_path=disp_path,
|
88
|
-
)
|
89
|
-
)
|
90
|
-
return (
|
91
|
-
tr(
|
92
|
-
"Deleted {count} block(s) between markers in {file_path}.",
|
93
|
-
count=count,
|
94
|
-
file_path=file_path,
|
95
|
-
)
|
96
|
-
+ backup_msg
|
97
|
-
)
|
janito/agent/tools/find_files.py
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
from janito.agent.tool_base import ToolBase
|
2
|
-
from janito.agent.tools_utils.action_type import ActionType
|
3
|
-
from janito.agent.tool_registry import register_tool
|
4
|
-
from janito.agent.tools_utils.utils import pluralize, display_path
|
5
|
-
from janito.agent.tools_utils.dir_walk_utils import walk_dir_with_gitignore
|
6
|
-
from janito.i18n import tr
|
7
|
-
import fnmatch
|
8
|
-
import os
|
9
|
-
|
10
|
-
|
11
|
-
@register_tool(name="find_files")
|
12
|
-
class FindFilesTool(ToolBase):
|
13
|
-
"""
|
14
|
-
Find files or directories in one or more directories matching a pattern. Respects .gitignore.
|
15
|
-
Args:
|
16
|
-
paths (str): String of one or more paths (space-separated) to search in. Each path can be a directory.
|
17
|
-
pattern (str): File pattern(s) to match. Multiple patterns can be separated by spaces. Uses Unix shell-style wildcards (fnmatch), e.g. '*.py', 'data_??.csv', '[a-z]*.txt'.
|
18
|
-
- If the pattern ends with '/' or '\\', only matching directory names (with trailing slash) are returned, not the files within those directories. For example, pattern '*/' will return only directories at the specified depth.
|
19
|
-
max_depth (int, optional): Maximum directory depth to search. If None, unlimited recursion. If 0, only the top-level directory. If 1, only the root directory (matches 'find . -maxdepth 1').
|
20
|
-
max_results (int, optional): Maximum number of results to return. 0 means no limit (default).
|
21
|
-
Returns:
|
22
|
-
str: Newline-separated list of matching file paths. Example:
|
23
|
-
"/path/to/file1.py\n/path/to/file2.py"
|
24
|
-
"Warning: Empty file pattern provided. Operation skipped."
|
25
|
-
If max_results is reached, appends a note to the output.
|
26
|
-
"""
|
27
|
-
|
28
|
-
def _match_directories(self, root, dirs, pat):
|
29
|
-
dir_output = set()
|
30
|
-
dir_pat = pat.rstrip("/\\")
|
31
|
-
for d in dirs:
|
32
|
-
if fnmatch.fnmatch(d, dir_pat):
|
33
|
-
dir_output.add(os.path.join(root, d) + os.sep)
|
34
|
-
return dir_output
|
35
|
-
|
36
|
-
def _match_files(self, root, files, pat):
|
37
|
-
file_output = set()
|
38
|
-
for filename in fnmatch.filter(files, pat):
|
39
|
-
file_output.add(os.path.join(root, filename))
|
40
|
-
return file_output
|
41
|
-
|
42
|
-
def _match_dirs_without_slash(self, root, dirs, pat):
|
43
|
-
dir_output = set()
|
44
|
-
for d in fnmatch.filter(dirs, pat):
|
45
|
-
dir_output.add(os.path.join(root, d))
|
46
|
-
return dir_output
|
47
|
-
|
48
|
-
def run(
|
49
|
-
self, paths: str, pattern: str, max_depth: int = None, max_results: int = 0
|
50
|
-
) -> str:
|
51
|
-
if not pattern:
|
52
|
-
self.report_warning(tr("ℹ️ Empty file pattern provided."))
|
53
|
-
return tr("Warning: Empty file pattern provided. Operation skipped.")
|
54
|
-
patterns = pattern.split()
|
55
|
-
results = []
|
56
|
-
for directory in paths.split():
|
57
|
-
disp_path = display_path(directory)
|
58
|
-
depth_msg = (
|
59
|
-
tr(" (max depth: {max_depth})", max_depth=max_depth)
|
60
|
-
if max_depth is not None and max_depth > 0
|
61
|
-
else ""
|
62
|
-
)
|
63
|
-
self.report_info(
|
64
|
-
ActionType.READ,
|
65
|
-
tr(
|
66
|
-
"🔍 Search files '{pattern}' in '{disp_path}'{depth_msg} ...",
|
67
|
-
pattern=pattern,
|
68
|
-
disp_path=disp_path,
|
69
|
-
depth_msg=depth_msg,
|
70
|
-
),
|
71
|
-
)
|
72
|
-
dir_output = set()
|
73
|
-
count_scanned = 0
|
74
|
-
limit_reached = False
|
75
|
-
for root, dirs, files in walk_dir_with_gitignore(
|
76
|
-
directory, max_depth=max_depth
|
77
|
-
):
|
78
|
-
for pat in patterns:
|
79
|
-
if pat.endswith("/") or pat.endswith("\\"):
|
80
|
-
dir_output.update(self._match_directories(root, dirs, pat))
|
81
|
-
else:
|
82
|
-
dir_output.update(self._match_files(root, files, pat))
|
83
|
-
dir_output.update(
|
84
|
-
self._match_dirs_without_slash(root, dirs, pat)
|
85
|
-
)
|
86
|
-
if max_results > 0 and len(dir_output) >= max_results:
|
87
|
-
limit_reached = True
|
88
|
-
# Truncate to max_results
|
89
|
-
dir_output = set(list(dir_output)[:max_results])
|
90
|
-
break
|
91
|
-
self.report_success(
|
92
|
-
tr(
|
93
|
-
" ✅ {count} {file_word}{max_flag}",
|
94
|
-
count=len(dir_output),
|
95
|
-
file_word=pluralize("file", len(dir_output)),
|
96
|
-
max_flag=" (max)" if limit_reached else "",
|
97
|
-
)
|
98
|
-
)
|
99
|
-
if directory.strip() == ".":
|
100
|
-
dir_output = {
|
101
|
-
p[2:] if (p.startswith("./") or p.startswith(".\\")) else p
|
102
|
-
for p in dir_output
|
103
|
-
}
|
104
|
-
results.extend(sorted(dir_output))
|
105
|
-
result = "\n".join(results)
|
106
|
-
return result
|
@@ -1,81 +0,0 @@
|
|
1
|
-
from janito.agent.tool_registry import register_tool
|
2
|
-
from .python_outline import parse_python_outline
|
3
|
-
from .markdown_outline import parse_markdown_outline
|
4
|
-
from janito.agent.tools_utils.formatting import OutlineFormatter
|
5
|
-
import os
|
6
|
-
from janito.agent.tool_base import ToolBase
|
7
|
-
from janito.agent.tools_utils.action_type import ActionType
|
8
|
-
from janito.agent.tools_utils.utils import display_path, pluralize
|
9
|
-
from janito.i18n import tr
|
10
|
-
|
11
|
-
|
12
|
-
@register_tool(name="get_file_outline")
|
13
|
-
class GetFileOutlineTool(ToolBase):
|
14
|
-
"""
|
15
|
-
Get an outline of a file's structure. Supports Python and Markdown files.
|
16
|
-
|
17
|
-
Args:
|
18
|
-
file_path (str): Path to the file to outline.
|
19
|
-
"""
|
20
|
-
|
21
|
-
def run(self, file_path: str) -> str:
|
22
|
-
try:
|
23
|
-
self.report_info(
|
24
|
-
ActionType.READ,
|
25
|
-
tr(
|
26
|
-
"📄 Outline file '{disp_path}' ...",
|
27
|
-
disp_path=display_path(file_path),
|
28
|
-
),
|
29
|
-
)
|
30
|
-
ext = os.path.splitext(file_path)[1].lower()
|
31
|
-
with open(file_path, "r", encoding="utf-8", errors="replace") as f:
|
32
|
-
lines = f.readlines()
|
33
|
-
if ext == ".py":
|
34
|
-
outline_items = parse_python_outline(lines)
|
35
|
-
outline_type = "python"
|
36
|
-
table = OutlineFormatter.format_outline_table(outline_items)
|
37
|
-
self.report_success(
|
38
|
-
tr(
|
39
|
-
"✅ Outlined {count} {item_word}",
|
40
|
-
count=len(outline_items),
|
41
|
-
item_word=pluralize("item", len(outline_items)),
|
42
|
-
)
|
43
|
-
)
|
44
|
-
return (
|
45
|
-
tr(
|
46
|
-
"Outline: {count} items ({outline_type})\n",
|
47
|
-
count=len(outline_items),
|
48
|
-
outline_type=outline_type,
|
49
|
-
)
|
50
|
-
+ table
|
51
|
-
)
|
52
|
-
elif ext == ".md":
|
53
|
-
outline_items = parse_markdown_outline(lines)
|
54
|
-
outline_type = "markdown"
|
55
|
-
table = OutlineFormatter.format_markdown_outline_table(outline_items)
|
56
|
-
self.report_success(
|
57
|
-
tr(
|
58
|
-
"✅ Outlined {count} {item_word}",
|
59
|
-
count=len(outline_items),
|
60
|
-
item_word=pluralize("item", len(outline_items)),
|
61
|
-
)
|
62
|
-
)
|
63
|
-
return (
|
64
|
-
tr(
|
65
|
-
"Outline: {count} items ({outline_type})\n",
|
66
|
-
count=len(outline_items),
|
67
|
-
outline_type=outline_type,
|
68
|
-
)
|
69
|
-
+ table
|
70
|
-
)
|
71
|
-
else:
|
72
|
-
outline_type = "default"
|
73
|
-
self.report_success(tr("✅ Outlined {count} items", count=len(lines)))
|
74
|
-
return tr(
|
75
|
-
"Outline: {count} lines ({outline_type})\nFile has {count} lines.",
|
76
|
-
count=len(lines),
|
77
|
-
outline_type=outline_type,
|
78
|
-
)
|
79
|
-
except Exception as e:
|
80
|
-
self.report_error(tr("❌ Error reading file: {error}", error=e))
|
81
|
-
return tr("Error reading file: {error}", error=e)
|
@@ -1,64 +0,0 @@
|
|
1
|
-
from typing import List
|
2
|
-
from janito.agent.tool_base import ToolBase
|
3
|
-
from janito.agent.tools_utils.action_type import ActionType
|
4
|
-
from janito.agent.tool_registry import register_tool
|
5
|
-
from janito.i18n import tr
|
6
|
-
import questionary
|
7
|
-
from questionary import Style
|
8
|
-
|
9
|
-
custom_style = Style(
|
10
|
-
[
|
11
|
-
("pointer", "fg:#ffffff bg:#1976d2 bold"),
|
12
|
-
("highlighted", "fg:#ffffff bg:#1565c0 bold"),
|
13
|
-
("answer", "fg:#1976d2 bold"),
|
14
|
-
("qmark", "fg:#1976d2 bold"),
|
15
|
-
]
|
16
|
-
)
|
17
|
-
HAND_EMOJI = "🖐️" # 🖐️
|
18
|
-
|
19
|
-
|
20
|
-
@register_tool(name="present_choices")
|
21
|
-
class PresentChoicesTool(ToolBase):
|
22
|
-
"""
|
23
|
-
Present a list of options to the user and return the selected option(s).
|
24
|
-
|
25
|
-
Args:
|
26
|
-
prompt (str): The prompt/question to display.
|
27
|
-
choices (List[str]): List of options to present. Use \n in option text for explicit line breaks if needed.
|
28
|
-
multi_select (bool): If True, allow multiple selections.
|
29
|
-
Returns:
|
30
|
-
str: The selected option(s) as a string, or a message if cancelled.
|
31
|
-
- For multi_select=True, returns each selection on a new line, each prefixed with '- '.
|
32
|
-
- For multi_select=False, returns the selected option as a string.
|
33
|
-
- If cancelled, returns 'No selection made.'
|
34
|
-
"""
|
35
|
-
|
36
|
-
def run(self, prompt: str, choices: List[str], multi_select: bool = False) -> str:
|
37
|
-
if not choices:
|
38
|
-
return tr("⚠️ No choices provided.")
|
39
|
-
self.report_info(
|
40
|
-
ActionType.EXECUTE,
|
41
|
-
tr(
|
42
|
-
"ℹ️ Prompting user: {prompt} (multi_select={multi_select}) ...",
|
43
|
-
prompt=prompt,
|
44
|
-
multi_select=multi_select,
|
45
|
-
),
|
46
|
-
)
|
47
|
-
if multi_select:
|
48
|
-
result = questionary.checkbox(
|
49
|
-
prompt, choices=choices, style=custom_style, pointer=HAND_EMOJI
|
50
|
-
).ask()
|
51
|
-
if result is None:
|
52
|
-
return tr("No selection made.")
|
53
|
-
return (
|
54
|
-
"\n".join(f"- {item}" for item in result)
|
55
|
-
if isinstance(result, list)
|
56
|
-
else f"- {result}"
|
57
|
-
)
|
58
|
-
else:
|
59
|
-
result = questionary.select(
|
60
|
-
prompt, choices=choices, style=custom_style, pointer=HAND_EMOJI
|
61
|
-
).ask()
|
62
|
-
if result is None:
|
63
|
-
return tr("No selection made.")
|
64
|
-
return str(result)
|
@@ -1,201 +0,0 @@
|
|
1
|
-
import subprocess
|
2
|
-
import os
|
3
|
-
import sys
|
4
|
-
import tempfile
|
5
|
-
import threading
|
6
|
-
from janito.agent.tool_base import ToolBase
|
7
|
-
from janito.agent.tools_utils.action_type import ActionType
|
8
|
-
from janito.agent.tool_registry import register_tool
|
9
|
-
from janito.i18n import tr
|
10
|
-
from janito.agent.runtime_config import runtime_config
|
11
|
-
|
12
|
-
|
13
|
-
@register_tool(name="python_command_runner")
|
14
|
-
class PythonCommandRunnerTool(ToolBase):
|
15
|
-
"""
|
16
|
-
Tool to execute Python code using the `python -c` command-line flag.
|
17
|
-
Args:
|
18
|
-
code (str): The Python code to execute as a string.
|
19
|
-
timeout (int, optional): Timeout in seconds for the command. Defaults to 60.
|
20
|
-
Returns:
|
21
|
-
str: Output and status message, or file paths/line counts if output is large.
|
22
|
-
"""
|
23
|
-
|
24
|
-
def run(self, code: str, timeout: int = 60) -> str:
|
25
|
-
if not code.strip():
|
26
|
-
self.report_warning(tr("539 Empty code provided."))
|
27
|
-
return tr("Warning: Empty code provided. Operation skipped.")
|
28
|
-
self.report_info(
|
29
|
-
ActionType.EXECUTE, tr("40d Running: python -c ...\n{code}\n", code=code)
|
30
|
-
)
|
31
|
-
try:
|
32
|
-
if runtime_config.get("all_out"):
|
33
|
-
process = subprocess.Popen(
|
34
|
-
[sys.executable, "-c", code],
|
35
|
-
stdout=subprocess.PIPE,
|
36
|
-
stderr=subprocess.PIPE,
|
37
|
-
text=True,
|
38
|
-
bufsize=1,
|
39
|
-
universal_newlines=True,
|
40
|
-
encoding="utf-8",
|
41
|
-
env={**os.environ, "PYTHONIOENCODING": "utf-8"},
|
42
|
-
)
|
43
|
-
stdout_accum = []
|
44
|
-
stderr_accum = []
|
45
|
-
|
46
|
-
def read_stream(stream, report_func, accum):
|
47
|
-
for line in stream:
|
48
|
-
accum.append(line)
|
49
|
-
report_func(line)
|
50
|
-
|
51
|
-
stdout_thread = threading.Thread(
|
52
|
-
target=read_stream,
|
53
|
-
args=(process.stdout, self.report_stdout, stdout_accum),
|
54
|
-
)
|
55
|
-
stderr_thread = threading.Thread(
|
56
|
-
target=read_stream,
|
57
|
-
args=(process.stderr, self.report_stderr, stderr_accum),
|
58
|
-
)
|
59
|
-
stdout_thread.start()
|
60
|
-
stderr_thread.start()
|
61
|
-
try:
|
62
|
-
return_code = process.wait(timeout=timeout)
|
63
|
-
except subprocess.TimeoutExpired:
|
64
|
-
process.kill()
|
65
|
-
self.report_error(
|
66
|
-
tr("6d1 Timed out after {timeout} seconds.", timeout=timeout)
|
67
|
-
)
|
68
|
-
return tr(
|
69
|
-
"Code timed out after {timeout} seconds.", timeout=timeout
|
70
|
-
)
|
71
|
-
stdout_thread.join()
|
72
|
-
stderr_thread.join()
|
73
|
-
self.report_success(
|
74
|
-
tr("197 Return code {return_code}", return_code=return_code)
|
75
|
-
)
|
76
|
-
stdout = "".join(stdout_accum)
|
77
|
-
stderr = "".join(stderr_accum)
|
78
|
-
result = f"Return code: {return_code}\n--- STDOUT ---\n{stdout}"
|
79
|
-
if stderr and stderr.strip():
|
80
|
-
result += f"\n--- STDERR ---\n{stderr}"
|
81
|
-
return result
|
82
|
-
else:
|
83
|
-
with (
|
84
|
-
tempfile.NamedTemporaryFile(
|
85
|
-
mode="w+",
|
86
|
-
prefix="python_cmd_stdout_",
|
87
|
-
delete=False,
|
88
|
-
encoding="utf-8",
|
89
|
-
) as stdout_file,
|
90
|
-
tempfile.NamedTemporaryFile(
|
91
|
-
mode="w+",
|
92
|
-
prefix="python_cmd_stderr_",
|
93
|
-
delete=False,
|
94
|
-
encoding="utf-8",
|
95
|
-
) as stderr_file,
|
96
|
-
):
|
97
|
-
process = subprocess.Popen(
|
98
|
-
[sys.executable, "-c", code],
|
99
|
-
stdout=subprocess.PIPE,
|
100
|
-
stderr=subprocess.PIPE,
|
101
|
-
text=True,
|
102
|
-
bufsize=1,
|
103
|
-
universal_newlines=True,
|
104
|
-
encoding="utf-8",
|
105
|
-
env={**os.environ, "PYTHONIOENCODING": "utf-8"},
|
106
|
-
)
|
107
|
-
stdout_lines, stderr_lines = self._stream_process_output(
|
108
|
-
process, stdout_file, stderr_file
|
109
|
-
)
|
110
|
-
return_code = self._wait_for_process(process, timeout)
|
111
|
-
if return_code is None:
|
112
|
-
return tr(
|
113
|
-
"Code timed out after {timeout} seconds.", timeout=timeout
|
114
|
-
)
|
115
|
-
stdout_file.flush()
|
116
|
-
stderr_file.flush()
|
117
|
-
self.report_success(
|
118
|
-
tr("197 Return code {return_code}", return_code=return_code)
|
119
|
-
)
|
120
|
-
return self._format_result(
|
121
|
-
stdout_file.name, stderr_file.name, return_code
|
122
|
-
)
|
123
|
-
except Exception as e:
|
124
|
-
self.report_error(tr("534 Error: {error}", error=e))
|
125
|
-
return tr("Error running code: {error}", error=e)
|
126
|
-
|
127
|
-
def _stream_process_output(self, process, stdout_file, stderr_file):
|
128
|
-
stdout_lines = 0
|
129
|
-
stderr_lines = 0
|
130
|
-
|
131
|
-
def stream_output(stream, file_obj, report_func, count_func):
|
132
|
-
nonlocal stdout_lines, stderr_lines
|
133
|
-
for line in stream:
|
134
|
-
file_obj.write(line)
|
135
|
-
file_obj.flush()
|
136
|
-
report_func(line)
|
137
|
-
if count_func == "stdout":
|
138
|
-
stdout_lines += 1
|
139
|
-
else:
|
140
|
-
stderr_lines += 1
|
141
|
-
|
142
|
-
stdout_thread = threading.Thread(
|
143
|
-
target=stream_output,
|
144
|
-
args=(process.stdout, stdout_file, self.report_stdout, "stdout"),
|
145
|
-
)
|
146
|
-
stderr_thread = threading.Thread(
|
147
|
-
target=stream_output,
|
148
|
-
args=(process.stderr, stderr_file, self.report_stderr, "stderr"),
|
149
|
-
)
|
150
|
-
stdout_thread.start()
|
151
|
-
stderr_thread.start()
|
152
|
-
stdout_thread.join()
|
153
|
-
stderr_thread.join()
|
154
|
-
return stdout_lines, stderr_lines
|
155
|
-
|
156
|
-
def _wait_for_process(self, process, timeout):
|
157
|
-
try:
|
158
|
-
return process.wait(timeout=timeout)
|
159
|
-
except subprocess.TimeoutExpired:
|
160
|
-
process.kill()
|
161
|
-
self.report_error(
|
162
|
-
tr("6d1 Timed out after {timeout} seconds.", timeout=timeout)
|
163
|
-
)
|
164
|
-
return None
|
165
|
-
|
166
|
-
def _format_result(self, stdout_file_name, stderr_file_name, return_code):
|
167
|
-
with open(stdout_file_name, "r", encoding="utf-8", errors="replace") as out_f:
|
168
|
-
stdout_content = out_f.read()
|
169
|
-
with open(stderr_file_name, "r", encoding="utf-8", errors="replace") as err_f:
|
170
|
-
stderr_content = err_f.read()
|
171
|
-
max_lines = 100
|
172
|
-
stdout_lines = stdout_content.count("\n")
|
173
|
-
stderr_lines = stderr_content.count("\n")
|
174
|
-
|
175
|
-
def head_tail(text, n=10):
|
176
|
-
lines = text.splitlines()
|
177
|
-
if len(lines) <= 2 * n:
|
178
|
-
return "\n".join(lines)
|
179
|
-
return "\n".join(
|
180
|
-
lines[:n]
|
181
|
-
+ ["... ({} lines omitted) ...".format(len(lines) - 2 * n)]
|
182
|
-
+ lines[-n:]
|
183
|
-
)
|
184
|
-
|
185
|
-
if stdout_lines <= max_lines and stderr_lines <= max_lines:
|
186
|
-
result = f"Return code: {return_code}\n--- STDOUT ---\n{stdout_content}"
|
187
|
-
if stderr_content.strip():
|
188
|
-
result += f"\n--- STDERR ---\n{stderr_content}"
|
189
|
-
return result
|
190
|
-
else:
|
191
|
-
result = f"stdout_file: {stdout_file_name} (lines: {stdout_lines})\n"
|
192
|
-
if stderr_lines > 0 and stderr_content.strip():
|
193
|
-
result += f"stderr_file: {stderr_file_name} (lines: {stderr_lines})\n"
|
194
|
-
result += f"returncode: {return_code}\n"
|
195
|
-
result += "--- STDOUT (head/tail) ---\n" + head_tail(stdout_content) + "\n"
|
196
|
-
if stderr_content.strip():
|
197
|
-
result += (
|
198
|
-
"--- STDERR (head/tail) ---\n" + head_tail(stderr_content) + "\n"
|
199
|
-
)
|
200
|
-
result += "Use the get_lines tool to inspect the contents of these files when needed."
|
201
|
-
return result
|