janito 2.27.1__py3-none-any.whl → 2.28.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/README.md +9 -9
- janito/agent/setup_agent.py +29 -16
- janito/cli/chat_mode/script_runner.py +1 -1
- janito/cli/chat_mode/session.py +17 -5
- janito/cli/chat_mode/session_profile_select.py +8 -2
- janito/cli/chat_mode/shell/commands/execute.py +4 -2
- janito/cli/chat_mode/shell/commands/help.py +2 -0
- janito/cli/chat_mode/shell/commands/privileges.py +6 -2
- janito/cli/chat_mode/shell/commands/provider.py +7 -4
- janito/cli/chat_mode/shell/commands/read.py +4 -2
- janito/cli/chat_mode/shell/commands/security/__init__.py +1 -1
- janito/cli/chat_mode/shell/commands/security/allowed_sites.py +16 -13
- janito/cli/chat_mode/shell/commands/security_command.py +14 -10
- janito/cli/chat_mode/shell/commands/tools.py +4 -2
- janito/cli/chat_mode/shell/commands/unrestricted.py +17 -12
- janito/cli/chat_mode/shell/commands/write.py +4 -2
- janito/cli/chat_mode/toolbar.py +4 -4
- janito/cli/cli_commands/enable_disable_plugin.py +48 -25
- janito/cli/cli_commands/list_models.py +2 -2
- janito/cli/cli_commands/list_plugins.py +18 -18
- janito/cli/cli_commands/list_profiles.py +6 -6
- janito/cli/cli_commands/list_providers.py +1 -1
- janito/cli/cli_commands/model_utils.py +45 -20
- janito/cli/cli_commands/ping_providers.py +10 -10
- janito/cli/cli_commands/set_api_key.py +5 -3
- janito/cli/cli_commands/show_config.py +13 -7
- janito/cli/cli_commands/show_system_prompt.py +13 -6
- janito/cli/core/getters.py +1 -0
- janito/cli/core/model_guesser.py +18 -15
- janito/cli/core/runner.py +15 -7
- janito/cli/core/setters.py +9 -6
- janito/cli/main_cli.py +15 -12
- janito/cli/prompt_core.py +2 -0
- janito/cli/prompt_setup.py +4 -4
- janito/cli/single_shot_mode/handler.py +2 -0
- janito/config_manager.py +2 -0
- janito/docs/GETTING_STARTED.md +9 -9
- janito/drivers/cerebras/__init__.py +1 -1
- janito/exceptions.py +6 -4
- janito/plugins/__init__.py +2 -2
- janito/plugins/base.py +48 -40
- janito/plugins/builtin.py +13 -9
- janito/plugins/config.py +16 -19
- janito/plugins/discovery.py +73 -66
- janito/plugins/manager.py +62 -60
- janito/provider_registry.py +10 -10
- janito/providers/__init__.py +1 -1
- janito/providers/alibaba/model_info.py +3 -5
- janito/providers/alibaba/provider.py +3 -1
- janito/providers/cerebras/__init__.py +1 -1
- janito/providers/cerebras/model_info.py +12 -27
- janito/providers/cerebras/provider.py +11 -9
- janito/providers/mistral/__init__.py +1 -1
- janito/providers/mistral/model_info.py +1 -1
- janito/providers/mistral/provider.py +1 -1
- janito/providers/moonshot/__init__.py +1 -0
- janito/providers/{moonshotai → moonshot}/model_info.py +3 -3
- janito/providers/{moonshotai → moonshot}/provider.py +8 -8
- janito/providers/openai/provider.py +3 -1
- janito/report_events.py +0 -1
- janito/tools/adapters/local/create_file.py +1 -1
- janito/tools/adapters/local/fetch_url.py +45 -29
- janito/tools/adapters/local/python_command_run.py +2 -1
- janito/tools/adapters/local/python_file_run.py +1 -0
- janito/tools/adapters/local/run_powershell_command.py +1 -1
- janito/tools/adapters/local/search_text/core.py +1 -1
- janito/tools/adapters/local/validate_file_syntax/jinja2_validator.py +14 -11
- janito/tools/base.py +4 -3
- janito/tools/loop_protection.py +24 -22
- janito/tools/path_utils.py +7 -7
- janito/tools/tool_base.py +0 -2
- janito/tools/tools_adapter.py +15 -5
- janito/tools/url_whitelist.py +27 -26
- {janito-2.27.1.dist-info → janito-2.28.0.dist-info}/METADATA +1 -1
- {janito-2.27.1.dist-info → janito-2.28.0.dist-info}/RECORD +79 -79
- janito/providers/moonshotai/__init__.py +0 -1
- {janito-2.27.1.dist-info → janito-2.28.0.dist-info}/WHEEL +0 -0
- {janito-2.27.1.dist-info → janito-2.28.0.dist-info}/entry_points.txt +0 -0
- {janito-2.27.1.dist-info → janito-2.28.0.dist-info}/licenses/LICENSE +0 -0
- {janito-2.27.1.dist-info → janito-2.28.0.dist-info}/top_level.txt +0 -0
@@ -6,25 +6,33 @@ import argparse
|
|
6
6
|
import json
|
7
7
|
from pathlib import Path
|
8
8
|
from typing import Dict, Any
|
9
|
-
from janito.plugins.config import
|
9
|
+
from janito.plugins.config import (
|
10
|
+
load_plugins_config,
|
11
|
+
save_plugins_config,
|
12
|
+
get_plugins_config_path,
|
13
|
+
)
|
10
14
|
from janito.plugins.manager import PluginManager
|
11
15
|
|
12
16
|
|
13
17
|
def handle_enable_plugin(args: argparse.Namespace) -> None:
|
14
18
|
"""Enable a plugin by adding it to plugins.json."""
|
15
19
|
config = load_plugins_config()
|
16
|
-
|
17
|
-
if
|
18
|
-
config[
|
19
|
-
if
|
20
|
-
config[
|
21
|
-
|
20
|
+
|
21
|
+
if "plugins" not in config:
|
22
|
+
config["plugins"] = {}
|
23
|
+
if "load" not in config["plugins"]:
|
24
|
+
config["plugins"]["load"] = {}
|
25
|
+
|
22
26
|
# Set the plugin to enabled (True)
|
23
|
-
config[
|
24
|
-
|
27
|
+
config["plugins"]["load"][args.plugin_name] = True
|
28
|
+
|
25
29
|
if save_plugins_config(config):
|
26
|
-
print(
|
27
|
-
|
30
|
+
print(
|
31
|
+
f"Plugin '{args.plugin_name}' has been enabled in {get_plugins_config_path()}"
|
32
|
+
)
|
33
|
+
print(
|
34
|
+
"Note: You may need to reload the plugin in the current session with 'plugin reload'"
|
35
|
+
)
|
28
36
|
else:
|
29
37
|
print(f"Error: Failed to enable plugin '{args.plugin_name}'")
|
30
38
|
|
@@ -32,33 +40,48 @@ def handle_enable_plugin(args: argparse.Namespace) -> None:
|
|
32
40
|
def handle_disable_plugin(args: argparse.Namespace) -> None:
|
33
41
|
"""Disable a plugin by removing it from plugins.json or setting it to False."""
|
34
42
|
config = load_plugins_config()
|
35
|
-
|
36
|
-
if
|
43
|
+
|
44
|
+
if (
|
45
|
+
"plugins" in config
|
46
|
+
and "load" in config["plugins"]
|
47
|
+
and args.plugin_name in config["plugins"]["load"]
|
48
|
+
):
|
37
49
|
# Remove the plugin entry or set it to False
|
38
50
|
if args.remove:
|
39
|
-
del config[
|
51
|
+
del config["plugins"]["load"][args.plugin_name]
|
40
52
|
action = "removed"
|
41
53
|
else:
|
42
|
-
config[
|
54
|
+
config["plugins"]["load"][args.plugin_name] = False
|
43
55
|
action = "disabled"
|
44
|
-
|
56
|
+
|
45
57
|
if save_plugins_config(config):
|
46
|
-
print(
|
47
|
-
|
58
|
+
print(
|
59
|
+
f"Plugin '{args.plugin_name}' has been {action} in {get_plugins_config_path()}"
|
60
|
+
)
|
61
|
+
print(
|
62
|
+
"Note: You may need to unload the plugin in the current session with 'plugin unload'"
|
63
|
+
)
|
48
64
|
else:
|
49
65
|
print(f"Error: Failed to {action} plugin '{args.plugin_name}'")
|
50
66
|
else:
|
51
|
-
print(
|
52
|
-
|
67
|
+
print(
|
68
|
+
f"Plugin '{args.plugin_name}' is not currently configured in plugins.json"
|
69
|
+
)
|
70
|
+
print(
|
71
|
+
"It may still be loaded in the current session, but won't be loaded on restart"
|
72
|
+
)
|
53
73
|
|
54
74
|
|
55
75
|
def add_enable_plugin_args(parser: argparse.ArgumentParser) -> None:
|
56
76
|
"""Add enable-plugin arguments to argument parser."""
|
57
|
-
parser.add_argument(
|
58
|
-
|
77
|
+
parser.add_argument("plugin_name", help="Name of the plugin to enable")
|
78
|
+
|
59
79
|
|
60
80
|
def add_disable_plugin_args(parser: argparse.ArgumentParser) -> None:
|
61
81
|
"""Add disable-plugin arguments to argument parser."""
|
62
|
-
parser.add_argument(
|
63
|
-
parser.add_argument(
|
64
|
-
|
82
|
+
parser.add_argument("plugin_name", help="Name of the plugin to disable")
|
83
|
+
parser.add_argument(
|
84
|
+
"--remove",
|
85
|
+
action="store_true",
|
86
|
+
help="Completely remove the plugin from config instead of setting to False",
|
87
|
+
)
|
@@ -30,10 +30,10 @@ def handle_list_models(args, provider_instance):
|
|
30
30
|
# Fallback for simple string model lists
|
31
31
|
from rich.table import Table
|
32
32
|
from janito.cli.console import shared_console
|
33
|
-
|
33
|
+
|
34
34
|
table = Table(title=f"Supported models for provider '{provider_name}'")
|
35
35
|
table.add_column("Model Name", style="cyan")
|
36
|
-
|
36
|
+
|
37
37
|
for m in models:
|
38
38
|
table.add_row(str(m))
|
39
39
|
if sys.stdout.isatty():
|
@@ -12,21 +12,21 @@ from janito.plugins.builtin import BuiltinPluginRegistry
|
|
12
12
|
|
13
13
|
def handle_list_plugins(args: argparse.Namespace) -> None:
|
14
14
|
"""List plugins command handler."""
|
15
|
-
|
16
|
-
if getattr(args,
|
15
|
+
|
16
|
+
if getattr(args, "list_plugins_available", False):
|
17
17
|
# List available plugins
|
18
18
|
available = list_available_plugins()
|
19
19
|
builtin_plugins = BuiltinPluginRegistry.list_builtin_plugins()
|
20
|
-
|
20
|
+
|
21
21
|
if available or builtin_plugins:
|
22
22
|
print("Available plugins:")
|
23
|
-
|
23
|
+
|
24
24
|
# Show builtin plugins first
|
25
25
|
if builtin_plugins:
|
26
26
|
print(" Builtin plugins:")
|
27
27
|
for plugin in builtin_plugins:
|
28
28
|
print(f" - {plugin} [BUILTIN]")
|
29
|
-
|
29
|
+
|
30
30
|
# Show other available plugins
|
31
31
|
other_plugins = [p for p in available if p not in builtin_plugins]
|
32
32
|
if other_plugins:
|
@@ -38,32 +38,34 @@ def handle_list_plugins(args: argparse.Namespace) -> None:
|
|
38
38
|
print("Search paths:")
|
39
39
|
print(f" - {os.getcwd()}/plugins")
|
40
40
|
print(f" - {os.path.expanduser('~')}/.janito/plugins")
|
41
|
-
elif getattr(args,
|
41
|
+
elif getattr(args, "list_resources", False):
|
42
42
|
# List all resources from loaded plugins
|
43
43
|
manager = PluginManager()
|
44
44
|
all_resources = manager.list_all_resources()
|
45
|
-
|
45
|
+
|
46
46
|
if all_resources:
|
47
47
|
print("Plugin Resources:")
|
48
48
|
for plugin_name, resources in all_resources.items():
|
49
49
|
metadata = manager.get_plugin_metadata(plugin_name)
|
50
|
-
print(
|
51
|
-
|
50
|
+
print(
|
51
|
+
f"\n{plugin_name} v{metadata.version if metadata else 'unknown'}:"
|
52
|
+
)
|
53
|
+
|
52
54
|
# Group resources by type
|
53
|
-
tools = [r for r in resources if r[
|
54
|
-
commands = [r for r in resources if r[
|
55
|
-
configs = [r for r in resources if r[
|
56
|
-
|
55
|
+
tools = [r for r in resources if r["type"] == "tool"]
|
56
|
+
commands = [r for r in resources if r["type"] == "command"]
|
57
|
+
configs = [r for r in resources if r["type"] == "config"]
|
58
|
+
|
57
59
|
if tools:
|
58
60
|
print(" Tools:")
|
59
61
|
for tool in tools:
|
60
62
|
print(f" - {tool['name']}: {tool['description']}")
|
61
|
-
|
63
|
+
|
62
64
|
if commands:
|
63
65
|
print(" Commands:")
|
64
66
|
for cmd in commands:
|
65
67
|
print(f" - {cmd['name']}: {cmd['description']}")
|
66
|
-
|
68
|
+
|
67
69
|
if configs:
|
68
70
|
print(" Configuration:")
|
69
71
|
for config in configs:
|
@@ -74,7 +76,7 @@ def handle_list_plugins(args: argparse.Namespace) -> None:
|
|
74
76
|
# List loaded plugins
|
75
77
|
manager = PluginManager()
|
76
78
|
loaded = manager.list_plugins()
|
77
|
-
|
79
|
+
|
78
80
|
if loaded:
|
79
81
|
print("Loaded plugins:")
|
80
82
|
for plugin_name in loaded:
|
@@ -89,5 +91,3 @@ def handle_list_plugins(args: argparse.Namespace) -> None:
|
|
89
91
|
print()
|
90
92
|
else:
|
91
93
|
print("No plugins loaded")
|
92
|
-
|
93
|
-
|
@@ -19,13 +19,13 @@ def _extract_profile_name(filename: str) -> str:
|
|
19
19
|
filename = filename[len(_PREFIX) :]
|
20
20
|
if filename.endswith(_SUFFIX):
|
21
21
|
filename = filename[: -len(_SUFFIX)]
|
22
|
-
|
22
|
+
|
23
23
|
# Convert to title case for consistent capitalization, but handle common acronyms
|
24
24
|
name = filename.replace("_", " ")
|
25
|
-
|
25
|
+
|
26
26
|
# Convert to proper title case with consistent capitalization
|
27
27
|
name = filename.replace("_", " ")
|
28
|
-
|
28
|
+
|
29
29
|
# Handle special cases and acronyms
|
30
30
|
special_cases = {
|
31
31
|
"python": "Python",
|
@@ -35,9 +35,9 @@ def _extract_profile_name(filename: str) -> str:
|
|
35
35
|
"developer": "Developer",
|
36
36
|
"analyst": "Analyst",
|
37
37
|
"conversation": "Conversation",
|
38
|
-
"without": "Without"
|
38
|
+
"without": "Without",
|
39
39
|
}
|
40
|
-
|
40
|
+
|
41
41
|
words = name.split()
|
42
42
|
capitalized_words = []
|
43
43
|
for word in words:
|
@@ -46,7 +46,7 @@ def _extract_profile_name(filename: str) -> str:
|
|
46
46
|
capitalized_words.append(special_cases[lower_word])
|
47
47
|
else:
|
48
48
|
capitalized_words.append(word.capitalize())
|
49
|
-
|
49
|
+
|
50
50
|
return " ".join(capitalized_words)
|
51
51
|
|
52
52
|
|
@@ -8,7 +8,7 @@ from janito.cli.cli_commands.ping_providers import handle_ping_providers
|
|
8
8
|
|
9
9
|
def handle_list_providers(args=None):
|
10
10
|
# Check if ping flag is set
|
11
|
-
if args and getattr(args,
|
11
|
+
if args and getattr(args, "ping", False):
|
12
12
|
handle_ping_providers(args)
|
13
13
|
else:
|
14
14
|
list_providers()
|
@@ -19,76 +19,101 @@ def _print_models_table(models, provider_name):
|
|
19
19
|
|
20
20
|
# Get default model for this provider
|
21
21
|
from janito.providers.registry import LLMProviderRegistry
|
22
|
+
|
22
23
|
try:
|
23
24
|
provider_class = LLMProviderRegistry.get(provider_name)
|
24
25
|
default_model = getattr(provider_class, "DEFAULT_MODEL", None)
|
25
26
|
except:
|
26
27
|
default_model = None
|
27
|
-
|
28
|
+
|
28
29
|
for m in models:
|
29
30
|
name = str(m.get("name", ""))
|
30
|
-
|
31
|
+
|
31
32
|
# Highlight default model with different color
|
32
33
|
if name == default_model:
|
33
34
|
name = f"[bold green]⭐ {name}[/bold green]"
|
34
|
-
|
35
|
-
vendor =
|
36
|
-
|
35
|
+
|
36
|
+
vendor = (
|
37
|
+
"Open" if m.get("open") is True or m.get("open") == "Open" else "Locked"
|
38
|
+
)
|
39
|
+
|
37
40
|
context = _format_context(m.get("context", ""))
|
38
41
|
max_input = _format_k(m.get("max_input", ""))
|
39
42
|
max_cot = _format_k(m.get("max_cot", ""))
|
40
43
|
max_response = _format_k(m.get("max_response", ""))
|
41
|
-
|
44
|
+
|
42
45
|
# Determine thinking indicators
|
43
|
-
thinking_supported =
|
46
|
+
thinking_supported = (
|
47
|
+
m.get("thinking_supported") is True or m.get("thinking_supported") == "True"
|
48
|
+
)
|
44
49
|
cot_value = m.get("max_cot", "")
|
45
|
-
|
50
|
+
|
46
51
|
thinking_icon = "📖" if thinking_supported and m.get("thinking", False) else ""
|
47
52
|
# Only show CoT value if it's a valid number and thinking is supported
|
48
53
|
cot_display = ""
|
49
54
|
if thinking_supported and cot_value and str(cot_value).lower() != "n/a":
|
50
55
|
cot_display = _format_k(cot_value)
|
51
|
-
|
56
|
+
|
52
57
|
driver = _format_driver(m.get("driver", ""))
|
53
|
-
|
54
|
-
table.add_row(
|
58
|
+
|
59
|
+
table.add_row(
|
60
|
+
name,
|
61
|
+
vendor,
|
62
|
+
context,
|
63
|
+
max_input,
|
64
|
+
cot_display,
|
65
|
+
max_response,
|
66
|
+
thinking_icon,
|
67
|
+
driver,
|
68
|
+
)
|
55
69
|
|
56
70
|
import sys
|
71
|
+
|
57
72
|
if sys.stdout.isatty():
|
58
73
|
shared_console.print(table)
|
59
74
|
else:
|
60
75
|
# ASCII-friendly fallback table when output is redirected
|
61
76
|
print(f"Supported models for provider '{provider_name}'")
|
62
|
-
print(
|
63
|
-
|
77
|
+
print(
|
78
|
+
"Model Name | Vendor | Context | Max Input | CoT | Max Response | Thinking | Driver"
|
79
|
+
)
|
80
|
+
|
64
81
|
# Get default model for fallback
|
65
82
|
from janito.providers.registry import LLMProviderRegistry
|
83
|
+
|
66
84
|
try:
|
67
85
|
provider_class = LLMProviderRegistry.get(provider_name)
|
68
86
|
default_model = getattr(provider_class, "DEFAULT_MODEL", None)
|
69
87
|
except:
|
70
88
|
default_model = None
|
71
|
-
|
89
|
+
|
72
90
|
for m in models:
|
73
91
|
name = str(m.get("name", ""))
|
74
92
|
if name == default_model:
|
75
93
|
name = f"⭐ {name} (default)"
|
76
|
-
|
77
|
-
vendor =
|
94
|
+
|
95
|
+
vendor = (
|
96
|
+
"Open" if m.get("open") is True or m.get("open") == "Open" else "Locked"
|
97
|
+
)
|
78
98
|
context = _format_context(m.get("context", ""))
|
79
99
|
max_input = _format_k(m.get("max_input", ""))
|
80
100
|
max_cot = _format_k(m.get("max_cot", ""))
|
81
101
|
max_response = _format_k(m.get("max_response", ""))
|
82
|
-
thinking_supported =
|
102
|
+
thinking_supported = (
|
103
|
+
m.get("thinking_supported") is True
|
104
|
+
or m.get("thinking_supported") == "True"
|
105
|
+
)
|
83
106
|
cot_value = m.get("max_cot", "")
|
84
|
-
|
107
|
+
|
85
108
|
thinking = "Y" if thinking_supported and m.get("thinking", False) else ""
|
86
109
|
cot_display = ""
|
87
110
|
if thinking_supported and cot_value and str(cot_value).lower() != "n/a":
|
88
111
|
cot_display = _format_k(cot_value)
|
89
|
-
|
112
|
+
|
90
113
|
driver = _format_driver(m.get("driver", ""))
|
91
|
-
print(
|
114
|
+
print(
|
115
|
+
f"{name} | {vendor} | {context} | {max_input} | {cot_display} | {max_response} | {thinking} | {driver}"
|
116
|
+
)
|
92
117
|
|
93
118
|
|
94
119
|
def _format_k(val):
|
@@ -12,14 +12,14 @@ def handle_ping_providers(args):
|
|
12
12
|
try:
|
13
13
|
# Get all providers
|
14
14
|
providers = list_providers()
|
15
|
-
|
15
|
+
|
16
16
|
# Create table for results
|
17
17
|
table = Table(title="Provider Connectivity Test")
|
18
18
|
table.add_column("Provider", style="cyan")
|
19
19
|
table.add_column("Status", style="magenta")
|
20
20
|
table.add_column("Time", style="green")
|
21
21
|
table.add_column("Details", style="yellow")
|
22
|
-
|
22
|
+
|
23
23
|
# Test each provider
|
24
24
|
for provider_name in providers:
|
25
25
|
start_time = time.time()
|
@@ -27,7 +27,7 @@ def handle_ping_providers(args):
|
|
27
27
|
# Get provider class
|
28
28
|
provider_class = LLMProviderRegistry.get(provider_name)
|
29
29
|
provider = provider_class()
|
30
|
-
|
30
|
+
|
31
31
|
# Test the provider (simplified - just check if we can instantiate and get models)
|
32
32
|
models = provider.get_models()
|
33
33
|
if models:
|
@@ -36,20 +36,20 @@ def handle_ping_providers(args):
|
|
36
36
|
else:
|
37
37
|
status = "⚠ No models"
|
38
38
|
details = "Provider reachable but no models returned"
|
39
|
-
|
39
|
+
|
40
40
|
except Exception as e:
|
41
41
|
status = "✗ Failed"
|
42
42
|
details = str(e)
|
43
|
-
|
43
|
+
|
44
44
|
end_time = time.time()
|
45
45
|
elapsed = f"{(end_time - start_time)*1000:.0f}ms"
|
46
|
-
|
46
|
+
|
47
47
|
table.add_row(provider_name, status, elapsed, details)
|
48
|
-
|
48
|
+
|
49
49
|
# Print results
|
50
50
|
shared_console.print(table)
|
51
|
-
|
51
|
+
|
52
52
|
except Exception as e:
|
53
53
|
print(f"Error testing provider connectivity: {e}")
|
54
|
-
|
55
|
-
return
|
54
|
+
|
55
|
+
return
|
@@ -13,13 +13,15 @@ def handle_set_api_key(args):
|
|
13
13
|
if not provider:
|
14
14
|
print("Error: --set-api-key requires -p/--provider to be specified.")
|
15
15
|
return
|
16
|
-
|
16
|
+
|
17
17
|
# Validate provider name
|
18
18
|
if provider not in LLMProviderRegistry.list_providers():
|
19
19
|
valid_providers = LLMProviderRegistry.list_providers()
|
20
|
-
print(
|
20
|
+
print(
|
21
|
+
f"Error: Unknown provider '{provider}'. Valid providers are: {', '.join(valid_providers)}"
|
22
|
+
)
|
21
23
|
return
|
22
|
-
|
24
|
+
|
23
25
|
try:
|
24
26
|
set_api_key(provider, api_key)
|
25
27
|
auth_manager = LLMAuthManager()
|
@@ -42,24 +42,30 @@ def handle_show_config(args):
|
|
42
42
|
console.print(f"[bold yellow]Current provider:[/bold yellow] {provider!r}\n")
|
43
43
|
if model is not None:
|
44
44
|
console.print(f"[bold yellow]Global model:[/bold yellow] {model!r}\n")
|
45
|
-
|
45
|
+
|
46
46
|
# Show all configuration values
|
47
47
|
console.print("[bold green]Configuration values:[/bold green]")
|
48
48
|
all_config = config.all()
|
49
49
|
if all_config:
|
50
50
|
for key, value in sorted(all_config.items()):
|
51
51
|
# Hide sensitive values like API keys
|
52
|
-
if
|
53
|
-
masked_value =
|
52
|
+
if "api_key" in key.lower() and value:
|
53
|
+
masked_value = (
|
54
|
+
value[:8] + "***" + value[-4:] if len(value) > 12 else "***"
|
55
|
+
)
|
54
56
|
console.print(f" {key}: {masked_value!r}")
|
55
|
-
elif key ==
|
57
|
+
elif key == "providers" and isinstance(value, dict):
|
56
58
|
# Handle nested provider configs with API keys
|
57
59
|
masked_providers = {}
|
58
60
|
for provider_name, provider_config in value.items():
|
59
61
|
masked_config = dict(provider_config)
|
60
|
-
if
|
61
|
-
api_key = masked_config[
|
62
|
-
masked_config[
|
62
|
+
if "api_key" in masked_config and masked_config["api_key"]:
|
63
|
+
api_key = masked_config["api_key"]
|
64
|
+
masked_config["api_key"] = (
|
65
|
+
api_key[:8] + "***" + api_key[-4:]
|
66
|
+
if len(api_key) > 12
|
67
|
+
else "***"
|
68
|
+
)
|
63
69
|
masked_providers[provider_name] = masked_config
|
64
70
|
console.print(f" {key}: {masked_providers!r}")
|
65
71
|
else:
|
@@ -64,6 +64,7 @@ def _load_template(profile, templates_dir):
|
|
64
64
|
# Also check user profiles directory
|
65
65
|
from pathlib import Path
|
66
66
|
import os
|
67
|
+
|
67
68
|
user_profiles_dir = Path(os.path.expanduser("~/.janito/profiles"))
|
68
69
|
user_template_path = user_profiles_dir / template_filename
|
69
70
|
if user_template_path.exists():
|
@@ -116,11 +117,11 @@ def handle_show_system_prompt(args):
|
|
116
117
|
Path(__file__).parent.parent.parent / "agent" / "templates" / "profiles"
|
117
118
|
)
|
118
119
|
profile = getattr(args, "profile", None)
|
119
|
-
|
120
|
+
|
120
121
|
# Handle --market flag mapping to Market Analyst profile
|
121
122
|
if profile is None and getattr(args, "market", False):
|
122
123
|
profile = "Market Analyst"
|
123
|
-
|
124
|
+
|
124
125
|
if not profile:
|
125
126
|
print(
|
126
127
|
"[janito] No profile specified. The main agent runs without a system prompt template.\n"
|
@@ -134,11 +135,17 @@ def handle_show_system_prompt(args):
|
|
134
135
|
if not template_content:
|
135
136
|
# Try to load directly from package resources as fallback
|
136
137
|
try:
|
137
|
-
template_content =
|
138
|
-
|
139
|
-
|
138
|
+
template_content = (
|
139
|
+
resources.files("janito.agent.templates.profiles")
|
140
|
+
.joinpath(
|
141
|
+
f"system_prompt_template_{profile.lower().replace(' ', '_')}.txt.j2"
|
142
|
+
)
|
143
|
+
.read_text(encoding="utf-8")
|
144
|
+
)
|
140
145
|
except (FileNotFoundError, ModuleNotFoundError, AttributeError):
|
141
|
-
print(
|
146
|
+
print(
|
147
|
+
f"[janito] Could not find profile '{profile}'. This may be a configuration issue."
|
148
|
+
)
|
142
149
|
return
|
143
150
|
|
144
151
|
template = Template(template_content)
|
janito/cli/core/getters.py
CHANGED
janito/cli/core/model_guesser.py
CHANGED
@@ -8,44 +8,47 @@ from janito.providers.registry import LLMProviderRegistry
|
|
8
8
|
def guess_provider_from_model(model_name: str) -> str:
|
9
9
|
"""
|
10
10
|
Guess the provider based on the model name.
|
11
|
-
|
11
|
+
|
12
12
|
Args:
|
13
13
|
model_name: The name of the model to guess the provider for
|
14
|
-
|
14
|
+
|
15
15
|
Returns:
|
16
16
|
The provider name if a match is found, None otherwise
|
17
17
|
"""
|
18
18
|
if not model_name:
|
19
19
|
return None
|
20
|
-
|
20
|
+
|
21
21
|
model_name = model_name.lower()
|
22
|
-
|
22
|
+
|
23
23
|
# Check each provider's models
|
24
24
|
for provider_name in LLMProviderRegistry.list_providers():
|
25
25
|
provider_class = LLMProviderRegistry.get(provider_name)
|
26
26
|
if not provider_class:
|
27
27
|
continue
|
28
|
-
|
28
|
+
|
29
29
|
# Get model specs for this provider
|
30
30
|
try:
|
31
|
-
if hasattr(provider_class,
|
31
|
+
if hasattr(provider_class, "MODEL_SPECS"):
|
32
32
|
model_specs = provider_class.MODEL_SPECS
|
33
33
|
for spec_model_name in model_specs.keys():
|
34
34
|
if spec_model_name.lower() == model_name:
|
35
35
|
return provider_name
|
36
|
-
|
37
|
-
# Handle special cases like
|
38
|
-
if provider_name == "
|
36
|
+
|
37
|
+
# Handle special cases like moonshot
|
38
|
+
if provider_name == "moonshot":
|
39
39
|
try:
|
40
|
-
from janito.providers.
|
41
|
-
|
40
|
+
from janito.providers.moonshot.model_info import (
|
41
|
+
MOONSHOT_MODEL_SPECS,
|
42
|
+
)
|
43
|
+
|
44
|
+
for spec_model_name in MOONSHOT_MODEL_SPECS.keys():
|
42
45
|
if spec_model_name.lower() == model_name:
|
43
|
-
return "
|
46
|
+
return "moonshot"
|
44
47
|
except ImportError:
|
45
48
|
pass
|
46
|
-
|
49
|
+
|
47
50
|
except Exception:
|
48
51
|
# Skip providers that have issues accessing model specs
|
49
52
|
continue
|
50
|
-
|
51
|
-
return None
|
53
|
+
|
54
|
+
return None
|