История диалога
Используйте историю для восстановления переписки в собственном интерфейсе. Идентификаторы секции, пользователя и диалога должны совпадать с исходными запросами генерации. Web-виджет 1.42 вызывает метод при включённом resumeDialog и при выборе разговора в списке dialogHistory; настройки виджета по умолчанию выключены.
Для гостевого ресурса добавьте к запросу Authorization: Bearer gst_.... Пример с page без заголовка ниже относится к прежнему режиму. Правила передачи токена и общие ошибки: Гостевые токены.
Для выбора разговора используйте список диалогов. Метод /shopping/history возвращает сообщения одного диалога и поддерживает два режима: страницы page/limit и
POST /shopping/history
Чтобы восстановить сообщения после перезагрузки страницы или повторного открытия чата, вызовите:
POST https://shopping-assistant-api.gravityfield.ai/shopping/history
Content-Type: application/json
Endpoint возвращает только сообщения покупателя и ответы Shopping Assistant. Внутренние system-сообщения, вызовы инструментов и служебные данные в ответ не попадают.
Запрос истории
Без paginationMode действует прежняя пагинация page/limit:
curl --request POST \
--url 'https://shopping-assistant-api.gravityfield.ai/shopping/history' \
--header 'Content-Type: application/json' \
--data '{
"tenant_id": "demo-section",
"resourceId": "demo-user",
"threadId": "thread-8f2b1c",
"page": 1,
"limit": 50
}'
История доступна только при точном совпадении tenant_id, resourceId и threadId. Для гостевого запроса диалог должен принадлежать сессии предъявленного токена. Другой токен с тем же resourceId не даёт доступ к прежнему диалогу. Если диалог не найден, скрыт через «Убрать из истории» или принадлежит другой секции, пользователю или сессии, API возвращает 404.
Храните threadId вместе с sessionId гостевой сессии. После повторной регистрации начинайте новый диалог: история и память прежней сессии не переносятся. В ответах API поле resourceId, включая сообщения в items, сохраняет внешний идентификатор Gravity Field.
Ответ
{
"threadId": "thread-8f2b1c",
"resourceId": "demo-user",
"messageFormat": "plain_text",
"items": [
{
"id": "shopping:user:4f8c...",
"role": "user",
"content": "Помогите выбрать ноутбук для учёбы",
"createdAt": "2026-07-28T10:00:00.000Z"
},
{
"id": "shopping:assistant:8a21...",
"role": "assistant",
"createdAt": "2026-07-28T10:00:01.250Z",
"threadId": "thread-8f2b1c",
"resourceId": "demo-user",
"context": {
"intent": "product-selection",
"scenario": { "id": "laptop-selection", "version": 1 },
"mode": "clarify"
},
"response": {
"contents": [
{
"type": "message",
"value": "Какой у вас бюджет и нужна ли большая диагональ экрана?"
}
],
"ui": {
"suggests": [
"До 60 000 ₽, компактный",
"До 80 000 ₽, большой экран",
"Помогите определиться с бюджетом"
]
}
},
"feedback": {
"reaction": "like"
},
"responseLatencyMs": 1250
}
],
"pagination": {
"page": 1,
"limit": 50,
"hasMore": false
}
}
Элементы в items отсортированы по времени создания от ранних к поздним в пределах страницы:
- для
role: "user"полеcontentимеет тот же формат, что в запросе/shopping/generate: строка для текста или массив блоковtextиimage; - для
role: "assistant"полеresponseимеет тот же контракт, что ответ/shopping/generate;idсообщения используйте какmessageIdдля/shopping/feedback; - у сообщения ассистента рядом с
responseнаходитсяcontextс контекстом сценария; у пользовательских сообщений этого поля нет; - поле
feedback.reactionв сообщении ассистента содержит текущую оценку пользователя:like,dislikeилиnull; - дополнительно в сообщении ассистента могут присутствовать
responseLatencyMsиevents; - при пагинации
page/limit, еслиpagination.hasMoreравноtrue, запросите следующую страницу, увеличивpageна1.
Поле messageFormat верхнего уровня задаёт формат текста ответов ассистента: plain_text или markdown. Применяйте к восстановленным ответам тот же способ отображения, что и к новым ответам генерации.
Для сообщения с изображением history endpoint возвращает блок image с Base64. Для отображения превью соберите data URL из source.mediaType и source.data, но не передавайте это сообщение повторно в /shopping/generate.
const previewUrl =
`data:${image.source.mediaType};base64,${image.source.data}`;
Ответ содержит заголовок Cache-Control: no-store. Не сохраняйте историю в общем или публичном кеше на клиентской стороне.
Контекст и восстановление интерфейса
items[].context у ответа ассистента имеет тип ShoppingResponseContext | null, как в контракте генерации. Он относится к этому сообщению и сохраняет ID и версию выбранного тогда плейбука. Обновление или архивация плейбука не меняет контекст старого ответа. Значения сценария в примере условные.
Восстанавливайте UI из последнего сообщения ассистента выбранного диалога. Если его context или scenario равен null, ID неизвестен либо поле отсутствует в старой версии сервера, показывайте обычный чат. Не ищите более ранний ответ с непустым сценарием: так можно вернуть интерфейс уже завершившегося подбора. Для handoff и refuse используйте правила обработки режима.
У старых сообщений без полных корректных метаданных возвращается context: null. При подгрузке более ранних страниц не переключайте UI на их сценарии. Для сопоставления с новым ответом используйте items[].id — это assistantMessageId из генерации.
Загрузка с конца
Для открытия чата с последними сообщениями передайте paginationMode: "backward" без page и before. В примере GUEST_ACCESS_TOKEN содержит полный токен сохранённой сессии, а USER_UID — тот же user.uid или user.custom, с которым зарегистрирована сессия:
curl --request POST \
--url 'https://shopping-assistant-api.gravityfield.ai/shopping/history' \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer $GUEST_ACCESS_TOKEN" \
--data '{
"tenant_id": "demo-section",
"resourceId": "USER_UID",
"threadId": "thread-8f2b1c",
"paginationMode": "backward",
"limit": 50
}'
Первый запрос возвращает последние limit сообщений. Допустимы значения от 1 до 100, по умолчанию — 50. Формат items, товарных карточек, изображений, оценок и messageFormat остаётся тем же. Меняется только объект пагинации:
{
"pagination": {
"limit": 50,
"hasMore": true,
"nextCursor": "opaque-cursor"
}
}
Это фрагмент ответа; opaque-cursor обозначает курсор из фактического ответа API.
Для загрузки более ранних сообщений отправьте тот же запрос, добавив before со значением pagination.nextCursor:
{
"tenant_id": "demo-section",
"resourceId": "USER_UID",
"threadId": "thread-8f2b1c",
"paginationMode": "backward",
"before": "opaque-cursor",
"limit": 50
}
Внутри каждой страницы сообщения идут от старых к новым. Добавляйте предыдущую страницу сверху, объединяя сообщения по id. Пагинация опирается на время и ID сообщения, поэтому новые сообщения не сдвигают границу уже полученной страницы.
Если более ранних сообщений нет, API возвращает hasMore: false и nextCursor: null. Для пустой страницы items равен []. Не отправляйте before: null — для первого запроса поле нужно пропустить.
Курсор привязан к секции, владельцу истории и диалогу; в гостевом режиме — к текущей сессии. Не разбирайте и не изменяйте его, не используйте курсор списка диалогов вместо курсора сообщений. Неверный курсор возвращает 400 INVALID_CURSOR. Поле page вместе с backward, before без backward или неизвестный paginationMode также приводят к 400.
Для продолжения разговора передайте в генерацию только новое сообщение с прежним threadId. Загруженную историю повторно отправлять не нужно.