janito 3.8.0__py3-none-any.whl → 3.10.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 (77) hide show
  1. janito/agent_events.py +75 -0
  2. janito/cli/chat_mode/session.py +1 -0
  3. janito/cli/chat_mode/shell/commands/__init__.py +2 -0
  4. janito/cli/chat_mode/shell/commands/interactive.py +33 -0
  5. janito/cli/chat_mode/toolbar.py +16 -1
  6. janito/cli/cli_commands/list_tools.py +1 -1
  7. janito/cli/core/runner.py +33 -0
  8. janito/cli/main_cli.py +9 -0
  9. janito/cli/prompt_core.py +301 -257
  10. janito/cli/rich_terminal_reporter.py +170 -171
  11. janito/cli/single_shot_mode/handler.py +19 -0
  12. janito/llm/agent.py +65 -0
  13. janito/{tools/adapters/local → plugins/core/filemanager/tools}/validate_file_syntax/core.py +7 -2
  14. janito/plugins/core/filemanager/tools/validate_file_syntax/txt_validator.py +28 -0
  15. janito/plugins/manager.py +1 -1
  16. janito/{tools/adapters → plugins/tools}/local/__init__.py +7 -0
  17. janito/{tools/adapters → plugins/tools}/local/adapter.py +1 -1
  18. janito/{tools/adapters → plugins/tools}/local/ask_user.py +1 -1
  19. janito/{tools/adapters → plugins/tools}/local/copy_file.py +1 -1
  20. janito/{tools/adapters → plugins/tools}/local/create_directory.py +45 -2
  21. janito/{tools/adapters → plugins/tools}/local/create_file.py +10 -6
  22. janito/{tools/adapters → plugins/tools}/local/delete_text_in_file.py +2 -2
  23. janito/{tools/adapters → plugins/tools}/local/fetch_url.py +3 -3
  24. janito/{tools/adapters → plugins/tools}/local/find_files.py +1 -1
  25. janito/{tools/adapters → plugins/tools}/local/get_file_outline/core.py +2 -2
  26. janito/{tools/adapters → plugins/tools}/local/move_file.py +1 -1
  27. janito/{tools/adapters → plugins/tools}/local/open_html_in_browser.py +1 -1
  28. janito/{tools/adapters → plugins/tools}/local/open_url.py +1 -1
  29. janito/{tools/adapters → plugins/tools}/local/python_code_run.py +1 -1
  30. janito/{tools/adapters → plugins/tools}/local/python_command_run.py +1 -1
  31. janito/{tools/adapters → plugins/tools}/local/python_file_run.py +1 -1
  32. janito/{tools/adapters → plugins/tools}/local/read_chart.py +1 -1
  33. janito/{tools/adapters → plugins/tools}/local/read_files.py +1 -1
  34. janito/{tools/adapters → plugins/tools}/local/remove_directory.py +1 -1
  35. janito/{tools/adapters → plugins/tools}/local/remove_file.py +1 -1
  36. janito/{tools/adapters → plugins/tools}/local/replace_text_in_file.py +2 -2
  37. janito/{tools/adapters → plugins/tools}/local/run_bash_command.py +1 -1
  38. janito/{tools/adapters → plugins/tools}/local/run_powershell_command.py +1 -1
  39. janito/{tools/adapters → plugins/tools}/local/search_text/core.py +2 -2
  40. janito/{tools/adapters → plugins/tools}/local/show_image.py +1 -1
  41. janito/{tools/adapters → plugins/tools}/local/show_image_grid.py +1 -1
  42. janito/plugins/tools/local/validate_file_syntax/__init__.py +1 -0
  43. janito/plugins/tools/local/validate_file_syntax/core.py +119 -0
  44. janito/plugins/tools/local/validate_file_syntax/txt_validator.py +28 -0
  45. janito/{tools/adapters → plugins/tools}/local/view_file.py +1 -1
  46. janito/tests/test_tool_adapter_case_insensitive.py +112 -0
  47. janito/tools/__init__.py +2 -2
  48. janito/tools/inspect_registry.py +1 -1
  49. janito/tools/tool_base.py +8 -1
  50. janito/tools/tools_adapter.py +514 -510
  51. {janito-3.8.0.dist-info → janito-3.10.0.dist-info}/METADATA +84 -84
  52. {janito-3.8.0.dist-info → janito-3.10.0.dist-info}/RECORD +77 -70
  53. /janito/{tools/adapters/local → plugins/core/filemanager/tools}/validate_file_syntax/__init__.py +0 -0
  54. /janito/{tools/adapters → plugins/tools}/__init__.py +0 -0
  55. /janito/{tools/adapters → plugins/tools}/local/get_file_outline/__init__.py +0 -0
  56. /janito/{tools/adapters → plugins/tools}/local/get_file_outline/java_outline.py +0 -0
  57. /janito/{tools/adapters → plugins/tools}/local/get_file_outline/markdown_outline.py +0 -0
  58. /janito/{tools/adapters → plugins/tools}/local/get_file_outline/python_outline.py +0 -0
  59. /janito/{tools/adapters → plugins/tools}/local/get_file_outline/search_outline.py +0 -0
  60. /janito/{tools/adapters → plugins/tools}/local/search_text/__init__.py +0 -0
  61. /janito/{tools/adapters → plugins/tools}/local/search_text/match_lines.py +0 -0
  62. /janito/{tools/adapters → plugins/tools}/local/search_text/pattern_utils.py +0 -0
  63. /janito/{tools/adapters → plugins/tools}/local/search_text/traverse_directory.py +0 -0
  64. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/css_validator.py +0 -0
  65. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/html_validator.py +0 -0
  66. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/jinja2_validator.py +0 -0
  67. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/js_validator.py +0 -0
  68. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/json_validator.py +0 -0
  69. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/markdown_validator.py +0 -0
  70. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/ps1_validator.py +0 -0
  71. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/python_validator.py +0 -0
  72. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/xml_validator.py +0 -0
  73. /janito/{tools/adapters → plugins/tools}/local/validate_file_syntax/yaml_validator.py +0 -0
  74. {janito-3.8.0.dist-info → janito-3.10.0.dist-info}/WHEEL +0 -0
  75. {janito-3.8.0.dist-info → janito-3.10.0.dist-info}/entry_points.txt +0 -0
  76. {janito-3.8.0.dist-info → janito-3.10.0.dist-info}/licenses/LICENSE +0 -0
  77. {janito-3.8.0.dist-info → janito-3.10.0.dist-info}/top_level.txt +0 -0
