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
@@ -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
@@ -0,0 +1,31 @@
1
+ from rich.console import Console
2
+ from pathlib import Path
3
+ import os
4
+
5
+
6
+ def handle_list_config(args=None):
7
+ console = Console()
8
+ home = Path.home()
9
+ default_config = home / ".janito" / "config.json"
10
+ custom_dir = home / ".janito" / "configs"
11
+ console.print("[bold green]Janito configuration files:[/bold green]")
12
+ if default_config.exists():
13
+ console.print(f"[bold yellow]Default config:[/bold yellow] {default_config}")
14
+ else:
15
+ console.print(
16
+ f"[bold yellow]Default config:[/bold yellow] {default_config} [red](not found)"
17
+ )
18
+ if custom_dir.exists() and custom_dir.is_dir():
19
+ files = sorted(
20
+ f for f in custom_dir.iterdir() if f.is_file() and f.suffix == ".json"
21
+ )
22
+ if files:
23
+ console.print("[bold yellow]Custom configs:[/bold yellow]")
24
+ for f in files:
25
+ console.print(f" - {f}")
26
+ else:
27
+ console.print("[bold yellow]Custom configs:[/bold yellow] (none found)")
28
+ else:
29
+ console.print(
30
+ f"[bold yellow]Custom configs:[/bold yellow] {custom_dir} [red](directory not found)"
31
+ )
@@ -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
@@ -0,0 +1,79 @@
1
+ """
2
+ CLI Command: List available system prompt profiles (default and user-specific)
3
+ """
4
+
5
+ from pathlib import Path
6
+ import importlib.resources as resources
7
+ from rich.console import Console
8
+ from rich.table import Table
9
+
10
+
11
+ _PREFIX = "system_prompt_template_"
12
+ _SUFFIX = ".txt.j2"
13
+
14
+
15
+ def _extract_profile_name(filename: str) -> str:
16
+ """Return the human-readable profile name from template file name."""
17
+ # Remove prefix & suffix and convert underscores back to spaces
18
+ if filename.startswith(_PREFIX):
19
+ filename = filename[len(_PREFIX) :]
20
+ if filename.endswith(_SUFFIX):
21
+ filename = filename[: -len(_SUFFIX)]
22
+ return filename.replace("_", " ")
23
+
24
+
25
+ def _gather_default_profiles():
26
+ """Return list of built-in profile names bundled with janito."""
27
+ profiles = []
28
+ try:
29
+ package_files = resources.files("janito.agent.templates.profiles")
30
+ for path in package_files.iterdir():
31
+ name = path.name
32
+ if name.startswith(_PREFIX) and name.endswith(_SUFFIX):
33
+ profiles.append(_extract_profile_name(name))
34
+ except Exception:
35
+ # If for some reason the resources are not available fall back to empty list
36
+ pass
37
+ return sorted(profiles, key=str.lower)
38
+
39
+
40
+ def _gather_user_profiles():
41
+ """Return list of user-defined profile names from ~/.janito/profiles directory."""
42
+ user_dir = Path.home() / ".janito" / "profiles"
43
+ profiles = []
44
+ if user_dir.exists() and user_dir.is_dir():
45
+ for path in user_dir.iterdir():
46
+ if (
47
+ path.is_file()
48
+ and path.name.startswith(_PREFIX)
49
+ and path.name.endswith(_SUFFIX)
50
+ ):
51
+ profiles.append(_extract_profile_name(path.name))
52
+ return sorted(profiles, key=str.lower)
53
+
54
+
55
+ def _print_profiles_table(default_profiles, user_profiles):
56
+ console = Console()
57
+ table = Table(title="Available System Prompt Profiles", box=None, show_lines=False)
58
+ table.add_column("Profile Name", style="cyan", no_wrap=False)
59
+ table.add_column("Source", style="magenta", no_wrap=True)
60
+
61
+ for p in default_profiles:
62
+ table.add_row(p, "default")
63
+ for p in user_profiles:
64
+ table.add_row(p, "user")
65
+
66
+ console.print(table)
67
+
68
+
69
+ def handle_list_profiles(args=None):
70
+ """Entry point for the --list-profiles CLI flag."""
71
+ default_profiles = _gather_default_profiles()
72
+ user_profiles = _gather_user_profiles()
73
+
74
+ if not default_profiles and not user_profiles:
75
+ print("No profiles found.")
76
+ return
77
+
78
+ _print_profiles_table(default_profiles, user_profiles)
79
+ 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):
@@ -34,18 +34,23 @@ def handle_show_config(args):
34
34
  provider_names = ProviderRegistry()._get_provider_names()
