# القواعد العامة

> قواعد تشترك فيها كل نقاط نهاية LMSP، وهي ترويسات الإصدار والامتدادات ومفاتيح التكرار الآمن وصيغة الأخطاء problem+json مع رموزها وفحص الصحة.

Source: https://madeforagent.com/ar/lmsp/1.0/common-rules/
Language: ar
Specification: LMSP 1.0 (draft)
Updated: 2026-11-08

## 9.1 الإصدارات والامتدادات {#versioning}

**يجوز** أن يحمل كل طلب LMSP هذه الترويسات:

```http
LMSP-Version: 1.0
LMSP-Client: example-client/1.2.0
```

`LMSP-Version` هي إصدار البروتوكول الذي يستهدفه العميل. و`LMSP-Client` يعرّف برنامج العميل لأغراض التشخيص، بصيغة `name/version`. و**لا يجوز** للخدمة أن تغيّر سلوك البروتوكول بناءً على هذه الترويسة.

القواعد:

- يدل `v1` في المسار على الإصدار الرئيسي.
- الطلب الذي يسمّي إصدارًا رئيسيًا مجهولًا يُرد عليه بـ `426 Upgrade Required` ورمز الخطأ `unsupported_protocol_version`.
- **لا يجوز** للحقول الاختيارية الجديدة أن تكسر توافق 1.x.
- **يجب** على الخدمات والعملاء تجاهل الحقول التي لا يعرفونها.
- تُوضَع الامتدادات الخاصة في كائن `extensions` وتُسمّى بصيغة النطاق المعكوس:

```json
{
  "extensions": {
    "com.example.cache": {
      "enabled": true
    }
  }
}
```

## 9.2 التكرار الآمن (Idempotency) {#idempotency}

الطلبات التي تنشئ شيئًا، مثل إنشاء استجابة أو إنشاء مهمة أو تحميل نموذج، تقبل مفتاح تكرار آمن:

```http
Idempotency-Key: <client-generated-unique-value>
```

تخزّن الخدمة المفتاح مع بصمة متن الطلب والنتيجة:

- المفتاح نفسه مع المتن نفسه يعيد النتيجة الأصلية.
- المفتاح نفسه مع متن مختلف يُرد عليه بـ `409 Conflict` مع `idempotency_conflict`.

نطاق المفتاح هو العميل ونقطة النهاية. و**ينبغي** أن يكون قيمة فريدة لا تتجاوز 255 حرفًا، مثل ULID أو UUID. و**ينبغي** للخدمة أن تحتفظ بالمفاتيح 24 ساعة على الأقل.

