janito 0.14.0__py3-none-any.whl → 1.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 +1 -5
- janito/__main__.py +3 -5
- janito/agent/__init__.py +1 -0
- janito/agent/agent.py +96 -0
- janito/agent/config.py +113 -0
- janito/agent/config_defaults.py +10 -0
- janito/agent/conversation.py +107 -0
- janito/agent/queued_tool_handler.py +16 -0
- janito/agent/runtime_config.py +30 -0
- janito/agent/tool_handler.py +124 -0
- janito/agent/tools/__init__.py +11 -0
- janito/agent/tools/ask_user.py +63 -0
- janito/agent/tools/bash_exec.py +58 -0
- janito/agent/tools/create_directory.py +19 -0
- janito/agent/tools/create_file.py +43 -0
- janito/agent/tools/fetch_url.py +48 -0
- janito/agent/tools/file_str_replace.py +48 -0
- janito/agent/tools/find_files.py +37 -0
- janito/agent/tools/gitignore_utils.py +40 -0
- janito/agent/tools/move_file.py +37 -0
- janito/agent/tools/remove_file.py +19 -0
- janito/agent/tools/rich_live.py +37 -0
- janito/agent/tools/rich_utils.py +31 -0
- janito/agent/tools/search_text.py +41 -0
- janito/agent/tools/view_file.py +34 -0
- janito/cli/__init__.py +0 -6
- janito/cli/_print_config.py +68 -0
- janito/cli/_utils.py +8 -0
- janito/cli/arg_parser.py +26 -0
- janito/cli/config_commands.py +131 -0
- janito/cli/logging_setup.py +27 -0
- janito/cli/main.py +39 -0
- janito/cli/runner.py +135 -0
- janito/cli_chat_shell/__init__.py +1 -0
- janito/cli_chat_shell/chat_loop.py +147 -0
- janito/cli_chat_shell/commands.py +202 -0
- janito/cli_chat_shell/config_shell.py +75 -0
- janito/cli_chat_shell/load_prompt.py +15 -0
- janito/cli_chat_shell/session_manager.py +60 -0
- janito/cli_chat_shell/ui.py +136 -0
- janito/render_prompt.py +12 -0
- janito/templates/system_instructions.j2 +36 -0
- janito/web/__init__.py +0 -0
- janito/web/__main__.py +17 -0
- janito/web/app.py +132 -0
- janito-1.0.0.dist-info/METADATA +144 -0
- janito-1.0.0.dist-info/RECORD +51 -0
- {janito-0.14.0.dist-info → janito-1.0.0.dist-info}/WHEEL +2 -1
- janito-1.0.0.dist-info/entry_points.txt +2 -0
- {janito-0.14.0.dist-info → janito-1.0.0.dist-info}/licenses/LICENSE +2 -2
- janito-1.0.0.dist-info/top_level.txt +1 -0
- janito/callbacks.py +0 -34
- janito/cli/agent/__init__.py +0 -7
- janito/cli/agent/conversation.py +0 -149
- janito/cli/agent/initialization.py +0 -172
- janito/cli/agent/query.py +0 -108
- janito/cli/agent.py +0 -12
- janito/cli/app.py +0 -182
- janito/cli/commands/__init__.py +0 -12
- janito/cli/commands/config.py +0 -242
- janito/cli/commands/history.py +0 -119
- janito/cli/commands/profile.py +0 -72
- janito/cli/commands/validation.py +0 -24
- janito/cli/commands/workspace.py +0 -31
- janito/cli/commands.py +0 -12
- janito/cli/output.py +0 -29
- janito/cli/utils.py +0 -22
- janito/config.py +0 -375
- janito/data/instructions_template.txt +0 -31
- janito/token_report.py +0 -154
- janito/tools/__init__.py +0 -44
- janito/tools/bash/bash.py +0 -84
- janito/tools/bash/unix_persistent_bash.py +0 -184
- janito/tools/bash/win_persistent_bash.py +0 -308
- janito/tools/decorators.py +0 -90
- janito/tools/delete_file.py +0 -65
- janito/tools/fetch_webpage/__init__.py +0 -23
- janito/tools/fetch_webpage/core.py +0 -182
- janito/tools/find_files.py +0 -220
- janito/tools/move_file.py +0 -72
- janito/tools/prompt_user.py +0 -57
- janito/tools/replace_file.py +0 -63
- janito/tools/rich_console.py +0 -176
- janito/tools/search_text.py +0 -226
- janito/tools/str_replace_editor/__init__.py +0 -6
- janito/tools/str_replace_editor/editor.py +0 -55
- janito/tools/str_replace_editor/handlers/__init__.py +0 -16
- janito/tools/str_replace_editor/handlers/create.py +0 -60
- janito/tools/str_replace_editor/handlers/insert.py +0 -100
- janito/tools/str_replace_editor/handlers/str_replace.py +0 -94
- janito/tools/str_replace_editor/handlers/undo.py +0 -64
- janito/tools/str_replace_editor/handlers/view.py +0 -159
- janito/tools/str_replace_editor/utils.py +0 -33
- janito/tools/think.py +0 -37
- janito/tools/usage_tracker.py +0 -137
- janito-0.14.0.dist-info/METADATA +0 -396
- janito-0.14.0.dist-info/RECORD +0 -53
- janito-0.14.0.dist-info/entry_points.txt +0 -2
janito/cli/commands.py
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Command handling logic for Janito CLI.
|
3
|
-
This module serves as a compatibility layer for the reorganized commands module.
|
4
|
-
"""
|
5
|
-
# Re-export the functions from the new module structure
|
6
|
-
from janito.cli.commands import handle_config_commands, validate_parameters, handle_history
|
7
|
-
|
8
|
-
__all__ = [
|
9
|
-
"handle_config_commands",
|
10
|
-
"validate_parameters",
|
11
|
-
"handle_history",
|
12
|
-
]
|
janito/cli/output.py
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Output formatting and display for Janito CLI.
|
3
|
-
"""
|
4
|
-
from rich.console import Console
|
5
|
-
from janito.config import get_config
|
6
|
-
|
7
|
-
console = Console()
|
8
|
-
|
9
|
-
def display_generation_params(
|
10
|
-
temp_to_use: float,
|
11
|
-
profile_data: dict = None,
|
12
|
-
temperature: float = 0.0
|
13
|
-
) -> None:
|
14
|
-
"""
|
15
|
-
Display generation parameters in verbose mode.
|
16
|
-
|
17
|
-
Args:
|
18
|
-
temp_to_use: The temperature value being used
|
19
|
-
profile_data: The profile data if a profile is being used
|
20
|
-
temperature: The temperature value from command line
|
21
|
-
"""
|
22
|
-
# Show profile information if one is active
|
23
|
-
config = get_config()
|
24
|
-
if config.profile:
|
25
|
-
if not profile_data:
|
26
|
-
profile_data = config.get_available_profiles()[config.profile]
|
27
|
-
console.print(f"[dim]👤 Using profile: {config.profile} - {profile_data['description']}[/dim]")
|
28
|
-
|
29
|
-
# Temperature, top_k, and top_p information is hidden
|
janito/cli/utils.py
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Utility functions for the CLI module.
|
3
|
-
"""
|
4
|
-
import platform
|
5
|
-
from rich.console import Console
|
6
|
-
|
7
|
-
console = Console()
|
8
|
-
|
9
|
-
def get_stdin_termination_hint():
|
10
|
-
"""
|
11
|
-
Returns a user-friendly message about how to terminate stdin input
|
12
|
-
based on the current platform.
|
13
|
-
|
14
|
-
Returns:
|
15
|
-
str: A message with the key sequence to terminate stdin input
|
16
|
-
"""
|
17
|
-
system = platform.system()
|
18
|
-
|
19
|
-
if system == "Windows":
|
20
|
-
return "[bold yellow]Press Ctrl+Z followed by Enter to terminate input[/bold yellow]"
|
21
|
-
else: # Unix-like systems (Linux, macOS)
|
22
|
-
return "[bold yellow]Press Ctrl+D to terminate input[/bold yellow]"
|
janito/config.py
DELETED
@@ -1,375 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Configuration module for Janito.
|
3
|
-
Provides a singleton Config class to access configuration values.
|
4
|
-
"""
|
5
|
-
import os
|
6
|
-
import json
|
7
|
-
from pathlib import Path
|
8
|
-
import typer
|
9
|
-
from typing import Dict, Any, Optional
|
10
|
-
|
11
|
-
# Predefined parameter profiles
|
12
|
-
PROFILES = {
|
13
|
-
"precise": {
|
14
|
-
"temperature": 0.2,
|
15
|
-
"top_p": 0.85,
|
16
|
-
"top_k": 20,
|
17
|
-
"description": "Factual answers, documentation, structured data, avoiding hallucinations"
|
18
|
-
},
|
19
|
-
"balanced": {
|
20
|
-
"temperature": 0.5,
|
21
|
-
"top_p": 0.9,
|
22
|
-
"top_k": 40,
|
23
|
-
"description": "Professional writing, summarization, everyday tasks with moderate creativity"
|
24
|
-
},
|
25
|
-
"conversational": {
|
26
|
-
"temperature": 0.7,
|
27
|
-
"top_p": 0.9,
|
28
|
-
"top_k": 45,
|
29
|
-
"description": "Natural dialogue, educational content, support conversations"
|
30
|
-
},
|
31
|
-
"creative": {
|
32
|
-
"temperature": 0.9,
|
33
|
-
"top_p": 0.95,
|
34
|
-
"top_k": 70,
|
35
|
-
"description": "Storytelling, brainstorming, marketing copy, poetry"
|
36
|
-
},
|
37
|
-
"technical": {
|
38
|
-
"temperature": 0.3,
|
39
|
-
"top_p": 0.95,
|
40
|
-
"top_k": 15,
|
41
|
-
"description": "Code generation, debugging, decision analysis, technical problem-solving"
|
42
|
-
}
|
43
|
-
}
|
44
|
-
|
45
|
-
class Config:
|
46
|
-
"""Singleton configuration class for Janito."""
|
47
|
-
_instance = None
|
48
|
-
|
49
|
-
def __new__(cls):
|
50
|
-
if cls._instance is None:
|
51
|
-
cls._instance = super(Config, cls).__new__(cls)
|
52
|
-
cls._instance._workspace_dir = os.getcwd()
|
53
|
-
cls._instance._verbose = False
|
54
|
-
# Chat history context feature has been removed
|
55
|
-
cls._instance._ask_mode = False
|
56
|
-
cls._instance._trust_mode = False # New trust mode setting
|
57
|
-
cls._instance._no_tools = False # New no-tools mode setting
|
58
|
-
# Set technical profile as default
|
59
|
-
profile_data = PROFILES["technical"]
|
60
|
-
cls._instance._temperature = profile_data["temperature"]
|
61
|
-
cls._instance._profile = "technical"
|
62
|
-
cls._instance._role = "software engineer"
|
63
|
-
cls._instance._gitbash_path = None # Default to None for auto-detection
|
64
|
-
cls._instance._load_config()
|
65
|
-
return cls._instance
|
66
|
-
|
67
|
-
def _load_config(self) -> None:
|
68
|
-
"""Load configuration from file."""
|
69
|
-
config_path = Path(self._workspace_dir) / ".janito" / "config.json"
|
70
|
-
if config_path.exists():
|
71
|
-
try:
|
72
|
-
with open(config_path, "r", encoding="utf-8") as f:
|
73
|
-
config_data = json.load(f)
|
74
|
-
# Chat history context feature has been removed
|
75
|
-
if "debug_mode" in config_data:
|
76
|
-
self._verbose = config_data["debug_mode"]
|
77
|
-
if "ask_mode" in config_data:
|
78
|
-
self._ask_mode = config_data["ask_mode"]
|
79
|
-
if "trust_mode" in config_data:
|
80
|
-
self._trust_mode = config_data["trust_mode"]
|
81
|
-
if "temperature" in config_data:
|
82
|
-
self._temperature = config_data["temperature"]
|
83
|
-
if "profile" in config_data:
|
84
|
-
self._profile = config_data["profile"]
|
85
|
-
if "role" in config_data:
|
86
|
-
self._role = config_data["role"]
|
87
|
-
if "gitbash_path" in config_data:
|
88
|
-
self._gitbash_path = config_data["gitbash_path"]
|
89
|
-
except Exception as e:
|
90
|
-
print(f"Warning: Failed to load configuration: {str(e)}")
|
91
|
-
|
92
|
-
def _save_config(self) -> None:
|
93
|
-
"""Save configuration to file."""
|
94
|
-
config_dir = Path(self._workspace_dir) / ".janito"
|
95
|
-
config_dir.mkdir(parents=True, exist_ok=True)
|
96
|
-
config_path = config_dir / "config.json"
|
97
|
-
|
98
|
-
config_data = {
|
99
|
-
# Chat history context feature has been removed
|
100
|
-
"verbose": self._verbose,
|
101
|
-
"ask_mode": self._ask_mode,
|
102
|
-
# trust_mode is not saved as it's a per-session setting
|
103
|
-
"temperature": self._temperature,
|
104
|
-
"role": self._role
|
105
|
-
}
|
106
|
-
|
107
|
-
# Save profile name if one is set
|
108
|
-
if self._profile:
|
109
|
-
config_data["profile"] = self._profile
|
110
|
-
|
111
|
-
# Save GitBash path if one is set
|
112
|
-
if self._gitbash_path:
|
113
|
-
config_data["gitbash_path"] = self._gitbash_path
|
114
|
-
|
115
|
-
try:
|
116
|
-
with open(config_path, "w", encoding="utf-8") as f:
|
117
|
-
json.dump(config_data, f, indent=2)
|
118
|
-
except Exception as e:
|
119
|
-
print(f"Warning: Failed to save configuration: {str(e)}")
|
120
|
-
|
121
|
-
def set_profile(self, profile_name: str) -> None:
|
122
|
-
"""Set parameter values based on a predefined profile.
|
123
|
-
|
124
|
-
Args:
|
125
|
-
profile_name: Name of the profile to use (precise, balanced, conversational, creative, technical)
|
126
|
-
|
127
|
-
Raises:
|
128
|
-
ValueError: If the profile name is not recognized
|
129
|
-
"""
|
130
|
-
profile_name = profile_name.lower()
|
131
|
-
if profile_name not in PROFILES:
|
132
|
-
valid_profiles = ", ".join(PROFILES.keys())
|
133
|
-
raise ValueError(f"Unknown profile: {profile_name}. Valid profiles are: {valid_profiles}")
|
134
|
-
|
135
|
-
profile = PROFILES[profile_name]
|
136
|
-
self._temperature = profile["temperature"]
|
137
|
-
self._profile = profile_name
|
138
|
-
self._save_config()
|
139
|
-
|
140
|
-
@property
|
141
|
-
def profile(self) -> Optional[str]:
|
142
|
-
"""Get the current profile name."""
|
143
|
-
return self._profile
|
144
|
-
|
145
|
-
@staticmethod
|
146
|
-
def get_available_profiles() -> Dict[str, Dict[str, Any]]:
|
147
|
-
"""Get all available predefined profiles."""
|
148
|
-
return PROFILES
|
149
|
-
|
150
|
-
@staticmethod
|
151
|
-
def set_api_key(api_key: str) -> None:
|
152
|
-
"""Set the API key in the global configuration file.
|
153
|
-
|
154
|
-
Args:
|
155
|
-
api_key: The Anthropic API key to store
|
156
|
-
|
157
|
-
Returns:
|
158
|
-
None
|
159
|
-
"""
|
160
|
-
# Create .janito directory in user's home directory if it doesn't exist
|
161
|
-
home_dir = Path.home()
|
162
|
-
config_dir = home_dir / ".janito"
|
163
|
-
config_dir.mkdir(parents=True, exist_ok=True)
|
164
|
-
|
165
|
-
# Create or update the config.json file
|
166
|
-
config_path = config_dir / "config.json"
|
167
|
-
|
168
|
-
# Load existing config if it exists
|
169
|
-
config_data = {}
|
170
|
-
if config_path.exists():
|
171
|
-
try:
|
172
|
-
with open(config_path, "r", encoding="utf-8") as f:
|
173
|
-
config_data = json.load(f)
|
174
|
-
except Exception as e:
|
175
|
-
print(f"Warning: Failed to load global configuration: {str(e)}")
|
176
|
-
|
177
|
-
# Update the API key
|
178
|
-
config_data["api_key"] = api_key
|
179
|
-
|
180
|
-
# Save the updated config
|
181
|
-
try:
|
182
|
-
with open(config_path, "w", encoding="utf-8") as f:
|
183
|
-
json.dump(config_data, f, indent=2)
|
184
|
-
print(f"API key saved to {config_path}")
|
185
|
-
except Exception as e:
|
186
|
-
raise ValueError(f"Failed to save API key: {str(e)}")
|
187
|
-
|
188
|
-
@staticmethod
|
189
|
-
def get_api_key() -> Optional[str]:
|
190
|
-
"""Get the API key from the global configuration file.
|
191
|
-
|
192
|
-
Returns:
|
193
|
-
The API key if found, None otherwise
|
194
|
-
"""
|
195
|
-
# Look for config.json in user's home directory
|
196
|
-
home_dir = Path.home()
|
197
|
-
config_path = home_dir / ".janito" / "config.json"
|
198
|
-
|
199
|
-
if config_path.exists():
|
200
|
-
try:
|
201
|
-
with open(config_path, "r", encoding="utf-8") as f:
|
202
|
-
config_data = json.load(f)
|
203
|
-
return config_data.get("api_key")
|
204
|
-
except Exception:
|
205
|
-
# Silently fail and return None
|
206
|
-
pass
|
207
|
-
|
208
|
-
return None
|
209
|
-
|
210
|
-
@property
|
211
|
-
def workspace_dir(self) -> str:
|
212
|
-
"""Get the current workspace directory."""
|
213
|
-
return self._workspace_dir
|
214
|
-
|
215
|
-
@workspace_dir.setter
|
216
|
-
def workspace_dir(self, path: str) -> None:
|
217
|
-
"""Set the workspace directory."""
|
218
|
-
# Convert to absolute path if not already
|
219
|
-
if not os.path.isabs(path):
|
220
|
-
path = os.path.normpath(os.path.abspath(path))
|
221
|
-
else:
|
222
|
-
# Ensure Windows paths are properly formatted
|
223
|
-
path = os.path.normpath(path)
|
224
|
-
|
225
|
-
# Check if the directory exists
|
226
|
-
if not os.path.isdir(path):
|
227
|
-
create_dir = typer.confirm(f"Workspace directory does not exist: {path}\nDo you want to create it?")
|
228
|
-
if create_dir:
|
229
|
-
try:
|
230
|
-
os.makedirs(path, exist_ok=True)
|
231
|
-
print(f"Created workspace directory: {path}")
|
232
|
-
except Exception as e:
|
233
|
-
raise ValueError(f"Failed to create workspace directory: {str(e)}") from e
|
234
|
-
else:
|
235
|
-
raise ValueError(f"Workspace directory does not exist: {path}")
|
236
|
-
|
237
|
-
self._workspace_dir = path
|
238
|
-
|
239
|
-
@property
|
240
|
-
def verbose(self) -> bool:
|
241
|
-
"""Get the verbose mode status."""
|
242
|
-
return self._verbose
|
243
|
-
|
244
|
-
@verbose.setter
|
245
|
-
def verbose(self, value: bool) -> None:
|
246
|
-
"""Set the verbose mode status."""
|
247
|
-
self._verbose = value
|
248
|
-
|
249
|
-
# For backward compatibility
|
250
|
-
@property
|
251
|
-
def debug_mode(self) -> bool:
|
252
|
-
"""Get the debug mode status (alias for verbose)."""
|
253
|
-
return self._verbose
|
254
|
-
|
255
|
-
@debug_mode.setter
|
256
|
-
def debug_mode(self, value: bool) -> None:
|
257
|
-
"""Set the debug mode status (alias for verbose)."""
|
258
|
-
self._verbose = value
|
259
|
-
|
260
|
-
# Chat history context feature has been removed
|
261
|
-
|
262
|
-
@property
|
263
|
-
def ask_mode(self) -> bool:
|
264
|
-
"""Get the ask mode status."""
|
265
|
-
return self._ask_mode
|
266
|
-
|
267
|
-
@ask_mode.setter
|
268
|
-
def ask_mode(self, value: bool) -> None:
|
269
|
-
"""Set the ask mode status."""
|
270
|
-
self._ask_mode = value
|
271
|
-
self._save_config()
|
272
|
-
|
273
|
-
@property
|
274
|
-
def trust_mode(self) -> bool:
|
275
|
-
"""Get the trust mode status."""
|
276
|
-
return self._trust_mode
|
277
|
-
|
278
|
-
@trust_mode.setter
|
279
|
-
def trust_mode(self, value: bool) -> None:
|
280
|
-
"""Set the trust mode status.
|
281
|
-
|
282
|
-
Note: This setting is not persisted to config file
|
283
|
-
as it's meant to be a per-session setting.
|
284
|
-
"""
|
285
|
-
self._trust_mode = value
|
286
|
-
# Don't save to config file - this is a per-session setting
|
287
|
-
|
288
|
-
@property
|
289
|
-
def no_tools(self) -> bool:
|
290
|
-
"""Get the no-tools mode status."""
|
291
|
-
return self._no_tools
|
292
|
-
|
293
|
-
@no_tools.setter
|
294
|
-
def no_tools(self, value: bool) -> None:
|
295
|
-
"""Set the no-tools mode status.
|
296
|
-
|
297
|
-
Note: This setting is not persisted to config file
|
298
|
-
as it's meant to be a per-session setting.
|
299
|
-
"""
|
300
|
-
self._no_tools = value
|
301
|
-
# Don't save to config file - this is a per-session setting
|
302
|
-
|
303
|
-
@property
|
304
|
-
def temperature(self) -> float:
|
305
|
-
"""Get the temperature value for model generation."""
|
306
|
-
return self._temperature
|
307
|
-
|
308
|
-
@temperature.setter
|
309
|
-
def temperature(self, value: float) -> None:
|
310
|
-
"""Set the temperature value for model generation."""
|
311
|
-
if value < 0.0 or value > 1.0:
|
312
|
-
raise ValueError("Temperature must be between 0.0 and 1.0")
|
313
|
-
self._temperature = value
|
314
|
-
self._save_config()
|
315
|
-
|
316
|
-
# top_k and top_p are now only accessible through profiles
|
317
|
-
|
318
|
-
@property
|
319
|
-
def role(self) -> str:
|
320
|
-
"""Get the role for the assistant."""
|
321
|
-
return self._role
|
322
|
-
|
323
|
-
@role.setter
|
324
|
-
def role(self, value: str) -> None:
|
325
|
-
"""Set the role for the assistant."""
|
326
|
-
self._role = value
|
327
|
-
self._save_config()
|
328
|
-
|
329
|
-
@property
|
330
|
-
def gitbash_path(self) -> Optional[str]:
|
331
|
-
"""Get the path to the GitBash executable."""
|
332
|
-
return self._gitbash_path
|
333
|
-
|
334
|
-
@gitbash_path.setter
|
335
|
-
def gitbash_path(self, value: Optional[str]) -> None:
|
336
|
-
"""Set the path to the GitBash executable.
|
337
|
-
|
338
|
-
Args:
|
339
|
-
value: Path to the GitBash executable, or None to use auto-detection
|
340
|
-
"""
|
341
|
-
# If a path is provided, verify it exists
|
342
|
-
if value is not None and not os.path.exists(value):
|
343
|
-
raise ValueError(f"GitBash executable not found at: {value}")
|
344
|
-
|
345
|
-
self._gitbash_path = value
|
346
|
-
self._save_config()
|
347
|
-
|
348
|
-
def reset_config(self) -> bool:
|
349
|
-
"""Reset configuration by removing the config file.
|
350
|
-
|
351
|
-
Returns:
|
352
|
-
bool: True if the config file was removed, False if it didn't exist
|
353
|
-
"""
|
354
|
-
config_path = Path(self._workspace_dir) / ".janito" / "config.json"
|
355
|
-
if config_path.exists():
|
356
|
-
config_path.unlink()
|
357
|
-
# Reset instance variables to defaults
|
358
|
-
self._verbose = False
|
359
|
-
# Chat history context feature has been removed
|
360
|
-
self._ask_mode = False
|
361
|
-
self._trust_mode = False
|
362
|
-
self._no_tools = False
|
363
|
-
# Set technical profile as default
|
364
|
-
profile_data = PROFILES["technical"]
|
365
|
-
self._temperature = profile_data["temperature"]
|
366
|
-
self._profile = "technical"
|
367
|
-
self._role = "software engineer"
|
368
|
-
self._gitbash_path = None # Reset to auto-detection
|
369
|
-
return True
|
370
|
-
return False
|
371
|
-
|
372
|
-
# Convenience function to get the config instance
|
373
|
-
def get_config() -> Config:
|
374
|
-
"""Get the singleton Config instance."""
|
375
|
-
return Config()
|
@@ -1,31 +0,0 @@
|
|
1
|
-
You are a {{ role }}, using the name Janito .
|
2
|
-
You will be assisting an user using a computer system on a {{ platform }} platform.
|
3
|
-
You can find more about the current project using the tools in the workspace directory.
|
4
|
-
If the question is related to the project, use the tools using the relative path, filename instead of /filename.
|
5
|
-
|
6
|
-
If creating or editing files with a large number of lines, organize them into smaller files.
|
7
|
-
If creating or editing files in an existing directory check surrounding files for the used patterns.
|
8
|
-
|
9
|
-
# Structure Discovery (docs/STRUCTURE.md from current directory)
|
10
|
-
Always start exploring the project by viewing for the file docs/STRUCTURE.md.
|
11
|
-
Do not track files or directories wich are in .gitignore in the structure.
|
12
|
-
At the end of responding to the user, update the structure file based on the files and directories you have interacted with,
|
13
|
-
be precise focusing on the most important files and directories, avoid adding extra information like architecture or design patterns.
|
14
|
-
|
15
|
-
# Tools
|
16
|
-
The bash tool does not support commands which will require user input.
|
17
|
-
Use the bash tool to get the current date or time when needed.
|
18
|
-
Prefer the str_replace_editor tool to view directories and file contents.
|
19
|
-
|
20
|
-
</IMPORTANT>
|
21
|
-
Call the user_prompt tool when:
|
22
|
-
- There are multiple options to apply a certain change
|
23
|
-
- The next operation risk is moderated or high
|
24
|
-
- The implementation plan is complex, requiring a review
|
25
|
-
Proceed according to the user answer.
|
26
|
-
<IMPORTANT/>
|
27
|
-
|
28
|
-
When changing code in Python files, be mindful about the need to review the imports specially when new type hints are used (eg. Optional, Tuple, List, Dict, etc).
|
29
|
-
After performing changes to a project in interfaces which are exposed to the user, respond to the user with a short summary on how to verify the changes. eg. "run cmd xpto", prefer to provide a command to run instead of a description.
|
30
|
-
When displaying commands in instructions to the user, consider their platform.
|
31
|
-
When creating html pages which refer to images that should be manually placed by the user, instead of broken links provide a frame with a placeholder image.
|
janito/token_report.py
DELETED
@@ -1,154 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Module for generating token usage reports.
|
3
|
-
"""
|
4
|
-
|
5
|
-
from rich.console import Console
|
6
|
-
|
7
|
-
def generate_token_report(agent, verbose=False, interrupted=False):
|
8
|
-
"""
|
9
|
-
Generate a token usage report.
|
10
|
-
|
11
|
-
Args:
|
12
|
-
agent: The Claude agent instance
|
13
|
-
verbose: Whether to show detailed token usage information
|
14
|
-
interrupted: Whether the request was interrupted
|
15
|
-
|
16
|
-
Returns:
|
17
|
-
None - prints the report to the console
|
18
|
-
"""
|
19
|
-
console = Console()
|
20
|
-
usage = agent.get_tokens()
|
21
|
-
cost = agent.get_token_cost()
|
22
|
-
|
23
|
-
text_usage = usage.text_usage
|
24
|
-
tools_usage = usage.tools_usage
|
25
|
-
|
26
|
-
if verbose:
|
27
|
-
total_usage = usage.total_usage
|
28
|
-
|
29
|
-
# Get costs from the cost object
|
30
|
-
text_input_cost = cost.input_cost
|
31
|
-
text_output_cost = cost.output_cost
|
32
|
-
text_cache_creation_cost = cost.cache_creation_cost
|
33
|
-
text_cache_read_cost = cost.cache_read_cost
|
34
|
-
|
35
|
-
tools_input_cost = cost.input_cost
|
36
|
-
tools_output_cost = cost.output_cost
|
37
|
-
tools_cache_creation_cost = cost.cache_creation_cost
|
38
|
-
tools_cache_read_cost = cost.cache_read_cost
|
39
|
-
|
40
|
-
# Format costs
|
41
|
-
def format_cost(cost):
|
42
|
-
return f"{cost * 100:.2f}¢ USD" if cost < 1.0 else f"${cost:.6f} USD"
|
43
|
-
|
44
|
-
console.print("\n[bold blue]📊 Detailed Token Usage:[/bold blue]")
|
45
|
-
console.print(f"📝 Text Input tokens: {text_usage.input_tokens}")
|
46
|
-
console.print(f"📤 Text Output tokens: {text_usage.output_tokens}")
|
47
|
-
console.print(f"💾 Text Cache Creation tokens: {text_usage.cache_creation_input_tokens}")
|
48
|
-
console.print(f"📖 Text Cache Read tokens: {text_usage.cache_read_input_tokens}")
|
49
|
-
console.print(f"📋 Text Total tokens: {text_usage.input_tokens + text_usage.output_tokens + text_usage.cache_creation_input_tokens + text_usage.cache_read_input_tokens}")
|
50
|
-
|
51
|
-
console.print(f"🔧 Tool Input tokens: {tools_usage.input_tokens}")
|
52
|
-
console.print(f"🔨 Tool Output tokens: {tools_usage.output_tokens}")
|
53
|
-
console.print(f"💾 Tool Cache Creation tokens: {tools_usage.cache_creation_input_tokens}")
|
54
|
-
console.print(f"📖 Tool Cache Read tokens: {tools_usage.cache_read_input_tokens}")
|
55
|
-
console.print(f"🧰 Tool Total tokens: {tools_usage.input_tokens + tools_usage.output_tokens + tools_usage.cache_creation_input_tokens + tools_usage.cache_read_input_tokens}")
|
56
|
-
|
57
|
-
console.print(f"🔢 Total tokens: {total_usage.input_tokens + total_usage.output_tokens + total_usage.cache_creation_input_tokens + total_usage.cache_read_input_tokens}")
|
58
|
-
|
59
|
-
console.print("\n[bold blue]💰 Pricing Information:[/bold blue]")
|
60
|
-
console.print(f"📝 Text Input cost: {format_cost(text_input_cost)}")
|
61
|
-
console.print(f"📤 Text Output cost: {format_cost(text_output_cost)}")
|
62
|
-
console.print(f"💾 Text Cache Creation cost: {format_cost(text_cache_creation_cost)}")
|
63
|
-
console.print(f"📖 Text Cache Read cost: {format_cost(text_cache_read_cost)}")
|
64
|
-
console.print(f"📋 Text Total cost: {format_cost(text_input_cost + text_output_cost + text_cache_creation_cost + text_cache_read_cost)}")
|
65
|
-
|
66
|
-
console.print(f"🔧 Tool Input cost: {format_cost(tools_input_cost)}")
|
67
|
-
console.print(f"🔨 Tool Output cost: {format_cost(tools_output_cost)}")
|
68
|
-
console.print(f"💾 Tool Cache Creation cost: {format_cost(tools_cache_creation_cost)}")
|
69
|
-
console.print(f"📖 Tool Cache Read cost: {format_cost(tools_cache_read_cost)}")
|
70
|
-
console.print(f"🧰 Tool Total cost: {format_cost(tools_input_cost + tools_output_cost + tools_cache_creation_cost + tools_cache_read_cost)}")
|
71
|
-
|
72
|
-
total_cost_text = f"💵 Total cost: {format_cost(text_input_cost + text_output_cost + text_cache_creation_cost + text_cache_read_cost + tools_input_cost + tools_output_cost + tools_cache_creation_cost + tools_cache_read_cost)}"
|
73
|
-
if interrupted:
|
74
|
-
total_cost_text += " (interrupted request not accounted)"
|
75
|
-
console.print(total_cost_text)
|
76
|
-
|
77
|
-
# Show cache delta if available
|
78
|
-
if hasattr(cost, 'cache_delta') and cost.cache_delta:
|
79
|
-
cache_delta = cost.cache_delta
|
80
|
-
console.print(f"\n[bold green]💰 Cache Savings:[/bold green] {format_cost(cache_delta)}")
|
81
|
-
|
82
|
-
# Calculate percentage savings
|
83
|
-
total_cost_without_cache = cost.total_cost + cache_delta
|
84
|
-
if total_cost_without_cache > 0:
|
85
|
-
savings_percentage = (cache_delta / total_cost_without_cache) * 100
|
86
|
-
console.print(f"[bold green]📊 Cache Savings Percentage:[/bold green] {savings_percentage:.2f}%")
|
87
|
-
console.print(f"[bold green]💸 Cost without cache:[/bold green] {format_cost(total_cost_without_cache)}")
|
88
|
-
console.print(f"[bold green]💲 Cost with cache:[/bold green] {format_cost(cost.total_cost)}")
|
89
|
-
|
90
|
-
# Per-tool breakdown
|
91
|
-
if usage.by_tool:
|
92
|
-
console.print("\n[bold blue]🔧 Per-Tool Breakdown:[/bold blue]")
|
93
|
-
try:
|
94
|
-
if hasattr(cost, 'by_tool') and cost.by_tool:
|
95
|
-
for tool_name, tool_usage in usage.by_tool.items():
|
96
|
-
tool_input_cost = cost.by_tool[tool_name].input_cost
|
97
|
-
tool_output_cost = cost.by_tool[tool_name].output_cost
|
98
|
-
tool_cache_creation_cost = cost.by_tool[tool_name].cache_creation_cost
|
99
|
-
tool_cache_read_cost = cost.by_tool[tool_name].cache_read_cost
|
100
|
-
tool_total_cost = tool_input_cost + tool_output_cost + tool_cache_creation_cost + tool_cache_read_cost
|
101
|
-
|
102
|
-
console.print(f" 🔧 Tool: {tool_name}")
|
103
|
-
console.print(f" 📥 Input tokens: {tool_usage.input_tokens}")
|
104
|
-
console.print(f" 📤 Output tokens: {tool_usage.output_tokens}")
|
105
|
-
console.print(f" 💾 Cache Creation tokens: {tool_usage.cache_creation_input_tokens}")
|
106
|
-
console.print(f" 📖 Cache Read tokens: {tool_usage.cache_read_input_tokens}")
|
107
|
-
console.print(f" 🔢 Total tokens: {tool_usage.input_tokens + tool_usage.output_tokens + tool_usage.cache_creation_input_tokens + tool_usage.cache_read_input_tokens}")
|
108
|
-
console.print(f" 💵 Total cost: {format_cost(tool_total_cost)}")
|
109
|
-
else:
|
110
|
-
# Calculate costs manually for each tool if cost.by_tool is not available
|
111
|
-
for tool_name, tool_usage in usage.by_tool.items():
|
112
|
-
# Estimate costs based on overall pricing
|
113
|
-
total_tokens = tool_usage.input_tokens + tool_usage.output_tokens + tool_usage.cache_creation_input_tokens + tool_usage.cache_read_input_tokens
|
114
|
-
estimated_cost = (total_tokens / (usage.total_usage.total_tokens + usage.total_usage.total_cache_tokens)) * cost.total_cost if usage.total_usage.total_tokens > 0 else 0
|
115
|
-
|
116
|
-
console.print(f" 🔧 Tool: {tool_name}")
|
117
|
-
console.print(f" 📥 Input tokens: {tool_usage.input_tokens}")
|
118
|
-
console.print(f" 📤 Output tokens: {tool_usage.output_tokens}")
|
119
|
-
console.print(f" 💾 Cache Creation tokens: {tool_usage.cache_creation_input_tokens}")
|
120
|
-
console.print(f" 📖 Cache Read tokens: {tool_usage.cache_read_input_tokens}")
|
121
|
-
console.print(f" 🔢 Total tokens: {tool_usage.input_tokens + tool_usage.output_tokens + tool_usage.cache_creation_input_tokens + tool_usage.cache_read_input_tokens}")
|
122
|
-
console.print(f" 💵 Total cost: {format_cost(estimated_cost)}")
|
123
|
-
except Exception as e:
|
124
|
-
console.print(f"❌ Error: {str(e)}")
|
125
|
-
else:
|
126
|
-
total_tokens = (text_usage.input_tokens + text_usage.output_tokens +
|
127
|
-
text_usage.cache_creation_input_tokens + text_usage.cache_read_input_tokens +
|
128
|
-
tools_usage.input_tokens + tools_usage.output_tokens +
|
129
|
-
tools_usage.cache_creation_input_tokens + tools_usage.cache_read_input_tokens)
|
130
|
-
|
131
|
-
# Format costs
|
132
|
-
def format_cost(cost):
|
133
|
-
return f"{cost * 100:.2f}¢ USD" if cost < 1.0 else f"${cost:.6f} USD"
|
134
|
-
|
135
|
-
# Prepare summary message
|
136
|
-
cost_text = f"Cost: {format_cost(cost.total_cost)}"
|
137
|
-
if interrupted:
|
138
|
-
cost_text += " (interrupted request not accounted)"
|
139
|
-
|
140
|
-
summary = f"Total tokens: {total_tokens} | {cost_text}"
|
141
|
-
|
142
|
-
# Add cache savings if available
|
143
|
-
if hasattr(cost, 'cache_delta') and cost.cache_delta != 0:
|
144
|
-
cache_delta = cost.cache_delta
|
145
|
-
total_cost_without_cache = cost.total_cost + cache_delta
|
146
|
-
savings_percentage = 0
|
147
|
-
if total_cost_without_cache > 0:
|
148
|
-
savings_percentage = (cache_delta / total_cost_without_cache) * 100
|
149
|
-
|
150
|
-
summary += f" | Cache savings: {format_cost(cache_delta)} ({savings_percentage:.1f}%)"
|
151
|
-
|
152
|
-
# Display with a rule
|
153
|
-
console.rule("[blue]Token Usage[/blue]")
|
154
|
-
console.print(f"[blue]{summary}[/blue]", justify="center")
|
janito/tools/__init__.py
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Janito tools package.
|
3
|
-
"""
|
4
|
-
|
5
|
-
from .str_replace_editor import str_replace_editor
|
6
|
-
from .find_files import find_files
|
7
|
-
from .delete_file import delete_file
|
8
|
-
from .search_text import search_text
|
9
|
-
from .replace_file import replace_file
|
10
|
-
from .prompt_user import prompt_user
|
11
|
-
from .move_file import move_file
|
12
|
-
from janito.tools.fetch_webpage import fetch_webpage
|
13
|
-
from .think import think
|
14
|
-
from .usage_tracker import get_tracker, reset_tracker, print_usage_stats
|
15
|
-
from janito.config import get_config
|
16
|
-
|
17
|
-
__all__ = ["str_replace_editor", "find_files", "delete_file", "search_text", "replace_file",
|
18
|
-
"prompt_user", "move_file", "fetch_webpage", "think", "get_tools",
|
19
|
-
"get_tracker", "reset_tracker", "print_usage_stats"]
|
20
|
-
|
21
|
-
def get_tools():
|
22
|
-
"""
|
23
|
-
Get a list of all available tools.
|
24
|
-
|
25
|
-
Returns:
|
26
|
-
List of tool functions (excluding str_replace_editor which is passed separately)
|
27
|
-
If no_tools mode is enabled, returns an empty list
|
28
|
-
If ask_mode is enabled, only returns tools that don't perform changes
|
29
|
-
"""
|
30
|
-
# If no_tools mode is enabled, return an empty list
|
31
|
-
if get_config().no_tools:
|
32
|
-
return []
|
33
|
-
|
34
|
-
# Tools that only read or view but don't modify anything
|
35
|
-
read_only_tools = [find_files, search_text, prompt_user, fetch_webpage, think]
|
36
|
-
|
37
|
-
# Tools that modify the filesystem
|
38
|
-
write_tools = [delete_file, replace_file, move_file]
|
39
|
-
|
40
|
-
# If ask_mode is enabled, only return read-only tools
|
41
|
-
if get_config().ask_mode:
|
42
|
-
return read_only_tools
|
43
|
-
else:
|
44
|
-
return read_only_tools + write_tools
|