janito 0.11.0__py3-none-any.whl → 0.13.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.
Files changed (50) hide show
  1. janito/__init__.py +1 -1
  2. janito/__main__.py +6 -204
  3. janito/callbacks.py +34 -132
  4. janito/cli/__init__.py +6 -0
  5. janito/cli/agent.py +400 -0
  6. janito/cli/app.py +94 -0
  7. janito/cli/commands.py +329 -0
  8. janito/cli/output.py +29 -0
  9. janito/cli/utils.py +22 -0
  10. janito/config.py +358 -121
  11. janito/data/instructions_template.txt +28 -0
  12. janito/token_report.py +154 -145
  13. janito/tools/__init__.py +38 -21
  14. janito/tools/bash/bash.py +84 -0
  15. janito/tools/bash/unix_persistent_bash.py +184 -0
  16. janito/tools/bash/win_persistent_bash.py +308 -0
  17. janito/tools/decorators.py +2 -13
  18. janito/tools/delete_file.py +27 -9
  19. janito/tools/fetch_webpage/__init__.py +34 -0
  20. janito/tools/fetch_webpage/chunking.py +76 -0
  21. janito/tools/fetch_webpage/core.py +155 -0
  22. janito/tools/fetch_webpage/extractors.py +276 -0
  23. janito/tools/fetch_webpage/news.py +137 -0
  24. janito/tools/fetch_webpage/utils.py +108 -0
  25. janito/tools/find_files.py +106 -44
  26. janito/tools/move_file.py +72 -0
  27. janito/tools/prompt_user.py +37 -6
  28. janito/tools/replace_file.py +31 -4
  29. janito/tools/rich_console.py +176 -0
  30. janito/tools/search_text.py +35 -22
  31. janito/tools/str_replace_editor/editor.py +7 -4
  32. janito/tools/str_replace_editor/handlers/__init__.py +16 -0
  33. janito/tools/str_replace_editor/handlers/create.py +60 -0
  34. janito/tools/str_replace_editor/handlers/insert.py +100 -0
  35. janito/tools/str_replace_editor/handlers/str_replace.py +94 -0
  36. janito/tools/str_replace_editor/handlers/undo.py +64 -0
  37. janito/tools/str_replace_editor/handlers/view.py +159 -0
  38. janito/tools/str_replace_editor/utils.py +0 -1
  39. janito/tools/usage_tracker.py +136 -0
  40. janito-0.13.0.dist-info/METADATA +300 -0
  41. janito-0.13.0.dist-info/RECORD +47 -0
  42. janito/chat_history.py +0 -117
  43. janito/data/instructions.txt +0 -4
  44. janito/tools/bash.py +0 -22
  45. janito/tools/str_replace_editor/handlers.py +0 -335
  46. janito-0.11.0.dist-info/METADATA +0 -86
  47. janito-0.11.0.dist-info/RECORD +0 -26
  48. {janito-0.11.0.dist-info → janito-0.13.0.dist-info}/WHEEL +0 -0
  49. {janito-0.11.0.dist-info → janito-0.13.0.dist-info}/entry_points.txt +0 -0
  50. {janito-0.11.0.dist-info → janito-0.13.0.dist-info}/licenses/LICENSE +0 -0
janito/__init__.py CHANGED
@@ -2,4 +2,4 @@
2
2
  Janito package.
