الـ 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 محرفاً سداسي عشري)، 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 MiB لكل تدفق |
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 MB.
الدالة usage() تُعيد ثواني التشغيل وثواني المعالج المستهلكة والبايتات الصادرة والسعر بالساعة و 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 | معرّف خاطئ أو ملف غير موجود |
SandboxPausedError | 409 | sandbox_paused | موقوف مؤقتاً لنفاد الرصيد، ويستأنف بعد الشحن |
SandboxDeletedError | 410 | sandbox_deleted | حُذف نهائياً |
FileTooLargeError | 413 | file_too_large | أبقِ النقل دون 5 MB |
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 سببها حدّان: الحساب ينفّذ أمرين في الوقت نفسه ويحتفظ بـ 20 صندوقاً على الأكثر. يعيد SDK المحاولة حين يحدد الخادم مدة الانتظار، وبعد ثلاث محاولات يصلك الاستثناء.
متى لا تحتاج الـ SDK
أي لغة فيها عميل HTTP تستطيع استدعاء الـ API مباشرة، ونقاط النهاية موصوفة في ملف OpenAPI على https://eqvps.com/openapi.json. والوكلاء في Claude و Cursor وغيرهما من عملاء MCP لا يحتاجون كوداً أصلاً: خادم MCP فيه أدوات صناديق الرمل نفسها. وإن أردت فقط أن تراه يعمل، ففي صفحة صناديق الرمل الخطط وتجربة الـ $1 للحسابات الجديدة.
التعليقات
لا تعليقات بعد. كن الأول.