janito 2.3.0__py3-none-any.whl → 2.4.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 (150) hide show
  1. janito/__init__.py +6 -6
  2. janito/_version.py +57 -0
  3. janito/agent/setup_agent.py +92 -18
  4. janito/agent/templates/profiles/system_prompt_template_developer.txt.j2 +44 -0
  5. janito/cli/chat_mode/bindings.py +21 -2
  6. janito/cli/chat_mode/chat_entry.py +2 -3
  7. janito/cli/chat_mode/prompt_style.py +5 -0
  8. janito/cli/chat_mode/session.py +80 -94
  9. janito/cli/chat_mode/session_profile_select.py +80 -0
  10. janito/cli/chat_mode/shell/autocomplete.py +21 -21
  11. janito/cli/chat_mode/shell/commands/__init__.py +13 -7
  12. janito/cli/chat_mode/shell/commands/_priv_check.py +5 -0
  13. janito/cli/chat_mode/shell/commands/clear.py +12 -12
  14. janito/cli/chat_mode/shell/commands/conversation_restart.py +30 -0
  15. janito/cli/chat_mode/shell/commands/execute.py +42 -0
  16. janito/cli/chat_mode/shell/commands/help.py +6 -3
  17. janito/cli/chat_mode/shell/commands/model.py +28 -0
  18. janito/cli/chat_mode/shell/commands/multi.py +51 -51
  19. janito/cli/chat_mode/shell/commands/read.py +37 -0
  20. janito/cli/chat_mode/shell/commands/tools.py +45 -18
  21. janito/cli/chat_mode/shell/commands/write.py +37 -0
  22. janito/cli/chat_mode/shell/commands.bak.zip +0 -0
  23. janito/cli/chat_mode/shell/input_history.py +62 -62
  24. janito/cli/chat_mode/shell/session.bak.zip +0 -0
  25. janito/cli/chat_mode/toolbar.py +44 -27
  26. janito/cli/cli_commands/list_models.py +35 -35
  27. janito/cli/cli_commands/list_providers.py +9 -9
  28. janito/cli/cli_commands/list_tools.py +86 -53
  29. janito/cli/cli_commands/model_selection.py +50 -50
  30. janito/cli/cli_commands/set_api_key.py +19 -19
  31. janito/cli/cli_commands/show_config.py +51 -51
  32. janito/cli/cli_commands/show_system_prompt.py +105 -62
  33. janito/cli/config.py +5 -6
  34. janito/cli/core/__init__.py +4 -4
  35. janito/cli/core/event_logger.py +59 -59
  36. janito/cli/core/runner.py +25 -18
  37. janito/cli/core/setters.py +10 -1
  38. janito/cli/core/unsetters.py +54 -54
  39. janito/cli/main_cli.py +28 -5
  40. janito/cli/prompt_core.py +18 -2
  41. janito/cli/prompt_setup.py +56 -0
  42. janito/cli/single_shot_mode/__init__.py +6 -6
  43. janito/cli/single_shot_mode/handler.py +14 -73
  44. janito/cli/verbose_output.py +1 -1
  45. janito/config.py +5 -5
  46. janito/config_manager.py +13 -0
  47. janito/drivers/anthropic/driver.py +113 -113
  48. janito/drivers/dashscope.bak.zip +0 -0
  49. janito/drivers/openai/README.md +20 -0
  50. janito/drivers/openai_responses.bak.zip +0 -0
  51. janito/event_bus/event.py +2 -2
  52. janito/formatting_token.py +54 -54
  53. janito/i18n/__init__.py +35 -35
  54. janito/i18n/messages.py +23 -23
  55. janito/i18n/pt.py +46 -47
  56. janito/llm/README.md +23 -0
  57. janito/llm/__init__.py +5 -5
  58. janito/llm/agent.py +507 -443
  59. janito/llm/driver.py +8 -0
  60. janito/llm/driver_config_builder.py +34 -34
  61. janito/llm/driver_input.py +12 -12
  62. janito/llm/message_parts.py +60 -60
  63. janito/llm/model.py +38 -38
  64. janito/llm/provider.py +196 -196
  65. janito/provider_registry.py +8 -6
  66. janito/providers/anthropic/model_info.py +22 -22
  67. janito/providers/anthropic/provider.py +2 -0
  68. janito/providers/azure_openai/provider.py +3 -0
  69. janito/providers/dashscope.bak.zip +0 -0
  70. janito/providers/deepseek/__init__.py +1 -1
  71. janito/providers/deepseek/model_info.py +16 -16
  72. janito/providers/deepseek/provider.py +94 -91
  73. janito/providers/google/provider.py +3 -0
  74. janito/providers/mistralai/provider.py +3 -0
  75. janito/providers/openai/provider.py +4 -0
  76. janito/providers/registry.py +26 -26
  77. janito/shell.bak.zip +0 -0
  78. janito/tools/DOCSTRING_STANDARD.txt +33 -0
  79. janito/tools/README.md +3 -0
  80. janito/tools/__init__.py +20 -6
  81. janito/tools/adapters/__init__.py +1 -1
  82. janito/tools/adapters/local/__init__.py +65 -62
  83. janito/tools/adapters/local/adapter.py +18 -35
  84. janito/tools/adapters/local/ask_user.py +101 -102
  85. janito/tools/adapters/local/copy_file.py +84 -84
  86. janito/tools/adapters/local/create_directory.py +69 -69
  87. janito/tools/adapters/local/create_file.py +82 -82
  88. janito/tools/adapters/local/delete_text_in_file.py +2 -2
  89. janito/tools/adapters/local/fetch_url.py +97 -97
  90. janito/tools/adapters/local/find_files.py +139 -138
  91. janito/tools/adapters/local/get_file_outline/__init__.py +1 -1
  92. janito/tools/adapters/local/get_file_outline/core.py +117 -117
  93. janito/tools/adapters/local/get_file_outline/java_outline.py +40 -40
  94. janito/tools/adapters/local/get_file_outline/markdown_outline.py +14 -14
  95. janito/tools/adapters/local/get_file_outline/python_outline.py +303 -303
  96. janito/tools/adapters/local/get_file_outline/python_outline_v2.py +156 -156
  97. janito/tools/adapters/local/get_file_outline/search_outline.py +33 -33
  98. janito/tools/adapters/local/move_file.py +2 -2
  99. janito/tools/adapters/local/open_html_in_browser.py +2 -1
  100. janito/tools/adapters/local/open_url.py +2 -2
  101. janito/tools/adapters/local/python_code_run.py +166 -166
  102. janito/tools/adapters/local/python_command_run.py +164 -164
  103. janito/tools/adapters/local/python_file_run.py +163 -163
  104. janito/tools/adapters/local/remove_directory.py +2 -2
  105. janito/tools/adapters/local/remove_file.py +2 -2
  106. janito/tools/adapters/local/replace_text_in_file.py +2 -2
  107. janito/tools/adapters/local/run_bash_command.py +176 -176
  108. janito/tools/adapters/local/run_powershell_command.py +219 -219
  109. janito/tools/adapters/local/search_text/__init__.py +1 -1
  110. janito/tools/adapters/local/search_text/core.py +201 -201
  111. janito/tools/adapters/local/search_text/pattern_utils.py +73 -73
  112. janito/tools/adapters/local/search_text/traverse_directory.py +145 -145
  113. janito/tools/adapters/local/validate_file_syntax/__init__.py +1 -1
  114. janito/tools/adapters/local/validate_file_syntax/core.py +106 -106
  115. janito/tools/adapters/local/validate_file_syntax/css_validator.py +35 -35
  116. janito/tools/adapters/local/validate_file_syntax/html_validator.py +93 -93
  117. janito/tools/adapters/local/validate_file_syntax/js_validator.py +27 -27
  118. janito/tools/adapters/local/validate_file_syntax/json_validator.py +6 -6
  119. janito/tools/adapters/local/validate_file_syntax/markdown_validator.py +109 -109
  120. janito/tools/adapters/local/validate_file_syntax/ps1_validator.py +32 -32
  121. janito/tools/adapters/local/validate_file_syntax/python_validator.py +5 -5
  122. janito/tools/adapters/local/validate_file_syntax/xml_validator.py +11 -11
  123. janito/tools/adapters/local/validate_file_syntax/yaml_validator.py +6 -6
  124. janito/tools/adapters/local/view_file.py +168 -167
  125. janito/tools/inspect_registry.py +17 -17
  126. janito/tools/outline_file.bak.zip +0 -0
  127. janito/tools/permissions.py +45 -0
  128. janito/tools/permissions_parse.py +12 -0
  129. janito/tools/tool_base.py +118 -105
  130. janito/tools/tool_events.py +58 -58
  131. janito/tools/tool_run_exception.py +12 -12
  132. janito/tools/tool_use_tracker.py +81 -81
  133. janito/tools/tool_utils.py +43 -45
  134. janito/tools/tools_adapter.py +25 -20
  135. janito/tools/tools_schema.py +104 -104
  136. {janito-2.3.0.dist-info → janito-2.4.0.dist-info}/METADATA +425 -388
  137. janito-2.4.0.dist-info/RECORD +195 -0
  138. janito/agent/templates/profiles/system_prompt_template_base_pt.txt.j2 +0 -13
  139. janito/agent/templates/profiles/system_prompt_template_main.txt.j2 +0 -37
  140. janito/cli/chat_mode/shell/commands/edit.py +0 -25
  141. janito/cli/chat_mode/shell/commands/exec.py +0 -27
  142. janito/cli/chat_mode/shell/commands/termweb_log.py +0 -92
  143. janito/cli/termweb_starter.py +0 -122
  144. janito/termweb/app.py +0 -95
  145. janito/version.py +0 -4
  146. janito-2.3.0.dist-info/RECORD +0 -181
  147. {janito-2.3.0.dist-info → janito-2.4.0.dist-info}/WHEEL +0 -0
  148. {janito-2.3.0.dist-info → janito-2.4.0.dist-info}/entry_points.txt +0 -0
  149. {janito-2.3.0.dist-info → janito-2.4.0.dist-info}/licenses/LICENSE +0 -0
  150. {janito-2.3.0.dist-info → janito-2.4.0.dist-info}/top_level.txt +0 -0
