Streaming
هذا المحتوى غير متوفر بلغتك بعد.
Enabling Streaming
Set stream: true in your chat completion request:
curl https://ghostmind.optdmsa.com/v1/chat/completions \ -H "Authorization: Bearer gmk_live_..." \ -H "Content-Type: application/json" \ -d '{ "model": "auto", "stream": true, "messages": [{"role": "user", "content": "Hello!"}] }'SSE Format
The response is a stream of Server-Sent Events:
data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"Hello"},"finish_reason":null}]}
data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"!"},"finish_reason":null}]}
data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: [DONE]Event Flow
- First chunk — Contains
delta.role: "assistant" - Content chunks — Contain
delta.contentwith text fragments - Final chunk — Contains
finish_reason: "stop" - [DONE] — Stream terminator
Error During Stream
If a provider or session error occurs during streaming, GhostMind emits a
structured response.failed lifecycle event — not assistant content text.
Never interpret error text as assistant content. The error is delivered
as a chunk with finish_reason: "error" and a lifecycle_event field.
Error event format
data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"error"}],"lifecycle_event":{"type":"response.failed","error":{"code":"ACCOUNT_REAUTH_REQUIRED","message":"ChatGPT session expired. Reconnect the account in the User App.","type":"account_error","http_status":403,"retryable":false}}}Machine-readable error codes
error.code | error.http_status | Meaning | retryable |
|---|---|---|---|
ACCOUNT_REAUTH_REQUIRED | 403 | ChatGPT session expired — reconnect in User App | false |
PROVIDER_RATE_LIMITED | 429 | Upstream provider rate-limited the request | true |
PROVIDER_UNAVAILABLE | 502/503 | Upstream provider returned an error or is down | true |
PROVIDER_TIMEOUT | 504 | Upstream provider did not respond in time | true |
INVALID_REQUEST | 400 | Request rejected by upstream (bad parameter) | false |
IMAGE_GENERATION_UNAVAILABLE | 503 | Image generation failed (plan/quota/feature) — the session is healthy, only the image feature failed | false |
Image generation failures
ChatGPT image generation is implicit — triggered by the user’s natural-language
prompt, not a request flag. When the account’s plan/quota cannot generate an image,
ChatGPT returns ordinary assistant text (e.g., “image creation is temporarily
unavailable”) instead of a structured image asset. GhostMind detects this pattern
and emits a IMAGE_GENERATION_UNAVAILABLE lifecycle event instead of passing the
fallback text through as a successful response.
Important: This error does not mean the session is dead. The account can still serve text/chat requests. Do not reconnect the account or mark it expired. Do not retry blindly — retrying re-triggers the same fallback and burns quota.
Client handling rules
- Stop reading the stream when you receive
lifecycle_event.type == "response.failed". - Check
error.retryable— iftrue, retry with exponential backoff. Iffalse, surface the error to the user. - Do not append
delta.contentto your assistant text buffer after aresponse.failedevent. - The stream will terminate with
data: [DONE]after the error event. - Save the
X-Request-Idheader for troubleshooting.
Client Example (JavaScript)
const response = await fetch("https://ghostmind.optdmsa.com/v1/chat/completions", { method: "POST", headers: { "Authorization": "Bearer gmk_live_...", "Content-Type": "application/json", }, body: JSON.stringify({ model: "auto", stream: true, messages: [{ role: "user", content: "Hello!" }], }),});
const reader = response.body.getReader();const decoder = new TextDecoder();let buffer = "";
while (true) { const { done, value } = await reader.read(); if (done) break;
buffer += decoder.decode(value, { stream: true }); const lines = buffer.split("\n"); buffer = lines.pop();
for (const line of lines) { if (line.startsWith("data: ")) { const data = line.slice(6); if (data === "[DONE]") return; const chunk = JSON.parse(data);
// Check for structured error event const lifecycle = chunk.lifecycle_event; if (lifecycle && lifecycle.type === "response.failed") { const err = lifecycle.error; console.error(`Stream error: ${err.code} — ${err.message}`); if (err.retryable) { // Retry with backoff } return; // Stop processing }
const content = chunk.choices?.[0]?.delta?.content; if (content) process.stdout.write(content); } }}Next Steps
- Chat Completions API — API reference
- Handling Errors — Error handling