janito 1.3.2__py3-none-any.whl → 1.4.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.
@@ -1,134 +1,80 @@
1
+ from janito.agent.tools.tool_base import ToolBase
1
2
  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
3
  import subprocess
5
- import multiprocessing
6
- from typing import Optional
4
+
5
+ from janito.agent.tools.rich_utils import print_info, print_success, print_error
7
6
 
8
7
  import tempfile
9
8
  import os
9
+ import sys
10
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)
11
+ class RunBashCommandTool(ToolBase):
56
12
  """
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.
13
+ Execute a non-interactive bash command and capture live output.
60
14
 
61
15
  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.
16
+ command (str): The bash command to execute.
17
+ timeout (int, optional): Timeout in seconds for the command. Defaults to 60.
18
+ require_confirmation (bool, optional): If True, require user confirmation before running. Defaults to False.
19
+ interactive (bool, optional): If True, warns that the command may require user interaction. Defaults to False. Non-interactive commands are preferred for automation and reliability.
64
20
 
65
21
  Returns:
66
- str: A formatted message string containing stdout, stderr, and return code.
22
+ str: File paths and line counts for stdout and stderr.
67
23
  """
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
24
+ def call(self, command: str, timeout: int = 60, require_confirmation: bool = False, interactive: bool = False) -> str:
25
+ print_info(f"🖥️ Running bash command: {command}")
26
+ if interactive:
27
+ print_info("⚠️ Warning: This command might be interactive, require user input, and might hang.")
28
+ print()
29
+ sys.stdout.flush()
30
+ self.update_progress(f"Running bash command: {command}")
96
31
  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
- )
32
+ with tempfile.NamedTemporaryFile(mode='w+', prefix='run_bash_stdout_', delete=False, encoding='utf-8') as stdout_file, \
33
+ tempfile.NamedTemporaryFile(mode='w+', prefix='run_bash_stderr_', delete=False, encoding='utf-8') as stderr_file:
34
+ process = subprocess.Popen(
35
+ command, shell=True,
36
+ stdout=stdout_file,
37
+ stderr=stderr_file,
38
+ text=True
39
+ )
40
+ try:
41
+ return_code = process.wait(timeout=timeout)
42
+ except subprocess.TimeoutExpired:
43
+ process.kill()
44
+ print_error(f" Timed out after {timeout} seconds.")
45
+ return f"Command timed out after {timeout} seconds."
46
+
47
+ # Print live output to user
48
+ stdout_file.flush()
49
+ stderr_file.flush()
50
+ with open(stdout_file.name, 'r', encoding='utf-8') as out_f:
51
+ out_f.seek(0)
52
+ for line in out_f:
53
+ print(line, end='')
54
+ with open(stderr_file.name, 'r', encoding='utf-8') as err_f:
55
+ err_f.seek(0)
56
+ for line in err_f:
57
+ print(line, end='', file=sys.stderr)
58
+
59
+ # Count lines
60
+ with open(stdout_file.name, 'r', encoding='utf-8') as out_f:
61
+ stdout_lines = sum(1 for _ in out_f)
62
+ with open(stderr_file.name, 'r', encoding='utf-8') as err_f:
63
+ stderr_lines = sum(1 for _ in err_f)
64
+
65
+ print_success(f" return code {return_code}")
66
+ warning_msg = ""
67
+ if interactive:
68
+ warning_msg = "⚠️ Warning: This command might be interactive, require user input, and might hang.\n"
69
+ return (
70
+ warning_msg +
71
+ f"stdout_file: {stdout_file.name} (lines: {stdout_lines})\n"
72
+ f"stderr_file: {stderr_file.name} (lines: {stderr_lines})\n"
73
+ f"returncode: {return_code}\n"
74
+ f"Use the get_lines tool to inspect the contents of these files when needed."
75
+ )
76
+ except Exception as e:
77
+ print_error(f" ❌ Error: {e}")
78
+ return f"Error running command: {e}"
134
79
 
80
+ ToolHandler.register_tool(RunBashCommandTool, name="run_bash_command")
@@ -1,52 +1,26 @@
1
- import os
2
- import re
3
- import fnmatch
1
+ from janito.agent.tools.tool_base import ToolBase
4
2
  from janito.agent.tool_handler import ToolHandler
