janito 2.6.1__py3-none-any.whl → 2.8.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. janito/__init__.py +6 -7
  2. janito/__main__.py +4 -5
  3. janito/_version.py +55 -58
  4. janito/agent/setup_agent.py +308 -241
  5. janito/agent/templates/profiles/{system_prompt_template_software developer.txt.j2 → system_prompt_template_Developer_with_Python_Tools.txt.j2} +43 -39
  6. janito/agent/templates/profiles/system_prompt_template_developer.txt.j2 +3 -12
  7. janito/cli/__init__.py +9 -10
  8. janito/cli/chat_mode/bindings.py +38 -38
  9. janito/cli/chat_mode/chat_entry.py +21 -23
  10. janito/cli/chat_mode/prompt_style.py +22 -25
  11. janito/cli/chat_mode/script_runner.py +158 -154
  12. janito/cli/chat_mode/session.py +80 -35
  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/bang.py +10 -3
  17. janito/cli/chat_mode/shell/commands/conversation_restart.py +24 -7
  18. janito/cli/chat_mode/shell/commands/execute.py +22 -7
  19. janito/cli/chat_mode/shell/commands/help.py +4 -1
  20. janito/cli/chat_mode/shell/commands/model.py +13 -5
  21. janito/cli/chat_mode/shell/commands/privileges.py +21 -0
  22. janito/cli/chat_mode/shell/commands/prompt.py +0 -2
  23. janito/cli/chat_mode/shell/commands/read.py +22 -5
  24. janito/cli/chat_mode/shell/commands/tools.py +15 -4
  25. janito/cli/chat_mode/shell/commands/write.py +22 -5
  26. janito/cli/chat_mode/shell/input_history.py +3 -1
  27. janito/cli/chat_mode/shell/session/manager.py +0 -2
  28. janito/cli/chat_mode/toolbar.py +25 -19
  29. janito/cli/cli_commands/list_models.py +1 -1
  30. janito/cli/cli_commands/list_providers.py +1 -0
  31. janito/cli/cli_commands/list_tools.py +35 -7
  32. janito/cli/cli_commands/model_utils.py +5 -3
  33. janito/cli/cli_commands/show_config.py +12 -0
  34. janito/cli/cli_commands/show_system_prompt.py +23 -9
  35. janito/cli/config.py +0 -13
  36. janito/cli/core/getters.py +2 -0
  37. janito/cli/core/runner.py +25 -8
  38. janito/cli/core/setters.py +13 -76
  39. janito/cli/main_cli.py +9 -25
  40. janito/cli/prompt_core.py +19 -18
  41. janito/cli/prompt_setup.py +6 -3
  42. janito/cli/rich_terminal_reporter.py +19 -5
  43. janito/cli/single_shot_mode/handler.py +104 -95
  44. janito/cli/verbose_output.py +5 -1
  45. janito/config_manager.py +4 -0
  46. janito/drivers/azure_openai/driver.py +27 -30
  47. janito/drivers/driver_registry.py +27 -27
  48. janito/drivers/openai/driver.py +452 -436
  49. janito/formatting_token.py +12 -4
  50. janito/llm/agent.py +15 -6
  51. janito/llm/driver.py +1 -0
  52. janito/provider_registry.py +139 -178
  53. janito/providers/__init__.py +2 -0
  54. janito/providers/anthropic/model_info.py +40 -41
  55. janito/providers/anthropic/provider.py +75 -80
  56. janito/providers/azure_openai/provider.py +9 -4
  57. janito/providers/deepseek/provider.py +5 -4
  58. janito/providers/google/model_info.py +4 -2
  59. janito/providers/google/provider.py +11 -5
  60. janito/providers/groq/__init__.py +1 -0
  61. janito/providers/groq/model_info.py +46 -0
  62. janito/providers/groq/provider.py +76 -0
  63. janito/providers/moonshotai/__init__.py +1 -0
  64. janito/providers/moonshotai/model_info.py +15 -0
  65. janito/providers/moonshotai/provider.py +89 -0
  66. janito/providers/openai/provider.py +6 -7
  67. janito/tools/__init__.py +2 -0
  68. janito/tools/adapters/local/__init__.py +67 -66
  69. janito/tools/adapters/local/adapter.py +21 -4
  70. janito/tools/adapters/local/ask_user.py +1 -0
  71. janito/tools/adapters/local/copy_file.py +1 -0
  72. janito/tools/adapters/local/create_directory.py +1 -0
  73. janito/tools/adapters/local/create_file.py +1 -0
  74. janito/tools/adapters/local/delete_text_in_file.py +2 -1
  75. janito/tools/adapters/local/fetch_url.py +1 -0
  76. janito/tools/adapters/local/find_files.py +7 -6
  77. janito/tools/adapters/local/get_file_outline/core.py +1 -0
  78. janito/tools/adapters/local/get_file_outline/java_outline.py +22 -15
  79. janito/tools/adapters/local/get_file_outline/search_outline.py +1 -0
  80. janito/tools/adapters/local/move_file.py +4 -3
  81. janito/tools/adapters/local/open_html_in_browser.py +15 -5
  82. janito/tools/adapters/local/open_url.py +1 -0
  83. janito/tools/adapters/local/python_code_run.py +1 -0
  84. janito/tools/adapters/local/python_command_run.py +1 -0
  85. janito/tools/adapters/local/python_file_run.py +1 -0
  86. janito/tools/adapters/local/read_files.py +55 -40
  87. janito/tools/adapters/local/remove_directory.py +1 -0
  88. janito/tools/adapters/local/remove_file.py +1 -0
  89. janito/tools/adapters/local/replace_text_in_file.py +4 -3
  90. janito/tools/adapters/local/run_bash_command.py +1 -0
  91. janito/tools/adapters/local/run_powershell_command.py +1 -0
  92. janito/tools/adapters/local/search_text/core.py +18 -17
  93. janito/tools/adapters/local/search_text/match_lines.py +5 -5
  94. janito/tools/adapters/local/search_text/pattern_utils.py +1 -1
  95. janito/tools/adapters/local/search_text/traverse_directory.py +7 -7
  96. janito/tools/adapters/local/validate_file_syntax/core.py +1 -1
  97. janito/tools/adapters/local/validate_file_syntax/html_validator.py +8 -1
  98. janito/tools/disabled_tools.py +68 -0
  99. janito/tools/path_security.py +18 -11
  100. janito/tools/permissions.py +6 -0
  101. janito/tools/permissions_parse.py +4 -3
  102. janito/tools/tool_base.py +11 -5
  103. janito/tools/tool_use_tracker.py +1 -4
  104. janito/tools/tool_utils.py +1 -1
  105. janito/tools/tools_adapter.py +57 -25
  106. {janito-2.6.1.dist-info → janito-2.8.0.dist-info}/METADATA +411 -417
  107. janito-2.8.0.dist-info/RECORD +202 -0
  108. janito/cli/chat_mode/shell/commands/livelogs.py +0 -49
  109. janito/drivers/mistralai/driver.py +0 -41
  110. janito/providers/mistralai/model_info.py +0 -37
  111. janito/providers/mistralai/provider.py +0 -72
  112. janito/providers/provider_static_info.py +0 -18
  113. janito-2.6.1.dist-info/RECORD +0 -199
  114. /janito/agent/templates/profiles/{system_prompt_template_assistant.txt.j2 → system_prompt_template_model_conversation_without_tools_or_context.txt.j2} +0 -0
  115. {janito-2.6.1.dist-info → janito-2.8.0.dist-info}/WHEEL +0 -0
  116. {janito-2.6.1.dist-info → janito-2.8.0.dist-info}/entry_points.txt +0 -0
  117. {janito-2.6.1.dist-info → janito-2.8.0.dist-info}/licenses/LICENSE +0 -0
  118. {janito-2.6.1.dist-info → janito-2.8.0.dist-info}/top_level.txt +0 -0
