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.
Files changed (80) 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 +17 -5
  5. janito/cli/chat_mode/session_profile_select.py +8 -2
  6. janito/cli/chat_mode/shell/commands/execute.py +4 -2
  7. janito/cli/chat_mode/shell/commands/help.py +2 -0
  8. janito/cli/chat_mode/shell/commands/privileges.py +6 -2
  9. janito/cli/chat_mode/shell/commands/provider.py +7 -4
  10. janito/cli/chat_mode/shell/commands/read.py +4 -2
  11. janito/cli/chat_mode/shell/commands/security/__init__.py +1 -1
  12. janito/cli/chat_mode/shell/commands/security/allowed_sites.py +16 -13
  13. janito/cli/chat_mode/shell/commands/security_command.py +14 -10
  14. janito/cli/chat_mode/shell/commands/tools.py +4 -2
  15. janito/cli/chat_mode/shell/commands/unrestricted.py +17 -12
  16. janito/cli/chat_mode/shell/commands/write.py +4 -2
  17. janito/cli/chat_mode/toolbar.py +4 -4
  18. janito/cli/cli_commands/enable_disable_plugin.py +48 -25
  19. janito/cli/cli_commands/list_models.py +2 -2
  20. janito/cli/cli_commands/list_plugins.py +18 -18
  21. janito/cli/cli_commands/list_profiles.py +6 -6
  22. janito/cli/cli_commands/list_providers.py +1 -1
  23. janito/cli/cli_commands/model_utils.py +45 -20
  24. janito/cli/cli_commands/ping_providers.py +10 -10
  25. janito/cli/cli_commands/set_api_key.py +5 -3
  26. janito/cli/cli_commands/show_config.py +13 -7
  27. janito/cli/cli_commands/show_system_prompt.py +13 -6
  28. janito/cli/core/getters.py +1 -0
  29. janito/cli/core/model_guesser.py +18 -15
  30. janito/cli/core/runner.py +15 -7
  31. janito/cli/core/setters.py +9 -6
  32. janito/cli/main_cli.py +15 -12
  33. janito/cli/prompt_core.py +2 -0
  34. janito/cli/prompt_setup.py +4 -4
  35. janito/cli/single_shot_mode/handler.py +2 -0
  36. janito/config_manager.py +2 -0
  37. janito/docs/GETTING_STARTED.md +9 -9
  38. janito/drivers/cerebras/__init__.py +1 -1
  39. janito/exceptions.py +6 -4
  40. janito/plugins/__init__.py +2 -2
  41. janito/plugins/base.py +48 -40
  42. janito/plugins/builtin.py +13 -9
  43. janito/plugins/config.py +16 -19
  44. janito/plugins/discovery.py +73 -66
  45. janito/plugins/manager.py +62 -60
  46. janito/provider_registry.py +10 -10
  47. janito/providers/__init__.py +1 -1
  48. janito/providers/alibaba/model_info.py +3 -5
  49. janito/providers/alibaba/provider.py +3 -1
  50. janito/providers/cerebras/__init__.py +1 -1
  51. janito/providers/cerebras/model_info.py +12 -27
  52. janito/providers/cerebras/provider.py +11 -9
  53. janito/providers/mistral/__init__.py +1 -1
  54. janito/providers/mistral/model_info.py +1 -1
  55. janito/providers/mistral/provider.py +1 -1
  56. janito/providers/moonshot/__init__.py +1 -0
  57. janito/providers/{moonshotai → moonshot}/model_info.py +3 -3
  58. janito/providers/{moonshotai → moonshot}/provider.py +8 -8
  59. janito/providers/openai/provider.py +3 -1
  60. janito/report_events.py +0 -1
  61. janito/tools/adapters/local/create_file.py +1 -1
  62. janito/tools/adapters/local/fetch_url.py +45 -29
  63. janito/tools/adapters/local/python_command_run.py +2 -1
  64. janito/tools/adapters/local/python_file_run.py +1 -0
  65. janito/tools/adapters/local/run_powershell_command.py +1 -1
  66. janito/tools/adapters/local/search_text/core.py +1 -1
  67. janito/tools/adapters/local/validate_file_syntax/jinja2_validator.py +14 -11
  68. janito/tools/base.py +4 -3
  69. janito/tools/loop_protection.py +24 -22
  70. janito/tools/path_utils.py +7 -7
  71. janito/tools/tool_base.py +0 -2
  72. janito/tools/tools_adapter.py +15 -5
  73. janito/tools/url_whitelist.py +27 -26
  74. {janito-2.27.1.dist-info → janito-2.28.0.dist-info}/METADATA +1 -1
  75. {janito-2.27.1.dist-info → janito-2.28.0.dist-info}/RECORD +79 -79
  76. janito/providers/moonshotai/__init__.py +0 -1
  77. {janito-2.27.1.dist-info → janito-2.28.0.dist-info}/WHEEL +0 -0
  78. {janito-2.27.1.dist-info → janito-2.28.0.dist-info}/entry_points.txt +0 -0
  79. {janito-2.27.1.dist-info → janito-2.28.0.dist-info}/licenses/LICENSE +0 -0
  80. {janito-2.27.1.dist-info → janito-2.28.0.dist-info}/top_level.txt +0 -0