3
3
  """
4
4
 
5
- __version__ = "0.11.0"
5
+ __version__ = "0.13.0"
janito/__main__.py CHANGED
@@ -1,205 +1,7 @@
1
- """
2
- Main entry point for Janito.
3
- """
4
- import os
5
- import sys
6
- from typing import Optional
7
- import importlib.resources
8
- import typer
9
- from rich.console import Console
10
- import anthropic
11
- from janito.config import get_config
12
- from janito.chat_history import store_conversation, get_chat_history_context
13
- from janito.callbacks import pre_tool_callback, post_tool_callback, text_callback
14
- from janito.token_report import generate_token_report
15
- from janito.tools import str_replace_editor
16
- from janito.tools.bash import bash_tool
17
- import claudine
18
-
19
- app = typer.Typer()
20
-
21
- @app.command()
22
- def create_tool(name: str = typer.Argument(..., help="Name of the tool to create")):
23
- """
24
- Create a new tool with the given name.
25
- """
26
- console = Console()
27
-
28
- # Ensure workspace is set
29
- workspace_dir = get_config().workspace_dir
30
-
31
- # Create the tools directory if it doesn't exist
32
- tools_dir = os.path.join(workspace_dir, "tools")
33
- os.makedirs(tools_dir, exist_ok=True)
34
-
35
- # Create the tool file
36
- tool_file = os.path.join(tools_dir, f"{name}.py")
37
-
38
- # Check if the file already exists
39
- if os.path.exists(tool_file):
40
- console.print(f"[bold red]Error:[/bold red] Tool file already exists: {tool_file}")
41
- return
42
-
43
- # Create the tool file with a template
44
- template = f'''"""
45
- {name} tool for Janito.
46
- """
47
-
48
- def {name}(param1: str) -> str:
49
- """
50
- Description of the {name} tool.
51
-
52
- Args:
53
- param1: Description of param1
54
-
55
- Returns:
56
- str: Description of return value
57
- """
58
- # TODO: Implement the tool
59
- return f"Executed {name} with param1={{param1}}"
60
- '''
61
-
62
- with open(tool_file, "w") as f:
63
- f.write(template)
64
-
65
- console.print(f"[bold green]Created tool:[/bold green] {tool_file}")
66
-
67
- @app.callback(invoke_without_command=True)
68
- def main(ctx: typer.Context,
69
- query: Optional[str] = typer.Argument(None, help="Query to send to the claudine agent"),
70
- verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable verbose mode with detailed output"),
71
- show_tokens: bool = typer.Option(False, "--show-tokens", "-t", help="Show detailed token usage and pricing information"),
72
- workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Set the workspace directory"),
73
- config_str: Optional[str] = typer.Option(None, "--set-config", help="Configuration string in format 'key=value', e.g., 'context=5' for number of history messages to include"),
74
- show_config: bool = typer.Option(False, "--show-config", help="Show current configuration")):
75
- """
76
- Janito CLI tool. If a query is provided without a command, it will be sent to the claudine agent.
77
- """
78
- console = Console()
79
-
80
- # Set verbose mode in config
81
- get_config().verbose = verbose
82
-
83
- if workspace:
84
- try:
85
- print(f"Setting workspace directory to: {workspace}")
86
- get_config().workspace_dir = workspace
87
- print(f"Workspace directory set to: {get_config().workspace_dir}")
88
- except ValueError as e:
89
- console.print(f"[bold red]Error:[/bold red] {str(e)}")
90
- sys.exit(1)
91
-
92
- # Show current configuration if requested
93
- if show_config:
94
- config = get_config()
95
- console.print("[bold blue]Current Configuration:[/bold blue]")
96
- console.print(f"[bold]Workspace Directory:[/bold] {config.workspace_dir}")
97
- console.print(f"[bold]Verbose Mode:[/bold] {'Enabled' if config.verbose else 'Disabled'}")
98
- console.print(f"[bold]Chat History Context Count:[/bold] {config.history_context_count} messages")
99
- # Exit if this was the only operation requested
100
- if ctx.invoked_subcommand is None and not query:
101
- sys.exit(0)
102
-
103
- # Handle the --set-config parameter
104
- if config_str is not None:
105
- try:
106
- # Parse the config string
107
- if "context=" in config_str:
108
- context_value = config_str.split("context=")[1].strip()
109
- # If there are other configs after context, extract just the number
110
- if " " in context_value:
111
- context_value = context_value.split(" ")[0]
112
-
113
- try:
114
- context_value = int(context_value)
115
- if context_value < 0:
116
- console.print("[bold red]Error:[/bold red] History context count must be a non-negative integer")
117
- return
118
-
119
- get_config().history_context_count = context_value
120
- console.print(f"[bold green]Chat history context count set to {context_value} messages[/bold green]")
121
- except ValueError:
122
- console.print(f"[bold red]Error:[/bold red] Invalid context value: {context_value}. Must be an integer.")
123
- else:
124
- console.print(f"[bold yellow]Warning:[/bold yellow] Unsupported configuration in: {config_str}")
125
- except Exception as e:
126
- console.print(f"[bold red]Error:[/bold red] {str(e)}")
127
-
128
- if ctx.invoked_subcommand is None:
129
- # If no query provided in command line, read from stdin
130
- if not query:
131
- console.print("[bold blue]No query provided in command line. Reading from stdin...[/bold blue]")
132
- query = sys.stdin.read().strip()
133
-
134
- # Only proceed if we have a query (either from command line or stdin)
135
- if query:
136
- # Get API key from environment variable or ask the user
137
- api_key = os.environ.get("ANTHROPIC_API_KEY")
138
- if not api_key:
139
- console.print("[bold yellow]Warning:[/bold yellow] ANTHROPIC_API_KEY environment variable not set.")
140
- console.print("Please set it or provide your API key now:")
141
- api_key = typer.prompt("Anthropic API Key", hide_input=True)
142
-
143
- # Load instructions from file
144
- import importlib.resources as pkg_resources
145
- try:
146
- # For Python 3.9+
147
- try:
148
- from importlib.resources import files
149
- instructions = files('janito.data').joinpath('instructions.txt').read_text(encoding='utf-8')
150
- # Fallback for older Python versions
151
- except (ImportError, AttributeError):
152
- instructions = pkg_resources.read_text('janito.data', 'instructions.txt', encoding='utf-8')
153
- except Exception as e:
154
- console.print(f"[bold red]Error loading instructions:[/bold red] {str(e)}")
155
- instructions = "You are Janito, an AI assistant."
156
-
157
- # Temporarily disable chat history
158
- # Get chat history context
159
- # chat_history = get_chat_history_context(get_config().history_context_count)
160
- # if chat_history:
161
- # console.print("[dim]Loaded chat history from previous sessions.[/dim]")
162
- # # Append chat history to instructions
163
- # instructions = f"{instructions}\n\n{chat_history}"
164
-
165
- # Get tools
166
- from janito.tools import get_tools
167
- tools_list = get_tools()
168
-
169
- # Initialize the agent with the tools
170
- agent = claudine.Agent(
171
- api_key=api_key,
172
- system_prompt=instructions,
173
- callbacks={"pre_tool": pre_tool_callback, "post_tool": post_tool_callback, "text": text_callback},
174
- text_editor_tool=str_replace_editor,
175
- #bash_tool=bash_tool,
176
- tools=tools_list,
177
- verbose=verbose
178
- )
179
-
180
- # Send the query to the agent
181
- try:
182
- agent.query(query)
183
-
184
- # Temporarily disable storing conversation in chat history
185
- # Store the conversation in chat history
186
- # store_conversation(query, response, agent)
187
-
188
- # Print token usage report if show_tokens mode is enabled
189
- if show_tokens:
190
- generate_token_report(agent, verbose=True)
191
- else:
192
- # Show basic token usage
193
- generate_token_report(agent, verbose=False)
194
-
195
- except anthropic.APIError as e:
196
- console.print(f"[bold red]Anthropic API Error:[/bold red] {str(e)}")
197
-
198
- except Exception as e:
199
- console.print(f"[bold red]Error:[/bold red] {str(e)}")
200
- if verbose:
201
- import traceback
202
- console.print(traceback.format_exc())
203
-
204
- if __name__ == "__main__":
1
+ """
2
+ Main entry point for Janito.
3
+ """
4
+ from janito.cli import app
5
+
6
+ if __name__ == "__main__":
205
7
  app()
janito/callbacks.py CHANGED
@@ -1,132 +1,34 @@
1
- """
2
- Callback functions for tool execution in janito.
3
- """
4
-
5
- from typing import Dict, Any, Tuple, Optional, List
6
- from rich.console import Console
7
- from rich.markdown import Markdown
8
-
9
- from janito.config import get_config
10
- from janito.tools import find_files
11
- from janito.tools.str_replace_editor.editor import str_replace_editor
12
- from janito.tools.delete_file import delete_file
13
- from janito.tools.search_text import search_text
14
- from janito.tools.decorators import format_tool_label
15
-
16
- # Note: ConsoleCallback has been removed as we're using pre_tool and post_tool callbacks directly
17
-
18
- def pre_tool_callback(tool_name: str, tool_input: Dict[str, Any]) -> Tuple[Dict[str, Any], bool]:
19
- """
20
- Callback function that runs before a tool is executed.
21
-
22
- Args:
23
- tool_name: Name of the tool being called
24
- tool_input: Input parameters for the tool
25
-
26
- Returns:
27
- Tuple of (modified tool input, whether to cancel the tool call)
28
- """
29
- console = Console()
30
-
31
- # Add debug counter only when verbose mode is enabled
32
- if get_config().verbose:
33
- if not hasattr(pre_tool_callback, "counter"):
34
- pre_tool_callback.counter = 1
35
- console.print(f"[bold green]DEBUG: Starting tool call #{pre_tool_callback.counter}[/bold green]")
36
-
37
- # Print the tool name and input
38
- console.print(f"[bold green]Tool:[/bold green] {tool_name}")
39
- console.print(f"[bold green]Input:[/bold green] {tool_input}")
40
- else:
41
- # For non-debug mode, just print a simple message
42
- # Find the tool function
43
- tool_func = None
44
- if tool_name == "find_files":
45
- tool_func = find_files
46
- elif tool_name == "str_replace_editor":
47
- tool_func = str_replace_editor
48
- elif tool_name == "delete_file":
49
- tool_func = delete_file
50
- elif tool_name == "search_text":
51
- tool_func = search_text
52
-
53
- # Format the input for display
54
- display_input = ""
55
- if "path" in tool_input:
56
- display_input = tool_input["path"]
57
- elif "file_path" in tool_input:
58
- display_input = tool_input["file_path"]
59
-
60
- # Print formatted tool label if available
61
- formatted_label = format_tool_label(tool_func, tool_input)
62
- if formatted_label:
63
- console.print("[bold cyan] Tool:[/bold cyan]", formatted_label, end=" → ")
64
- else:
65
- console.print("[bold cyan] Tool:[/bold cyan]", f"{tool_name} {display_input}", end=" → ")
66
-
67
- return tool_input, True # Continue with the tool call
68
-
69
- def post_tool_callback(tool_name: str, tool_input: Dict[str, Any], result: Any) -> Any:
70
- """
71
- Callback function that runs after a tool is executed.
72
-
73
- Args:
74
- tool_name: Name of the tool that was called
75
- tool_input: Input parameters for the tool
76
- result: Result of the tool call
77
-
78
- Returns:
79
- Modified result
80
- """
81
- console = Console()
82
-
83
- # Add debug counter only when verbose mode is enabled
84
- if get_config().verbose:
85
- if not hasattr(post_tool_callback, "counter"):
86
- post_tool_callback.counter = 1
87
- console.print(f"[bold green]DEBUG: Completed tool call #{post_tool_callback.counter}[/bold green]")
88
- post_tool_callback.counter += 1
89
-
90
- # Show the number of lines in the result content
91
- if isinstance(result, tuple) and len(result) >= 1:
92
- content, is_error = result
93
- # Define prefix icon based on is_error
94
- icon_prefix = "❌ " if is_error else "✅ "
95
-
96
- if isinstance(content, str):
97
- # Count the number of lines in the content
98
- line_count = content.count('\n') + 1 if content else 0
99
- console.print(f"{icon_prefix}{line_count} items")
100
- else:
101
- console.print(f"{icon_prefix}{content}")
102
- else:
103
- # If result is not a tuple, convert to string and count lines
104
- result_str = str(result)
105
- # Default to success icon when no error status is available
106
- icon_prefix = "✅ "
107
- line_count = result_str.count('\n') + 1 if result_str else 0
108
- console.print(f"{icon_prefix}{line_count} lines")
109
-
110
- return result
111
-
112
- def text_callback(text: str) -> None:
113
- """
114
- Callback function that handles text output from the agent.
115
-
116
- Args:
117
- text: Text output from the agent
118
-
119
- Returns:
120
- None
121
- """
122
- console = Console()
123
-
124
- # Add debug counter only when debug mode is enabled
125
- if get_config().debug_mode:
126
- if not hasattr(text_callback, "counter"):
127
- text_callback.counter = 1
128
- console.print(f"[bold blue]DEBUG: Text callback #{text_callback.counter}[/bold blue]")
129
- text_callback.counter += 1
130
-
131
- # Print the text with markdown formatting
132
- console.print("[bold magenta]Janito:[/bold magenta] ", Markdown(text, code_theme="monokai"), end="")
1
+ """
2
+ Callback functions for tool execution in janito.
3
+ """
4
+
5
+ from rich.console import Console
6
+ from rich.markdown import Markdown
7
+
8
+ from janito.config import get_config
9
+
10
+ # Counter for pre-tool callbacks
11
+ pre_tool_callbacks = 0
12
+
13
+ def text_callback(text: str) -> None:
14
+ """
15
+ Callback function that handles text output from the agent.
16
+
17
+ Args:
18
+ text: Text output from the agent
19
+
20
+ Returns:
21
+ None
22
+ """
23
+ console = Console()
24
+
25
+ # Add debug counter only when debug mode is enabled
26
+ if get_config().debug_mode:
27
+ if not hasattr(text_callback, "counter"):
28
+ text_callback.counter = 1
29
+ console.print(f"[bold blue]DEBUG: Text callback #{text_callback.counter}[/bold blue]")
30
+ text_callback.counter += 1
31
+
32
+ # Print the text with markdown formatting
33
+ console.print(Markdown(text, code_theme="monokai"), end="")
34
+
janito/cli/__init__.py ADDED
@@ -0,0 +1,6 @@
1
+ """
2
+ CLI module for Janito.
3
+ """
4
+ from janito.cli.app import app
5
+
6
+ __all__ = ["app"]