@@ -3,6 +3,7 @@ from janito.tools.tool_events import ToolCallStarted, ToolCallFinished, ToolCall
3
3
  from janito.exceptions import ToolCallException
4
4
  from janito.tools.tool_base import ToolPermissions
5
5
 
6
+
6
7
  class ToolsAdapterBase:
7
8
  """
8
9
  Composable entry point for tools management and provisioning in LLM pipelines.
@@ -11,9 +12,7 @@ class ToolsAdapterBase:
11
12
  After refactor, also responsible for tool execution.
12
13
  """
13
14
 
14
- def __init__(
15
- self, tools=None, event_bus=None
16
- ):
15
+ def __init__(self, tools=None, event_bus=None):
17
16
  self._tools = tools or []
18
17
  self._event_bus = event_bus # event bus can be set on all adapters
19
18
  self.verbose_tools = False
@@ -32,31 +31,43 @@ class ToolsAdapterBase:
32
31
  def is_tool_allowed(self, tool):
33
32
  """Check if a tool is allowed based on current global AllowedPermissionsState."""
34
33
  from janito.tools.permissions import get_global_allowed_permissions
34
+
35
35
  allowed_permissions = get_global_allowed_permissions()
36
36
  perms = tool.permissions # permissions are mandatory and type-checked
