janito 2.7.0__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 (116) 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 +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 +14 -5
  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/openai/driver.py +52 -36
  48. janito/formatting_token.py +12 -4
  49. janito/llm/agent.py +15 -6
  50. janito/llm/driver.py +1 -0
  51. janito/provider_registry.py +31 -70
  52. janito/providers/__init__.py +1 -0
  53. janito/providers/anthropic/model_info.py +0 -1
  54. janito/providers/anthropic/provider.py +9 -14
  55. janito/providers/azure_openai/provider.py +9 -4
  56. janito/providers/deepseek/provider.py +5 -4
  57. janito/providers/google/model_info.py +4 -2
  58. janito/providers/google/provider.py +11 -5
  59. janito/providers/groq/__init__.py +1 -0
  60. janito/providers/groq/model_info.py +46 -0
  61. janito/providers/groq/provider.py +76 -0
  62. janito/providers/moonshotai/provider.py +11 -4
  63. janito/providers/openai/model_info.py +0 -1
  64. janito/providers/openai/provider.py +6 -7
  65. janito/tools/__init__.py +2 -0
  66. janito/tools/adapters/local/__init__.py +2 -1
  67. janito/tools/adapters/local/adapter.py +21 -4
  68. janito/tools/adapters/local/ask_user.py +1 -0
  69. janito/tools/adapters/local/copy_file.py +1 -0
  70. janito/tools/adapters/local/create_directory.py +1 -0
  71. janito/tools/adapters/local/create_file.py +1 -0
  72. janito/tools/adapters/local/delete_text_in_file.py +2 -1
  73. janito/tools/adapters/local/fetch_url.py +1 -0
  74. janito/tools/adapters/local/find_files.py +7 -6
  75. janito/tools/adapters/local/get_file_outline/core.py +1 -0
  76. janito/tools/adapters/local/get_file_outline/java_outline.py +22 -15
  77. janito/tools/adapters/local/get_file_outline/search_outline.py +1 -0
  78. janito/tools/adapters/local/move_file.py +1 -0
  79. janito/tools/adapters/local/open_html_in_browser.py +15 -5
  80. janito/tools/adapters/local/open_url.py +1 -0
  81. janito/tools/adapters/local/python_code_run.py +1 -0
  82. janito/tools/adapters/local/python_command_run.py +1 -0
  83. janito/tools/adapters/local/python_file_run.py +1 -0
  84. janito/tools/adapters/local/read_files.py +19 -4
  85. janito/tools/adapters/local/remove_directory.py +1 -0
  86. janito/tools/adapters/local/remove_file.py +1 -0
  87. janito/tools/adapters/local/replace_text_in_file.py +4 -3
  88. janito/tools/adapters/local/run_bash_command.py +1 -0
  89. janito/tools/adapters/local/run_powershell_command.py +1 -0
  90. janito/tools/adapters/local/search_text/core.py +18 -17
  91. janito/tools/adapters/local/search_text/match_lines.py +5 -5
  92. janito/tools/adapters/local/search_text/pattern_utils.py +1 -1
  93. janito/tools/adapters/local/search_text/traverse_directory.py +7 -7
  94. janito/tools/adapters/local/validate_file_syntax/core.py +1 -1
  95. janito/tools/adapters/local/validate_file_syntax/html_validator.py +8 -1
  96. janito/tools/disabled_tools.py +68 -0
  97. janito/tools/path_security.py +18 -11
  98. janito/tools/permissions.py +6 -0
  99. janito/tools/permissions_parse.py +4 -3
  100. janito/tools/tool_base.py +11 -5
  101. janito/tools/tool_use_tracker.py +1 -4
  102. janito/tools/tool_utils.py +1 -1
  103. janito/tools/tools_adapter.py +57 -25
  104. {janito-2.7.0.dist-info → janito-2.8.0.dist-info}/METADATA +4 -12
  105. janito-2.8.0.dist-info/RECORD +202 -0
  106. janito/cli/chat_mode/shell/commands/livelogs.py +0 -49
  107. janito/drivers/mistralai/driver.py +0 -41
  108. janito/providers/mistralai/model_info.py +0 -37
  109. janito/providers/mistralai/provider.py +0 -72
  110. janito/providers/provider_static_info.py +0 -21
  111. janito-2.7.0.dist-info/RECORD +0 -202
  112. /janito/agent/templates/profiles/{system_prompt_template_assistant.txt.j2 → system_prompt_template_model_conversation_without_tools_or_context.txt.j2} +0 -0
  113. {janito-2.7.0.dist-info → janito-2.8.0.dist-info}/WHEEL +0 -0
  114. {janito-2.7.0.dist-info → janito-2.8.0.dist-info}/entry_points.txt +0 -0
  115. {janito-2.7.0.dist-info → janito-2.8.0.dist-info}/licenses/LICENSE +0 -0
  116. {janito-2.7.0.dist-info → janito-2.8.0.dist-info}/top_level.txt +0 -0
