janito 1.8.0__py3-none-any.whl → 1.9.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/config_defaults.py +23 -0
- janito/agent/config_utils.py +0 -9
- janito/agent/conversation.py +31 -9
- janito/agent/conversation_api.py +32 -2
- janito/agent/conversation_history.py +53 -0
- janito/agent/conversation_tool_calls.py +11 -8
- janito/agent/openai_client.py +11 -3
- janito/agent/openai_schema_generator.py +9 -6
- janito/agent/providers.py +77 -0
- janito/agent/rich_message_handler.py +1 -1
- janito/agent/templates/profiles/system_prompt_template_base.txt.j2 +8 -8
- janito/agent/tool_executor.py +18 -10
- janito/agent/tool_use_tracker.py +16 -0
- janito/agent/tools/__init__.py +7 -9
- janito/agent/tools/create_directory.py +7 -6
- janito/agent/tools/create_file.py +29 -54
- janito/agent/tools/delete_text_in_file.py +97 -0
- janito/agent/tools/fetch_url.py +11 -3
- janito/agent/tools/find_files.py +37 -25
- janito/agent/tools/get_file_outline/__init__.py +1 -0
- janito/agent/tools/{outline_file/__init__.py → get_file_outline/core.py} +12 -15
- janito/agent/tools/get_file_outline/python_outline.py +134 -0
- janito/agent/tools/{search_outline.py → get_file_outline/search_outline.py} +9 -0
- janito/agent/tools/get_lines.py +15 -11
- janito/agent/tools/move_file.py +10 -11
- janito/agent/tools/remove_directory.py +2 -2
- janito/agent/tools/remove_file.py +11 -13
- janito/agent/tools/replace_file.py +62 -0
- janito/agent/tools/replace_text_in_file.py +3 -3
- janito/agent/tools/run_bash_command.py +3 -7
- janito/agent/tools/run_powershell_command.py +39 -28
- janito/agent/tools/run_python_command.py +3 -5
- janito/agent/tools/search_text.py +10 -14
- janito/agent/tools/validate_file_syntax/__init__.py +1 -0
- janito/agent/tools/validate_file_syntax/core.py +92 -0
- janito/agent/tools/validate_file_syntax/css_validator.py +35 -0
- janito/agent/tools/validate_file_syntax/html_validator.py +77 -0
- janito/agent/tools/validate_file_syntax/js_validator.py +27 -0
- janito/agent/tools/validate_file_syntax/json_validator.py +6 -0
- janito/agent/tools/validate_file_syntax/markdown_validator.py +66 -0
- janito/agent/tools/validate_file_syntax/ps1_validator.py +32 -0
- janito/agent/tools/validate_file_syntax/python_validator.py +5 -0
- janito/agent/tools/validate_file_syntax/xml_validator.py +11 -0
- janito/agent/tools/validate_file_syntax/yaml_validator.py +6 -0
- janito/agent/tools_utils/__init__.py +1 -0
- janito/agent/tools_utils/dir_walk_utils.py +23 -0
- janito/agent/{tools/outline_file → tools_utils}/formatting.py +5 -2
- janito/agent/{tools → tools_utils}/gitignore_utils.py +0 -3
- janito/agent/tools_utils/utils.py +30 -0
- janito/cli/_livereload_log_utils.py +13 -0
- janito/cli/arg_parser.py +45 -3
- janito/cli/{runner/cli_main.py → cli_main.py} +120 -20
- janito/cli/livereload_starter.py +60 -0
- janito/cli/main.py +110 -21
- janito/cli/one_shot.py +66 -0
- janito/cli/termweb_starter.py +2 -2
- janito/livereload/app.py +25 -0
- janito/rich_utils.py +0 -22
- janito/{cli_chat_shell → shell}/commands/__init__.py +18 -11
- janito/{cli_chat_shell → shell}/commands/config.py +4 -4
- janito/shell/commands/conversation_restart.py +72 -0
- janito/shell/commands/edit.py +21 -0
- janito/shell/commands/history_view.py +18 -0
- janito/shell/commands/livelogs.py +40 -0
- janito/{cli_chat_shell → shell}/commands/prompt.py +10 -6
- janito/shell/commands/session.py +32 -0
- janito/{cli_chat_shell → shell}/commands/session_control.py +2 -7
- janito/{cli_chat_shell → shell}/commands/sum.py +6 -6
- janito/{cli_chat_shell → shell}/commands/termweb_log.py +10 -10
- janito/shell/commands/tools.py +23 -0
- janito/{cli_chat_shell → shell}/commands/utility.py +5 -4
- janito/{cli_chat_shell → shell}/commands/verbose.py +1 -1
- janito/shell/commands.py +40 -0
- janito/shell/main.py +321 -0
- janito/{cli_chat_shell/shell_command_completer.py → shell/prompt/completer.py} +1 -1
- janito/{cli_chat_shell/chat_ui.py → shell/prompt/session_setup.py} +19 -5
- janito/{cli_chat_shell/session_manager.py → shell/session/manager.py} +53 -3
- janito/{cli_chat_shell/ui.py → shell/ui/interactive.py} +23 -15
- janito/termweb/app.py +3 -3
- janito/termweb/static/editor.css +146 -0
- janito/termweb/static/editor.css.bak +27 -0
- janito/termweb/static/editor.html +15 -213
- janito/termweb/static/editor.html.bak +16 -215
- janito/termweb/static/editor.js +209 -0
- janito/termweb/static/editor.js.bak +227 -0
- janito/termweb/static/index.html +2 -3
- janito/termweb/static/index.html.bak +2 -3
- janito/termweb/static/termweb.css.bak +33 -84
- janito/termweb/static/termweb.js +15 -34
- janito/termweb/static/termweb.js.bak +18 -36
- {janito-1.8.0.dist-info → janito-1.9.0.dist-info}/METADATA +6 -3
- janito-1.9.0.dist-info/RECORD +151 -0
- {janito-1.8.0.dist-info → janito-1.9.0.dist-info}/WHEEL +1 -1
- janito/agent/tools/dir_walk_utils.py +0 -16
- janito/agent/tools/memory.py +0 -48
- janito/agent/tools/outline_file/python_outline.py +0 -71
- janito/agent/tools/present_choices_test.py +0 -18
- janito/agent/tools/rich_live.py +0 -44
- janito/agent/tools/tools_utils.py +0 -56
- janito/agent/tools/utils.py +0 -33
- janito/agent/tools/validate_file_syntax.py +0 -163
- janito/cli_chat_shell/chat_loop.py +0 -163
- janito/cli_chat_shell/chat_state.py +0 -38
- janito/cli_chat_shell/commands/history_start.py +0 -37
- janito/cli_chat_shell/commands/session.py +0 -48
- janito-1.8.0.dist-info/RECORD +0 -127
- /janito/agent/tools/{outline_file → get_file_outline}/markdown_outline.py +0 -0
- /janito/cli/{runner/_termweb_log_utils.py → _termweb_log_utils.py} +0 -0
- /janito/cli/{runner/config.py → config_runner.py} +0 -0
- /janito/cli/{runner/formatting.py → formatting_runner.py} +0 -0
- /janito/{cli/runner → shell}/__init__.py +0 -0
- /janito/{cli_chat_shell → shell}/commands/lang.py +0 -0
- /janito/{cli_chat_shell → shell/prompt}/load_prompt.py +0 -0
- /janito/{cli_chat_shell/config_shell.py → shell/session/config.py} +0 -0
- /janito/{cli_chat_shell/__init__.py → shell/session/history.py} +0 -0
- {janito-1.8.0.dist-info → janito-1.9.0.dist-info}/entry_points.txt +0 -0
- {janito-1.8.0.dist-info → janito-1.9.0.dist-info}/licenses/LICENSE +0 -0
- {janito-1.8.0.dist-info → janito-1.9.0.dist-info}/top_level.txt +0 -0
janito/cli/main.py
CHANGED
@@ -3,8 +3,9 @@
|
|
3
3
|
from janito.cli.arg_parser import create_parser
|
4
4
|
from janito.cli.config_commands import handle_config_commands
|
5
5
|
from janito.cli.logging_setup import setup_verbose_logging
|
6
|
-
from janito.cli.
|
6
|
+
from janito.cli.cli_main import run_cli
|
7
7
|
from janito.agent.runtime_config import unified_config
|
8
|
+
from janito.cli.livereload_starter import start_livereload
|
8
9
|
|
9
10
|
# Ensure all tools are registered at startup
|
10
11
|
import janito.agent.tools # noqa: F401
|
@@ -25,6 +26,77 @@ def main():
|
|
25
26
|
parser = create_parser()
|
26
27
|
args = parser.parse_args()
|
27
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
|
+
# Handle --list [n] before anything else
|
60
|
+
if getattr(args, "list", None) is not None:
|
61
|
+
import os
|
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.")
|
68
|
+
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
|
+
# Handle --view <id> to print conversation history
|
78
|
+
if getattr(args, "view", None) is not None:
|
79
|
+
import os
|
80
|
+
import json
|
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
|
+
|
28
100
|
# Seleção de idioma: prioridade --lang > config.json > padrão
|
29
101
|
lang = getattr(args, "lang", None) or unified_config.get("lang", None) or "en"
|
30
102
|
runtime_config.set("lang", lang)
|
@@ -72,37 +144,31 @@ def main():
|
|
72
144
|
sys.exit(0)
|
73
145
|
|
74
146
|
if getattr(args, "info", False):
|
75
|
-
#
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
print(f"Temperatura: {unified_config.get('temperature')}")
|
80
|
-
print(f"Max tokens: {unified_config.get('max_tokens')}")
|
81
|
-
# System prompt real via AgentProfileManager
|
82
|
-
# Prioridade: --system-file > --system > AgentProfileManager
|
147
|
+
# Compact, colored, single-line info output using rich
|
148
|
+
from janito import __version__
|
149
|
+
from rich.console import Console
|
150
|
+
from rich.text import Text
|
83
151
|
from janito.agent.runtime_config import runtime_config
|
84
152
|
|
153
|
+
model = unified_config.get("model")
|
154
|
+
temperature = unified_config.get("temperature")
|
155
|
+
max_tokens = unified_config.get("max_tokens")
|
85
156
|
system_prompt_val = None
|
86
|
-
origem = None
|
87
157
|
if getattr(args, "system_file", None):
|
88
158
|
try:
|
89
159
|
with open(args.system_file, "r", encoding="utf-8") as f:
|
90
160
|
system_prompt_val = f.read().strip()
|
91
161
|
runtime_config.set("system_prompt_template", system_prompt_val)
|
92
|
-
origem = "--system-file"
|
93
162
|
except Exception as e:
|
94
|
-
|
163
|
+
system_prompt_val = f"(error reading system-file: {e})"
|
95
164
|
elif getattr(args, "system", None):
|
96
165
|
system_prompt_val = args.system
|
97
166
|
runtime_config.set("system_prompt_template", system_prompt_val)
|
98
|
-
origem = "--system"
|
99
167
|
else:
|
100
168
|
system_prompt_val = runtime_config.get("system_prompt_template")
|
101
|
-
if system_prompt_val:
|
102
|
-
|
103
|
-
if system_prompt_val:
|
104
|
-
print(f"System prompt ({origem or 'runtime_config'}): {system_prompt_val}")
|
105
|
-
else:
|
169
|
+
# if system_prompt_val:
|
170
|
+
# origem = "runtime_config"
|
171
|
+
if not system_prompt_val:
|
106
172
|
try:
|
107
173
|
from janito.agent.profile_manager import AgentProfileManager
|
108
174
|
from janito.agent.config import get_api_key
|
@@ -119,10 +185,22 @@ def main():
|
|
119
185
|
system_prompt_val = profile_manager.get_system_prompt(
|
120
186
|
role, interaction_mode, profile
|
121
187
|
)
|
122
|
-
print(f"System prompt (profile_manager): {system_prompt_val}")
|
123
188
|
except Exception as e:
|
124
|
-
|
125
|
-
|
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.
|
126
204
|
|
127
205
|
# ... resto do main ...
|
128
206
|
handle_config_commands(args)
|
@@ -131,5 +209,16 @@ def main():
|
|
131
209
|
import subprocess # Only needed if launching web
|
132
210
|
|
133
211
|
subprocess.run([sys.executable, "-m", "janito.web"])
|
212
|
+
elif getattr(args, "live", False):
|
213
|
+
port = 35729 # Default livereload port
|
214
|
+
livereload_proc, started, livereload_stdout_path, livereload_stderr_path = (
|
215
|
+
start_livereload(port)
|
216
|
+
)
|
217
|
+
try:
|
218
|
+
run_cli(args)
|
219
|
+
finally:
|
220
|
+
if livereload_proc:
|
221
|
+
livereload_proc.terminate()
|
222
|
+
livereload_proc.wait()
|
134
223
|
else:
|
135
224
|
run_cli(args)
|
janito/cli/one_shot.py
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
from janito.agent.conversation_exceptions import (
|
2
|
+
MaxRoundsExceededError,
|
3
|
+
ProviderError,
|
4
|
+
EmptyResponseError,
|
5
|
+
)
|
6
|
+
|
7
|
+
|
8
|
+
def run_oneshot_mode(args, profile_manager, runtime_config):
|
9
|
+
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
|
+
messages = []
|
16
|
+
system_prompt_override = runtime_config.get("system_prompt_template")
|
17
|
+
if system_prompt_override:
|
18
|
+
if not runtime_config.get("vanilla_mode", False) or getattr(
|
19
|
+
args, "system", None
|
20
|
+
):
|
21
|
+
messages.append({"role": "system", "content": system_prompt_override})
|
22
|
+
elif profile_manager.system_prompt_template and not runtime_config.get(
|
23
|
+
"vanilla_mode", False
|
24
|
+
):
|
25
|
+
messages.append(
|
26
|
+
{"role": "system", "content": profile_manager.system_prompt_template}
|
27
|
+
)
|
28
|
+
messages.append({"role": "user", "content": prompt})
|
29
|
+
import time
|
30
|
+
|
31
|
+
info_start_time = None
|
32
|
+
if getattr(args, "info", False):
|
33
|
+
info_start_time = time.time()
|
34
|
+
try:
|
35
|
+
max_rounds = 100
|
36
|
+
from janito.agent.conversation_history import ConversationHistory
|
37
|
+
|
38
|
+
result = profile_manager.agent.chat(
|
39
|
+
ConversationHistory(messages),
|
40
|
+
message_handler=message_handler,
|
41
|
+
spinner=True,
|
42
|
+
max_rounds=max_rounds,
|
43
|
+
stream=getattr(args, "stream", False),
|
44
|
+
)
|
45
|
+
if (
|
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
|
+
)
|
61
|
+
except MaxRoundsExceededError:
|
62
|
+
console.print("[red]Max conversation rounds exceeded.[/red]")
|
63
|
+
except ProviderError as e:
|
64
|
+
console.print(f"[red]Provider error:[/red] {e}")
|
65
|
+
except EmptyResponseError as e:
|
66
|
+
console.print(f"[red]Error:[/red] {e}")
|
janito/cli/termweb_starter.py
CHANGED
@@ -5,7 +5,7 @@ import time
|
|
5
5
|
import http.client
|
6
6
|
import os
|
7
7
|
from rich.console import Console
|
8
|
-
from janito.cli.
|
8
|
+
from janito.cli._termweb_log_utils import print_termweb_logs
|
9
9
|
from janito.i18n import tr
|
10
10
|
|
11
11
|
|
@@ -69,5 +69,5 @@ def start_termweb(selected_port):
|
|
69
69
|
console.print(
|
70
70
|
f"[red]Failed to start TermWeb on port {selected_port}. Check logs for details.[/red]"
|
71
71
|
)
|
72
|
-
print_termweb_logs(termweb_stdout.name, termweb_stderr.name)
|
72
|
+
print_termweb_logs(termweb_stdout.name, termweb_stderr.name, console)
|
73
73
|
return None, False, termweb_stdout.name, termweb_stderr.name
|
janito/livereload/app.py
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
import sys
|
2
|
+
import os
|
3
|
+
from livereload import Server
|
4
|
+
|
5
|
+
|
6
|
+
def main():
|
7
|
+
port = 35729 # Default livereload port
|
8
|
+
if "--port" in sys.argv:
|
9
|
+
idx = sys.argv.index("--port")
|
10
|
+
if idx + 1 < len(sys.argv):
|
11
|
+
try:
|
12
|
+
port = int(sys.argv[idx + 1])
|
13
|
+
except ValueError:
|
14
|
+
pass
|
15
|
+
watch_dir = os.path.abspath(os.getcwd())
|
16
|
+
server = Server()
|
17
|
+
server.watch(watch_dir, delay=1)
|
18
|
+
print(
|
19
|
+
f"Starting livereload server on http://localhost:{port}, watching {watch_dir}"
|
20
|
+
)
|
21
|
+
server.serve(root=watch_dir, port=port, open_url_delay=None)
|
22
|
+
|
23
|
+
|
24
|
+
if __name__ == "__main__":
|
25
|
+
main()
|
janito/rich_utils.py
CHANGED
@@ -2,23 +2,13 @@
|
|
2
2
|
Utilities for working with the Rich library.
|
3
3
|
"""
|
4
4
|
|
5
|
-
from rich.markdown import Markdown
|
6
|
-
from rich.text import Text
|
7
5
|
from rich.console import Console
|
8
6
|
|
9
7
|
|
10
|
-
def print_markdown(console: Console, message: str):
|
11
|
-
console.print(Markdown(message))
|
12
|
-
|
13
|
-
|
14
8
|
def print_info(console: Console, message: str):
|
15
9
|
console.print(message, style="cyan", end="")
|
16
10
|
|
17
11
|
|
18
|
-
def print_success(console: Console, message: str):
|
19
|
-
console.print(message, style="bold green", end="\n")
|
20
|
-
|
21
|
-
|
22
12
|
def print_error(console: Console, message: str):
|
23
13
|
console.print(message, style="bold red", end="\n")
|
24
14
|
|
@@ -29,15 +19,3 @@ def print_warning(console: Console, message: str):
|
|
29
19
|
|
30
20
|
def print_magenta(console: Console, message: str):
|
31
21
|
console.print(message, style="magenta", end="\n")
|
32
|
-
|
33
|
-
|
34
|
-
def print_stdout(console: Console, message: str):
|
35
|
-
console.print(
|
36
|
-
Text(message, style="on #003300", no_wrap=True, overflow=None), end=""
|
37
|
-
)
|
38
|
-
|
39
|
-
|
40
|
-
def print_stderr(console: Console, message: str):
|
41
|
-
console.print(
|
42
|
-
Text(message, style="on #330000", no_wrap=True, overflow=None), end=""
|
43
|
-
)
|
@@ -1,27 +1,34 @@
|
|
1
|
-
from .session import
|
1
|
+
from .session import handle_history
|
2
2
|
from .prompt import handle_prompt, handle_role
|
3
|
-
from .session_control import handle_exit
|
3
|
+
from .session_control import handle_exit
|
4
|
+
from .conversation_restart import handle_restart
|
4
5
|
from .utility import handle_help, handle_clear, handle_multi
|
6
|
+
from .tools import handle_tools
|
5
7
|
from .termweb_log import handle_termweb_log_tail, handle_termweb_status
|
8
|
+
from .livelogs import handle_livelogs
|
6
9
|
from .sum import handle_sum
|
7
|
-
from .
|
8
|
-
|
9
|
-
from
|
10
|
+
from .edit import handle_edit
|
11
|
+
|
12
|
+
from .history_view import handle_view
|
13
|
+
from janito.shell.session.config import handle_config_shell
|
10
14
|
from .verbose import handle_verbose
|
11
15
|
from .lang import handle_lang
|
12
16
|
from janito.agent.runtime_config import runtime_config
|
13
17
|
|
14
18
|
COMMAND_HANDLERS = {
|
15
19
|
"/termweb-logs": handle_termweb_log_tail,
|
20
|
+
"/livelogs": handle_livelogs,
|
16
21
|
"/termweb-status": handle_termweb_status,
|
22
|
+
"/edit": handle_edit,
|
17
23
|
"/history": handle_history,
|
18
|
-
"/continue": handle_continue,
|
19
24
|
"/exit": handle_exit,
|
20
25
|
"exit": handle_exit,
|
21
26
|
"/restart": handle_restart,
|
27
|
+
"/start": handle_restart,
|
22
28
|
"/help": handle_help,
|
23
29
|
"/multi": handle_multi,
|
24
30
|
"/prompt": handle_prompt,
|
31
|
+
"/tools": handle_tools,
|
25
32
|
"/verbose": handle_verbose,
|
26
33
|
}
|
27
34
|
|
@@ -35,21 +42,21 @@ COMMAND_HANDLERS.update(
|
|
35
42
|
{
|
36
43
|
"/sum": handle_sum,
|
37
44
|
"/clear": handle_clear,
|
38
|
-
"/
|
45
|
+
"/restart": handle_restart,
|
39
46
|
"/config": handle_config_shell,
|
40
|
-
"/
|
47
|
+
"/view": handle_view,
|
41
48
|
}
|
42
49
|
)
|
43
50
|
|
44
51
|
|
45
|
-
def handle_command(command, console,
|
52
|
+
def handle_command(command, console, shell_state=None):
|
46
53
|
parts = command.strip().split()
|
47
54
|
cmd = parts[0]
|
48
55
|
args = parts[1:]
|
49
56
|
handler = COMMAND_HANDLERS.get(cmd)
|
50
57
|
if handler:
|
51
|
-
# Pass args as
|
52
|
-
return handler(console, args=args,
|
58
|
+
# Pass shell_state and args as keyword arguments for handlers that expect them
|
59
|
+
return handler(console, args=args, shell_state=shell_state)
|
53
60
|
console.print(
|
54
61
|
f"[bold red]Invalid command: {cmd}. Type /help for a list of commands.[/bold red]"
|
55
62
|
)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
def handle_reload(console, *args, **kwargs):
|
2
|
-
from
|
2
|
+
from janito.shell.prompt.load_prompt import load_prompt
|
3
3
|
|
4
4
|
agent = kwargs.get("agent")
|
5
5
|
state = kwargs.get("state")
|
@@ -9,9 +9,9 @@ def handle_reload(console, *args, **kwargs):
|
|
9
9
|
if hasattr(agent, "system_prompt_template"):
|
10
10
|
agent.system_prompt_template = prompt_text
|
11
11
|
# Update the first system message in the conversation if present
|
12
|
-
|
13
|
-
if
|
14
|
-
for msg in
|
12
|
+
history = state.get("history") if state else None
|
13
|
+
if history:
|
14
|
+
for msg in history:
|
15
15
|
if msg.get("role") == "system":
|
16
16
|
msg["content"] = prompt_text
|
17
17
|
break
|
@@ -0,0 +1,72 @@
|
|
1
|
+
import os
|
2
|
+
|
3
|
+
|
4
|
+
from janito.shell.session.manager import reset_session_id
|
5
|
+
|
6
|
+
|
7
|
+
def handle_restart(console, shell_state=None, **kwargs):
|
8
|
+
from janito.shell.session.manager import load_last_conversation, save_conversation
|
9
|
+
|
10
|
+
reset_session_id()
|
11
|
+
save_path = os.path.join(".janito", "last_conversation.json")
|
12
|
+
|
13
|
+
# --- Append end-of-conversation message to old history if it exists and is non-trivial ---
|
14
|
+
if os.path.exists(save_path):
|
15
|
+
try:
|
16
|
+
messages, prompts, usage = load_last_conversation(save_path)
|
17
|
+
if messages and (
|
18
|
+
len(messages) > 1
|
19
|
+
or (len(messages) == 1 and messages[0].get("role") != "system")
|
20
|
+
):
|
21
|
+
messages.append(
|
22
|
+
{"role": "system", "content": "[Session ended by user]"}
|
23
|
+
)
|
24
|
+
# Save to permanent chat history (let save_conversation pick session file)
|
25
|
+
save_conversation(messages, prompts, usage)
|
26
|
+
except Exception as e:
|
27
|
+
console.print(
|
28
|
+
f"[bold red]Failed to update previous conversation history:[/bold red] {e}"
|
29
|
+
)
|
30
|
+
|
31
|
+
# Clear the terminal screen
|
32
|
+
console.clear()
|
33
|
+
|
34
|
+
# Reset conversation history using its clear method
|
35
|
+
shell_state.conversation_history.clear()
|
36
|
+
|
37
|
+
# Reset tool use tracker
|
38
|
+
try:
|
39
|
+
from janito.agent.tool_use_tracker import ToolUseTracker
|
40
|
+
|
41
|
+
ToolUseTracker.instance().clear_history()
|
42
|
+
except Exception as e:
|
43
|
+
console.print(
|
44
|
+
f"[bold yellow]Warning: Failed to reset tool use tracker:[/bold yellow] {e}"
|
45
|
+
)
|
46
|
+
# Set system prompt from agent template if available
|
47
|
+
if (
|
48
|
+
hasattr(shell_state, "profile_manager")
|
49
|
+
and shell_state.profile_manager
|
50
|
+
and hasattr(shell_state.profile_manager, "agent")
|
51
|
+
and shell_state.profile_manager.agent
|
52
|
+
and getattr(shell_state.profile_manager.agent, "system_prompt_template", None)
|
53
|
+
and not any(
|
54
|
+
m.get("role") == "system"
|
55
|
+
for m in shell_state.conversation_history.get_messages()
|
56
|
+
)
|
57
|
+
):
|
58
|
+
shell_state.conversation_history.set_system_message(
|
59
|
+
shell_state.profile_manager.agent.system_prompt_template
|
60
|
+
)
|
61
|
+
|
62
|
+
# Reset token usage info in-place so all references (including status bar) are updated
|
63
|
+
for k in ("prompt_tokens", "completion_tokens", "total_tokens"):
|
64
|
+
if k in shell_state.last_usage_info:
|
65
|
+
shell_state.last_usage_info[k] = 0
|
66
|
+
else:
|
67
|
+
shell_state.last_usage_info[k] = 0
|
68
|
+
shell_state.last_elapsed = None
|
69
|
+
|
70
|
+
console.print(
|
71
|
+
"[bold green]Conversation history has been started (context reset).[/bold green]"
|
72
|
+
)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import os
|
2
|
+
import webbrowser
|
3
|
+
from janito.agent.runtime_config import runtime_config
|
4
|
+
|
5
|
+
|
6
|
+
def handle_edit(console, args=None, shell_state=None, **kwargs):
|
7
|
+
if not args or len(args) < 1:
|
8
|
+
console.print("[red]Usage: /edit <filename>[/red]")
|
9
|
+
return
|
10
|
+
filename = args[0]
|
11
|
+
if not os.path.isfile(filename):
|
12
|
+
console.print(f"[red]File not found:[/red] {filename}")
|
13
|
+
return
|
14
|
+
port = getattr(shell_state, "termweb_port", None) or runtime_config.get(
|
15
|
+
"termweb_port", 8080
|
16
|
+
)
|
17
|
+
url = f"http://localhost:{port}/?path={filename}"
|
18
|
+
console.print(
|
19
|
+
f"[green]Opening in browser:[/green] [underline blue]{url}[/underline blue]"
|
20
|
+
)
|
21
|
+
webbrowser.open(url)
|
@@ -0,0 +1,18 @@
|
|
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
|
+
messages = shell_state.conversation_history.get_messages()
|
6
|
+
if not messages:
|
7
|
+
console.print("[yellow]Conversation history is empty.[/yellow]")
|
8
|
+
return
|
9
|
+
for i, msg in enumerate(messages, 1):
|
10
|
+
role = msg.get("role", "?")
|
11
|
+
content = msg.get("content", "")
|
12
|
+
tool_calls = msg.get("tool_calls")
|
13
|
+
tool_call_id = msg.get("tool_call_id")
|
14
|
+
console.print(f"[bold]{i}. {role}:[/bold] {content}")
|
15
|
+
if tool_calls:
|
16
|
+
console.print(f" [cyan]tool_calls:[/cyan] {tool_calls}")
|
17
|
+
if tool_call_id:
|
18
|
+
console.print(f" [magenta]tool_call_id:[/magenta] {tool_call_id}")
|
@@ -0,0 +1,40 @@
|
|
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
|
+
lines = 20
|
6
|
+
if args and len(args) > 0 and str(args[0]).isdigit():
|
7
|
+
lines = int(args[0])
|
8
|
+
stdout_path = shell_state.termweb_stdout_path if shell_state else None
|
9
|
+
stderr_path = shell_state.livereload_stderr_path if shell_state else None
|
10
|
+
if not stdout_path and not stderr_path:
|
11
|
+
console.print(
|
12
|
+
"[yellow][livereload] No livereload log files found for this session.[/yellow]"
|
13
|
+
)
|
14
|
+
return
|
15
|
+
stdout_lines = []
|
16
|
+
stderr_lines = []
|
17
|
+
if stdout_path:
|
18
|
+
try:
|
19
|
+
with open(stdout_path, encoding="utf-8") as f:
|
20
|
+
stdout_lines = f.readlines()[-lines:]
|
21
|
+
if stdout_lines:
|
22
|
+
console.print(
|
23
|
+
f"[yellow][livereload][stdout] Tail of {stdout_path}:\n"
|
24
|
+
+ "".join(stdout_lines)
|
25
|
+
)
|
26
|
+
except Exception as e:
|
27
|
+
console.print(f"[red][livereload][stdout] Error: {e}[/red]")
|
28
|
+
if stderr_path:
|
29
|
+
try:
|
30
|
+
with open(stderr_path, encoding="utf-8") as f:
|
31
|
+
stderr_lines = f.readlines()[-lines:]
|
32
|
+
if stderr_lines:
|
33
|
+
console.print(
|
34
|
+
f"[red][livereload][stderr] Tail of {stderr_path}:\n"
|
35
|
+
+ "".join(stderr_lines)
|
36
|
+
)
|
37
|
+
except Exception as e:
|
38
|
+
console.print(f"[red][livereload][stderr] Error: {e}[/red]")
|
39
|
+
if (not stdout_path or not stdout_lines) and (not stderr_path or not stderr_lines):
|
40
|
+
console.print("[livereload] No output or errors captured in logs.")
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from janito.agent.runtime_config import runtime_config
|
2
2
|
|
3
3
|
|
4
|
-
def handle_prompt(console, **kwargs):
|
4
|
+
def handle_prompt(console, shell_state=None, **kwargs):
|
5
5
|
profile_manager = kwargs.get("profile_manager")
|
6
6
|
prompt = profile_manager.system_prompt_template if profile_manager else None
|
7
7
|
if not prompt and profile_manager:
|
@@ -9,9 +9,12 @@ def handle_prompt(console, **kwargs):
|
|
9
9
|
console.print(f"[bold magenta]System Prompt:[/bold magenta]\n{prompt}")
|
10
10
|
|
11
11
|
|
12
|
-
def handle_role(console,
|
13
|
-
|
14
|
-
|
12
|
+
def handle_role(console, args=None, shell_state=None, **kwargs):
|
13
|
+
profile_manager = (
|
14
|
+
shell_state.profile_manager
|
15
|
+
if shell_state and hasattr(shell_state, "profile_manager")
|
16
|
+
else kwargs.get("profile_manager")
|
17
|
+
)
|
15
18
|
if not args:
|
16
19
|
console.print("[bold red]Usage: /role <new role description>[/bold red]")
|
17
20
|
return
|
@@ -20,7 +23,7 @@ def handle_role(console, *args, **kwargs):
|
|
20
23
|
profile_manager.set_role(new_role)
|
21
24
|
# Update system message in conversation
|
22
25
|
found = False
|
23
|
-
for msg in
|
26
|
+
for msg in shell_state.conversation_history.get_messages():
|
24
27
|
if msg.get("role") == "system":
|
25
28
|
msg["content"] = (
|
26
29
|
profile_manager.system_prompt_template if profile_manager else new_role
|
@@ -28,7 +31,8 @@ def handle_role(console, *args, **kwargs):
|
|
28
31
|
found = True
|
29
32
|
break
|
30
33
|
if not found:
|
31
|
-
|
34
|
+
if shell_state and hasattr(shell_state, "conversation_history"):
|
35
|
+
shell_state.conversation_history.set_system_message(new_role)
|
32
36
|
# Also store the raw role string
|
33
37
|
if profile_manager:
|
34
38
|
setattr(profile_manager, "role_name", new_role)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
def handle_history(console, shell_state=None, *args, **kwargs):
|
2
|
+
if shell_state and hasattr(shell_state, "mem_history"):
|
3
|
+
input_history = list(shell_state.mem_history.get_strings())
|
4
|
+
else:
|
5
|
+
input_history = []
|
6
|
+
if not args:
|
7
|
+
# Default: last 5 inputs
|
8
|
+
start = max(0, len(input_history) - 5)
|
9
|
+
end = len(input_history)
|
10
|
+
elif len(args) == 1:
|
11
|
+
count = int(args[0])
|
12
|
+
start = max(0, len(input_history) - count)
|
13
|
+
end = len(input_history)
|
14
|
+
elif len(args) >= 2:
|
15
|
+
start = int(args[0])
|
16
|
+
end = int(args[1]) + 1 # inclusive
|
17
|
+
else:
|
18
|
+
start = 0
|
19
|
+
end = len(input_history)
|
20
|
+
|
21
|
+
console.print(
|
22
|
+
f"[bold cyan]Showing input history {start} to {end - 1} (total {len(input_history)}):[/bold cyan]"
|
23
|
+
)
|
24
|
+
for idx, line in enumerate(input_history[start:end], start=start):
|
25
|
+
console.print(f"{idx}: {line}")
|
26
|
+
if isinstance(line, dict):
|
27
|
+
role = line.get("role", "unknown")
|
28
|
+
content = line.get("content", "")
|
29
|
+
else:
|
30
|
+
role = "user"
|
31
|
+
content = line
|
32
|
+
console.print(f"[bold]{idx} [{role}]:[/bold] {content}")
|
@@ -6,9 +6,9 @@ import subprocess
|
|
6
6
|
def restart_cli():
|
7
7
|
# Clean up prompt_toolkit session if active
|
8
8
|
try:
|
9
|
-
from janito.
|
9
|
+
from janito.shell import main
|
10
10
|
|
11
|
-
session = getattr(
|
11
|
+
session = getattr(main, "active_prompt_session", None)
|
12
12
|
if session is not None and hasattr(session, "app"):
|
13
13
|
session.app.exit()
|
14
14
|
except Exception:
|
@@ -40,8 +40,3 @@ def restart_cli():
|
|
40
40
|
def handle_exit(console, **kwargs):
|
41
41
|
console.print("[bold red]Exiting chat mode.[/bold red]")
|
42
42
|
sys.exit(0)
|
43
|
-
|
44
|
-
|
45
|
-
def handle_restart(console, **kwargs):
|
46
|
-
console.print("[bold yellow]Restarting CLI...[/bold yellow]")
|
47
|
-
restart_cli()
|