37
37
  # If all permissions are False, block all tools
38
- if not (allowed_permissions.read or allowed_permissions.write or allowed_permissions.execute):
38
+ if not (
39
+ allowed_permissions.read
40
+ or allowed_permissions.write
41
+ or allowed_permissions.execute
42
+ ):
39
43
  return False
40
- for perm in ['read', 'write', 'execute']:
44
+ for perm in ["read", "write", "execute"]:
41
45
  if getattr(perms, perm) and not getattr(allowed_permissions, perm):
42
46
  return False
43
47
  return True
44
48
 
45
49
  def get_tools(self):
46
- """Return the list of enabled tools managed by this provider, filtered by allowed permissions."""
47
- tools = [tool for tool in self._tools if self.is_tool_allowed(tool)]
50
+ """Return the list of enabled tools managed by this provider, filtered by allowed permissions and disabled tools."""
51
+ from janito.tools.disabled_tools import is_tool_disabled
52
+
53
+ tools = [
54
+ tool
55
+ for tool in self._tools
56
+ if self.is_tool_allowed(tool)
57
+ and not is_tool_disabled(getattr(tool, "tool_name", str(tool)))
58
+ ]
48
59
  return tools
49
60
 
50
61
  def set_allowed_permissions(self, allowed_permissions):
51
62
  """Set the allowed permissions at runtime. This now updates the global AllowedPermissionsState only."""
52
63
  from janito.tools.permissions import set_global_allowed_permissions
64
+
53
65
  set_global_allowed_permissions(allowed_permissions)
54
66
 
55
67
  def add_tool(self, tool):
56
68
  self._tools.append(tool)
57
69
 
58
- def clear_tools(self):
59
- self._tools = []
70
+
60
71
 
61
72
  def _validate_arguments_against_schema(self, arguments: dict, schema: dict):
62
73
  properties = schema.get("properties", {})
@@ -134,15 +145,14 @@ class ToolsAdapterBase:
134
145
  if not accepts_kwargs:
135
146
  unexpected = [k for k in arguments.keys() if k not in params]
136
147
  if unexpected:
137
- return (
138
- "Unexpected argument(s): " + ", ".join(sorted(unexpected))
139
- )
148
+ return "Unexpected argument(s): " + ", ".join(sorted(unexpected))
140
149
 
141
150
  # Check for missing required arguments (ignoring *args / **kwargs / self)
