feat: Add agent listing functionality (#444)
* Create agent listing functionality * feat: add agent listing functionality with proper documentation and style * removed pyopenagi and focusing only on cerebrum
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -206,4 +206,7 @@ workspace
|
||||
cache
|
||||
|
||||
# Ignore configuration files
|
||||
aios/config/config.yaml
|
||||
aios/config/config.yaml
|
||||
|
||||
# ignore cerebrum
|
||||
Cerebrum/*
|
||||
|
||||
@@ -21,4 +21,4 @@ llm:
|
||||
|
||||
server:
|
||||
host: "localhost"
|
||||
port: 8000
|
||||
port: 8000
|
||||
|
||||
@@ -60,8 +60,14 @@ python -m pip install --upgrade pip
|
||||
|
||||
pip install -r "$INSTALL_DIR/src/requirements.txt"
|
||||
|
||||
# Remove non-kernel files
|
||||
# Remove non-kernel files but preserve necessary scripts
|
||||
mkdir -p "$INSTALL_DIR/src/scripts_temp"
|
||||
cp "$INSTALL_DIR/src/scripts/list_agents.py" "$INSTALL_DIR/src/scripts_temp/"
|
||||
rm -rf "$INSTALL_DIR/src/scripts"
|
||||
mkdir -p "$INSTALL_DIR/src/scripts"
|
||||
mv "$INSTALL_DIR/src/scripts_temp/list_agents.py" "$INSTALL_DIR/src/scripts/"
|
||||
rm -rf "$INSTALL_DIR/src/scripts_temp"
|
||||
|
||||
rm -rf "$INSTALL_DIR/src/tests"
|
||||
rm -rf "$INSTALL_DIR/src/docs"
|
||||
|
||||
@@ -99,14 +105,14 @@ start() {
|
||||
return
|
||||
fi
|
||||
source "$INSTALL_DIR/venv/bin/activate"
|
||||
|
||||
|
||||
# Check Python version before starting
|
||||
PYTHON_VERSION=$(python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
|
||||
if [[ ! "$PYTHON_VERSION" =~ ^3\.(10|11)$ ]]; then
|
||||
echo "Error: Unsupported Python version $PYTHON_VERSION. Only Python 3.10 or 3.11 are supported."
|
||||
return 1
|
||||
fi
|
||||
|
||||
|
||||
load_env
|
||||
cd "$INSTALL_DIR/src"
|
||||
nohup uvicorn runtime.kernel:app --reload > "$INSTALL_DIR/server.log" 2>&1 &
|
||||
@@ -133,13 +139,13 @@ restart() {
|
||||
|
||||
update() {
|
||||
echo "Checking for updates..."
|
||||
|
||||
|
||||
# Stop server if running
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
echo "Stopping server for update..."
|
||||
stop
|
||||
fi
|
||||
|
||||
|
||||
# Check Python version before updating
|
||||
source "$INSTALL_DIR/venv/bin/activate"
|
||||
PYTHON_VERSION=$(python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
|
||||
@@ -147,43 +153,43 @@ update() {
|
||||
echo "Error: Unsupported Python version $PYTHON_VERSION. Only Python 3.10 or 3.11 are supported."
|
||||
return 1
|
||||
fi
|
||||
|
||||
|
||||
# Store current commit hash
|
||||
cd "$INSTALL_DIR/src"
|
||||
current_hash=$(git rev-parse HEAD)
|
||||
|
||||
|
||||
# Fetch and pull latest changes
|
||||
git fetch origin
|
||||
remote_hash=$(git rev-parse origin/$(git rev-parse --abbrev-ref HEAD))
|
||||
|
||||
|
||||
if [ "$current_hash" = "$remote_hash" ]; then
|
||||
echo "Already up to date!"
|
||||
start
|
||||
return
|
||||
fi
|
||||
|
||||
|
||||
echo "Updates found, installing..."
|
||||
|
||||
|
||||
# Pull latest changes
|
||||
git pull
|
||||
|
||||
|
||||
# Activate venv and update dependencies
|
||||
pip install -r requirements.txt
|
||||
|
||||
|
||||
# Remove any new non-kernel files that might have been added
|
||||
rm -rf "$INSTALL_DIR/src/scripts"
|
||||
rm -rf "$INSTALL_DIR/src/tests"
|
||||
rm -rf "$INSTALL_DIR/src/docs"
|
||||
|
||||
|
||||
rm -f "$INSTALL_DIR/src/requirements-cuda.txt"
|
||||
rm -f "$INSTALL_DIR/src/.dockerignore"
|
||||
rm -f "$INSTALL_DIR/src/.env.example"
|
||||
rm -f "$INSTALL_DIR/src/.precommit-config.yaml"
|
||||
rm -f "$INSTALL_DIR/src/README.md"
|
||||
rm -f "$INSTALL_DIR/src/Dockerfile"
|
||||
|
||||
|
||||
echo "Update complete!"
|
||||
|
||||
|
||||
# Restart server
|
||||
start
|
||||
}
|
||||
@@ -191,18 +197,18 @@ update() {
|
||||
clean() {
|
||||
# First stop everything
|
||||
stop
|
||||
|
||||
|
||||
# Deactivate virtual environment if active
|
||||
if [ -n "$VIRTUAL_ENV" ]; then
|
||||
deactivate
|
||||
fi
|
||||
|
||||
|
||||
# Remove the installation directory
|
||||
rm -rf "$INSTALL_DIR"
|
||||
|
||||
|
||||
# Remove the executable
|
||||
rm -f "$HOME/.local/bin/aios"
|
||||
|
||||
|
||||
echo "AIOS installation cleaned up successfully"
|
||||
}
|
||||
|
||||
@@ -210,17 +216,17 @@ env_add() {
|
||||
echo "Adding new environment variable"
|
||||
echo "Enter variable name (e.g., API_KEY):"
|
||||
read varname
|
||||
|
||||
|
||||
# Validate variable name
|
||||
if [[ ! $varname =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then
|
||||
echo "Invalid variable name. Use only letters, numbers, and underscores, and start with a letter or underscore."
|
||||
return 1
|
||||
fi
|
||||
|
||||
|
||||
echo "Enter variable value:"
|
||||
read -s varvalue # -s flag hides the input (good for sensitive values)
|
||||
echo # Add newline after hidden input
|
||||
|
||||
|
||||
# Check if variable already exists
|
||||
if grep -q "^$varname=" "$ENV_FILE" 2>/dev/null; then
|
||||
echo "Variable $varname already exists. Do you want to update it? (y/n)"
|
||||
@@ -232,7 +238,7 @@ env_add() {
|
||||
# Remove old value
|
||||
sed -i.bak "/^$varname=/d" "$ENV_FILE" && rm "$ENV_FILE.bak"
|
||||
fi
|
||||
|
||||
|
||||
# Add new value
|
||||
echo "$varname=$varvalue" >> "$ENV_FILE"
|
||||
echo "Environment variable added successfully"
|
||||
@@ -255,7 +261,7 @@ env_remove() {
|
||||
echo ""
|
||||
echo "Enter the number of the variable to remove:"
|
||||
read varnum
|
||||
|
||||
|
||||
if [[ "$varnum" =~ ^[0-9]+$ ]]; then
|
||||
varname=$(sed -n "${varnum}p" "$ENV_FILE" | cut -d= -f1)
|
||||
if [ -n "$varname" ]; then
|
||||
@@ -331,6 +337,31 @@ Subcommands:
|
||||
- Immediate removal from configuration
|
||||
|
||||
Note: Server restart required for environment changes to take effect
|
||||
HELP
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
"agents")
|
||||
case "$2" in
|
||||
"list")
|
||||
# Activate virtual environment and run Python script
|
||||
source "$INSTALL_DIR/venv/bin/activate"
|
||||
python "$INSTALL_DIR/src/scripts/list_agents.py"
|
||||
;;
|
||||
*)
|
||||
cat << 'HELP'
|
||||
Agent Management
|
||||
|
||||
Usage: aios agents <subcommand>
|
||||
|
||||
Subcommands:
|
||||
list List all available agents
|
||||
- Shows Cerebrum built-in agents
|
||||
- Shows cached agents from previous installations
|
||||
- Shows available agents to install from AIOS foundation
|
||||
- Displays versions and sources for each agent
|
||||
|
||||
Note: Requires active internet connection for online agent listing
|
||||
HELP
|
||||
;;
|
||||
esac
|
||||
@@ -373,6 +404,14 @@ Commands:
|
||||
remove - Remove a variable (interactive)
|
||||
Environment changes require server restart to take effect
|
||||
|
||||
agents Manage AIOS agents
|
||||
Subcommands:
|
||||
list - List all available agents
|
||||
• Shows Cerebrum built-in agents
|
||||
• Shows cached agents from previous installations
|
||||
• Shows available agents to install from AIOS foundation
|
||||
• Displays versions and sources for each agent
|
||||
|
||||
clean Uninstall AIOS completely
|
||||
- Stops any running server
|
||||
- Removes all AIOS files and configurations
|
||||
@@ -383,6 +422,7 @@ Commands:
|
||||
Examples:
|
||||
aios start # Start the server
|
||||
aios env add # Add a new API key or configuration value
|
||||
aios agents list # View all available agents
|
||||
aios update # Update to the latest version
|
||||
|
||||
Notes:
|
||||
@@ -428,4 +468,4 @@ Note: AIOS requires Python 3.10 or 3.11
|
||||
|
||||
For more information, visit:
|
||||
https://github.com/agiresearch/AIOS
|
||||
COMPLETE
|
||||
COMPLETE
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
# scripts
|
||||
|
||||
## list_agents.py
|
||||
|
||||
List all agents available to use and install.
|
||||
|
||||
155
scripts/list_agents.py
Normal file
155
scripts/list_agents.py
Normal file
@@ -0,0 +1,155 @@
|
||||
# This file provides functionality to list both offline and online AIOS agents.
|
||||
# It can display locally installed agents as well as agents available for installation
|
||||
# from the AIOS foundation.
|
||||
|
||||
import os
|
||||
import importlib
|
||||
from pathlib import Path
|
||||
from typing import Dict, List
|
||||
from cerebrum.manager.agent import AgentManager
|
||||
import platformdirs
|
||||
|
||||
def parse_version_from_filename(filename: str) -> str:
|
||||
"""Extract version from a filename like 'agent_1.2.3.agent'
|
||||
|
||||
Args:
|
||||
filename (str): The filename to parse version from
|
||||
|
||||
Returns:
|
||||
str: The extracted version string
|
||||
"""
|
||||
return filename.replace('agent_', '').replace('.agent', '')
|
||||
|
||||
def get_offline_agents() -> Dict[str, List[str]]:
|
||||
"""Get all locally downloaded/installed agents with their versions
|
||||
|
||||
This function checks multiple locations for installed agents:
|
||||
- Cerebrum built-in agents
|
||||
- User's cache directory
|
||||
|
||||
Returns:
|
||||
Dict[str, List[str]]: A dictionary mapping agent IDs to their available versions
|
||||
"""
|
||||
offline_agents = {}
|
||||
|
||||
# Check in Cerebrum built-in agents
|
||||
try:
|
||||
cerebrum_path = importlib.util.find_spec('cerebrum').submodule_search_locations[0]
|
||||
example_paths = [
|
||||
os.path.join(cerebrum_path, "example", "agents"),
|
||||
os.path.join(cerebrum_path, "cerebrum", "example", "agents")
|
||||
]
|
||||
|
||||
for example_path in example_paths:
|
||||
if os.path.exists(example_path):
|
||||
for agent in os.listdir(example_path):
|
||||
agent_path = os.path.join(example_path, agent)
|
||||
if os.path.isdir(agent_path) and os.path.exists(os.path.join(agent_path, 'agent.py')):
|
||||
agent_id = f"example/{agent}"
|
||||
if agent_id not in offline_agents:
|
||||
offline_agents[agent_id] = ["built-in"]
|
||||
except (ImportError, AttributeError):
|
||||
print("Error getting offline agents: cerebrum package not found")
|
||||
|
||||
# Check in cache directory
|
||||
try:
|
||||
cache_dir = Path(platformdirs.user_cache_dir("cerebrum"))
|
||||
if cache_dir.exists():
|
||||
for author in cache_dir.iterdir():
|
||||
if author.is_dir():
|
||||
for agent in author.iterdir():
|
||||
if agent.is_dir():
|
||||
agent_id = f"{author.name}/{agent.name}"
|
||||
versions = []
|
||||
for version_file in agent.glob("*.agent"):
|
||||
version = parse_version_from_filename(version_file.stem)
|
||||
versions.append(version)
|
||||
if versions:
|
||||
offline_agents[agent_id] = sorted(versions, key=lambda v: [int(x) for x in v.split('.')])
|
||||
except Exception as e:
|
||||
print(f"Error getting offline agents: Could not access cache directory: {str(e)}")
|
||||
|
||||
return offline_agents
|
||||
|
||||
def get_online_agents() -> Dict[str, List[str]]:
|
||||
"""Get all available online agents from AIOS foundation with their versions
|
||||
|
||||
This function connects to the AIOS foundation server to retrieve a list of
|
||||
all available agents and their versions.
|
||||
|
||||
Returns:
|
||||
Dict[str, List[str]]: A dictionary mapping agent IDs to their available versions
|
||||
"""
|
||||
online_agents = {}
|
||||
try:
|
||||
manager = AgentManager("https://app.aios.foundation/")
|
||||
agent_list = manager.list_available_agents()
|
||||
for agent_info in agent_list:
|
||||
# Parse the full agent path which includes version
|
||||
full_path = agent_info["agent"]
|
||||
agent_path, version = full_path.rsplit("/", 1)
|
||||
if agent_path in online_agents:
|
||||
online_agents[agent_path].append(version)
|
||||
else:
|
||||
online_agents[agent_path] = [version]
|
||||
|
||||
# Sort versions for each agent
|
||||
for agent_id in online_agents:
|
||||
online_agents[agent_id] = sorted(online_agents[agent_id], key=lambda v: [int(x) for x in v.split('.')])
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error getting online agents: {str(e)}")
|
||||
|
||||
return online_agents
|
||||
|
||||
def main():
|
||||
"""Main function to list all offline and online AIOS agents
|
||||
|
||||
This function retrieves and displays:
|
||||
- Offline agents that are ready to use (locally installed)
|
||||
- Online agents that are available to install
|
||||
Each agent entry shows its latest version and any other available versions.
|
||||
"""
|
||||
# Get offline and online agents
|
||||
offline_agents = get_offline_agents()
|
||||
online_agents = get_online_agents()
|
||||
|
||||
# Print results
|
||||
print("\n=== List of Agents ===")
|
||||
|
||||
print("Offline Agents (Ready to Use):")
|
||||
print("-" * 50)
|
||||
if offline_agents:
|
||||
for agent_id in sorted(offline_agents.keys()):
|
||||
versions = offline_agents[agent_id]
|
||||
if len(versions) == 1 and versions[0] in ["local", "built-in"]:
|
||||
print(f" • {agent_id} [{versions[0]}]")
|
||||
else:
|
||||
latest_version = versions[-1] if versions else "unknown"
|
||||
other_versions = versions[:-1] if len(versions) > 1 else []
|
||||
version_str = f"v{latest_version}"
|
||||
if other_versions:
|
||||
version_str += f" (also: {', '.join(f'v{v}' for v in other_versions)})"
|
||||
print(f" • {agent_id} [{version_str}]")
|
||||
else:
|
||||
print(" No agents installed locally")
|
||||
print("-" * 50)
|
||||
|
||||
print("\nOnline Agents (Available to Install):")
|
||||
print("-" * 50)
|
||||
installable_agents = set(online_agents.keys()) - set(offline_agents.keys())
|
||||
if installable_agents:
|
||||
for agent_id in sorted(installable_agents):
|
||||
versions = online_agents[agent_id]
|
||||
latest_version = versions[-1] if versions else "unknown"
|
||||
other_versions = versions[:-1] if len(versions) > 1 else []
|
||||
version_str = f"v{latest_version}"
|
||||
if other_versions:
|
||||
version_str += f" (also: {', '.join(f'v{v}' for v in other_versions)})"
|
||||
print(f" • {agent_id} [{version_str}]")
|
||||
else:
|
||||
print(" No additional agents available to install")
|
||||
print("-" * 50)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user