janito 2.7.0__py3-none-any.whl → 2.9.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 (121) hide show
  1. janito/__init__.py +0 -1
  2. janito/__main__.py +0 -1
  3. janito/_version.py +0 -3
  4. janito/agent/setup_agent.py +77 -10
  5. janito/agent/templates/profiles/{system_prompt_template_plain_software_developer.txt.j2 → system_prompt_template_Developer_with_Python_Tools.txt.j2} +5 -1
  6. janito/agent/templates/profiles/system_prompt_template_developer.txt.j2 +3 -12
  7. janito/cli/__init__.py +0 -1
  8. janito/cli/chat_mode/bindings.py +1 -1
  9. janito/cli/chat_mode/chat_entry.py +0 -2
  10. janito/cli/chat_mode/prompt_style.py +0 -3
  11. janito/cli/chat_mode/script_runner.py +9 -5
  12. janito/cli/chat_mode/session.py +100 -37
  13. janito/cli/chat_mode/session_profile_select.py +61 -52
  14. janito/cli/chat_mode/shell/commands/__init__.py +1 -5
  15. janito/cli/chat_mode/shell/commands/_priv_check.py +1 -0
  16. janito/cli/chat_mode/shell/commands/_priv_status.py +13 -0
  17. janito/cli/chat_mode/shell/commands/bang.py +10 -3
  18. janito/cli/chat_mode/shell/commands/conversation_restart.py +24 -7
  19. janito/cli/chat_mode/shell/commands/execute.py +22 -7
  20. janito/cli/chat_mode/shell/commands/help.py +4 -1
  21. janito/cli/chat_mode/shell/commands/model.py +13 -5
  22. janito/cli/chat_mode/shell/commands/privileges.py +21 -0
  23. janito/cli/chat_mode/shell/commands/prompt.py +0 -2
  24. janito/cli/chat_mode/shell/commands/read.py +22 -5
  25. janito/cli/chat_mode/shell/commands/tools.py +15 -4
  26. janito/cli/chat_mode/shell/commands/write.py +22 -5
  27. janito/cli/chat_mode/shell/input_history.py +3 -1
  28. janito/cli/chat_mode/shell/session/manager.py +0 -2
  29. janito/cli/chat_mode/toolbar.py +25 -19
  30. janito/cli/cli_commands/list_config.py +31 -0
  31. janito/cli/cli_commands/list_models.py +1 -1
  32. janito/cli/cli_commands/list_profiles.py +79 -0
  33. janito/cli/cli_commands/list_providers.py +1 -0
  34. janito/cli/cli_commands/list_tools.py +35 -7
  35. janito/cli/cli_commands/model_utils.py +5 -3
  36. janito/cli/cli_commands/show_config.py +16 -11
  37. janito/cli/cli_commands/show_system_prompt.py +23 -9
  38. janito/cli/config.py +0 -13
  39. janito/cli/core/getters.py +16 -1
  40. janito/cli/core/runner.py +25 -8
  41. janito/cli/core/setters.py +13 -76
  42. janito/cli/main_cli.py +60 -27
  43. janito/cli/prompt_core.py +19 -18
  44. janito/cli/prompt_setup.py +6 -3
  45. janito/cli/rich_terminal_reporter.py +19 -5
  46. janito/cli/single_shot_mode/handler.py +14 -5
  47. janito/cli/verbose_output.py +5 -1
  48. janito/config.py +1 -0
  49. janito/config_manager.py +15 -2
  50. janito/drivers/azure_openai/driver.py +27 -30
  51. janito/drivers/openai/driver.py +53 -36
  52. janito/formatting_token.py +12 -4
  53. janito/llm/agent.py +15 -6
  54. janito/llm/driver.py +1 -0
  55. janito/llm/provider.py +1 -1
  56. janito/provider_registry.py +31 -70
  57. janito/providers/__init__.py +1 -0
  58. janito/providers/anthropic/model_info.py +0 -1
  59. janito/providers/anthropic/provider.py +9 -14
  60. janito/providers/azure_openai/provider.py +10 -5
  61. janito/providers/deepseek/provider.py +5 -4
  62. janito/providers/google/model_info.py +4 -2
  63. janito/providers/google/provider.py +11 -5
  64. janito/providers/groq/__init__.py +1 -0
  65. janito/providers/groq/model_info.py +45 -0
  66. janito/providers/groq/provider.py +76 -0
  67. janito/providers/moonshotai/provider.py +11 -4
  68. janito/providers/openai/model_info.py +0 -1
  69. janito/providers/openai/provider.py +6 -7
  70. janito/tools/__init__.py +2 -0
  71. janito/tools/adapters/local/__init__.py +2 -1
  72. janito/tools/adapters/local/adapter.py +21 -4
  73. janito/tools/adapters/local/ask_user.py +1 -0
  74. janito/tools/adapters/local/copy_file.py +1 -0
  75. janito/tools/adapters/local/create_directory.py +1 -0
  76. janito/tools/adapters/local/create_file.py +1 -0
  77. janito/tools/adapters/local/delete_text_in_file.py +2 -1
  78. janito/tools/adapters/local/fetch_url.py +1 -0
  79. janito/tools/adapters/local/find_files.py +7 -6
  80. janito/tools/adapters/local/get_file_outline/core.py +1 -0
  81. janito/tools/adapters/local/get_file_outline/java_outline.py +22 -15
  82. janito/tools/adapters/local/get_file_outline/search_outline.py +1 -0
  83. janito/tools/adapters/local/move_file.py +1 -0
  84. janito/tools/adapters/local/open_html_in_browser.py +15 -5
  85. janito/tools/adapters/local/open_url.py +1 -0
  86. janito/tools/adapters/local/python_code_run.py +1 -0
  87. janito/tools/adapters/local/python_command_run.py +1 -0
  88. janito/tools/adapters/local/python_file_run.py +1 -0
  89. janito/tools/adapters/local/read_files.py +19 -4
  90. janito/tools/adapters/local/remove_directory.py +1 -0
  91. janito/tools/adapters/local/remove_file.py +1 -0
  92. janito/tools/adapters/local/replace_text_in_file.py +4 -3
  93. janito/tools/adapters/local/run_bash_command.py +1 -0
  94. janito/tools/adapters/local/run_powershell_command.py +1 -0
  95. janito/tools/adapters/local/search_text/core.py +18 -17
  96. janito/tools/adapters/local/search_text/match_lines.py +5 -5
  97. janito/tools/adapters/local/search_text/pattern_utils.py +1 -1
  98. janito/tools/adapters/local/search_text/traverse_directory.py +7 -7
  99. janito/tools/adapters/local/validate_file_syntax/core.py +1 -1
  100. janito/tools/adapters/local/validate_file_syntax/html_validator.py +8 -1
  101. janito/tools/disabled_tools.py +68 -0
  102. janito/tools/path_security.py +18 -11
  103. janito/tools/permissions.py +6 -0
  104. janito/tools/permissions_parse.py +4 -3
  105. janito/tools/tool_base.py +11 -5
  106. janito/tools/tool_use_tracker.py +1 -4
  107. janito/tools/tool_utils.py +1 -1
  108. janito/tools/tools_adapter.py +57 -25
  109. {janito-2.7.0.dist-info → janito-2.9.0.dist-info}/METADATA +11 -19
  110. janito-2.9.0.dist-info/RECORD +205 -0
  111. janito/cli/chat_mode/shell/commands/livelogs.py +0 -49
  112. janito/drivers/mistralai/driver.py +0 -41
  113. janito/providers/mistralai/model_info.py +0 -37
  114. janito/providers/mistralai/provider.py +0 -72
  115. janito/providers/provider_static_info.py +0 -21
  116. janito-2.7.0.dist-info/RECORD +0 -202
  117. /janito/agent/templates/profiles/{system_prompt_template_assistant.txt.j2 → system_prompt_template_model_conversation_without_tools_or_context.txt.j2} +0 -0
  118. {janito-2.7.0.dist-info → janito-2.9.0.dist-info}/WHEEL +0 -0
  119. {janito-2.7.0.dist-info → janito-2.9.0.dist-info}/entry_points.txt +0 -0
  120. {janito-2.7.0.dist-info → janito-2.9.0.dist-info}/licenses/LICENSE +0 -0
  121. {janito-2.7.0.dist-info → janito-2.9.0.dist-info}/top_level.txt +0 -0
