Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,12 @@ GPU_SWARM_DB=data/swarm.db

# Worker / utilizer client defaults
# Local host scripts: http://127.0.0.1:8766
# Tailscale members / SDK default: http://100.85.165.84:8766
GPU_SWARM_SCHEDULER_URL=http://127.0.0.1:8766
GPU_SWARM_WORKER_NAME=
GPU_SWARM_MAX_VRAM_MB=0
GPU_SWARM_MAX_CPU_PERCENT=50
GPU_SWARM_MAX_RAM_MB=0
GPU_SWARM_MAX_DISK_MB=0
# Desktop joiner may set GB instead; worker converts to MB
# GPU_SWARM_MAX_DISK_GB=0
# Portal aliases (optional):
# GPU_SWARM_DEDICATED_RAM_MB=0
# GPU_SWARM_DEDICATED_DISK_MB=0
# GPU_SWARM_DEDICATED_CPU_CORES=0
GPU_SWARM_DISCORD_USER=
# Optional: drive free-space is measured on this path (default = project root)
# GPU_SWARM_WORK_DIR=
Expand All @@ -48,7 +41,7 @@ GPU_SWARM_INVITE_CODES=
# Discord Developer Portal: https://discord.com/developers/applications → GPU Pool (client id 1534226262510403654)
# Enable Message Content Intent on the Bot page (required by gpu_swarm/bot.py).
# Invite: make-invite-url.cmd <CLIENT_ID> (scopes bot + applications.commands, perms 84992)
DISCORD_BOT_TOKEN=
DISCORD_BOT_TOKEN=here u need to put token pls don't make it public
DISCORD_CLIENT_ID=1534226262510403654
# Guild for fast slash sync (Glitch Factor = 1532614467974856724; Jarvis HQ = 1532553474577924156)
DISCORD_GUILD_ID=
161 changes: 81 additions & 80 deletions examples/coding_agent_pool.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,8 @@
#!/usr/bin/env python3
"""Offload an allowlisted GPU Pool job and print the JSON result.

Coding agents / local tools can call this instead of inventing shell on workers.

python examples/coding_agent_pool.py
python examples/coding_agent_pool.py --job probe
python examples/coding_agent_pool.py --job pytorch_cuda_probe --matrix-size 1024
python examples/coding_agent_pool.py --scheduler-url http://127.0.0.1:8766 --wait

Env:
GPU_SWARM_SCHEDULER_URL default scheduler base (else http://127.0.0.1:8766)
//remove and optmize a code from ai slop//

HTTP: POST /jobs · GET /jobs/{id} · GET /status (same surface as gpu_swarm.client.GPUPool).
SDK twin: examples/use_pool_from_script.py · CLI: python -m gpu_swarm utilize …
Guide: CONNECTING.md
#!/usr/bin/env python3
"""Submit an allowlisted GPU Pool job and print the JSON result."""

v1 allowlist only: probe, pytorch_cuda_probe — no arbitrary shell / Ollama proxy.
"""
from __future__ import annotations

import argparse
Expand All @@ -29,30 +15,33 @@
from typing import Any

DEFAULT_SCHEDULER = "http://127.0.0.1:8766"
ALLOWED = frozenset({"probe", "pytorch_cuda_probe"})
ALLOWED = {"probe", "pytorch_cuda_probe"}


def _request(method: str, url: str, body: dict[str, Any] | None = None, timeout: float = 30.0) -> dict[str, Any]:
data = None
def request(method: str, url: str, body: dict[str, Any] | None = None, timeout: float = 30) -> dict[str, Any]:
headers = {"Accept": "application/json"}
if body is not None:
data = json.dumps(body).encode("utf-8")

data = None
if body:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
data = json.dumps(body).encode()