@@ -3,6 +3,7 @@ from janito.performance_collector import PerformanceCollector
3
3
  from janito.cli.config import config
4
4
  from janito import __version__ as VERSION
5
5
 
6
+
6
7
  def format_tokens(n, tag=None):
7
8
  if n is None:
8
9
  return "?"
@@ -14,15 +15,20 @@ def format_tokens(n, tag=None):
14
15
  val = f"{n/1000000:.1f}M"
15
16
  return f"<{tag}>{val}</{tag}>" if tag else val
16
17
 
18
+
17
19
  def assemble_first_line(provider_name, model_name, role, agent=None):
18
20
  return f" Janito {VERSION} | Provider: <provider>{provider_name}</provider> | Model: <model>{model_name}</model> | Role: <role>{role}</role>"
19
21
 
22
+
20
23
  def assemble_bindings_line(width, permissions=None):
21
24
  def color_state(state):
22
- return 'on ' if state == "on" else 'off'
25
+ return "on " if state == "on" else "off"
26
+
23
27
  read_state = color_state("on" if getattr(permissions, "read", False) else "off")
24
28
  write_state = color_state("on" if getattr(permissions, "write", False) else "off")
25
- execute_state = color_state("on" if getattr(permissions, "execute", False) else "off")
29
+ execute_state = color_state(
30
+ "on" if getattr(permissions, "execute", False) else "off"
31
+ )
26
32
  return (
27
33
  f" <key-label>CTRL-C</key-label>: Interrupt/Exit | "
28
34
  f"<key-label>F2</key-label>: /restart | "
@@ -30,6 +36,7 @@ def assemble_bindings_line(width, permissions=None):
30
36
  f"<key-label>F12</key-label>: Do It "
31
37
  )
32
38
 
39
+
33
40
  def _get_status(shell_state):
34
41
  _support = getattr(shell_state, "_support", False)
35
42
  _status = getattr(shell_state, "_status", None)
@@ -37,47 +44,46 @@ def _get_status(shell_state):
37
44
  return None
38
45
  if _status == "starting" or _status is None:
39
46
  return _status
40
- live_status = getattr(shell_state, "_live_status", None)
41
- if live_status is not None:
42
- return live_status
47
+
43
48
  return _status
44
49
 
50
+
45
51
  def _get_agent_info(agent):
46
- provider_name = agent.get_provider_name() if hasattr(agent, "get_provider_name") else "?"
52
+ provider_name = (
53
+ agent.get_provider_name() if hasattr(agent, "get_provider_name") else "?"
54
+ )
47
55
  model_name = agent.get_model_name() if hasattr(agent, "get_model_name") else "?"
48
- role = agent.template_vars.get("role", "?") if hasattr(agent, "template_vars") else "?"
56
+ role = (
57
+ agent.template_vars.get("role", "?") if hasattr(agent, "template_vars") else "?"
58
+ )
49
59
  return provider_name, model_name, role
50
60
 
61
+
51
62
  def _get_permissions():
52
63
  try:
53
64
  from janito.tools.permissions import get_global_allowed_permissions