janito/__init__.py CHANGED
@@ -4,4 +4,3 @@ Provides a CLI for credential management and an extensible driver system for LLM
4
4
  """
5
5
 
6
6
  from ._version import __version__
7
-
janito/__main__.py CHANGED
@@ -2,4 +2,3 @@ from .cli.main import main
2
2
 
3
3
  if __name__ == "__main__":
4
4
  main()
5
-
janito/_version.py CHANGED
@@ -53,6 +53,3 @@ except ImportError: # pragma: no cover – not available in editable installs
53
53
  return "unknown"
54
54
 
55
55
  __version__ = _resolve_version()
56
-
57
-
58
-
@@ -17,14 +17,55 @@ from janito.platform_discovery import PlatformDiscovery
17
17
  from janito.tools.tool_base import ToolPermissions
18
18
  from janito.tools.permissions import get_global_allowed_permissions
19
19
 
20
+
20
21
  def _load_template_content(profile, templates_dir):
21
22
  """
22
23
  Loads the template content for the given profile from the specified directory or package resources.
23
24
  If the profile template is not found in the default locations, tries to load from the user profiles directory ~/.janito/profiles.
25
+
26
+ Spaces in the profile name are converted to underscores to align with the file-naming convention (e.g. "Developer with Python Tools" ➜ "Developer_with_Python_Tools" (matches: system_prompt_template_Developer_with_Python_Tools.txt.j2)).
24
27
  """
28
+ # Sanitize profile for filename resolution (convert whitespace to underscores)
29
+ sanitized_profile = re.sub(r"\s+", "_", profile.strip()) if profile else profile
30
+
31
+ template_filename = f"system_prompt_template_{sanitized_profile}.txt.j2"
32
+ template_path = templates_dir / template_filename
33
+
34
+ # 1) Check local templates directory
35
+ if template_path.exists():
36
+ with open(template_path, "r", encoding="utf-8") as file:
37
+ return file.read(), template_path
38
+
39
+ # 2) Try package resources fallback
40
+ try:
41
+ with importlib.resources.files("janito.agent.templates.profiles").joinpath(
42
+ template_filename
43
+ ).open("r", encoding="utf-8") as file:
44
+ return file.read(), template_path
45
+ except (FileNotFoundError, ModuleNotFoundError, AttributeError):
46
+ pass
25
47
 
48
+ # 3) Finally, look in the user profiles directory (~/.janito/profiles)
49
+ user_profiles_dir = Path(os.path.expanduser("~/.janito/profiles"))
50
+ user_template_path = user_profiles_dir / template_filename
51
+ if user_template_path.exists():
52
+ with open(user_template_path, "r", encoding="utf-8") as file:
53
+ return file.read(), user_template_path
54
+
55
+ # If nothing matched, raise an informative error
56
+ raise FileNotFoundError(
57
+ f"[janito] Could not find profile-specific template '{template_filename}' in {template_path} nor in janito.agent.templates.profiles package nor in user profiles directory {user_template_path}."
58
+ )
59
+ # Replace spaces in profile name with underscores for filename resolution
60
+ sanitized_profile = re.sub(r"\\s+", "_", profile.strip()) if profile else profile
61
+ """
62
+ Loads the template content for the given profile from the specified directory or package resources.
63
+ If the profile template is not found in the default locations, tries to load from the user profiles directory ~/.janito/profiles.
64
+ """
26
65
 
27
- template_filename = f"system_prompt_template_{profile}.txt.j2"
66
+ # Sanitize profile name by replacing spaces with underscores to match filename conventions
67
+ sanitized_profile = re.sub(r"\\s+", "_", profile.strip())
68
+ template_filename = f"system_prompt_template_{sanitized_profile}.txt.j2"
28
69
  template_path = templates_dir / template_filename
29
70
  if template_path.exists():
30
71
  with open(template_path, "r", encoding="utf-8") as file:
@@ -68,7 +109,7 @@ def _prepare_template_context(role, profile, allowed_permissions):
68
109
  allowed_permissions = perm_str or None
69
110
  context["allowed_permissions"] = allowed_permissions
70
111
  # Inject platform info if execute permission is present
71
- if allowed_permissions and 'x' in allowed_permissions:
112
+ if allowed_permissions and "x" in allowed_permissions:
72
113
  pd = PlatformDiscovery()
73
114
  context["platform"] = pd.get_platform_name()
74
115
  context["python_version"] = pd.get_python_version()
@@ -76,7 +117,18 @@ def _prepare_template_context(role, profile, allowed_permissions):
76
117
  return context
77
118
 
78
119
 
79
- def _create_agent(provider_instance, tools_provider, role, system_prompt, input_queue, output_queue, verbose_agent, context, template_path, profile):
120
+ def _create_agent(
121
+ provider_instance,
122
+ tools_provider,
123
+ role,
124
+ system_prompt,
125
+ input_queue,
126
+ output_queue,
127
+ verbose_agent,
128
+ context,
129
+ template_path,
130
+ profile,
131
+ ):
80
132
  """
