JSON parse error на части ответа
Буферизуйте данные до границы SSE-события; сетевой chunk не гарантирует полный JSON.
Как читать потоковые ответы Chat Completions, Responses и Messages, отменять запрос и подтверждать завершение по итоговой квитанции.
Базовый адрес — https://tokenmost.ru/v1. Создайте ключ в личном кабинете, выберите модель в каталоге и отправьте первый запрос. Методы, которые ещё не доступны, отмечены отдельно.
При streaming сервер отправляет события Server-Sent Events по мере генерации. Частичный текст улучшает интерфейс, но не является доказательством завершения: клиент должен дождаться терминального события и итоговой квитанции.
const response = await fetch(url, { ...options, signal: controller.signal });
if (!response.ok || !response.body) throw new Error(`HTTP ${response.status}`);
const reader = response.body.getReader();
const decoder = new TextDecoder();
for (;;) {
const { value, done } = await reader.read();
if (done) break;
const chunk = decoder.decode(value, { stream: true });
// Передайте chunk в SSE-парсер; не делите JSON по сетевым чанкам.
}Укажите TOKENMOST_BASE_URL=https://tokenmost.ru/v1, ключ проекта и точный ID модели из каталога. Пример отправляет запрос в публичный API и может списать средства с баланса по тарифу модели.
curl -N "https://tokenmost.ru/v1/chat/completions" \
-H "Authorization: Bearer $TOKENMOST_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: stream-example-0001" \
-d '{
"model": "MODEL_ID_FROM_CATALOG",
"messages": [{"role": "user", "content": "Ответь по пунктам."}],
"max_tokens": 128,
"stream": true
}'Проверяйте streaming после обычного запроса. Частичный текст нельзя считать подтверждённым результатом без финального события и квитанции.
Один JSON может быть разрезан между чтениями, а несколько событий могут прийти одним chunk. Используйте буфер и разбирайте полные SSE-события, а не каждый value отдельно.
Chat, Responses и Messages используют разные имена событий. Клиент должен понимать выбранный контракт и проверять финальную квитанцию, а не только маркер конца текста.
Отмена до отправки освобождает резерв. Разрыв после начала генерации может оставить исход неизвестным; автоматический повтор с новым ключом запрещён.
Буферизуйте данные до границы SSE-события; сетевой chunk не гарантирует полный JSON.
Не добавляйте итоговый объект поверх уже обработанных delta и учитывайте replay.
Ждите терминальное событие и итоговую квитанцию биллинга.
Передайте AbortSignal в fetch и закройте reader при отмене страницы или задачи.
Сохраните Idempotency-Key и проверьте историю; не создавайте новый платный запрос автоматически.