65
+
54
66
  return get_global_allowed_permissions()
55
67
  except Exception:
56
68
  return None
57
69
 
58
- def _get_termweb_status_line(this__status, _port):
59
- if this__status == "online" and _port:
60
- return "\n<> Termweb </>Online"
61
- elif this__status == "starting":
62
- return "\n<> Termweb </>Starting"
63
- elif this__status == "offline":
64
- return "\n<> Termweb </>Offline"
65
- return ""
66
70
 
67
71
  def get_toolbar_func(perf: PerformanceCollector, msg_count: int, shell_state):
68
72
  from prompt_toolkit.application.current import get_app
73
+
69
74
  def get_toolbar():
70
75
  width = get_app().output.get_size().columns
71
76
  agent = getattr(shell_state, "agent", None)
72
77
  this__status = _get_status(shell_state)
73
- provider_name, model_name, role = _get_agent_info(agent) if agent is not None else ("?", "?", "?")
78
+ provider_name, model_name, role = (
79
+ _get_agent_info(agent) if agent is not None else ("?", "?", "?")
80
+ )
74
81
  usage = perf.get_last_request_usage()
75
82
  first_line = assemble_first_line(provider_name, model_name, role, agent=agent)
76
83
  permissions = _get_permissions()
77
84
  bindings_line = assemble_bindings_line(width, permissions)
78
85
  toolbar_text = first_line + "\n" + bindings_line
79
- _port = getattr(shell_state, "_port", None)
80
- toolbar_text += _get_termweb_status_line(this__status, _port)
86
+
81
87
  return HTML(toolbar_text)
82
- return get_toolbar
83
88
 
89
+ return get_toolbar
@@ -32,4 +32,4 @@ def handle_list_models(args, provider_instance):
32
32
  print(f"- {m}")
33
33
  except Exception as e:
34
34
  print(f"Error listing models for provider '{provider_name}': {e}")
35
- sys.exit(0)
35
+ return
@@ -7,3 +7,4 @@ from janito.provider_registry import list_providers
7
7
 
8
8
  def handle_list_providers(args=None):
9
9
  list_providers()
