janito 1.4.0__py3-none-any.whl → 1.4.1__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/conversation.py +7 -1
- janito/agent/tools/fetch_url.py +2 -2
- janito/agent/tools/file_ops.py +3 -57
- janito/agent/tools/find_files.py +1 -1
- janito/agent/tools/get_file_outline.py +4 -3
- janito/agent/tools/get_lines.py +3 -0
- janito/agent/tools/py_compile.py +1 -1
- janito/agent/tools/python_exec.py +2 -2
- janito/agent/tools/remove_directory.py +2 -2
- janito/agent/tools/search_files.py +2 -2
- {janito-1.4.0.dist-info → janito-1.4.1.dist-info}/METADATA +1 -2
- {janito-1.4.0.dist-info → janito-1.4.1.dist-info}/RECORD +17 -17
- {janito-1.4.0.dist-info → janito-1.4.1.dist-info}/WHEEL +0 -0
- {janito-1.4.0.dist-info → janito-1.4.1.dist-info}/entry_points.txt +0 -0
- {janito-1.4.0.dist-info → janito-1.4.1.dist-info}/licenses/LICENSE +0 -0
- {janito-1.4.0.dist-info → janito-1.4.1.dist-info}/top_level.txt +0 -0
janito/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "1.4.
|
1
|
+
__version__ = "1.4.1"
|
janito/agent/conversation.py
CHANGED
@@ -45,7 +45,13 @@ class ConversationHandler:
|
|
45
45
|
if spinner:
|
46
46
|
# Calculate word count for all messages
|
47
47
|
word_count = sum(len(str(m.get('content', '')).split()) for m in messages if 'content' in m)
|
48
|
-
|
48
|
+
def format_count(n):
|
49
|
+
if n >= 1_000_000:
|
50
|
+
return f"{n/1_000_000:.1f}m"
|
51
|
+
elif n >= 1_000:
|
52
|
+
return f"{n/1_000:.1f}k"
|
53
|
+
return str(n)
|
54
|
+
spinner_msg = f"[bold green]Waiting for AI response... ({format_count(word_count)} words in conversation)"
|
49
55
|
with console.status(spinner_msg, spinner="dots") as status:
|
50
56
|
response = self.client.chat.completions.create(
|
51
57
|
model=self.model,
|
janito/agent/tools/fetch_url.py
CHANGED
@@ -8,7 +8,7 @@ from janito.agent.tools.tool_base import ToolBase
|
|
8
8
|
class FetchUrlTool(ToolBase):
|
9
9
|
"""Fetch the content of a web page and extract its text."""
|
10
10
|
def call(self, url: str, search_strings: list[str] = None) -> str:
|
11
|
-
print_info(f"🌐 Fetching URL: {url} ... ")
|
11
|
+
print_info(f"🌐 Fetching URL: {url} ... ", end="")
|
12
12
|
response = requests.get(url, timeout=10)
|
13
13
|
response.raise_for_status()
|
14
14
|
self.update_progress(f"Fetched URL with status {response.status_code}")
|
@@ -29,7 +29,7 @@ class FetchUrlTool(ToolBase):
|
|
29
29
|
else:
|
30
30
|
text = "No matches found for the provided search strings."
|
31
31
|
|
32
|
-
print_success("
|
32
|
+
print_success("✅ Success")
|
33
33
|
return text
|
34
34
|
|
35
35
|
ToolHandler.register_tool(FetchUrlTool, name="fetch_url")
|
janito/agent/tools/file_ops.py
CHANGED
@@ -31,11 +31,11 @@ class CreateFileTool(ToolBase):
|
|
31
31
|
old_lines = sum(1 for _ in f)
|
32
32
|
with open(path, "w", encoding="utf-8") as f:
|
33
33
|
f.write(content)
|
34
|
-
|
34
|
+
new_lines = content.count('\n') + 1 if content else 0
|
35
35
|
if old_lines is not None:
|
36
|
-
|
36
|
+
print_success(f"✅ Successfully updated the file at '{disp_path}' ({old_lines} > {new_lines} lines).")
|
37
37
|
return f"✅ Successfully updated the file at '{disp_path}' ({old_lines} > {new_lines} lines)."
|
38
|
-
|
38
|
+
print_success(f"✅ Successfully created the file at '{disp_path}' ({new_lines} lines).")
|
39
39
|
return f"✅ Successfully created the file at '{disp_path}' ({new_lines} lines)."
|
40
40
|
|
41
41
|
class CreateDirectoryTool(ToolBase):
|
@@ -58,57 +58,3 @@ class CreateDirectoryTool(ToolBase):
|
|
58
58
|
if not os.path.isdir(path):
|
59
59
|
print_error(f"❌ Path '{disp_path}' exists and is not a directory.")
|
60
60
|
return f"❌ Path '{disp_path}' exists and is not a directory."
|
61
|
-
if not overwrite:
|
62
|
-
print_error(f"❗ Directory '{disp_path}' already exists and overwrite is False.")
|
63
|
-
return f"❗ Directory '{disp_path}' already exists and overwrite is False."
|
64
|
-
# Remove existing directory if overwrite is True
|
65
|
-
shutil.rmtree(path)
|
66
|
-
print_info(f"🗑️ Removed existing directory: '{disp_path}'")
|
67
|
-
os.makedirs(path, exist_ok=True)
|
68
|
-
print_success(f"✅ Created directory: '{disp_path}'")
|
69
|
-
return f"✅ Successfully created directory at '{disp_path}'."
|
70
|
-
|
71
|
-
class RemoveFileTool(ToolBase):
|
72
|
-
"""
|
73
|
-
Remove a file at the specified path.
|
74
|
-
"""
|
75
|
-
def call(self, path: str) -> str:
|
76
|
-
original_path = path
|
77
|
-
path = expand_path(path)
|
78
|
-
disp_path = display_path(original_path, path)
|
79
|
-
print_info(f"🗑️ Removing file: '{disp_path}' ... ")
|
80
|
-
os.remove(path)
|
81
|
-
print_success("✅ Success")
|
82
|
-
return f"✅ Successfully deleted the file at '{disp_path}'."
|
83
|
-
|
84
|
-
class MoveFileTool(ToolBase):
|
85
|
-
"""
|
86
|
-
Move or rename a file from source to destination.
|
87
|
-
"""
|
88
|
-
def call(self, source_path: str, destination_path: str, overwrite: bool = False) -> str:
|
89
|
-
orig_source = source_path
|
90
|
-
orig_dest = destination_path
|
91
|
-
source_path = expand_path(source_path)
|
92
|
-
destination_path = expand_path(destination_path)
|
93
|
-
disp_source = display_path(orig_source, source_path)
|
94
|
-
disp_dest = display_path(orig_dest, destination_path)
|
95
|
-
print_info(f"🚚 Moving '{disp_source}' to '{disp_dest}' ... ")
|
96
|
-
if not os.path.exists(source_path):
|
97
|
-
print_error(f"❌ Error: source does not exist")
|
98
|
-
return f"❌ Source path '{disp_source}' does not exist."
|
99
|
-
if os.path.exists(destination_path):
|
100
|
-
if not overwrite:
|
101
|
-
print_error(f"❗ Error: destination exists and overwrite is False")
|
102
|
-
return f"❗ Destination path '{disp_dest}' already exists and overwrite is False."
|
103
|
-
if os.path.isdir(destination_path):
|
104
|
-
print_error(f"❌ Error: destination is a directory")
|
105
|
-
return f"❌ Destination path '{disp_dest}' is an existing directory."
|
106
|
-
shutil.move(source_path, destination_path)
|
107
|
-
print_success("✅ Success")
|
108
|
-
return f"✅ Successfully moved '{disp_source}' to '{disp_dest}'."
|
109
|
-
|
110
|
-
# register tools
|
111
|
-
ToolHandler.register_tool(CreateFileTool, name="create_file")
|
112
|
-
ToolHandler.register_tool(CreateDirectoryTool, name="create_directory")
|
113
|
-
ToolHandler.register_tool(RemoveFileTool, name="remove_file")
|
114
|
-
ToolHandler.register_tool(MoveFileTool, name="move_file")
|
janito/agent/tools/find_files.py
CHANGED
@@ -15,7 +15,7 @@ class FindFilesTool(ToolBase):
|
|
15
15
|
return os.path.relpath(path)
|
16
16
|
disp_path = _display_path(directory)
|
17
17
|
rec = "recursively" if recursive else "non-recursively"
|
18
|
-
print_info(f"\U0001F50D Searching '{disp_path}' for pattern '{pattern}' ({rec}, max {max_results})")
|
18
|
+
print_info(f"\U0001F50D Searching '{disp_path}' for pattern '{pattern}' ({rec}, max {max_results})", end="")
|
19
19
|
self.update_progress(f"Searching for files in {directory} matching {pattern}")
|
20
20
|
matches = []
|
21
21
|
for root, dirs, files in os.walk(directory):
|
@@ -6,14 +6,15 @@ from janito.agent.tools.rich_utils import print_info, print_success, print_error
|
|
6
6
|
class GetFileOutlineTool(ToolBase):
|
7
7
|
"""Get an outline of a file's structure."""
|
8
8
|
def call(self, file_path: str) -> str:
|
9
|
-
print_info(f"
|
9
|
+
print_info(f"\U0001F4C4 Getting outline for: {file_path}", end="")
|
10
10
|
self.update_progress(f"Getting outline for: {file_path}")
|
11
11
|
try:
|
12
12
|
with open(file_path, 'r', encoding='utf-8') as f:
|
13
13
|
lines = f.readlines()
|
14
14
|
outline = [line.strip() for line in lines if line.strip()]
|
15
|
-
|
16
|
-
|
15
|
+
num_items = len(outline)
|
16
|
+
print_success(f"✅ Outline generated ({num_items} items)")
|
17
|
+
return f"Outline: {num_items} items\n" + '\n'.join(outline)
|
17
18
|
except Exception as e:
|
18
19
|
print_error(f"\u274c Error reading file: {e}")
|
19
20
|
return f"Error reading file: {e}"
|
janito/agent/tools/get_lines.py
CHANGED
@@ -28,6 +28,9 @@ class GetLinesTool(ToolBase):
|
|
28
28
|
print_success(f" ✅ {len(lines)} lines read")
|
29
29
|
return ''.join(selected)
|
30
30
|
except Exception as e:
|
31
|
+
if isinstance(e, FileNotFoundError):
|
32
|
+
print_error(f"❗ not found")
|
33
|
+
return "❗ not found"
|
31
34
|
print_error(f" ❌ Error: {e}")
|
32
35
|
return f"Error reading file: {e}"
|
33
36
|
|
janito/agent/tools/py_compile.py
CHANGED
@@ -7,7 +7,7 @@ import py_compile
|
|
7
7
|
class PyCompileTool(ToolBase):
|
8
8
|
"""Validate a Python file by compiling it with py_compile."""
|
9
9
|
def call(self, file_path: str, doraise: Optional[bool] = True) -> str:
|
10
|
-
print_info(f"[py_compile] Compiling Python file: {file_path}")
|
10
|
+
print_info(f"[py_compile] Compiling Python file: {file_path}", end="")
|
11
11
|
self.update_progress(f"Compiling Python file: {file_path}")
|
12
12
|
try:
|
13
13
|
py_compile.compile(file_path, doraise=doraise)
|
@@ -31,7 +31,7 @@ class PythonExecTool(ToolBase):
|
|
31
31
|
str: Formatted stdout, stderr, and return code.
|
32
32
|
"""
|
33
33
|
def call(self, code: str) -> str:
|
34
|
-
print_info(f"🐍 Executing Python code ...")
|
34
|
+
print_info(f"🐍 Executing Python code ...", end="")
|
35
35
|
print_info(code)
|
36
36
|
self.update_progress("Starting Python code execution...")
|
37
37
|
result_queue = multiprocessing.Queue()
|
@@ -45,7 +45,7 @@ class PythonExecTool(ToolBase):
|
|
45
45
|
self.update_progress(f"Python code execution completed with return code: {result['returncode']}")
|
46
46
|
if result['returncode'] == 0:
|
47
47
|
from janito.agent.tools.rich_utils import print_success
|
48
|
-
print_success(f"
|
48
|
+
print_success(f"✅ Python code executed successfully.")
|
49
49
|
else:
|
50
50
|
from janito.agent.tools.rich_utils import print_error
|
51
51
|
print_error(f"\u274c Python code execution failed with return code {result['returncode']}")
|
@@ -8,14 +8,14 @@ from janito.agent.tools.rich_utils import print_info, print_success, print_error
|
|
8
8
|
class RemoveDirectoryTool(ToolBase):
|
9
9
|
"""Remove a directory. If recursive=False and directory not empty, raises error."""
|
10
10
|
def call(self, directory: str, recursive: bool = False) -> str:
|
11
|
-
print_info(f"🗃️ Removing directory: {directory} (recursive={recursive})")
|
11
|
+
print_info(f"🗃️ Removing directory: {directory} (recursive={recursive})", end="")
|
12
12
|
self.update_progress(f"Removing directory: {directory} (recursive={recursive})")
|
13
13
|
try:
|
14
14
|
if recursive:
|
15
15
|
shutil.rmtree(directory)
|
16
16
|
else:
|
17
17
|
os.rmdir(directory)
|
18
|
-
print_success(f"
|
18
|
+
print_success(f"✅ Directory removed: {directory}")
|
19
19
|
return f"Directory removed: {directory}"
|
20
20
|
except Exception as e:
|
21
21
|
print_error(f"\u274c Error removing directory: {e}")
|
@@ -7,7 +7,7 @@ from janito.agent.tools.rich_utils import print_info, print_success
|
|
7
7
|
class SearchFilesTool(ToolBase):
|
8
8
|
"""Search for a text pattern in all files within a directory and return matching lines."""
|
9
9
|
def call(self, directory: str, pattern: str) -> str:
|
10
|
-
print_info(f"🔎 Searching for pattern '{pattern}' in directory {directory}")
|
10
|
+
print_info(f"🔎 Searching for pattern '{pattern}' in directory {directory}", end="")
|
11
11
|
self.update_progress(f"Searching for pattern '{pattern}' in directory {directory}")
|
12
12
|
matches = []
|
13
13
|
for root, dirs, files in os.walk(directory):
|
@@ -20,7 +20,7 @@ class SearchFilesTool(ToolBase):
|
|
20
20
|
matches.append(f"{path}:{lineno}: {line.strip()}")
|
21
21
|
except Exception:
|
22
22
|
continue
|
23
|
-
print_success(f"
|
23
|
+
print_success(f"✅ {len(matches)} matches found")
|
24
24
|
return '\n'.join(matches)
|
25
25
|
|
26
26
|
ToolHandler.register_tool(SearchFilesTool, name="search_files")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: janito
|
3
|
-
Version: 1.4.
|
3
|
+
Version: 1.4.1
|
4
4
|
Summary: A Natural Programming Language Agent,
|
5
5
|
Author-email: João Pinto <joao.pinto@gmail.com>
|
6
6
|
License: MIT
|
@@ -8,7 +8,6 @@ Project-URL: homepage, https://github.com/joaompinto/janito
|
|
8
8
|
Project-URL: repository, https://github.com/joaompinto/janito
|
9
9
|
Keywords: agent,framework,tools,automation
|
10
10
|
Classifier: Programming Language :: Python :: 3.10
|
11
|
-
Classifier: License :: OSI Approved :: MIT License
|
12
11
|
Classifier: Operating System :: OS Independent
|
13
12
|
Requires-Python: >=3.10
|
14
13
|
Description-Content-Type: text/markdown
|
@@ -1,4 +1,4 @@
|
|
1
|
-
janito/__init__.py,sha256
|
1
|
+
janito/__init__.py,sha256=nxjQ6mMSJJKqkpX2IY-1BmdpErEa1Lx5hYzk9ULB09w,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
|
@@ -6,27 +6,27 @@ janito/agent/agent.py,sha256=X5swt-SUKnIxrSQaGfhxPk61M-BXREz4n02ynE0dVVU,4245
|
|
6
6
|
janito/agent/config.py,sha256=Z-_IeWxJB_1ca5LVR7PtHChZgc5eAsgegyEmVAxr1NY,4472
|
7
7
|
janito/agent/config_defaults.py,sha256=vSif3tJYZ7pMHaNqH6jGb7EKctfE-Kt8ueD17sC0ESY,395
|
8
8
|
janito/agent/config_utils.py,sha256=UmvR236wDrMc-aTy9LxVbop6YeoJaaPb1d2DBMlkSRg,254
|
9
|
-
janito/agent/conversation.py,sha256=
|
9
|
+
janito/agent/conversation.py,sha256=Ih1brlxJ4m3LZS99gqgH9XK2ohTSLPOurCqd0RqCXm8,6453
|
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=h-pxG1lhyIJohZmvwHSsknBSonrJQYGGzBL6Tobgmrg,7414
|
13
13
|
janito/agent/templates/system_instructions.j2,sha256=BtwMcibxnwZmQhGN7p_VGhhyAPzCfqksnW4B-PTWa-8,1532
|
14
14
|
janito/agent/tools/__init__.py,sha256=Vv1oWF6Ur-Tkm3p0KCz5HD7wwar9rUHtY596NGPnn2s,378
|
15
15
|
janito/agent/tools/ask_user.py,sha256=C1YC_gr0kh3-7vw2PgdIi4D8Paw-eNGpaWQy4HD3Gmo,2180
|
16
|
-
janito/agent/tools/fetch_url.py,sha256=
|
17
|
-
janito/agent/tools/file_ops.py,sha256=
|
18
|
-
janito/agent/tools/find_files.py,sha256=
|
19
|
-
janito/agent/tools/get_file_outline.py,sha256=
|
20
|
-
janito/agent/tools/get_lines.py,sha256=
|
16
|
+
janito/agent/tools/fetch_url.py,sha256=UZ9lv0Ko88eDeu6gvEqqPQ5Yug2aBb1NawaoFAIte8Y,1423
|
17
|
+
janito/agent/tools/file_ops.py,sha256=qdcroy6aE0f4ZZERgbFEsxkzc0yJZAvlhtFl_6JIEaM,2884
|
18
|
+
janito/agent/tools/find_files.py,sha256=unw82GwaNa6_2kKD2wTzJ9r66-j_FHboi2W3bfCMAaw,1372
|
19
|
+
janito/agent/tools/get_file_outline.py,sha256=OUJui1oxKkQUDtGaIHAK-u8xG60Vv8VvO_Idy-7xr6k,1046
|
20
|
+
janito/agent/tools/get_lines.py,sha256=QoJGgINpghe87i6j20UhBGPa9rFI1DHEojh8PR1e_ek,1692
|
21
21
|
janito/agent/tools/gitignore_utils.py,sha256=z_IYilabTD_-c14aRxuVasojOzTsg-11xJPJqudWIKA,1306
|
22
|
-
janito/agent/tools/py_compile.py,sha256=
|
23
|
-
janito/agent/tools/python_exec.py,sha256=
|
24
|
-
janito/agent/tools/remove_directory.py,sha256=
|
22
|
+
janito/agent/tools/py_compile.py,sha256=fYGR6zRepmV7uHExOEaa61Fr7IdnY7a7HOhtFJ-xnzY,1107
|
23
|
+
janito/agent/tools/python_exec.py,sha256=R8PenQliPTdNEazvuW6bW4MYioO9Q46oAMJK-hg3qTI,2193
|
24
|
+
janito/agent/tools/remove_directory.py,sha256=UvtTd3pxKRQ2I4hyFBBuOORz2OygvlMgM8akeMHvwSw,1081
|
25
25
|
janito/agent/tools/replace_text_in_file.py,sha256=eO7YumsT8Eq3_SOgl5DW_k9vhXO7egyMaiB6ZgtiHRU,3894
|
26
26
|
janito/agent/tools/rich_live.py,sha256=cuZ3-ZxpuHxR1TvIcp0bi9F3QM1M6Ms0XiOMd8If8gU,1161
|
27
27
|
janito/agent/tools/rich_utils.py,sha256=Lc4phM4DUG-eiiub2PFThc6pBk5aOo_6f09JPdZIdsk,894
|
28
28
|
janito/agent/tools/run_bash_command.py,sha256=rKAx_n6xxpHeBzDg_7BVkAjMgPGiXVLpjx6i2o1lMb0,3883
|
29
|
-
janito/agent/tools/search_files.py,sha256=
|
29
|
+
janito/agent/tools/search_files.py,sha256=h6-7DsWdrvzBhBWE0NkmELV0ZzO8Dme1kmfOgYL3x9Y,1255
|
30
30
|
janito/agent/tools/tool_base.py,sha256=nS2FXSw3YY6gJiKh-l1m1udnHT7F3yKwGpGHJHfERbY,836
|
31
31
|
janito/agent/tools/utils.py,sha256=cKZ2qxK-S01mzBmCXYWwQ9zOyT994SaoRZYbD1o57Dk,1113
|
32
32
|
janito/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -47,9 +47,9 @@ janito/cli_chat_shell/ui.py,sha256=9IngH8HFherjatfa9Eu37jb4b2gOP0lsgcUhbnQKCZA,5
|
|
47
47
|
janito/web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
48
48
|
janito/web/__main__.py,sha256=oPXNF332aCeI7aUWr7_8M57oOKugw422VrEubxFp0P4,354
|
49
49
|
janito/web/app.py,sha256=stogs_HaM-axsWTwoiVma9M46Y8dMu0QRjopsekRjQs,6622
|
50
|
-
janito-1.4.
|
51
|
-
janito-1.4.
|
52
|
-
janito-1.4.
|
53
|
-
janito-1.4.
|
54
|
-
janito-1.4.
|
55
|
-
janito-1.4.
|
50
|
+
janito-1.4.1.dist-info/licenses/LICENSE,sha256=sHBqv0bvtrb29H7WRR-Z603YHm9pLtJIo3nHU_9cmgE,1091
|
51
|
+
janito-1.4.1.dist-info/METADATA,sha256=NzxCNDao3CIqAETg4KZb0wTBnVD5Ne9T2jrN90zcFFk,9062
|
52
|
+
janito-1.4.1.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
53
|
+
janito-1.4.1.dist-info/entry_points.txt,sha256=wIo5zZxbmu4fC-ZMrsKD0T0vq7IqkOOLYhrqRGypkx4,48
|
54
|
+
janito-1.4.1.dist-info/top_level.txt,sha256=m0NaVCq0-ivxbazE2-ND0EA9Hmuijj_OGkmCbnBcCig,7
|
55
|
+
janito-1.4.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|