81
133
  Creates and returns an LLMAgent instance with the provided parameters.
82
134
  """
@@ -110,12 +162,16 @@ def setup_agent(
110
162
  allowed_permissions=None,
111
163
  profile=None,
112
164
  profile_system_prompt=None,
165
+ no_tools_mode=False,
113
166
  ):
114
167
  """
115
168
  Creates an agent. A system prompt is rendered from a template only when a profile is specified.
116
169
  """
117
- tools_provider = get_local_tools_adapter()
118
- tools_provider.set_verbose_tools(verbose_tools)
170
+ if no_tools_mode:
171
+ tools_provider = None
172
+ else:
173
+ tools_provider = get_local_tools_adapter()
174
+ tools_provider.set_verbose_tools(verbose_tools)
119
175
 
120
176
  # If zero_mode is enabled or no profile is given we skip the system prompt.
121
177
  if zero_mode or (profile is None and profile_system_prompt is None):
@@ -159,17 +215,23 @@ def setup_agent(
159
215
  # Debug output if requested
160
216
  debug_flag = False
161
217
  try:
162
- debug_flag = (hasattr(sys, 'argv') and ('--debug' in sys.argv or '--verbose' in sys.argv or '-v' in sys.argv))
218
+ debug_flag = hasattr(sys, "argv") and (
219
+ "--debug" in sys.argv or "--verbose" in sys.argv or "-v" in sys.argv
220
+ )
163
221
  except Exception:
164
222
  pass
165
223
  if debug_flag:
166
- rich_print(f"[bold magenta][DEBUG][/bold magenta] Rendering system prompt template '[cyan]{template_path.name}[/cyan]' with allowed_permissions: [yellow]{context.get('allowed_permissions')}[/yellow]")
167
- rich_print(f"[bold magenta][DEBUG][/bold magenta] Template context: [green]{context}[/green]")
224
+ rich_print(
225
+ f"[bold magenta][DEBUG][/bold magenta] Rendering system prompt template '[cyan]{template_path.name}[/cyan]' with allowed_permissions: [yellow]{context.get('allowed_permissions')}[/yellow]"
226
+ )
227
+ rich_print(
228
+ f"[bold magenta][DEBUG][/bold magenta] Template context: [green]{context}[/green]"
229
+ )
168
230
  start_render = time.time()
169
231
  rendered_prompt = template.render(**context)
170
232
  end_render = time.time()
171
233
  # Merge multiple empty lines into a single empty line
172
- rendered_prompt = re.sub(r'\n{3,}', '\n\n', rendered_prompt)
234
+ rendered_prompt = re.sub(r"\n{3,}", "\n\n", rendered_prompt)
173
235
 
174
236
  return _create_agent(
175
237
  provider_instance,
@@ -197,6 +259,7 @@ def create_configured_agent(
197
259
  allowed_permissions=None,
198
260
  profile=None,
199
261
  profile_system_prompt=None,
262
+ no_tools_mode=False,
200
263
  ):
201
264
  """