**يجوز** للخدمة أن تتجاهل المفتاح في الطلبات المبثوثة. والعميل الذي يحتاج إلى إعادة محاولة آمنة يستخدم [مهمة](https://madeforagent.com/ar/lmsp/1.0/tasks.md).

## 9.3 الأخطاء {#errors}

كل خطأ على واجهة LMSP يستخدم `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)):

```json
{
  "type": "urn:lmsp:error:model-not-found",
  "title": "Model not found",
  "status": 404,
  "code": "model_not_found",
  "detail": "No local model with id 'qwen3:14b-q4_k_m'",
  "request_id": "req_01J8M9S6Y4W8C3P5R1V7Z2A0DH",
  "retryable": false
}
```

| الحقل | إلزامي | المعنى |
| --- | --- | --- |
| `type` | نعم | URI يحدد نوع الخطأ. يستخدم LMSP البادئة `urn:lmsp:error:` متبوعة بالرمز مع شرطات بدل الشرطات السفلية. |
| `title` | نعم | ملخص قصير مقروء للبشر. |
| `status` | نعم | رمز حالة HTTP. |
| `code` | نعم | رمز خطأ مقروء آليًا، من القائمة أدناه. |
| `detail` | لا | شرح مقروء للبشر لهذه الحالة. و**لا يجوز** أن يحتوي على أسرار أو مطالبات أو محتوى مولَّد. |
| `request_id` | لا | معرّف الطلب، لربطه بسجلات الخدمة. |
| `retryable` | نعم | هل يمكن أن ينجح تكرار الطلب لاحقًا. |

رموز الأخطاء الشائعة:

| الرمز | حالة HTTP | قابل لإعادة المحاولة | المعنى |
| --- | --- | --- | --- |
| `invalid_request` | 400 | لا | الطلب مشوَّه أو معاملاته غير صالحة. |
| `unauthorized` | 401 | لا | الرمز مفقود أو غير صالح أو منتهي أو مسحوب، أو رمز الاقتران خاطئ. |
| `forbidden` | 403 | لا | الرمز يفتقر إلى النطاق المطلوب، أو فشل فحص `Origin` أو `Host`. |
| `model_not_found` | 404 | لا | لا نموذج محليًا بهذا المعرّف. |
| `model_not_ready` | 409 | نعم | النموذج غير محمَّل ولا يُحمَّل عند الطلب. |
| `model_load_failed` | 500 | نعم | فشل تحميل النموذج. |
| `context_length_exceeded` | 400 | لا | المدخل لا تتسع له نافذة سياق النموذج. |
| `unsupported_capability` | 400 أو 501 | لا | النموذج أو الخدمة لا يدعم ما يحتاجه الطلب. وترد نقطة النهاية الاختيارية غير المنفذة بـ 501. |
| `unsupported_protocol_version` | 426 | لا | الخدمة لا تدعم الإصدار الرئيسي المطلوب. |
| `response_not_found` | 404 | لا | لا استجابة مخزَّنة بهذا المعرّف. |
| `task_not_found` | 404 | لا | لا مهمة بهذا المعرّف. |
| `task_not_cancelable` | 409 | لا | المهمة نجحت أو فشلت أصلًا. |
| `idempotency_conflict` | 409 | لا | استُخدم مفتاح التكرار الآمن من قبل مع متن طلب مختلف. |
| `event_history_expired` | 410 | لا | الأحداث المطلوبة أقدم من مدة الاحتفاظ. |
| `rate_limited` | 429 | نعم | طلبات كثيرة جدًا. |
| `resource_exhausted` | 503 | نعم | نفدت ذاكرة الجهاز أو مورد آخر. |
| `backend_unavailable` | 503 | نعم | يتعذر الوصول إلى بيئة تشغيل النموذج. |
| `server_restarted` | 503 | نعم | أُعيد تشغيل الخدمة والمهمة غير منتهية. |
| `internal_error` | 500 | يختلف | فشل غير متوقع داخل الخدمة. |

الحقل `retryable` هو المرجع الحاكم. ويُظهر العمود أعلاه القيمة المعتادة. و**يجوز** للخدمة أن تعرّف رموزًا أخرى. و**يجب** على العميل أن يتعامل مع أي رمز لا يعرفه بحسب حالة HTTP والحقل `retryable`.

## 9.4 فحص الصحة {#health}

```http
GET /lmsp/v1/health
```

```json
{
  "status": "ready",
  "service_id": "svc_01J8M4Y8K6M5E6K6Z7Z0Y8W3M2",
  "uptime_seconds": 86420,
  "loaded_models": 1,
  "active_tasks": 2,
  "storage": "ok"
}
```

| الحقل | المعنى |
| --- | --- |
| `status` | `starting` أو `ready` أو `degraded` أو `stopping`. |
| `service_id` | معرّف الخدمة من وصف الخدمة. |
| `uptime_seconds` | الثواني منذ بدء الخدمة. |
| `loaded_models` | عدد النماذج في حالة `ready`. |
| `active_tasks` | عدد المهام التي هي `queued` أو `loading` أو `running` أو `cancelling`. |
| `storage` | `ok` أو `error`. |

تكون حالة HTTP هي `200 OK` عندما تكون `status` هي `ready` أو `degraded`، وإلا فهي `503 Service Unavailable`.

تعيد نقطة نهاية الصحة الحالة التشغيلية فحسب. و**لا يجوز** لها أن تعيد مسارات النماذج أو المطالبات أو رموز الوصول أو أي معلومات حساسة أخرى.
