عقد SSE wire
تقوم AI chat endpoints ببث Server-Sent Events (text/event-stream).
توثق هذه الصفحة عقد control-stream المستخدم بواسطة
POST /chat/control/stream. ومصدر الحقيقة هو parser + types داخل
@kaleidr/inference-ui (packages/inference-ui/src/control/sse.ts و
types.ts). إذا كنت تستخدم kaleidr.js، فإن chat bundle يقوم بالتحليل نيابة عنك —
ولا تحتاج هذه الصفحة إلا لبناء custom client.
تستخدم /chat/summary/stream و/chat/button/stream عقود SSE
مختلفة ولا تشملها هذه الصفحة. لا تعِد استخدام control-stream
parser مع تلك endpoints.
قاعدة التوافق
يجب على العملاء تجاهل أسماء events غير المعروفة. قد تتم إضافة events جديدة إلى العقد المستقر دون version bump. أما downstream events الموثقة في جدول "diagnostic / experimental" أدناه فهي ليست ضمن contract — ويتجاهلها العميل الرسمي وقد تختفي.
الأحداث المستقرة
Payloads هي ما يفترضه control parser. لا يحتوي start على field باسم phase
(فهو يظهر فقط في phase events).
event: | Payload | Meaning |
|---|---|---|
| (unnamed) | { text } | prose token تدريجي. وقد يحتوي على markers بصيغة [[Place]]. |
phase | { type: "phase", phase, session_id } | lifecycle قبل stream. |
start | { type: "start", session_id, purpose? } | تم فتح stream. |
place | { name, coordinates: { lat, lng }, address?, category?, source?, id? } | مكان تم حله (merge-by-name → map pin). وتشير source: "vendor" إلى place من البيانات التي رفعتها المؤسسة. |
place_linked | place fields + is_update? | إثراء place تم إرساله مسبقًا. |
early_actions | { type: "early_actions", actions: [ { type, payload } ], places_count?, is_partial? } | Map actions (fitBounds / route / highlight) قبل اكتمال الرد. |
prompt_options | { type: "prompt_options", schema_version, kind, question, allow_free_text, options: [ { label, send_text } ] } | خيارات إزالة الغموض — اعرضها كخيارات قابلة للنقر وأرسل send_text للخيار كرسالة المستخدم التالية. |
route_clear | {} | مسح جميع overlays قبل وصول routes جديدة. Stable. |
route | { type: "route", schema_version, id?, profile, origin, destination, primary, alternatives[], comparison[], stops?, connectors?, color?, label? } | turn متعلق بالرحلة — route محسوبة من engine، تُرسل قبل prose لكي تستطيع الخريطة الرسم أثناء streaming للإجابة. |
quota | { type: "quota", product, meter, tier, used, limit, reset_at, period } | meter أثناء stream — اعرض الميزانية المتبقية. |
end | { type: "end", full_text, places[], actions[], question_type, response_time, total_tokens? } | terminal envelope — النتيجة الكاملة. |
error | { type: "error", message, code?, partial_text? } | خطأ نهائي. |
: keep-alive | comment line | Proxy keep-alive (~10s). تجاهله. |
تمت الإزالة: grounding (2026-09-05). ما زال Grounding يؤثر في الإجابة لكنه
لا يضع frame على wire.
تشخيصي / تجريبي (غير ضمن العقد)
هذه implementation details يتم إرسالها. ويتجاهلها العميل الرسمي؛ لا تعتمد عليها.
event: | Payload | Notes |
|---|---|---|
debug | { scope, … } | تشخيص داخلي. قد يتغير أو يختفي. |
place_name_found | { name, is_early? } | غير ضمن contract؛ يتجاهله العميل الرسمي. |
Tokens والبيانات المنظمة
تقوم events غير المسماة ببث prose عادية. وقد تحمل [[Place]] markers
ضمن النص حيث تتم الإشارة إلى place (مثل …cafes near [[Louvre]]…) —
أزلها للحصول على display نظيف، أو تجاهل prose تمامًا وشغّل
UI من structured events.
تصل structured data كـ events، وليس داخل prose أبدًا. تظهر resolved
places عبر place (وplace_linked للـ metadata المتأخرة) أثناء
geocode؛ وتصل map actions عبر early_actions؛ وتصل routes عبر route
بعد route_clear؛ أما authoritative final payload فهو event باسم end.
عادةً ما يعرض client pins من place events عند وصولها ويعتبر
end مصدر الحقيقة.
عميل بسيط
const res = await fetch(`${API}/inference-api/b2b/v1/chat/control/stream`, {
method: 'POST',
headers: { 'X-Api-Key': key, 'Content-Type': 'application/json', Accept: 'text/event-stream' },
body: JSON.stringify({ messages: [{ role: 'user', content: 'cafes near the Louvre' }] }),
});
const reader = res.body.getReader();
// …decode chunks, split on \n\n, parse `event:` + `data:` lines
// IMPORTANT: ignore any unknown event name (forward-compat rule above).
راجع Endpoints لمعرفة request bodies و Errors للتعامل مع حالات الفشل.