@@ -1,62 +1,62 @@
1
- import os
2
- import json
3
- from datetime import datetime
4
- from typing import List, Any, Dict
5
-
6
-
7
- class UserInputHistory:
8
- """
9
- Handles loading, saving, and appending of user input history for the shell.
10
- Each day's history is stored in a line-delimited JSONL file (.jsonl) under .janito/input_history/.
11
- Each line is a JSON dict, e.g., {"input": ..., "ts": ...}
12
- """
13
-
14
- def __init__(self, history_dir=None):
15
- self.history_dir = history_dir or os.path.join(".janito", "input_history")
16
- os.makedirs(self.history_dir, exist_ok=True)
17
-
18
- def _get_today_file(self):
19
- today_str = datetime.now().strftime("%y%m%d")
20
- return os.path.join(self.history_dir, f"{today_str}.jsonl")
21
-
22
- def load(self) -> List[Dict[str, Any]]:
23
- """Load today's input history as a list of dicts."""
24
- history_file = self._get_today_file()
25
- history = []
26
- try:
27
- with open(history_file, "r", encoding="utf-8") as f:
28
- for line in f:
29
- line = line.strip()
30
- if not line:
31
- continue
32
- try:
33
- history.append(json.loads(line))
34
- except json.JSONDecodeError:
35
- continue
36
- except FileNotFoundError:
37
- pass
38
- return history
39
-
40
- def sanitize_surrogates(self, s):
41
- if isinstance(s, str):
42
- return s.encode("utf-8", errors="replace").decode("utf-8")
43
- return s
44
-
45
- def append(self, input_str: str):
46
- """Append a new input as a JSON dict to today's history file."""
47
- history_file = self._get_today_file()
48
- input_str = self.sanitize_surrogates(input_str)
49
- entry = {"input": input_str, "ts": datetime.now().isoformat()}
50
- with open(history_file, "a", encoding="utf-8") as f:
51
- f.write(json.dumps(entry, ensure_ascii=False) + "\n")
52
-
53
- def save(self, history_list: List[Any]):
54
- """Overwrite today's history file with the given list (for compatibility)."""
55
- history_file = self._get_today_file()
56
- with open(history_file, "w", encoding="utf-8") as f:
57
- for item in history_list:
58
- if isinstance(item, dict):
59
- f.write(json.dumps(item, ensure_ascii=False) + "\n")
60
- else:
61
- entry = {"input": str(item), "ts": datetime.now().isoformat()}
62
- f.write(json.dumps(entry, ensure_ascii=False) + "\n")
1
+ import os
2
+ import json
3
+ from datetime import datetime
4
+ from typing import List, Any, Dict
5
+
6
+
7
+ class UserInputHistory:
8
+ """
9
+ Handles loading, saving, and appending of user input history for the shell.
10
+ Each day's history is stored in a line-delimited JSONL file (.jsonl) under .janito/input_history/.
11
+ Each line is a JSON dict, e.g., {"input": ..., "ts": ...}
12
+ """
13
+
14
+ def __init__(self, history_dir=None):
15
+ self.history_dir = history_dir or os.path.join(".janito", "input_history")
16
+ os.makedirs(self.history_dir, exist_ok=True)
17
+
18
+ def _get_today_file(self):
19
+ today_str = datetime.now().strftime("%y%m%d")
20
+ return os.path.join(self.history_dir, f"{today_str}.jsonl")
21
+
22
+ def load(self) -> List[Dict[str, Any]]:
23
+ """Load today's input history as a list of dicts."""
24
+ history_file = self._get_today_file()
25
+ history = []
26
+ try:
27
+ with open(history_file, "r", encoding="utf-8") as f:
28
+ for line in f:
29
+ line = line.strip()
30
+ if not line:
31
+ continue
32
+ try:
33
+ history.append(json.loads(line))
34
+ except json.JSONDecodeError:
35
+ continue
36
+ except FileNotFoundError:
37
+ pass
38
+ return history
39
+
40
+ def sanitize_surrogates(self, s):
41
+ if isinstance(s, str):
42
+ return s.encode("utf-8", errors="replace").decode("utf-8")
43
+ return s
44
+
45
+ def append(self, input_str: str):
46
+ """Append a new input as a JSON dict to today's history file."""
47
+ history_file = self._get_today_file()
48
+ input_str = self.sanitize_surrogates(input_str)
49
+ entry = {"input": input_str, "ts": datetime.now().isoformat()}
50
+ with open(history_file, "a", encoding="utf-8") as f:
51
+ f.write(json.dumps(entry, ensure_ascii=False) + "\n")
52
+
53
+ def save(self, history_list: List[Any]):
54
+ """Overwrite today's history file with the given list (for compatibility)."""
55
+ history_file = self._get_today_file()
56
+ with open(history_file, "w", encoding="utf-8") as f:
57
+ for item in history_list:
58
+ if isinstance(item, dict):
59
+ f.write(json.dumps(item, ensure_ascii=False) + "\n")
60
+ else:
61
+ entry = {"input": str(item), "ts": datetime.now().isoformat()}
62
+ f.write(json.dumps(entry, ensure_ascii=False) + "\n")
@@ -1,7 +1,7 @@
1
1
  from prompt_toolkit.formatted_text import HTML
