janito 1.3.1__py3-none-any.whl → 1.3.2__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 +1 -1
- janito/agent/templates/system_instructions.j2 +36 -0
- janito/agent/tools/file_ops.py +72 -72
- janito/agent/tools/run_bash_command.py +134 -134
- janito/agent/tools/tool_base.py +22 -0
- {janito-1.3.1.dist-info → janito-1.3.2.dist-info}/METADATA +1 -1
- {janito-1.3.1.dist-info → janito-1.3.2.dist-info}/RECORD +11 -9
- {janito-1.3.1.dist-info → janito-1.3.2.dist-info}/WHEEL +0 -0
- {janito-1.3.1.dist-info → janito-1.3.2.dist-info}/entry_points.txt +0 -0
- {janito-1.3.1.dist-info → janito-1.3.2.dist-info}/licenses/LICENSE +0 -0
- {janito-1.3.1.dist-info → janito-1.3.2.dist-info}/top_level.txt +0 -0
janito/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "1.3.
|
1
|
+
__version__ = "1.3.2"
|
@@ -0,0 +1,36 @@
|
|
1
|
+
Your main role is {{ role }} .
|
2
|
+
|
3
|
+
You are an assistant for a analysis and development tool that operates on files and
|
4
|
+
directories using text-based operations.
|
5
|
+
|
6
|
+
Provide a concise plan before calling any tool.
|
7
|
+
|
8
|
+
<context>
|
9
|
+
Always review `README_structure.txt` before conducting file-specific searches.
|
10
|
+
Unless specified otherwise, look for the files that match the questions context.
|
11
|
+
Explore files that might be relevant to the current task.
|
12
|
+
</context>
|
13
|
+
|
14
|
+
<analysis>
|
15
|
+
When analyzing issues, you might want to look into the git history for clues.
|
16
|
+
</analysis>
|
17
|
+
|
18
|
+
<editing>
|
19
|
+
If in doubt during editing, use the `ask_user` function to get additional information; otherwise, proceed and inform the user of the decision made.
|
20
|
+
|
21
|
+
When you need to make changes to a file, consider the following:
|
22
|
+
|
23
|
+
- Use the `edit_file` tool when you want to update or fix specific text fragments within a file without altering the rest of its content. It is preferred over full file replacement when:
|
24
|
+
- Only small, targeted changes are needed.
|
25
|
+
- You want to avoid the risk of accidentally overwriting unrelated content.
|
26
|
+
- The file is large, and rewriting the entire file would be inefficient.
|
27
|
+
- You want to preserve formatting, comments, or code structure outside the replaced text.
|
28
|
+
|
29
|
+
- When replacing files, review their current content before requesting the update.
|
30
|
+
- When reorganizing, moving files, or functions, search for references in other files that might need to be updated accordingly.
|
31
|
+
</editing>
|
32
|
+
|
33
|
+
<finishing>
|
34
|
+
- Review the README content if there are user-exposed or public API changes.
|
35
|
+
- Update `README_structure.txt` considering discovered, created, or modified files.
|
36
|
+
</finishing>
|
janito/agent/tools/file_ops.py
CHANGED
@@ -1,72 +1,72 @@
|
|
1
|
-
import os
|
2
|
-
import shutil
|
3
|
-
from janito.agent.tool_handler import ToolHandler
|
4
|
-
from janito.agent.tools.rich_utils import print_info, print_success, print_error, format_path
|
5
|
-
|
6
|
-
@ToolHandler.register_tool
|
7
|
-
def create_file(path: str, content: str, overwrite: bool = False) -> str:
|
8
|
-
"""
|
9
|
-
Create a new file or update an existing file with the given content.
|
10
|
-
|
11
|
-
Args:
|
12
|
-
path (str): Path to the file to create or update.
|
13
|
-
content (str): Content to write to the file.
|
14
|
-
overwrite (bool): Whether to overwrite the file if it exists.
|
15
|
-
"""
|
16
|
-
updating = os.path.exists(path) and not os.path.isdir(path)
|
17
|
-
if os.path.exists(path):
|
18
|
-
if os.path.isdir(path):
|
19
|
-
print_error("❌ Error: is a directory")
|
20
|
-
return f"❌ Cannot create file: '{path}' is an existing directory."
|
21
|
-
if not overwrite:
|
22
|
-
print_error(f"❗ Error: file '{path}' exists and overwrite is False")
|
23
|
-
return f"❗ Cannot create file: '{path}' already exists and overwrite is False."
|
24
|
-
if updating and overwrite:
|
25
|
-
print_info(f"📝 Updating file: '{format_path(path)}' ... ")
|
26
|
-
else:
|
27
|
-
print_info(f"📝 Creating file: '{format_path(path)}' ... ")
|
28
|
-
old_lines = None
|
29
|
-
if updating and overwrite:
|
30
|
-
with open(path, "r", encoding="utf-8") as f:
|
31
|
-
old_lines = sum(1 for _ in f)
|
32
|
-
with open(path, "w", encoding="utf-8") as f:
|
33
|
-
f.write(content)
|
34
|
-
print_success("✅ Success")
|
35
|
-
if old_lines is not None:
|
36
|
-
new_lines = content.count('\n') + 1 if content else 0
|
37
|
-
return f"✅ Successfully updated the file at '{path}' ({old_lines} > {new_lines} lines)."
|
38
|
-
else:
|
39
|
-
return f"✅ Successfully created the file at '{path}'."
|
40
|
-
|
41
|
-
|
42
|
-
@ToolHandler.register_tool
|
43
|
-
def remove_file(path: str) -> str:
|
44
|
-
print_info(f"🗑️ Removing file: '{format_path(path)}' ... ")
|
45
|
-
os.remove(path)
|
46
|
-
print_success("✅ Success")
|
47
|
-
return f"✅ Successfully deleted the file at '{path}'."
|
48
|
-
|
49
|
-
@ToolHandler.register_tool
|
50
|
-
def move_file(source_path: str, destination_path: str, overwrite: bool = False) -> str:
|
51
|
-
print_info(f"🚚 Moving '{format_path(source_path)}' to '{format_path(destination_path)}' ... ")
|
52
|
-
if not os.path.exists(source_path):
|
53
|
-
print_error("❌ Error: source does not exist")
|
54
|
-
return f"❌ Source path '{source_path}' does not exist."
|
55
|
-
if os.path.exists(destination_path):
|
56
|
-
if not overwrite:
|
57
|
-
print_error("❌ Error: destination exists and overwrite is False")
|
58
|
-
return f"❌ Destination path '{destination_path}' already exists. Use overwrite=True to replace it."
|
59
|
-
if os.path.isdir(destination_path):
|
60
|
-
shutil.rmtree(destination_path)
|
61
|
-
else:
|
62
|
-
os.remove(destination_path)
|
63
|
-
shutil.move(source_path, destination_path)
|
64
|
-
print_success("✅ Success")
|
65
|
-
return f"✅ Successfully moved '{source_path}' to '{destination_path}'."
|
66
|
-
|
67
|
-
@ToolHandler.register_tool
|
68
|
-
def create_directory(path: str) -> str:
|
69
|
-
print_info(f"📁 Creating directory: '{format_path(path)}' ... ")
|
70
|
-
os.makedirs(path, exist_ok=True)
|
71
|
-
print_success("✅ Success")
|
72
|
-
return f"✅ Directory '{path}' created successfully."
|
1
|
+
import os
|
2
|
+
import shutil
|
3
|
+
from janito.agent.tool_handler import ToolHandler
|
4
|
+
from janito.agent.tools.rich_utils import print_info, print_success, print_error, format_path
|
5
|
+
|
6
|
+
@ToolHandler.register_tool
|
7
|
+
def create_file(path: str, content: str, overwrite: bool = False) -> str:
|
8
|
+
"""
|
9
|
+
Create a new file or update an existing file with the given content.
|
10
|
+
|
11
|
+
Args:
|
12
|
+
path (str): Path to the file to create or update.
|
13
|
+
content (str): Content to write to the file.
|
14
|
+
overwrite (bool): Whether to overwrite the file if it exists.
|
15
|
+
"""
|
16
|
+
updating = os.path.exists(path) and not os.path.isdir(path)
|
17
|
+
if os.path.exists(path):
|
18
|
+
if os.path.isdir(path):
|
19
|
+
print_error("❌ Error: is a directory")
|
20
|
+
return f"❌ Cannot create file: '{path}' is an existing directory."
|
21
|
+
if not overwrite:
|
22
|
+
print_error(f"❗ Error: file '{path}' exists and overwrite is False")
|
23
|
+
return f"❗ Cannot create file: '{path}' already exists and overwrite is False."
|
24
|
+
if updating and overwrite:
|
25
|
+
print_info(f"📝 Updating file: '{format_path(path)}' ... ")
|
26
|
+
else:
|
27
|
+
print_info(f"📝 Creating file: '{format_path(path)}' ... ")
|
28
|
+
old_lines = None
|
29
|
+
if updating and overwrite:
|
30
|
+
with open(path, "r", encoding="utf-8") as f:
|
31
|
+
old_lines = sum(1 for _ in f)
|
32
|
+
with open(path, "w", encoding="utf-8") as f:
|
33
|
+
f.write(content)
|
34
|
+
print_success("✅ Success")
|
35
|
+
if old_lines is not None:
|
36
|
+
new_lines = content.count('\n') + 1 if content else 0
|
37
|
+
return f"✅ Successfully updated the file at '{path}' ({old_lines} > {new_lines} lines)."
|
38
|
+
else:
|
39
|
+
return f"✅ Successfully created the file at '{path}'."
|
40
|
+
|
41
|
+
|
42
|
+
@ToolHandler.register_tool
|
43
|
+
def remove_file(path: str) -> str:
|
44
|
+
print_info(f"🗑️ Removing file: '{format_path(path)}' ... ")
|
45
|
+
os.remove(path)
|
46
|
+
print_success("✅ Success")
|
47
|
+
return f"✅ Successfully deleted the file at '{path}'."
|
48
|
+
|
49
|
+
@ToolHandler.register_tool
|
50
|
+
def move_file(source_path: str, destination_path: str, overwrite: bool = False) -> str:
|
51
|
+
print_info(f"🚚 Moving '{format_path(source_path)}' to '{format_path(destination_path)}' ... ")
|
52
|
+
if not os.path.exists(source_path):
|
53
|
+
print_error("❌ Error: source does not exist")
|
54
|
+
return f"❌ Source path '{source_path}' does not exist."
|
55
|
+
if os.path.exists(destination_path):
|
56
|
+
if not overwrite:
|
57
|
+
print_error("❌ Error: destination exists and overwrite is False")
|
58
|
+
return f"❌ Destination path '{destination_path}' already exists. Use overwrite=True to replace it."
|
59
|
+
if os.path.isdir(destination_path):
|
60
|
+
shutil.rmtree(destination_path)
|
61
|
+
else:
|
62
|
+
os.remove(destination_path)
|
63
|
+
shutil.move(source_path, destination_path)
|
64
|
+
print_success("✅ Success")
|
65
|
+
return f"✅ Successfully moved '{source_path}' to '{destination_path}'."
|
66
|
+
|
67
|
+
@ToolHandler.register_tool
|
68
|
+
def create_directory(path: str) -> str:
|
69
|
+
print_info(f"📁 Creating directory: '{format_path(path)}' ... ")
|
70
|
+
os.makedirs(path, exist_ok=True)
|
71
|
+
print_success("✅ Success")
|
72
|
+
return f"✅ Directory '{path}' created successfully."
|
@@ -1,134 +1,134 @@
|
|
1
|
-
from janito.agent.tool_handler import ToolHandler
|
2
|
-
from janito.agent.runtime_config import runtime_config
|
3
|
-
from janito.agent.tools.rich_utils import print_info, print_success, print_error
|
4
|
-
import subprocess
|
5
|
-
import multiprocessing
|
6
|
-
from typing import Optional
|
7
|
-
|
8
|
-
import tempfile
|
9
|
-
import os
|
10
|
-
|
11
|
-
def _run_bash_command(command: str, result_queue: 'multiprocessing.Queue', trust: bool = False):
|
12
|
-
import subprocess
|
13
|
-
with tempfile.NamedTemporaryFile(delete=False, mode='w+', encoding='utf-8', suffix='.stdout') as stdout_file, \
|
14
|
-
tempfile.NamedTemporaryFile(delete=False, mode='w+', encoding='utf-8', suffix='.stderr') as stderr_file:
|
15
|
-
process = subprocess.Popen(
|
16
|
-
command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, encoding='utf-8', errors='replace'
|
17
|
-
)
|
18
|
-
while True:
|
19
|
-
stdout_line = process.stdout.readline() if process.stdout else ''
|
20
|
-
stderr_line = process.stderr.readline() if process.stderr else ''
|
21
|
-
if stdout_line:
|
22
|
-
if not trust:
|
23
|
-
print(stdout_line, end='')
|
24
|
-
stdout_file.write(stdout_line)
|
25
|
-
stdout_file.flush()
|
26
|
-
if stderr_line:
|
27
|
-
if not trust:
|
28
|
-
print(stderr_line, end='')
|
29
|
-
stderr_file.write(stderr_line)
|
30
|
-
stderr_file.flush()
|
31
|
-
if not stdout_line and not stderr_line and process.poll() is not None:
|
32
|
-
break
|
33
|
-
# Capture any remaining output after process ends
|
34
|
-
if process.stdout:
|
35
|
-
for line in process.stdout:
|
36
|
-
if not trust:
|
37
|
-
print(line, end='')
|
38
|
-
stdout_file.write(line)
|
39
|
-
if process.stderr:
|
40
|
-
for line in process.stderr:
|
41
|
-
if not trust:
|
42
|
-
print(line, end='')
|
43
|
-
stderr_file.write(line)
|
44
|
-
stdout_file_path = stdout_file.name
|
45
|
-
stderr_file_path = stderr_file.name
|
46
|
-
result_queue.put({
|
47
|
-
'stdout_file': stdout_file_path,
|
48
|
-
'stderr_file': stderr_file_path,
|
49
|
-
'returncode': process.returncode
|
50
|
-
})
|
51
|
-
|
52
|
-
|
53
|
-
@ToolHandler.register_tool
|
54
|
-
def run_bash_command(command: str, timeout: int = 60, require_confirmation: bool = False) -> str:
|
55
|
-
trust = runtime_config.get('trust', False)
|
56
|
-
"""
|
57
|
-
Execute a non-interactive bash command and print output live.
|
58
|
-
|
59
|
-
If require_confirmation is True, the user will be prompted to confirm execution before running the command.
|
60
|
-
|
61
|
-
Args:
|
62
|
-
command (str): The Bash command to execute.
|
63
|
-
timeout (int): Maximum number of seconds to allow the command to run. Default is 60.
|
64
|
-
|
65
|
-
Returns:
|
66
|
-
str: A formatted message string containing stdout, stderr, and return code.
|
67
|
-
"""
|
68
|
-
print_info(f"[run_bash_command] Running: {command}")
|
69
|
-
if require_confirmation:
|
70
|
-
# Prompt the user for confirmation directly
|
71
|
-
resp = input(f"Are you sure you want to run this command?\n\n{command}\n\nType 'yes' to confirm: ")
|
72
|
-
if resp.strip().lower() != 'yes':
|
73
|
-
print_error("❌ Command not confirmed by user.")
|
74
|
-
return "❌ Command not confirmed by user."
|
75
|
-
print_info(f"🐛 Running bash command: [bold]{command}[/bold] (timeout: {timeout}s)")
|
76
|
-
result_queue = multiprocessing.Queue()
|
77
|
-
process = multiprocessing.Process(target=_run_bash_command, args=(command, result_queue, trust))
|
78
|
-
process.start()
|
79
|
-
process.join(timeout)
|
80
|
-
if process.is_alive():
|
81
|
-
process.terminate()
|
82
|
-
process.join()
|
83
|
-
result = {'stdout_file': '', 'stderr_file': '', 'error': f'Process timed out after {timeout} seconds.', 'returncode': -1}
|
84
|
-
elif not result_queue.empty():
|
85
|
-
result = result_queue.get()
|
86
|
-
else:
|
87
|
-
result = {'stdout_file': '', 'stderr_file': '', 'error': 'No result returned from process.', 'returncode': -1}
|
88
|
-
if trust:
|
89
|
-
stdout_lines = 0
|
90
|
-
stderr_lines = 0
|
91
|
-
try:
|
92
|
-
with open(result['stdout_file'], 'r', encoding='utf-8') as f:
|
93
|
-
stdout_lines = sum(1 for _ in f)
|
94
|
-
except Exception:
|
95
|
-
pass
|
96
|
-
try:
|
97
|
-
with open(result['stderr_file'], 'r', encoding='utf-8') as f:
|
98
|
-
stderr_lines = sum(1 for _ in f)
|
99
|
-
except Exception:
|
100
|
-
pass
|
101
|
-
print_success(f"✅ Success (trust mode)\nstdout: {result['stdout_file']} (lines: {stdout_lines})\nstderr: {result['stderr_file']} (lines: {stderr_lines})")
|
102
|
-
return (
|
103
|
-
f"✅ Bash command executed in trust mode. Output is stored at:\n"
|
104
|
-
f"stdout: {result['stdout_file']} (lines: {stdout_lines})\n"
|
105
|
-
f"stderr: {result['stderr_file']} (lines: {stderr_lines})\n"
|
106
|
-
f"returncode: {result['returncode']}\n"
|
107
|
-
"To examine the output, use the file-related tools such as get_lines or search_files on the above files."
|
108
|
-
)
|
109
|
-
print_info("🐛 Bash command execution completed.")
|
110
|
-
print_info(f"Return code: {result['returncode']}")
|
111
|
-
if result.get('error'):
|
112
|
-
print_error(f"Error: {result['error']}")
|
113
|
-
return f"❌ Error: {result['error']}\nreturncode: {result['returncode']}"
|
114
|
-
stdout_lines = 0
|
115
|
-
stderr_lines = 0
|
116
|
-
try:
|
117
|
-
with open(result['stdout_file'], 'r', encoding='utf-8') as f:
|
118
|
-
stdout_lines = sum(1 for _ in f)
|
119
|
-
except Exception:
|
120
|
-
pass
|
121
|
-
try:
|
122
|
-
with open(result['stderr_file'], 'r', encoding='utf-8') as f:
|
123
|
-
stderr_lines = sum(1 for _ in f)
|
124
|
-
except Exception:
|
125
|
-
pass
|
126
|
-
print_success(f"✅ Success\nstdout saved to: {result['stdout_file']} (lines: {stdout_lines})\nstderr saved to: {result['stderr_file']} (lines: {stderr_lines})")
|
127
|
-
return (
|
128
|
-
f"✅ Bash command executed.\n"
|
129
|
-
f"stdout saved to: {result['stdout_file']} (lines: {stdout_lines})\n"
|
130
|
-
f"stderr saved to: {result['stderr_file']} (lines: {stderr_lines})\n"
|
131
|
-
f"returncode: {result['returncode']}\n"
|
132
|
-
"\nTo examine the output, use the file-related tools such as get_lines or search_files on the above files."
|
133
|
-
)
|
134
|
-
|
1
|
+
from janito.agent.tool_handler import ToolHandler
|
2
|
+
from janito.agent.runtime_config import runtime_config
|
3
|
+
from janito.agent.tools.rich_utils import print_info, print_success, print_error
|
4
|
+
import subprocess
|
5
|
+
import multiprocessing
|
6
|
+
from typing import Optional
|
7
|
+
|
8
|
+
import tempfile
|
9
|
+
import os
|
10
|
+
|
11
|
+
def _run_bash_command(command: str, result_queue: 'multiprocessing.Queue', trust: bool = False):
|
12
|
+
import subprocess
|
13
|
+
with tempfile.NamedTemporaryFile(delete=False, mode='w+', encoding='utf-8', suffix='.stdout') as stdout_file, \
|
14
|
+
tempfile.NamedTemporaryFile(delete=False, mode='w+', encoding='utf-8', suffix='.stderr') as stderr_file:
|
15
|
+
process = subprocess.Popen(
|
16
|
+
command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, encoding='utf-8', errors='replace'
|
17
|
+
)
|
18
|
+
while True:
|
19
|
+
stdout_line = process.stdout.readline() if process.stdout else ''
|
20
|
+
stderr_line = process.stderr.readline() if process.stderr else ''
|
21
|
+
if stdout_line:
|
22
|
+
if not trust:
|
23
|
+
print(stdout_line, end='')
|
24
|
+
stdout_file.write(stdout_line)
|
25
|
+
stdout_file.flush()
|
26
|
+
if stderr_line:
|
27
|
+
if not trust:
|
28
|
+
print(stderr_line, end='')
|
29
|
+
stderr_file.write(stderr_line)
|
30
|
+
stderr_file.flush()
|
31
|
+
if not stdout_line and not stderr_line and process.poll() is not None:
|
32
|
+
break
|
33
|
+
# Capture any remaining output after process ends
|
34
|
+
if process.stdout:
|
35
|
+
for line in process.stdout:
|
36
|
+
if not trust:
|
37
|
+
print(line, end='')
|
38
|
+
stdout_file.write(line)
|
39
|
+
if process.stderr:
|
40
|
+
for line in process.stderr:
|
41
|
+
if not trust:
|
42
|
+
print(line, end='')
|
43
|
+
stderr_file.write(line)
|
44
|
+
stdout_file_path = stdout_file.name
|
45
|
+
stderr_file_path = stderr_file.name
|
46
|
+
result_queue.put({
|
47
|
+
'stdout_file': stdout_file_path,
|
48
|
+
'stderr_file': stderr_file_path,
|
49
|
+
'returncode': process.returncode
|
50
|
+
})
|
51
|
+
|
52
|
+
|
53
|
+
@ToolHandler.register_tool
|
54
|
+
def run_bash_command(command: str, timeout: int = 60, require_confirmation: bool = False) -> str:
|
55
|
+
trust = runtime_config.get('trust', False)
|
56
|
+
"""
|
57
|
+
Execute a non-interactive bash command and print output live.
|
58
|
+
|
59
|
+
If require_confirmation is True, the user will be prompted to confirm execution before running the command.
|
60
|
+
|
61
|
+
Args:
|
62
|
+
command (str): The Bash command to execute.
|
63
|
+
timeout (int): Maximum number of seconds to allow the command to run. Default is 60.
|
64
|
+
|
65
|
+
Returns:
|
66
|
+
str: A formatted message string containing stdout, stderr, and return code.
|
67
|
+
"""
|
68
|
+
print_info(f"[run_bash_command] Running: {command}")
|
69
|
+
if require_confirmation:
|
70
|
+
# Prompt the user for confirmation directly
|
71
|
+
resp = input(f"Are you sure you want to run this command?\n\n{command}\n\nType 'yes' to confirm: ")
|
72
|
+
if resp.strip().lower() != 'yes':
|
73
|
+
print_error("❌ Command not confirmed by user.")
|
74
|
+
return "❌ Command not confirmed by user."
|
75
|
+
print_info(f"🐛 Running bash command: [bold]{command}[/bold] (timeout: {timeout}s)")
|
76
|
+
result_queue = multiprocessing.Queue()
|
77
|
+
process = multiprocessing.Process(target=_run_bash_command, args=(command, result_queue, trust))
|
78
|
+
process.start()
|
79
|
+
process.join(timeout)
|
80
|
+
if process.is_alive():
|
81
|
+
process.terminate()
|
82
|
+
process.join()
|
83
|
+
result = {'stdout_file': '', 'stderr_file': '', 'error': f'Process timed out after {timeout} seconds.', 'returncode': -1}
|
84
|
+
elif not result_queue.empty():
|
85
|
+
result = result_queue.get()
|
86
|
+
else:
|
87
|
+
result = {'stdout_file': '', 'stderr_file': '', 'error': 'No result returned from process.', 'returncode': -1}
|
88
|
+
if trust:
|
89
|
+
stdout_lines = 0
|
90
|
+
stderr_lines = 0
|
91
|
+
try:
|
92
|
+
with open(result['stdout_file'], 'r', encoding='utf-8') as f:
|
93
|
+
stdout_lines = sum(1 for _ in f)
|
94
|
+
except Exception:
|
95
|
+
pass
|
96
|
+
try:
|
97
|
+
with open(result['stderr_file'], 'r', encoding='utf-8') as f:
|
98
|
+
stderr_lines = sum(1 for _ in f)
|
99
|
+
except Exception:
|
100
|
+
pass
|
101
|
+
print_success(f"✅ Success (trust mode)\nstdout: {result['stdout_file']} (lines: {stdout_lines})\nstderr: {result['stderr_file']} (lines: {stderr_lines})")
|
102
|
+
return (
|
103
|
+
f"✅ Bash command executed in trust mode. Output is stored at:\n"
|
104
|
+
f"stdout: {result['stdout_file']} (lines: {stdout_lines})\n"
|
105
|
+
f"stderr: {result['stderr_file']} (lines: {stderr_lines})\n"
|
106
|
+
f"returncode: {result['returncode']}\n"
|
107
|
+
"To examine the output, use the file-related tools such as get_lines or search_files on the above files."
|
108
|
+
)
|
109
|
+
print_info("🐛 Bash command execution completed.")
|
110
|
+
print_info(f"Return code: {result['returncode']}")
|
111
|
+
if result.get('error'):
|
112
|
+
print_error(f"Error: {result['error']}")
|
113
|
+
return f"❌ Error: {result['error']}\nreturncode: {result['returncode']}"
|
114
|
+
stdout_lines = 0
|
115
|
+
stderr_lines = 0
|
116
|
+
try:
|
117
|
+
with open(result['stdout_file'], 'r', encoding='utf-8') as f:
|
118
|
+
stdout_lines = sum(1 for _ in f)
|
119
|
+
except Exception:
|
120
|
+
pass
|
121
|
+
try:
|
122
|
+
with open(result['stderr_file'], 'r', encoding='utf-8') as f:
|
123
|
+
stderr_lines = sum(1 for _ in f)
|
124
|
+
except Exception:
|
125
|
+
pass
|
126
|
+
print_success(f"✅ Success\nstdout saved to: {result['stdout_file']} (lines: {stdout_lines})\nstderr saved to: {result['stderr_file']} (lines: {stderr_lines})")
|
127
|
+
return (
|
128
|
+
f"✅ Bash command executed.\n"
|
129
|
+
f"stdout saved to: {result['stdout_file']} (lines: {stdout_lines})\n"
|
130
|
+
f"stderr saved to: {result['stderr_file']} (lines: {stderr_lines})\n"
|
131
|
+
f"returncode: {result['returncode']}\n"
|
132
|
+
"\nTo examine the output, use the file-related tools such as get_lines or search_files on the above files."
|
133
|
+
)
|
134
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
|
3
|
+
class ToolBase(ABC):
|
4
|
+
"""
|
5
|
+
Base class for all tools. Inherit from this class to implement a new tool.
|
6
|
+
"""
|
7
|
+
def __init__(self):
|
8
|
+
self.progress_messages = []
|
9
|
+
|
10
|
+
@abstractmethod
|
11
|
+
def call(self, **kwargs):
|
12
|
+
"""
|
13
|
+
Trigger the tool's action. Must be implemented by subclasses.
|
14
|
+
"""
|
15
|
+
pass
|
16
|
+
|
17
|
+
def on_progress(self, message: str):
|
18
|
+
"""
|
19
|
+
Report progress. Subclasses can override this to customize progress reporting.
|
20
|
+
"""
|
21
|
+
self.progress_messages.append(message)
|
22
|
+
print(f"[Tool Progress] {message}")
|
@@ -1,4 +1,4 @@
|
|
1
|
-
janito/__init__.py,sha256=
|
1
|
+
janito/__init__.py,sha256=uCv73rgSEXLv0WZ2fvJpwCpBCFcxOh94XqSDccIBrL8,23
|
2
2
|
janito/__main__.py,sha256=CBScR30Tm-vuhIJM8o5HXKr0q-smICiwSVyuU68BP8U,78
|
3
3
|
janito/render_prompt.py,sha256=xCQgYRqMyz9Pzi7096NoZfC4lFiKEHEaXiTYP6ByViY,513
|
4
4
|
janito/agent/__init__.py,sha256=CByAH5Yk-yH64zo0RU7Z3nsn_7Vmandphqk0JNlpyj8,21
|
@@ -10,10 +10,11 @@ janito/agent/conversation.py,sha256=vbCL-1LlJjKRN6q3CjfSe4ENGplP-YQKsAEA1uX3RWU,
|
|
10
10
|
janito/agent/queued_tool_handler.py,sha256=THPymKXnpoXfN49EhW5b4hrwpWZZup73JKFDJ_U03tI,540
|
11
11
|
janito/agent/runtime_config.py,sha256=H6bnRVYR0zC-WhmLpBU-IXikXWKcIiBQqFnc4uGooj4,908
|
12
12
|
janito/agent/tool_handler.py,sha256=sKnySRfZQBUjZxve8CH74me9Q4_ewtIege_HBiCs9wY,8291
|
13
|
+
janito/agent/templates/system_instructions.j2,sha256=3lZShjpzg-PBx27TmtmJijR6gedmNZtdXIwCVgYILzw,1704
|
13
14
|
janito/agent/tools/__init__.py,sha256=j0MGKIrtEkI3f6yumsJeDqiPyvDMehZ_3e2Osujev3c,486
|
14
15
|
janito/agent/tools/ask_user.py,sha256=-omTj2woHGbl4xR14sB3dbnRD1zGIbvKv4wjq9g4NXE,1917
|
15
16
|
janito/agent/tools/fetch_url.py,sha256=tce4L5LDiIsSreo-aJVmpwu1yCkDCY0kEZId3lgGiCU,1578
|
16
|
-
janito/agent/tools/file_ops.py,sha256=
|
17
|
+
janito/agent/tools/file_ops.py,sha256=RBnKKvRagEu3rIeNYrpgbaxDts7D_B1ivjJrpSQ2QzA,3243
|
17
18
|
janito/agent/tools/find_files.py,sha256=OxJghgmPvk3RFF5N_6CCW_ftB6RgG3QzeBzc1bItLKA,2353
|
18
19
|
janito/agent/tools/get_lines.py,sha256=eazwPkwB_P9VkHN-ubOZK5lK5qOJGU0QXVOb6RwQl3g,2948
|
19
20
|
janito/agent/tools/gitignore_utils.py,sha256=zXiqx4HetZ7iKkV5qXyHyZ5yrrVex4G17WHBWToFo3Y,1158
|
@@ -23,8 +24,9 @@ janito/agent/tools/remove_directory.py,sha256=CUzXaotktgpyX6LUsfK_-m91Onkwk9wbdA
|
|
23
24
|
janito/agent/tools/replace_text_in_file.py,sha256=2uOZJW2SzZPFp7_wcU8Hw38pKWDWkmq_24mxiUrRWDo,3533
|
24
25
|
janito/agent/tools/rich_live.py,sha256=cuZ3-ZxpuHxR1TvIcp0bi9F3QM1M6Ms0XiOMd8If8gU,1161
|
25
26
|
janito/agent/tools/rich_utils.py,sha256=aQMqeaq3hIpzZ5EHQBNTKS5dNsojQp9MDfJSoqOQe0k,837
|
26
|
-
janito/agent/tools/run_bash_command.py,sha256=
|
27
|
+
janito/agent/tools/run_bash_command.py,sha256=qY8h6b4ru9J7u7Ve6oYOqwqYXH14J4BUACriCsCZKK0,6154
|
27
28
|
janito/agent/tools/search_files.py,sha256=HbLq9oHcb9udrbql6-QE53zo5F3UeuhlptMvf2mIQVo,1945
|
29
|
+
janito/agent/tools/tool_base.py,sha256=Q1wcJdDiLRVldtqVYCiRTGFyVv1Xz4rboHnJAKIJsrs,637
|
28
30
|
janito/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
29
31
|
janito/cli/_print_config.py,sha256=vMMlCY-hJPsLHUxx9TJuOY9iyYVBH8C4nVACCwY4l5U,3294
|
30
32
|
janito/cli/_utils.py,sha256=Q_OCFZmbr78qW4hSSUUhjondVc0ao7-iUHE7Ig8IP1g,289
|
@@ -43,9 +45,9 @@ janito/cli_chat_shell/ui.py,sha256=9IngH8HFherjatfa9Eu37jb4b2gOP0lsgcUhbnQKCZA,5
|
|
43
45
|
janito/web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
44
46
|
janito/web/__main__.py,sha256=oPXNF332aCeI7aUWr7_8M57oOKugw422VrEubxFp0P4,354
|
45
47
|
janito/web/app.py,sha256=stogs_HaM-axsWTwoiVma9M46Y8dMu0QRjopsekRjQs,6622
|
46
|
-
janito-1.3.
|
47
|
-
janito-1.3.
|
48
|
-
janito-1.3.
|
49
|
-
janito-1.3.
|
50
|
-
janito-1.3.
|
51
|
-
janito-1.3.
|
48
|
+
janito-1.3.2.dist-info/licenses/LICENSE,sha256=sHBqv0bvtrb29H7WRR-Z603YHm9pLtJIo3nHU_9cmgE,1091
|
49
|
+
janito-1.3.2.dist-info/METADATA,sha256=SZfXBoD6mH5cxOTG7j3kSXi2tGoOhi-fNC-jpk3Vo9I,9071
|
50
|
+
janito-1.3.2.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
51
|
+
janito-1.3.2.dist-info/entry_points.txt,sha256=wIo5zZxbmu4fC-ZMrsKD0T0vq7IqkOOLYhrqRGypkx4,48
|
52
|
+
janito-1.3.2.dist-info/top_level.txt,sha256=m0NaVCq0-ivxbazE2-ND0EA9Hmuijj_OGkmCbnBcCig,7
|
53
|
+
janito-1.3.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|