janito/agent_events.py ADDED
@@ -0,0 +1,75 @@
1
+ import attr
2
+ from typing import Any, ClassVar, Optional
3
+ from janito.event_bus.event import Event
4
+
5
+
6
+ @attr.s(auto_attribs=True, kw_only=True)
7
+ class AgentEvent(Event):
8
+ """
9
+ Base class for events related to an agent.
10
+ Includes agent name for identification.
11
+ """
12
+
13
+ category: ClassVar[str] = "agent"
14
+ agent_name: Optional[str] = None
15
+
16
+
17
+ @attr.s(auto_attribs=True, kw_only=True)
18
+ class AgentInitialized(AgentEvent):
19
+ """Emitted when an agent is initialized."""
20
+ pass
21
+
22
+
23
+ @attr.s(auto_attribs=True, kw_only=True)
24
+ class AgentChatStarted(AgentEvent):
25
+ """Emitted when an agent starts a chat session."""
26
+ prompt: Optional[str] = None
27
+ messages: Optional[list] = None
28
+ role: Optional[str] = None
29
+
30
+
31
+ @attr.s(auto_attribs=True, kw_only=True)
32
+ class AgentChatFinished(AgentEvent):
33
+ """Emitted when an agent completes a chat session."""
34
+ result: Any = None
35
+ loop_count: int = 0
36
+
37
+
38
+ @attr.s(auto_attribs=True, kw_only=True)
39
+ class AgentProcessingResponse(AgentEvent):
40
+ """Emitted when an agent is processing a response."""
41
+ response: Any = None
42
+
43
+
44
+ @attr.s(auto_attribs=True, kw_only=True)
45
+ class AgentToolCallStarted(AgentEvent):
46
+ """Emitted when an agent starts processing a tool call."""
47
+ tool_call_id: Optional[str] = None
48
+ name: Optional[str] = None
49
+ arguments: Any = None
50
+
51
+
52
+ @attr.s(auto_attribs=True, kw_only=True)
53
+ class AgentToolCallFinished(AgentEvent):
54
+ """Emitted when an agent completes processing a tool call."""
55
+ tool_call_id: Optional[str] = None
56
+ name: Optional[str] = None
57
+ result: Any = None
58
+
59
+
60
+ @attr.s(auto_attribs=True, kw_only=True)
61
+ class AgentWaitingForResponse(AgentEvent):
62
+ """Emitted when an agent is waiting for a response from the LLM API."""
63
+ pass
64
+
65
+
66
+ @attr.s(auto_attribs=True, kw_only=True)
67
+ class AgentReceivedResponse(AgentEvent):
68
+ """Emitted when an agent receives a response from the LLM API."""
69
+ response: Any = None
70
+
71
+
72
+ @attr.s(auto_attribs=True, kw_only=True)
73
+ class AgentShutdown(AgentEvent):
74
+ """Emitted when an agent is shutting down."""
75
+ pass
@@ -31,6 +31,7 @@ class ChatShellState:
31
31
  self.mem_history = mem_history