5
- from janito.agent.tools.rich_utils import print_info, print_success, print_error, format_path, format_number
6
- from janito.agent.tools.gitignore_utils import load_gitignore_patterns, filter_ignored
7
-
8
- @ToolHandler.register_tool
9
- def search_files(
10
- directory: str,
11
- pattern: str
12
- ) -> str:
13
- """
14
- Search for a text pattern in all files within a directory and return matching lines and their content.
3
+ import os
15
4
 
16
- Args:
17
- directory (str): The directory to search in.
18
- pattern (str): The text pattern to search for.
19
- Returns:
20
- str: Each match as 'filepath:lineno:linecontent', one per line.
21
- """
22
- print_info(f"🔎 search_files | Path: {directory} | pattern: '{pattern}'")
23
- results = []
24
- ignore_patterns = load_gitignore_patterns()
25
- try:
26
- regex = re.compile(pattern, re.IGNORECASE)
27
- except re.error:
28
- regex = None
5
+ from janito.agent.tools.rich_utils import print_info, print_success
29
6
 
30
- files_to_search = []
31
- if os.path.isfile(directory):
32
- files_to_search = [directory]
33
- else:
7
+ class SearchFilesTool(ToolBase):
8
+ """Search for a text pattern in all files within a directory and return matching lines."""
9
+ def call(self, directory: str, pattern: str) -> str:
10
+ print_info(f"🔎 Searching for pattern '{pattern}' in directory {directory}")
11
+ self.update_progress(f"Searching for pattern '{pattern}' in directory {directory}")
12
+ matches = []
34
13
  for root, dirs, files in os.walk(directory):
35
- dirs, files = filter_ignored(root, dirs, files, ignore_patterns)
36
- for file in files:
37
- filepath = os.path.join(root, file)
38
- files_to_search.append(filepath)
39
-
40
- for filepath in files_to_search:
41
- with open(filepath, 'r', encoding='utf-8', errors='replace') as f:
42
- for lineno, line in enumerate(f, start=1):
43
- if regex:
44
- if regex.search(line):
45
- results.append(f"{filepath}:{lineno}:{line.rstrip()}")
46
- else:
47
- if pattern.lower() in line.lower():
48
- results.append(f"{filepath}:{lineno}:{line.rstrip()}")
49
-
50
- print_success(f"✅ Found {format_number(len(results))} matches")
51
- return "\n".join(results)
14
+ for filename in files:
15
+ path = os.path.join(root, filename)
16
+ try:
17
+ with open(path, 'r', encoding='utf-8', errors='ignore') as f:
18
+ for lineno, line in enumerate(f, 1):
19
+ if pattern in line:
20
+ matches.append(f"{path}:{lineno}: {line.strip()}")
21
+ except Exception:
22
+ continue
23
+ print_success(f"\u2705 {len(matches)} matches found")
24
+ return '\n'.join(matches)
52
25
 
26
+ ToolHandler.register_tool(SearchFilesTool, name="search_files")
@@ -6,6 +6,7 @@ class ToolBase(ABC):
6
6
  """
7
7
  def __init__(self):
8
8
  self.progress_messages = []
9
+ self._progress_callback = None # Will be set by ToolHandler if available
9
10
 
10
11
  @abstractmethod
11
12
  def call(self, **kwargs):
@@ -14,9 +15,10 @@ class ToolBase(ABC):
14
15
  """
15
16
  pass
16
17
 
17
- def on_progress(self, message: str):
18
+ def update_progress(self, message: str):
18
19
  """
19
20
  Report progress. Subclasses can override this to customize progress reporting.
20
21
  """
21
22
  self.progress_messages.append(message)
