ТЭ Тэрил

Документация API

Ход: одна просьба клиента

Ход — это единица работы сервиса. Внутри него ассистент читает разговор, пишет изменение заказа, собирает его геометрией и проверяет; не сошлось — переспрашивает себя до трёх раз. Поэтому ход идёт десятки секунд, иногда минуты, и отвечает сервис заявкой, а не результатом.

POST /v1/conversations/{id}/turns  →  202 {turn:{id, state:"queued"}}
                                        │
                     queued → running → done | stopped | failed
                                        │
                        вебхук turn.completed / .stopped / .failed

Один ход на разговор

Пока идёт ход, второй запрос по тому же разговору отвечает 409 conflict_busy. Это не очередь и не защита от нагрузки: следующая просьба человека почти всегда зависит от того, чем кончилась предыдущая, и собирать их параллельно значило бы собирать по устаревшему заказу.

Если клиент дописал, пока ход идёт, — у вас два честных пути: дождаться исхода и послать дописанное следующим ходом либо оборвать текущий (POST /v1/turns/{id}/stop) и послать просьбу целиком заново. Остановленный ход денег не стоит.

Идемпотентность

Заголовок Idempotency-Key — ваш id сообщения:

Idempotency-Key: msg-991

Повтор с тем же ключом возвращает тот же ход. Без заголовка повтор — это второй ход и вторые деньги. Ключ уникален в пределах разговора.

Исход

{
  "status": "built",
  "note": "Собрал кухню 3 метра: тумба под мойку 800, посудомойка 600, ящики. Сверху четыре навесных шкафа.",
  "applied": 9,
  "turn": 1,
  "order_id": "lead-7781",
  "findings": [
    { "code": "GEO-GAP", "severity": "warning", "path": "низ.шкаф2",
      "msg": "…", "fixHint": "…" }
  ],
  "why": "Ряд не сошёлся: мебели на 925 мм больше, чем стены…",
  "usage": { "model": "…", "attempts": 1, "prompt_tokens": 12400,
             "completion_tokens": 900, "cost_usd": 0.0231, "ms": 41200, "coins": 1 }
}
ПолеЧто это
statusЧем кончилось — таблица ниже
noteОтвет клиенту, по-русски. Единственное, что ему показывают
appliedСколько узлов заказа изменилось. 0 — заказ не тронут
turnНомер хода в разговоре
findingsНаходки проверки: code, severity (error/warning), path, msg, fixHint?. Есть не всегда
whyПочему не вышло — по-русски, одной фразой. Только у неудачных ходов
usageЧем обошёлся ход. coins — сколько монет он стоит

Статусы

statusЧто случилосьЧто делать
builtМебель собрана, заказ изменилсяПоказать note и обновить картинку
parsedПриложенный чертёж прочитан вслух; мебель НЕ собранаПоказать note — это разбор. Клиент поправляет словами или говорит «собирай»
questionАссистент ответил словами: спросил недостающее или отказалсяПоказать note и ждать ответа клиента. Картинка остаётся прежней
rejectedПросьба спорит с нормой производства; переспрашивать нечемПоказать note и why. Решение за человеком: другое число или другой состав
failedХод не состоялся: модель не поняла, оборвалась связьКлиенту ничего не показывать. Предложить сказать иначе

questionнормальный исход, а не ошибка. Ассистенту велено спрашивать то, чего он не может знать: вдоль какой стены мебель, какой длины стена, какая техника встраивается, что мешает в комнате. Спрашивает он по одному-два пункта за ход, а не анкетой.

Наоборот, то, что решается правилами (наполнение тумбы, сторона открывания, высота полки), он не спрашивает, а собирает по умолчанию и называет это строкой в note.

Картинку не отменяет ни один статус. Вид принадлежит разговору, а не ходу: пока в разговоре что-то собрано, GET .../render отдаёт его после ЛЮБОГО хода. built значит «картинка изменилась, возьмите новую», а не «только теперь она есть»: после question и rejected в силе прежняя, и ссылку на неё можно выписать заново хоть тем же запросом.

Картинки

К просьбе прикладывается до двух картинок, каждая не больше 5 МБ:

{ "text": "собери по этому плану",
  "images": [{ "mime": "image/png", "b64": "iVBORw0…" }] }

Форматы: png, jpeg, webp, gif.

Чертёж сперва читается вслух. На картинку с составом (модули вдоль стены, в порядке и с размерами) ассистент отвечает не мебелью, а разбором по-русски: что стоит у какой стены, в каком порядке, на скольких миллиметрах, какие числа он взял не с чертежа и чего не разобрал. Статус такого хода — parsed, заказ при этом не меняется. Клиент правит разбор словами («вторая стена 3400», «бутылочницы нет») или говорит «собирай» — и следующий ход собирает всё разом.

Двух картинок хватает по сроку хода: чертёж разбирает медленная модель, и ход с картинкой идёт три-пять минут.

Мелкая картинка (меньше 600 пикселей по короткой стороне) не отбивается, но читается плохо: швы в пару пикселей превращают семь створок в пять, и шкаф по такому разбору собирается без единой ошибки. Есть крупнее — шлите крупнее.

Картинка помнится ровно один следующий ход. Нужна снова — приложите снова.

Деньги

ЧтоСколько
Просьба словами1 монета
Просьба с картинкой8 монет
question, rejected, failed, остановленный ход0

Списывается ход, который дал работу: built и parsed.

Единственное исключение — ход с картинкой: он списывает свои восемь монет всегда, когда ассистент ответил, даже если в заказе не изменилось ничего. Работа там сделана разбором чертежа, и делает её самая дорогая модель сервиса. Ход с картинкой, который не состоялся вовсе (модель не ответила, связь оборвалась), не списывается и здесь.

Число картинок на цену не влияет: дорог разбор, а не изображение.

Не хватает монет — 402 quota_exceeded ещё до вопроса модели. В details лежит reason: out_of_coins, period_over, canceled, no_subscription.

Почём монета и как она покупается объёмом — в pricing.md.

Сроки

Ход живёт до четырёх минут; не уложился — failed. Разговор живёт 30 дней с последней просьбы и продлевается каждым ходом.

Если сервис перезапустили посреди хода, ход придёт failed вебхуком, а разговор освободится — «вечно занятых» разговоров не бывает.

Эта страница разметкой: /docs/api/turns.md · вся документация одним файлом: /llms-full.txt