janito 1.6.0__py3-none-any.whl → 1.8.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.py +3 -3
- janito/agent/config_defaults.py +3 -2
- janito/agent/conversation.py +73 -27
- janito/agent/conversation_api.py +104 -4
- janito/agent/conversation_exceptions.py +6 -0
- janito/agent/conversation_tool_calls.py +17 -3
- janito/agent/event.py +24 -0
- janito/agent/event_dispatcher.py +24 -0
- janito/agent/event_handler_protocol.py +5 -0
- janito/agent/event_system.py +15 -0
- janito/agent/message_handler.py +4 -1
- janito/agent/message_handler_protocol.py +5 -0
- janito/agent/openai_client.py +5 -6
- janito/agent/openai_schema_generator.py +23 -4
- janito/agent/platform_discovery.py +90 -0
- janito/agent/profile_manager.py +34 -110
- janito/agent/queued_message_handler.py +22 -3
- janito/agent/rich_message_handler.py +3 -1
- janito/agent/templates/profiles/system_prompt_template_base.txt.j2 +14 -0
- janito/agent/templates/profiles/system_prompt_template_base_pt.txt.j2 +13 -0
- janito/agent/test_handler_protocols.py +47 -0
- janito/agent/tests/__init__.py +1 -0
- janito/agent/tool_base.py +1 -1
- janito/agent/tool_executor.py +109 -0
- janito/agent/tool_registry.py +3 -75
- janito/agent/tool_use_tracker.py +46 -0
- janito/agent/tools/__init__.py +11 -8
- janito/agent/tools/ask_user.py +26 -12
- janito/agent/tools/create_directory.py +50 -18
- janito/agent/tools/create_file.py +60 -29
- janito/agent/tools/dir_walk_utils.py +16 -0
- janito/agent/tools/fetch_url.py +10 -11
- janito/agent/tools/find_files.py +49 -40
- janito/agent/tools/get_lines.py +60 -25
- janito/agent/tools/memory.py +48 -0
- janito/agent/tools/move_file.py +72 -23
- janito/agent/tools/outline_file/__init__.py +85 -0
- janito/agent/tools/outline_file/formatting.py +20 -0
- janito/agent/tools/outline_file/markdown_outline.py +14 -0
- janito/agent/tools/outline_file/python_outline.py +71 -0
- janito/agent/tools/present_choices.py +62 -0
- janito/agent/tools/present_choices_test.py +18 -0
- janito/agent/tools/remove_directory.py +31 -26
- janito/agent/tools/remove_file.py +31 -13
- janito/agent/tools/replace_text_in_file.py +135 -36
- janito/agent/tools/run_bash_command.py +113 -97
- janito/agent/tools/run_powershell_command.py +169 -0
- janito/agent/tools/run_python_command.py +53 -29
- janito/agent/tools/search_outline.py +17 -0
- janito/agent/tools/search_text.py +208 -0
- janito/agent/tools/tools_utils.py +47 -4
- janito/agent/tools/utils.py +14 -15
- janito/agent/tools/validate_file_syntax.py +163 -0
- janito/cli/_print_config.py +1 -1
- janito/cli/arg_parser.py +36 -4
- janito/cli/config_commands.py +1 -1
- janito/cli/logging_setup.py +7 -2
- janito/cli/main.py +97 -3
- janito/cli/runner/__init__.py +0 -2
- janito/cli/runner/_termweb_log_utils.py +17 -0
- janito/cli/runner/cli_main.py +121 -89
- janito/cli/runner/config.py +6 -4
- janito/cli/termweb_starter.py +73 -0
- janito/cli_chat_shell/chat_loop.py +52 -13
- janito/cli_chat_shell/chat_state.py +1 -1
- janito/cli_chat_shell/chat_ui.py +2 -3
- janito/cli_chat_shell/commands/__init__.py +17 -6
- janito/cli_chat_shell/commands/{history_reset.py → history_start.py} +13 -5
- janito/cli_chat_shell/commands/lang.py +16 -0
- janito/cli_chat_shell/commands/prompt.py +42 -0
- janito/cli_chat_shell/commands/session_control.py +36 -1
- janito/cli_chat_shell/commands/sum.py +49 -0
- janito/cli_chat_shell/commands/termweb_log.py +86 -0
- janito/cli_chat_shell/commands/utility.py +5 -2
- janito/cli_chat_shell/commands/verbose.py +29 -0
- janito/cli_chat_shell/load_prompt.py +47 -8
- janito/cli_chat_shell/session_manager.py +9 -1
- janito/cli_chat_shell/shell_command_completer.py +20 -0
- janito/cli_chat_shell/ui.py +110 -93
- janito/i18n/__init__.py +35 -0
- janito/i18n/messages.py +23 -0
- janito/i18n/pt.py +46 -0
- janito/rich_utils.py +43 -43
- janito/termweb/app.py +95 -0
- janito/termweb/static/editor.html +238 -0
- janito/termweb/static/editor.html.bak +238 -0
- janito/termweb/static/explorer.html.bak +59 -0
- janito/termweb/static/favicon.ico +0 -0
- janito/termweb/static/favicon.ico.bak +0 -0
- janito/termweb/static/index.html +55 -0
- janito/termweb/static/index.html.bak +55 -0
- janito/termweb/static/index.html.bak.bak +175 -0
- janito/termweb/static/landing.html.bak +36 -0
- janito/termweb/static/termicon.svg +1 -0
- janito/termweb/static/termweb.css +235 -0
- janito/termweb/static/termweb.css.bak +286 -0
- janito/termweb/static/termweb.js +187 -0
- janito/termweb/static/termweb.js.bak +187 -0
- janito/termweb/static/termweb.js.bak.bak +157 -0
- janito/termweb/static/termweb_quickopen.js +135 -0
- janito/termweb/static/termweb_quickopen.js.bak +125 -0
- janito/web/app.py +10 -13
- {janito-1.6.0.dist-info → janito-1.8.0.dist-info}/METADATA +73 -32
- janito-1.8.0.dist-info/RECORD +127 -0
- {janito-1.6.0.dist-info → janito-1.8.0.dist-info}/WHEEL +1 -1
- janito/agent/tool_registry_core.py +0 -2
- janito/agent/tools/get_file_outline.py +0 -117
- janito/agent/tools/py_compile_file.py +0 -40
- janito/agent/tools/replace_file.py +0 -51
- janito/agent/tools/search_files.py +0 -71
- janito/cli/runner/scan.py +0 -44
- janito/cli_chat_shell/commands/system.py +0 -73
- janito-1.6.0.dist-info/RECORD +0 -81
- {janito-1.6.0.dist-info → janito-1.8.0.dist-info}/entry_points.txt +0 -0
- {janito-1.6.0.dist-info → janito-1.8.0.dist-info}/licenses/LICENSE +0 -0
- {janito-1.6.0.dist-info → janito-1.8.0.dist-info}/top_level.txt +0 -0
janito/cli/arg_parser.py
CHANGED
@@ -2,12 +2,21 @@ import argparse
|
|
2
2
|
|
3
3
|
|
4
4
|
def create_parser():
|
5
|
+
# Adiciona --list-tools para listar ferramentas registradas
|
6
|
+
# (adição incremental segura)
|
7
|
+
|
5
8
|
parser = argparse.ArgumentParser(
|
6
9
|
description="OpenRouter API call using OpenAI Python SDK"
|
7
10
|
)
|
8
11
|
parser.add_argument(
|
9
12
|
"prompt", type=str, nargs="?", help="Prompt to send to the model"
|
10
13
|
)
|
14
|
+
parser.add_argument(
|
15
|
+
"--lang",
|
16
|
+
type=str,
|
17
|
+
default=None,
|
18
|
+
help="Language for interface messages (e.g., en, pt). Overrides config if set.",
|
19
|
+
)
|
11
20
|
|
12
21
|
parser.add_argument(
|
13
22
|
"--max-tokens",
|
@@ -23,6 +32,7 @@ def create_parser():
|
|
23
32
|
)
|
24
33
|
parser.add_argument(
|
25
34
|
"--model",
|
35
|
+
"-m",
|
26
36
|
type=str,
|
27
37
|
default=None,
|
28
38
|
help="Model name to use for this session (overrides config, does not persist)",
|
@@ -77,11 +87,21 @@ def create_parser():
|
|
77
87
|
action="store_true",
|
78
88
|
help="Pretty print the full response object",
|
79
89
|
)
|
90
|
+
parser.add_argument(
|
91
|
+
"--list-tools",
|
92
|
+
action="store_true",
|
93
|
+
help="Lista todas as ferramentas registradas e sai.",
|
94
|
+
)
|
80
95
|
parser.add_argument(
|
81
96
|
"--show-system",
|
82
97
|
action="store_true",
|
83
98
|
help="Show model, parameters, system prompt, and tool definitions, then exit",
|
84
99
|
)
|
100
|
+
parser.add_argument(
|
101
|
+
"--verbose-reason",
|
102
|
+
action="store_true",
|
103
|
+
help="Print the tool call reason whenever a tool is invoked (for debugging)",
|
104
|
+
)
|
85
105
|
parser.add_argument(
|
86
106
|
"--verbose-tools",
|
87
107
|
action="store_true",
|
@@ -169,10 +189,10 @@ def create_parser():
|
|
169
189
|
help="Suppress all tool output (trusted tools mode: only shows output file locations)",
|
170
190
|
)
|
171
191
|
parser.add_argument(
|
172
|
-
"--
|
192
|
+
"--profile",
|
173
193
|
type=str,
|
174
194
|
default=None,
|
175
|
-
help="
|
195
|
+
help="Agent Profile name (only 'base' is supported)",
|
176
196
|
)
|
177
197
|
parser.add_argument(
|
178
198
|
"--stream",
|
@@ -185,8 +205,20 @@ def create_parser():
|
|
185
205
|
help="Print raw chunks as they are fetched from OpenAI (for debugging)",
|
186
206
|
)
|
187
207
|
parser.add_argument(
|
188
|
-
"--
|
208
|
+
"--no-termweb",
|
209
|
+
action="store_true",
|
210
|
+
help="Disable the built-in lightweight web file viewer for terminal links (enabled by default)",
|
211
|
+
)
|
212
|
+
parser.add_argument(
|
213
|
+
"--termweb-port",
|
214
|
+
type=int,
|
215
|
+
default=8088,
|
216
|
+
help="Port for the termweb server (default: 8088)",
|
217
|
+
)
|
218
|
+
parser.add_argument(
|
219
|
+
"-i",
|
220
|
+
"--info",
|
189
221
|
action="store_true",
|
190
|
-
help="
|
222
|
+
help="Exibe informações básicas do programa e sai (útil para execução única em shell)",
|
191
223
|
)
|
192
224
|
return parser
|
janito/cli/config_commands.py
CHANGED
@@ -175,7 +175,7 @@ def handle_config_commands(args):
|
|
175
175
|
Path(__file__).parent
|
176
176
|
/ "agent"
|
177
177
|
/ "templates"
|
178
|
-
/ "
|
178
|
+
/ "system_prompt_template_default.j2"
|
179
179
|
)
|
180
180
|
print(
|
181
181
|
f"{key} = (default template path: {home_shorten(str(template_path))})"
|
janito/cli/logging_setup.py
CHANGED
@@ -2,8 +2,13 @@ import os
|
|
2
2
|
import logging
|
3
3
|
|
4
4
|
|
5
|
+
from janito.agent.runtime_config import runtime_config
|
6
|
+
|
7
|
+
|
5
8
|
def setup_verbose_logging(args):
|
6
|
-
if
|
9
|
+
if runtime_config.get("verbose_http", False) or runtime_config.get(
|
10
|
+
"verbose_http_raw", False
|
11
|
+
):
|
7
12
|
httpx_logger = logging.getLogger("httpx")
|
8
13
|
httpx_logger.setLevel(logging.DEBUG)
|
9
14
|
handler = logging.StreamHandler()
|
@@ -12,7 +17,7 @@ def setup_verbose_logging(args):
|
|
12
17
|
)
|
13
18
|
httpx_logger.addHandler(handler)
|
14
19
|
|
15
|
-
if
|
20
|
+
if runtime_config.get("verbose_http_raw", False):
|
16
21
|
os.environ["HTTPX_LOG_LEVEL"] = "trace"
|
17
22
|
|
18
23
|
httpcore_logger = logging.getLogger("httpcore")
|
janito/cli/main.py
CHANGED
@@ -3,10 +3,12 @@
|
|
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.runner import run_cli
|
6
|
+
from janito.cli.runner.cli_main import run_cli
|
7
|
+
from janito.agent.runtime_config import unified_config
|
7
8
|
|
8
9
|
# Ensure all tools are registered at startup
|
9
10
|
import janito.agent.tools # noqa: F401
|
11
|
+
from janito.i18n import tr
|
10
12
|
|
11
13
|
|
12
14
|
def main():
|
@@ -14,6 +16,8 @@ def main():
|
|
14
16
|
import sys
|
15
17
|
|
16
18
|
from janito.agent.config import local_config, global_config
|
19
|
+
import janito.i18n as i18n
|
20
|
+
from janito.agent.runtime_config import runtime_config
|
17
21
|
|
18
22
|
local_config.load()
|
19
23
|
global_config.load()
|
@@ -21,16 +25,106 @@ def main():
|
|
21
25
|
parser = create_parser()
|
22
26
|
args = parser.parse_args()
|
23
27
|
|
28
|
+
# Seleção de idioma: prioridade --lang > config.json > padrão
|
29
|
+
lang = getattr(args, "lang", None) or unified_config.get("lang", None) or "en"
|
30
|
+
runtime_config.set("lang", lang)
|
31
|
+
i18n.set_locale(lang)
|
32
|
+
|
24
33
|
from janito.agent.config import CONFIG_OPTIONS
|
25
34
|
from janito.agent.config_defaults import CONFIG_DEFAULTS
|
26
35
|
|
27
36
|
if getattr(args, "help_config", False):
|
28
|
-
print("Available configuration options:\n")
|
37
|
+
print(tr("Available configuration options:\n"))
|
29
38
|
for key, desc in CONFIG_OPTIONS.items():
|
30
39
|
default = CONFIG_DEFAULTS.get(key, None)
|
31
|
-
print(
|
40
|
+
print(
|
41
|
+
tr(
|
42
|
+
"{key:15} {desc} (default: {default})",
|
43
|
+
key=key,
|
44
|
+
desc=desc,
|
45
|
+
default=default,
|
46
|
+
)
|
47
|
+
)
|
48
|
+
sys.exit(0)
|
49
|
+
|
50
|
+
if getattr(args, "list_tools", False):
|
51
|
+
from janito.agent.tool_registry import get_tool_schemas
|
52
|
+
from rich.console import Console
|
53
|
+
from rich.table import Table
|
54
|
+
|
55
|
+
console = Console()
|
56
|
+
table = Table(
|
57
|
+
title="Ferramentas Registradas", show_lines=True, style="bold magenta"
|
58
|
+
)
|
59
|
+
table.add_column("Gnome", style="cyan", no_wrap=True)
|
60
|
+
table.add_column("Descrição", style="green")
|
61
|
+
table.add_column("Parâmetros", style="yellow")
|
62
|
+
for schema in get_tool_schemas():
|
63
|
+
fn = schema["function"]
|
64
|
+
params = "\n".join(
|
65
|
+
[
|
66
|
+
f"[bold]{k}[/]: {v['type']}"
|
67
|
+
for k, v in fn["parameters"].get("properties", {}).items()
|
68
|
+
]
|
69
|
+
)
|
70
|
+
table.add_row(f"[b]{fn['name']}[/b]", fn["description"], params or "-")
|
71
|
+
console.print(table)
|
72
|
+
sys.exit(0)
|
73
|
+
|
74
|
+
if getattr(args, "info", False):
|
75
|
+
# (mantém bloco info)
|
76
|
+
|
77
|
+
print("Janito - Agente CLI de automação")
|
78
|
+
print(f"Modelo: {unified_config.get('model')}")
|
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
|
83
|
+
from janito.agent.runtime_config import runtime_config
|
84
|
+
|
85
|
+
system_prompt_val = None
|
86
|
+
origem = None
|
87
|
+
if getattr(args, "system_file", None):
|
88
|
+
try:
|
89
|
+
with open(args.system_file, "r", encoding="utf-8") as f:
|
90
|
+
system_prompt_val = f.read().strip()
|
91
|
+
runtime_config.set("system_prompt_template", system_prompt_val)
|
92
|
+
origem = "--system-file"
|
93
|
+
except Exception as e:
|
94
|
+
print(f"System prompt: (error reading system-file: {e})")
|
95
|
+
elif getattr(args, "system", None):
|
96
|
+
system_prompt_val = args.system
|
97
|
+
runtime_config.set("system_prompt_template", system_prompt_val)
|
98
|
+
origem = "--system"
|
99
|
+
else:
|
100
|
+
system_prompt_val = runtime_config.get("system_prompt_template")
|
101
|
+
if system_prompt_val:
|
102
|
+
origem = "runtime_config"
|
103
|
+
if system_prompt_val:
|
104
|
+
print(f"System prompt ({origem or 'runtime_config'}): {system_prompt_val}")
|
105
|
+
else:
|
106
|
+
try:
|
107
|
+
from janito.agent.profile_manager import AgentProfileManager
|
108
|
+
from janito.agent.config import get_api_key
|
109
|
+
|
110
|
+
role = args.role or unified_config.get("role", "software engineer")
|
111
|
+
interaction_mode = (
|
112
|
+
"chat" if not getattr(args, "prompt", None) else "prompt"
|
113
|
+
)
|
114
|
+
profile = "base"
|
115
|
+
profile_manager = AgentProfileManager(
|
116
|
+
api_key=get_api_key(),
|
117
|
+
model=unified_config.get("model"),
|
118
|
+
)
|
119
|
+
system_prompt_val = profile_manager.get_system_prompt(
|
120
|
+
role, interaction_mode, profile
|
121
|
+
)
|
122
|
+
print(f"System prompt (profile_manager): {system_prompt_val}")
|
123
|
+
except Exception as e:
|
124
|
+
print(f"System prompt: (error obtaining from profile_manager: {e})")
|
32
125
|
sys.exit(0)
|
33
126
|
|
127
|
+
# ... resto do main ...
|
34
128
|
handle_config_commands(args)
|
35
129
|
setup_verbose_logging(args)
|
36
130
|
if getattr(args, "web", False):
|
janito/cli/runner/__init__.py
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
def print_termweb_logs(stdout_path, stderr_path, console):
|
2
|
+
try:
|
3
|
+
with open(stdout_path, encoding="utf-8") as f:
|
4
|
+
stdout_content = f.read().strip()
|
5
|
+
except Exception:
|
6
|
+
stdout_content = None
|
7
|
+
try:
|
8
|
+
with open(stderr_path, encoding="utf-8") as f:
|
9
|
+
stderr_content = f.read().strip()
|
10
|
+
except Exception:
|
11
|
+
stderr_content = None
|
12
|
+
if stdout_content:
|
13
|
+
console.print("[yellow][termweb][stdout] Output:\n" + stdout_content)
|
14
|
+
if stderr_content:
|
15
|
+
console.print("[red][termweb][stderr] Errors:\n" + stderr_content)
|
16
|
+
if not stdout_content and not stderr_content:
|
17
|
+
console.print("[termweb] No output or errors captured in logs.")
|
janito/cli/runner/cli_main.py
CHANGED
@@ -1,142 +1,167 @@
|
|
1
1
|
import sys
|
2
|
-
import
|
3
|
-
from rich.console import Console
|
2
|
+
import socket
|
4
3
|
from janito.agent.profile_manager import AgentProfileManager
|
5
4
|
from janito.agent.runtime_config import unified_config, runtime_config
|
6
5
|
from janito.agent.config import get_api_key
|
7
6
|
from janito import __version__
|
8
|
-
from .formatting import format_tokens
|
9
|
-
from .scan import scan_project
|
10
|
-
from .config import get_system_prompt_template
|
11
7
|
from janito.agent.conversation_exceptions import (
|
12
8
|
MaxRoundsExceededError,
|
13
9
|
EmptyResponseError,
|
14
10
|
ProviderError,
|
15
11
|
)
|
16
12
|
|
13
|
+
|
14
|
+
def is_port_free(port):
|
15
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
16
|
+
return s.connect_ex(("localhost", port)) != 0
|
17
|
+
|
18
|
+
|
17
19
|
def run_cli(args):
|
18
20
|
if args.version:
|
19
21
|
print(f"janito version {__version__}")
|
20
22
|
sys.exit(0)
|
21
23
|
|
22
|
-
#
|
23
|
-
if getattr(args, "
|
24
|
-
|
25
|
-
sys.exit(0)
|
24
|
+
# Set vanilla mode if -V/--vanilla is passed
|
25
|
+
if getattr(args, "vanilla", False):
|
26
|
+
runtime_config.set("vanilla_mode", True)
|
26
27
|
|
27
|
-
#
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
# Normalize all verbose flags into runtime_config
|
29
|
+
for flag in [
|
30
|
+
"verbose_http",
|
31
|
+
"verbose_http_raw",
|
32
|
+
"verbose_response",
|
33
|
+
"verbose_reason",
|
34
|
+
"verbose_tools",
|
35
|
+
"verbose_events",
|
36
|
+
"verbose_stream",
|
37
|
+
]:
|
38
|
+
if hasattr(args, flag):
|
39
|
+
runtime_config.set(flag, getattr(args, flag, False))
|
34
40
|
|
35
41
|
role = args.role or unified_config.get("role", "software engineer")
|
36
|
-
|
37
|
-
# Ensure runtime_config is updated so chat shell sees the role
|
38
42
|
if args.role:
|
39
43
|
runtime_config.set("role", args.role)
|
40
|
-
|
41
|
-
# Set runtime_config['model'] if --model is provided (highest priority, session only)
|
42
44
|
if getattr(args, "model", None):
|
43
45
|
runtime_config.set("model", args.model)
|
44
|
-
|
45
|
-
# Set runtime_config['max_tools'] if --max-tools is provided
|
46
46
|
if getattr(args, "max_tools", None) is not None:
|
47
47
|
runtime_config.set("max_tools", args.max_tools)
|
48
|
-
|
49
|
-
# Set trust-tools mode if enabled
|
50
48
|
if getattr(args, "trust_tools", False):
|
51
49
|
runtime_config.set("trust_tools", True)
|
52
|
-
|
53
|
-
# Get system prompt template (instructions/config logic)
|
54
|
-
system_prompt_template = get_system_prompt_template(args, role)
|
55
|
-
|
56
|
-
if args.show_system:
|
57
|
-
api_key = get_api_key()
|
58
|
-
model = unified_config.get("model")
|
59
|
-
print("Model:", model)
|
60
|
-
print("Parameters: {}")
|
61
|
-
print(
|
62
|
-
"System Prompt Template:",
|
63
|
-
system_prompt_template or "(default system prompt template not provided)",
|
64
|
-
)
|
65
|
-
sys.exit(0)
|
66
|
-
|
67
|
-
api_key = get_api_key()
|
68
|
-
model = unified_config.get("model")
|
69
|
-
base_url = unified_config.get("base_url", "https://openrouter.ai/api/v1")
|
70
|
-
azure_openai_api_version = unified_config.get(
|
71
|
-
"azure_openai_api_version", "2023-05-15"
|
72
|
-
)
|
73
|
-
# Handle vanilla mode
|
74
|
-
vanilla_mode = getattr(args, "vanilla", False)
|
75
|
-
if vanilla_mode:
|
76
|
-
runtime_config.set("vanilla_mode", True)
|
77
|
-
system_prompt_template = None
|
78
|
-
runtime_config.set("system_prompt_template", None)
|
79
|
-
if args.temperature is None:
|
80
|
-
runtime_config.set("temperature", None)
|
81
|
-
else:
|
82
|
-
runtime_config.set("vanilla_mode", False)
|
83
|
-
|
84
|
-
interaction_style = getattr(args, "style", None) or unified_config.get(
|
85
|
-
"interaction_style", "default"
|
86
|
-
)
|
87
|
-
|
88
50
|
if not getattr(args, "prompt", None):
|
89
51
|
interaction_mode = "chat"
|
90
52
|
else:
|
91
53
|
interaction_mode = "prompt"
|
92
|
-
|
54
|
+
profile = "base"
|
55
|
+
# PATCH: Pass lang from args or runtime_config to AgentProfileManager
|
56
|
+
lang = getattr(args, "lang", None) or runtime_config.get("lang", "en")
|
93
57
|
profile_manager = AgentProfileManager(
|
94
|
-
api_key=
|
95
|
-
model=model,
|
58
|
+
api_key=get_api_key(),
|
59
|
+
model=unified_config.get("model"),
|
96
60
|
role=role,
|
97
|
-
|
61
|
+
profile_name=profile,
|
98
62
|
interaction_mode=interaction_mode,
|
99
63
|
verbose_tools=args.verbose_tools,
|
100
|
-
base_url=base_url,
|
101
|
-
azure_openai_api_version=
|
64
|
+
base_url=unified_config.get("base_url", "https://openrouter.ai/api/v1"),
|
65
|
+
azure_openai_api_version=unified_config.get(
|
66
|
+
"azure_openai_api_version", "2023-05-15"
|
67
|
+
),
|
102
68
|
use_azure_openai=unified_config.get("use_azure_openai", False),
|
69
|
+
lang=lang,
|
103
70
|
)
|
104
71
|
profile_manager.refresh_prompt()
|
105
|
-
|
72
|
+
if getattr(args, "show_system", False):
|
73
|
+
print(profile_manager.render_prompt())
|
74
|
+
sys.exit(0)
|
106
75
|
if args.max_tokens is not None:
|
107
76
|
runtime_config.set("max_tokens", args.max_tokens)
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
77
|
+
if getattr(args, "verbose_reason", False):
|
78
|
+
runtime_config.set("verbose_reason", True)
|
79
|
+
|
80
|
+
# --- Liteweb integration ---
|
81
|
+
termweb_proc = None
|
82
|
+
selected_port = None
|
83
|
+
if (
|
84
|
+
not getattr(args, "no_termweb", False)
|
85
|
+
and interaction_mode == "chat"
|
86
|
+
and not runtime_config.get("vanilla_mode", False)
|
87
|
+
):
|
88
|
+
default_port = 8088
|
89
|
+
max_port = 8100
|
90
|
+
requested_port = args.termweb_port
|
91
|
+
if requested_port == default_port:
|
92
|
+
for port in range(default_port, max_port + 1):
|
93
|
+
if is_port_free(port):
|
94
|
+
selected_port = port
|
95
|
+
break
|
96
|
+
if selected_port is None:
|
97
|
+
print(
|
98
|
+
f"[red]No free port found for termweb in range {default_port}-{max_port}.[/red]"
|
99
|
+
)
|
100
|
+
sys.exit(1)
|
101
|
+
else:
|
102
|
+
if not is_port_free(requested_port):
|
103
|
+
print(f"[red]Port {requested_port} is not available for termweb.[/red]")
|
104
|
+
sys.exit(1)
|
105
|
+
selected_port = requested_port
|
106
|
+
runtime_config.set("termweb_port", selected_port)
|
107
|
+
from janito.cli.termweb_starter import start_termweb
|
108
|
+
|
109
|
+
termweb_proc, started, termweb_stdout_path, termweb_stderr_path = start_termweb(
|
110
|
+
selected_port
|
114
111
|
)
|
115
|
-
|
112
|
+
# Store last running port in .janito/config.json if started
|
113
|
+
if started:
|
114
|
+
from janito.agent.config import local_config
|
116
115
|
|
117
|
-
|
118
|
-
|
119
|
-
from janito.agent.rich_message_handler import RichMessageHandler
|
116
|
+
local_config.set("termweb_last_running_port", selected_port)
|
117
|
+
local_config.save()
|
120
118
|
|
121
|
-
|
122
|
-
messages = []
|
123
|
-
if profile_manager.system_prompt_template:
|
124
|
-
messages.append(
|
125
|
-
{"role": "system", "content": profile_manager.system_prompt_template}
|
126
|
-
)
|
127
|
-
messages.append({"role": "user", "content": prompt})
|
119
|
+
# --- End termweb integration ---
|
128
120
|
try:
|
121
|
+
if not getattr(args, "prompt", None):
|
122
|
+
from janito.cli_chat_shell.chat_loop import start_chat_shell
|
123
|
+
|
124
|
+
start_chat_shell(
|
125
|
+
profile_manager,
|
126
|
+
continue_session=getattr(args, "continue_session", False),
|
127
|
+
termweb_stdout_path=(
|
128
|
+
termweb_stdout_path if "termweb_stdout_path" in locals() else None
|
129
|
+
),
|
130
|
+
termweb_stderr_path=(
|
131
|
+
termweb_stderr_path if "termweb_stderr_path" in locals() else None
|
132
|
+
),
|
133
|
+
)
|
134
|
+
sys.exit(0)
|
135
|
+
# --- Prompt mode ---
|
136
|
+
prompt = args.prompt
|
137
|
+
from rich.console import Console
|
138
|
+
from janito.agent.rich_message_handler import RichMessageHandler
|
139
|
+
|
140
|
+
console = Console()
|
141
|
+
message_handler = RichMessageHandler()
|
142
|
+
messages = []
|
143
|
+
system_prompt_override = runtime_config.get("system_prompt_template")
|
144
|
+
if system_prompt_override:
|
145
|
+
# Só adiciona system prompt se NÃO for vanilla, ou se foi explicitamente passado via --system
|
146
|
+
if not runtime_config.get("vanilla_mode", False) or getattr(
|
147
|
+
args, "system", None
|
148
|
+
):
|
149
|
+
messages.append({"role": "system", "content": system_prompt_override})
|
150
|
+
elif profile_manager.system_prompt_template and not runtime_config.get(
|
151
|
+
"vanilla_mode", False
|
152
|
+
):
|
153
|
+
messages.append(
|
154
|
+
{"role": "system", "content": profile_manager.system_prompt_template}
|
155
|
+
)
|
156
|
+
messages.append({"role": "user", "content": prompt})
|
129
157
|
try:
|
130
|
-
max_rounds =
|
131
|
-
profile_manager.agent.
|
158
|
+
max_rounds = 50
|
159
|
+
profile_manager.agent.chat(
|
132
160
|
messages,
|
133
161
|
message_handler=message_handler,
|
134
162
|
spinner=True,
|
135
163
|
max_rounds=max_rounds,
|
136
|
-
verbose_response=getattr(args, "verbose_response", False),
|
137
|
-
verbose_events=getattr(args, "verbose_events", False),
|
138
164
|
stream=getattr(args, "stream", False),
|
139
|
-
verbose_stream=getattr(args, "verbose_stream", False),
|
140
165
|
)
|
141
166
|
except MaxRoundsExceededError:
|
142
167
|
console.print("[red]Max conversation rounds exceeded.[/red]")
|
@@ -145,4 +170,11 @@ def run_cli(args):
|
|
145
170
|
except EmptyResponseError as e:
|
146
171
|
console.print(f"[red]Error:[/red] {e}")
|
147
172
|
except KeyboardInterrupt:
|
173
|
+
from rich.console import Console
|
174
|
+
|
175
|
+
console = Console()
|
148
176
|
console.print("[yellow]Interrupted by user.[/yellow]")
|
177
|
+
finally:
|
178
|
+
if termweb_proc:
|
179
|
+
termweb_proc.terminate()
|
180
|
+
termweb_proc.wait()
|
janito/cli/runner/config.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
import os
|
2
1
|
from janito.agent.profile_manager import AgentProfileManager
|
3
2
|
from janito.agent.runtime_config import unified_config, runtime_config
|
4
3
|
from janito.agent.config import get_api_key
|
5
4
|
|
5
|
+
|
6
6
|
def get_system_prompt_template(args, role):
|
7
7
|
system_prompt_template = None
|
8
8
|
if getattr(args, "system_prompt_template_file", None):
|
@@ -22,12 +22,14 @@ def get_system_prompt_template(args, role):
|
|
22
22
|
api_key=get_api_key(),
|
23
23
|
model=unified_config.get("model"),
|
24
24
|
role=role,
|
25
|
-
|
25
|
+
profile_name="base",
|
26
26
|
interaction_mode=unified_config.get("interaction_mode", "prompt"),
|
27
27
|
verbose_tools=unified_config.get("verbose_tools", False),
|
28
28
|
base_url=unified_config.get("base_url", None),
|
29
|
-
azure_openai_api_version=unified_config.get(
|
29
|
+
azure_openai_api_version=unified_config.get(
|
30
|
+
"azure_openai_api_version", "2023-05-15"
|
31
|
+
),
|
30
32
|
use_azure_openai=unified_config.get("use_azure_openai", False),
|
31
33
|
)
|
32
|
-
system_prompt_template = profile_manager.
|
34
|
+
system_prompt_template = profile_manager.system_prompt_template
|
33
35
|
return system_prompt_template
|
@@ -0,0 +1,73 @@
|
|
1
|
+
import sys
|
2
|
+
import subprocess
|
3
|
+
import tempfile
|
4
|
+
import time
|
5
|
+
import http.client
|
6
|
+
import os
|
7
|
+
from rich.console import Console
|
8
|
+
from janito.cli.runner._termweb_log_utils import print_termweb_logs
|
9
|
+
from janito.i18n import tr
|
10
|
+
|
11
|
+
|
12
|
+
def wait_for_termweb(port, timeout=3.0):
|
13
|
+
"""Polls the Bottle app root endpoint until it responds or timeout (seconds) is reached."""
|
14
|
+
deadline = time.time() + timeout
|
15
|
+
while time.time() < deadline:
|
16
|
+
try:
|
17
|
+
conn = http.client.HTTPConnection("localhost", port, timeout=0.5)
|
18
|
+
conn.request("GET", "/")
|
19
|
+
resp = conn.getresponse()
|
20
|
+
if resp.status == 200:
|
21
|
+
return True
|
22
|
+
except Exception:
|
23
|
+
pass
|
24
|
+
time.sleep(0.1)
|
25
|
+
return False
|
26
|
+
|
27
|
+
|
28
|
+
def start_termweb(selected_port):
|
29
|
+
"""
|
30
|
+
Start the termweb server on the given port, with rich spinner and logging.
|
31
|
+
Returns (termweb_proc, started: bool)
|
32
|
+
"""
|
33
|
+
console = Console()
|
34
|
+
with console.status("[cyan]Starting web server...", spinner="dots"):
|
35
|
+
# Step 1: Try source path
|
36
|
+
app_py_path = os.path.join(os.path.dirname(__file__), "..", "termweb", "app.py")
|
37
|
+
app_py_path = os.path.abspath(app_py_path)
|
38
|
+
if not os.path.isfile(app_py_path):
|
39
|
+
# Step 2: Try installed package
|
40
|
+
try:
|
41
|
+
import janito_termweb
|
42
|
+
|
43
|
+
app_py_path = janito_termweb.__file__.replace("__init__.py", "app.py")
|
44
|
+
except ImportError:
|
45
|
+
console.print("[red]Could not find termweb app.py![/red]")
|
46
|
+
return None, False, None, None
|
47
|
+
termweb_stdout = tempfile.NamedTemporaryFile(
|
48
|
+
delete=False, mode="w+", encoding="utf-8"
|
49
|
+
)
|
50
|
+
termweb_stderr = tempfile.NamedTemporaryFile(
|
51
|
+
delete=False, mode="w+", encoding="utf-8"
|
52
|
+
)
|
53
|
+
termweb_proc = subprocess.Popen(
|
54
|
+
[sys.executable, app_py_path, "--port", str(selected_port)],
|
55
|
+
stdout=termweb_stdout,
|
56
|
+
stderr=termweb_stderr,
|
57
|
+
)
|
58
|
+
if wait_for_termweb(selected_port, timeout=3.0):
|
59
|
+
console.print(
|
60
|
+
tr(
|
61
|
+
"TermWeb started... Available at http://localhost:{selected_port}",
|
62
|
+
selected_port=selected_port,
|
63
|
+
)
|
64
|
+
)
|
65
|
+
return termweb_proc, True, termweb_stdout.name, termweb_stderr.name
|
66
|
+
else:
|
67
|
+
termweb_proc.terminate()
|
68
|
+
termweb_proc.wait()
|
69
|
+
console.print(
|
70
|
+
f"[red]Failed to start TermWeb on port {selected_port}. Check logs for details.[/red]"
|
71
|
+
)
|
72
|
+
print_termweb_logs(termweb_stdout.name, termweb_stderr.name)
|
73
|
+
return None, False, termweb_stdout.name, termweb_stderr.name
|