202
265
  Normalizes agent setup for all CLI modes.
@@ -218,6 +281,9 @@ def create_configured_agent(
218
281
  driver = None
219
282
  if hasattr(provider_instance, "create_driver"):
220
283
  driver = provider_instance.create_driver()
284
+ # Ensure no tools are passed to the driver when --no-tools flag is active
285
+ if no_tools_mode:
286
+ driver.tools_adapter = None
221
287
  driver.start() # Ensure the driver background thread is started
222
288
  input_queue = getattr(driver, "input_queue", None)
223
289
  output_queue = getattr(driver, "output_queue", None)
@@ -235,7 +301,8 @@ def create_configured_agent(
235
301
  allowed_permissions=allowed_permissions,
236
302
  profile=profile,
237
303
  profile_system_prompt=profile_system_prompt,
304
+ no_tools_mode=no_tools_mode,
238
305
  )
239
306
  if driver is not None:
240
307
  agent.driver = driver # Attach driver to agent for thread management
241
- return agent
308
+ return agent
@@ -1,9 +1,13 @@
1
- You are: software developer
1
+ {# General role setup
2
+ ex. "Search in code" -> Python Developer -> find(*.py) | Java Developer -> find(*.java)
3
+ #}
4
+ You are: {{ role }}
2
5
 
3
6
  {# Improves tool selection and platform specific constrains, eg, path format, C:\ vs /path #}
4
7
  {% if allowed_permissions and 'x' in allowed_permissions %}
5
8
  You will be using the following environment:
6
9
  Platform: {{ platform }}
10
+ Python version: {{ python_version }}
7
11
  Shell/Environment: {{ shell_info }}
8
12
  {% endif %}
9
13
 
@@ -1,21 +1,12 @@
1
- {# General role setup
2
- ex. "Search in code" -> Python Developer -> find(*.py) | Java Developer -> find(*.java)
3
- #}
4
- You are: {{ role }}
1
+ You are: software developer
5
2
 
6
3
  {# Improves tool selection and platform specific constrains, eg, path format, C:\ vs /path #}
7
- {% if allowed_permissions and 'x' in allowed_permissions %}
8
4
  You will be using the following environment:
9
- Platform: {{ platform }}
10
- Python version: {{ python_version }}
11
- Shell/Environment: {{ shell_info }}
12
- {% endif %}
13
-
5
+ Platform: Windows
6
+ Shell/Environment: PowerShell
14
7
 
15
8
 
16
- {% if allowed_permissions and 'r' in allowed_permissions %}
17
9
  Before answering map the questions to artifacts found in the current directory - the current project.
18
- {% endif %}
19
10
 
20
11
  Respond according to the following guidelines:
21
12
  {% if allowed_permissions %}
janito/cli/__init__.py CHANGED
@@ -7,4 +7,3 @@ __all__ = [
7
7
  "format_tokens",
8
8
  "format_generation_time",
9
9
  ]
10
-
@@ -5,6 +5,7 @@ Key bindings for Janito Chat CLI.
5
5
  from prompt_toolkit.key_binding import KeyBindings
6
6
  from janito.tools.permissions import get_global_allowed_permissions
7
7
 
8
+
8
9
  class KeyBindingsFactory:
9
10
  @staticmethod
10
11
  def create():
@@ -35,4 +36,3 @@ class KeyBindingsFactory:
35
36
  buf.validate_and_handle()
36
37
 
37
38
  return bindings
38
-
@@ -13,11 +13,9 @@ def main(args=None):
13
13
  console.clear()
14
14
  from janito.version import __version__
15
15
 
16
-
17
16
  session = ChatSession(console, args=args)
18
17
  session.run()
19
18
 
20
19
 
21
20
  if __name__ == "__main__":
22
21
  main()
23
-
@@ -15,11 +15,8 @@ chat_shell_style = Style.from_dict(
15
15
  "tokens_in": "fg:#00af5f",
16
16
  "tokens_out": "fg:#01814a",
17
17
  "max-tokens": "fg:#888888",
18
-
19
-
20
18
  "key-toggle-on": "bg:#ffd700 fg:#232323 bold",
21
19
  "key-toggle-off": "bg:#444444 fg:#ffffff bold",
22
20
  "cmd-label": "bg:#ff9500 fg:#232323 bold",
23
21
  }
24
22
  )
25
-
@@ -23,6 +23,7 @@ Typical usage
23
23
  The ``ChatScriptRunner`` purposefully replaces the internal call to the agent
24
24
  with a real agent call by default. If you want to use a stub, you must modify the runner implementation.
25
25
  """
26
+
26
27
  from __future__ import annotations
27
28
 
28
29
  from types import MethodType
@@ -43,7 +44,6 @@ auth_warning = (
43
44
  )
44
45
 
45
46
 
46
-
47
47
  class ChatScriptRunner:
48
48
  """Run a **ChatSession** non-interactively using a predefined set of inputs."""
49
49
 
@@ -81,6 +81,7 @@ class ChatScriptRunner:
81
81
  # is incompatible with headless test runs.
82
82
  if "args" not in chat_session_kwargs or chat_session_kwargs["args"] is None:
83
83
  from types import SimpleNamespace
84
+
84
85
  chat_session_kwargs["args"] = SimpleNamespace(
85
86
  profile="developer",
86
87
  provider=self.provider,
@@ -94,6 +95,7 @@ class ChatScriptRunner:
94
95
  # 1) Patch *ChatSession._create_prompt_session* to do nothing – the
95
96
  # interactive session object is irrelevant for scripted runs.
96
97
  from types import MethodType as _MT
98
+
97
99
  if "_original_create_prompt_session" not in ChatSession.__dict__:
98
100
  ChatSession._original_create_prompt_session = ChatSession._create_prompt_session # type: ignore[attr-defined]
99
101
  ChatSession._create_prompt_session = _MT(lambda _self: None, ChatSession) # type: ignore[method-assign]
@@ -101,17 +103,20 @@ class ChatScriptRunner:
101
103
  # Resolve provider instance now so that ChatSession uses a ready agent
102
104
  provider_instance = ProviderRegistry().get_instance(self.provider)
103
105
  if provider_instance is None:
104
- raise RuntimeError(f"Provider '{self.provider}' is not available on this system.")
106
+ raise RuntimeError(
107
+ f"Provider '{self.provider}' is not available on this system."
108
+ )
105
109
  driver_config = LLMDriverConfig(model=self.model)
106
110
  chat_session_kwargs.setdefault("provider_instance", provider_instance)
107
111
  chat_session_kwargs.setdefault("llm_driver_config", driver_config)
108
112
 
109
113
  self.chat_session = ChatSession(console=self.console, **chat_session_kwargs)
110
114
 
111
-
112
115
  # Monkey-patch the *ChatSession._handle_input* method so that it pops
113
116
  # from our in-memory queue instead of reading from stdin.
114
- def _script_handle_input(this: ChatSession, _prompt_session_unused): # noqa: D401
117
+ def _script_handle_input(
118
+ this: ChatSession, _prompt_session_unused
119
+ ): # noqa: D401
115
120
  if not self._input_queue:
116
121
  # Signal normal shutdown
117
122
  this._handle_exit()
@@ -151,4 +156,3 @@ class ChatScriptRunner:
151
156
 
152
157
  # Convenience alias so tests can simply call *runner()*
153
158
  __call__ = run
154
-
@@ -25,17 +25,20 @@ from janito.cli.prompt_setup import setup_agent_and_prompt_handler
25
25
 
26
26
  import time
27
27
 
28
+
28
29
  class ChatShellState:
29
30
  def __init__(self, mem_history, conversation_history):
30
31
  self.mem_history = mem_history
31
32
  self.conversation_history = conversation_history
32
33
  self.paste_mode = False
33
- self._port = None
34
+
34
35
  self._pid = None
35
36
  self._stdout_path = None
36
37
  self._stderr_path = None
37
- self.livereload_stderr_path = None
38
- self._status = "starting" # Tracks the current status (updated by background thread/UI)
38
+
39
+ self._status = (
40
+ "starting" # Tracks the current status (updated by background thread/UI)
41
+ )
39
42
 
40
43
  self.last_usage_info = {}
41
44
  self.last_elapsed = None
@@ -44,6 +47,8 @@ class ChatShellState:
44
47
  self.agent = None
45
48
  self.main_agent = None
46
49
  self.main_enabled = False
50
+ self.no_tools_mode = False
51
+
47
52
 
48
53
  class ChatSession:
49
54
  def __init__(
@@ -67,53 +72,92 @@ class ChatSession:
67
72
  self.provider_instance = provider_instance
68
73
  self.llm_driver_config = llm_driver_config
69
74
 
70
- profile, role, profile_system_prompt = self._select_profile_and_role(args, role)
75
+ profile, role, profile_system_prompt, no_tools_mode = (
76
+ self._select_profile_and_role(args, role)
77
+ )
78
+ # Propagate no_tools_mode flag to downstream components via args
79
+ if args is not None and not hasattr(args, "no_tools_mode"):
80
+ try:
81
+ setattr(args, "no_tools_mode", no_tools_mode)
82
+ except Exception:
83
+ pass
71
84
  conversation_history = self._create_conversation_history()
72
85
  self.agent, self._prompt_handler = self._setup_agent_and_prompt_handler(
73
- args, provider_instance, llm_driver_config, role, verbose_tools, verbose_agent, allowed_permissions, profile, profile_system_prompt, conversation_history
86
+ args,
87
+ provider_instance,
88
+ llm_driver_config,
89
+ role,
90
+ verbose_tools,
91
+ verbose_agent,
92
+ allowed_permissions,
93
+ profile,
94
+ profile_system_prompt,
95
+ conversation_history,
74
96
  )
75
97
  self.shell_state = ChatShellState(self.mem_history, conversation_history)
76
98
  self.shell_state.agent = self.agent
99
+ # Set no_tools_mode if present
100
+ self.shell_state.no_tools_mode = bool(no_tools_mode)
77
101
  self._filter_execution_tools()
78
102
  from janito.perf_singleton import performance_collector
103
+
79
104
  self.performance_collector = performance_collector
80
105
  self.key_bindings = KeyBindingsFactory.create()
81
106
  self._prompt_handler.agent = self.agent
82
- self._prompt_handler.conversation_history = self.shell_state.conversation_history
107
+ self._prompt_handler.conversation_history = (
108
+ self.shell_state.conversation_history
109
+ )
83
110
  self._support = False
84
- self._maybe_enable_web_support(args)
85
111
 
86
112
  def _select_profile_and_role(self, args, role):
87
113
  profile = getattr(args, "profile", None) if args is not None else None
88
114
  role_arg = getattr(args, "role", None) if args is not None else None
89
115
  profile_system_prompt = None
116
+ no_tools_mode = False
90
117
  if profile is None and role_arg is None:
91
118
  try:
92
119
  from janito.cli.chat_mode.session_profile_select import select_profile
120
+
93
121
  result = select_profile()
94
122
  if isinstance(result, dict):
95
123
  profile = result.get("profile")
96
124
  profile_system_prompt = result.get("profile_system_prompt")
125
+ no_tools_mode = result.get("no_tools_mode", False)
97
126
  elif isinstance(result, str) and result.startswith("role:"):
98
127
  role = result[len("role:") :].strip()
99
- profile = "developer"
128
+ profile = "Developer with Python Tools"
100
129
  else:
101
130
  profile = (
102
- "developer" if result == "plain_software_developer" else result
131
+ "Developer with Python Tools"
132
+ if result == "Developer"
133
+ else result
103
134
  )
104
135
  except ImportError:
105
- profile = "helpful assistant"
136
+ profile = "Raw Model Session (no tools, no context)"
106
137
  if role_arg is not None:
107
138
  role = role_arg
108
139
  if profile is None:
109
- profile = "developer"
110
- return profile, role, profile_system_prompt
140
+ profile = "Developer with Python Tools"
141
+ return profile, role, profile_system_prompt, no_tools_mode
111
142
 
112
143
  def _create_conversation_history(self):
113
144
  from janito.conversation_history import LLMConversationHistory
145
+
114
146
  return LLMConversationHistory()
115
147
 
116
- def _setup_agent_and_prompt_handler(self, args, provider_instance, llm_driver_config, role, verbose_tools, verbose_agent, allowed_permissions, profile, profile_system_prompt, conversation_history):
148
+ def _setup_agent_and_prompt_handler(
149
+ self,
150
+ args,
151
+ provider_instance,
152
+ llm_driver_config,
153
+ role,
154
+ verbose_tools,
155
+ verbose_agent,
156
+ allowed_permissions,
157
+ profile,
158
+ profile_system_prompt,
159
+ conversation_history,
160
+ ):
117
161
  return setup_agent_and_prompt_handler(
118
162
  args=args,
119
163
  provider_instance=provider_instance,
@@ -129,23 +173,16 @@ class ChatSession:
129
173
 
130
174
  def _filter_execution_tools(self):
131
175
  try:
132
- getattr(__import__('janito.tools', fromlist=['get_local_tools_adapter']), 'get_local_tools_adapter')()
176
+ getattr(
177
+ __import__("janito.tools", fromlist=["get_local_tools_adapter"]),
178
+ "get_local_tools_adapter",
179
+ )()
133
180
  except Exception as e:
134
- self.console.print(f"[yellow]Warning: Could not filter execution tools at startup: {e}[/yellow]")
135
-
136
- def _maybe_enable_web_support(self, args):
137
- if args and getattr(args, "web", False):
138
- self._support = True
139
- self.shell_state._support = self._support
140
- from janito.cli._starter import _start_and_watch
141
- from janito.cli.config import get__port
142
- import threading
143
- from rich.console import Console
144
- Console().print("[yellow]Starting in background...[/yellow]")
145
- self._lock = threading.Lock()
146
- _thread = _start_and_watch(
147
- self.shell_state, self._lock, get__port()
181
+ self.console.print(
182
+ f"[yellow]Warning: Could not filter execution tools at startup: {e}[/yellow]"
148
183
  )
184
+
185
+ _thread = _start_and_watch(self.shell_state, self._lock, get__port())
149
186
  self._thread = _thread
150
187
  else:
151
188
  self.shell_state._support = False
@@ -154,22 +191,43 @@ class ChatSession:
154
191
  def run(self):
155
192
  self.console.clear()
156
193
  from janito import __version__
194
+
195
+ self.console.print(f"[bold green]Janito Chat Mode v{__version__}[/bold green]")
157
196
  self.console.print(
158
- f"[bold green]Janito Chat Mode v{__version__}[/bold green]"
197
+ "[green]/help for commands /exit or Ctrl+C to quit[/green]"
159
198
  )
160
- self.console.print("[green]/help for commands /exit or Ctrl+C to quit[/green]")
161
199
  import os
200
+
162
201
  cwd = os.getcwd()
163
- home = os.path.expanduser('~')
202
+ home = os.path.expanduser("~")
164
203
  if cwd.startswith(home):
165
- cwd_display = '~' + cwd[len(home):]
204
+ cwd_display = "~" + cwd[len(home) :]
166
205
  else:
167
206
  cwd_display = cwd
168
- self.console.print(f"[green]Working Dir:[/green] {cwd_display}")
207
+ from janito.cli.chat_mode.shell.commands._priv_status import (
208
+ get_privilege_status_message,
209
+ )
210
+
211
+ priv_status = get_privilege_status_message()
212
+ self.console.print(
213
+ f"[green]Working Dir:[/green] {cwd_display} | {priv_status}"
214
+ )
169
215
 
170
- from janito.cli.chat_mode.shell.commands._priv_check import user_has_any_privileges
171
- if not user_has_any_privileges():
172
- self.console.print("[yellow]Note: You currently have no privileges enabled. If you need to interact with files or the system, enable permissions using /read on, /write on, or /execute on.[/yellow]")
216
+ from janito.cli.chat_mode.shell.commands._priv_check import (
217
+ user_has_any_privileges,
218
+ )
219
+
220
+ perms = __import__(
221
+ "janito.tools.permissions", fromlist=["get_global_allowed_permissions"]
222
+ ).get_global_allowed_permissions()
223
+ if perms.execute:
224
+ self.console.print(
225
+ "[bold red]Commands/Code execution is enabled - Be cautious[/bold red]"
226
+ )
227
+ if not (perms.read or perms.write or perms.execute):
228
+ self.console.print(
229
+ "[yellow]Note: You currently have no privileges enabled. If you need to interact with files or the system, enable permissions using /read on, /write on, or /execute on.[/yellow]"
230
+ )
173
231
 
174
232
  session = self._create_prompt_session()
175
233
  self._chat_loop(session)
@@ -204,6 +262,7 @@ class ChatSession:
204
262
  def _process_prompt(self, cmd_input):
205
263
  try:
206
264
  import time
265
+
207
266
  final_event = (
208
267
  self._prompt_handler.agent.last_event
209
268
  if hasattr(self._prompt_handler.agent, "last_event")
@@ -215,8 +274,11 @@ class ChatSession:
215
274
  elapsed = end_time - start_time
216
275
  self.msg_count += 1
217
276
  from janito.formatting_token import print_token_message_summary
277
+
218
278
  usage = self.performance_collector.get_last_request_usage()
219
- print_token_message_summary(self.console, self.msg_count, usage, elapsed=elapsed)
279
+ print_token_message_summary(
280
+ self.console, self.msg_count, usage, elapsed=elapsed
281
+ )
220
282
  if final_event and hasattr(final_event, "metadata"):
221
283
  exit_reason = (
222
284
  final_event.metadata.get("exit_reason")
@@ -230,6 +292,7 @@ class ChatSession:
230
292
  except Exception as exc:
231
293
  self.console.print(f"[red]Exception in agent: {exc}[/red]")
232
294
  import traceback
295
+
233
296
  self.console.print(traceback.format_exc())
234
297
 
235
298
  def _create_prompt_session(self):