2
2
  from janito.performance_collector import PerformanceCollector
3
3
  from janito.cli.config import config
4
- from janito.version import __version__ as VERSION
4
+ from janito import __version__ as VERSION
5
5
 
6
6
 
7
7
  def format_tokens(n, tag=None):
@@ -20,11 +20,22 @@ def assemble_first_line(provider_name, model_name, role, agent=None):
20
20
  return f" Janito {VERSION} | Provider: <provider>{provider_name}</provider> | Model: <model>{model_name}</model> | Role: <role>{role}</role>"
21
21
 
22
22
 
23
- def assemble_bindings_line(width):
23
+ def assemble_bindings_line(width, permissions=None):
24
+ # permissions: ToolPermissions or None
25
+ def color_state(state):
26
+ if state == "on":
27
+ return 'on '
28
+ else:
29
+ return 'off'
30
+ read_state = color_state("on" if getattr(permissions, "read", False) else "off")
31
+ write_state = color_state("on" if getattr(permissions, "write", False) else "off")
32
+ execute_state = color_state("on" if getattr(permissions, "execute", False) else "off")
24
33
  return (
25
- f" <key-label>CTRL-C</key-label>: Interrupt Request/Exit Shell | "
26
- f"<key-label>F1</key-label>: Restart conversation | "
27
- f"<key-label>F2</key-label>: Exec | "
34
+ f" <key-label>CTRL-C</key-label>: Interrupt/Exit | "
35
+ f"<key-label>F1</key-label>: /restart | "
36
+ f"<key-label>F2</key-label>: <key-toggle-{('on' if not getattr(permissions, 'read', False) else 'off')}>/read {'on ' if not getattr(permissions, 'read', False) else 'off'}</key-toggle-{('on' if not getattr(permissions, 'read', False) else 'off')}> | "
37
+ f"<key-label>F3</key-label>: <key-toggle-{('on' if not getattr(permissions, 'write', False) else 'off')}>/write {'on ' if not getattr(permissions, 'write', False) else 'off'}</key-toggle-{('on' if not getattr(permissions, 'write', False) else 'off')}> | "
38
+ f"<key-label>F4</key-label>: <key-toggle-{('on' if not getattr(permissions, 'execute', False) else 'off')}>/execute {'on ' if not getattr(permissions, 'execute', False) else 'off'}</key-toggle-{('on' if not getattr(permissions, 'execute', False) else 'off')}> | "
28
39
  f"<b>/help</b>: Help | "
29
40
  f"<key-label>F12</key-label>: Do It "
30
41
  )
