janito 2.27.0__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.
Files changed (88) hide show
  1. janito/README.md +9 -9
  2. janito/agent/setup_agent.py +29 -16
  3. janito/cli/chat_mode/script_runner.py +1 -1
  4. janito/cli/chat_mode/session.py +50 -24
  5. janito/cli/chat_mode/session_profile_select.py +8 -2
  6. janito/cli/chat_mode/shell/commands/__init__.py +2 -0
  7. janito/cli/chat_mode/shell/commands/execute.py +4 -2
  8. janito/cli/chat_mode/shell/commands/help.py +8 -1
  9. janito/cli/chat_mode/shell/commands/privileges.py +6 -2
  10. janito/cli/chat_mode/shell/commands/provider.py +28 -0
  11. janito/cli/chat_mode/shell/commands/read.py +4 -2
  12. janito/cli/chat_mode/shell/commands/security/__init__.py +1 -1
  13. janito/cli/chat_mode/shell/commands/security/allowed_sites.py +16 -13
  14. janito/cli/chat_mode/shell/commands/security_command.py +14 -10
  15. janito/cli/chat_mode/shell/commands/tools.py +4 -2
  16. janito/cli/chat_mode/shell/commands/unrestricted.py +17 -12
  17. janito/cli/chat_mode/shell/commands/write.py +4 -2
  18. janito/cli/chat_mode/toolbar.py +15 -1
  19. janito/cli/cli_commands/enable_disable_plugin.py +87 -0
  20. janito/cli/cli_commands/list_models.py +2 -2
  21. janito/cli/cli_commands/list_plugins.py +35 -19
  22. janito/cli/cli_commands/list_profiles.py +6 -6
  23. janito/cli/cli_commands/list_providers.py +1 -1
  24. janito/cli/cli_commands/model_utils.py +45 -20
  25. janito/cli/cli_commands/ping_providers.py +10 -10
  26. janito/cli/cli_commands/set_api_key.py +5 -3
  27. janito/cli/cli_commands/show_config.py +13 -7
  28. janito/cli/cli_commands/show_system_prompt.py +13 -6
  29. janito/cli/core/getters.py +7 -0
  30. janito/cli/core/model_guesser.py +18 -15
  31. janito/cli/core/runner.py +28 -6
  32. janito/cli/core/setters.py +21 -6
  33. janito/cli/main_cli.py +14 -12
  34. janito/cli/prompt_core.py +2 -0
  35. janito/cli/prompt_setup.py +4 -4
  36. janito/cli/single_shot_mode/handler.py +2 -0
  37. janito/config_manager.py +2 -0
  38. janito/docs/GETTING_STARTED.md +9 -9
  39. janito/drivers/cerebras/__init__.py +1 -1
  40. janito/exceptions.py +6 -4
  41. janito/plugins/__init__.py +2 -2
  42. janito/plugins/base.py +48 -40
  43. janito/plugins/builtin.py +88 -0
  44. janito/plugins/config.py +16 -19
  45. janito/plugins/discovery.py +129 -40
  46. janito/plugins/manager.py +63 -59
  47. janito/provider_registry.py +10 -10
  48. janito/providers/__init__.py +1 -1
  49. janito/providers/alibaba/model_info.py +3 -5
  50. janito/providers/alibaba/provider.py +3 -1
  51. janito/providers/cerebras/__init__.py +1 -1
  52. janito/providers/cerebras/model_info.py +12 -27
  53. janito/providers/cerebras/provider.py +11 -9
  54. janito/providers/mistral/__init__.py +1 -1
  55. janito/providers/mistral/model_info.py +1 -1
  56. janito/providers/mistral/provider.py +1 -1
  57. janito/providers/moonshot/__init__.py +1 -0
  58. janito/providers/{moonshotai → moonshot}/model_info.py +3 -3
  59. janito/providers/{moonshotai → moonshot}/provider.py +8 -8
  60. janito/providers/openai/provider.py +3 -1
  61. janito/report_events.py +0 -1
  62. janito/tools/adapters/local/ask_user.py +7 -1
  63. janito/tools/adapters/local/create_file.py +1 -1
  64. janito/tools/adapters/local/fetch_url.py +45 -29
  65. janito/tools/adapters/local/python_command_run.py +2 -1
  66. janito/tools/adapters/local/python_file_run.py +1 -0
  67. janito/tools/adapters/local/run_powershell_command.py +1 -1
  68. janito/tools/adapters/local/search_text/core.py +1 -1
  69. janito/tools/adapters/local/validate_file_syntax/jinja2_validator.py +14 -11
  70. janito/tools/base.py +12 -0
  71. janito/tools/loop_protection.py +24 -22
  72. janito/tools/path_utils.py +7 -7
  73. janito/tools/tool_base.py +0 -2
  74. janito/tools/tools_adapter.py +15 -5
  75. janito/tools/url_whitelist.py +27 -26
  76. {janito-2.27.0.dist-info → janito-2.28.0.dist-info}/METADATA +3 -1
  77. {janito-2.27.0.dist-info → janito-2.28.0.dist-info}/RECORD +81 -82
  78. janito-2.28.0.dist-info/top_level.txt +1 -0
  79. janito/providers/moonshotai/__init__.py +0 -1
  80. janito-2.27.0.dist-info/top_level.txt +0 -2
  81. janito-coder/janito_coder/__init__.py +0 -9
  82. janito-coder/janito_coder/plugins/__init__.py +0 -27
  83. janito-coder/janito_coder/plugins/code_navigator.py +0 -618
  84. janito-coder/janito_coder/plugins/git_analyzer.py +0 -273
  85. janito-coder/pyproject.toml +0 -347
  86. {janito-2.27.0.dist-info → janito-2.28.0.dist-info}/WHEEL +0 -0
  87. {janito-2.27.0.dist-info → janito-2.28.0.dist-info}/entry_points.txt +0 -0
  88. {janito-2.27.0.dist-info → janito-2.28.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,3 +1,4 @@
1
+ import os
1
2
  from prompt_toolkit.formatted_text import HTML
2
3
  from janito.performance_collector import PerformanceCollector
3
4
  from janito.cli.config import config
@@ -17,7 +18,20 @@ def format_tokens(n, tag=None):
17
18
 
18
19
 
19
20
  def assemble_first_line(provider_name, model_name, role, agent=None):
20
- return f" Janito {VERSION} | Provider: <provider>{provider_name}</provider> | Model: <model>{model_name}</model> | Role: <role>{role}</role>"
21
+ cwd = os.getcwd()
22
+ home = os.path.expanduser("~")
23
+
24
+ # Convert to relative path if under home directory
25
+ if cwd.startswith(home):
26
+ cwd_display = "~" + cwd[len(home) :]
27
+ else:
28
+ cwd_display = cwd
29
+
30
+ # Shorten long paths for display
31
+ if len(cwd_display) > 50:
32
+ cwd_display = "..." + cwd_display[-47:]
33
+
34
+ return f" Janito {VERSION} | Provider: <provider>{provider_name}</provider> | Model: <model>{model_name}</model> | Dir: <model>{cwd_display}</model>"
21
35
 
22
36
 
23
37
  def assemble_bindings_line(width, permissions=None):
@@ -0,0 +1,87 @@
1
+ """
2
+ CLI command to enable/disable plugins by modifying plugins.json configuration.
3
+ """
4
+
5
+ import argparse
6
+ import json
7
+ from pathlib import Path
8
+ from typing import Dict, Any
9
+ from janito.plugins.config import (
10
+ load_plugins_config,
11
+ save_plugins_config,
12
+ get_plugins_config_path,
13
+ )
14
+ from janito.plugins.manager import PluginManager
15
+
16
+
17
+ def handle_enable_plugin(args: argparse.Namespace) -> None:
18
+ """Enable a plugin by adding it to plugins.json."""
19
+ config = load_plugins_config()
20
+
21
+ if "plugins" not in config:
22
+ config["plugins"] = {}
23
+ if "load" not in config["plugins"]:
24
+ config["plugins"]["load"] = {}
25
+
26
+ # Set the plugin to enabled (True)
27
+ config["plugins"]["load"][args.plugin_name] = True
28
+
29
+ if save_plugins_config(config):
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
+ )
36
+ else:
37
+ print(f"Error: Failed to enable plugin '{args.plugin_name}'")
38
+
39
+
40
+ def handle_disable_plugin(args: argparse.Namespace) -> None:
41
+ """Disable a plugin by removing it from plugins.json or setting it to False."""
42
+ config = load_plugins_config()
43
+
44
+ if (
45
+ "plugins" in config
46
+ and "load" in config["plugins"]
47
+ and args.plugin_name in config["plugins"]["load"]
48
+ ):
49
+ # Remove the plugin entry or set it to False
50
+ if args.remove:
51
+ del config["plugins"]["load"][args.plugin_name]
52
+ action = "removed"
53
+ else:
54
+ config["plugins"]["load"][args.plugin_name] = False
55
+ action = "disabled"
56
+
57
+ if save_plugins_config(config):
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
+ )
64
+ else:
65
+ print(f"Error: Failed to {action} plugin '{args.plugin_name}'")
66
+ else:
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
+ )
73
+
74
+
75
+ def add_enable_plugin_args(parser: argparse.ArgumentParser) -> None:
76
+ """Add enable-plugin arguments to argument parser."""
77
+ parser.add_argument("plugin_name", help="Name of the plugin to enable")
78
+
79
+
80
+ def add_disable_plugin_args(parser: argparse.ArgumentParser) -> None:
81
+ """Add disable-plugin arguments to argument parser."""
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():
@@ -7,49 +7,65 @@ from typing import List, Dict, Any
7
7
  from janito.plugins.discovery import list_available_plugins, discover_plugins