142
151
  required_params = [
143
152
  name
144
153
  for name, p in params.items()
145
- if p.kind in (
154
+ if p.kind
155
+ in (
146
156
  inspect.Parameter.POSITIONAL_OR_KEYWORD,
147
157
  inspect.Parameter.KEYWORD_ONLY,
148
158
  )
@@ -163,45 +173,63 @@ class ToolsAdapterBase:
163
173
  self._ensure_tool_exists(tool, tool_name, request_id, arguments)
164
174
  func = self._get_tool_callable(tool)
165
175
 
166
- validation_error = self._validate_tool_arguments(tool, func, arguments, tool_name, request_id)
176
+ validation_error = self._validate_tool_arguments(
177
+ tool, func, arguments, tool_name, request_id
178
+ )
167
179
  if validation_error:
168
180
  return validation_error
169
181
 
170
182
  # --- SECURITY: Path restriction enforcement ---
171
- if not getattr(self, 'unrestricted_paths', False):
172
- workdir = getattr(self, 'workdir', None)
183
+ if not getattr(self, "unrestricted_paths", False):
184
+ workdir = getattr(self, "workdir", None)
173
185
  # Ensure workdir is always set; default to current working directory.
174
186
  if not workdir:
175
187
  import os
188
+
176
189
  workdir = os.getcwd()
177
- from janito.tools.path_security import validate_paths_in_arguments, PathSecurityError
178
- schema = getattr(tool, 'schema', None)
190
+ from janito.tools.path_security import (
191
+ validate_paths_in_arguments,
192
+ PathSecurityError,
193
+ )
194
+
195
+ schema = getattr(tool, "schema", None)
179
196
  try:
180
197
  validate_paths_in_arguments(arguments, workdir, schema=schema)
181
198
  except PathSecurityError as sec_err:
182
199
  # Publish both a ToolCallError and a user-facing ReportEvent for path security errors
183
- self._publish_tool_call_error(tool_name, request_id, str(sec_err), arguments)
200
+ self._publish_tool_call_error(
201
+ tool_name, request_id, str(sec_err), arguments
202
+ )
184
203
  if self._event_bus:
185
- from janito.report_events import ReportEvent, ReportSubtype, ReportAction
204
+ from janito.report_events import (
205
+ ReportEvent,
206
+ ReportSubtype,
207
+ ReportAction,
208
+ )
209
+
186
210
  self._event_bus.publish(
187
211
  ReportEvent(
188
212
  subtype=ReportSubtype.ERROR,
189
213
  message=f"[SECURITY] Path access denied: {sec_err}",
190
214
  action=ReportAction.EXECUTE,
191
215
  tool=tool_name,
192
- context={"arguments": arguments, "request_id": request_id}
216
+ context={"arguments": arguments, "request_id": request_id},
193
217
  )
194
218
  )
195
219
  return f"Security error: {sec_err}"
196
220
  # --- END SECURITY ---
197
221
 
198
222
  self._publish_tool_call_started(tool_name, request_id, arguments)
199
- self._print_verbose(f"[tools-adapter] Executing tool: {tool_name} with arguments: {arguments}")
223
+ self._print_verbose(
224
+ f"[tools-adapter] Executing tool: {tool_name} with arguments: {arguments}"
225
+ )
200
226
  try:
201
227
  result = self.execute(tool, **(arguments or {}), **kwargs)
202
228
  except Exception as e:
203
229
  self._handle_execution_error(tool_name, request_id, e, arguments)
204
- self._print_verbose(f"[tools-adapter] Tool execution finished: {tool_name} -> {result}")
230
+ self._print_verbose(
231
+ f"[tools-adapter] Tool execution finished: {tool_name} -> {result}"
232
+ )
205
233
  self._publish_tool_call_finished(tool_name, request_id, result)
206
234
  return result
207
235
 
@@ -212,9 +240,13 @@ class ToolsAdapterBase:
212
240
  return sig_error
213
241
  schema = getattr(tool, "schema", None)
214
242
  if schema and arguments is not None:
215
- validation_error = self._validate_arguments_against_schema(arguments, schema)
243
+ validation_error = self._validate_arguments_against_schema(
244
+ arguments, schema
245
+ )
216
246
  if validation_error:
217
- self._publish_tool_call_error(tool_name, request_id, validation_error, arguments)
247
+ self._publish_tool_call_error(
248
+ tool_name, request_id, validation_error, arguments
249
+ )
218
250
  return validation_error
219
251
  return None
220
252