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

7.1 إنشاء مهمة

ينشئ العميل مهمة بإرسال طلب الاستجابة الذي يريد تشغيله، ملفوفًا في مغلّف مهمة. ويُنصح باستخدام ترويسة Idempotency-Key (القسم 9.2).

POST /lmsp/v1/tasks
Authorization: Bearer <token>
Idempotency-Key: 01J8M7C4Y3N5P8R2T6V9X1Z4BH
{
  "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.

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

HTTP/1.1 202 Accepted
{
  "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).
created_at, updated_at أوقات بالثواني منذ حقبة Unix.
response_id معرّف الاستجابة التي تنتجها المهمة. ويُسند عند إنشاء المهمة.
events_url مسار تدفق الأحداث. موجود عندما تكون القدرة event_resume هي true.
on_restart سياسة إعادة التشغيل للمهمة.
response كائن الاستجابة عندما تكون status هي succeeded، وإلا null.
error كائن مشكلة (القسم 9.3) عندما تكون status هي failed، وإلا null.

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

{
  "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 آلة الحالات

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 الإلغاء

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 تدفقات الأحداث

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

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

  • الأحداث هي أحداث الاستجابة الواردة في القسم 6.3، للاستجابة التي تنتجها المهمة. ويتبع الترقيم والاستئناف القسم 6.4.
  • يبدأ التدفق بـ response.created الذي يُسجَّل عند قبول المهمة. وينتهي بحدث أخير واحد يطابق النتيجة: response.completed أو response.incomplete أو response.failed أو response.cancelled.
  • العميل الذي يتصل متأخرًا يتلقى أولًا الأحداث التي فاتته، ثم الأحداث المباشرة. وتغلق الخدمة التدفق بعد الحدث الأخير.
  • تُحفظ الأحداث طوال مدة احتفاظ (القسم 11.2). والأحداث الأقدم تعطي 410 Gone مع event_history_expired.

7.5 دلالات إعادة التشغيل

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

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

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

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