32
32
  self.conversation_history = conversation_history
33
33
  self.paste_mode = False
34
+ self.interactive_mode = True # Default to interactive mode
34
35
 
35
36
  self._pid = None
36
37
  self._stdout_path = None
@@ -11,6 +11,7 @@ from .session import HistoryShellHandler
11
11
  from .tools import ToolsShellHandler
12
12
  from .help import HelpShellHandler
13
13
  from .security_command import SecurityCommand
14
+ from .interactive import InteractiveShellHandler
14
15
  from janito.cli.console import shared_console
15
16
 
16
17
  COMMAND_HANDLERS = {
@@ -45,6 +46,7 @@ COMMAND_HANDLERS = {
45
46
  "/help": HelpShellHandler,
46
47
  "/security": SecurityCommand,
47
48
  "/provider": ProviderCmdHandler,
49
+ "/interactive": InteractiveShellHandler,
48
50
  }
49
51
 
50
52
 
@@ -0,0 +1,33 @@
1
+ from janito.cli.chat_mode.shell.commands.base import ShellCmdHandler
2
+ from janito.cli.console import shared_console
3
+
4
+
5
+ class InteractiveShellHandler(ShellCmdHandler):
6
+ help_text = "Toggle interactive mode on/off"
7
+
8
+ def run(self):
9
+ args = self.after_cmd_line.strip().lower()
10
+
11
+ if args not in ["on", "off"]:
12
+ shared_console.print(
13
+ "[bold red]Usage: /interactive on|off[/bold red]"
14
+ )
15
+ return
16
+
17
+ # Get current interactive state from shell_state if available
18
+ current_state = getattr(self.shell_state, 'interactive_mode', True)
19
+
20
+ if args == "on":
21
+ if current_state:
22
+ shared_console.print("[yellow]Interactive mode is already enabled.[/yellow]")
23
+ else:
24
+ if hasattr(self.shell_state, 'interactive_mode'):
25
+ self.shell_state.interactive_mode = True
26
+ shared_console.print("[green]Interactive mode enabled.[/green]")
27
+ elif args == "off":
28
+ if not current_state:
29
+ shared_console.print("[yellow]Interactive mode is already disabled.[/yellow]")
30
+ else:
31
+ if hasattr(self.shell_state, 'interactive_mode'):
32
+ self.shell_state.interactive_mode = False
33
+ shared_console.print("[green]Interactive mode disabled.[/green]")
@@ -51,6 +51,20 @@ def assemble_bindings_line(width, permissions=None):
51
51
  )
52
52
 
53
53
 
54
+ def assemble_platform_line():
55
+ import platform
56
+ import sys
57
+ from janito.platform_discovery import PlatformDiscovery
58
+
59
+ discovery = PlatformDiscovery()
60
+ system_info = f"{platform.system()} {platform.release()}"
61
+ arch_info = platform.machine()
62
+ shell_info = discovery.detect_shell()
63
+ python_version = f"Python {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
64
+
65
+ return f" Platform: {system_info} ({arch_info}) | Shell: {shell_info} | {python_version}"
66
+
67
+
54
68
  def _get_status(shell_state):
55
69
  _support = getattr(shell_state, "_support", False)
56
70
  _status = getattr(shell_state, "_status", None)
@@ -96,7 +110,8 @@ def get_toolbar_func(perf: PerformanceCollector, msg_count: int, shell_state):
96
110
  first_line = assemble_first_line(provider_name, model_name, role, agent=agent)
97
111
  permissions = _get_permissions()
98
112
  bindings_line = assemble_bindings_line(width, permissions)
99
- toolbar_text = first_line + "\n" + bindings_line
113
+ platform_line = assemble_platform_line()
114
+ toolbar_text = first_line + "\n" + platform_line + "\n" + bindings_line
100
115
 