35
35
  except Exception:
36
36
  pass
37
+ from janito.provider_config import get_config_path
38
+
39
+ config_path = get_config_path()
37
40
  console.print("[bold green]Current configuration:[/bold green]")
41
+ console.print(f"[bold yellow]Config file:[/bold yellow] {config_path}")
38
42
  console.print(f"[bold yellow]Current provider:[/bold yellow] {provider!r}\n")
39
43
  if model is not None:
40
44
  console.print(f"[bold yellow]Global model:[/bold yellow] {model!r}\n")
41
- if provider_names:
42
- console.print("[bold cyan]Provider specific default models:[/bold cyan]")
43
- for pname in provider_names:
44
- eff_model = resolve_effective_model(pname)
45
- prov_cfg = config.get_provider_config(pname)
46
- prov_model = prov_cfg.get("model") if prov_cfg else None
47
- extra = f" (override)" if prov_model else ""
48
- sel = "[default]" if pname == provider else ""
49
- console.print(
50
- f" [bold]{pname}[/bold]{' '+sel if sel else ''}: model = [magenta]{eff_model}[/magenta]{extra}"
51
- )
45
+
46
+ # Show disabled tools
47
+ from janito.tools.disabled_tools import load_disabled_tools_from_config
48
+
49
+ disabled_tools = load_disabled_tools_from_config()
50
+ if disabled_tools:
51
+ console.print(
52
+ f"\n[bold red]Disabled tools:[/bold red] {', '.join(sorted(disabled_tools))}"
53
+ )
54
+ else:
55
+ console.print("\n[bold green]No tools are disabled[/bold green]")
56
+ 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,14 +1,23 @@
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
5
6
  from janito.cli.cli_commands.list_models import handle_list_models
6
7
  from janito.cli.cli_commands.list_tools import handle_list_tools
7
8
  from janito.cli.cli_commands.show_config import handle_show_config
9
+ from janito.cli.cli_commands.list_config import handle_list_config
8
10
  from functools import partial
9
11
  from janito.provider_registry import ProviderRegistry
10
12
 
11
- GETTER_KEYS = ["show_config", "list_providers", "list_models", "list_tools"]
13
+ GETTER_KEYS = [
14
+ "show_config",
15
+ "list_providers",
16
+ "list_profiles",
17
+ "list_models",
18
+ "list_tools",
19
+ "list_config",
20
+ ]
12
21
 
13
22
 
14
23
  def handle_getter(args, config_mgr=None):
@@ -17,16 +26,22 @@ def handle_getter(args, config_mgr=None):
17
26
  provider = getattr(args, "provider", None)
18
27
  if not provider:
19
28
  import sys
29
+
20
30
  print(
21
31
  "Error: No provider selected. Please set a provider using '-p PROVIDER', '--set provider=name', or configure a provider."
22
32
  )
23
33
  sys.exit(1)
24
34
  provider_instance = ProviderRegistry().get_instance(provider)
35
+ # Lazy import to avoid overhead unless needed
36
+ from janito.cli.cli_commands.list_profiles import handle_list_profiles
37
+
25
38
  GETTER_DISPATCH = {
26
39
  "list_providers": partial(handle_list_providers, args),
27
40
  "list_models": partial(handle_list_models, args, provider_instance),
28
41
  "list_tools": partial(handle_list_tools, args),
42
+ "list_profiles": partial(handle_list_profiles, args),
29
43
  "show_config": partial(handle_show_config, args),
44
+ "list_config": partial(handle_list_config, args),
30
45
  }
31
46
  for arg in GETTER_KEYS:
32
47
  if getattr(args, arg, False) and arg in GETTER_DISPATCH:
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()