# المهام غير المتزامنة

> كيف يشغّل LMSP عمليات التوليد الطويلة بوصفها مهام محفوظة، مع إنشاء المهام وآلة حالاتها والإلغاء الآمن عند التكرار وتدفقات الأحداث وسياسات إعادة التشغيل للمهام غير المنتهية.

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

## 7.1 إنشاء مهمة {#create}

ينشئ العميل مهمة بإرسال طلب الاستجابة الذي يريد تشغيله، ملفوفًا في مغلّف مهمة. ويُنصح باستخدام ترويسة `Idempotency-Key` ([القسم 9.2](https://madeforagent.com/ar/lmsp/1.0/common-rules.md#idempotency)).

```http
POST /lmsp/v1/tasks
Authorization: Bearer <token>
Idempotency-Key: 01J8M7C4Y3N5P8R2T6V9X1Z4BH
```

```json
{
  "type": "response",
  "input": {
    "model": "qwen3:14b-q4_k_m",
    "input": [
      {
        "type": "message",
        "role": "user",
        "content": [
          {
            "type": "input_text",
            "text": "Write a long report."
          }
        ]
      }
    ]
  },
  "on_restart": "fail"
}
```

| الحقل | إلزامي | المعنى |
| --- | --- | --- |
| `type` | نعم | `response`، وهو نوع المهمة الوحيد في 1.0. |
| `input` | نعم | طلب استجابة، تمامًا كما في `POST /lmsp/v1/responses`. ويُتجاهل حقله `stream`. |
| `on_restart` | لا | `fail` (الافتراضي) أو `retry` أو `resume`. انظر [القسم 7.5](https://madeforagent.com/ar/lmsp/1.0/tasks.md#restart). |

**يجب** على الخدمة أن تحفظ المهمة قبل أن ترد. ثم تعيد:

```http
HTTP/1.1 202 Accepted
```

```json
{
  "id": "task_01J8M8R5X3V7B2N4Q9T1W6Y0ZC",
  "object": "task",
  "type": "response",
  "status": "queued",
  "created_at": 1794200100,
  "updated_at": 1794200100,
  "response_id": "resp_01J8M8R5X4B9D2F6H1K3N7Q0ZW",
  "events_url": "/lmsp/v1/tasks/task_01J8M8R5X3V7B2N4Q9T1W6Y0ZC/events",
  "on_restart": "fail",
  "response": null,
  "error": null
}
```

| حقل المهمة | المعنى |
| --- | --- |
| `id` | معرّف المهمة، مثل `task_...`. |
| `object` | دائمًا `"task"`. |
| `type` | `response`. |
| `status` | الحالة الحالية ([القسم 7.2](https://madeforagent.com/ar/lmsp/1.0/tasks.md#states)). |
| `created_at`, `updated_at` | أوقات بالثواني منذ حقبة Unix. |
| `response_id` | معرّف الاستجابة التي تنتجها المهمة. ويُسند عند إنشاء المهمة. |
| `events_url` | مسار تدفق الأحداث. موجود عندما تكون القدرة `event_resume` هي `true`. |
| `on_restart` | سياسة إعادة التشغيل للمهمة. |
| `response` | كائن الاستجابة عندما تكون `status` هي `succeeded`، وإلا `null`. |
| `error` | كائن مشكلة ([القسم 9.3](https://madeforagent.com/ar/lmsp/1.0/common-rules.md#errors)) عندما تكون `status` هي `failed`، وإلا `null`. |

يعيد `GET /lmsp/v1/tasks/{task_id}` كائن المهمة. والعملاء الذين لا يستخدمون تدفقات الأحداث يستعلمون من هذه النقطة دوريًا. والمعرّف المجهول يعطي `404` مع `task_not_found`. وتبدو المهمة المنتهية هكذا:

```json
{
  "id": "task_01J8M8R5X3V7B2N4Q9T1W6Y0ZC",
  "object": "task",
  "type": "response",
  "status": "succeeded",
  "created_at": 1794200100,
  "updated_at": 1794200162,
  "response_id": "resp_01J8M8R5X4B9D2F6H1K3N7Q0ZW",
  "events_url": "/lmsp/v1/tasks/task_01J8M8R5X3V7B2N4Q9T1W6Y0ZC/events",
  "on_restart": "fail",
  "response": {
    "id": "resp_01J8M8R5X4B9D2F6H1K3N7Q0ZW",
    "object": "response",
    "created_at": 1794200100,
    "status": "completed",
    "model": "qwen3:14b-q4_k_m",
    "output": [
      {
        "id": "msg_01J8M8R6A2C5E8G1J4M7P0S3VY",
        "type": "message",
        "role": "assistant",
        "content": [
          {
            "type": "output_text",
            "text": "Local model services make on-device inference a shared, discoverable utility..."
          }
        ]
      }
    ],
    "usage": {
      "input_tokens": 12,
      "output_tokens": 1480,
      "total_tokens": 1492
    },
    "error": null,
    "incomplete_details": null
  },
  "error": null
}
```

## 7.2 آلة الحالات {#states}

```text
queued --> loading --> running --> succeeded
  |           |           |
  |           |           +--> failed
  |           |           +--> cancelling --> cancelled
  |           +--------------> failed
  +--------------------------> cancelled
```

| الحالة | المعنى | الحالات التالية |
| --- | --- | --- |
| `queued` | مقبولة ومحفوظة، تنتظر البدء. | `loading`، `cancelled`، `failed` |
| `loading` | يجري تحميل النموذج. | `running`، `cancelling`، `failed` |
| `running` | النموذج يولّد. | `succeeded`، `failed`، `cancelling` |
| `cancelling` | طُلب الإلغاء، ولم تتوقف الواجهة الخلفية بعد. | `cancelled` |
| `succeeded` | نهائية. الاستجابة مكتملة. | لا شيء |
| `failed` | نهائية. | لا شيء |
| `cancelled` | نهائية. | لا شيء |

الحالات النهائية هي `succeeded` و`failed` و`cancelled`. و**لا يجوز** أن تتغير مهمة في حالة نهائية مرة أخرى. والمهمة التي تنتهي استجابتها بحالة `incomplete`، مثلًا عند حد الرموز، تكون `succeeded`.

كل انتقال ذري، فلا تكون المهمة ملغاة ومكتملة معًا أبدًا. ويفوز الانتقال الذي يُثبَّت أولًا.

## 7.3 الإلغاء {#cancel}

```http
POST /lmsp/v1/tasks/{task_id}/cancel
```

تعيد الخدمة `200 OK` وكائن المهمة الحالي. وتصبح المهمة `queued` في حالة `cancelled` فورًا. وتصبح المهمة `loading` أو `running` في حالة `cancelling` إلى أن تتوقف الواجهة الخلفية، ثم `cancelled`.

**يجب** أن يكون الإلغاء آمنًا عند التكرار (idempotent). فإلغاء مهمة هي أصلًا `cancelling` أو `cancelled` يعيد المهمة الحالية ولا يُنتج خطأً جديدًا.

وإلغاء مهمة هي أصلًا `succeeded` أو `failed` يُرد عليه بـ `409` مع `task_not_cancelable`. والمعرّف المجهول يعطي `404` مع `task_not_found`.

## 7.4 تدفقات الأحداث {#events}

```http
GET /lmsp/v1/tasks/{task_id}/events
Accept: text/event-stream
```

نقطة النهاية هذه اختيارية. وهي متاحة عندما تكون القدرة `event_resume` هي `true`.

- الأحداث هي أحداث الاستجابة الواردة في [القسم 6.3](https://madeforagent.com/ar/lmsp/1.0/responses.md#streaming)، للاستجابة التي تنتجها المهمة. ويتبع الترقيم والاستئناف [القسم 6.4](https://madeforagent.com/ar/lmsp/1.0/responses.md#reconnection).
- يبدأ التدفق بـ `response.created` الذي يُسجَّل عند قبول المهمة. وينتهي بحدث أخير واحد يطابق النتيجة: `response.completed` أو `response.incomplete` أو `response.failed` أو `response.cancelled`.
- العميل الذي يتصل متأخرًا يتلقى أولًا الأحداث التي فاتته، ثم الأحداث المباشرة. وتغلق الخدمة التدفق بعد الحدث الأخير.
- تُحفظ الأحداث طوال مدة احتفاظ ([القسم 11.2](https://madeforagent.com/ar/lmsp/1.0/persistence.md#rules)). والأحداث الأقدم تعطي `410 Gone` مع `event_history_expired`.

## 7.5 دلالات إعادة التشغيل {#restart}

يحدد `on_restart` ما يحدث لمهمة غير منتهية عند إعادة تشغيل الخدمة:

| القيمة | السلوك |
| --- | --- |
| `fail` | الافتراضي. تعلّم الخدمة المهمة غير المنتهية بالحالة `failed`، مع رمز الخطأ `server_restarted`. |
| `retry` | تشغّل الخدمة المهمة من جديد من البداية. |
| `resume` | تتابع الخدمة من لقطة حالة. ولا يُسمح بذلك إلا عندما تدعم الواجهة الخلفية صراحةً لقطات قابلة للاستئناف. وإلا يُرفض طلب الإنشاء بـ `400` مع `unsupported_capability`. |

المهمة التي تكون `cancelling` عند إعادة تشغيل الخدمة تُكمل إلغاءها وتصبح `cancelled`، أيًّا كانت سياستها.

لا يُنصح بـ `retry` افتراضيًا، لأن المهمة ربما شغّلت أدوات بالفعل أو أحدثت آثارًا جانبية خارجية. و**يجب** على العميل الذي يختار `retry` أن يقرنه بـ `Idempotency-Key` وأن يجعل استدعاءات أدواته آمنة عند التكرار.