101
116
  return HTML(toolbar_text)
102
117
 
@@ -53,7 +53,7 @@ def _print_tools_table(console, title, tools_info):
53
53
 
54
54
 
55
55
  def handle_list_tools(args=None):
56
- from janito.tools.adapters.local.adapter import LocalToolsAdapter
56
+ from janito.plugins.tools.local.adapter import LocalToolsAdapter
57
57
  import janito.tools # Ensure all tools are registered
58
58
  from janito.tools.tool_base import ToolPermissions
59
59
 
janito/cli/core/runner.py CHANGED
@@ -38,6 +38,16 @@ def _choose_provider(args):
38
38
  return provider
39
39
 
40
40
 
41
+ def _select_coder_model_for_provider(provider: str) -> str:
42
+ """Auto-select the best coder model for the given provider when --developer mode is used."""
43
+ coder_models = {
44
+ "alibaba": "qwen3-coder-plus",
45
+ "cerebras": "qwen-3-coder-480b",
46
+ }
47
+
48
+ return coder_models.get(provider)
49
+
50
+
41
51
  def _populate_driver_config_data(args, modifiers, provider, model):
42
52
  from janito.provider_config import get_effective_setting
43
53
 
@@ -80,6 +90,17 @@ def prepare_llm_driver_config(args, modifiers):
80
90
  if not model:
81
91
  model = get_effective_model(provider)
82
92
 
93
+ # Auto-select coder model when --developer mode is used and no model is specified
94
+ if not model and getattr(args, "developer", False):
95
+ model = _select_coder_model_for_provider(provider)
96
+ if model and getattr(args, "verbose", False):
97
+ print_verbose_info(
98
+ "Auto-selected coder model",
99
+ f"{model} for provider {provider} (developer mode)",
100
+ style="magenta",
101
+ align_content=True,
102
+ )
103
+
83
104
  # Validate that the chosen model is supported by the selected provider
84
105
  if model:
85
106
  from janito.provider_registry import ProviderRegistry
@@ -149,6 +170,15 @@ def handle_runner(
149
170
 
150
171
  load_disabled_tools_from_config()
151
172
 
173
+ # Disable bash tools when running in PowerShell
174
+ from janito.platform_discovery import PlatformDiscovery
175
+
176
+ pd = PlatformDiscovery()
177
+ if pd.detect_shell().startswith("PowerShell"):
178
+ from janito.tools.disabled_tools import DisabledToolsState
179
+
180
+ DisabledToolsState.disable_tool("run_bash_command")
181
+
152
182
  unrestricted = getattr(args, "unrestricted", False)
153
183
  adapter = janito.tools.get_local_tools_adapter(
154
184
  workdir=getattr(args, "workdir", None)
@@ -230,4 +260,7 @@ def handle_runner(
230
260
 
231
261
 
232
262
  def get_prompt_mode(args):
263
+ # If interactive flag is set, force chat mode regardless of user_prompt
264
+ if getattr(args, "interactive", False):
265
+ return "chat_mode"
233
266
  return "single_shot" if getattr(args, "user_prompt", None) else "chat_mode"
janito/cli/main_cli.py CHANGED
@@ -204,6 +204,13 @@ definition = [
204
204
  "help": "Enable emoji usage in responses to make output more engaging and expressive",
205
205
  },
206
206
  ),
207
+ (
208
+ ["-i", "--interactive"],
209
+ {
210
+ "action": "store_true",
211
+ "help": "Signal that this is an interactive chat session",
212
+ },
213
+ ),
207
214
  (["user_prompt"], {"nargs": argparse.REMAINDER, "help": "Prompt to submit"}),
208
215
  (
209
216
  ["-e", "--event-log"],
@@ -256,6 +263,7 @@ MODIFIER_KEYS = [
256
263
  "read",
257
264
  "write",
258
265
  "emoji",
266
+ "interactive",
259
267
  ]
260
268
  SETTER_KEYS = ["set", "set_provider", "set_api_key", "unset"]
261
269
  GETTER_KEYS = [
@@ -420,6 +428,7 @@ class JanitoCLI:
420
428
 
421
429
  # If running in single shot mode and --profile is not provided, default to 'developer' profile
422
430
  # Skip profile selection for list commands that don't need it
431
+ # Also skip if interactive mode is enabled (forces chat mode)
423
432
  if get_prompt_mode(self.args) == "single_shot" and not getattr(
424
433
  self.args, "profile", None
425
434
  ):