@@ -40,29 +51,29 @@ def get_toolbar_func(perf: PerformanceCollector, msg_count: int, shell_state):
40
51
  model_name = "?"
41
52
  role = "?"
42
53
  agent = shell_state.agent if hasattr(shell_state, "agent") else None
43
- termweb_support = getattr(shell_state, "termweb_support", False)
44
- termweb_port = (
45
- shell_state.termweb_port if hasattr(shell_state, "termweb_port") else None
54
+ _support = getattr(shell_state, "_support", False)
55
+ _port = (
56
+ shell_state._port if hasattr(shell_state, "_port") else None
46
57
  )
47
- termweb_status = (
48
- shell_state.termweb_status
49
- if hasattr(shell_state, "termweb_status")
58
+ _status = (
59
+ shell_state._status
60
+ if hasattr(shell_state, "_status")
50
61
  else None
51
62
  )
52
63
  # Use cached liveness check only (set by background thread in shell_state)
53
- this_termweb_status = termweb_status
54
- if not termweb_support:
55
- this_termweb_status = None
56
- elif termweb_status == "starting" or termweb_status is None:
57
- this_termweb_status = termweb_status
64
+ this__status = _status
65
+ if not _support:
66
+ this__status = None
67
+ elif _status == "starting" or _status is None:
68
+ this__status = _status
58
69
  else:
59
70
  live_status = (
60
- shell_state.termweb_live_status
61
- if hasattr(shell_state, "termweb_live_status")
71
+ shell_state._live_status
72
+ if hasattr(shell_state, "_live_status")
62
73
  else None
63
74
  )
64
75
  if live_status is not None:
65
- this_termweb_status = live_status
76
+ this__status = live_status
66
77
  if agent is not None:
67
78
  # Use agent API to get provider and model name
68
79
  provider_name = (
@@ -78,15 +89,21 @@ def get_toolbar_func(perf: PerformanceCollector, msg_count: int, shell_state):
78
89
  usage = perf.get_last_request_usage()
79
90
  first_line = assemble_first_line(provider_name, model_name, role, agent=agent)
80
91
 
81
- bindings_line = assemble_bindings_line(width)
92
+ # Get current permissions for toolbar state
93
+ try:
94
+ from janito.tools.permissions import get_global_allowed_permissions
95
+ permissions = get_global_allowed_permissions()
96
+ except Exception:
97
+ permissions = None
98
+ bindings_line = assemble_bindings_line(width, permissions)
82
99
  toolbar_text = first_line + "\n" + bindings_line
83
- # Add termweb status if available, after the F12 line
84
- if this_termweb_status == "online" and termweb_port:
85
- toolbar_text += f"\n<termweb> Termweb </termweb>Online<termweb> at <u>http://localhost:{termweb_port}</u></termweb>"
86
- elif this_termweb_status == "starting":
87
- toolbar_text += "\n<termweb> Termweb </termweb>Starting"
88
- elif this_termweb_status == "offline":
89
- toolbar_text += "\n<termweb> Termweb </termweb>Offline"
100
+ # Add status if available, after the F12 line
101
+ if this__status == "online" and _port:
102
+ toolbar_text += f"\n<> Termweb </>Online"
103
+ elif this__status == "starting":
104
+ toolbar_text += "\n<> Termweb </>Starting"
105
+ elif this__status == "offline":
106
+ toolbar_text += "\n<> Termweb </>Offline"
90
107
  return HTML(toolbar_text)
91
108
 
92
109
  return get_toolbar
@@ -1,35 +1,35 @@
1
- """
2
- CLI Command: List models for the specified/current provider
3
- """
4
-
5
- from janito.cli.cli_commands.model_utils import _print_models_table
6
- import sys
7
-
8
- _provider_instance = None
9
-
10
-
11
- def get_provider_instance():
12
- global _provider_instance
13
- if _provider_instance is None:
14
- _provider_instance = setup_provider()
15
- return _provider_instance
16
-
17
-
18
- def handle_list_models(args, provider_instance):
19
- provider_name = getattr(provider_instance, "name", None)
20
- if not provider_name:
21
- print(
22
- "Error: Provider must be specified with --provider or set as default before listing models."
23
- )
24
- sys.exit(1)
25
- try:
26
- models = list(provider_instance.get_model_info().values())
27
- if models and isinstance(models[0], dict):
28
- _print_models_table(models, provider_name)
29
- else:
30
- print(f"Supported models for provider '{provider_name}':")
31
- for m in models:
32
- print(f"- {m}")
33
- except Exception as e:
34
- print(f"Error listing models for provider '{provider_name}': {e}")
35
- sys.exit(0)
1
+ """
2
+ CLI Command: List models for the specified/current provider
3
+ """
4
+
5
+ from janito.cli.cli_commands.model_utils import _print_models_table
6
+ import sys
7
+
8
+ _provider_instance = None
9
+
10
+
11
+ def get_provider_instance():
12
+ global _provider_instance
13
+ if _provider_instance is None:
14
+ _provider_instance = setup_provider()
15
+ return _provider_instance
16
+
17
+
18
+ def handle_list_models(args, provider_instance):
19
+ provider_name = getattr(provider_instance, "name", None)
20
+ if not provider_name:
21
+ print(
22
+ "Error: Provider must be specified with --provider or set as default before listing models."
23
+ )
24
+ sys.exit(1)
25
+ try:
26
+ models = list(provider_instance.get_model_info().values())
27
+ if models and isinstance(models[0], dict):
28
+ _print_models_table(models, provider_name)
29
+ else:
30
+ print(f"Supported models for provider '{provider_name}':")
31
+ for m in models:
32
+ print(f"- {m}")
33
+ except Exception as e:
34
+ print(f"Error listing models for provider '{provider_name}': {e}")
35
+ sys.exit(0)
@@ -1,9 +1,9 @@
1
- """
2
- CLI Command: List supported LLM providers
3
- """
4
-
5
- from janito.provider_registry import list_providers
6
-
7
-
8
- def handle_list_providers(args=None):
9
- list_providers()
1
+ """
2
+ CLI Command: List supported LLM providers
3
+ """
4
+
5
+ from janito.provider_registry import list_providers
6
+
7
+
8
+ def handle_list_providers(args=None):
9
+ list_providers()
@@ -1,53 +1,86 @@
1
- """
2
- CLI Command: List available tools
3
- """
4
-
5
-
6
- def handle_list_tools(args=None):
7
- from janito.tools.adapters.local.adapter import LocalToolsAdapter
8
- import janito.tools # Ensure all tools are registered
9
-
10
- registry = janito.tools.get_local_tools_adapter()
11
- tools = registry.list_tools()
12
- if tools:
13
- from rich.table import Table
14
- from rich.console import Console
15
- console = Console()
16
- # Get tool instances to check provides_execution and get info
17
- tool_instances = {t.tool_name: t for t in registry.get_tools()}
18
- normal_tools = []
19
- exec_tools = []
20
- for tool in tools:
21
- inst = tool_instances.get(tool, None)
22
- # Extract parameter names from run signature
23
- param_names = []
24
- if inst and hasattr(inst, "run"):
25
- import inspect
26
- sig = inspect.signature(inst.run)
27
- param_names = [p for p in sig.parameters if p != "self"]
28
- info = {
29
- "name": tool,
30
- "params": ", ".join(param_names),
31
- }
32
- if getattr(inst, "provides_execution", False):
33
- exec_tools.append(info)
34
- else:
35
- normal_tools.append(info)
36
- table = Table(title="Registered tools", show_header=True, header_style="bold", show_lines=False, box=None)
37
- table.add_column("Name", style="cyan", no_wrap=True)
38
- table.add_column("Parameters", style="yellow")
39
- for info in normal_tools:
40
- table.add_row(info["name"], info["params"] or "-")
41
- console.print(table)
42
- if exec_tools:
43
- exec_table = Table(title="Execution tools (only available with -x)", show_header=True, header_style="bold", show_lines=False, box=None)
44
- exec_table.add_column("Name", style="cyan", no_wrap=True)
45
- exec_table.add_column("Parameters", style="yellow")
46
- for info in exec_tools:
47
- exec_table.add_row(info["name"], info["params"] or "-")
48
- console.print(exec_table)
49
- else:
50
- print("No tools registered.")
51
- import sys
52
-
53
- sys.exit(0)
1
+ """
2
+ CLI Command: List available tools
3
+ """
4
+
5
+
6
+ def handle_list_tools(args=None):
7
+ from janito.tools.adapters.local.adapter import LocalToolsAdapter
8
+ import janito.tools # Ensure all tools are registered
9
+
10
+ # Determine permissions from args (default: all False)
11
+ from janito.tools.tool_base import ToolPermissions
12
+ read = getattr(args, "read", False) if args else False
13
+ write = getattr(args, "write", False) if args else False
14
+ execute = getattr(args, "exec", False) if args else False
15
+ # If no permissions are specified, assume user wants to list all tools
16
+ if not (read or write or execute):
17
+ read = write = execute = True
18
+ from janito.tools.permissions import set_global_allowed_permissions
19
+ set_global_allowed_permissions(ToolPermissions(read=read, write=write, execute=execute))
20
+ registry = janito.tools.get_local_tools_adapter()
21
+ tools = registry.list_tools()
22
+ if tools:
23
+ from rich.table import Table
24
+ from rich.console import Console
25
+ console = Console()
26
+ # Get tool instances to check provides_execution and get info
27
+ tool_instances = {t.tool_name: t for t in registry.get_tools()}
28
+ read_only_tools = []
29
+ write_only_tools = []
30
+ read_write_tools = []
31
+ exec_tools = []
32
+ for tool in tools:
33
+ inst = tool_instances.get(tool, None)
34
+ # Extract parameter names from run signature
35
+ param_names = []
36
+ if inst and hasattr(inst, "run"):
37
+ import inspect
38
+ sig = inspect.signature(inst.run)
39
+ param_names = [p for p in sig.parameters if p != "self"]
40
+ info = {
41
+ "name": tool,
42
+ "params": ", ".join(param_names),
43
+ }
44
+ perms = getattr(inst, "permissions", None)
45
+ if perms and perms.execute:
46
+ exec_tools.append(info)
47
+ elif perms and perms.read and perms.write:
48
+ read_write_tools.append(info)
49
+ elif perms and perms.read:
50
+ read_only_tools.append(info)
51
+ elif perms and perms.write:
52
+ write_only_tools.append(info)
53
+ # Print each group if not empty
54
+ if read_only_tools:
55
+ table = Table(title="Read-only tools (-r)", show_header=True, header_style="bold", show_lines=False, box=None)
56
+ table.add_column("Name", style="cyan", no_wrap=True)
57
+ table.add_column("Parameters", style="yellow")
58
+ for info in read_only_tools:
59
+ table.add_row(info["name"], info["params"] or "-")
60
+ console.print(table)
61
+ if write_only_tools:
62
+ table = Table(title="Write-only tools (-w)", show_header=True, header_style="bold", show_lines=False, box=None)
63
+ table.add_column("Name", style="cyan", no_wrap=True)
64
+ table.add_column("Parameters", style="yellow")
65
+ for info in write_only_tools:
66
+ table.add_row(info["name"], info["params"] or "-")
67
+ console.print(table)
68
+ if read_write_tools:
69
+ table = Table(title="Read-Write tools (-rw)", show_header=True, header_style="bold", show_lines=False, box=None)
70
+ table.add_column("Name", style="cyan", no_wrap=True)
71
+ table.add_column("Parameters", style="yellow")
72
+ for info in read_write_tools:
73
+ table.add_row(info["name"], info["params"] or "-")
74
+ console.print(table)
75
+ if exec_tools:
76
+ exec_table = Table(title="Execution tools (-x)", show_header=True, header_style="bold", show_lines=False, box=None)
77
+ exec_table.add_column("Name", style="cyan", no_wrap=True)
78
+ exec_table.add_column("Parameters", style="yellow")
79
+ for info in exec_tools:
80
+ exec_table.add_row(info["name"], info["params"] or "-")
81
+ console.print(exec_table)
82
+ else:
83
+ print("No tools registered.")
84
+ import sys
85
+
86
+ sys.exit(0)
@@ -1,50 +1,50 @@
1
- """
2
- CLI Command: Validate and set the model provider selection
3
- """
4
-
5
- from janito.cli.config import config
6
-
7
- _provider_instance = None
8
-
9
-
10
- def get_provider_instance():
11
- global _provider_instance
12
- if _provider_instance is None:
13
- _provider_instance = setup_provider()
14
- return _provider_instance
15
-
16
-
17
- def handle_model_selection(args):
18
- if getattr(args, "model", None):
19
- provider_instance = get_provider_instance()
20
- provider_name = getattr(provider_instance, "name", None)
21
- if not provider_name:
22
- print(
23
- "Error: Provider must be specified with --provider or set as default before selecting a model."
24
- )
25
- import sys
26
-
27
- sys.exit(1)
28
- if not validate_model_for_provider(provider_name, args.model):
29
- sys.exit(1)
30
- config.runtime_set("model", args.model)
31
-
32
-
33
- def validate_model_for_provider(provider_name, model_name):
34
- try:
35
- provider_instance = get_provider_instance()
36
- info_dict = provider_instance.get_model_info()
37
- available_names = [
38
- m["name"] for m in info_dict.values() if isinstance(m, dict) and "name" in m
39
- ]
40
- if model_name in available_names:
41
- return True
42
- else:
43
- print(
44
- f"Error: Model '{model_name}' is not available for provider '{provider_name}'."
45
- )
46
- print(f"Available models: {', '.join(available_names)}")
47
- return False
48
- except Exception as e:
49
- print(f"Error validating model for provider '{provider_name}': {e}")
50
- return False
1
+ """
2
+ CLI Command: Validate and set the model provider selection
3
+ """
4
+
5
+ from janito.cli.config import config
6
+
7
+ _provider_instance = None
8
+
9
+
10
+ def get_provider_instance():
11
+ global _provider_instance
12
+ if _provider_instance is None:
13
+ _provider_instance = setup_provider()
14
+ return _provider_instance
15
+
16
+
17
+ def handle_model_selection(args):
18
+ if getattr(args, "model", None):
19
+ provider_instance = get_provider_instance()
20
+ provider_name = getattr(provider_instance, "name", None)
21
+ if not provider_name:
22
+ print(
23
+ "Error: Provider must be specified with --provider or set as default before selecting a model."
24
+ )
25
+ import sys
26
+
27
+ sys.exit(1)
28
+ if not validate_model_for_provider(provider_name, args.model):
29
+ sys.exit(1)
30
+ config.runtime_set("model", args.model)
31
+
32
+
33
+ def validate_model_for_provider(provider_name, model_name):
34
+ try:
35
+ provider_instance = get_provider_instance()
36
+ info_dict = provider_instance.get_model_info()
37
+ available_names = [
38
+ m["name"] for m in info_dict.values() if isinstance(m, dict) and "name" in m
39
+ ]
40
+ if model_name in available_names:
41
+ return True
42
+ else:
43
+ print(
44
+ f"Error: Model '{model_name}' is not available for provider '{provider_name}'."
45
+ )
46
+ print(f"Available models: {', '.join(available_names)}")
47
+ return False
48
+ except Exception as e:
49
+ print(f"Error validating model for provider '{provider_name}': {e}")
50
+ return False
@@ -1,19 +1,19 @@
1
- """
2
- CLI Command: Set API key for the current or selected provider
3
- """
4
-
5
- from janito.provider_config import set_api_key
6
- from janito.llm.auth import LLMAuthManager
7
-
8
-
9
- def handle_set_api_key(args):
10
- api_key = getattr(args, "set_api_key", None)
11
- provider = getattr(args, "provider", None)
12
- if not provider:
13
- print("Error: --set-api-key requires -p/--provider to be specified.")
14
- return
15
- set_api_key(provider, api_key)
16
- auth_manager = LLMAuthManager()
17
- print(
18
- f"API key set for provider '{provider}'. Auth file updated: {auth_manager._auth_file}"
19
- )
1
+ """
2
+ CLI Command: Set API key for the current or selected provider
3
+ """
4
+
5
+ from janito.provider_config import set_api_key
6
+ from janito.llm.auth import LLMAuthManager
7
+
8
+
9
+ def handle_set_api_key(args):
10
+ api_key = getattr(args, "set_api_key", None)
11
+ provider = getattr(args, "provider", None)
12
+ if not provider:
13
+ print("Error: --set-api-key requires -p/--provider to be specified.")
14
+ return
15
+ set_api_key(provider, api_key)
16
+ auth_manager = LLMAuthManager()
17
+ print(
18
+ f"API key set for provider '{provider}'. Auth file updated: {auth_manager._auth_file}"
19
+ )