Skip to content

Commit b332204

Browse files
committed
✨ Unit test: The terminal tool supports password login #1052
1 parent 574e330 commit b332204

File tree

4 files changed

+606
-91
lines changed

4 files changed

+606
-91
lines changed

backend/database/tool_db.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,7 @@ def add_tool_field(tool_info):
165165
tool_params = tool.params
166166
for ele in tool_params:
167167
param_name = ele["name"]
168-
param_value = tool_info["params"].get(param_name)
169-
ele["default"] = param_value
168+
ele["default"] = tool_info["params"].get(param_name)
170169

171170
tool_dict = as_dict(tool)
172171
tool_dict["params"] = tool_params

docker/deploy.sh

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -386,19 +386,19 @@ deploy_infrastructure() {
386386
echo "🔧 Starting infrastructure services..."
387387
INFRA_SERVICES="nexent-elasticsearch nexent-postgresql nexent-minio redis"
388388

389-
# Add openssh-server if Terminal tool is enabled
390-
if [ "$ENABLE_TERMINAL_TOOL" = "true" ]; then
389+
# Add openssh-server if Terminal tool container is enabled
390+
if [ "$ENABLE_TERMINAL_TOOL_CONTAINER" = "true" ]; then
391391
INFRA_SERVICES="$INFRA_SERVICES nexent-openssh-server"
392-
echo "🔧 Terminal tool enabled - openssh-server will be included in infrastructure"
392+
echo "🔧 Terminal tool container enabled - openssh-server will be included in infrastructure"
393393
fi
394394

395395
if ! ${docker_compose_command} -p nexent -f "docker-compose${COMPOSE_FILE_SUFFIX}" up -d $INFRA_SERVICES; then
396396
echo " ❌ ERROR Failed to start infrastructure services"
397397
exit 1
398398
fi
399399

400-
if [ "$ENABLE_TERMINAL_TOOL" = "true" ]; then
401-
echo "🔧 Terminal tool (openssh-server) is now available for AI agents"
400+
if [ "$ENABLE_TERMINAL_TOOL_CONTAINER" = "true" ]; then
401+
echo "🔧 Terminal tool container (openssh-server) is now available for AI agents"
402402
fi
403403

404404
# Deploy Supabase services based on DEPLOYMENT_VERSION
@@ -514,34 +514,33 @@ wait_for_elasticsearch_healthy() {
514514
}
515515

516516
select_terminal_tool() {
517-
# Function to ask if user wants to enable Terminal tool
518-
echo "🔧 Terminal Tool Configuration:"
517+
# Function to ask if user wants to create Terminal tool container
518+
echo "🔧 Terminal Tool Container Setup:"
519519
echo " Terminal tool allows AI agents to execute shell commands via SSH."
520-
echo " This creates an openssh-server container for secure command execution."
520+
echo " This will create an openssh-server container for secure command execution."
521521
if [ -n "$ENABLE_TERMINAL" ]; then
522522
enable_terminal="$ENABLE_TERMINAL"
523523
else
524-
read -p "👉 Do you want to enable Terminal tool? [Y/N] (default: N): " enable_terminal
524+
read -p "👉 Do you want to create Terminal tool container? [Y/N] (default: N): " enable_terminal
525525
fi
526526

527527
# Sanitize potential Windows CR in input
528528
enable_terminal=$(sanitize_input "$enable_terminal")
529529

530530
if [[ "$enable_terminal" =~ ^[Yy]$ ]]; then
531-
export ENABLE_TERMINAL_TOOL="true"
531+
export ENABLE_TERMINAL_TOOL_CONTAINER="true"
532532
export COMPOSE_PROFILES="${COMPOSE_PROFILES:+$COMPOSE_PROFILES,}terminal"
533-
echo "✅ Terminal tool enabled 🔧"
534-
echo " 🔧 Deploying an openssh-server container for secure command execution"
535-
update_env_var "ENABLE_TERMINAL_TOOL" "true"
533+
echo "✅ Terminal tool container will be created 🔧"
534+
echo " 🔧 Creating openssh-server container for secure command execution"
536535

537-
# Ask user to specify directory mapping
536+
# Ask user to specify directory mapping for container
538537
default_terminal_dir="/opt/terminal"
539-
echo " 📁 Terminal directory configuration:"
538+
echo " 📁 Terminal container directory mapping:"
540539
echo " • Container path: /opt/terminal (fixed)"
541540
echo " • Host path: You can specify any directory on your host machine"
542541
echo " • Default host path: /opt/terminal (recommended)"
543542
echo ""
544-
read -p " 📁 Enter host directory to mount (default: /opt/terminal): " terminal_mount_dir
543+
read -p " 📁 Enter host directory to mount to container (default: /opt/terminal): " terminal_mount_dir
545544
terminal_mount_dir=$(sanitize_input "$terminal_mount_dir")
546545
TERMINAL_MOUNT_DIR="${terminal_mount_dir:-$default_terminal_dir}"
547546

@@ -555,8 +554,8 @@ select_terminal_tool() {
555554
echo " • This directory will be created if it doesn't exist"
556555
echo ""
557556

558-
# Setup SSH credentials for Terminal tool
559-
echo "🔐 Setting up SSH credentials for Terminal tool..."
557+
# Setup SSH credentials for Terminal tool container
558+
echo "🔐 Setting up SSH credentials for Terminal tool container..."
560559

561560
# Check if SSH credentials are already set
562561
if [ -n "$SSH_USERNAME" ] && [ -n "$SSH_PASSWORD" ]; then
@@ -565,7 +564,7 @@ select_terminal_tool() {
565564
echo "🔑 Password: [HIDDEN]"
566565
else
567566
# Prompt for SSH credentials
568-
echo "Please enter SSH credentials for Terminal tool:"
567+
echo "Please enter SSH credentials for Terminal tool container:"
569568
echo ""
570569

571570
# Get SSH username
@@ -609,9 +608,8 @@ select_terminal_tool() {
609608
fi
610609
echo ""
611610
else
612-
export ENABLE_TERMINAL_TOOL="false"
613-
echo "🚫 Terminal tool disabled"
614-
update_env_var "ENABLE_TERMINAL_TOOL" "false"
611+
export ENABLE_TERMINAL_TOOL_CONTAINER="false"
612+
echo "🚫 Terminal tool container disabled"
615613
fi
616614
echo ""
617615
echo "--------------------------------"
@@ -676,7 +674,7 @@ main_deploy() {
676674
# Select deployment version, mode and image source
677675
select_deployment_version || { echo "❌ Deployment version selection failed"; exit 1; }
678676
select_deployment_mode || { echo "❌ Deployment mode selection failed"; exit 1; }
679-
select_terminal_tool || { echo "❌ Terminal tool configuration failed"; exit 1; }
677+
select_terminal_tool || { echo "❌ Terminal tool container configuration failed"; exit 1; }
680678
choose_image_env || { echo "❌ Image environment setup failed"; exit 1; }
681679

682680
# Add permission

sdk/nexent/core/tools/terminal_tool.py

Lines changed: 7 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@ class TerminalTool(Tool):
3131

3232
tool_sign = ToolSign.TERMINAL_OPERATION.value # Terminal operation tool identifier
3333

34-
# Class-level session storage
35-
_sessions: Dict[str, Dict[str, Any]] = {}
36-
3734
def __init__(self,
3835
init_path: str = Field(description="Initial workspace path", default="~"),
3936
observer: MessageObserver = Field(description="Message observer", default=None, exclude=True),
@@ -52,12 +49,17 @@ def __init__(self,
5249
password (str): SSH password for authentication. Required parameter.
5350
"""
5451
super().__init__()
55-
# Handle ~ for home directory
52+
# Handle ~ for home directory and None values
5653
if init_path == "~":
5754
self.init_path = "~"
55+
elif init_path is None:
56+
self.init_path = None
5857
else:
5958
self.init_path = os.path.abspath(init_path)
60-
59+
60+
# Class-level session storage
61+
self._sessions: Dict[str, Dict[str, Any]] = {}
62+
6163
self.observer = observer
6264
self.ssh_host = ssh_host
6365
self.ssh_port = ssh_port
@@ -339,64 +341,3 @@ def forward(self, command: str, session_name: str = "default", timeout: int = 30
339341
"error": str(e),
340342
"timestamp": time.time()
341343
}, ensure_ascii=False, indent=2)
342-
343-
@classmethod
344-
def cleanup_all_sessions(cls):
345-
"""Clean up all active sessions."""
346-
for session_name, session in cls._sessions.items():
347-
try:
348-
if session and "channel" in session:
349-
session["channel"].close()
350-
if session and "client" in session:
351-
session["client"].close()
352-
except:
353-
pass
354-
cls._sessions.clear()
355-
logger.info("All SSH sessions cleaned up")
356-
357-
358-
if __name__ == "__main__":
359-
"""Test the TerminalTool functionality"""
360-
import sys
361-
362-
# Basic configuration - 直接创建实例并设置属性
363-
tool = TerminalTool.__new__(TerminalTool)
364-
Tool.__init__(tool)
365-
tool.init_path = "~" # Use home directory as default
366-
tool.observer = None
367-
tool.ssh_host = "localhost" # For local testing
368-
tool.ssh_port = 2222
369-
tool.ssh_user = input("Enter SSH username: ").strip()
370-
tool.password = input("Enter SSH password: ").strip()
371-
tool.running_prompt_zh = "正在执行终端命令..."
372-
tool.running_prompt_en = "Executing terminal command..."
373-
374-
print("=== Terminal Tool Test ===")
375-
print("Make sure openssh-server container is running and password authentication is configured.")
376-
print("You will be prompted to enter SSH username and password.")
377-
print("Commands to test: 'ls -la', 'pwd', 'whoami', 'echo \"Hello World\"', 'exit'")
378-
print()
379-
380-
try:
381-
while True:
382-
command = input("Enter command (or 'quit' to exit): ").strip()
383-
384-
if command.lower() in ['quit', 'exit']:
385-
break
386-
387-
if not command:
388-
continue
389-
390-
print(f"\n>>> Executing: {command}")
391-
result = tool.forward(command, session_name="test_session", timeout=30)
392-
print(f"Result: {result}")
393-
print("-" * 50)
394-
395-
except KeyboardInterrupt:
396-
print("\nTest interrupted by user")
397-
except Exception as e:
398-
print(f"Test error: {e}")
399-
finally:
400-
print("Cleaning up sessions...")
401-
TerminalTool.cleanup_all_sessions()
402-
print("Test completed.")

0 commit comments

Comments
 (0)