10
+ return
@@ -3,21 +3,29 @@ CLI Command: List available tools
3
3
  """
4
4
 
5
5
 
6
- def _group_tools_by_permission(tools, tool_instances):
6
+ def _group_tools_by_permission(tools, tool_instances, disabled_tools):
7
7
  read_only_tools = []
8
8
  write_only_tools = []
9
9
  read_write_tools = []
10
10
  exec_tools = []
11
11
  import inspect
12
+
12
13
  for tool in tools:
14
+ # Skip disabled tools entirely
15
+ if tool in disabled_tools:
16
+ continue
17
+
13
18
  inst = tool_instances.get(tool, None)
14
19
  param_names = []
15
20
  if inst and hasattr(inst, "run"):
16
21
  sig = inspect.signature(inst.run)
17
22
  param_names = [p for p in sig.parameters if p != "self"]
23
+
18
24
  info = {
19
25
  "name": tool,
20
26
  "params": ", ".join(param_names),
27
+ "tool_name": tool,
28
+ "disabled": False,
21
29
  }
22
30
  perms = getattr(inst, "permissions", None)
23
31
  if perms and perms.execute:
@@ -30,33 +38,54 @@ def _group_tools_by_permission(tools, tool_instances):
30
38
  write_only_tools.append(info)
31
39
  return read_only_tools, write_only_tools, read_write_tools, exec_tools
32
40
 
41
+
33
42
  def _print_tools_table(console, title, tools_info):
34
43
  from rich.table import Table
35
- table = Table(title=title, show_header=True, header_style="bold", show_lines=False, box=None)
44
+
45
+ table = Table(
46
+ title=title, show_header=True, header_style="bold", show_lines=False, box=None
47
+ )
36
48
  table.add_column("Name", style="cyan", no_wrap=True)
37
49
  table.add_column("Parameters", style="yellow")
38
50
  for info in tools_info:
39
51
  table.add_row(info["name"], info["params"] or "-")
40
52
  console.print(table)
41
53
 
54
+
42
55
  def handle_list_tools(args=None):
43
56
  from janito.tools.adapters.local.adapter import LocalToolsAdapter
44
57
  import janito.tools # Ensure all tools are registered
45
58
  from janito.tools.tool_base import ToolPermissions
59
+
46
60
  read = getattr(args, "read", False) if args else False
47
61
  write = getattr(args, "write", False) if args else False
48
62
  execute = getattr(args, "exec", False) if args else False
49
63
  if not (read or write or execute):
50
64
  read = write = execute = True
51
65
  from janito.tools.permissions import set_global_allowed_permissions
52
- set_global_allowed_permissions(ToolPermissions(read=read, write=write, execute=execute))
53
- registry = janito.tools.get_local_tools_adapter()
66
+
67
+ set_global_allowed_permissions(
68
+ ToolPermissions(read=read, write=write, execute=execute)
69
+ )
70
+ # Load disabled tools from config
71
+ from janito.tools.disabled_tools import DisabledToolsState
72
+ from janito.config import config
73
+
74
+ disabled_str = config.get("disabled_tools", "")
75
+ if disabled_str:
76
+ DisabledToolsState.set_disabled_tools(disabled_str)
77
+ disabled_tools = DisabledToolsState.get_disabled_tools()
78
+
79
+ registry = janito.tools.local_tools_adapter
54
80
  tools = registry.list_tools()
55
81
  if tools:
56
82
  from rich.console import Console
83
+
57
84
  console = Console()
58
85
  tool_instances = {t.tool_name: t for t in registry.get_tools()}
59
- read_only_tools, write_only_tools, read_write_tools, exec_tools = _group_tools_by_permission(tools, tool_instances)
86
+ read_only_tools, write_only_tools, read_write_tools, exec_tools = (
87
+ _group_tools_by_permission(tools, tool_instances, disabled_tools)
88
+ )
60
89
  if read_only_tools:
61
90
  _print_tools_table(console, "Read-only tools (-r)", read_only_tools)
62
91
  if write_only_tools:
@@ -67,5 +96,4 @@ def handle_list_tools(args=None):
67
96
  _print_tools_table(console, "Execution tools (-x)", exec_tools)
68
97
  else:
69
98
  print("No tools registered.")
70
- import sys
71
- sys.exit(0)
99
+ return
@@ -35,18 +35,20 @@ def _print_models_table(models, provider_name):
35
35
  row.extend(_build_model_row(m, headers, num_fields))
36
36
  table.add_row(*row)
37
37
  import sys
38
+
38
39
  if sys.stdout.isatty():
39
40
  from rich.console import Console
41
+
40
42
  Console().print(table)
41
43
  else:
42
44
  # ASCII-friendly fallback table when output is redirected
43
45
  print(f"Supported models for provider '{provider_name}'")
44
46
  headers_fallback = [h for h in display_headers]
45
- print(' | '.join(headers_fallback))
47
+ print(" | ".join(headers_fallback))
46
48
  for m in models:
47
- row = [str(m.get('name', ''))]
49
+ row = [str(m.get("name", ""))]
48
50
  row.extend(_build_model_row(m, headers, num_fields))
49
- print(' | '.join(row))
51
+ print(" | ".join(row))
50
52
 
51
53
 
52
54
  def _add_table_columns(table, display_headers):
@@ -49,3 +49,15 @@ def handle_show_config(args):
49
49
  console.print(
50
50
  f" [bold]{pname}[/bold]{' '+sel if sel else ''}: model = [magenta]{eff_model}[/magenta]{extra}"
51
51
  )
52
+
53
+ # Show disabled tools
54
+ from janito.tools.disabled_tools import load_disabled_tools_from_config
55
+
56
+ disabled_tools = load_disabled_tools_from_config()
57
+ if disabled_tools:
58
+ console.print(
59
+ f"\n[bold red]Disabled tools:[/bold red] {', '.join(sorted(disabled_tools))}"
60
+ )
61
+ else:
62
+ console.print("\n[bold green]No tools are disabled[/bold green]")
63
+ return
@@ -14,6 +14,7 @@ import re
14
14
 
15
15
  def _compute_permission_string(args):
16
16
  from janito.tools.tool_base import ToolPermissions
17
+
17
18
  read = getattr(args, "read", False)
18
19
  write = getattr(args, "write", False)
19
20
  execute = getattr(args, "exec", False)
@@ -33,7 +34,7 @@ def _prepare_context(args, agent_role, allowed_permissions):
33
34
  context["role"] = agent_role or "developer"
34
35
  context["profile"] = getattr(args, "profile", None)
35
36
  context["allowed_permissions"] = allowed_permissions
36
- if allowed_permissions and 'x' in allowed_permissions:
37
+ if allowed_permissions and "x" in allowed_permissions:
37
38
  pd = PlatformDiscovery()
38
39
  context["platform"] = pd.get_platform_name()
39
40
  context["python_version"] = pd.get_python_version()
@@ -43,7 +44,8 @@ def _prepare_context(args, agent_role, allowed_permissions):
43
44
 
44
45
  def _load_template(profile, templates_dir):
45
46
  if profile:
46
- template_filename = f"system_prompt_template_{profile}.txt.j2"
47
+ sanitized_profile = re.sub(r"\\s+", "_", profile.strip())
48
+ template_filename = f"system_prompt_template_{sanitized_profile}.txt.j2"
47
49
  template_path = templates_dir / template_filename
48
50
  else:
49
51
  return None, None
@@ -65,8 +67,13 @@ def _load_template(profile, templates_dir):
65
67
  def _print_debug_info(debug_flag, template_filename, allowed_permissions, context):
66
68
  if debug_flag:
67
69
  from rich import print as rich_print
68
- rich_print(f"[bold magenta][DEBUG][/bold magenta] Rendering system prompt template '[cyan]{template_filename}[/cyan]' with allowed_permissions: [yellow]{allowed_permissions}[/yellow]")
69
- rich_print(f"[bold magenta][DEBUG][/bold magenta] Template context: [green]{context}[/green]")
70
+
71
+ rich_print(
72
+ f"[bold magenta][DEBUG][/bold magenta] Rendering system prompt template '[cyan]{template_filename}[/cyan]' with allowed_permissions: [yellow]{allowed_permissions}[/yellow]"
73
+ )
74
+ rich_print(
75
+ f"[bold magenta][DEBUG][/bold magenta] Template context: [green]{context}[/green]"
76
+ )
70
77
 
71
78
 
72
79
  def handle_show_system_prompt(args):
@@ -85,9 +92,12 @@ def handle_show_system_prompt(args):
85
92
 
86
93
  # Debug flag detection
87
94
  import sys
95
+
88
96
  debug_flag = False
89
97
  try:
90
- debug_flag = (hasattr(sys, 'argv') and ('--debug' in sys.argv or '--verbose' in sys.argv or '-v' in sys.argv))
98
+ debug_flag = hasattr(sys, "argv") and (
99
+ "--debug" in sys.argv or "--verbose" in sys.argv or "-v" in sys.argv
100
+ )
91
101
  except Exception:
92
102
  pass
93
103
 
@@ -96,8 +106,10 @@ def handle_show_system_prompt(args):
96
106
  )
97
107
  profile = getattr(args, "profile", None)
98
108
  if not profile:
99
- print("[janito] No profile specified. The main agent runs without a system prompt template.\n"
100
- "Use --profile PROFILE to view a profile-specific system prompt.")
109
+ print(
110
+ "[janito] No profile specified. The main agent runs without a system prompt template.\n"
111
+ "Use --profile PROFILE to view a profile-specific system prompt."
112
+ )
101
113
  return
102
114
 
103
115
  template_filename, template_content = _load_template(profile, templates_dir)
@@ -117,9 +129,11 @@ def handle_show_system_prompt(args):
117
129
 
118
130
  template = Template(template_content)
119
131
  system_prompt = template.render(**context)
120
- system_prompt = re.sub(r'\n{3,}', '\n\n', system_prompt)
132
+ system_prompt = re.sub(r"\n{3,}", "\n\n", system_prompt)
121
133
 
122
- print(f"\n--- System Prompt (resolved, profile: {getattr(args, 'profile', 'main')}) ---\n")
134
+ print(
135
+ f"\n--- System Prompt (resolved, profile: {getattr(args, 'profile', 'main')}) ---\n"
136
+ )
123
137
  print(system_prompt)
124
138
  print("\n-------------------------------\n")
125
139
  if agent_role:
janito/cli/config.py CHANGED
@@ -12,16 +12,3 @@ CONFIG_OPTIONS = {
12
12
  "template": "Template context dictionary for Agent Profile prompt rendering (nested)",
13
13
  "profile": "Agent Profile name (only 'base' is supported)",
14
14
  }
15
-
16
-
17
-
18
- def get__port():
19
- port = config.get("_port")
20
- try:
21
- return int(port)
22
- except Exception:
23
- pass
24
-
25
-
26
- def set__port(port):
27
- config.file_set("_port", int(port))
@@ -1,4 +1,5 @@
1
1
  """Handlers for get-type CLI commands (show_config, list_providers, models, tools)."""
2
+
2
3
  import sys
3
4
 
4
5
  from janito.cli.cli_commands.list_providers import handle_list_providers
@@ -17,6 +18,7 @@ def handle_getter(args, config_mgr=None):
17
18
  provider = getattr(args, "provider", None)
18
19
  if not provider:
19
20
  import sys
21
+
20
22
  print(
21
23
  "Error: No provider selected. Please set a provider using '-p PROVIDER', '--set provider=name', or configure a provider."
22
24
  )
janito/cli/core/runner.py CHANGED
@@ -77,7 +77,7 @@ def prepare_llm_driver_config(args, modifiers):
77
77
  f"Error: Model '{model}' is not available for provider '{provider}'."
78
78
  )
79
79
  # Optionally, print available models if possible
80
- if hasattr(provider_instance, 'get_model_info'):
80
+ if hasattr(provider_instance, "get_model_info"):
81
81
  available_models = [
82
82
  m["name"]
83
83
  for m in provider_instance.get_model_info().values()
@@ -97,7 +97,13 @@ def prepare_llm_driver_config(args, modifiers):
97
97
  return provider, llm_driver_config, agent_role
98
98
 
99
99
 
100
- def handle_runner(args, provider, llm_driver_config, agent_role, verbose_tools=False, ):
100
+ def handle_runner(
101
+ args,
102
+ provider,
103
+ llm_driver_config,
104
+ agent_role,
105
+ verbose_tools=False,
106
+ ):
101
107
  """
