trycua--cua
91e75e620b
CI: cua-driver distro-compat matrix / debian:12 (glibc 2.36) (push) Has been cancelled
CI: SPDX Headers / Check SPDX headers (warn-only) (push) Has been cancelled
CD: Docs MCP Server / build (linux/amd64) (push) Has been cancelled
CD: Docs MCP Server / build (linux/arm64) (push) Has been cancelled
CD: Docs MCP Server / merge (push) Has been cancelled
CI: cua-driver distro-compat matrix / Resolve release version (push) Has been cancelled
CI: cua-driver distro-compat matrix / fedora:41 (glibc 2.40) (push) Has been cancelled
CI: cua-driver distro-compat matrix / rockylinux:9 (glibc 2.34) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:22.04 (glibc 2.35) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:24.04 (glibc 2.39) (push) Has been cancelled
CI: cua-driver distro-compat matrix / Distro compat summary (push) Has been cancelled
CI: Rust Linux unit / Rust Linux unit and compile (push) Has been cancelled
CI: Rust Windows unit / Rust Windows unit and compile (push) Has been cancelled
CI: Nix Linux Rust source / Nix / compositor build (push) Has been cancelled
CI: Nix Linux Rust source / Nix / driver package (push) Has been cancelled
CI: Nix Linux Rust source / Nix / Rust unit tests (push) Has been cancelled
171 行
5.4 KiB
Python
171 行
5.4 KiB
Python
"""Diagnostic script to understand why aiohttp /cmd calls fail from subprocess context."""
|
|
|
|
import asyncio
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
import urllib.request
|
|
from pathlib import Path
|
|
|
|
# Load .env
|
|
env_file = Path(__file__).parent.parent / ".env"
|
|
if env_file.exists():
|
|
for line in env_file.read_text().splitlines():
|
|
line = line.strip()
|
|
if line and not line.startswith("#") and "=" in line:
|
|
k, v = line.split("=", 1)
|
|
os.environ.setdefault(k, v)
|
|
|
|
|
|
async def test_url(url: str, label: str):
|
|
"""Test aiohttp POST to /cmd."""
|
|
import aiohttp
|
|
|
|
cmd_url = url.rstrip("/") + "/cmd"
|
|
payload = {"command": "run_command", "params": {"command": "echo hello"}}
|
|
headers = {"Content-Type": "application/json"}
|
|
|
|
print(f"\n[{label}] POST {cmd_url}")
|
|
try:
|
|
async with aiohttp.ClientSession() as session:
|
|
async with session.post(cmd_url, json=payload, headers=headers, timeout=aiohttp.ClientTimeout(total=30)) as resp:
|
|
body = await resp.text()
|
|
print(f" status={resp.status} headers={dict(resp.headers)}")
|
|
print(f" body={body[:200]!r}")
|
|
except Exception as e:
|
|
print(f" ERROR: {e}")
|
|
|
|
|
|
async def test_status(url: str, label: str):
|
|
"""Test urllib GET to /status."""
|
|
status_url = url.rstrip("/") + "/status"
|
|
print(f"\n[{label}] GET {status_url}")
|
|
try:
|
|
with urllib.request.urlopen(status_url, timeout=10) as resp:
|
|
body = resp.read().decode()
|
|
print(f" status={resp.status} body={body[:100]!r}")
|
|
except Exception as e:
|
|
print(f" ERROR: {e}")
|
|
|
|
|
|
async def main():
|
|
api_key = os.environ.get("DAYTONA_API_KEY")
|
|
api_url_env = os.environ.get("DAYTONA_API_URL")
|
|
|
|
if not api_key:
|
|
print("ERROR: DAYTONA_API_KEY not set")
|
|
sys.exit(1)
|
|
|
|
print("Importing Daytona SDK...")
|
|
from daytona_sdk import Daytona, DaytonaConfig
|
|
from daytona_sdk.common.daytona import CreateSandboxFromSnapshotParams
|
|
from daytona_sdk.common.sandbox import Resources
|
|
|
|
daytona = Daytona(DaytonaConfig(api_key=api_key, api_url=api_url_env))
|
|
|
|
print("Creating sandbox from snapshot nikri/kicad-snorkel:latest...")
|
|
params = CreateSandboxFromSnapshotParams(
|
|
snapshot="nikri/kicad-snorkel:latest",
|
|
env_vars={},
|
|
auto_stop_interval=0,
|
|
resources=Resources(cpu=2, memory=4, disk=10),
|
|
)
|
|
sandbox = daytona.create(params)
|
|
print(f" Sandbox ID: {sandbox.id}")
|
|
|
|
# Bootstrap supervisord
|
|
print("Bootstrapping supervisord...")
|
|
try:
|
|
sandbox.process.exec(
|
|
"nohup /usr/bin/supervisord -c /etc/supervisor/supervisord.conf"
|
|
" > /var/log/supervisor/supervisord.log 2>&1 &",
|
|
timeout=10,
|
|
)
|
|
except Exception as exc:
|
|
print(f" exec returned (expected for nohup): {exc}")
|
|
|
|
# Get signed URL
|
|
signed = sandbox.create_signed_preview_url(8000, expires_in_seconds=14400)
|
|
url = signed.url
|
|
print(f"\nSigned URL: {url!r}")
|
|
|
|
# Wait for server to be ready
|
|
print("\nWaiting for cua-computer-server...")
|
|
status_url = url.rstrip("/") + "/status"
|
|
deadline = time.monotonic() + 300
|
|
while time.monotonic() < deadline:
|
|
try:
|
|
with urllib.request.urlopen(status_url, timeout=5) as resp:
|
|
if resp.status == 200:
|
|
print(f" Ready! status={resp.status}")
|
|
break
|
|
except Exception:
|
|
pass
|
|
time.sleep(5)
|
|
else:
|
|
print(" TIMEOUT waiting for server")
|
|
daytona.delete(sandbox)
|
|
sys.exit(1)
|
|
|
|
# Test 1: aiohttp from this process
|
|
await test_url(url, "aiohttp-direct")
|
|
|
|
# Test 2: urllib from this process
|
|
await test_status(url, "urllib-direct")
|
|
|
|
# Test 3: spawn subprocess and test aiohttp from there
|
|
print("\n[subprocess] Testing aiohttp from subprocess...")
|
|
subprocess_code = f"""
|
|
import asyncio
|
|
import aiohttp
|
|
import sys
|
|
|
|
async def test():
|
|
url = {url!r}
|
|
cmd_url = url.rstrip('/') + '/cmd'
|
|
payload = {{"command": "run_command", "params": {{"command": "echo subprocess_hello"}}}}
|
|
headers = {{"Content-Type": "application/json"}}
|
|
print(f"POST {{cmd_url}}")
|
|
try:
|
|
async with aiohttp.ClientSession() as session:
|
|
async with session.post(cmd_url, json=payload, headers=headers, timeout=aiohttp.ClientTimeout(total=30)) as resp:
|
|
body = await resp.text()
|
|
print(f"status={{resp.status}} body={{body[:200]!r}}")
|
|
except Exception as e:
|
|
print(f"ERROR: {{e}}")
|
|
|
|
asyncio.run(test())
|
|
"""
|
|
result = subprocess.run(
|
|
[sys.executable, "-c", subprocess_code],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=60,
|
|
)
|
|
print(f" stdout: {result.stdout!r}")
|
|
print(f" stderr: {result.stderr[:500]!r}")
|
|
|
|
# Test 4: spawn subprocess with start_new_session=True (like task_runner does)
|
|
print("\n[subprocess+new_session] Testing with start_new_session=True...")
|
|
result2 = subprocess.run(
|
|
[sys.executable, "-c", subprocess_code],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=60,
|
|
start_new_session=True,
|
|
)
|
|
print(f" stdout: {result2.stdout!r}")
|
|
print(f" stderr: {result2.stderr[:500]!r}")
|
|
|
|
print("\nCleaning up sandbox...")
|
|
try:
|
|
daytona.delete(sandbox)
|
|
print(" Done.")
|
|
except Exception as e:
|
|
print(f" Cleanup error: {e}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|