8
8
  import os
9
9
  from janito.plugins.manager import PluginManager
10
+ from janito.plugins.builtin import BuiltinPluginRegistry
10
11
 
11
12
 
12
13
  def handle_list_plugins(args: argparse.Namespace) -> None:
13
14
  """List plugins command handler."""
14
-
15
- if getattr(args, 'list_plugins_available', False):
15
+
16
+ if getattr(args, "list_plugins_available", False):
16
17
  # List available plugins
17
18
  available = list_available_plugins()
18
- if available:
19
+ builtin_plugins = BuiltinPluginRegistry.list_builtin_plugins()
20
+
21
+ if available or builtin_plugins:
19
22
  print("Available plugins:")
20
- for plugin in available:
21
- print(f" - {plugin}")
23
+
24
+ # Show builtin plugins first
25
+ if builtin_plugins:
26
+ print(" Builtin plugins:")
27
+ for plugin in builtin_plugins:
28
+ print(f" - {plugin} [BUILTIN]")
29
+
30
+ # Show other available plugins
31
+ other_plugins = [p for p in available if p not in builtin_plugins]
32
+ if other_plugins:
33
+ print(" External plugins:")
34
+ for plugin in other_plugins:
35
+ print(f" - {plugin}")
22
36
  else:
23
37
  print("No plugins found in search paths")
