Раздел нужен, чтобы понимать, когда агенту нужно просто время, когда пора нажать Stop, а когда диалог пришлось разблокировать вручную.
Два разных состояния, которые легко спутать
Подозрение на зависание и блокировка диалога выглядят похоже, но означают разное.
- Подозрение на зависание означает, что от агента долго нет событий, и приложение пока не знает, жив ход или нет.
- Подозрение ничего не прерывает само: решение остаётся за вами, а ход на сервере может продолжаться прямо сейчас.
- Блокировка диалога означает, что ход потерян настолько, что отправлять в него новые сообщения опасно.
- При блокировке приложение не отправляет ни очередь, ни новое сообщение и ждёт, пока вы нажмёте Unlock.
- Подозрение снимается само, как только агент снова подаст признаки жизни: плашка исчезает без всяких действий с вашей стороны.
- Блокировка сама не проходит: её снимает либо подтверждение окончания хода, либо ваша кнопка Unlock.
Когда появляется подозрение на зависание
Приложение считает признаком жизни любое событие хода: текст, размышления, запуск команды, вызов инструмента, счётчик токенов. Как только такое событие приходит, отсчёт тишины начинается заново с нуля.
- Полная тишина длиной четыре минуты считается подозрительной и включает сверку хода с сервером.
- Сверка спрашивает у сервера статус последнего хода и сравнивает его с тем, что видит приложение.
- Сторож смотрит на состояние хода каждые тридцать секунд, а не постоянно.
- Проверка не чаще одного раза в две минуты, поэтому плашка может висеть заметно дольше первой сверки.
- Пока в ленте висит открытый вопрос агента, подозрение не возникает: тишина ожидаема, ведь ход специально ждёт вашего ответа.
- Пока план ждёт вашего одобрения, подозрение не возникает по той же причине: ход уже закончился и ждёт решения.
- Пока идёт сжатие переписки, подозрение не возникает: сжатие идёт отдельным ходом без единого события.
- Пока агент выполняет ещё не законченную команду, подозрение не возникает: команда может молча работать долго, и это нормально.
Плашка в ленте
Плашка появляется в ленте над сообщениями и всегда оформлена одинаково: жёлтый фон, треугольник с восклицательным знаком и подпись. Подпись всегда начинается со слова WARNING, а дальше идёт объяснение, что именно случилось.
- При подозрении текст плашки сообщает, что агент не отвечает, и показывает, сколько минут прошло с начала тишины.
- При блокировке текст плашки сообщает, что ход на сервере был потерян, и напоминает, что сообщения стоят в очереди до разблокировки.
- Кнопки у двух состояний разные: при подозрении это Check и Stop, при блокировке остаётся одна кнопка Unlock.
- Плашка живёт в ленте, а не поверх неё, поэтому она прокручивается вместе с сообщениями.
- Плашка встаёт после карточек вопросов и разрешений, а перед сообщениями и ответами агента.
- Число минут округляется вниз до целых, но показывается хотя бы одна минута, поэтому плашка никогда не пишет ноль минут.
Кнопка Check
Кнопка Check отвечает на один вопрос: продолжает ли агент работать или ход уже закончился, а приложение просто не получило об этом событие.
- Check делает ровно то же, что и автоматическая сверка, но не ждёт двухминутной паузы.
- После нажатия кнопка сразу спрашивает у сервера статус последнего хода и смотрит на ответ.
- Если сервер отвечает, что ход ещё идёт, приложение ничего не меняет: подозрение остаётся, а прерывание предлагает кнопка Stop.
- Если сервер отвечает, что ход закончен, прерван или упал, приложение закрывает ход у себя и отправляет накопленную очередь.
- Если сервер отвечает, что хода нет вообще, приложение делает то же самое: закрывает ход локально.
- Если сервер ответил, что такого хода нет, приложение тоже считает ход закрытым и освобождает очередь.
- Если запрос не дошёл до сервера, приложение ничего не решает и повторит проверку позже.
- Check работает только пока ход ещё числится активным: если ход уже закрыт, кнопка ничего не делает.
Кнопка Stop
Кнопка Stop прерывает текущий ход агента и освобождает диалог для новых сообщений. Такая же кнопка есть в поле ввода под лентой, и она работает одинаково.
- Stop отправляет серверу команду преривания хода и сразу гасит саму кнопку, чтобы второе нажатие не прошло.
- Пока прерывание в работе, кнопка Stop в поле ввода не нажимается: она выглядит погасшей и ждёт ответа сервера.
- Если ход ещё только стартует, приложение ждёт его идентификатор и прерывает сразу, как только тот появился.
- Ожидание идентификатора длится до трёх секунд с проверкой каждые сто миллисекунд.
- Если за эти секунды ход так и не начался, приложение просто закрывает ход у себя, чтобы индикаторы не висели.
- Если сервер отвечает, что активного хода у него нет, приложение закрывает ход локально без дополнительных действий.
- Если команда прерывания не дошла до сервера, приложение закрывает ход локально и блокирует диалог: ход на сервере мог остаться в работе.
- После команды прерывания приложение двадцать секунд ждёт подтверждения, что ход действительно закончился.
- Если через двадцать секунд сервер всё ещё пишет, что ход идёт, приложение оставляет локальное состояние как есть и ждёт дальше.
- Если через двадцать секунд хода на сервере уже нет, приложение закрывает его локально, и тогда уходят индикаторы работы и освобождается очередь.
- Долгие ходы обрывать не нужно: если агент молчит, но сервер пишет, что ход в работе, кнопка Stop не поможет.
Блокировка диалога
Блокировка появляется не от долгого молчания, а только когда ход потерян технически.
- Единственная причина блокировки: команда прерывания не дошла до сервера, а сам ход при этом ещё числится работающим.
- Блокировка помнит конкретный диалог: застрявший ход одного диалога не мешает работать остальным.
- Пока диалог заблокирован, отправка сообщений в него не уходит, даже если вы напишете в поле ввода и нажмёте Send.
- Сообщение при блокировке встаёт в локальный буфер, а не в очередь на стороне агента, и ждёт разблокировки.
- Строка статуса под лентой пишет thread blocked красным цветом, чтобы состояние было видно и без плашки.
- Блокировка защищает от цикла, в котором новое сообщение запускает ход, ход снова молчит, вы жмёте Stop, и всё повторяется заново.
- Блокировка живёт только в памяти приложения: после перезапуска телефона она исчезает сама.
Когда блокировка снимается сама
Иногда разблокировка происходит без вас, и это хороший знак: значит, движок жив и ход просто дошёл до конца.
- Подтверждение окончания хода снимает блокировку сразу и разрешает отправку накопленной очереди.
- Успешный запуск нового хода тоже снимает блокировку, потому что сервер принял сообщение и начал работу.
- Кнопка Unlock снимает блокировку вручную и показывает уведомление об успешной разблокировке.
- После разблокировки очередь уходит сразу, без ожидания следующего хода.
- Разблокировка попутно снимает и подозрение на зависание, если оно было в этот момент.
- Разблокировка ничего не спрашивает у сервера, поэтому снять её можно, даже когда связи нет.
Потерянный диалог и потерянная рабочая папка
Иногда сообщение не отправляется вовсе, и вместо ошибки появляется вопрос: продолжать ли работу в новом диалоге.
- Диалог считается недоступным, если движок не находит сам диалог или рабочую папку, в которой он жил.
- Обычная причина: движок перезапустился или папка проекта исчезла с диска.
- Приложение не отправляет сообщение молча, а показывает окно с вопросом и сохраняет ваш текст.
- Окно называется Thread unavailable и объясняет, что агент не может открыть этот диалог здесь.
- Перед окном приложение один раз пробует поднять диалог заново и отправить сообщение повторно.
- Кнопка Continue in new создаёт новый диалог и отправляет в него сохранённое сообщение сразу.
- Кнопка New thread создаёт новый диалог, а текст возвращает в поле ввода, чтобы вы решили сами.
- Кнопка Cancel закрывает окно, ничего не создавая и не отправляя, а сохранённый текст при этом теряется.
- Окно можно закрыть и тапом мимо него, это равносильно Cancel.
- Если сообщение отвергли только потому, что шёл другой ход, окно не открывается: сообщение встаёт в полосу очереди и ждёт конца хода.
Сверка хода при возврате в приложение
Приложение умеет само исправлять рассинхрон между своим экраном и тем, что реально происходит на сервере. Делается это в момент возврата из фона, после обрыва связи и при входе в диалог.
- При возврате из фона с открытым ходом приложение спрашивает у сервера статус хода и сверяет его со своим.
- Если ход на сервере идёт, а лента отстала, приложение перечитывает хвост диалога и догоняет пропущенные шаги.
- Если ход на сервере другой, чем тот, который считает приложение, приложение принимает серверный и помечает свой как закрытый без уведомления.
- Если сервер отвечает, что ход закончен, приложение закрывает его у себя и освобождает очередь.
- Если ход уже закрыт, а экран всё ещё рисует работу, приложение просто гасит индикаторы и ничего не переигрывает.
- Если сервер не назвал статус хода, приложение ничего не меняет и решит вопрос позже.
- Ход, который приложение подхватило у сервера, проверяется ещё раз через шесть секунд: вдруг он уже закончился.
- Если за эти шесть секунд события хода пришли, значит ход живой, и лишней проверки не будет.
- После обрыва связи подписка на события теряется, поэтому сверка при возврате — единственный способ узнать, чем кончился ход.
- Обновление списка диалогов тоже сверяет статусы: ход, который сервер считает свободным, перестаёт быть рабочим.
- Живой ход, который приложение видит у себя, серверному статусу «свободен» не подчиняется, пока не прошло десять секунд тишины.
Как зависание видно в списке диалогов
Подозрение на зависание видно не только в открытом диалоге: у диалогов и проектов в списках появляется своя пометка.
- У диалога в списке подпись читается как stuck и рядом показывает, сколько минут молчит ход.
- У проекта в списке собирается сводка вида «два работают, один ждёт, один завис» по всем его диалогам.
- Если в проекте есть хотя бы один работающий диалог, сводка говорит о работе и не упоминает зависшие.
- Приоритет в сводке такой: работа важнее зависания, а зависание важнее ожидания.
- Пока не идёт ни работа, ни ожидание, ни подозрение, у диалога вообще нет статусной подписи.
- Диалог, который ждёт вашего ответа, получает подпись awaiting you, а не зависание.
- После перезапуска приложения старый рабочий ход может выглядеть зависшим: если запись о ходе пролежала дольше десяти минут, она помечается как подозрительная.
- Если список диалогов три раза подряд не обновился, все диалоги, которые рисуются рабочими, получают знак предупреждения: их статус может быть недостоверным.
- Успешное обновление списка снимает это предупреждение автоматически.
Технические данные
| Параметр | Значение |
|---|---|
| Порог тишины, после которого начинается сверка | 4 минуты |
| Как часто сторож смотрит на состояние хода | каждые 30 секунд |
| Минимальный интервал между сверками хода | 2 минуты |
| Грейс живости: сколько тишины терпит серверный статус «свободен» | 10 секунд |
| Ожидание идентификатора только что стартовавшего хода | до 3 секунд с шагом 100 мс |
| Ожидание подтверждения после прерывания | 20 секунд |
| Чтение статуса после прерывания, тайм-аут | 6 секунд |
| Повторная проверка хода, принятого у сервера | через 6 секунд |
| Сверка хода при возврате из фона | чтение статуса хода у сервера |
| Тайм-аут сверки при возврате из фона | 6 секунд |
| Порог устаревания записи хода после перезапуска | 10 минут |
| Неудачных обновлений списка диалогов до пометки сомнения | 3 |
| Период фонового обновления списка диалогов | 20 секунд |
| Формат подписи зависшего диалога | stuck · silence Nм |
| Формат подписи в строке статуса | suspected hang · silence Nм |
| Подпись при блокировке | thread blocked |
| Подпись плашки при подозрении | агент не отвечает, N мин |
| Подпись плашки при блокировке | ход на сервере потерян, сообщения в очереди |
| Кнопки плашки при подозрении | Check и Stop |
| Кнопки плашки при блокировке | Unlock |
| Уведомление после ручной разблокировки | Thread unlocked |
| Заголовок окна потерянного диалога | Thread unavailable |
| Кнопки окна потерянного диалога | Continue in new, New thread, Cancel |
| Цвет строки статуса при подозрении и блокировке | цвет ошибки |
| Радиус скругления плашки | 16dp |
| Отступы внутри плашки | 16dp по горизонтали, 8dp по вертикали |
| Отступы вокруг плашки | 4dp со всех сторон |
| Значок предупреждения в плашке | 14dp |
| Троттлинг записи времени активности в интерфейс | не чаще одного раза в 100 мс |
| Сообщение в журнале после ручной разблокировки | thread unblocked by user |
Что агент умеет
- Агент умеет молчать во время долгой работы над задачей, и приложение отличит такой молчун от зависания, если на сервере ход ещё идёт.
- Агент умеет задать вопрос и остановиться на вашем ответе, и приложение не считает это молчание зависанием.
- Агент умеет ждать одобрения плана столько, сколько нужно, и подозрение на зависание в этот момент не возникает.
- Агент умеет выполнять команду без вывода столько, сколько она реально работает, и таймер зависания её не прервёт.
- Агент умеет закончиться, пока событие об окончании потерялось по дороге, и приложение закроет такой ход сам при очередной сверке.
- Агент умеет возобновить работу после того, как вы разблокировали диалог, и очередь уйдёт к нему автоматически.
- Агент умеет работать сразу в нескольких диалогах, и блокировка одного из них не останавливает остальные.
- Агент умеет продолжить ход, пока телефон лежал в фоне, и приложение подхватит его прогресс при возврате.
Ограничения
- Приложение не прерывает ход само по таймеру: молчание четыре минуты и дольше только показывает подозрение, а решение остаётся за вами.
- Подозрение на зависание нельзя снять без события от агента: если ход на самом деле жив, плашка будет висеть до вашего Stop.
- Блокировку диалога нельзя снять, не нажав Unlock: приложение намеренно не отправляет сообщения в застрявший ход.
- Разблокировка не проверяет сервер, поэтому снять её можно и тогда, когда ход на самом деле всё ещё работает: сообщения уйдут в занятый ход.
- Проверка живости хода отвечает только на вопрос «идёт ход или уже закончен» и не показывает, на чём именно агент застрял.
- Окно потерянного диалога предлагает только новый диалог: восстановить старую рабочую папку из приложения нельзя.
- Текст, сохранённый при потерянном диалоге, не переживает ни закрытие приложения, ни нажатие Cancel: нажать Continue in new или New thread.
- Пометка подозрения в списке диалогов после перезапуска опирается на время сохранённой записи, а не на реальную проверку хода.
- Предупреждение о недостоверных статусах в списке появляется после трёх неудачных обновлений подряд и держится до первого успешного.
- При остановке хода приложение ждёт двадцать секунд подтверждения, поэтому признаки работы могут остаться на экране ещё на это время.