22
- print(f"[Tool Progress] {message}")
23
+ if hasattr(self, '_progress_callback') and self._progress_callback:
24
+ self._progress_callback({'event': 'progress', 'message': message})
@@ -0,0 +1,31 @@
1
+ import os
2
+ import sys
3
+
4
+
5
+ def expand_path(path: str) -> str:
6
+ """
7
+ If ~ is present in the path, expands it to the user's home directory.
8
+ Otherwise, returns the path unchanged.
9
+ """
10
+ if "~" in path:
11
+ return os.path.expanduser(path)
12
+ return path
13
+
14
+
15
+ def display_path(original_path: str, expanded_path: str) -> str:
16
+ """
17
+ Returns a user-friendly path for display:
18
+ - If the original path is relative, return it as-is.
19
+ - If the original path starts with ~, keep it as ~.
20
+ - Otherwise, if the expanded path is under the home directory, replace the home dir with ~.
21
+ - Else, show the expanded path.
22
+ """
23
+ # Detect relative path (POSIX or Windows)
24
+ if not (original_path.startswith("/") or original_path.startswith("~") or (os.name == "nt" and len(original_path) > 1 and original_path[1] == ":")):
25
+ return original_path
26
+ home = os.path.expanduser("~")
27
+ if original_path.startswith("~"):
28
+ return original_path
29
+ if expanded_path.startswith(home):
30
+ return "~" + expanded_path[len(home):]
31
+ return expanded_path
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: janito
3
- Version: 1.3.2
3
+ Version: 1.4.0
4
4
  Summary: A Natural Programming Language Agent,
5
5
  Author-email: João Pinto <joao.pinto@gmail.com>
6
6
  License: MIT
@@ -23,7 +23,7 @@ Requires-Dist: requests
23
23
  Requires-Dist: rich
24
24
  Dynamic: license-file
25
25
 
26
- # 🚀 Janito: Agent
26
+ # 🚀 Janito: Natural Programming Language Agent
27
27
 
28
28
  Janito is an AI-powered assistant for the command line and web that interprets natural language instructions to edit code, manage files, and analyze projects using patterns and tools designed by experienced software engineers. It prioritizes transparency, interactive clarification, and precise, reviewable changes.
29
29
 
@@ -60,7 +60,7 @@ python -m janito.web
60
60
  - `replace_text_in_file`: Replace exact text fragments in files.
61
61
  - `search_files`: Search for text patterns across files.
62
62
  - `python_exec`: Execute Python code and capture output.
63
- - And more, see `janito/agent/tools/` for the full list.
63
+ - And more built-in operations for code and file management.
64
64
  - 🌐 **Web Interface (In Development):** Upcoming simple web UI for streaming responses and tool progress.
65
65
 
66
66
  ---
@@ -79,9 +79,9 @@ Below are the supported configuration parameters and CLI flags. Some options can
79
79
 
80
80
  | Key / Flag | Description | How to set | Default |
81
81
  |---------------------------|---------------------------------------------------------------------------------------------|-----------------------------------------------------------------|--------------------------------------------|