24
38
  print("Search paths:")
25
39
  print(f" - {os.getcwd()}/plugins")
26
40
  print(f" - {os.path.expanduser('~')}/.janito/plugins")
27
- elif getattr(args, 'list_resources', False):
41
+ elif getattr(args, "list_resources", False):
28
42
  # List all resources from loaded plugins
29
43
  manager = PluginManager()
30
44
  all_resources = manager.list_all_resources()
31
-
45
+
32
46
  if all_resources:
33
47
  print("Plugin Resources:")
34
48
  for plugin_name, resources in all_resources.items():
35
49
  metadata = manager.get_plugin_metadata(plugin_name)
36
- print(f"\n{plugin_name} v{metadata.version if metadata else 'unknown'}:")
37
-
50
+ print(
51
+ f"\n{plugin_name} v{metadata.version if metadata else 'unknown'}:"
52
+ )
53
+
38
54
  # Group resources by type
39
- tools = [r for r in resources if r['type'] == 'tool']
40
- commands = [r for r in resources if r['type'] == 'command']
41
- configs = [r for r in resources if r['type'] == 'config']
42
-
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
+
43
59
  if tools:
44
60
  print(" Tools:")
45
61
  for tool in tools:
46
62
  print(f" - {tool['name']}: {tool['description']}")
47
-
63
+
48
64
  if commands:
49
65
  print(" Commands:")
50
66
  for cmd in commands:
51
67
  print(f" - {cmd['name']}: {cmd['description']}")
52
-
68
+
53
69
  if configs:
54
70
  print(" Configuration:")
55
71
  for config in configs:
@@ -60,18 +76,18 @@ def handle_list_plugins(args: argparse.Namespace) -> None:
60
76
  # List loaded plugins
61
77
  manager = PluginManager()
62
78
  loaded = manager.list_plugins()
63
-
79
+
64
80
  if loaded:
65
81
  print("Loaded plugins:")
66
82
  for plugin_name in loaded:
67
83
  metadata = manager.get_plugin_metadata(plugin_name)
84
+ is_builtin = BuiltinPluginRegistry.is_builtin(plugin_name)
68
85
  if metadata:
69
- print(f" - {metadata.name} v{metadata.version}")
86
+ builtin_tag = " [BUILTIN]" if is_builtin else ""
87
+ print(f" - {metadata.name} v{metadata.version}{builtin_tag}")
70
88
  print(f" {metadata.description}")
71
89
  if metadata.author:
72
90
  print(f" Author: {metadata.author}")
73
91
  print()
74
92
  else:
75
93
  print("No plugins loaded")
76
-
77
-
@@ -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, 'ping', False):
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 = "Open" if m.get("open") is True or m.get("open") == "Open" else "Locked"
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 = m.get("thinking_supported") is True or m.get("thinking_supported") == "True"
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(name, vendor, context, max_input, cot_display, max_response, thinking_icon, driver)
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("Model Name | Vendor | Context | Max Input | CoT | Max Response | Thinking | Driver")
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 = "Open" if m.get("open") is True or m.get("open") == "Open" else "Locked"
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 = m.get("thinking_supported") is True or m.get("thinking_supported") == "True"
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(f"{name} | {vendor} | {context} | {max_input} | {cot_display} | {max_response} | {thinking} | {driver}")
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(f"Error: Unknown provider '{provider}'. Valid providers are: {', '.join(valid_providers)}")
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 'api_key' in key.lower() and value:
53
- masked_value = value[:8] + '***' + value[-4:] if len(value) > 12 else '***'
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 == 'providers' and isinstance(value, dict):
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 'api_key' in masked_config and masked_config['api_key']:
61
- api_key = masked_config['api_key']
62
- masked_config['api_key'] = api_key[:8] + '***' + api_key[-4:] if len(api_key) > 12 else '***'
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 = resources.files("janito.agent.templates.profiles").joinpath(
138
- f"system_prompt_template_{profile.lower().replace(' ', '_')}.txt.j2"
139
- ).read_text(encoding="utf-8")
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(f"[janito] Could not find profile '{profile}'. This may be a configuration issue.")
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)
@@ -13,6 +13,7 @@ from janito.cli.cli_commands.list_providers_region import handle_list_providers_
13
13
  from janito.cli.cli_commands.list_plugins import handle_list_plugins
14
14
  from functools import partial
15
15
  from janito.provider_registry import ProviderRegistry
16
+ from janito.config import config as global_config
16
17
 
17
18
  GETTER_KEYS = [
18
19
  "show_config",
@@ -30,6 +31,11 @@ GETTER_KEYS = [
30
31
  ]
31
32
 
32
33
 
34
+ def get_current_provider():
35
+ """Get the current provider from the global config."""
36
+ return global_config.get("provider", "none")
37
+
38
+
33
39
  def handle_getter(args, config_mgr=None):
34
40
  provider_instance = None
35
41
  if getattr(args, "list_models", False):
@@ -56,6 +62,7 @@ def handle_getter(args, config_mgr=None):
56
62
  "region_info": partial(handle_region_info, args),
57
63
  "list_providers_region": partial(handle_list_providers_region, args),
58
64
  "list_plugins": partial(handle_list_plugins, args),
65
+ "list_plugins_available": partial(handle_list_plugins, args),
59
66
  "list_resources": partial(handle_list_plugins, args),
60
67
  }
61
68
  for arg in GETTER_KEYS:
@@ -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, 'MODEL_SPECS'):
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 moonshotai
38
- if provider_name == "moonshotai":
36
+
37
+ # Handle special cases like moonshot
38
+ if provider_name == "moonshot":
39
39
  try:
40
- from janito.providers.moonshotai.model_info import MOONSHOTAI_MODEL_SPECS
41
- for spec_model_name in MOONSHOTAI_MODEL_SPECS.keys():
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 "moonshotai"
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