项目文件夹

文件
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 13:03:19 +08:00

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())