82
- | `api_key` | API key for OpenAI-compatible service | `--set-api-key`, config file | _None_ (required) |
83
- | `model` | Model name to use for this session | `--model` (session only), `--set-local-config model=...`, or `--set-global-config` | `openai/gpt-4.1` |
84
- | `base_url` | API base URL (OpenAI-compatible endpoint) | `--set-local-config base_url=...` or `--set-global-config` | `https://openrouter.ai/api/v1` |
82
+ | `api_key` | API key for a compatible language model service | `--set-api-key`, config file | _None_ (required) |
83
+ | `model` | Model name to use for this session | `--model` (session only), `--set-local-config model=...`, or `--set-global-config` | _(example: gpt-4)_ |
84
+ | `base_url` | API base URL for your language model service | `--set-local-config base_url=...` or `--set-global-config` | _(example: https://api.your-model.com)_ |
85
85
  | `role` | Role description for the system prompt | `--role` or config | "software engineer" |
86
86
  | `system_prompt` | Override the entire system prompt as a raw string | `--system-prompt` or config | _Default prompt_ |
87
87
  | `system_file` | Use a plain text file as the system prompt (takes precedence over `system_prompt`) | `--system-file` (CLI only) | _None_ |
@@ -1,4 +1,4 @@
1
- janito/__init__.py,sha256=uCv73rgSEXLv0WZ2fvJpwCpBCFcxOh94XqSDccIBrL8,23
1
+ janito/__init__.py,sha256=-pa9pj_zJgPDZtE3ena4mjuVS3FEWQWYij1shjLYS80,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
@@ -9,24 +9,26 @@ janito/agent/config_utils.py,sha256=UmvR236wDrMc-aTy9LxVbop6YeoJaaPb1d2DBMlkSRg,
9
9
  janito/agent/conversation.py,sha256=vbCL-1LlJjKRN6q3CjfSe4ENGplP-YQKsAEA1uX3RWU,6184
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
- janito/agent/tool_handler.py,sha256=sKnySRfZQBUjZxve8CH74me9Q4_ewtIege_HBiCs9wY,8291
13
- janito/agent/templates/system_instructions.j2,sha256=3lZShjpzg-PBx27TmtmJijR6gedmNZtdXIwCVgYILzw,1704
14
- janito/agent/tools/__init__.py,sha256=j0MGKIrtEkI3f6yumsJeDqiPyvDMehZ_3e2Osujev3c,486
15
- janito/agent/tools/ask_user.py,sha256=-omTj2woHGbl4xR14sB3dbnRD1zGIbvKv4wjq9g4NXE,1917
16
- janito/agent/tools/fetch_url.py,sha256=tce4L5LDiIsSreo-aJVmpwu1yCkDCY0kEZId3lgGiCU,1578
17
- janito/agent/tools/file_ops.py,sha256=RBnKKvRagEu3rIeNYrpgbaxDts7D_B1ivjJrpSQ2QzA,3243
18
- janito/agent/tools/find_files.py,sha256=OxJghgmPvk3RFF5N_6CCW_ftB6RgG3QzeBzc1bItLKA,2353
19
- janito/agent/tools/get_lines.py,sha256=eazwPkwB_P9VkHN-ubOZK5lK5qOJGU0QXVOb6RwQl3g,2948
20
- janito/agent/tools/gitignore_utils.py,sha256=zXiqx4HetZ7iKkV5qXyHyZ5yrrVex4G17WHBWToFo3Y,1158
21
- janito/agent/tools/py_compile.py,sha256=bQ6P0Vr8FBZQ_hqNjIEylJIzeiH2aggRjNW_WCgG7sA,1042
22
- janito/agent/tools/python_exec.py,sha256=C4qG6Um9RsnpHqii1Z3mVFp3qXnaL87Ns0mJSeBgOJc,1769
23
- janito/agent/tools/remove_directory.py,sha256=CUzXaotktgpyX6LUsfK_-m91Onkwk9wbdAZcUayt2jw,1727
24
- janito/agent/tools/replace_text_in_file.py,sha256=2uOZJW2SzZPFp7_wcU8Hw38pKWDWkmq_24mxiUrRWDo,3533
12
+ janito/agent/tool_handler.py,sha256=h-pxG1lhyIJohZmvwHSsknBSonrJQYGGzBL6Tobgmrg,7414
13
+ janito/agent/templates/system_instructions.j2,sha256=BtwMcibxnwZmQhGN7p_VGhhyAPzCfqksnW4B-PTWa-8,1532
14
+ janito/agent/tools/__init__.py,sha256=Vv1oWF6Ur-Tkm3p0KCz5HD7wwar9rUHtY596NGPnn2s,378
15
+ janito/agent/tools/ask_user.py,sha256=C1YC_gr0kh3-7vw2PgdIi4D8Paw-eNGpaWQy4HD3Gmo,2180
16
+ janito/agent/tools/fetch_url.py,sha256=XUHEex1An1Ql4p8H1UKWzaIxo9a6WkZC4uRPkhBQHeU,1418
17
+ janito/agent/tools/file_ops.py,sha256=5FnggSPv-Tsgq038T1YK5bpJZE5kPY_biB5fXZg48X0,5476
18
+ janito/agent/tools/find_files.py,sha256=jq55uUSfAUJ2gmJ29YQmo8XZ92cptb2C5hpc_pjbrQg,1364
19
+ janito/agent/tools/get_file_outline.py,sha256=aLNNWMalvE-3CXLEuBVe4ihDMciP4grbsol6Yw01O44,959
20
+ janito/agent/tools/get_lines.py,sha256=0Yg6JFPAOCJuR7HYcFIGwn83BCv_SnuWp0T7v4RtT9Q,1555
21
+ janito/agent/tools/gitignore_utils.py,sha256=z_IYilabTD_-c14aRxuVasojOzTsg-11xJPJqudWIKA,1306
22
+ janito/agent/tools/py_compile.py,sha256=y8f48WaHpsPFCt1Ksi-JEVbFxWvZU-lQzCHsR796pWg,1099
23
+ janito/agent/tools/python_exec.py,sha256=TPU1LvRNNJMpsyhy1kD8pe2go5V2fheD93HBjKrXrFM,2188
24
+ janito/agent/tools/remove_directory.py,sha256=xcyGyF5vC_AU7dzIVNa65aYUYuF5mBjGZ2MwnLsLafs,1076
25
+ janito/agent/tools/replace_text_in_file.py,sha256=eO7YumsT8Eq3_SOgl5DW_k9vhXO7egyMaiB6ZgtiHRU,3894
25
26
  janito/agent/tools/rich_live.py,sha256=cuZ3-ZxpuHxR1TvIcp0bi9F3QM1M6Ms0XiOMd8If8gU,1161
26
- janito/agent/tools/rich_utils.py,sha256=aQMqeaq3hIpzZ5EHQBNTKS5dNsojQp9MDfJSoqOQe0k,837
27
- janito/agent/tools/run_bash_command.py,sha256=qY8h6b4ru9J7u7Ve6oYOqwqYXH14J4BUACriCsCZKK0,6154
28
- janito/agent/tools/search_files.py,sha256=HbLq9oHcb9udrbql6-QE53zo5F3UeuhlptMvf2mIQVo,1945
29
- janito/agent/tools/tool_base.py,sha256=Q1wcJdDiLRVldtqVYCiRTGFyVv1Xz4rboHnJAKIJsrs,637
27
+ janito/agent/tools/rich_utils.py,sha256=Lc4phM4DUG-eiiub2PFThc6pBk5aOo_6f09JPdZIdsk,894
28
+ janito/agent/tools/run_bash_command.py,sha256=rKAx_n6xxpHeBzDg_7BVkAjMgPGiXVLpjx6i2o1lMb0,3883
29
+ janito/agent/tools/search_files.py,sha256=ejHDp_I-GGQPucAKcXLgVO3LFPiOXNS77tEHME9QsvQ,1250
30
+ janito/agent/tools/tool_base.py,sha256=nS2FXSw3YY6gJiKh-l1m1udnHT7F3yKwGpGHJHfERbY,836
31
+ janito/agent/tools/utils.py,sha256=cKZ2qxK-S01mzBmCXYWwQ9zOyT994SaoRZYbD1o57Dk,1113
30
32
  janito/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
33
  janito/cli/_print_config.py,sha256=vMMlCY-hJPsLHUxx9TJuOY9iyYVBH8C4nVACCwY4l5U,3294
32
34
  janito/cli/_utils.py,sha256=Q_OCFZmbr78qW4hSSUUhjondVc0ao7-iUHE7Ig8IP1g,289
@@ -45,9 +47,9 @@ janito/cli_chat_shell/ui.py,sha256=9IngH8HFherjatfa9Eu37jb4b2gOP0lsgcUhbnQKCZA,5
45
47
  janito/web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
48
  janito/web/__main__.py,sha256=oPXNF332aCeI7aUWr7_8M57oOKugw422VrEubxFp0P4,354
47
49
  janito/web/app.py,sha256=stogs_HaM-axsWTwoiVma9M46Y8dMu0QRjopsekRjQs,6622
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,,
50
+ janito-1.4.0.dist-info/licenses/LICENSE,sha256=sHBqv0bvtrb29H7WRR-Z603YHm9pLtJIo3nHU_9cmgE,1091
51
+ janito-1.4.0.dist-info/METADATA,sha256=_rNaRL-V53vjwrWJVJmgfz5XqRvekKr-Ju2bhi9G7FE,9114
52
+ janito-1.4.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
53
+ janito-1.4.0.dist-info/entry_points.txt,sha256=wIo5zZxbmu4fC-ZMrsKD0T0vq7IqkOOLYhrqRGypkx4,48
54
+ janito-1.4.0.dist-info/top_level.txt,sha256=m0NaVCq0-ivxbazE2-ND0EA9Hmuijj_OGkmCbnBcCig,7
55
+ janito-1.4.0.dist-info/RECORD,,
File without changes