janito 1.8.1__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 -3
- janito/agent/config_utils.py +0 -9
- janito/agent/conversation.py +177 -114
- janito/agent/conversation_api.py +179 -159
- janito/agent/conversation_tool_calls.py +11 -8
- janito/agent/llm_conversation_history.py +70 -0
- janito/agent/openai_client.py +44 -21
- janito/agent/openai_schema_generator.py +164 -128
- 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 +9 -8
- janito/agent/test_openai_schema_generator.py +93 -0
- janito/agent/tool_base.py +7 -2
- janito/agent/tool_executor.py +63 -50
- janito/agent/tool_registry.py +5 -2
- janito/agent/tool_use_tracker.py +42 -5
- janito/agent/tools/__init__.py +13 -12
- janito/agent/tools/create_directory.py +9 -6
- janito/agent/tools/create_file.py +35 -54
- janito/agent/tools/delete_text_in_file.py +97 -0
- janito/agent/tools/fetch_url.py +50 -5
- janito/agent/tools/find_files.py +40 -26
- janito/agent/tools/get_file_outline/__init__.py +1 -0
- janito/agent/tools/{outline_file/__init__.py → get_file_outline/core.py} +14 -18
- janito/agent/tools/get_file_outline/python_outline.py +134 -0
- janito/agent/tools/{search_outline.py → get_file_outline/search_outline.py} +11 -0
- janito/agent/tools/get_lines.py +21 -12
- janito/agent/tools/move_file.py +13 -12
- 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 +4 -2
- janito/agent/tools/remove_file.py +15 -13
- janito/agent/tools/replace_file.py +72 -0
- janito/agent/tools/replace_text_in_file.py +7 -5
- janito/agent/tools/run_bash_command.py +29 -72
- janito/agent/tools/run_powershell_command.py +142 -102
- janito/agent/tools/search_text.py +177 -131
- janito/agent/tools/validate_file_syntax/__init__.py +1 -0
- janito/agent/tools/validate_file_syntax/core.py +94 -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/action_type.py +7 -0
- janito/agent/tools_utils/dir_walk_utils.py +24 -0
- janito/agent/tools_utils/formatting.py +49 -0
- janito/agent/tools_utils/gitignore_utils.py +69 -0
- janito/agent/tools_utils/test_gitignore_utils.py +46 -0
- janito/agent/tools_utils/utils.py +30 -0
- janito/cli/_livereload_log_utils.py +13 -0
- janito/cli/_print_config.py +63 -61
- janito/cli/arg_parser.py +57 -14
- janito/cli/cli_main.py +270 -0
- janito/cli/livereload_starter.py +60 -0
- janito/cli/main.py +166 -99
- janito/cli/one_shot.py +80 -0
- janito/cli/termweb_starter.py +2 -2
- janito/i18n/__init__.py +1 -1
- janito/livereload/app.py +25 -0
- janito/rich_utils.py +41 -25
- janito/{cli_chat_shell → shell}/commands/__init__.py +19 -14
- janito/{cli_chat_shell → shell}/commands/config.py +4 -4
- janito/shell/commands/conversation_restart.py +74 -0
- janito/shell/commands/edit.py +24 -0
- janito/shell/commands/history_view.py +18 -0
- janito/{cli_chat_shell → shell}/commands/lang.py +3 -0
- janito/shell/commands/livelogs.py +42 -0
- janito/{cli_chat_shell → shell}/commands/prompt.py +16 -6
- janito/shell/commands/session.py +35 -0
- janito/{cli_chat_shell → shell}/commands/session_control.py +3 -5
- janito/{cli_chat_shell → shell}/commands/termweb_log.py +18 -10
- janito/shell/commands/tools.py +26 -0
- janito/shell/commands/track.py +36 -0
- janito/shell/commands/utility.py +28 -0
- janito/{cli_chat_shell → shell}/commands/verbose.py +4 -5
- janito/shell/commands.py +40 -0
- janito/shell/input_history.py +62 -0
- janito/shell/main.py +257 -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/shell/session/manager.py +101 -0
- janito/{cli_chat_shell/ui.py → shell/ui/interactive.py} +23 -17
- janito/termweb/app.py +3 -3
- janito/termweb/static/editor.css +142 -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/tests/test_rich_utils.py +44 -0
- janito/web/app.py +0 -75
- {janito-1.8.1.dist-info → janito-1.10.0.dist-info}/METADATA +62 -42
- janito-1.10.0.dist-info/RECORD +158 -0
- {janito-1.8.1.dist-info → janito-1.10.0.dist-info}/WHEEL +1 -1
- janito/agent/tools/dir_walk_utils.py +0 -16
- janito/agent/tools/gitignore_utils.py +0 -46
- janito/agent/tools/memory.py +0 -48
- janito/agent/tools/outline_file/formatting.py +0 -20
- 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/run_python_command.py +0 -163
- 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/runner/cli_main.py +0 -180
- 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/cli_chat_shell/commands/sum.py +0 -49
- janito/cli_chat_shell/commands/utility.py +0 -32
- janito/cli_chat_shell/session_manager.py +0 -72
- janito-1.8.1.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/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.1.dist-info → janito-1.10.0.dist-info}/entry_points.txt +0 -0
- {janito-1.8.1.dist-info → janito-1.10.0.dist-info}/licenses/LICENSE +0 -0
- {janito-1.8.1.dist-info → janito-1.10.0.dist-info}/top_level.txt +0 -0
janito/cli/one_shot.py
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
from janito.agent.conversation_exceptions import (
|
2
|
+
MaxRoundsExceededError,
|
3
|
+
ProviderError,
|
4
|
+
EmptyResponseError,
|
5
|
+
)
|
6
|
+
from janito.agent.api_exceptions import ApiError
|
7
|
+
from janito.agent.llm_conversation_history import LLMConversationHistory
|
8
|
+
|
9
|
+
|
10
|
+
def prepare_messages(args, profile_manager, runtime_config):
|
11
|
+
prompt = getattr(args, "input_arg", None)
|
12
|
+
messages = []
|
13
|
+
system_prompt_override = runtime_config.get("system_prompt_template")
|
14
|
+
if system_prompt_override:
|
15
|
+
if not runtime_config.get("vanilla_mode", False) or getattr(
|
16
|
+
args, "system", None
|
17
|
+
):
|
18
|
+
messages.append({"role": "system", "content": system_prompt_override})
|
19
|
+
elif profile_manager.system_prompt_template and not runtime_config.get(
|
20
|
+
"vanilla_mode", False
|
21
|
+
):
|
22
|
+
messages.append(
|
23
|
+
{"role": "system", "content": profile_manager.system_prompt_template}
|
24
|
+
)
|
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
|
49
|
+
import time
|
50
|
+
|
51
|
+
console = Console()
|
52
|
+
message_handler = RichMessageHandler()
|
53
|
+
messages = prepare_messages(args, profile_manager, runtime_config)
|
54
|
+
info_start_time = None
|
55
|
+
if getattr(args, "info", False):
|
56
|
+
info_start_time = time.time()
|
57
|
+
try:
|
58
|
+
max_rounds = 100
|
59
|
+
result = profile_manager.agent.chat(
|
60
|
+
LLMConversationHistory(messages),
|
61
|
+
message_handler=message_handler,
|
62
|
+
spinner=True,
|
63
|
+
max_rounds=max_rounds,
|
64
|
+
)
|
65
|
+
print_usage_info(args, info_start_time, result, console)
|
66
|
+
except MaxRoundsExceededError:
|
67
|
+
console.print("[red]Max conversation rounds exceeded.[/red]")
|
68
|
+
except ProviderError as e:
|
69
|
+
console.print(f"[red]Provider error:[/red] {e}")
|
70
|
+
except EmptyResponseError as e:
|
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/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/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/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,42 +2,58 @@
|
|
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
|
6
|
+
from typing import Optional
|
8
7
|
|
9
8
|
|
10
|
-
|
11
|
-
|
9
|
+
class RichPrinter:
|
10
|
+
"""
|
11
|
+
Utility class for printing styled messages using the Rich library.
|
12
12
|
|
13
|
+
Args:
|
14
|
+
console (Optional[Console]): An optional Rich Console instance. If not provided, a default Console will be created.
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
+
Methods:
|
17
|
+
print_info(message: str)
|
18
|
+
Print an informational message in cyan (no newline at end).
|
16
19
|
|
20
|
+
print_error(message: str)
|
21
|
+
Print an error message in bold red.
|
17
22
|
|
18
|
-
|
19
|
-
|
23
|
+
print_warning(message: str)
|
24
|
+
Print a warning message in bold yellow.
|
20
25
|
|
26
|
+
print_magenta(message: str)
|
27
|
+
Print a message in magenta.
|
28
|
+
"""
|
21
29
|
|
22
|
-
def
|
23
|
-
|
30
|
+
def __init__(self, console: Optional[Console] = None):
|
31
|
+
self.console = console or Console()
|
24
32
|
|
33
|
+
def print_info(self, message: str):
|
34
|
+
self.console.print(message, style="cyan", end="")
|
25
35
|
|
26
|
-
def
|
27
|
-
|
36
|
+
def print_error(self, message: str):
|
37
|
+
self.console.print(message, style="bold red", end="\n")
|
28
38
|
|
39
|
+
def print_warning(self, message: str):
|
40
|
+
self.console.print(message, style="bold yellow", end="\n")
|
29
41
|
|
30
|
-
def print_magenta(
|
31
|
-
|
42
|
+
def print_magenta(self, message: str):
|
43
|
+
self.console.print(message, style="magenta", end="\n")
|
32
44
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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")
|
@@ -1,55 +1,60 @@
|
|
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
|
6
|
-
from .
|
7
|
-
from .
|
8
|
-
from .
|
9
|
-
from
|
8
|
+
from .livelogs import handle_livelogs
|
9
|
+
from .edit import handle_edit
|
10
|
+
from .history_view import handle_view
|
11
|
+
from janito.shell.session.config import handle_config_shell
|
10
12
|
from .verbose import handle_verbose
|
11
13
|
from .lang import handle_lang
|
12
14
|
from janito.agent.runtime_config import runtime_config
|
15
|
+
from .track import handle_track
|
13
16
|
|
14
17
|
COMMAND_HANDLERS = {
|
15
18
|
"/termweb-logs": handle_termweb_log_tail,
|
19
|
+
"/livelogs": handle_livelogs,
|
16
20
|
"/termweb-status": handle_termweb_status,
|
21
|
+
"/edit": handle_edit,
|
17
22
|
"/history": handle_history,
|
18
|
-
"/continue": handle_continue,
|
19
23
|
"/exit": handle_exit,
|
20
24
|
"exit": handle_exit,
|
21
25
|
"/restart": handle_restart,
|
26
|
+
"/start": handle_restart,
|
22
27
|
"/help": handle_help,
|
23
28
|
"/multi": handle_multi,
|
24
29
|
"/prompt": handle_prompt,
|
30
|
+
"/tools": handle_tools,
|
25
31
|
"/verbose": handle_verbose,
|
26
32
|
}
|
27
33
|
|
28
34
|
if not runtime_config.get("vanilla_mode", False):
|
29
35
|
COMMAND_HANDLERS["/role"] = handle_role
|
30
36
|
|
31
|
-
|
32
37
|
COMMAND_HANDLERS["/lang"] = handle_lang
|
38
|
+
COMMAND_HANDLERS["/track"] = handle_track
|
33
39
|
|
34
40
|
COMMAND_HANDLERS.update(
|
35
41
|
{
|
36
|
-
"/sum": handle_sum,
|
37
42
|
"/clear": handle_clear,
|
38
|
-
"/
|
43
|
+
"/restart": handle_restart,
|
39
44
|
"/config": handle_config_shell,
|
40
|
-
"/
|
45
|
+
"/view": handle_view,
|
41
46
|
}
|
42
47
|
)
|
43
48
|
|
44
49
|
|
45
|
-
def handle_command(command, console,
|
50
|
+
def handle_command(command, console, shell_state=None):
|
46
51
|
parts = command.strip().split()
|
47
52
|
cmd = parts[0]
|
48
53
|
args = parts[1:]
|
49
54
|
handler = COMMAND_HANDLERS.get(cmd)
|
50
55
|
if handler:
|
51
|
-
# Pass args as
|
52
|
-
return handler(console, args=args,
|
56
|
+
# Pass shell_state and args as keyword arguments for handlers that expect them
|
57
|
+
return handler(console, args=args, shell_state=shell_state)
|
53
58
|
console.print(
|
54
59
|
f"[bold red]Invalid command: {cmd}. Type /help for a list of commands.[/bold red]"
|
55
60
|
)
|
@@ -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,74 @@
|
|
1
|
+
import os
|
2
|
+
|
3
|
+
from janito.shell.session.manager import reset_session_id
|
4
|
+
|
5
|
+
|
6
|
+
def handle_restart(console, shell_state=None, **kwargs):
|
7
|
+
from janito.shell.session.manager import load_last_conversation, save_conversation
|
8
|
+
|
9
|
+
reset_session_id()
|
10
|
+
save_path = os.path.join(".janito", "last_conversation.json")
|
11
|
+
|
12
|
+
# --- Append end-of-conversation message to old history if it exists and is non-trivial ---
|
13
|
+
if os.path.exists(save_path):
|
14
|
+
try:
|
15
|
+
messages, prompts, usage = load_last_conversation(save_path)
|
16
|
+
if messages and (
|
17
|
+
len(messages) > 1
|
18
|
+
or (len(messages) == 1 and messages[0].get("role") != "system")
|
19
|
+
):
|
20
|
+
messages.append(
|
21
|
+
{"role": "system", "content": "[Session ended by user]"}
|
22
|
+
)
|
23
|
+
# Save to permanent chat history (let save_conversation pick session file)
|
24
|
+
save_conversation(messages, prompts, usage)
|
25
|
+
except Exception as e:
|
26
|
+
console.print(
|
27
|
+
f"[bold red]Failed to update previous conversation history:[/bold red] {e}"
|
28
|
+
)
|
29
|
+
|
30
|
+
# Clear the terminal screen
|
31
|
+
console.clear()
|
32
|
+
|
33
|
+
# Reset conversation history using its clear method
|
34
|
+
shell_state.conversation_history.clear()
|
35
|
+
|
36
|
+
# Reset tool use tracker
|
37
|
+
try:
|
38
|
+
from janito.agent.tool_use_tracker import ToolUseTracker
|
39
|
+
|
40
|
+
ToolUseTracker.instance().clear_history()
|
41
|
+
except Exception as e:
|
42
|
+
console.print(
|
43
|
+
f"[bold yellow]Warning: Failed to reset tool use tracker:[/bold yellow] {e}"
|
44
|
+
)
|
45
|
+
# Set system prompt from agent template if available
|
46
|
+
if (
|
47
|
+
hasattr(shell_state, "profile_manager")
|
48
|
+
and shell_state.profile_manager
|
49
|
+
and hasattr(shell_state.profile_manager, "agent")
|
50
|
+
and shell_state.profile_manager.agent
|
51
|
+
and getattr(shell_state.profile_manager.agent, "system_prompt_template", None)
|
52
|
+
and not any(
|
53
|
+
m.get("role") == "system"
|
54
|
+
for m in shell_state.conversation_history.get_messages()
|
55
|
+
)
|
56
|
+
):
|
57
|
+
shell_state.conversation_history.set_system_message(
|
58
|
+
shell_state.profile_manager.agent.system_prompt_template
|
59
|
+
)
|
60
|
+
|
61
|
+
# Reset token usage info in-place so all references (including status bar) are updated
|
62
|
+
for k in ("prompt_tokens", "completion_tokens", "total_tokens"):
|
63
|
+
if k in shell_state.last_usage_info:
|
64
|
+
shell_state.last_usage_info[k] = 0
|
65
|
+
else:
|
66
|
+
shell_state.last_usage_info[k] = 0
|
67
|
+
shell_state.last_elapsed = None
|
68
|
+
|
69
|
+
console.print(
|
70
|
+
"[bold green]Conversation history has been started (context reset).[/bold green]"
|
71
|
+
)
|
72
|
+
|
73
|
+
|
74
|
+
handle_restart.help_text = "Start a new conversation (reset context)"
|
@@ -0,0 +1,24 @@
|
|
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)
|
22
|
+
|
23
|
+
|
24
|
+
handle_edit.help_text = "Open a file in the browser-based editor"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
def handle_view(console, args=None, shell_state=None, **kwargs):
|
2
|
+
messages = shell_state.conversation_history.get_messages()
|
3
|
+
if not messages:
|
4
|
+
console.print("[yellow]Conversation history is empty.[/yellow]")
|
5
|
+
return
|
6
|
+
for i, msg in enumerate(messages, 1):
|
7
|
+
role = msg.get("role", "?")
|
8
|
+
content = msg.get("content", "")
|
9
|
+
tool_calls = msg.get("tool_calls")
|
10
|
+
tool_call_id = msg.get("tool_call_id")
|
11
|
+
console.print(f"[bold]{i}. {role}:[/bold] {content}")
|
12
|
+
if tool_calls:
|
13
|
+
console.print(f" [cyan]tool_calls:[/cyan] {tool_calls}")
|
14
|
+
if tool_call_id:
|
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"
|
@@ -0,0 +1,42 @@
|
|
1
|
+
def handle_livelogs(console, args=None, shell_state=None, **kwargs):
|
2
|
+
lines = 20
|
3
|
+
if args and len(args) > 0 and str(args[0]).isdigit():
|
4
|
+
lines = int(args[0])
|
5
|
+
stdout_path = shell_state.termweb_stdout_path if shell_state else None
|
6
|
+
stderr_path = shell_state.livereload_stderr_path if shell_state else None
|
7
|
+
if not stdout_path and not stderr_path:
|
8
|
+
console.print(
|
9
|
+
"[yellow][livereload] No livereload log files found for this session.[/yellow]"
|
10
|
+
)
|
11
|
+
return
|
12
|
+
stdout_lines = []
|
13
|
+
stderr_lines = []
|
14
|
+
if stdout_path:
|
15
|
+
try:
|
16
|
+
with open(stdout_path, encoding="utf-8") as f:
|
17
|
+
stdout_lines = f.readlines()[-lines:]
|
18
|
+
if stdout_lines:
|
19
|
+
console.print(
|
20
|
+
f"[yellow][livereload][stdout] Tail of {stdout_path}:\n"
|
21
|
+
+ "".join(stdout_lines)
|
22
|
+
)
|
23
|
+
except Exception as e:
|
24
|
+
console.print(f"[red][livereload][stdout] Error: {e}[/red]")
|
25
|
+
if stderr_path:
|
26
|
+
try:
|
27
|
+
with open(stderr_path, encoding="utf-8") as f:
|
28
|
+
stderr_lines = f.readlines()[-lines:]
|
29
|
+
if stderr_lines:
|
30
|
+
console.print(
|
31
|
+
f"[red][livereload][stderr] Tail of {stderr_path}:\n"
|
32
|
+
+ "".join(stderr_lines)
|
33
|
+
)
|
34
|
+
except Exception as e:
|
35
|
+
console.print(f"[red][livereload][stderr] Error: {e}[/red]")
|
36
|
+
if (not stdout_path or not stdout_lines) and (not stderr_path or not stderr_lines):
|
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
|
+
)
|
@@ -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,15 @@ def handle_prompt(console, **kwargs):
|
|
9
9
|
console.print(f"[bold magenta]System Prompt:[/bold magenta]\n{prompt}")
|
10
10
|
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
handle_prompt.help_text = "Show the system prompt"
|
13
|
+
|
14
|
+
|
15
|
+
def handle_role(console, args=None, shell_state=None, **kwargs):
|
16
|
+
profile_manager = (
|
17
|
+
shell_state.profile_manager
|
18
|
+
if shell_state and hasattr(shell_state, "profile_manager")
|
19
|
+
else kwargs.get("profile_manager")
|
20
|
+
)
|
15
21
|
if not args:
|
16
22
|
console.print("[bold red]Usage: /role <new role description>[/bold red]")
|
17
23
|
return
|
@@ -20,7 +26,7 @@ def handle_role(console, *args, **kwargs):
|
|
20
26
|
profile_manager.set_role(new_role)
|
21
27
|
# Update system message in conversation
|
22
28
|
found = False
|
23
|
-
for msg in
|
29
|
+
for msg in shell_state.conversation_history.get_messages():
|
24
30
|
if msg.get("role") == "system":
|
25
31
|
msg["content"] = (
|
26
32
|
profile_manager.system_prompt_template if profile_manager else new_role
|
@@ -28,7 +34,8 @@ def handle_role(console, *args, **kwargs):
|
|
28
34
|
found = True
|
29
35
|
break
|
30
36
|
if not found:
|
31
|
-
|
37
|
+
if shell_state and hasattr(shell_state, "conversation_history"):
|
38
|
+
shell_state.conversation_history.set_system_message(new_role)
|
32
39
|
# Also store the raw role string
|
33
40
|
if profile_manager:
|
34
41
|
setattr(profile_manager, "role_name", new_role)
|
@@ -36,6 +43,9 @@ def handle_role(console, *args, **kwargs):
|
|
36
43
|
console.print(f"[bold green]System role updated to:[/bold green] {new_role}")
|
37
44
|
|
38
45
|
|
46
|
+
handle_role.help_text = "Change the system role"
|
47
|
+
|
48
|
+
|
39
49
|
def handle_profile(console, *args, **kwargs):
|
40
50
|
"""/profile - Show the current and available Agent Profile (only 'base' is supported)"""
|
41
51
|
console.print("[bold green]Current profile:[/bold green] base")
|
@@ -0,0 +1,35 @@
|
|
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}")
|
33
|
+
|
34
|
+
|
35
|
+
handle_history.help_text = "Show input history for this session"
|
@@ -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:
|
@@ -42,6 +42,4 @@ def handle_exit(console, **kwargs):
|
|
42
42
|
sys.exit(0)
|
43
43
|
|
44
44
|
|
45
|
-
|
46
|
-
console.print("[bold yellow]Restarting CLI...[/bold yellow]")
|
47
|
-
restart_cli()
|
45
|
+
handle_exit.help_text = "Exit chat mode"
|
@@ -14,12 +14,12 @@ def is_termweb_running(port):
|
|
14
14
|
return False
|
15
15
|
|
16
16
|
|
17
|
-
def handle_termweb_log_tail(console: Console, *args,
|
17
|
+
def handle_termweb_log_tail(console: Console, *args, shell_state=None, **kwargs):
|
18
18
|
lines = 20
|
19
19
|
if args and args[0].isdigit():
|
20
20
|
lines = int(args[0])
|
21
|
-
stdout_path =
|
22
|
-
stderr_path =
|
21
|
+
stdout_path = shell_state.termweb_stdout_path if shell_state else None
|
22
|
+
stderr_path = shell_state.termweb_stderr_path if shell_state else None
|
23
23
|
if not stdout_path and not stderr_path:
|
24
24
|
console.print(
|
25
25
|
"[yellow][termweb] No termweb log files found for this session.[/yellow]"
|
@@ -51,20 +51,23 @@ def handle_termweb_log_tail(console: Console, *args, state=None, **kwargs):
|
|
51
51
|
console.print("[termweb] No output or errors captured in logs.")
|
52
52
|
|
53
53
|
|
54
|
-
|
55
|
-
|
54
|
+
handle_termweb_log_tail.help_text = "Show the last lines of the latest termweb logs"
|
55
|
+
|
56
|
+
|
57
|
+
def handle_termweb_status(console: Console, *args, shell_state=None, **kwargs):
|
58
|
+
if shell_state is None:
|
56
59
|
console.print(
|
57
60
|
"[red]No shell state available. Cannot determine termweb status.[/red]"
|
58
61
|
)
|
59
62
|
return
|
60
|
-
port =
|
61
|
-
port_source = "
|
63
|
+
port = getattr(shell_state, "termweb_port", None)
|
64
|
+
port_source = "shell_state"
|
62
65
|
if not port:
|
63
66
|
port = runtime_config.get("termweb_port")
|
64
67
|
port_source = "runtime_config"
|
65
|
-
pid =
|
66
|
-
stdout_path =
|
67
|
-
stderr_path =
|
68
|
+
pid = getattr(shell_state, "termweb_pid", None)
|
69
|
+
stdout_path = getattr(shell_state, "termweb_stdout_path", None)
|
70
|
+
stderr_path = getattr(shell_state, "termweb_stderr_path", None)
|
68
71
|
running = False
|
69
72
|
if port:
|
70
73
|
running = is_termweb_running(port)
|
@@ -84,3 +87,8 @@ def handle_termweb_status(console: Console, *args, 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
|
+
)
|