janito/README.md CHANGED
@@ -15,17 +15,17 @@ pip install janito
15
15
  1. **Get your API key**: Sign up at [Moonshot AI](https://platform.moonshot.cn/) and get your API key
16
16
  2. **Set your API key**:
17
17
  ```bash
18
- janito --set-api-key YOUR_MOONSHOT_API_KEY -p moonshotai
18
+ janito --set-api-key YOUR_MOONSHOT_API_KEY -p moonshot
19
19
  ```
20
20
 
21
21
  ### Basic Usage
22
22
 
23
- **MoonshotAI (Recommended - Default Provider)**
23
+ **Moonshot (Recommended - Default Provider)**
24
24
  ```bash
25
- # Using the default provider (moonshotai) and model
25
+ # Using the default provider (moonshot) and model
26
26
  janito "Create a Python script that reads a CSV file"
27
27
 
28
- # Using a specific MoonshotAI model
28
+ # Using a specific Moonshot model
29
29
  janito -m kimi-k1-8k "Explain quantum computing"
30
30
  ```
31
31
 
@@ -71,13 +71,13 @@ In chat mode, you can:
71
71
 
72
72
  Set default provider and model:
73
73
  ```bash
74
- janito --set provider=moonshotai
74
+ janito --set provider=moonshot
75
75
  janito --set model=kimi-k1-8k
76
76
  ```
77
77
 
78
78
  ## Providers
79
79
 
80
- ### MoonshotAI (Recommended)
80
+ ### Moonshot (Recommended)
81
81
 
82
82
  - **Models**: kimi-k1-8k, kimi-k1-32k, kimi-k1-128k, kimi-k2-turbo-preview
83
83
  - **Strengths**: Excellent Chinese/English support, competitive pricing, fast responses
@@ -126,10 +126,10 @@ janito --role python-expert "Optimize this algorithm"
126
126
  ### Environment Variables
127
127
  You can also configure via environment variables:
128
128
 
129
- **MoonshotAI:**
129
+ **Moonshot:**
130
130
  ```bash
131
- export MOONSHOTAI_API_KEY=your_key_here
132
- export JANITO_PROVIDER=moonshotai
131
+ export MOONSHOT_API_KEY=your_key_here
132
+ export JANITO_PROVIDER=moonshot
133
133
  export JANITO_MODEL=kimi-k1-8k
134
134
  ```
135
135
 
@@ -53,38 +53,48 @@ def _load_template_content(profile, templates_dir):
53
53
  return file.read(), user_template_path
54
54
 
55
55
  # If nothing matched, list available profiles and raise an informative error
56
- from janito.cli.cli_commands.list_profiles import _gather_default_profiles, _gather_user_profiles
57
-
56
+ from janito.cli.cli_commands.list_profiles import (
57
+ _gather_default_profiles,
58
+ _gather_user_profiles,
59
+ )
60
+
58
61
  default_profiles = _gather_default_profiles()
59
62
  user_profiles = _gather_user_profiles()
60
-
63
+
61
64
  available_profiles = []
62
65
  if default_profiles:
63
66
  available_profiles.extend([(p, "default") for p in default_profiles])
64
67
  if user_profiles:
65
68
  available_profiles.extend([(p, "user") for p in user_profiles])
66
-
69
+
67
70
  # Normalize the input profile for better matching suggestions
68
71
  normalized_input = re.sub(r"\s+", " ", profile.strip().lower())
69
-
72
+
70
73
  if available_profiles:
71
- profile_list = "\n".join([f" - {name} ({source})" for name, source in available_profiles])
72
-
74
+ profile_list = "\n".join(
75
+ [f" - {name} ({source})" for name, source in available_profiles]
76
+ )
77
+
73
78
  # Find close matches
74
79
  close_matches = []
75
80
  for name, source in available_profiles:
76
81
  normalized_name = name.lower()
77
- if normalized_input in normalized_name or normalized_name in normalized_input:
82
+ if (
83
+ normalized_input in normalized_name
84
+ or normalized_name in normalized_input
85
+ ):
78
86
  close_matches.append(name)
79
-
87
+
80
88
  suggestion = ""
81
89
  if close_matches:
82
90
  suggestion = f"\nDid you mean: {', '.join(close_matches)}?"
83
-
91
+
84
92
  error_msg = f"[janito] Could not find profile '{profile}'. Available profiles:\n{profile_list}{suggestion}"
85
93
  else:
86
- error_msg = f"[janito] Could not find profile '{profile}'. No profiles available."
87
-
94
+ error_msg = (
95
+ f"[janito] Could not find profile '{profile}'. No profiles available."
96
+ )
97
+
88
98
  raise FileNotFoundError(error_msg)
89
99
  # Replace spaces in profile name with underscores for filename resolution
90
100
  sanitized_profile = re.sub(r"\\s+", "_", profile.strip()) if profile else profile
@@ -144,20 +154,23 @@ def _prepare_template_context(role, profile, allowed_permissions):
144
154
  context["platform"] = pd.get_platform_name()
145
155
  context["python_version"] = pd.get_python_version()
146
156
  context["shell_info"] = pd.detect_shell()
147
-
157
+
148
158
  # Add allowed sites for market analyst profile
149
159
  if profile == "market-analyst":
150
160
  from janito.tools.url_whitelist import get_url_whitelist_manager
161
+
151
162
  whitelist_manager = get_url_whitelist_manager()
152
163
  allowed_sites = whitelist_manager.get_allowed_sites()
153
164
  context["allowed_sites"] = allowed_sites
154
-
165
+
155
166
  # Add market data sources documentation
156
167
  if not allowed_sites:
157
- context["allowed_sites_info"] = "No whitelist restrictions - all sites allowed"
168
+ context["allowed_sites_info"] = (
169
+ "No whitelist restrictions - all sites allowed"
170
+ )
158
171
  else:
159
172
  context["allowed_sites_info"] = f"Restricted to: {', '.join(allowed_sites)}"
160
-
173
+
161
174
  return context
162
175
 
163
176
 
@@ -52,7 +52,7 @@ class ChatScriptRunner:
52
52
  inputs: List[str],
53
53
  *,
54
54
  console: Optional[Console] = None,
55
- provider: str = "moonshotai",
55
+ provider: str = "moonshot",
56
56
  model: str = "kimi-k1-8k",
57
57
  use_real_agent: bool = True,
58
58
  **chat_session_kwargs,
@@ -116,7 +116,9 @@ class ChatSession:
116
116
  def _select_profile_and_role(self, args, role):
117
117
  profile = getattr(args, "profile", None) if args is not None else None
118
118
  role_arg = getattr(args, "role", None) if args is not None else None
119
- python_profile = getattr(args, "developer", False) if args is not None else False
119
+ python_profile = (
120
+ getattr(args, "developer", False) if args is not None else False
121
+ )
120
122
  market_profile = getattr(args, "market", False) if args is not None else False
121
123
  profile_system_prompt = None
122
124
  no_tools_mode = False
@@ -129,10 +131,15 @@ class ChatSession:
129
131
  if market_profile and profile is None and role_arg is None:
130
132
  profile = "Market Analyst"
131
133
 
132
- if profile is None and role_arg is None and not python_profile and not market_profile:
134
+ if (
135
+ profile is None
136
+ and role_arg is None
137
+ and not python_profile
138
+ and not market_profile
139
+ ):
133
140
  # Skip interactive profile selection for list commands
134
141
  from janito.cli.core.getters import GETTER_KEYS
135
-
142
+
136
143
  # Check if any getter command is active - these don't need interactive mode
137
144
  skip_profile_selection = False
138
145
  if args is not None:
@@ -140,12 +147,14 @@ class ChatSession:
140
147
  if getattr(args, key, False):
141
148
  skip_profile_selection = True
142
149
  break
143
-
150
+
144
151
  if skip_profile_selection:
145
152
  profile = "Developer with Python Tools" # Default for non-interactive commands
146
153
  else:
147
154
  try:
148
- from janito.cli.chat_mode.session_profile_select import select_profile
155
+ from janito.cli.chat_mode.session_profile_select import (
156
+ select_profile,
157
+ )
149
158
 
150
159
  result = select_profile()
151
160
  if isinstance(result, dict):
@@ -338,6 +347,7 @@ class ChatSession:
338
347
  if top_base:
339
348
  candidates.append(top_base)
340
349
  from urllib.parse import urlparse
350
+
341
351
  for candidate in candidates:
342
352
  try:
343
353
  if not candidate:
@@ -367,6 +377,8 @@ class ChatSession:
367
377
  print_token_message_summary(
368
378
  self.console, self.msg_count, usage, elapsed=elapsed
369
379
  )
380
+ # Send terminal bell character to trigger TUI bell after printing token summary
381
+ print("\a", end="", flush=True)
370
382
  if final_event and hasattr(final_event, "metadata"):
371
383
  exit_reason = (
372
384
  final_event.metadata.get("exit_reason")
@@ -149,7 +149,10 @@ def select_profile():
149
149
 
150
150
  # Get the absolute path relative to the current script location
151
151
  current_dir = Path(__file__).parent
152
- template_path = current_dir / "../../agent/templates/profiles/system_prompt_template_developer.txt.j2"
152
+ template_path = (
153
+ current_dir
154
+ / "../../agent/templates/profiles/system_prompt_template_developer.txt.j2"
155
+ )
153
156
  with open(template_path, "r", encoding="utf-8") as f:
154
157
  template_content = f.read()
155
158
 
@@ -165,7 +168,10 @@ def select_profile():
165
168
 
166
169
  # Get the absolute path relative to the current script location
167
170
  current_dir = Path(__file__).parent
168
- template_path = current_dir / "../../agent/templates/profiles/system_prompt_template_market_analyst.txt.j2"
171
+ template_path = (
172
+ current_dir
173
+ / "../../agent/templates/profiles/system_prompt_template_market_analyst.txt.j2"
174
+ )
169
175
  with open(template_path, "r", encoding="utf-8") as f:
170
176
  template_content = f.read()
171
177
 
@@ -6,8 +6,10 @@ class ExecuteShellHandler(ShellCmdHandler):
6
6
  help_text = "/execute on|off: Enable or disable code and command execution tools. Usage: /execute on or /execute off."
7
7
 
8
8
  def run(self):
9
- if self.shell_state and getattr(self.shell_state, 'no_tools_mode', False):
10
- shared_console.print("[yellow]No tools are available in this mode (no tools, no context).[/yellow]")
9
+ if self.shell_state and getattr(self.shell_state, "no_tools_mode", False):
10
+ shared_console.print(
11
+ "[yellow]No tools are available in this mode (no tools, no context).[/yellow]"
12
+ )
11
13
  return
12
14
  if not self.shell_state:
13
15
  shared_console.print("[red]Shell state unavailable.[/red]")
@@ -9,8 +9,10 @@ class HelpShellHandler(ShellCmdHandler):
9
9
  def run(self):
10
10
  # Ensure /provider command is registered before showing help
11
11
  from janito.cli.chat_mode.shell.commands import COMMAND_HANDLERS
12
+
12
13
  if "/provider" not in COMMAND_HANDLERS:
13
14
  from janito.cli.chat_mode.shell.commands.provider import ProviderCmdHandler
15
+
14
16
  COMMAND_HANDLERS["/provider"] = ProviderCmdHandler
15
17
 
16
18
  from ._priv_check import user_has_any_privileges
@@ -1,16 +1,20 @@
1
1
  from janito.cli.console import shared_console
2
2
  from janito.cli.chat_mode.shell.commands.base import ShellCmdHandler
3
3
 
4
+
4
5
  class PrivilegesShellHandler(ShellCmdHandler):
5
6
  help_text = "Show current tool privileges or availability."
6
7
 
7
8
  def run(self):
8
9
  # Check for no_tools_mode in shell_state
9
- if self.shell_state and getattr(self.shell_state, 'no_tools_mode', False):
10
- shared_console.print("[yellow]No tools are available in this mode (no tools, no context).[/yellow]")
10
+ if self.shell_state and getattr(self.shell_state, "no_tools_mode", False):
11
+ shared_console.print(
12
+ "[yellow]No tools are available in this mode (no tools, no context).[/yellow]"
13
+ )
11
14
  return
12
15
  try:
13
16
  from janito.tools.permissions import get_global_allowed_permissions
17
+
14
18
  perms = get_global_allowed_permissions()
15
19
  lines = ["[bold]Current tool privileges:[/bold]"]
16
20
  lines.append(f"Read: {'✅' if perms.read else '❌'}")
@@ -3,11 +3,12 @@ from janito.cli.core.setters import set_provider
3
3
  from janito.cli.chat_mode.shell.commands.base import ShellCmdHandler
4
4
  from janito.cli.console import shared_console as console
5
5
 
6
+
6
7
  class ProviderCmdHandler(ShellCmdHandler):
7
8
  """Handler for the /provider command to view or change the current provider."""
8
-
9
+
9
10
  help_text = "Manage the current LLM provider. Usage: /provider [provider_name]"
10
-
11
+
11
12
  def run(self):
12
13
  """Execute the provider command."""
13
14
  if not self.after_cmd_line.strip():
@@ -15,11 +16,13 @@ class ProviderCmdHandler(ShellCmdHandler):
15
16
  current = get_current_provider()
16
17
  console.print(f"[bold]Current provider:[/bold] {current}")
17
18
  return
18
-
19
+
19
20
  # Argument provided, attempt to change provider
20
21
  new_provider = self.after_cmd_line.strip()
21
22
  try:
22
23
  set_provider(new_provider)
23
- console.print(f"[bold green]Provider changed to:[/bold green] {new_provider}")
24
+ console.print(
25
+ f"[bold green]Provider changed to:[/bold green] {new_provider}"
26
+ )
24
27
  except ValueError as e:
25
28
  console.print(f"[bold red]Error:[/bold red] {str(e)}")
@@ -6,8 +6,10 @@ class ReadShellHandler(ShellCmdHandler):
6
6
  help_text = "/read on|off: Enable or disable read permissions for tools. Usage: /read on or /read off."
7
7
 
8
8
  def run(self):
9
- if self.shell_state and getattr(self.shell_state, 'no_tools_mode', False):
10
- shared_console.print("[yellow]No tools are available in this mode (no tools, no context).[/yellow]")
9
+ if self.shell_state and getattr(self.shell_state, "no_tools_mode", False):
10
+ shared_console.print(
11
+ "[yellow]No tools are available in this mode (no tools, no context).[/yellow]"
12
+ )
11
13
  return
12
14
  if not self.shell_state:
13
15
  shared_console.print("[red]Shell state unavailable.[/red]")
@@ -1 +1 @@
1
- """Security management commands for chat mode."""
1
+ """Security management commands for chat mode."""
@@ -6,15 +6,17 @@ from janito.tools.url_whitelist import get_url_whitelist_manager
6
6
 
7
7
  class SecurityAllowedSitesCommand(BaseCommand):
8
8
  """Manage allowed sites for fetch_url tool."""
9
-
9
+
10
10
  def get_name(self) -> str:
11
11
  return "allowed-sites"
12
-
12
+
13
13
  def get_description(self) -> str:
14
14
  return "Manage allowed sites for the fetch_url tool"
15
-
15
+
16
16
  def get_usage(self):
17
- return self.get_description() + """
17
+ return (
18
+ self.get_description()
19
+ + """
18
20
  Usage: /security allowed-sites [command] [site]
19
21
 
20
22
  Commands:
@@ -29,6 +31,7 @@ Examples:
29
31
  /security allowed-sites remove yahoo.com
30
32
  /security allowed-sites clear
31
33
  """
34
+ )
32
35
  return """
33
36
  Usage: /security allowed-sites [command] [site]
34
37
 
@@ -44,18 +47,18 @@ Examples:
44
47
  /security allowed-sites remove yahoo.com
45
48
  /security allowed-sites clear
46
49
  """
47
-
50
+
48
51
  def run(self):
49
52
  """Execute the allowed-sites command."""
50
53
  args = self.after_cmd_line.strip().split()
51
-
54
+
52
55
  if not args:
53
56
  print(self.get_usage())
54
57
  return
55
-
58
+
56
59
  command = args[0].lower()
57
60
  whitelist_manager = get_url_whitelist_manager()
58
-
61
+
59
62
  if command == "list":
60
63
  sites = whitelist_manager.get_allowed_sites()
61
64
  if sites:
@@ -64,7 +67,7 @@ Examples:
64
67
  print(f" • {site}")
65
68
  else:
66
69
  print("No sites are whitelisted (all sites are allowed)")
67
-
70
+
68
71
  elif command == "add":
69
72
  if len(args) < 2:
70
73
  print("Error: Please specify a site to add")
@@ -74,7 +77,7 @@ Examples:
74
77
  print(f"✅ Added '{site}' to allowed sites")
75
78
  else:
76
79
  print(f"ℹ️ '{site}' is already in allowed sites")
77
-
80
+
78
81
  elif command == "remove":
79
82
  if len(args) < 2:
80
83
  print("Error: Please specify a site to remove")
@@ -84,11 +87,11 @@ Examples:
84
87
  print(f"✅ Removed '{site}' from allowed sites")
85
88
  else:
86
89
  print(f"ℹ️ '{site}' was not in allowed sites")
87
-
90
+
88
91
  elif command == "clear":
89
92
  whitelist_manager.clear_whitelist()
90
93
  print("✅ Cleared all allowed sites (all sites are now allowed)")
91
-
94
+
92
95
  else:
93
96
  print(f"Error: Unknown command '{command}'")
94
- print(self.get_usage())
97
+ print(self.get_usage())
@@ -1,18 +1,20 @@
1
1
  """Security command group for chat mode."""
2
2
 
3
3
  from janito.cli.chat_mode.shell.commands.base import ShellCmdHandler as BaseCommand
4
- from janito.cli.chat_mode.shell.commands.security.allowed_sites import SecurityAllowedSitesCommand
4
+ from janito.cli.chat_mode.shell.commands.security.allowed_sites import (
5
+ SecurityAllowedSitesCommand,
6
+ )
5
7
 
6
8
 
7
9
  class SecurityCommand(BaseCommand):
8
10
  """Security management command group."""
9
-
11
+
10
12
  def get_name(self) -> str:
11
13
  return "security"
12
-
14
+
13
15
  def get_description(self) -> str:
14
16
  return "Security management commands"
15
-
17
+
16
18
  def get_usage(self):
17
19
  return """
18
20
  Usage: /security <subcommand> [args...]
@@ -25,21 +27,23 @@ Examples:
25
27
  /security allowed-sites add tradingview.com
26
28
  /security allowed-sites remove yahoo.com
27
29
  """
28
-
30
+
29
31
  def __init__(self, after_cmd_line=None, shell_state=None):
30
32
  super().__init__(after_cmd_line=after_cmd_line, shell_state=shell_state)
31
33
  self.subcommands = {
32
- "allowed-sites": SecurityAllowedSitesCommand(after_cmd_line=after_cmd_line, shell_state=shell_state)
34
+ "allowed-sites": SecurityAllowedSitesCommand(
35
+ after_cmd_line=after_cmd_line, shell_state=shell_state
36
+ )
33
37
  }
34
-
38
+
35
39
  def run(self):
36
40
  """Execute the security command."""
37
41
  args = self.after_cmd_line.strip().split()
38
-
42
+
39
43
  if not args:
40
44
  print(self.get_usage())
41
45
  return
42
-
46
+
43
47
  subcommand = args[0].lower()
44
48
  if subcommand in self.subcommands:
45
49
  # Pass the remaining args to the subcommand
@@ -48,4 +52,4 @@ Examples:
48
52
  self.subcommands[subcommand].run()
49
53
  else:
50
54
  print(f"Error: Unknown security subcommand '{subcommand}'")
51
- print(self.get_usage())
55
+ print(self.get_usage())
@@ -56,8 +56,10 @@ class ToolsShellHandler(ShellCmdHandler):
56
56
 
57
57
  def run(self):
58
58
  # Check for no_tools_mode in shell_state
59
- if self.shell_state and getattr(self.shell_state, 'no_tools_mode', False):
60
- shared_console.print("[yellow]No tools are available in this mode (no tools, no context).[/yellow]")
59
+ if self.shell_state and getattr(self.shell_state, "no_tools_mode", False):
60
+ shared_console.print(
61
+ "[yellow]No tools are available in this mode (no tools, no context).[/yellow]"
62
+ )
61
63
  return
62
64
  try:
63
65
  import janito.tools # Ensure all tools are registered
@@ -6,7 +6,7 @@ from janito.cli.console import shared_console
6
6
 
7
7
  class UnrestrictedShellHandler(ShellCmdHandler):
8
8
  """Toggle unrestricted mode (equivalent to -u CLI flag)."""
9
-
9
+
10
10
  help_text = "Toggle unrestricted mode (disable path security and URL whitelist)"
11
11
 
12
12
  def run(self):
@@ -14,27 +14,32 @@ class UnrestrictedShellHandler(ShellCmdHandler):
14
14
  if not self.shell_state:
15
15
  shared_console.print("[red]Error: Shell state not available[/red]")
16
16
  return
17
-
17
+
18
18
  # Toggle unrestricted mode
19
- current_unrestricted = getattr(self.shell_state, 'unrestricted_mode', False)
19
+ current_unrestricted = getattr(self.shell_state, "unrestricted_mode", False)
20
20
  new_unrestricted = not current_unrestricted
21
-
21
+
22
22
  # Update shell state
23
23
  self.shell_state.unrestricted_mode = new_unrestricted
24
-
24
+
25
25
  # Update tools adapter
26
- if hasattr(self.shell_state, 'tools_adapter'):
27
- setattr(self.shell_state.tools_adapter, 'unrestricted_paths', new_unrestricted)
28
-
26
+ if hasattr(self.shell_state, "tools_adapter"):
27
+ setattr(
28
+ self.shell_state.tools_adapter, "unrestricted_paths", new_unrestricted
29
+ )
30
+
29
31
  # Update URL whitelist manager
30
32
  from janito.tools.url_whitelist import get_url_whitelist_manager
33
+
31
34
  whitelist_manager = get_url_whitelist_manager()
32
35
  whitelist_manager.set_unrestricted_mode(new_unrestricted)
33
-
36
+
34
37
  status = "enabled" if new_unrestricted else "disabled"
35
- warning = " (DANGEROUS - no path or URL restrictions)" if new_unrestricted else ""
36
-
38
+ warning = (
39
+ " (DANGEROUS - no path or URL restrictions)" if new_unrestricted else ""
40
+ )
41
+
37
42
  shared_console.print(
38
43
  f"[bold {'red' if new_unrestricted else 'green'}]"
39
44
  f"Unrestricted mode {status}{warning}[/bold {'red' if new_unrestricted else 'green'}]"
40
- )
45
+ )
@@ -6,8 +6,10 @@ class WriteShellHandler(ShellCmdHandler):
6
6
  help_text = "/write on|off: Enable or disable write permissions for tools. Usage: /write on or /write off."
7
7
 
8
8
  def run(self):
9
- if self.shell_state and getattr(self.shell_state, 'no_tools_mode', False):
10
- shared_console.print("[yellow]No tools are available in this mode (no tools, no context).[/yellow]")
9
+ if self.shell_state and getattr(self.shell_state, "no_tools_mode", False):
10
+ shared_console.print(
11
+ "[yellow]No tools are available in this mode (no tools, no context).[/yellow]"
12
+ )
11
13
  return
12
14
  if not self.shell_state:
13
15
  shared_console.print("[red]Shell state unavailable.[/red]")
@@ -20,17 +20,17 @@ def format_tokens(n, tag=None):
20
20
  def assemble_first_line(provider_name, model_name, role, agent=None):
21
21
  cwd = os.getcwd()
22
22
  home = os.path.expanduser("~")
23
-
23
+
24
24
  # Convert to relative path if under home directory
25
25
  if cwd.startswith(home):
26
- cwd_display = "~" + cwd[len(home):]
26
+ cwd_display = "~" + cwd[len(home) :]
27
27
  else:
28
28
  cwd_display = cwd
29
-
29
+
30
30
  # Shorten long paths for display
31
31
  if len(cwd_display) > 50:
32
32
  cwd_display = "..." + cwd_display[-47:]
33
-
33
+
34
34
  return f" Janito {VERSION} | Provider: <provider>{provider_name}</provider> | Model: <model>{model_name}</model> | Dir: <model>{cwd_display}</model>"
35
35
 
36
36