SDK — тонка обгортка над REST API пісочниць. Він позбавляє трьох речей: збирати запити вручну, повторювати їх, коли платформа зайнята, і забувати видалити пісочницю, якщо код упав. Усе тут відповідає версії 0.2.0 обох пакетів.
Якщо ви ще жодного разу не створювали пісочницю, посібник із підключення за 5 хвилин спершу допоможе отримати токен. Що таке пісочниця і що всередині — у розділі Пісочниці.
Встановлення і налаштування
pip install eqvps # Python 3.8+
npm i @eqvps/sdk # Node.js 18+, Deno, Bun
export EQVPS_API_KEY=... # your EQVPS account token
Та сама програма обома мовами: створити пісочницю, виконати код, видалити.
from eqvps import Sandbox
with Sandbox.create(tariff="small") as sb:
r = sb.run("print(2 + 2)")
print(r.exit_code, r.stdout) # 0 4
import { Sandbox } from "@eqvps/sdk";
await Sandbox.with({ tariff: "small" }, async (sb) => {
const r = await sb.run("print(2 + 2)");
console.log(r.exit_code, r.stdout); // 0 4
});
Створення і пошук пісочниць
Sandbox.create(...) запускає пісочницю, зазвичай приблизно за секунду. У Python — іменовані аргументи, у TypeScript — один об'єкт опцій.
| Python | TypeScript | Типово | Що означає |
|---|---|---|---|
mode | mode | "ephemeral" | "ephemeral" (посекундно) або "persistent" (за розпочату годину, диск зберігається) |
tariff | tariff | "small" | micro, small, standard, plus, pro, max |
idle_timeout | idleTimeout | 300 | секунд без активності до видалення ефемерної пісочниці, до 3600 |
ttl | ttl | — | максимальний час життя в секундах: до 86400 в ефемерної, 2592000 у постійної |
env | env | — | змінні оточення для всіх команд, зберігаються зашифрованими |
api_key, base_url | apiKey, baseUrl | змінні оточення | перевизначають EQVPS_API_KEY / EQVPS_API_URL |
timeout | timeoutMs | 70 с | HTTP-тайм-аут одного запиту |
max_retries | maxRetries | 3 | повтори при 429/503 |
Sandbox.connect(id) підключається до наявної пісочниці — зазвичай до постійної, створеної вчора. Sandbox.list() повертає всі пісочниці акаунта, робочі та на паузі.
Властивості: id (sb_ + 24 hex-символи), mode, tariff, state (running, starting, paused, pausing, resuming, deleting, deleted), env_keys / envKeys (лише імена, значення не повертаються) і info (сирий об'єкт). refresh() перечитує їх.
kill() видаляє пісочницю й зупиняє тарифікацію. Виклик для вже видаленої пісочниці помилкою не вважається.
Виконання коду
run(code, language="python", timeout=30) передає код через stdin у Python 3.12, Node.js 22 або bash ("python", "node", "bash"). exec(command, cwd=None, stdin=None, timeout=30) виконує команду оболонки: рядок іде через bash -lc, список виконується як argv без оболонки.
Обидва повертають ExecResult:
| Поле | Що означає |
|---|---|
exit_code | код завершення процесу |
stdout, stderr | вивід, до 1 МіБ на потік |
timed_out | команда вперлася в тайм-аут |
truncated | вивід обрізано |
duration_ms | скільки тривало виконання |
ok | exit_code == 0 і без тайм-ауту |
Синхронний виклик працює не довше 55 секунд. Обидва методи приймають і env на один виклик; він перекриває значення, задані під час створення.
Довгі завдання: фоновий режим
Передайте background=True (у TypeScript { background: true }) — і одразу отримаєте Task. У завдання немає обмеження в 55 секунд, воно може працювати до кінця життя пісочниці. До 8 завдань на пісочницю.
task = sb.exec("cd /root/app && python3 -m pytest -q", background=True)
result = task.wait(on_output=lambda out, err: print(out, end=""))
print(result.state, result.exit_code) # done 0
const task = await sb.exec("cd /root/app && npm test", { background: true });
const result = await task.wait({ onOutput: (out) => process.stdout.write(out) });
| Метод | Що робить |
|---|---|
task.logs() | новий stdout і stderr з минулого виклику |
task.status() | стан без читання виводу: running, done, failed, killed, timeout |
task.wait(timeout, poll_interval=2, on_output) | опитує до завершення, повертає TaskResult |
task.kill() | зупиняє завдання та його процеси |
sb.task(id) / sb.tasks() | перепідключитися до завдання / список завдань |
Якщо в wait сплив власний тайм-аут, він кидає SandboxTimeoutError, але завдання продовжує працювати. Робоче завдання також не дає ефемерній пісочниці видалитися через бездіяльність.
Файли та витрати
upload(path, content, mode=None) записує файл за абсолютним шляхом і повертає його розмір. download(path) повертає байти, download_text(path) / downloadText(path) — рядок. Одна передача обмежена 5 МБ.
usage() повертає секунди роботи, використані CPU-секунди, вихідні байти, ціну за годину, billed_usd і estimated_total_usd. tariffs() — звичайна функція, ключ їй не потрібен; повертає поточні ціни й ліміти. Правила тарифікації — на сторінці Ліміти й оплата пісочниць.
Помилки
Кожна помилка API — підклас EqvpsError з полями status (HTTP), code (стабільний рядок) і body. retry_after / retryAfter заповнене, якщо сервер його надіслав.
| Клас | HTTP | Типовий code | Що робити |
|---|---|---|---|
AuthenticationError | 401 | unauthenticated | перевірити токен |
InsufficientBalanceError | 402 | insufficient_balance | поповнити баланс |
NotFoundError | 404 | not_found | неправильний id або файлу немає |
SandboxPausedError | 409 | sandbox_paused | на паузі після вичерпання балансу; продовжить після поповнення |
SandboxDeletedError | 410 | sandbox_deleted | видалена остаточно |
FileTooLargeError | 413 | file_too_large | тримати передачі менше 5 МБ |
ValidationError | 422 | invalid_request | виправити параметри |
RateLimitError | 429 | too_many_concurrent, too_many_tasks, rate_limited | зачекати й повторити |
BudgetExceededError | 429 | budget_exceeded | досягнуто денного або місячного ліміту витрат на пісочниці |
CapacityError | 503 | capacity | повторити трохи пізніше або взяти менший тариф |
SandboxTimeoutError | — | request_timeout, wait_timeout | сплив тайм-аут HTTP-запиту (або wait), а не команди |
Більшість 429 спричиняють два ліміти: акаунт виконує 2 команди одночасно і тримає до 20 пісочниць. SDK повторює такі запити, якщо сервер повідомив, скільки чекати; після трьох спроб ви отримаєте виняток.
Коли SDK не потрібен
Будь-яка мова з HTTP-клієнтом може звертатися до API напряму; ендпоінти описані у файлі OpenAPI за адресою https://eqvps.com/openapi.json. Агентам у Claude, Cursor та інших MCP-клієнтах код не потрібен узагалі: у MCP-сервера ті самі інструменти пісочниць. А якщо хочеться просто подивитися, як це працює, на сторінці пісочниць є тарифи й пробний $1 для нових акаунтів.
Коментарі
Поки немає коментарів. Будьте першим.