janito 1.9.0__py3-none-any.whl → 1.10.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 -1
- janito/agent/api_exceptions.py +4 -0
- janito/agent/config.py +1 -1
- janito/agent/config_defaults.py +2 -26
- janito/agent/conversation.py +163 -122
- janito/agent/conversation_api.py +149 -159
- janito/agent/{conversation_history.py → llm_conversation_history.py} +18 -1
- janito/agent/openai_client.py +38 -23
- janito/agent/openai_schema_generator.py +162 -129
- janito/agent/platform_discovery.py +134 -77
- janito/agent/profile_manager.py +5 -5
- janito/agent/rich_message_handler.py +80 -31
- janito/agent/templates/profiles/system_prompt_template_base.txt.j2 +5 -4
- janito/agent/test_openai_schema_generator.py +93 -0
- janito/agent/tool_base.py +7 -2
- janito/agent/tool_executor.py +54 -49
- janito/agent/tool_registry.py +5 -2
- janito/agent/tool_use_tracker.py +26 -5
- janito/agent/tools/__init__.py +6 -3
- janito/agent/tools/create_directory.py +3 -1
- janito/agent/tools/create_file.py +7 -1
- janito/agent/tools/fetch_url.py +40 -3
- janito/agent/tools/find_files.py +3 -1
- janito/agent/tools/get_file_outline/core.py +6 -7
- janito/agent/tools/get_file_outline/search_outline.py +3 -1
- janito/agent/tools/get_lines.py +7 -2
- janito/agent/tools/move_file.py +3 -1
- janito/agent/tools/present_choices.py +3 -1
- janito/agent/tools/python_command_runner.py +150 -0
- janito/agent/tools/python_file_runner.py +148 -0
- janito/agent/tools/python_stdin_runner.py +154 -0
- janito/agent/tools/remove_directory.py +3 -1
- janito/agent/tools/remove_file.py +5 -1
- janito/agent/tools/replace_file.py +12 -2
- janito/agent/tools/replace_text_in_file.py +4 -2
- janito/agent/tools/run_bash_command.py +30 -69
- janito/agent/tools/run_powershell_command.py +134 -105
- janito/agent/tools/search_text.py +172 -122
- janito/agent/tools/validate_file_syntax/core.py +3 -1
- janito/agent/tools_utils/action_type.py +7 -0
- janito/agent/tools_utils/dir_walk_utils.py +3 -2
- janito/agent/tools_utils/formatting.py +47 -21
- janito/agent/tools_utils/gitignore_utils.py +66 -40
- janito/agent/tools_utils/test_gitignore_utils.py +46 -0
- janito/cli/_print_config.py +63 -61
- janito/cli/arg_parser.py +13 -12
- janito/cli/cli_main.py +137 -147
- janito/cli/main.py +152 -174
- janito/cli/one_shot.py +40 -26
- janito/i18n/__init__.py +1 -1
- janito/rich_utils.py +46 -8
- janito/shell/commands/__init__.py +2 -4
- janito/shell/commands/conversation_restart.py +3 -1
- janito/shell/commands/edit.py +3 -0
- janito/shell/commands/history_view.py +3 -3
- janito/shell/commands/lang.py +3 -0
- janito/shell/commands/livelogs.py +5 -3
- janito/shell/commands/prompt.py +6 -0
- janito/shell/commands/session.py +3 -0
- janito/shell/commands/session_control.py +3 -0
- janito/shell/commands/termweb_log.py +8 -0
- janito/shell/commands/tools.py +3 -0
- janito/shell/commands/track.py +36 -0
- janito/shell/commands/utility.py +13 -18
- janito/shell/commands/verbose.py +3 -4
- janito/shell/input_history.py +62 -0
- janito/shell/main.py +117 -181
- janito/shell/session/manager.py +0 -21
- janito/shell/ui/interactive.py +0 -2
- janito/termweb/static/editor.css +0 -4
- janito/tests/test_rich_utils.py +44 -0
- janito/web/app.py +0 -75
- {janito-1.9.0.dist-info → janito-1.10.0.dist-info}/METADATA +61 -42
- {janito-1.9.0.dist-info → janito-1.10.0.dist-info}/RECORD +78 -71
- {janito-1.9.0.dist-info → janito-1.10.0.dist-info}/WHEEL +1 -1
- janito/agent/providers.py +0 -77
- janito/agent/tools/run_python_command.py +0 -161
- janito/shell/commands/sum.py +0 -49
- {janito-1.9.0.dist-info → janito-1.10.0.dist-info}/entry_points.txt +0 -0
- {janito-1.9.0.dist-info → janito-1.10.0.dist-info}/licenses/LICENSE +0 -0
- {janito-1.9.0.dist-info → janito-1.10.0.dist-info}/top_level.txt +0 -0
janito/cli/main.py
CHANGED
@@ -12,205 +12,183 @@ import janito.agent.tools # noqa: F401
|
|
12
12
|
from janito.i18n import tr
|
13
13
|
|
14
14
|
|
15
|
+
def handle_list_sessions(args):
|
16
|
+
import os
|
17
|
+
import glob
|
18
|
+
|
19
|
+
n = args.list if args.list is not None else 10
|
20
|
+
history_dir = os.path.join(os.path.expanduser(".janito"), "chat_history")
|
21
|
+
if not os.path.exists(history_dir):
|
22
|
+
print("No session history found.")
|
23
|
+
return True
|
24
|
+
files = glob.glob(os.path.join(history_dir, "*.json"))
|
25
|
+
files = sorted(files, key=os.path.getmtime, reverse=True)
|
26
|
+
print(f"Last {n} sessions:")
|
27
|
+
for f in files[:n]:
|
28
|
+
session_id = os.path.splitext(os.path.basename(f))[0]
|
29
|
+
print(session_id)
|
30
|
+
return True
|
31
|
+
|
32
|
+
|
33
|
+
def handle_view_session(args):
|
34
|
+
import os
|
35
|
+
import json
|
36
|
+
|
37
|
+
history_dir = os.path.join(os.path.expanduser(".janito"), "chat_history")
|
38
|
+
session_file = os.path.join(history_dir, f"{args.view}.json")
|
39
|
+
if not os.path.exists(session_file):
|
40
|
+
print(f"Session '{args.view}' not found.")
|
41
|
+
return 1
|
42
|
+
with open(session_file, "r", encoding="utf-8") as f:
|
43
|
+
try:
|
44
|
+
messages = json.load(f)
|
45
|
+
except Exception as e:
|
46
|
+
print(f"Failed to load session: {e}")
|
47
|
+
return 1
|
48
|
+
print(f"Conversation history for session '{args.view}':\n")
|
49
|
+
for i, msg in enumerate(messages, 1):
|
50
|
+
role = msg.get("role", "?")
|
51
|
+
content = msg.get("content", "")
|
52
|
+
print(f"[{i}] {role}: {content}\n")
|
53
|
+
return 0
|
54
|
+
|
55
|
+
|
56
|
+
def handle_lang_selection(args):
|
57
|
+
import janito.i18n as i18n
|
58
|
+
from janito.agent.runtime_config import runtime_config
|
59
|
+
|
60
|
+
lang = getattr(args, "lang", None) or unified_config.get("lang", None) or "en"
|
61
|
+
runtime_config.set("lang", lang)
|
62
|
+
i18n.set_locale(lang)
|
63
|
+
|
64
|
+
|
65
|
+
def handle_help_config(args):
|
66
|
+
from janito.agent.config import CONFIG_OPTIONS
|
67
|
+
from janito.agent.config_defaults import CONFIG_DEFAULTS
|
68
|
+
|
69
|
+
print(tr("Available configuration options:\n"))
|
70
|
+
for key, desc in CONFIG_OPTIONS.items():
|
71
|
+
default = CONFIG_DEFAULTS.get(key, None)
|
72
|
+
print(
|
73
|
+
tr(
|
74
|
+
"{key:15} {desc} (default: {default})",
|
75
|
+
key=key,
|
76
|
+
desc=desc,
|
77
|
+
default=default,
|
78
|
+
)
|
79
|
+
)
|
80
|
+
|
81
|
+
|
82
|
+
def handle_list_tools(args):
|
83
|
+
from janito.agent.tool_registry import get_tool_schemas
|
84
|
+
from rich.console import Console
|
85
|
+
from rich.table import Table
|
86
|
+
|
87
|
+
console = Console()
|
88
|
+
table = Table(
|
89
|
+
title="Ferramentas Registradas", show_lines=True, style="bold magenta"
|
90
|
+
)
|
91
|
+
table.add_column("Gnome", style="cyan", no_wrap=True)
|
92
|
+
table.add_column("Descrição", style="green")
|
93
|
+
table.add_column("Parâmetros", style="yellow")
|
94
|
+
for schema in get_tool_schemas():
|
95
|
+
fn = schema["function"]
|
96
|
+
params = "\n".join(
|
97
|
+
[
|
98
|
+
f"[bold]{k}[/]: {v['type']}"
|
99
|
+
for k, v in fn["parameters"].get("properties", {}).items()
|
100
|
+
]
|
101
|
+
)
|
102
|
+
table.add_row(f"[b]{fn['name']}[/b]", fn["description"], params or "-")
|
103
|
+
console.print(table)
|
104
|
+
|
105
|
+
|
106
|
+
def handle_info(args):
|
107
|
+
from janito import __version__
|
108
|
+
from rich.console import Console
|
109
|
+
from rich.text import Text
|
110
|
+
from janito.agent.runtime_config import runtime_config
|
111
|
+
|
112
|
+
model = unified_config.get("model")
|
113
|
+
temperature = unified_config.get("temperature")
|
114
|
+
max_tokens = unified_config.get("max_tokens")
|
115
|
+
system_prompt_val = None
|
116
|
+
if getattr(args, "system_file", None):
|
117
|
+
try:
|
118
|
+
with open(args.system_file, "r", encoding="utf-8") as f:
|
119
|
+
system_prompt_val = f.read().strip()
|
120
|
+
runtime_config.set("system_prompt_template", system_prompt_val)
|
121
|
+
except Exception as e:
|
122
|
+
system_prompt_val = f"(error reading system-file: {e})"
|
123
|
+
elif getattr(args, "system", None):
|
124
|
+
system_prompt_val = args.system
|
125
|
+
runtime_config.set("system_prompt_template", system_prompt_val)
|
126
|
+
else:
|
127
|
+
system_prompt_val = runtime_config.get("system_prompt_template")
|
128
|
+
if not system_prompt_val:
|
129
|
+
try:
|
130
|
+
from janito.agent.profile_manager import AgentProfileManager
|
131
|
+
from janito.agent.config import get_api_key
|
132
|
+
|
133
|
+
role = args.role or unified_config.get("role", "software engineer")
|
134
|
+
interaction_mode = "chat" if not getattr(args, "prompt", None) else "prompt"
|
135
|
+
profile = "base"
|
136
|
+
profile_manager = AgentProfileManager(
|
137
|
+
api_key=get_api_key(),
|
138
|
+
model=unified_config.get("model"),
|
139
|
+
)
|
140
|
+
system_prompt_val = profile_manager.get_system_prompt(
|
141
|
+
role, interaction_mode, profile
|
142
|
+
)
|
143
|
+
except Exception as e:
|
144
|
+
system_prompt_val = f"(error: {e})"
|
145
|
+
console = Console()
|
146
|
+
info_text = Text()
|
147
|
+
info_text.append(f"Janito v{__version__}", style="bold cyan")
|
148
|
+
info_text.append(" | model: ", style="white")
|
149
|
+
info_text.append(str(model), style="green")
|
150
|
+
info_text.append(" | temp: ", style="white")
|
151
|
+
info_text.append(str(temperature), style="yellow")
|
152
|
+
info_text.append(" | max_tokens: ", style="white")
|
153
|
+
info_text.append(str(max_tokens), style="magenta")
|
154
|
+
info_text.append(" | system: ", style="white")
|
155
|
+
info_text.append(str(system_prompt_val), style="bold blue")
|
156
|
+
console.print(info_text, style="dim")
|
157
|
+
|
158
|
+
|
15
159
|
def main():
|
16
160
|
"""Unified entry point for the Janito CLI and web server."""
|
17
161
|
import sys
|
18
|
-
|
19
162
|
from janito.agent.config import local_config, global_config
|
20
|
-
import janito.i18n as i18n
|
21
|
-
from janito.agent.runtime_config import runtime_config
|
22
163
|
|
23
164
|
local_config.load()
|
24
165
|
global_config.load()
|
25
|
-
|
26
166
|
parser = create_parser()
|
27
167
|
args = parser.parse_args()
|
28
|
-
|
29
|
-
# Handle --set-provider-config <name> <key> <value>
|
30
|
-
if getattr(args, "set_provider_config", None) is not None:
|
31
|
-
import os
|
32
|
-
import json
|
33
|
-
|
34
|
-
name, key, value = args.set_provider_config
|
35
|
-
config_dir = os.path.expanduser("~/.janito")
|
36
|
-
os.makedirs(config_dir, exist_ok=True)
|
37
|
-
providers_path = os.path.join(config_dir, "providers.json")
|
38
|
-
|
39
|
-
# Load or initialize providers config
|
40
|
-
if os.path.exists(providers_path):
|
41
|
-
with open(providers_path, "r", encoding="utf-8") as f:
|
42
|
-
try:
|
43
|
-
providers = json.load(f)
|
44
|
-
except Exception:
|
45
|
-
providers = {}
|
46
|
-
else:
|
47
|
-
providers = {}
|
48
|
-
|
49
|
-
if name not in providers or not isinstance(providers[name], dict):
|
50
|
-
providers[name] = {}
|
51
|
-
providers[name][key] = value
|
52
|
-
|
53
|
-
with open(providers_path, "w", encoding="utf-8") as f:
|
54
|
-
json.dump(providers, f, indent=2)
|
55
|
-
|
56
|
-
print(f"Set {key} for provider '{name}' in {providers_path}.")
|
57
|
-
sys.exit(0)
|
58
|
-
|
59
168
|
# Handle --list [n] before anything else
|
60
169
|
if getattr(args, "list", None) is not None:
|
61
|
-
|
62
|
-
import glob
|
63
|
-
|
64
|
-
n = args.list if args.list is not None else 10
|
65
|
-
history_dir = os.path.join(os.path.expanduser(".janito"), "chat_history")
|
66
|
-
if not os.path.exists(history_dir):
|
67
|
-
print("No session history found.")
|
170
|
+
if handle_list_sessions(args):
|
68
171
|
sys.exit(0)
|
69
|
-
files = glob.glob(os.path.join(history_dir, "*.json"))
|
70
|
-
files = sorted(files, key=os.path.getmtime, reverse=True)
|
71
|
-
print(f"Last {n} sessions:")
|
72
|
-
for f in files[:n]:
|
73
|
-
session_id = os.path.splitext(os.path.basename(f))[0]
|
74
|
-
print(session_id)
|
75
|
-
sys.exit(0)
|
76
|
-
|
77
172
|
# Handle --view <id> to print conversation history
|
78
173
|
if getattr(args, "view", None) is not None:
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
history_dir = os.path.join(os.path.expanduser(".janito"), "chat_history")
|
83
|
-
session_file = os.path.join(history_dir, f"{args.view}.json")
|
84
|
-
if not os.path.exists(session_file):
|
85
|
-
print(f"Session '{args.view}' not found.")
|
86
|
-
sys.exit(1)
|
87
|
-
with open(session_file, "r", encoding="utf-8") as f:
|
88
|
-
try:
|
89
|
-
messages = json.load(f)
|
90
|
-
except Exception as e:
|
91
|
-
print(f"Failed to load session: {e}")
|
92
|
-
sys.exit(1)
|
93
|
-
print(f"Conversation history for session '{args.view}':\n")
|
94
|
-
for i, msg in enumerate(messages, 1):
|
95
|
-
role = msg.get("role", "?")
|
96
|
-
content = msg.get("content", "")
|
97
|
-
print(f"[{i}] {role}: {content}\n")
|
98
|
-
sys.exit(0)
|
99
|
-
|
100
|
-
# Seleção de idioma: prioridade --lang > config.json > padrão
|
101
|
-
lang = getattr(args, "lang", None) or unified_config.get("lang", None) or "en"
|
102
|
-
runtime_config.set("lang", lang)
|
103
|
-
i18n.set_locale(lang)
|
104
|
-
|
105
|
-
from janito.agent.config import CONFIG_OPTIONS
|
106
|
-
from janito.agent.config_defaults import CONFIG_DEFAULTS
|
107
|
-
|
174
|
+
sys.exit(handle_view_session(args))
|
175
|
+
handle_lang_selection(args)
|
108
176
|
if getattr(args, "help_config", False):
|
109
|
-
|
110
|
-
for key, desc in CONFIG_OPTIONS.items():
|
111
|
-
default = CONFIG_DEFAULTS.get(key, None)
|
112
|
-
print(
|
113
|
-
tr(
|
114
|
-
"{key:15} {desc} (default: {default})",
|
115
|
-
key=key,
|
116
|
-
desc=desc,
|
117
|
-
default=default,
|
118
|
-
)
|
119
|
-
)
|
177
|
+
handle_help_config(args)
|
120
178
|
sys.exit(0)
|
121
|
-
|
122
179
|
if getattr(args, "list_tools", False):
|
123
|
-
|
124
|
-
from rich.console import Console
|
125
|
-
from rich.table import Table
|
126
|
-
|
127
|
-
console = Console()
|
128
|
-
table = Table(
|
129
|
-
title="Ferramentas Registradas", show_lines=True, style="bold magenta"
|
130
|
-
)
|
131
|
-
table.add_column("Gnome", style="cyan", no_wrap=True)
|
132
|
-
table.add_column("Descrição", style="green")
|
133
|
-
table.add_column("Parâmetros", style="yellow")
|
134
|
-
for schema in get_tool_schemas():
|
135
|
-
fn = schema["function"]
|
136
|
-
params = "\n".join(
|
137
|
-
[
|
138
|
-
f"[bold]{k}[/]: {v['type']}"
|
139
|
-
for k, v in fn["parameters"].get("properties", {}).items()
|
140
|
-
]
|
141
|
-
)
|
142
|
-
table.add_row(f"[b]{fn['name']}[/b]", fn["description"], params or "-")
|
143
|
-
console.print(table)
|
180
|
+
handle_list_tools(args)
|
144
181
|
sys.exit(0)
|
145
|
-
|
146
182
|
if getattr(args, "info", False):
|
147
|
-
|
148
|
-
from janito import __version__
|
149
|
-
from rich.console import Console
|
150
|
-
from rich.text import Text
|
151
|
-
from janito.agent.runtime_config import runtime_config
|
152
|
-
|
153
|
-
model = unified_config.get("model")
|
154
|
-
temperature = unified_config.get("temperature")
|
155
|
-
max_tokens = unified_config.get("max_tokens")
|
156
|
-
system_prompt_val = None
|
157
|
-
if getattr(args, "system_file", None):
|
158
|
-
try:
|
159
|
-
with open(args.system_file, "r", encoding="utf-8") as f:
|
160
|
-
system_prompt_val = f.read().strip()
|
161
|
-
runtime_config.set("system_prompt_template", system_prompt_val)
|
162
|
-
except Exception as e:
|
163
|
-
system_prompt_val = f"(error reading system-file: {e})"
|
164
|
-
elif getattr(args, "system", None):
|
165
|
-
system_prompt_val = args.system
|
166
|
-
runtime_config.set("system_prompt_template", system_prompt_val)
|
167
|
-
else:
|
168
|
-
system_prompt_val = runtime_config.get("system_prompt_template")
|
169
|
-
# if system_prompt_val:
|
170
|
-
# origem = "runtime_config"
|
171
|
-
if not system_prompt_val:
|
172
|
-
try:
|
173
|
-
from janito.agent.profile_manager import AgentProfileManager
|
174
|
-
from janito.agent.config import get_api_key
|
175
|
-
|
176
|
-
role = args.role or unified_config.get("role", "software engineer")
|
177
|
-
interaction_mode = (
|
178
|
-
"chat" if not getattr(args, "prompt", None) else "prompt"
|
179
|
-
)
|
180
|
-
profile = "base"
|
181
|
-
profile_manager = AgentProfileManager(
|
182
|
-
api_key=get_api_key(),
|
183
|
-
model=unified_config.get("model"),
|
184
|
-
)
|
185
|
-
system_prompt_val = profile_manager.get_system_prompt(
|
186
|
-
role, interaction_mode, profile
|
187
|
-
)
|
188
|
-
except Exception as e:
|
189
|
-
system_prompt_val = f"(error: {e})"
|
190
|
-
|
191
|
-
console = Console()
|
192
|
-
info_text = Text()
|
193
|
-
info_text.append(f"Janito v{__version__}", style="bold cyan")
|
194
|
-
info_text.append(" | model: ", style="white")
|
195
|
-
info_text.append(str(model), style="green")
|
196
|
-
info_text.append(" | temp: ", style="white")
|
197
|
-
info_text.append(str(temperature), style="yellow")
|
198
|
-
info_text.append(" | max_tokens: ", style="white")
|
199
|
-
info_text.append(str(max_tokens), style="magenta")
|
200
|
-
info_text.append(" | system: ", style="white")
|
201
|
-
info_text.append(str(system_prompt_val), style="bold blue")
|
202
|
-
console.print(info_text, style="dim")
|
203
|
-
# Previously: sys.exit(0) would exit after showing info. Now, program continues after displaying info.
|
204
|
-
|
205
|
-
# ... resto do main ...
|
183
|
+
handle_info(args)
|
206
184
|
handle_config_commands(args)
|
207
185
|
setup_verbose_logging(args)
|
208
186
|
if getattr(args, "web", False):
|
209
|
-
import subprocess
|
187
|
+
import subprocess
|
210
188
|
|
211
189
|
subprocess.run([sys.executable, "-m", "janito.web"])
|
212
190
|
elif getattr(args, "live", False):
|
213
|
-
port = 35729
|
191
|
+
port = 35729
|
214
192
|
livereload_proc, started, livereload_stdout_path, livereload_stderr_path = (
|
215
193
|
start_livereload(port)
|
216
194
|
)
|
janito/cli/one_shot.py
CHANGED
@@ -3,15 +3,12 @@ from janito.agent.conversation_exceptions import (
|
|
3
3
|
ProviderError,
|
4
4
|
EmptyResponseError,
|
5
5
|
)
|
6
|
+
from janito.agent.api_exceptions import ApiError
|
7
|
+
from janito.agent.llm_conversation_history import LLMConversationHistory
|
6
8
|
|
7
9
|
|
8
|
-
def
|
10
|
+
def prepare_messages(args, profile_manager, runtime_config):
|
9
11
|
prompt = getattr(args, "input_arg", None)
|
10
|
-
from rich.console import Console
|
11
|
-
from janito.agent.rich_message_handler import RichMessageHandler
|
12
|
-
|
13
|
-
console = Console()
|
14
|
-
message_handler = RichMessageHandler()
|
15
12
|
messages = []
|
16
13
|
system_prompt_override = runtime_config.get("system_prompt_template")
|
17
14
|
if system_prompt_override:
|
@@ -26,41 +23,58 @@ def run_oneshot_mode(args, profile_manager, runtime_config):
|
|
26
23
|
{"role": "system", "content": profile_manager.system_prompt_template}
|
27
24
|
)
|
28
25
|
messages.append({"role": "user", "content": prompt})
|
26
|
+
return messages
|
27
|
+
|
28
|
+
|
29
|
+
def print_usage_info(args, info_start_time, result, console):
|
30
|
+
if (
|
31
|
+
getattr(args, "info", False)
|
32
|
+
and info_start_time is not None
|
33
|
+
and result is not None
|
34
|
+
):
|
35
|
+
usage_info = result.get("usage")
|
36
|
+
total_tokens = usage_info.get("total_tokens") if usage_info else None
|
37
|
+
prompt_tokens = usage_info.get("prompt_tokens") if usage_info else None
|
38
|
+
completion_tokens = usage_info.get("completion_tokens") if usage_info else None
|
39
|
+
elapsed = time.time() - info_start_time
|
40
|
+
console.print(
|
41
|
+
f"[bold green]Total tokens:[/] [yellow]{total_tokens}[/yellow] [bold green]| Input:[/] [cyan]{prompt_tokens}[/cyan] [bold green]| Output:[/] [magenta]{completion_tokens}[/magenta] [bold green]| Elapsed:[/] [yellow]{elapsed:.2f}s[/yellow]",
|
42
|
+
style="dim",
|
43
|
+
)
|
44
|
+
|
45
|
+
|
46
|
+
def run_oneshot_mode(args, profile_manager, runtime_config):
|
47
|
+
from rich.console import Console
|
48
|
+
from janito.agent.rich_message_handler import RichMessageHandler
|
29
49
|
import time
|
30
50
|
|
51
|
+
console = Console()
|
52
|
+
message_handler = RichMessageHandler()
|
53
|
+
messages = prepare_messages(args, profile_manager, runtime_config)
|
31
54
|
info_start_time = None
|
32
55
|
if getattr(args, "info", False):
|
33
56
|
info_start_time = time.time()
|
34
57
|
try:
|
35
58
|
max_rounds = 100
|
36
|
-
from janito.agent.conversation_history import ConversationHistory
|
37
|
-
|
38
59
|
result = profile_manager.agent.chat(
|
39
|
-
|
60
|
+
LLMConversationHistory(messages),
|
40
61
|
message_handler=message_handler,
|
41
62
|
spinner=True,
|
42
63
|
max_rounds=max_rounds,
|
43
|
-
stream=getattr(args, "stream", False),
|
44
64
|
)
|
45
|
-
|
46
|
-
getattr(args, "info", False)
|
47
|
-
and info_start_time is not None
|
48
|
-
and result is not None
|
49
|
-
):
|
50
|
-
usage_info = result.get("usage")
|
51
|
-
total_tokens = usage_info.get("total_tokens") if usage_info else None
|
52
|
-
prompt_tokens = usage_info.get("prompt_tokens") if usage_info else None
|
53
|
-
completion_tokens = (
|
54
|
-
usage_info.get("completion_tokens") if usage_info else None
|
55
|
-
)
|
56
|
-
elapsed = time.time() - info_start_time
|
57
|
-
console.print(
|
58
|
-
f"[bold green]Total tokens:[/] [yellow]{total_tokens}[/yellow] [bold green]| Input:[/] [cyan]{prompt_tokens}[/cyan] [bold green]| Output:[/] [magenta]{completion_tokens}[/magenta] [bold green]| Elapsed:[/] [yellow]{elapsed:.2f}s[/yellow]",
|
59
|
-
style="dim",
|
60
|
-
)
|
65
|
+
print_usage_info(args, info_start_time, result, console)
|
61
66
|
except MaxRoundsExceededError:
|
62
67
|
console.print("[red]Max conversation rounds exceeded.[/red]")
|
63
68
|
except ProviderError as e:
|
64
69
|
console.print(f"[red]Provider error:[/red] {e}")
|
65
70
|
except EmptyResponseError as e:
|
66
71
|
console.print(f"[red]Error:[/red] {e}")
|
72
|
+
except ApiError as e:
|
73
|
+
if "maximum context length" in str(e):
|
74
|
+
console.print(
|
75
|
+
f"[red]Error:[/red] {e}\n[bold yellow]Tip:[/] Try using [green]--max-tokens[/green] with a lower value."
|
76
|
+
)
|
77
|
+
else:
|
78
|
+
console.print(f"[red]API error:[/red] {e}")
|
79
|
+
except Exception:
|
80
|
+
raise
|
janito/i18n/__init__.py
CHANGED
@@ -23,7 +23,7 @@ def set_locale(locale):
|
|
23
23
|
|
24
24
|
def tr(msg, **kwargs):
|
25
25
|
"""Translate message to current locale, usando hash SHA-1 da mensagem como chave."""
|
26
|
-
msg_hash = hashlib.sha1(msg.encode("utf-8")).hexdigest()
|
26
|
+
msg_hash = hashlib.sha1(msg.encode("utf-8", errors="surrogatepass")).hexdigest()
|
27
27
|
template = _translations.get(msg_hash, msg)
|
28
28
|
try:
|
29
29
|
return template.format(**kwargs)
|
janito/rich_utils.py
CHANGED
@@ -3,19 +3,57 @@ Utilities for working with the Rich library.
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
from rich.console import Console
|
6
|
+
from typing import Optional
|
6
7
|
|
7
8
|
|
8
|
-
|
9
|
-
|
9
|
+
class RichPrinter:
|
10
|
+
"""
|
11
|
+
Utility class for printing styled messages using the Rich library.
|
10
12
|
|
13
|
+
Args:
|
14
|
+
console (Optional[Console]): An optional Rich Console instance. If not provided, a default Console will be created.
|
11
15
|
|
12
|
-
|
13
|
-
|
16
|
+
Methods:
|
17
|
+
print_info(message: str)
|
18
|
+
Print an informational message in cyan (no newline at end).
|
14
19
|
|
20
|
+
print_error(message: str)
|
21
|
+
Print an error message in bold red.
|
15
22
|
|
16
|
-
|
17
|
-
|
23
|
+
print_warning(message: str)
|
24
|
+
Print a warning message in bold yellow.
|
18
25
|
|
26
|
+
print_magenta(message: str)
|
27
|
+
Print a message in magenta.
|
28
|
+
"""
|
19
29
|
|
20
|
-
def
|
21
|
-
|
30
|
+
def __init__(self, console: Optional[Console] = None):
|
31
|
+
self.console = console or Console()
|
32
|
+
|
33
|
+
def print_info(self, message: str):
|
34
|
+
self.console.print(message, style="cyan", end="")
|
35
|
+
|
36
|
+
def print_error(self, message: str):
|
37
|
+
self.console.print(message, style="bold red", end="\n")
|
38
|
+
|
39
|
+
def print_warning(self, message: str):
|
40
|
+
self.console.print(message, style="bold yellow", end="\n")
|
41
|
+
|
42
|
+
def print_magenta(self, message: str):
|
43
|
+
self.console.print(message, style="magenta", end="\n")
|
44
|
+
|
45
|
+
def print_colored_message(self, message: str, color_index: int = 0):
|
46
|
+
"""
|
47
|
+
Print a message with a cycling background color for verbose-messages.
|
48
|
+
"""
|
49
|
+
bg_colors = [
|
50
|
+
"on blue",
|
51
|
+
"on green",
|
52
|
+
"on magenta",
|
53
|
+
"on cyan",
|
54
|
+
"on yellow",
|
55
|
+
"on red",
|
56
|
+
"on bright_black",
|
57
|
+
]
|
58
|
+
style = f"bold white {bg_colors[color_index % len(bg_colors)]}"
|
59
|
+
self.console.print(message, style=style, end="\n")
|
@@ -6,14 +6,13 @@ from .utility import handle_help, handle_clear, handle_multi
|
|
6
6
|
from .tools import handle_tools
|
7
7
|
from .termweb_log import handle_termweb_log_tail, handle_termweb_status
|
8
8
|
from .livelogs import handle_livelogs
|
9
|
-
from .sum import handle_sum
|
10
9
|
from .edit import handle_edit
|
11
|
-
|
12
10
|
from .history_view import handle_view
|
13
11
|
from janito.shell.session.config import handle_config_shell
|
14
12
|
from .verbose import handle_verbose
|
15
13
|
from .lang import handle_lang
|
16
14
|
from janito.agent.runtime_config import runtime_config
|
15
|
+
from .track import handle_track
|
17
16
|
|
18
17
|
COMMAND_HANDLERS = {
|
19
18
|
"/termweb-logs": handle_termweb_log_tail,
|
@@ -35,12 +34,11 @@ COMMAND_HANDLERS = {
|
|
35
34
|
if not runtime_config.get("vanilla_mode", False):
|
36
35
|
COMMAND_HANDLERS["/role"] = handle_role
|
37
36
|
|
38
|
-
|
39
37
|
COMMAND_HANDLERS["/lang"] = handle_lang
|
38
|
+
COMMAND_HANDLERS["/track"] = handle_track
|
40
39
|
|
41
40
|
COMMAND_HANDLERS.update(
|
42
41
|
{
|
43
|
-
"/sum": handle_sum,
|
44
42
|
"/clear": handle_clear,
|
45
43
|
"/restart": handle_restart,
|
46
44
|
"/config": handle_config_shell,
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import os
|
2
2
|
|
3
|
-
|
4
3
|
from janito.shell.session.manager import reset_session_id
|
5
4
|
|
6
5
|
|
@@ -70,3 +69,6 @@ def handle_restart(console, shell_state=None, **kwargs):
|
|
70
69
|
console.print(
|
71
70
|
"[bold green]Conversation history has been started (context reset).[/bold green]"
|
72
71
|
)
|
72
|
+
|
73
|
+
|
74
|
+
handle_restart.help_text = "Start a new conversation (reset context)"
|
janito/shell/commands/edit.py
CHANGED
@@ -1,7 +1,4 @@
|
|
1
1
|
def handle_view(console, args=None, shell_state=None, **kwargs):
|
2
|
-
"""
|
3
|
-
Prints the current LLM conversation history in a readable format.
|
4
|
-
"""
|
5
2
|
messages = shell_state.conversation_history.get_messages()
|
6
3
|
if not messages:
|
7
4
|
console.print("[yellow]Conversation history is empty.[/yellow]")
|
@@ -16,3 +13,6 @@ def handle_view(console, args=None, shell_state=None, **kwargs):
|
|
16
13
|
console.print(f" [cyan]tool_calls:[/cyan] {tool_calls}")
|
17
14
|
if tool_call_id:
|
18
15
|
console.print(f" [magenta]tool_call_id:[/magenta] {tool_call_id}")
|
16
|
+
|
17
|
+
|
18
|
+
handle_view.help_text = "Print the current LLM conversation history"
|
janito/shell/commands/lang.py
CHANGED
@@ -1,7 +1,4 @@
|
|
1
1
|
def handle_livelogs(console, args=None, shell_state=None, **kwargs):
|
2
|
-
"""
|
3
|
-
/livelogs [N] - Show the last N lines of the livereload server logs (default: 20)
|
4
|
-
"""
|
5
2
|
lines = 20
|
6
3
|
if args and len(args) > 0 and str(args[0]).isdigit():
|
7
4
|
lines = int(args[0])
|
@@ -38,3 +35,8 @@ def handle_livelogs(console, args=None, shell_state=None, **kwargs):
|
|
38
35
|
console.print(f"[red][livereload][stderr] Error: {e}[/red]")
|
39
36
|
if (not stdout_path or not stdout_lines) and (not stderr_path or not stderr_lines):
|
40
37
|
console.print("[livereload] No output or errors captured in logs.")
|
38
|
+
|
39
|
+
|
40
|
+
handle_livelogs.help_text = (
|
41
|
+
"Show live updates from the server log file (default: server.log)"
|
42
|
+
)
|
janito/shell/commands/prompt.py
CHANGED
@@ -9,6 +9,9 @@ def handle_prompt(console, shell_state=None, **kwargs):
|
|
9
9
|
console.print(f"[bold magenta]System Prompt:[/bold magenta]\n{prompt}")
|
10
10
|
|
11
11
|
|
12
|
+
handle_prompt.help_text = "Show the system prompt"
|
13
|
+
|
14
|
+
|
12
15
|
def handle_role(console, args=None, shell_state=None, **kwargs):
|
13
16
|
profile_manager = (
|
14
17
|
shell_state.profile_manager
|
@@ -40,6 +43,9 @@ def handle_role(console, args=None, shell_state=None, **kwargs):
|
|
40
43
|
console.print(f"[bold green]System role updated to:[/bold green] {new_role}")
|
41
44
|
|
42
45
|
|
46
|
+
handle_role.help_text = "Change the system role"
|
47
|
+
|
48
|
+
|
43
49
|
def handle_profile(console, *args, **kwargs):
|
44
50
|
"""/profile - Show the current and available Agent Profile (only 'base' is supported)"""
|
45
51
|
console.print("[bold green]Current profile:[/bold green] base")
|
janito/shell/commands/session.py
CHANGED
@@ -51,6 +51,9 @@ def handle_termweb_log_tail(console: Console, *args, shell_state=None, **kwargs)
|
|
51
51
|
console.print("[termweb] No output or errors captured in logs.")
|
52
52
|
|
53
53
|
|
54
|
+
handle_termweb_log_tail.help_text = "Show the last lines of the latest termweb logs"
|
55
|
+
|
56
|
+
|
54
57
|
def handle_termweb_status(console: Console, *args, shell_state=None, **kwargs):
|
55
58
|
if shell_state is None:
|
56
59
|
console.print(
|
@@ -84,3 +87,8 @@ def handle_termweb_status(console: Console, *args, shell_state=None, **kwargs):
|
|
84
87
|
console.print(f" Stdout log: {stdout_path}")
|
85
88
|
if stderr_path:
|
86
89
|
console.print(f" Stderr log: {stderr_path}")
|
90
|
+
|
91
|
+
|
92
|
+
handle_termweb_status.help_text = (
|
93
|
+
"Show status information about the running termweb server"
|
94
|
+
)
|