102
108
  Main runner for CLI execution. If exec_enabled is False, disables execution/run tools.
103
109
  """
@@ -107,18 +113,29 @@ def handle_runner(args, provider, llm_driver_config, agent_role, verbose_tools=F
107
113
  # Patch: disable execution/run tools if not enabled
108
114
  import janito.tools
109
115
  from janito.tools.tool_base import ToolPermissions
116
+
110
117
  read = getattr(args, "read", False)
111
118
  write = getattr(args, "write", False)
112
119
  execute = getattr(args, "exec", False)
113
120
  from janito.tools.permissions import set_global_allowed_permissions
114
121
  from janito.tools.tool_base import ToolPermissions
122
+
115
123
  allowed_permissions = ToolPermissions(read=read, write=write, execute=execute)
116
124
  set_global_allowed_permissions(allowed_permissions)
117
125
  # Store the default permissions for later restoration (e.g., on /restart)
118
126
  from janito.tools.permissions import set_default_allowed_permissions
127
+
119
128
  set_default_allowed_permissions(allowed_permissions)
129
+
130
+ # Load disabled tools from config
131
+ from janito.tools.disabled_tools import load_disabled_tools_from_config
132
+
133
+ load_disabled_tools_from_config()
134
+
120
135
  unrestricted_paths = getattr(args, "unrestricted_paths", False)
121
- adapter = janito.tools.get_local_tools_adapter(workdir=getattr(args, "workdir", None))
136
+ adapter = janito.tools.get_local_tools_adapter(
137
+ workdir=getattr(args, "workdir", None)
138
+ )
122
139
  if unrestricted_paths:
123
140
  # Patch: disable path security enforcement for this adapter instance
124
141
  setattr(adapter, "unrestricted_paths", True)
@@ -128,7 +145,7 @@ def handle_runner(args, provider, llm_driver_config, agent_role, verbose_tools=F
128
145
  print_verbose_info(
129
146
  "Allowed Tool Permissions",
130
147
  f"read={read}, write={write}, execute={execute}",
131
- style="yellow"
148
+ style="yellow",
132
149
  )
133
150
 
134
151
  provider_instance = ProviderRegistry().get_instance(provider, llm_driver_config)
@@ -146,11 +163,12 @@ def handle_runner(args, provider, llm_driver_config, agent_role, verbose_tools=F
146
163
  )
147
164
 
148
165
  # DEBUG: Print exec_enabled propagation at runner
149
-
166
+
150
167
  handler = SingleShotPromptHandler(
151
- args, provider_instance, llm_driver_config,
168
+ args,
169
+ provider_instance,
170
+ llm_driver_config,
152
171
  role=agent_role,
153
-
154
172
  allowed_permissions=allowed_permissions,
155
173
  )
156
174
  handler.handle()
@@ -167,7 +185,6 @@ def handle_runner(args, provider, llm_driver_config, agent_role, verbose_tools=F
167
185
  args=args,
168
186
  verbose_tools=verbose_tools,
169
187
  verbose_agent=getattr(args, "verbose_agent", False),
170
-
171
188
  allowed_permissions=allowed_permissions,
172
189
  )
173
190
  session.run()
@@ -27,25 +27,24 @@ def handle_set(args, config_mgr=None):
27
27
  print(f"Error parsing --set value: {e}")
28
28
  return True
29
29
 
30
+
30
31
  def _validate_set_arg_format(set_arg):
31
32
  if "=" not in set_arg:
32
- print(
33
- "Error: --set requires KEY=VALUE (e.g., --set provider=provider_name)."
34
- )
33
+ print("Error: --set requires KEY=VALUE (e.g., --set provider=provider_name).")
35
34
  return False
36
35
  return True
37
36
 
37
+
38
38
  def _parse_set_arg(set_arg):
39
39
  key, value = set_arg.split("=", 1)
40
40
  return key.strip(), value.strip()
41
41
 
42
+
42
43
  def _dispatch_set_key(key, value):
43
44
  if key == "provider":
44
45
  return _handle_set_config_provider(value)
45
46
  if key == "model":
46
47
  return _handle_set_global_model(value)
47
- if "." in key and key.endswith(".model"):
48
- return _handle_set_provider_model(key, value)
49
48
  if key == "max_tokens":
50
49
  return _handle_set_max_tokens(value)
51
50
  if key == "base_url":
@@ -54,18 +53,24 @@ def _dispatch_set_key(key, value):
54
53
  global_config.file_set("azure_deployment_name", value)
55
54
  print(f"Azure deployment name set to '{value}'.")
56
55
  return True
57
- if ".max_tokens" in key or ".base_url" in key:
58
- return _handle_set_provider_level_setting(key, value)
59
56
  if key == "tool_permissions":
60
57
  from janito.tools.permissions_parse import parse_permissions_string
61
58
  from janito.tools.permissions import set_global_allowed_permissions
59
+
62
60
  perms = parse_permissions_string(value)
63
61
  global_config.file_set("tool_permissions", value)
64
62
  set_global_allowed_permissions(perms)
65
63
  print(f"Tool permissions set to '{value}' (parsed: {perms})")
66
64
  return True
65
+ if key == "disabled_tools":
66
+ from janito.tools.disabled_tools import set_disabled_tools
67
+
68
+ set_disabled_tools(value)
69
+ global_config.file_set("disabled_tools", value)
70
+ print(f"Disabled tools set to '{value}'")
71
+ return True
67
72
  print(
68
- f"Error: Unknown config key '{key}'. Supported: provider, model, <provider>.model, max_tokens, base_url, azure_deployment_name, <provider>.max_tokens, <provider>.base_url, <provider>.<model>.max_tokens, <provider>.<model>.base_url, tool_permissions"
73
+ f"Error: Unknown config key '{key}'. Supported: provider, model, max_tokens, base_url, azure_deployment_name, tool_permissions, disabled_tools"
69
74
  )
70
75
  return True
71
76
 
@@ -87,48 +92,6 @@ def _handle_set_base_url(value):
87
92
  return True
88
93
 
89
94
 
90
- def _handle_set_provider_level_setting(key, value):
91
- parts = key.split(".")
92
- if len(parts) == 2:
93
- provider, par_key = parts
94
- if par_key == "max_tokens":
95
- try:
96
- ival = int(value)
97
- except Exception:
98
- print("Error: max_tokens must be set to an integer value.")
99
- return True
100
- global_config.set_provider_config(provider, "max_tokens", ival)
101
- print(f"max_tokens for provider '{provider}' set to {ival}.")
102
- return True
103
- if par_key == "base_url":
104
- global_config.set_provider_config(provider, "base_url", value)
105
- print(f"base_url for provider '{provider}' set to {value}.")
106
- return True
107
- elif len(parts) == 3:
108
- provider, model, mk = parts
109
- if mk == "max_tokens":
110
- try:
111
- ival = int(value)
112
- except Exception:
113
- print("Error: max_tokens must be set to an integer value.")
114
- return True
115
- global_config.set_provider_model_config(provider, model, "max_tokens", ival)
116
- print(
117
- f"max_tokens for provider '{provider}', model '{model}' set to {ival}."
118
- )
119
- return True
120
- if mk == "base_url":
121
- global_config.set_provider_model_config(provider, model, "base_url", value)
122
- print(
123
- f"base_url for provider '{provider}', model '{model}' set to {value}."
124
- )
125
- return True
126
- print(
127
- f"Error: Unknown config key '{key}'. Supported: provider, model, <provider>.model, max_tokens, base_url, <provider>.max_tokens, <provider>.base_url, <provider>.<model>.max_tokens, <provider>.<model>.base_url"
128
- )
129
- return True
130
-
131
-
132
95
  def _handle_set_config_provider(value):
133
96
  try:
134
97
  supported = ProviderRegistry().get_provider(value)
@@ -144,32 +107,6 @@ def _handle_set_config_provider(value):
144
107
  return True
145
108
 
146
109
 
147
- def _handle_set_provider_model(key, value):
148
- provider_name, suffix = key.rsplit(".", 1)
149
- if suffix != "model":
150
- print(
151
- f"Error: Only <provider>.model is supported for provider-specific model override. Not: '{key}'"
152
- )
153
- return True
154
- try:
155
- provider_cls = ProviderRegistry().get_provider(provider_name)
156
- provider_instance = provider_cls()
157
- except Exception:
158
- print(
159
- f"Error: Provider '{provider_name}' is not supported. Run '--list-providers' to see the supported list."
160
- )
161
- return True
162
- model_info = provider_instance.get_model_info(value)
163
- if not model_info:
164
- print(
165
- f"Error: Model '{value}' is not defined for provider '{provider_name}'. Run '-p {provider_name} -l' to see models."
166
- )
167
- return True
168
- global_config.set_provider_config(provider_name, "model", value)
169
- print(f"Default model for provider '{provider_name}' set to '{value}'.")
170
- return True
171
-
172
-
173
110
  def _handle_set_global_model(value):
174
111
  # Try to validate model choice (against current provider if possible)
175
112
  provider_name = global_config.get("provider")