janito 2.5.1__py3-none-any.whl → 2.6.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.
- janito/agent/setup_agent.py +231 -223
- janito/agent/templates/profiles/system_prompt_template_software_developer.txt.j2 +39 -0
- janito/cli/chat_mode/bindings.py +1 -26
- janito/cli/chat_mode/session.py +282 -294
- janito/cli/chat_mode/session_profile_select.py +125 -55
- janito/cli/chat_mode/shell/commands/tools.py +51 -48
- janito/cli/chat_mode/toolbar.py +42 -68
- janito/cli/cli_commands/list_tools.py +41 -56
- janito/cli/cli_commands/show_system_prompt.py +70 -49
- janito/cli/core/runner.py +6 -1
- janito/cli/core/setters.py +43 -34
- janito/cli/main_cli.py +25 -1
- janito/cli/prompt_core.py +76 -69
- janito/cli/rich_terminal_reporter.py +22 -1
- janito/cli/single_shot_mode/handler.py +95 -94
- janito/drivers/driver_registry.py +27 -29
- janito/drivers/openai/driver.py +436 -494
- janito/llm/agent.py +54 -68
- janito/provider_registry.py +178 -178
- janito/providers/anthropic/model_info.py +41 -22
- janito/providers/anthropic/provider.py +80 -67
- janito/providers/provider_static_info.py +18 -17
- janito/tools/adapters/local/__init__.py +66 -65
- janito/tools/adapters/local/adapter.py +79 -18
- janito/tools/adapters/local/create_directory.py +9 -9
- janito/tools/adapters/local/create_file.py +12 -12
- janito/tools/adapters/local/delete_text_in_file.py +16 -16
- janito/tools/adapters/local/find_files.py +2 -2
- janito/tools/adapters/local/get_file_outline/core.py +5 -5
- janito/tools/adapters/local/get_file_outline/search_outline.py +4 -4
- janito/tools/adapters/local/open_html_in_browser.py +15 -15
- janito/tools/adapters/local/python_file_run.py +4 -4
- janito/tools/adapters/local/read_files.py +40 -0
- janito/tools/adapters/local/remove_directory.py +5 -5
- janito/tools/adapters/local/remove_file.py +4 -4
- janito/tools/adapters/local/replace_text_in_file.py +21 -21
- janito/tools/adapters/local/run_bash_command.py +1 -1
- janito/tools/adapters/local/search_text/pattern_utils.py +2 -2
- janito/tools/adapters/local/search_text/traverse_directory.py +10 -10
- janito/tools/adapters/local/validate_file_syntax/core.py +7 -7
- janito/tools/adapters/local/validate_file_syntax/css_validator.py +2 -2
- janito/tools/adapters/local/validate_file_syntax/html_validator.py +7 -7
- janito/tools/adapters/local/validate_file_syntax/js_validator.py +2 -2
- janito/tools/adapters/local/validate_file_syntax/json_validator.py +2 -2
- janito/tools/adapters/local/validate_file_syntax/markdown_validator.py +2 -2
- janito/tools/adapters/local/validate_file_syntax/ps1_validator.py +2 -2
- janito/tools/adapters/local/validate_file_syntax/python_validator.py +2 -2
- janito/tools/adapters/local/validate_file_syntax/xml_validator.py +2 -2
- janito/tools/adapters/local/validate_file_syntax/yaml_validator.py +2 -2
- janito/tools/adapters/local/view_file.py +12 -12
- janito/tools/path_security.py +204 -0
- janito/tools/tool_use_tracker.py +12 -12
- janito/tools/tools_adapter.py +66 -34
- {janito-2.5.1.dist-info → janito-2.6.0.dist-info}/METADATA +412 -412
- {janito-2.5.1.dist-info → janito-2.6.0.dist-info}/RECORD +59 -58
- janito/drivers/anthropic/driver.py +0 -113
- janito/tools/adapters/local/get_file_outline/python_outline_v2.py +0 -156
- {janito-2.5.1.dist-info → janito-2.6.0.dist-info}/WHEEL +0 -0
- {janito-2.5.1.dist-info → janito-2.6.0.dist-info}/entry_points.txt +0 -0
- {janito-2.5.1.dist-info → janito-2.6.0.dist-info}/licenses/LICENSE +0 -0
- {janito-2.5.1.dist-info → janito-2.6.0.dist-info}/top_level.txt +0 -0
@@ -1,16 +1,103 @@
|
|
1
|
+
import os
|
2
|
+
from pathlib import Path
|
3
|
+
import questionary
|
4
|
+
from questionary import Style
|
5
|
+
import os
|
6
|
+
from pathlib import Path
|
7
|
+
from prompt_toolkit.formatted_text import HTML
|
8
|
+
from prompt_toolkit import PromptSession
|
9
|
+
from prompt_toolkit.key_binding import KeyBindings
|
10
|
+
from prompt_toolkit.enums import EditingMode
|
11
|
+
from prompt_toolkit.formatted_text import HTML
|
12
|
+
from .prompt_style import chat_shell_style
|
13
|
+
|
14
|
+
|
1
15
|
"""
|
2
16
|
Profile selection logic for Janito Chat CLI using questionary.
|
3
17
|
"""
|
4
|
-
|
5
|
-
|
18
|
+
|
19
|
+
def _handle_helpful_assistant():
|
20
|
+
return {"profile": "assistant", "profile_system_prompt": None}
|
21
|
+
|
22
|
+
def _handle_using_role():
|
23
|
+
role_name = questionary.text("Enter the role name:").ask()
|
24
|
+
return f"role:{role_name}"
|
25
|
+
|
26
|
+
def _get_toolbar(mode):
|
27
|
+
if mode["multiline"]:
|
28
|
+
return HTML("<b>Multiline mode (Esc+Enter to submit). Type /single to switch.</b>")
|
29
|
+
else:
|
30
|
+
return HTML("<b>Single-line mode (Enter to submit). Type /multi for multiline.</b>")
|
31
|
+
|
32
|
+
def _handle_custom_system_prompt():
|
33
|
+
mode = {"multiline": False}
|
34
|
+
bindings = KeyBindings()
|
35
|
+
|
36
|
+
@bindings.add("c-r")
|
37
|
+
def _(event):
|
38
|
+
pass
|
39
|
+
|
40
|
+
@bindings.add("f12")
|
41
|
+
def _(event):
|
42
|
+
buf = event.app.current_buffer
|
43
|
+
buf.text = "Do It"
|
44
|
+
buf.validate_and_handle()
|
45
|
+
|
46
|
+
session = PromptSession(
|
47
|
+
multiline=False,
|
48
|
+
key_bindings=bindings,
|
49
|
+
editing_mode=EditingMode.EMACS,
|
50
|
+
bottom_toolbar=lambda: _get_toolbar(mode),
|
51
|
+
style=chat_shell_style,
|
52
|
+
)
|
53
|
+
prompt_icon = HTML("<inputline>📝 </inputline>")
|
54
|
+
while True:
|
55
|
+
response = session.prompt(prompt_icon)
|
56
|
+
if not mode["multiline"] and response.strip() == "/multi":
|
57
|
+
mode["multiline"] = True
|
58
|
+
session.multiline = True
|
59
|
+
continue
|
60
|
+
elif mode["multiline"] and response.strip() == "/single":
|
61
|
+
mode["multiline"] = False
|
62
|
+
session.multiline = False
|
63
|
+
continue
|
64
|
+
else:
|
65
|
+
sanitized = response.strip()
|
66
|
+
try:
|
67
|
+
sanitized.encode("utf-8")
|
68
|
+
except UnicodeEncodeError:
|
69
|
+
sanitized = sanitized.encode("utf-8", errors="replace").decode("utf-8")
|
70
|
+
return {"profile": None, "profile_system_prompt": sanitized}
|
71
|
+
|
72
|
+
|
73
|
+
def _load_user_profiles():
|
74
|
+
user_profiles_dir = Path.home() / ".janito" / "profiles"
|
75
|
+
profiles = {}
|
76
|
+
if user_profiles_dir.exists() and user_profiles_dir.is_dir():
|
77
|
+
for profile_file in user_profiles_dir.glob("*"):
|
78
|
+
if profile_file.is_file():
|
79
|
+
try:
|
80
|
+
with open(profile_file, "r", encoding="utf-8") as f:
|
81
|
+
profiles[profile_file.stem] = f.read().strip()
|
82
|
+
except Exception:
|
83
|
+
# Ignore unreadable files
|
84
|
+
pass
|
85
|
+
return profiles
|
86
|
+
|
6
87
|
|
7
88
|
def select_profile():
|
89
|
+
user_profiles = _load_user_profiles()
|
8
90
|
choices = [
|
9
91
|
"helpful assistant",
|
10
92
|
"developer",
|
93
|
+
"software developer",
|
11
94
|
"using role...",
|
12
95
|
"full custom system prompt..."
|
13
96
|
]
|
97
|
+
# Add user profiles to choices
|
98
|
+
if user_profiles:
|
99
|
+
choices.extend(user_profiles.keys())
|
100
|
+
|
14
101
|
custom_style = Style([
|
15
102
|
("highlighted", "bg:#00aaff #ffffff"), # background for item under cursor
|
16
103
|
("question", "fg:#00aaff bold"),
|
@@ -21,60 +108,43 @@ def select_profile():
|
|
21
108
|
default=None,
|
22
109
|
style=custom_style
|
23
110
|
).ask()
|
111
|
+
|
24
112
|
if answer == "helpful assistant":
|
25
|
-
return
|
113
|
+
return _handle_helpful_assistant()
|
26
114
|
if answer == "using role...":
|
27
|
-
|
28
|
-
return f"role:{role_name}"
|
115
|
+
return _handle_using_role()
|
29
116
|
elif answer == "full custom system prompt...":
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
while True:
|
64
|
-
response = session.prompt(prompt_icon)
|
65
|
-
if not mode["multiline"] and response.strip() == "/multi":
|
66
|
-
mode["multiline"] = True
|
67
|
-
session.multiline = True
|
68
|
-
continue
|
69
|
-
elif mode["multiline"] and response.strip() == "/single":
|
70
|
-
mode["multiline"] = False
|
71
|
-
session.multiline = False
|
72
|
-
continue
|
73
|
-
else:
|
74
|
-
sanitized = response.strip()
|
75
|
-
try:
|
76
|
-
sanitized.encode("utf-8")
|
77
|
-
except UnicodeEncodeError:
|
78
|
-
sanitized = sanitized.encode("utf-8", errors="replace").decode("utf-8")
|
79
|
-
return {"profile": None, "profile_system_prompt": sanitized}
|
117
|
+
return _handle_custom_system_prompt()
|
118
|
+
elif answer in user_profiles:
|
119
|
+
# Return the content of the user profile as a custom system prompt
|
120
|
+
return {"profile": None, "profile_system_prompt": user_profiles[answer]}
|
121
|
+
elif answer == "software developer":
|
122
|
+
# Return the content of the built-in software developer profile prompt
|
123
|
+
with open("./janito/agent/templates/profiles/system_prompt_template_software_developer.txt.j2", "r", encoding="utf-8") as f:
|
124
|
+
prompt = f.read().strip()
|
125
|
+
return {"profile": "software developer", "profile_system_prompt": prompt}
|
126
|
+
return answer
|
127
|
+
|
128
|
+
choices = [
|
129
|
+
"helpful assistant",
|
130
|
+
"developer",
|
131
|
+
"using role...",
|
132
|
+
"full custom system prompt..."
|
133
|
+
]
|
134
|
+
custom_style = Style([
|
135
|
+
("highlighted", "bg:#00aaff #ffffff"), # background for item under cursor
|
136
|
+
("question", "fg:#00aaff bold"),
|
137
|
+
])
|
138
|
+
answer = questionary.select(
|
139
|
+
"Select a profile to use:",
|
140
|
+
choices=choices,
|
141
|
+
default=None,
|
142
|
+
style=custom_style
|
143
|
+
).ask()
|
144
|
+
if answer == "helpful assistant":
|
145
|
+
return _handle_helpful_assistant()
|
146
|
+
if answer == "using role...":
|
147
|
+
return _handle_using_role()
|
148
|
+
elif answer == "full custom system prompt...":
|
149
|
+
return _handle_custom_system_prompt()
|
80
150
|
return answer
|
@@ -4,67 +4,70 @@ from janito.cli.chat_mode.shell.commands.base import ShellCmdHandler
|
|
4
4
|
class ToolsShellHandler(ShellCmdHandler):
|
5
5
|
help_text = "List available tools"
|
6
6
|
|
7
|
+
def _perm_class(self, perms):
|
8
|
+
if perms.execute:
|
9
|
+
if perms.read and perms.write:
|
10
|
+
return "read-write-execute"
|
11
|
+
elif perms.read:
|
12
|
+
return "read-execute"
|
13
|
+
elif perms.write:
|
14
|
+
return "write-execute"
|
15
|
+
else:
|
16
|
+
return "execute-only"
|
17
|
+
elif perms.read and perms.write:
|
18
|
+
return "read-write"
|
19
|
+
elif perms.read:
|
20
|
+
return "read-only"
|
21
|
+
elif perms.write:
|
22
|
+
return "write-only"
|
23
|
+
else:
|
24
|
+
return "none"
|
25
|
+
|
26
|
+
def _group_tools_by_permission(self, tools, tool_instances):
|
27
|
+
perm_groups = {}
|
28
|
+
for tool in tools:
|
29
|
+
inst = tool_instances.get(tool, None)
|
30
|
+
perms = getattr(inst, 'permissions', None)
|
31
|
+
if not perms:
|
32
|
+
group = "unknown"
|
33
|
+
else:
|
34
|
+
group = self._perm_class(perms)
|
35
|
+
perm_groups.setdefault(group, []).append(tool)
|
36
|
+
return perm_groups
|
37
|
+
|
38
|
+
def _print_tools_table(self, perm_groups):
|
39
|
+
from rich.table import Table
|
40
|
+
table = Table(title="Tools by Permission Class")
|
41
|
+
table.add_column("Permission Type", style="cyan", no_wrap=True)
|
42
|
+
table.add_column("Tools", style="magenta")
|
43
|
+
for group, tool_list in sorted(perm_groups.items()):
|
44
|
+
table.add_row(group, " ".join(sorted(tool_list)))
|
45
|
+
shared_console.print(table)
|
46
|
+
|
47
|
+
def _find_exec_tools(self, registry):
|
48
|
+
exec_tools = []
|
49
|
+
for tool_instance in registry.get_tools():
|
50
|
+
perms = getattr(tool_instance, 'permissions', None)
|
51
|
+
if perms and perms.execute:
|
52
|
+
exec_tools.append(tool_instance.tool_name)
|
53
|
+
return exec_tools
|
54
|
+
|
7
55
|
def run(self):
|
8
56
|
try:
|
9
|
-
|
10
57
|
import janito.tools # Ensure all tools are registered
|
11
58
|
from janito.tools.permissions import get_global_allowed_permissions
|
12
59
|
registry = janito.tools.get_local_tools_adapter()
|
13
60
|
tools = registry.list_tools()
|
14
|
-
from rich.table import Table
|
15
61
|
shared_console.print("Registered tools:")
|
16
62
|
tool_instances = {t.tool_name: t for t in registry.get_tools()}
|
17
63
|
if not tools:
|
18
64
|
shared_console.print("No tools are enabled under the current permission settings.")
|
19
65
|
return
|
20
|
-
|
21
|
-
perm_groups
|
22
|
-
|
23
|
-
if perms.execute:
|
24
|
-
if perms.read and perms.write:
|
25
|
-
return "read-write-execute"
|
26
|
-
elif perms.read:
|
27
|
-
return "read-execute"
|
28
|
-
elif perms.write:
|
29
|
-
return "write-execute"
|
30
|
-
else:
|
31
|
-
return "execute-only"
|
32
|
-
elif perms.read and perms.write:
|
33
|
-
return "read-write"
|
34
|
-
elif perms.read:
|
35
|
-
return "read-only"
|
36
|
-
elif perms.write:
|
37
|
-
return "write-only"
|
38
|
-
else:
|
39
|
-
return "none"
|
40
|
-
for tool in tools:
|
41
|
-
inst = tool_instances.get(tool, None)
|
42
|
-
perms = getattr(inst, 'permissions', None)
|
43
|
-
if not perms:
|
44
|
-
group = "unknown"
|
45
|
-
else:
|
46
|
-
group = perm_class(perms)
|
47
|
-
perm_groups.setdefault(group, []).append(tool)
|
48
|
-
# Build and print table
|
49
|
-
table = Table(title="Tools by Permission Class")
|
50
|
-
table.add_column("Permission Type", style="cyan", no_wrap=True)
|
51
|
-
table.add_column("Tools", style="magenta")
|
52
|
-
for group, tool_list in sorted(perm_groups.items()):
|
53
|
-
table.add_row(group, " ".join(sorted(tool_list)))
|
54
|
-
shared_console.print(table)
|
55
|
-
|
56
|
-
|
57
|
-
# Find all possible execution tools (by permission: execute=True)
|
58
|
-
exec_tools = []
|
59
|
-
for tool_instance in registry.get_tools():
|
60
|
-
perms = getattr(tool_instance, 'permissions', None)
|
61
|
-
if perms and perms.execute:
|
62
|
-
exec_tools.append(tool_instance.tool_name)
|
63
|
-
|
64
|
-
from janito.tools.permissions import get_global_allowed_permissions
|
66
|
+
perm_groups = self._group_tools_by_permission(tools, tool_instances)
|
67
|
+
self._print_tools_table(perm_groups)
|
68
|
+
exec_tools = self._find_exec_tools(registry)
|
65
69
|
perms = get_global_allowed_permissions()
|
66
70
|
if not perms.execute and exec_tools:
|
67
71
|
shared_console.print("[yellow]⚠️ Warning: Execution tools (e.g., commands, code execution) are disabled. Use -x to enable them.[/yellow]")
|
68
|
-
|
69
72
|
except Exception as e:
|
70
73
|
shared_console.print(f"[red]Error loading tools: {e}[/red]")
|
janito/cli/chat_mode/toolbar.py
CHANGED
@@ -3,7 +3,6 @@ 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
|
-
|
7
6
|
def format_tokens(n, tag=None):
|
8
7
|
if n is None:
|
9
8
|
return "?"
|
@@ -15,95 +14,70 @@ def format_tokens(n, tag=None):
|
|
15
14
|
val = f"{n/1000000:.1f}M"
|
16
15
|
return f"<{tag}>{val}</{tag}>" if tag else val
|
17
16
|
|
18
|
-
|
19
17
|
def assemble_first_line(provider_name, model_name, role, agent=None):
|
20
18
|
return f" Janito {VERSION} | Provider: <provider>{provider_name}</provider> | Model: <model>{model_name}</model> | Role: <role>{role}</role>"
|
21
19
|
|
22
|
-
|
23
20
|
def assemble_bindings_line(width, permissions=None):
|
24
|
-
# permissions: ToolPermissions or None
|
25
21
|
def color_state(state):
|
26
|
-
if state == "on"
|
27
|
-
return 'on '
|
28
|
-
else:
|
29
|
-
return 'off'
|
22
|
+
return 'on ' if state == "on" else 'off'
|
30
23
|
read_state = color_state("on" if getattr(permissions, "read", False) else "off")
|
31
24
|
write_state = color_state("on" if getattr(permissions, "write", False) else "off")
|
32
25
|
execute_state = color_state("on" if getattr(permissions, "execute", False) else "off")
|
33
26
|
return (
|
34
27
|
f" <key-label>CTRL-C</key-label>: Interrupt/Exit | "
|
35
|
-
f"<key-label>
|
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
|
+
f"<key-label>F2</key-label>: /restart | "
|
39
29
|
f"<b>/help</b>: Help | "
|
40
30
|
f"<key-label>F12</key-label>: Do It "
|
41
31
|
)
|
42
32
|
|
33
|
+
def _get_status(shell_state):
|
34
|
+
_support = getattr(shell_state, "_support", False)
|
35
|
+
_status = getattr(shell_state, "_status", None)
|
36
|
+
if not _support:
|
37
|
+
return None
|
38
|
+
if _status == "starting" or _status is None:
|
39
|
+
return _status
|
40
|
+
live_status = getattr(shell_state, "_live_status", None)
|
41
|
+
if live_status is not None:
|
42
|
+
return live_status
|
43
|
+
return _status
|
44
|
+
|
45
|
+
def _get_agent_info(agent):
|
46
|
+
provider_name = agent.get_provider_name() if hasattr(agent, "get_provider_name") else "?"
|
47
|
+
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 "?"
|
49
|
+
return provider_name, model_name, role
|
50
|
+
|
51
|
+
def _get_permissions():
|
52
|
+
try:
|
53
|
+
from janito.tools.permissions import get_global_allowed_permissions
|
54
|
+
return get_global_allowed_permissions()
|
55
|
+
except Exception:
|
56
|
+
return None
|
57
|
+
|
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 ""
|
43
66
|
|
44
67
|
def get_toolbar_func(perf: PerformanceCollector, msg_count: int, shell_state):
|
45
68
|
from prompt_toolkit.application.current import get_app
|
46
|
-
import importlib
|
47
|
-
|
48
69
|
def get_toolbar():
|
49
70
|
width = get_app().output.get_size().columns
|
50
|
-
|
51
|
-
|
52
|
-
role = "?"
|
53
|
-
agent = shell_state.agent if hasattr(shell_state, "agent") else None
|
54
|
-
_support = getattr(shell_state, "_support", False)
|
55
|
-
_port = (
|
56
|
-
shell_state._port if hasattr(shell_state, "_port") else None
|
57
|
-
)
|
58
|
-
_status = (
|
59
|
-
shell_state._status
|
60
|
-
if hasattr(shell_state, "_status")
|
61
|
-
else None
|
62
|
-
)
|
63
|
-
# Use cached liveness check only (set by background thread in shell_state)
|
64
|
-
this__status = _status
|
65
|
-
if not _support:
|
66
|
-
this__status = None
|
67
|
-
elif _status == "starting" or _status is None:
|
68
|
-
this__status = _status
|
69
|
-
else:
|
70
|
-
live_status = (
|
71
|
-
shell_state._live_status
|
72
|
-
if hasattr(shell_state, "_live_status")
|
73
|
-
else None
|
74
|
-
)
|
75
|
-
if live_status is not None:
|
76
|
-
this__status = live_status
|
77
|
-
if agent is not None:
|
78
|
-
# Use agent API to get provider and model name
|
79
|
-
provider_name = (
|
80
|
-
agent.get_provider_name()
|
81
|
-
if hasattr(agent, "get_provider_name")
|
82
|
-
else "?"
|
83
|
-
)
|
84
|
-
model_name = (
|
85
|
-
agent.get_model_name() if hasattr(agent, "get_model_name") else "?"
|
86
|
-
)
|
87
|
-
if hasattr(agent, "template_vars"):
|
88
|
-
role = agent.template_vars.get("role", "?")
|
71
|
+
agent = getattr(shell_state, "agent", None)
|
72
|
+
this__status = _get_status(shell_state)
|
73
|
+
provider_name, model_name, role = _get_agent_info(agent) if agent is not None else ("?", "?", "?")
|
89
74
|
usage = perf.get_last_request_usage()
|
90
75
|
first_line = assemble_first_line(provider_name, model_name, role, agent=agent)
|
91
|
-
|
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
|
76
|
+
permissions = _get_permissions()
|
98
77
|
bindings_line = assemble_bindings_line(width, permissions)
|
99
78
|
toolbar_text = first_line + "\n" + bindings_line
|
100
|
-
|
101
|
-
|
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"
|
79
|
+
_port = getattr(shell_state, "_port", None)
|
80
|
+
toolbar_text += _get_termweb_status_line(this__status, _port)
|
107
81
|
return HTML(toolbar_text)
|
108
|
-
|
109
82
|
return get_toolbar
|
83
|
+
|
@@ -3,16 +3,49 @@ CLI Command: List available tools
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
|
6
|
+
def _group_tools_by_permission(tools, tool_instances):
|
7
|
+
read_only_tools = []
|
8
|
+
write_only_tools = []
|
9
|
+
read_write_tools = []
|
10
|
+
exec_tools = []
|
11
|
+
import inspect
|
12
|
+
for tool in tools:
|
13
|
+
inst = tool_instances.get(tool, None)
|
14
|
+
param_names = []
|
15
|
+
if inst and hasattr(inst, "run"):
|
16
|
+
sig = inspect.signature(inst.run)
|
17
|
+
param_names = [p for p in sig.parameters if p != "self"]
|
18
|
+
info = {
|
19
|
+
"name": tool,
|
20
|
+
"params": ", ".join(param_names),
|
21
|
+
}
|
22
|
+
perms = getattr(inst, "permissions", None)
|
23
|
+
if perms and perms.execute:
|
24
|
+
exec_tools.append(info)
|
25
|
+
elif perms and perms.read and perms.write:
|
26
|
+
read_write_tools.append(info)
|
27
|
+
elif perms and perms.read:
|
28
|
+
read_only_tools.append(info)
|
29
|
+
elif perms and perms.write:
|
30
|
+
write_only_tools.append(info)
|
31
|
+
return read_only_tools, write_only_tools, read_write_tools, exec_tools
|
32
|
+
|
33
|
+
def _print_tools_table(console, title, tools_info):
|
34
|
+
from rich.table import Table
|
35
|
+
table = Table(title=title, show_header=True, header_style="bold", show_lines=False, box=None)
|
36
|
+
table.add_column("Name", style="cyan", no_wrap=True)
|
37
|
+
table.add_column("Parameters", style="yellow")
|
38
|
+
for info in tools_info:
|
39
|
+
table.add_row(info["name"], info["params"] or "-")
|
40
|
+
console.print(table)
|
41
|
+
|
6
42
|
def handle_list_tools(args=None):
|
7
43
|
from janito.tools.adapters.local.adapter import LocalToolsAdapter
|
8
44
|
import janito.tools # Ensure all tools are registered
|
9
|
-
|
10
|
-
# Determine permissions from args (default: all False)
|
11
45
|
from janito.tools.tool_base import ToolPermissions
|
12
46
|
read = getattr(args, "read", False) if args else False
|
13
47
|
write = getattr(args, "write", False) if args else False
|
14
48
|
execute = getattr(args, "exec", False) if args else False
|
15
|
-
# If no permissions are specified, assume user wants to list all tools
|
16
49
|
if not (read or write or execute):
|
17
50
|
read = write = execute = True
|
18
51
|
from janito.tools.permissions import set_global_allowed_permissions
|
@@ -20,67 +53,19 @@ def handle_list_tools(args=None):
|
|
20
53
|
registry = janito.tools.get_local_tools_adapter()
|
21
54
|
tools = registry.list_tools()
|
22
55
|
if tools:
|
23
|
-
from rich.table import Table
|
24
56
|
from rich.console import Console
|
25
57
|
console = Console()
|
26
|
-
# Get tool instances to check provides_execution and get info
|
27
58
|
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
|
59
|
+
read_only_tools, write_only_tools, read_write_tools, exec_tools = _group_tools_by_permission(tools, tool_instances)
|
54
60
|
if read_only_tools:
|
55
|
-
|
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
|
+
_print_tools_table(console, "Read-only tools (-r)", read_only_tools)
|
61
62
|
if write_only_tools:
|
62
|
-
|
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)
|
63
|
+
_print_tools_table(console, "Write-only tools (-w)", write_only_tools)
|
68
64
|
if read_write_tools:
|
69
|
-
|
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)
|
65
|
+
_print_tools_table(console, "Read-Write tools (-rw)", read_write_tools)
|
75
66
|
if exec_tools:
|
76
|
-
|
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)
|
67
|
+
_print_tools_table(console, "Execution tools (-x)", exec_tools)
|
82
68
|
else:
|
83
69
|
print("No tools registered.")
|
84
70
|
import sys
|
85
|
-
|
86
71
|
sys.exit(0)
|