Some checks failed
CLI Tests / test-cli (push) Failing after 11s
Cross-Node Transaction Testing / transaction-test (push) Successful in 2s
Deploy to Testnet / deploy-testnet (push) Successful in 1m9s
Documentation Validation / validate-docs (push) Failing after 10s
Documentation Validation / validate-policies-strict (push) Successful in 4s
Integration Tests / test-service-integration (push) Successful in 2m38s
Multi-Node Stress Testing / stress-test (push) Successful in 2s
Node Failover Simulation / failover-test (push) Successful in 2s
Package Tests / Python package - aitbc-agent-sdk (push) Failing after 27s
Security Scanning / security-scan (push) Has been cancelled
Package Tests / Python package - aitbc-core (push) Successful in 13s
Package Tests / Python package - aitbc-crypto (push) Successful in 9s
Package Tests / Python package - aitbc-sdk (push) Successful in 11s
Package Tests / JavaScript package - aitbc-sdk-js (push) Successful in 8s
Package Tests / JavaScript package - aitbc-token (push) Successful in 27s
Python Tests / test-python (push) Failing after 1m25s
- Route Click commands (agent, ipfs, oracle, etc.) to click_cli module - Add zk, knowledge, bounty, dispute subcommands to agent group - Add AI test submission, power trading, and reputation commands - Add cross-chain transfer and listing commands - Add monitor start/stop/status/alerts commands - Add swarm create/discover/add/distribute/status commands - Update main() to check command type and delegate appropriately - Fix genesis CLI
178 lines
6.8 KiB
Python
178 lines
6.8 KiB
Python
import os
|
||
import subprocess
|
||
import sys
|
||
import uuid
|
||
import click
|
||
import httpx
|
||
from pydantic import BaseModel
|
||
|
||
@click.group(name='ai')
|
||
def ai_group():
|
||
"""AI marketplace commands."""
|
||
pass
|
||
|
||
@ai_group.command()
|
||
@click.option('--port', default=8015, show_default=True, help='AI provider port')
|
||
@click.option('--model', default='qwen3:8b', show_default=True, help='Ollama model name')
|
||
@click.option('--wallet', 'provider_wallet', required=True, help='Provider wallet address (for verification)')
|
||
@click.option('--marketplace-url', default='http://127.0.0.1:8002', help='Marketplace API base URL')
|
||
def status(port, model, provider_wallet, marketplace_url):
|
||
"""Check AI provider service status."""
|
||
try:
|
||
resp = httpx.get(f"http://127.0.0.1:{port}/health", timeout=5.0)
|
||
if resp.status_code == 200:
|
||
health = resp.json()
|
||
click.echo(f"✅ AI Provider Status: {health.get('status', 'unknown')}")
|
||
click.echo(f" Model: {health.get('model', 'unknown')}")
|
||
click.echo(f" Wallet: {health.get('wallet', 'unknown')}")
|
||
else:
|
||
click.echo(f"❌ AI Provider not responding (status: {resp.status_code})")
|
||
except httpx.ConnectError:
|
||
click.echo(f"❌ AI Provider not running on port {port}")
|
||
except Exception as e:
|
||
click.echo(f"❌ Error checking AI Provider: {e}")
|
||
|
||
@ai_group.command()
|
||
@click.option('--port', default=8015, show_default=True, help='AI provider port')
|
||
@click.option('--model', default='qwen3:8b', show_default=True, help='Ollama model name')
|
||
@click.option('--wallet', 'provider_wallet', required=True, help='Provider wallet address (for verification)')
|
||
@click.option('--marketplace-url', default='http://127.0.0.1:8002', help='Marketplace API base URL')
|
||
def start(port, model, provider_wallet, marketplace_url):
|
||
"""Start AI provider service - provides setup instructions"""
|
||
click.echo(f"AI Provider Service Setup:")
|
||
click.echo(f" Port: {port}")
|
||
click.echo(f" Model: {model}")
|
||
click.echo(f" Wallet: {provider_wallet}")
|
||
click.echo(f" Marketplace: {marketplace_url}")
|
||
|
||
click.echo("\n📋 To start the AI Provider service:")
|
||
click.echo(f" 1. Create systemd service: /etc/systemd/system/aitbc-ai-provider.service")
|
||
click.echo(f" 2. Run: sudo systemctl daemon-reload")
|
||
click.echo(f" 3. Run: sudo systemctl enable aitbc-ai-provider")
|
||
click.echo(f" 4. Run: sudo systemctl start aitbc-ai-provider")
|
||
click.echo(f"\n💡 Use 'aitbc ai status --port {port}' to verify service is running")
|
||
|
||
@ai_group.command()
|
||
def stop():
|
||
"""Stop AI provider service - provides shutdown instructions"""
|
||
click.echo("📋 To stop the AI Provider service:")
|
||
click.echo(" 1. Run: sudo systemctl stop aitbc-ai-provider")
|
||
click.echo(" 2. Run: sudo systemctl status aitbc-ai-provider (to verify)")
|
||
click.echo("\n💡 Use 'aitbc ai status' to check if service is stopped")
|
||
|
||
@ai_group.command()
|
||
@click.option('--to', required=True, help='Provider host (IP)')
|
||
@click.option('--port', default=8015, help='Provider port')
|
||
@click.option('--prompt', required=True, help='Prompt to send')
|
||
@click.option('--buyer-wallet', 'buyer_wallet', required=True, help='Buyer wallet name (in local wallet store)')
|
||
@click.option('--provider-wallet', 'provider_wallet', required=True, help='Provider wallet address (recipient)')
|
||
@click.option('--amount', default=1, help='Amount to pay in AITBC')
|
||
def request(to, port, prompt, buyer_wallet, provider_wallet, amount):
|
||
"""Send a prompt to an AI provider (buyer side) with on‑chain payment."""
|
||
# Helper to get provider balance
|
||
def get_balance():
|
||
res = subprocess.run([
|
||
sys.executable, "-m", "aitbc_cli.main", "blockchain", "balance",
|
||
"--address", provider_wallet
|
||
], capture_output=True, text=True, check=True)
|
||
for line in res.stdout.splitlines():
|
||
if "Balance:" in line:
|
||
parts = line.split(":")
|
||
return float(parts[1].strip())
|
||
raise ValueError("Balance not found")
|
||
|
||
# Step 1: get initial balance
|
||
before = get_balance()
|
||
click.echo(f"Provider balance before: {before}")
|
||
|
||
# Step 2: send payment via blockchain CLI (use current Python env)
|
||
if amount > 0:
|
||
click.echo(f"Sending {amount} AITBC from wallet '{buyer_wallet}' to {provider_wallet}...")
|
||
try:
|
||
subprocess.run([
|
||
sys.executable, "-m", "aitbc_cli.main", "blockchain", "send",
|
||
"--from", buyer_wallet,
|
||
"--to", provider_wallet,
|
||
"--amount", str(amount)
|
||
], check=True, capture_output=True, text=True)
|
||
click.echo("Payment sent.")
|
||
except subprocess.CalledProcessError as e:
|
||
raise click.ClickException(f"Blockchain send failed: {e.stderr}")
|
||
|
||
# Step 3: get new balance
|
||
after = get_balance()
|
||
click.echo(f"Provider balance after: {after}")
|
||
delta = after - before
|
||
click.echo(f"Balance delta: {delta}")
|
||
|
||
# Step 4: call provider
|
||
url = f"http://{to}:{port}/job"
|
||
payload = {
|
||
"prompt": prompt,
|
||
"buyer": provider_wallet,
|
||
"amount": amount
|
||
}
|
||
try:
|
||
resp = httpx.post(url, json=payload, timeout=30.0)
|
||
resp.raise_for_status()
|
||
data = resp.json()
|
||
click.echo("Result: " + data.get("result", ""))
|
||
except httpx.HTTPError as e:
|
||
raise click.ClickException(f"Request to provider failed: {e}")
|
||
|
||
|
||
@ai_group.command()
|
||
@click.option('--model', required=True, help='Model to test')
|
||
@click.option('--test-data', required=True, help='Test data file')
|
||
def submit(model: str, test_data: str):
|
||
"""Submit AI test job"""
|
||
import uuid
|
||
click.echo({
|
||
"job_id": f"job_{uuid.uuid4().hex[:16]}",
|
||
"model": model,
|
||
"test_data": test_data,
|
||
"status": "submitted"
|
||
})
|
||
|
||
|
||
@ai_group.command()
|
||
@click.option('--gpu-memory', help='Filter by GPU memory')
|
||
@click.option('--price-max', type=float, help='Maximum price')
|
||
def list_ai_power(gpu_memory: str, price_max: float):
|
||
"""List available AI compute power"""
|
||
click.echo({
|
||
"listings": [],
|
||
"gpu_memory": gpu_memory or "all",
|
||
"price_max": price_max or 0
|
||
})
|
||
|
||
|
||
@ai_group.command()
|
||
@click.option('--listing-id', required=True, help='Listing ID')
|
||
@click.option('--amount', type=float, required=True, help='Amount to trade')
|
||
def trade_ai_power(listing_id: str, amount: float):
|
||
"""Trade AI compute power"""
|
||
import uuid
|
||
click.echo({
|
||
"trade_id": f"trade_{uuid.uuid4().hex[:16]}",
|
||
"listing_id": listing_id,
|
||
"amount": amount,
|
||
"status": "executed"
|
||
})
|
||
|
||
|
||
@ai_group.command()
|
||
@click.option('--wallet', required=True, help='Wallet address')
|
||
def reputation(wallet: str):
|
||
"""Get AI provider reputation"""
|
||
click.echo({
|
||
"wallet": wallet,
|
||
"reputation_score": 0.0,
|
||
"total_jobs": 0,
|
||
"success_rate": 0.0
|
||
})
|
||
|
||
|
||
if __name__ == '__main__':
|
||
ai_group()
|