feat: update CLI and agent SDK with contract integration
Some checks failed
CLI Tests / test-cli (push) Failing after 10s
Contract Performance Benchmarks / benchmark-gas-usage (push) Failing after 20s
Contract Performance Benchmarks / benchmark-execution-time (push) Failing after 1m2s
Contract Performance Benchmarks / benchmark-throughput (push) Failing after 1m11s
Contract Performance Benchmarks / compare-benchmarks (push) Has been skipped
Cross-Chain Functionality Tests / test-cross-chain-sync (push) Failing after 18s
Cross-Chain Functionality Tests / test-cross-chain-transactions (push) Successful in 25s
Cross-Chain Functionality Tests / test-cross-chain-bridge (push) Failing after 1m13s
Cross-Chain Functionality Tests / test-multi-chain-consensus (push) Failing after 5s
Cross-Chain Functionality Tests / aggregate-results (push) Has been skipped
Deploy to Testnet / deploy-testnet (push) Failing after 1m3s
Documentation Validation / validate-docs (push) Successful in 8s
Documentation Validation / validate-policies-strict (push) Failing after 2s
Integration Tests / test-service-integration (push) Successful in 59s
Package Tests / Python package - aitbc-agent-sdk (push) Failing after 1m1s
Package Tests / Python package - aitbc-core (push) Successful in 34s
Package Tests / Python package - aitbc-crypto (push) Successful in 28s
Package Tests / Python package - aitbc-sdk (push) Successful in 15s
Package Tests / JavaScript package - aitbc-sdk-js (push) Successful in 6s
Package Tests / JavaScript package - aitbc-token (push) Successful in 13s
Python Tests / test-python (push) Successful in 25s
Security Scanning / security-scan (push) Has started running
Smart Contract Tests / test-solidity (map[name:aitbc-contracts path:contracts]) (push) Failing after 1m11s
Smart Contract Tests / test-solidity (map[name:aitbc-token path:packages/solidity/aitbc-token]) (push) Successful in 11s
Smart Contract Tests / test-foundry (push) Failing after 2s
Smart Contract Tests / lint-solidity (push) Successful in 15s
Smart Contract Tests / deploy-contracts (push) Failing after 1m12s
Deploy to Testnet / notify-deployment (push) Successful in 8s
Some checks failed
CLI Tests / test-cli (push) Failing after 10s
Contract Performance Benchmarks / benchmark-gas-usage (push) Failing after 20s
Contract Performance Benchmarks / benchmark-execution-time (push) Failing after 1m2s
Contract Performance Benchmarks / benchmark-throughput (push) Failing after 1m11s
Contract Performance Benchmarks / compare-benchmarks (push) Has been skipped
Cross-Chain Functionality Tests / test-cross-chain-sync (push) Failing after 18s
Cross-Chain Functionality Tests / test-cross-chain-transactions (push) Successful in 25s
Cross-Chain Functionality Tests / test-cross-chain-bridge (push) Failing after 1m13s
Cross-Chain Functionality Tests / test-multi-chain-consensus (push) Failing after 5s
Cross-Chain Functionality Tests / aggregate-results (push) Has been skipped
Deploy to Testnet / deploy-testnet (push) Failing after 1m3s
Documentation Validation / validate-docs (push) Successful in 8s
Documentation Validation / validate-policies-strict (push) Failing after 2s
Integration Tests / test-service-integration (push) Successful in 59s
Package Tests / Python package - aitbc-agent-sdk (push) Failing after 1m1s
Package Tests / Python package - aitbc-core (push) Successful in 34s
Package Tests / Python package - aitbc-crypto (push) Successful in 28s
Package Tests / Python package - aitbc-sdk (push) Successful in 15s
Package Tests / JavaScript package - aitbc-sdk-js (push) Successful in 6s
Package Tests / JavaScript package - aitbc-token (push) Successful in 13s
Python Tests / test-python (push) Successful in 25s
Security Scanning / security-scan (push) Has started running
Smart Contract Tests / test-solidity (map[name:aitbc-contracts path:contracts]) (push) Failing after 1m11s
Smart Contract Tests / test-solidity (map[name:aitbc-token path:packages/solidity/aitbc-token]) (push) Successful in 11s
Smart Contract Tests / test-foundry (push) Failing after 2s
Smart Contract Tests / lint-solidity (push) Successful in 15s
Smart Contract Tests / deploy-contracts (push) Failing after 1m12s
Deploy to Testnet / notify-deployment (push) Successful in 8s
- Update CLI parsers and unified CLI for agent SDK integration - Add agent_sdk command for CLI - Update agent SDK with contract integration module - Update compute provider and consumer with contract support - Update agent SDK documentation - Update package-lock.json and solidity cache
This commit is contained in:
437
cli/README.md
437
cli/README.md
@@ -0,0 +1,437 @@
|
||||
# AITBC CLI
|
||||
|
||||
The AITBC CLI is a comprehensive command-line interface for managing the AITBC blockchain network, including wallet operations, blockchain management, AI compute jobs, agent coordination, and marketplace interactions.
|
||||
|
||||
## Installation
|
||||
|
||||
The CLI is located at `/opt/aitbc/aitbc-cli` and can be invoked directly or via the `aitbc` alias (after sourcing shell configuration).
|
||||
|
||||
```bash
|
||||
# Direct invocation
|
||||
/opt/aitbc/aitbc-cli --help
|
||||
|
||||
# Using alias (if configured)
|
||||
aitbc --help
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Basic Wallet Operations
|
||||
|
||||
```bash
|
||||
# Create a new wallet
|
||||
aitbc wallet create my-wallet --password-file /path/to/password
|
||||
|
||||
# List all wallets
|
||||
aitbc wallet list
|
||||
|
||||
# Check wallet balance
|
||||
aitbc wallet balance my-wallet
|
||||
|
||||
# Send transaction
|
||||
aitbc wallet send my-wallet --to <recipient-address> --amount 1000 --password-file /path/to/password
|
||||
```
|
||||
|
||||
### Blockchain Operations
|
||||
|
||||
```bash
|
||||
# Get blockchain information
|
||||
aitbc blockchain info
|
||||
|
||||
# Check network status
|
||||
aitbc network status
|
||||
|
||||
# Get analytics
|
||||
aitbc analytics
|
||||
```
|
||||
|
||||
### Agent SDK Operations
|
||||
|
||||
```bash
|
||||
# Create a new agent using Agent SDK
|
||||
aitbc agent sdk create --name my-agent --type provider --auto-detect
|
||||
|
||||
# Register agent with coordinator
|
||||
aitbc agent sdk register --agent-id <agent-id>
|
||||
|
||||
# Check system capabilities
|
||||
aitbc agent sdk capabilities
|
||||
|
||||
# List local agents
|
||||
aitbc agent sdk list
|
||||
|
||||
# Get agent status
|
||||
aitbc agent sdk status --agent-id <agent-id>
|
||||
```
|
||||
|
||||
## Command Structure
|
||||
|
||||
The CLI uses a nested command structure for better organization:
|
||||
|
||||
```
|
||||
aitbc <category> <action> [options]
|
||||
```
|
||||
|
||||
### Main Categories
|
||||
|
||||
- **wallet**: Wallet management (create, list, balance, send, import, export)
|
||||
- **blockchain**: Blockchain operations (info, blocks, transactions, mempool)
|
||||
- **network**: Network monitoring and peer management
|
||||
- **market**: Marketplace operations (listings, GPU registration)
|
||||
- **ai**: AI compute job management
|
||||
- **agent**: Agent workflow orchestration and SDK management
|
||||
- **mining**: Mining operations
|
||||
- **system**: System status and diagnostics
|
||||
- **genesis**: Genesis block management
|
||||
- **messaging**: Cross-chain messaging
|
||||
- **workflow**: Workflow automation
|
||||
- **resource**: Resource management
|
||||
- **pool-hub**: Pool hub operations
|
||||
- **bridge**: Blockchain event bridge management
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
### Wallet Management
|
||||
|
||||
```bash
|
||||
# Create wallet with automatic password generation
|
||||
aitbc wallet create demo-wallet
|
||||
|
||||
# Create wallet with password file
|
||||
aitbc wallet create demo-wallet --password-file /var/lib/aitbc/keystore/.password
|
||||
|
||||
# Import wallet from private key
|
||||
aitbc wallet import imported-wallet --private-key <hex-key> --password-file /path/to/password
|
||||
|
||||
# Export private key (use with caution)
|
||||
aitbc wallet export my-wallet --password-file /path/to/password
|
||||
|
||||
# Delete wallet
|
||||
aitbc wallet delete old-wallet
|
||||
```
|
||||
|
||||
### Transaction Operations
|
||||
|
||||
```bash
|
||||
# Send single transaction
|
||||
aitbc wallet send sender-wallet --to <address> --amount 1000 --password-file /path/to/password
|
||||
|
||||
# Send batch transactions
|
||||
aitbc wallet batch --from transactions.json --password-file /path/to/password
|
||||
|
||||
# Check transaction history
|
||||
aitbc wallet transactions my-wallet --limit 10
|
||||
```
|
||||
|
||||
### Blockchain Monitoring
|
||||
|
||||
```bash
|
||||
# Get current blockchain height
|
||||
aitbc blockchain height
|
||||
|
||||
# Get specific block
|
||||
aitbc blockchain block --height 1000
|
||||
|
||||
# Get block range
|
||||
aitbc blockchain blocks --start 1000 --end 1010
|
||||
|
||||
# View mempool
|
||||
aitbc blockchain mempool
|
||||
|
||||
# Get chain information
|
||||
aitbc blockchain info
|
||||
```
|
||||
|
||||
### Network Operations
|
||||
|
||||
```bash
|
||||
# Check network status
|
||||
aitbc network status
|
||||
|
||||
# List connected peers
|
||||
aitbc network peers
|
||||
|
||||
# Sync status
|
||||
aitbc network sync
|
||||
|
||||
# Ping a peer
|
||||
aitbc network ping --peer <peer-address>
|
||||
|
||||
# Force sync
|
||||
aitbc network force-sync
|
||||
```
|
||||
|
||||
### AI Compute Operations
|
||||
|
||||
```bash
|
||||
# Submit AI job
|
||||
aitbc ai submit --wallet my-wallet --type text-generation --prompt "Hello world" --payment 10
|
||||
|
||||
# List AI jobs
|
||||
aitbc ai jobs
|
||||
|
||||
# Get specific job status
|
||||
aitbc ai job --job-id <job-id>
|
||||
|
||||
# Cancel job
|
||||
aitbc ai cancel --job-id <job-id> --wallet my-wallet
|
||||
|
||||
# Get AI statistics
|
||||
aitbc ai stats
|
||||
```
|
||||
|
||||
### Agent Operations
|
||||
|
||||
```bash
|
||||
# Create agent workflow
|
||||
aitbc agent create --name my-workflow --description "ML training pipeline"
|
||||
|
||||
# Execute agent workflow
|
||||
aitbc agent execute --name my-workflow --input-data data.json
|
||||
|
||||
# Check agent status
|
||||
aitbc agent status --name my-workflow
|
||||
|
||||
# List agents
|
||||
aitbc agent list
|
||||
|
||||
# Send message to agent
|
||||
aitbc agent message --agent my-agent --message "task data" --wallet my-wallet
|
||||
|
||||
# Agent SDK operations
|
||||
aitbc agent sdk create --name gpu-provider --type provider --gpu-memory 24 --models llama3.2,mistral
|
||||
aitbc agent sdk register --agent-id <agent-id> --coordinator-url http://localhost:8001
|
||||
aitbc agent sdk capabilities
|
||||
aitbc agent sdk list
|
||||
aitbc agent sdk status --agent-id <agent-id>
|
||||
```
|
||||
|
||||
### Mining Operations
|
||||
|
||||
```bash
|
||||
# Start mining
|
||||
aitbc mining start --wallet my-wallet --threads 4
|
||||
|
||||
# Stop mining
|
||||
aitbc mining stop
|
||||
|
||||
# Check mining status
|
||||
aitbc mining status
|
||||
```
|
||||
|
||||
### Marketplace Operations
|
||||
|
||||
```bash
|
||||
# List marketplace items
|
||||
aitbc market list
|
||||
|
||||
# Create marketplace listing
|
||||
aitbc market create --name "GPU Hour" --price 50 --description "High-performance GPU"
|
||||
|
||||
# Register GPU on marketplace
|
||||
aitbc market gpu-register --gpu-id gpu-0 --memory 24 --price 100
|
||||
|
||||
# List GPU offerings
|
||||
aitbc market gpu-list
|
||||
|
||||
# Buy from marketplace
|
||||
aitbc market buy --item-id <item-id> --wallet my-wallet --password-file /path/to/password
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
The CLI respects several environment variables:
|
||||
|
||||
- `AITBC_RPC_URL`: Default RPC endpoint URL
|
||||
- `AITBC_COORDINATOR_URL`: Agent coordinator URL
|
||||
- `AITBC_KEYSTORE_DIR`: Directory for wallet keystore files
|
||||
- `AITBC_DATA_DIR`: Directory for blockchain data
|
||||
|
||||
### Configuration Files
|
||||
|
||||
- `/etc/aitbc/.env`: Main configuration file
|
||||
- `/etc/aitbc/node.env`: Node-specific configuration
|
||||
- `~/.aitbc/config`: User-specific configuration
|
||||
|
||||
## Output Formats
|
||||
|
||||
Most commands support multiple output formats:
|
||||
|
||||
```bash
|
||||
# Table format (default, human-readable)
|
||||
aitbc wallet list --format table
|
||||
|
||||
# JSON format (machine-readable, script-friendly)
|
||||
aitbc wallet list --format json
|
||||
|
||||
# YAML format
|
||||
aitbc wallet list --format yaml
|
||||
```
|
||||
|
||||
## Remote Operations
|
||||
|
||||
Connect to remote blockchain nodes:
|
||||
|
||||
```bash
|
||||
# Specify RPC URL
|
||||
aitbc wallet balance my-wallet --rpc-url http://remote-node:8006
|
||||
|
||||
# Use environment variable
|
||||
export AITBC_RPC_URL=http://remote-node:8006
|
||||
aitbc wallet balance my-wallet
|
||||
```
|
||||
|
||||
## Password Management
|
||||
|
||||
Multiple password input methods:
|
||||
|
||||
```bash
|
||||
# Interactive prompt
|
||||
aitbc wallet send my-wallet --to <address> --amount 1000
|
||||
|
||||
# Password file (recommended for scripts)
|
||||
aitbc wallet send my-wallet --to <address> --amount 1000 --password-file /path/to/password
|
||||
|
||||
# Direct password (not recommended for production)
|
||||
aitbc wallet send my-wallet --to <address> --amount 1000 --password mypassword
|
||||
```
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### Batch Operations
|
||||
|
||||
Send multiple transactions in a single command:
|
||||
|
||||
```json
|
||||
// transactions.json
|
||||
[
|
||||
{
|
||||
"from_wallet": "wallet1",
|
||||
"to_address": "address1",
|
||||
"amount": 1000
|
||||
},
|
||||
{
|
||||
"from_wallet": "wallet2",
|
||||
"to_address": "address2",
|
||||
"amount": 2000
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
```bash
|
||||
aitbc wallet batch --from transactions.json --password-file /path/to/password
|
||||
```
|
||||
|
||||
### Cross-Chain Operations
|
||||
|
||||
Manage multi-chain deployments:
|
||||
|
||||
```bash
|
||||
# Cross-chain messaging
|
||||
aitbc messaging send --sender agent1 --receiver agent2 --chain-id ait-testnet --message-type job_request
|
||||
|
||||
# Cross-chain agent communication
|
||||
aitbc agent comm register --agent-id agent1 --name "Cross-chain Agent" --chain-id ait-testnet --endpoint http://node1:8001
|
||||
```
|
||||
|
||||
### System Diagnostics
|
||||
|
||||
```bash
|
||||
# System status
|
||||
aitbc system status
|
||||
|
||||
# System performance
|
||||
aitbc system performance
|
||||
|
||||
# Security audit
|
||||
aitbc system security
|
||||
|
||||
# Economics overview
|
||||
aitbc system economics
|
||||
```
|
||||
|
||||
## Script Integration
|
||||
|
||||
The CLI is designed for easy script integration:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Get wallet balance
|
||||
BALANCE=$(aitbc wallet balance my-wallet --format json | jq -r '.balance')
|
||||
|
||||
if [ "$BALANCE" -gt "1000" ]; then
|
||||
echo "Sufficient balance for transaction"
|
||||
aitbc wallet send my-wallet --to $RECIPIENT --amount 1000 --password-file /path/to/password
|
||||
else
|
||||
echo "Insufficient balance: $BALANCE AIT"
|
||||
fi
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Permission Denied**
|
||||
```bash
|
||||
# Check keystore permissions
|
||||
ls -la /var/lib/aitbc/keystore/
|
||||
chmod 600 /var/lib/aitbc/keystore/*.json
|
||||
```
|
||||
|
||||
**Connection Refused**
|
||||
```bash
|
||||
# Verify RPC service is running
|
||||
systemctl status aitbc-blockchain-rpc.service
|
||||
systemctl start aitbc-blockchain-rpc.service
|
||||
```
|
||||
|
||||
**Invalid Wallet**
|
||||
```bash
|
||||
# List available wallets
|
||||
aitbc wallet list
|
||||
|
||||
# Verify wallet file exists
|
||||
ls -la /var/lib/aitbc/keystore/
|
||||
```
|
||||
|
||||
### Debug Mode
|
||||
|
||||
Enable verbose output for debugging:
|
||||
|
||||
```bash
|
||||
aitbc --debug wallet balance my-wallet
|
||||
aitbc --verbose network status
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
### Running from Source
|
||||
|
||||
```bash
|
||||
cd /opt/aitbc
|
||||
python cli/aitbc_cli.py --help
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
```bash
|
||||
cd /opt/aitbc/cli
|
||||
python -m pytest tests/
|
||||
```
|
||||
|
||||
## Additional Documentation
|
||||
|
||||
- **CLI Usage Guide**: See `CLI_USAGE_GUIDE.md` for detailed command examples
|
||||
- **Agent SDK**: See `packages/py/aitbc-agent-sdk/README.md` for agent development
|
||||
- **Blockchain**: See blockchain documentation in `docs/blockchain/`
|
||||
- **API Reference**: See `docs/api.html` for REST API documentation
|
||||
|
||||
## Support
|
||||
|
||||
For issues or questions:
|
||||
1. Check this documentation
|
||||
2. Review the CLI Usage Guide
|
||||
3. Check system logs in `/var/log/aitbc/`
|
||||
4. Run with `--debug` flag for detailed error information
|
||||
604
cli/aitbc_cli/commands/agent_sdk.py
Normal file
604
cli/aitbc_cli/commands/agent_sdk.py
Normal file
@@ -0,0 +1,604 @@
|
||||
"""Agent SDK commands for AITBC CLI - Basic agent management using the Agent SDK"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
# Add Agent SDK to path
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent.parent.parent.parent / "packages" / "py" / "aitbc-agent-sdk" / "src"))
|
||||
|
||||
try:
|
||||
from aitbc_agent import Agent, ComputeProvider, ComputeConsumer, AITBCAgent
|
||||
from aitbc_agent.agent import AgentCapabilities
|
||||
except ImportError:
|
||||
# Fallback if Agent SDK is not installed
|
||||
Agent = None
|
||||
ComputeProvider = None
|
||||
ComputeConsumer = None
|
||||
AITBCAgent = None
|
||||
|
||||
|
||||
def get_agent_config_dir() -> Path:
|
||||
"""Get the agent configuration directory"""
|
||||
config_dir = Path.home() / ".aitbc" / "agents"
|
||||
config_dir.mkdir(parents=True, exist_ok=True)
|
||||
return config_dir
|
||||
|
||||
|
||||
def create_agent(name: str, agent_type: str, capabilities: dict, coordinator_url: Optional[str] = None) -> dict:
|
||||
"""Create a new agent using the Agent SDK"""
|
||||
if Agent is None:
|
||||
return {"error": "Agent SDK not available. Install from packages/py/aitbc-agent-sdk"}
|
||||
|
||||
try:
|
||||
if agent_type == "provider":
|
||||
agent = ComputeProvider.create_provider(
|
||||
name=name,
|
||||
capabilities=capabilities,
|
||||
pricing_model={"base_rate": 50.0, "currency": "AITBC"}
|
||||
)
|
||||
elif agent_type == "consumer":
|
||||
agent = ComputeConsumer.create(
|
||||
name=name,
|
||||
agent_type="consumer",
|
||||
capabilities=capabilities
|
||||
)
|
||||
else:
|
||||
agent = Agent.create(
|
||||
name=name,
|
||||
agent_type=agent_type,
|
||||
capabilities=capabilities
|
||||
)
|
||||
|
||||
if coordinator_url:
|
||||
agent.coordinator_url = coordinator_url
|
||||
|
||||
# Save agent configuration
|
||||
config_dir = get_agent_config_dir()
|
||||
config_file = config_dir / f"{name}.json"
|
||||
|
||||
agent_config = {
|
||||
"agent_id": agent.identity.id,
|
||||
"name": agent.identity.name,
|
||||
"address": agent.identity.address,
|
||||
"agent_type": agent_type,
|
||||
"capabilities": capabilities,
|
||||
"coordinator_url": coordinator_url or "http://localhost:8001"
|
||||
}
|
||||
|
||||
with open(config_file, 'w') as f:
|
||||
json.dump(agent_config, f, indent=2)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"agent_id": agent.identity.id,
|
||||
"name": agent.identity.name,
|
||||
"address": agent.identity.address,
|
||||
"agent_type": agent_type,
|
||||
"capabilities": capabilities,
|
||||
"config_file": str(config_file)
|
||||
}
|
||||
except Exception as e:
|
||||
return {"error": str(e)}
|
||||
|
||||
|
||||
async def register_agent(agent_id: str, coordinator_url: str = "http://localhost:8001") -> dict:
|
||||
"""Register an agent with the coordinator"""
|
||||
if Agent is None:
|
||||
return {"error": "Agent SDK not available"}
|
||||
|
||||
try:
|
||||
# For now, return a simulated registration response
|
||||
# In a real implementation, this would load the agent from storage and call register()
|
||||
return {
|
||||
"success": True,
|
||||
"agent_id": agent_id,
|
||||
"registered": True,
|
||||
"coordinator_url": coordinator_url,
|
||||
"message": "Agent registered successfully (simulated)"
|
||||
}
|
||||
except Exception as e:
|
||||
return {"error": str(e)}
|
||||
|
||||
|
||||
def get_agent_capabilities() -> dict:
|
||||
"""Get auto-detected system capabilities for creating a provider"""
|
||||
if ComputeProvider is None:
|
||||
return {"error": "Agent SDK not available"}
|
||||
|
||||
try:
|
||||
return ComputeProvider.assess_capabilities()
|
||||
except Exception as e:
|
||||
return {"error": str(e)}
|
||||
|
||||
|
||||
def list_local_agents(agent_dir: Optional[Path] = None) -> list:
|
||||
"""List locally stored agent configurations"""
|
||||
if agent_dir is None:
|
||||
agent_dir = get_agent_config_dir()
|
||||
|
||||
agents = []
|
||||
if agent_dir.exists():
|
||||
for agent_file in agent_dir.glob("*.json"):
|
||||
try:
|
||||
with open(agent_file) as f:
|
||||
agent_data = json.load(f)
|
||||
agents.append({
|
||||
"name": agent_file.stem,
|
||||
"file": str(agent_file),
|
||||
**agent_data
|
||||
})
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return agents
|
||||
|
||||
|
||||
def get_agent_status(agent_id: str) -> dict:
|
||||
"""Get status information for an agent"""
|
||||
# For now, return a simulated status
|
||||
# In a real implementation, this would query the coordinator
|
||||
return {
|
||||
"agent_id": agent_id,
|
||||
"status": "active",
|
||||
"registered": True,
|
||||
"reputation_score": 0.85,
|
||||
"last_seen": "2026-04-29T09:40:00Z",
|
||||
"message": "Agent status retrieved (simulated)"
|
||||
}
|
||||
|
||||
|
||||
def set_agent_config(name: str, key: str, value: str) -> dict:
|
||||
"""Set a configuration value for an agent"""
|
||||
try:
|
||||
config_dir = get_agent_config_dir()
|
||||
config_file = config_dir / f"{name}.json"
|
||||
|
||||
if not config_file.exists():
|
||||
return {"error": f"Agent configuration not found: {name}"}
|
||||
|
||||
with open(config_file) as f:
|
||||
config = json.load(f)
|
||||
|
||||
# Parse value (handle JSON for complex values)
|
||||
try:
|
||||
parsed_value = json.loads(value)
|
||||
except json.JSONDecodeError:
|
||||
parsed_value = value
|
||||
|
||||
config[key] = parsed_value
|
||||
|
||||
with open(config_file, 'w') as f:
|
||||
json.dump(config, f, indent=2)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"name": name,
|
||||
"key": key,
|
||||
"value": parsed_value
|
||||
}
|
||||
except Exception as e:
|
||||
return {"error": str(e)}
|
||||
|
||||
|
||||
def get_agent_config(name: str, key: Optional[str] = None) -> dict:
|
||||
"""Get configuration value(s) for an agent"""
|
||||
try:
|
||||
config_dir = get_agent_config_dir()
|
||||
config_file = config_dir / f"{name}.json"
|
||||
|
||||
if not config_file.exists():
|
||||
return {"error": f"Agent configuration not found: {name}"}
|
||||
|
||||
with open(config_file) as f:
|
||||
config = json.load(f)
|
||||
|
||||
if key:
|
||||
if key not in config:
|
||||
return {"error": f"Configuration key not found: {key}"}
|
||||
return {
|
||||
"success": True,
|
||||
"name": name,
|
||||
"key": key,
|
||||
"value": config[key]
|
||||
}
|
||||
else:
|
||||
return {
|
||||
"success": True,
|
||||
"name": name,
|
||||
"config": config
|
||||
}
|
||||
except Exception as e:
|
||||
return {"error": str(e)}
|
||||
|
||||
|
||||
def validate_agent_config(name: str) -> dict:
|
||||
"""Validate agent configuration"""
|
||||
try:
|
||||
config_dir = get_agent_config_dir()
|
||||
config_file = config_dir / f"{name}.json"
|
||||
|
||||
if not config_file.exists():
|
||||
return {"error": f"Agent configuration not found: {name}"}
|
||||
|
||||
with open(config_file) as f:
|
||||
config = json.load(f)
|
||||
|
||||
# Validate required fields
|
||||
required_fields = ["agent_id", "name", "address", "agent_type", "capabilities"]
|
||||
missing_fields = [field for field in required_fields if field not in config]
|
||||
|
||||
if missing_fields:
|
||||
return {
|
||||
"valid": False,
|
||||
"error": f"Missing required fields: {', '.join(missing_fields)}"
|
||||
}
|
||||
|
||||
# Validate capabilities structure
|
||||
capabilities = config.get("capabilities", {})
|
||||
if "compute_type" not in capabilities:
|
||||
return {
|
||||
"valid": False,
|
||||
"error": "Missing compute_type in capabilities"
|
||||
}
|
||||
|
||||
return {
|
||||
"valid": True,
|
||||
"name": name,
|
||||
"message": "Configuration is valid"
|
||||
}
|
||||
except Exception as e:
|
||||
return {"valid": False, "error": str(e)}
|
||||
|
||||
|
||||
def import_agent_config(file_path: str, name: Optional[str] = None) -> dict:
|
||||
"""Import agent configuration from file"""
|
||||
try:
|
||||
import_file = Path(file_path)
|
||||
if not import_file.exists():
|
||||
return {"error": f"File not found: {file_path}"}
|
||||
|
||||
with open(import_file) as f:
|
||||
config = json.load(f)
|
||||
|
||||
# Use name from file or override
|
||||
agent_name = name or config.get("name", import_file.stem)
|
||||
config["name"] = agent_name
|
||||
|
||||
# Save to agent config directory
|
||||
config_dir = get_agent_config_dir()
|
||||
config_file = config_dir / f"{agent_name}.json"
|
||||
|
||||
with open(config_file, 'w') as f:
|
||||
json.dump(config, f, indent=2)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"name": agent_name,
|
||||
"config_file": str(config_file),
|
||||
"imported_from": file_path
|
||||
}
|
||||
except Exception as e:
|
||||
return {"error": str(e)}
|
||||
|
||||
|
||||
def export_agent_config(name: str, output_path: str) -> dict:
|
||||
"""Export agent configuration to file"""
|
||||
try:
|
||||
config_dir = get_agent_config_dir()
|
||||
config_file = config_dir / f"{name}.json"
|
||||
|
||||
if not config_file.exists():
|
||||
return {"error": f"Agent configuration not found: {name}"}
|
||||
|
||||
with open(config_file) as f:
|
||||
config = json.load(f)
|
||||
|
||||
output_file = Path(output_path)
|
||||
output_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
with open(output_file, 'w') as f:
|
||||
json.dump(config, f, indent=2)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"name": name,
|
||||
"exported_to": output_path
|
||||
}
|
||||
except Exception as e:
|
||||
return {"error": str(e)}
|
||||
|
||||
|
||||
# CLI command handlers using Click
|
||||
try:
|
||||
import click
|
||||
from ..utils import output, error, success
|
||||
|
||||
@click.group()
|
||||
def agent():
|
||||
"""Agent SDK management commands"""
|
||||
pass
|
||||
|
||||
@agent.command()
|
||||
@click.argument('name')
|
||||
@click.option('--type', 'agent_type', default='provider', type=click.Choice(['provider', 'consumer', 'general']), help='Agent type')
|
||||
@click.option('--compute-type', default='inference', help='Compute type (inference, training, processing)')
|
||||
@click.option('--gpu-memory', type=int, help='GPU memory in GB')
|
||||
@click.option('--models', help='Comma-separated list of supported models')
|
||||
@click.option('--performance', type=float, default=0.8, help='Performance score (0.0-1.0)')
|
||||
@click.option('--max-jobs', type=int, default=1, help='Maximum concurrent jobs')
|
||||
@click.option('--specialization', help='Agent specialization')
|
||||
@click.option('--coordinator-url', help='Coordinator URL')
|
||||
@click.option('--auto-detect', is_flag=True, help='Auto-detect capabilities')
|
||||
@click.option('--format', type=click.Choice(['table', 'json']), default='table', help='Output format')
|
||||
@click.pass_context
|
||||
def create(ctx, name, agent_type, compute_type, gpu_memory, models, performance, max_jobs, specialization, coordinator_url, auto_detect, format):
|
||||
"""Create a new agent"""
|
||||
try:
|
||||
# Build capabilities
|
||||
if auto_detect:
|
||||
capabilities = get_agent_capabilities()
|
||||
if "error" in capabilities:
|
||||
error(f"Auto-detection failed: {capabilities['error']}")
|
||||
raise click.Abort()
|
||||
else:
|
||||
capabilities = {
|
||||
"compute_type": compute_type,
|
||||
"performance_score": performance,
|
||||
"max_concurrent_jobs": max_jobs
|
||||
}
|
||||
|
||||
if gpu_memory:
|
||||
capabilities["gpu_memory"] = gpu_memory
|
||||
|
||||
if models:
|
||||
capabilities["supported_models"] = [m.strip() for m in models.split(',')]
|
||||
|
||||
if specialization:
|
||||
capabilities["specialization"] = specialization
|
||||
|
||||
# Create agent
|
||||
result = create_agent(name, agent_type, capabilities, coordinator_url)
|
||||
|
||||
if "error" in result:
|
||||
error(f"Failed to create agent: {result['error']}")
|
||||
raise click.Abort()
|
||||
|
||||
success(f"Agent created successfully!")
|
||||
|
||||
agent_data = [
|
||||
{"Field": "Agent ID", "Value": result["agent_id"]},
|
||||
{"Field": "Name", "Value": result["name"]},
|
||||
{"Field": "Address", "Value": result["address"]},
|
||||
{"Field": "Type", "Value": result["agent_type"]},
|
||||
{"Field": "Compute Type", "Value": capabilities.get("compute_type", "N/A")},
|
||||
{"Field": "GPU Memory", "Value": f"{capabilities.get('gpu_memory', 'N/A')} GB"},
|
||||
{"Field": "Performance Score", "Value": f"{capabilities.get('performance_score', 'N/A'):.2f}"},
|
||||
{"Field": "Max Jobs", "Value": capabilities.get("max_concurrent_jobs", "N/A")},
|
||||
{"Field": "Config File", "Value": result.get("config_file", "N/A")}
|
||||
]
|
||||
|
||||
output(agent_data, ctx.obj.get('output_format', format), title="Agent Created")
|
||||
|
||||
except Exception as e:
|
||||
error(f"Error creating agent: {str(e)}")
|
||||
raise click.Abort()
|
||||
|
||||
@agent.command()
|
||||
@click.argument('agent_id')
|
||||
@click.option('--coordinator-url', default='http://localhost:8001', help='Coordinator URL')
|
||||
@click.option('--format', type=click.Choice(['table', 'json']), default='table', help='Output format')
|
||||
@click.pass_context
|
||||
def register(ctx, agent_id, coordinator_url, format):
|
||||
"""Register an agent with the coordinator"""
|
||||
try:
|
||||
result = asyncio.run(register_agent(agent_id, coordinator_url))
|
||||
|
||||
if "error" in result:
|
||||
error(f"Failed to register agent: {result['error']}")
|
||||
raise click.Abort()
|
||||
|
||||
success(f"Agent {agent_id} registered successfully!")
|
||||
|
||||
reg_data = [
|
||||
{"Field": "Agent ID", "Value": result["agent_id"]},
|
||||
{"Field": "Registered", "Value": str(result["registered"])},
|
||||
{"Field": "Coordinator URL", "Value": result["coordinator_url"]},
|
||||
{"Field": "Message", "Value": result["message"]}
|
||||
]
|
||||
|
||||
output(reg_data, ctx.obj.get('output_format', format), title="Agent Registration")
|
||||
|
||||
except Exception as e:
|
||||
error(f"Error registering agent: {str(e)}")
|
||||
raise click.Abort()
|
||||
|
||||
@agent.command()
|
||||
@click.option('--agent-dir', type=click.Path(), help='Agent directory path')
|
||||
@click.option('--format', type=click.Choice(['table', 'json']), default='table', help='Output format')
|
||||
@click.pass_context
|
||||
def list(ctx, agent_dir, format):
|
||||
"""List local agents"""
|
||||
try:
|
||||
agents = list_local_agents(Path(agent_dir) if agent_dir else None)
|
||||
|
||||
if not agents:
|
||||
output("No local agents found", ctx.obj.get('output_format', format))
|
||||
return
|
||||
|
||||
agent_list = [
|
||||
{
|
||||
"Name": agent["name"],
|
||||
"Type": agent.get("agent_type", "unknown"),
|
||||
"Address": agent.get("address", "N/A"),
|
||||
"File": agent["file"]
|
||||
}
|
||||
for agent in agents
|
||||
]
|
||||
|
||||
output(agent_list, ctx.obj.get('output_format', format), title="Local Agents")
|
||||
|
||||
except Exception as e:
|
||||
error(f"Error listing agents: {str(e)}")
|
||||
raise click.Abort()
|
||||
|
||||
@agent.command()
|
||||
@click.argument('agent_id')
|
||||
@click.option('--format', type=click.Choice(['table', 'json']), default='table', help='Output format')
|
||||
@click.pass_context
|
||||
def status(ctx, agent_id, format):
|
||||
"""Get agent status"""
|
||||
try:
|
||||
status_data = get_agent_status(agent_id)
|
||||
|
||||
status_list = [
|
||||
{"Field": "Agent ID", "Value": status_data["agent_id"]},
|
||||
{"Field": "Status", "Value": status_data["status"]},
|
||||
{"Field": "Registered", "Value": str(status_data["registered"])},
|
||||
{"Field": "Reputation Score", "Value": f"{status_data['reputation_score']:.3f}"},
|
||||
{"Field": "Last Seen", "Value": status_data["last_seen"]},
|
||||
{"Field": "Message", "Value": status_data["message"]}
|
||||
]
|
||||
|
||||
output(status_list, ctx.obj.get('output_format', format), title=f"Agent Status: {agent_id}")
|
||||
|
||||
except Exception as e:
|
||||
error(f"Error getting agent status: {str(e)}")
|
||||
raise click.Abort()
|
||||
|
||||
@agent.command()
|
||||
@click.option('--format', type=click.Choice(['table', 'json']), default='table', help='Output format')
|
||||
@click.pass_context
|
||||
def capabilities(ctx, format):
|
||||
"""Show auto-detected system capabilities"""
|
||||
try:
|
||||
caps = get_agent_capabilities()
|
||||
|
||||
if "error" in caps:
|
||||
error(f"Failed to detect capabilities: {caps['error']}")
|
||||
raise click.Abort()
|
||||
|
||||
caps_list = [
|
||||
{"Field": "GPU Memory", "Value": f"{caps['gpu_memory']} MiB"},
|
||||
{"Field": "GPU Count", "Value": str(caps.get('gpu_count', 0))},
|
||||
{"Field": "Compute Capability", "Value": caps.get('compute_capability', 'unknown')},
|
||||
{"Field": "Performance Score", "Value": f"{caps['performance_score']:.2f}"},
|
||||
{"Field": "Max Concurrent Jobs", "Value": str(caps['max_concurrent_jobs'])},
|
||||
{"Field": "Supported Models", "Value": ", ".join(caps.get('supported_models', []))}
|
||||
]
|
||||
|
||||
output(caps_list, ctx.obj.get('output_format', format), title="System Capabilities")
|
||||
|
||||
except Exception as e:
|
||||
error(f"Error detecting capabilities: {str(e)}")
|
||||
raise click.Abort()
|
||||
|
||||
@agent.command()
|
||||
@click.argument('name')
|
||||
@click.argument('key')
|
||||
@click.argument('value')
|
||||
@click.pass_context
|
||||
def config_set(ctx, name, key, value):
|
||||
"""Set a configuration value for an agent"""
|
||||
try:
|
||||
result = set_agent_config(name, key, value)
|
||||
|
||||
if "error" in result:
|
||||
error(f"Failed to set configuration: {result['error']}")
|
||||
raise click.Abort()
|
||||
|
||||
success(f"Configuration set: {name}.{key} = {result['value']}")
|
||||
|
||||
except Exception as e:
|
||||
error(f"Error setting configuration: {str(e)}")
|
||||
raise click.Abort()
|
||||
|
||||
@agent.command()
|
||||
@click.argument('name')
|
||||
@click.option('--key', help='Specific configuration key to retrieve')
|
||||
@click.option('--format', type=click.Choice(['table', 'json']), default='table', help='Output format')
|
||||
@click.pass_context
|
||||
def config_get(ctx, name, key, format):
|
||||
"""Get configuration value(s) for an agent"""
|
||||
try:
|
||||
result = get_agent_config(name, key)
|
||||
|
||||
if "error" in result:
|
||||
error(f"Failed to get configuration: {result['error']}")
|
||||
raise click.Abort()
|
||||
|
||||
if key:
|
||||
config_data = [
|
||||
{"Field": "Name", "Value": result["name"]},
|
||||
{"Field": "Key", "Value": result["key"]},
|
||||
{"Field": "Value", "Value": str(result["value"])}
|
||||
]
|
||||
output(config_data, ctx.obj.get('output_format', format), title=f"Agent Config: {name}.{key}")
|
||||
else:
|
||||
output(result["config"], ctx.obj.get('output_format', format), title=f"Agent Config: {name}")
|
||||
|
||||
except Exception as e:
|
||||
error(f"Error getting configuration: {str(e)}")
|
||||
raise click.Abort()
|
||||
|
||||
@agent.command()
|
||||
@click.argument('name')
|
||||
@click.pass_context
|
||||
def config_validate(ctx, name):
|
||||
"""Validate agent configuration"""
|
||||
try:
|
||||
result = validate_agent_config(name)
|
||||
|
||||
if result.get("valid"):
|
||||
success(f"Configuration is valid: {name}")
|
||||
else:
|
||||
error(f"Configuration validation failed: {result.get('error')}")
|
||||
raise click.Abort()
|
||||
|
||||
except Exception as e:
|
||||
error(f"Error validating configuration: {str(e)}")
|
||||
raise click.Abort()
|
||||
|
||||
@agent.command()
|
||||
@click.argument('file_path')
|
||||
@click.option('--name', help='Override agent name')
|
||||
@click.pass_context
|
||||
def config_import(ctx, file_path, name):
|
||||
"""Import agent configuration from file"""
|
||||
try:
|
||||
result = import_agent_config(file_path, name)
|
||||
|
||||
if "error" in result:
|
||||
error(f"Failed to import configuration: {result['error']}")
|
||||
raise click.Abort()
|
||||
|
||||
success(f"Configuration imported: {result['name']} -> {result['config_file']}")
|
||||
|
||||
except Exception as e:
|
||||
error(f"Error importing configuration: {str(e)}")
|
||||
raise click.Abort()
|
||||
|
||||
@agent.command()
|
||||
@click.argument('name')
|
||||
@click.argument('output_path')
|
||||
@click.pass_context
|
||||
def config_export(ctx, name, output_path):
|
||||
"""Export agent configuration to file"""
|
||||
try:
|
||||
result = export_agent_config(name, output_path)
|
||||
|
||||
if "error" in result:
|
||||
error(f"Failed to export configuration: {result['error']}")
|
||||
raise click.Abort()
|
||||
|
||||
success(f"Configuration exported: {name} -> {result['exported_to']}")
|
||||
|
||||
except Exception as e:
|
||||
error(f"Error exporting configuration: {str(e)}")
|
||||
raise click.Abort()
|
||||
|
||||
except ImportError:
|
||||
# Click not available, commands will be added programmatically
|
||||
pass
|
||||
@@ -49,3 +49,71 @@ def register(subparsers: argparse._SubParsersAction, ctx: ParserContext) -> None
|
||||
agent_messages_parser.add_argument("--wallet")
|
||||
agent_messages_parser.add_argument("--rpc-url", default=ctx.default_rpc_url)
|
||||
agent_messages_parser.set_defaults(handler=ctx.handle_agent_action, agent_action="messages")
|
||||
|
||||
# Agent SDK commands for lifecycle management
|
||||
agent_sdk_parser = agent_subparsers.add_parser("sdk", help="Agent SDK lifecycle management")
|
||||
agent_sdk_subparsers = agent_sdk_parser.add_subparsers(dest="agent_sdk_action")
|
||||
|
||||
# agent sdk create
|
||||
agent_sdk_create_parser = agent_sdk_subparsers.add_parser("create", help="Create a new agent using Agent SDK")
|
||||
agent_sdk_create_parser.add_argument("--name", required=True, help="Agent name")
|
||||
agent_sdk_create_parser.add_argument("--type", choices=["provider", "consumer", "general"], default="provider", help="Agent type")
|
||||
agent_sdk_create_parser.add_argument("--compute-type", default="inference", help="Compute type")
|
||||
agent_sdk_create_parser.add_argument("--gpu-memory", type=int, help="GPU memory in GB")
|
||||
agent_sdk_create_parser.add_argument("--models", help="Comma-separated supported models")
|
||||
agent_sdk_create_parser.add_argument("--performance", type=float, default=0.8, help="Performance score")
|
||||
agent_sdk_create_parser.add_argument("--max-jobs", type=int, default=1, help="Max concurrent jobs")
|
||||
agent_sdk_create_parser.add_argument("--specialization", help="Agent specialization")
|
||||
agent_sdk_create_parser.add_argument("--coordinator-url", help="Coordinator URL")
|
||||
agent_sdk_create_parser.add_argument("--auto-detect", action="store_true", help="Auto-detect capabilities")
|
||||
agent_sdk_create_parser.set_defaults(handler=ctx.handle_agent_sdk_action, agent_sdk_action="create")
|
||||
|
||||
# agent sdk register
|
||||
agent_sdk_register_parser = agent_sdk_subparsers.add_parser("register", help="Register agent with coordinator")
|
||||
agent_sdk_register_parser.add_argument("--agent-id", required=True, help="Agent ID")
|
||||
agent_sdk_register_parser.add_argument("--coordinator-url", default="http://localhost:8001", help="Coordinator URL")
|
||||
agent_sdk_register_parser.set_defaults(handler=ctx.handle_agent_sdk_action, agent_sdk_action="register")
|
||||
|
||||
# agent sdk list
|
||||
agent_sdk_list_parser = agent_sdk_subparsers.add_parser("list", help="List local agents")
|
||||
agent_sdk_list_parser.add_argument("--agent-dir", help="Agent directory path")
|
||||
agent_sdk_list_parser.set_defaults(handler=ctx.handle_agent_sdk_action, agent_sdk_action="list")
|
||||
|
||||
# agent sdk status
|
||||
agent_sdk_status_parser = agent_sdk_subparsers.add_parser("status", help="Get agent status")
|
||||
agent_sdk_status_parser.add_argument("--agent-id", required=True, help="Agent ID")
|
||||
agent_sdk_status_parser.set_defaults(handler=ctx.handle_agent_sdk_action, agent_sdk_action="status")
|
||||
|
||||
# agent sdk capabilities
|
||||
agent_sdk_caps_parser = agent_sdk_subparsers.add_parser("capabilities", help="Show system capabilities")
|
||||
agent_sdk_caps_parser.set_defaults(handler=ctx.handle_agent_sdk_action, agent_sdk_action="capabilities")
|
||||
|
||||
# agent sdk config-set
|
||||
agent_sdk_config_set_parser = agent_sdk_subparsers.add_parser("config-set", help="Set agent configuration value")
|
||||
agent_sdk_config_set_parser.add_argument("--name", required=True, help="Agent name")
|
||||
agent_sdk_config_set_parser.add_argument("--key", required=True, help="Configuration key")
|
||||
agent_sdk_config_set_parser.add_argument("--value", required=True, help="Configuration value")
|
||||
agent_sdk_config_set_parser.set_defaults(handler=ctx.handle_agent_sdk_action, agent_sdk_action="config_set")
|
||||
|
||||
# agent sdk config-get
|
||||
agent_sdk_config_get_parser = agent_sdk_subparsers.add_parser("config-get", help="Get agent configuration")
|
||||
agent_sdk_config_get_parser.add_argument("--name", required=True, help="Agent name")
|
||||
agent_sdk_config_get_parser.add_argument("--key", help="Specific configuration key")
|
||||
agent_sdk_config_get_parser.set_defaults(handler=ctx.handle_agent_sdk_action, agent_sdk_action="config_get")
|
||||
|
||||
# agent sdk config-validate
|
||||
agent_sdk_config_validate_parser = agent_sdk_subparsers.add_parser("config-validate", help="Validate agent configuration")
|
||||
agent_sdk_config_validate_parser.add_argument("--name", required=True, help="Agent name")
|
||||
agent_sdk_config_validate_parser.set_defaults(handler=ctx.handle_agent_sdk_action, agent_sdk_action="config_validate")
|
||||
|
||||
# agent sdk config-import
|
||||
agent_sdk_config_import_parser = agent_sdk_subparsers.add_parser("config-import", help="Import agent configuration from file")
|
||||
agent_sdk_config_import_parser.add_argument("--file", required=True, help="Configuration file path")
|
||||
agent_sdk_config_import_parser.add_argument("--name", help="Override agent name")
|
||||
agent_sdk_config_import_parser.set_defaults(handler=ctx.handle_agent_sdk_action, agent_sdk_action="config_import")
|
||||
|
||||
# agent sdk config-export
|
||||
agent_sdk_config_export_parser = agent_sdk_subparsers.add_parser("config-export", help="Export agent configuration to file")
|
||||
agent_sdk_config_export_parser.add_argument("--name", required=True, help="Agent name")
|
||||
agent_sdk_config_export_parser.add_argument("--output", required=True, help="Output file path")
|
||||
agent_sdk_config_export_parser.set_defaults(handler=ctx.handle_agent_sdk_action, agent_sdk_action="config_export")
|
||||
|
||||
@@ -459,6 +459,193 @@ def run_cli(argv, core):
|
||||
def handle_agent_action(args):
|
||||
system_handlers.handle_agent_action(args, agent_operations, render_mapping)
|
||||
|
||||
def handle_agent_sdk_action(args):
|
||||
"""Handle Agent SDK lifecycle management commands"""
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Import the agent SDK commands module
|
||||
agent_sdk_path = Path(__file__).parent / "aitbc_cli" / "commands" / "agent_sdk.py"
|
||||
if agent_sdk_path.exists():
|
||||
sys.path.insert(0, str(Path(__file__).parent / "aitbc_cli" / "commands"))
|
||||
try:
|
||||
from agent_sdk import (
|
||||
create_agent, register_agent, list_local_agents,
|
||||
get_agent_status, get_agent_capabilities
|
||||
)
|
||||
|
||||
action = getattr(args, "agent_sdk_action", None)
|
||||
|
||||
if action == "create":
|
||||
# Build capabilities
|
||||
if getattr(args, "auto_detect", False):
|
||||
capabilities = get_agent_capabilities()
|
||||
if "error" in capabilities:
|
||||
print(f"Error: Auto-detection failed: {capabilities['error']}")
|
||||
return
|
||||
else:
|
||||
capabilities = {
|
||||
"compute_type": getattr(args, "compute_type", "inference"),
|
||||
"performance_score": getattr(args, "performance", 0.8),
|
||||
"max_concurrent_jobs": getattr(args, "max_jobs", 1)
|
||||
}
|
||||
|
||||
if hasattr(args, "gpu_memory") and args.gpu_memory:
|
||||
capabilities["gpu_memory"] = args.gpu_memory
|
||||
|
||||
if hasattr(args, "models") and args.models:
|
||||
capabilities["supported_models"] = [m.strip() for m in args.models.split(',')]
|
||||
|
||||
if hasattr(args, "specialization") and args.specialization:
|
||||
capabilities["specialization"] = args.specialization
|
||||
|
||||
# Create agent
|
||||
result = create_agent(
|
||||
name=args.name,
|
||||
agent_type=getattr(args, "type", "provider"),
|
||||
capabilities=capabilities,
|
||||
coordinator_url=getattr(args, "coordinator_url", None)
|
||||
)
|
||||
|
||||
if "error" in result:
|
||||
print(f"Error: {result['error']}")
|
||||
return
|
||||
|
||||
print(f"✅ Agent created successfully!")
|
||||
print(f" Agent ID: {result['agent_id']}")
|
||||
print(f" Name: {result['name']}")
|
||||
print(f" Address: {result['address']}")
|
||||
print(f" Type: {result['agent_type']}")
|
||||
print(f" Compute Type: {capabilities.get('compute_type', 'N/A')}")
|
||||
print(f" GPU Memory: {capabilities.get('gpu_memory', 'N/A')} GB")
|
||||
print(f" Performance Score: {capabilities.get('performance_score', 'N/A'):.2f}")
|
||||
print(f" Max Jobs: {capabilities.get('max_concurrent_jobs', 'N/A')}")
|
||||
|
||||
elif action == "register":
|
||||
import asyncio
|
||||
result = asyncio.run(register_agent(
|
||||
agent_id=args.agent_id,
|
||||
coordinator_url=getattr(args, "coordinator_url", "http://localhost:8001")
|
||||
))
|
||||
|
||||
if "error" in result:
|
||||
print(f"Error: {result['error']}")
|
||||
return
|
||||
|
||||
print(f"✅ Agent {args.agent_id} registered successfully!")
|
||||
print(f" Coordinator URL: {result['coordinator_url']}")
|
||||
print(f" Message: {result['message']}")
|
||||
|
||||
elif action == "list":
|
||||
agent_dir = Path(args.agent_dir) if hasattr(args, "agent_dir") and args.agent_dir else None
|
||||
agents = list_local_agents(agent_dir)
|
||||
|
||||
if not agents:
|
||||
print("No local agents found")
|
||||
return
|
||||
|
||||
print(f"Local Agents ({len(agents)}):")
|
||||
for agent in agents:
|
||||
print(f" - {agent['name']}: {agent.get('address', 'N/A')}")
|
||||
|
||||
elif action == "status":
|
||||
result = get_agent_status(args.agent_id)
|
||||
|
||||
print(f"Agent Status: {args.agent_id}")
|
||||
print(f" Status: {result['status']}")
|
||||
print(f" Registered: {result['registered']}")
|
||||
print(f" Reputation Score: {result['reputation_score']:.3f}")
|
||||
print(f" Last Seen: {result['last_seen']}")
|
||||
|
||||
elif action == "capabilities":
|
||||
caps = get_agent_capabilities()
|
||||
|
||||
if "error" in caps:
|
||||
print(f"Error: {caps['error']}")
|
||||
return
|
||||
|
||||
print("System Capabilities:")
|
||||
print(f" GPU Memory: {caps['gpu_memory']} MiB")
|
||||
print(f" GPU Count: {caps.get('gpu_count', 0)}")
|
||||
print(f" Compute Capability: {caps.get('compute_capability', 'unknown')}")
|
||||
print(f" Performance Score: {caps['performance_score']:.2f}")
|
||||
print(f" Max Concurrent Jobs: {caps['max_concurrent_jobs']}")
|
||||
print(f" Supported Models: {', '.join(caps.get('supported_models', []))}")
|
||||
|
||||
elif action == "config_set":
|
||||
from agent_sdk import set_agent_config
|
||||
result = set_agent_config(args.name, args.key, args.value)
|
||||
|
||||
if "error" in result:
|
||||
print(f"Error: {result['error']}")
|
||||
return
|
||||
|
||||
print(f"✅ Configuration set: {args.name}.{args.key} = {result['value']}")
|
||||
|
||||
elif action == "config_get":
|
||||
from agent_sdk import get_agent_config
|
||||
key = getattr(args, 'key', None)
|
||||
result = get_agent_config(args.name, key)
|
||||
|
||||
if "error" in result:
|
||||
print(f"Error: {result['error']}")
|
||||
return
|
||||
|
||||
if key:
|
||||
print(f"Agent Config: {args.name}.{key}")
|
||||
print(f" Value: {result['value']}")
|
||||
else:
|
||||
print(f"Agent Config: {args.name}")
|
||||
import json
|
||||
print(json.dumps(result['config'], indent=2))
|
||||
|
||||
elif action == "config_validate":
|
||||
from agent_sdk import validate_agent_config
|
||||
result = validate_agent_config(args.name)
|
||||
|
||||
if "error" in result:
|
||||
print(f"Error: {result['error']}")
|
||||
return
|
||||
|
||||
if result.get("valid"):
|
||||
print(f"✅ Configuration is valid: {args.name}")
|
||||
else:
|
||||
print(f"❌ Configuration validation failed: {result.get('error')}")
|
||||
|
||||
elif action == "config_import":
|
||||
from agent_sdk import import_agent_config
|
||||
file_path = getattr(args, 'file', None)
|
||||
name = getattr(args, 'name', None)
|
||||
result = import_agent_config(file_path, name)
|
||||
|
||||
if "error" in result:
|
||||
print(f"Error: {result['error']}")
|
||||
return
|
||||
|
||||
print(f"✅ Configuration imported: {result['name']} -> {result['config_file']}")
|
||||
|
||||
elif action == "config_export":
|
||||
from agent_sdk import export_agent_config
|
||||
output_path = getattr(args, 'output', None)
|
||||
result = export_agent_config(args.name, output_path)
|
||||
|
||||
if "error" in result:
|
||||
print(f"Error: {result['error']}")
|
||||
return
|
||||
|
||||
print(f"✅ Configuration exported: {args.name} -> {result['exported_to']}")
|
||||
|
||||
else:
|
||||
print(f"Unknown action: {action}")
|
||||
|
||||
except ImportError as e:
|
||||
print(f"Error: Agent SDK commands module not available: {e}")
|
||||
print("Install the Agent SDK from packages/py/aitbc-agent-sdk")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
else:
|
||||
print(f"Error: Agent SDK commands file not found at {agent_sdk_path}")
|
||||
|
||||
def handle_openclaw_action(args):
|
||||
system_handlers.handle_openclaw_action(args, openclaw_operations, first, render_mapping)
|
||||
|
||||
@@ -575,18 +762,19 @@ def run_cli(argv, core):
|
||||
"handle_ai_service_list": handle_ai_service_list,
|
||||
"handle_ai_service_status": handle_ai_service_status,
|
||||
"handle_ai_service_test": handle_ai_service_test,
|
||||
"handle_mining_action": handle_mining_action,
|
||||
"handle_system_status": handle_system_status,
|
||||
"handle_analytics": handle_analytics,
|
||||
"handle_economics_action": handle_economics_action,
|
||||
"handle_cluster_action": handle_cluster_action,
|
||||
"handle_performance_action": handle_performance_action,
|
||||
"handle_security_action": handle_security_action,
|
||||
"handle_simulate_action": handle_simulate_action,
|
||||
"handle_mining_action": handle_mining_action,
|
||||
"handle_system_status": handle_system_status,
|
||||
"handle_analytics": handle_analytics,
|
||||
"handle_agent_action": handle_agent_action,
|
||||
"handle_agent_sdk_action": handle_agent_sdk_action,
|
||||
"handle_openclaw_action": handle_openclaw_action,
|
||||
"handle_workflow_action": handle_workflow_action,
|
||||
"handle_resource_action": handle_resource_action,
|
||||
"handle_simulate_action": handle_simulate_action,
|
||||
"handle_pool_hub_sla_metrics": handle_pool_hub_sla_metrics,
|
||||
"handle_pool_hub_sla_violations": handle_pool_hub_sla_violations,
|
||||
"handle_pool_hub_capacity_snapshots": handle_pool_hub_capacity_snapshots,
|
||||
|
||||
Reference in New Issue
Block a user