try:
with urllib.request.urlopen(req, timeout=timeout) as resp:
raw = resp.read().decode("utf-8")
except urllib.error.HTTPError as exc:
detail = exc.read().decode("utf-8", errors="replace")
raise SystemExit(f"HTTP {exc.code} {url}: {detail}") from exc
except urllib.error.URLError as exc:
with urllib.request.urlopen(
urllib.request.Request(url, data=data, headers=headers, method=method),
timeout=timeout,
) as resp:
return json.loads(resp.read() or "{}")

except urllib.error.HTTPError as e:
raise SystemExit(f"HTTP {e.code}: {e.read().decode(errors='replace')}") from e

except urllib.error.URLError as e:
raise SystemExit(
f"Cannot reach scheduler at {url}: {exc.reason}\n"
"Is the pool up? Try: curl http://127.0.0.1:8766/status"
) from exc
if not raw:
return {}
return json.loads(raw)
f"Cannot reach scheduler: {url}\n"
f"Reason: {e.reason}\n"
"Try: curl http://127.0.0.1:8766/status"
) from e


def submit_job(
Expand All @@ -64,57 +53,67 @@ def submit_job(
min_vram_mb: int = 0,
submitted_by: str = "coding_agent",
) -> dict[str, Any]:

if job_type not in ALLOWED:
raise SystemExit(f"job type not allowlisted: {job_type}. Allowed: {sorted(ALLOWED)}")
payload: dict[str, Any] = {}
require_gpu = False
if job_type == "pytorch_cuda_probe":
payload["matrix_size"] = max(64, min(int(matrix_size), 4096))
raise SystemExit(f"Unknown job: {job_type}")

payload = {}
require_gpu = job_type == "pytorch_cuda_probe"

if require_gpu:
payload["matrix_size"] = max(64, min(matrix_size, 4096))
if device_index is not None:
payload["device_index"] = int(device_index)
require_gpu = True
body = {
"job_type": job_type,
"payload": payload,
"require_gpu": require_gpu,
"min_vram_mb": int(min_vram_mb),
"submitted_by": submitted_by,
}
return _request("POST", f"{base.rstrip('/')}/jobs", body)


def wait_job(base: str, job_id: str, timeout: float) -> dict[str, Any]:
deadline = time.time() + timeout
last: dict[str, Any] = {}
while time.time() < deadline:
last = _request("GET", f"{base.rstrip('/')}/jobs/{job_id}")
if last.get("status") in ("completed", "failed"):
return last
time.sleep(1.0)
raise SystemExit(f"timeout waiting for job {job_id} after {timeout}s; last={json.dumps(last)}")
payload["device_index"] = device_index

return request(
"POST",
f"{base}/jobs",
{
"job_type": job_type,
"payload": payload,
"require_gpu": require_gpu,
"min_vram_mb": min_vram_mb,
"submitted_by": submitted_by,
},
)


def wait_for_job(base: str, job_id: str, timeout: float) -> dict[str, Any]:
end = time.time() + timeout

while time.time() < end:
job = request("GET", f"{base}/jobs/{job_id}")

if job.get("status") in {"completed", "failed"}:
return job

time.sleep(1)

raise SystemExit(f"Timed out waiting for {job_id}")


def main(argv: list[str] | None = None) -> int:
p = argparse.ArgumentParser(description="Submit allowlisted GPU Pool job; print JSON result")
p.add_argument(
parser = argparse.ArgumentParser(description="GPU Pool client")

parser.add_argument(
"--scheduler-url",
default=os.environ.get("GPU_SWARM_SCHEDULER_URL", DEFAULT_SCHEDULER),
help=f"Scheduler base URL (default {DEFAULT_SCHEDULER})",
default=os.getenv("GPU_SWARM_SCHEDULER_URL", DEFAULT_SCHEDULER),
)
p.add_argument("--job", choices=sorted(ALLOWED), default="probe", help="Allowlisted job type")
p.add_argument("--matrix-size", type=int, default=1024, help="For pytorch_cuda_probe")
p.add_argument("--device-index", type=int, default=None, help="Optional CUDA device index")
p.add_argument("--min-vram-mb", type=int, default=0)
p.add_argument("--by", default="coding_agent", help="submitted_by label")
p.add_argument("--wait", action="store_true", default=True, help="Wait for completion (default)")
p.add_argument("--no-wait", action="store_true", help="Print queued job JSON and exit")
p.add_argument("--wait-timeout", type=float, default=120.0)
p.add_argument("--status-only", action="store_true", help="GET /status and exit")
args = p.parse_args(argv)
parser.add_argument("--job", choices=sorted(ALLOWED), default="probe")
parser.add_argument("--matrix-size", type=int, default=1024)
parser.add_argument("--device-index", type=int)
parser.add_argument("--min-vram-mb", type=int, default=0)
parser.add_argument("--by", default="coding_agent")
parser.add_argument("--wait-timeout", type=float, default=120)
parser.add_argument("--status-only", action="store_true")
parser.add_argument("--no-wait", action="store_true")

args = parser.parse_args(argv)

base = args.scheduler_url.rstrip("/")

if args.status_only:
print(json.dumps(_request("GET", f"{base}/status"), indent=2))
print(json.dumps(request("GET", f"{base}/status"), indent=2))
return 0

job = submit_job(
Expand All @@ -125,14 +124,16 @@ def main(argv: list[str] | None = None) -> int:
min_vram_mb=args.min_vram_mb,
submitted_by=args.by,
)

if args.no_wait:
print(json.dumps(job, indent=2))
return 0

final = wait_job(base, job["id"], args.wait_timeout)
print(json.dumps(final, indent=2))
return 0 if final.get("status") == "completed" else 1
result = wait_for_job(base, job["id"], args.wait_timeout)
print(json.dumps(result, indent=2))

return 0 if result["status"] == "completed" else 1


if __name__ == "__main__":
sys.exit(main())
raise SystemExit(main())
4 changes: 3 additions & 1 deletion gpu_swarm/portal.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,8 @@ def run_portal(host: str | None = None, port: int | None = None) -> None:
)


PORTAL_HTML = r"""<!DOCTYPE html>
PORTAL_HTML =
r"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
Expand Down Expand Up @@ -992,3 +993,4 @@ def run_portal(host: str | None = None, port: int | None = None) -> None:
</body>
</html>
"""
//neeed to fix this it wrong formet and to much cna be optimize more and make better as wwell use less paython dude //
31 changes: 15 additions & 16 deletions scripts/check_prereqs.cmd
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
@echo off
setlocal
REM GPU Pool prerequisite probe (JSON by default)
REM Usage: scripts\check_prereqs.cmd [--text] [--scheduler-url URL]
set "SCRIPT_DIR=%~dp0"
cd /d "%SCRIPT_DIR%.."
cd /d "%~dp0.."
set "ARGS="
:parse
if "%~1"=="" goto run
if /I "%~1"=="--text" set "ARGS=%ARGS% -Text" & shift & goto parse
if /I "%~1"=="--json" set "ARGS=%ARGS% -Json" & shift & goto parse
:loop
if "%~1"=="" goto exec
if /I "%~1"=="--text" set "ARGS=%ARGS% -Text" & shift & goto loop
if /I "%~1"=="--json" set "ARGS=%ARGS% -Json" & shift & goto loop
if /I "%~1"=="--scheduler-url" (
set "ARGS=%ARGS% -SchedulerUrl ""%~2"""
shift & shift & goto parse
set "ARGS=%ARGS% -SchedulerUrl ""%~2"""
shift & shift
goto loop
)
if /I "%~1"=="--min-disk-gb" (
set "ARGS=%ARGS% -MinDiskGb %~2"
shift & shift & goto parse
set "ARGS=%ARGS% -MinDiskGb %~2"
shift & shift
goto loop
)
echo Unknown arg: %~1
echo Unknown argument: %~1
exit /b 2
:run
powershell -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_DIR%check_prereqs.ps1" %ARGS%
exit /b %ERRORLEVEL%
:exec
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0check_prereqs.ps1" %ARGS%
exit /b %ERRORLEVEL%