Skip to content

fix(agent-core): фоновий читач стріму AcpClient (доповнення до #51) - #52

Merged
vitaliytv merged 4 commits into
mainfrom
claude/m1-acp-adapters-persistent-reader
Jul 17, 2026
Merged

fix(agent-core): фоновий читач стріму AcpClient (доповнення до #51)#52
vitaliytv merged 4 commits into
mainfrom
claude/m1-acp-adapters-persistent-reader

Conversation

@vitaliytv

Copy link
Copy Markdown
Member

Summary

Контекст: #51 було змерджено (squash) достроково — захопило лише перший коміт цієї роботи (базовий cwd-фікс). Три подальші коміти (підтвердження pi з піднятим omlx, і головне — фікс фонового читача-петлі, що реально усуває банер-баг) лишились поза main. Цей PR довершує #51 тими самими комітами (cherry-pick на актуальний main, чисто, без конфліктів).

  • AcpClient тепер має фоновий tokio-таск на весь час життя клієнта замість читання, прив'язаного до конкретного call() — той самий принцип, що у Zed (persistent-лістенер нотифікацій). session/new додатково дренує нотифікації, що осіли протягом 150мс (SETTLE_TIMEOUT), перш ніж повернути керування.
  • Публічний тип спростився: AcpClient<R, W>AcpClient<W> (reader живе лише в фоновому таску); AcpTurnRunner::client оновлено відповідно.
  • Новий тест session_new_drains_prelude_before_first_prompt відтворює сценарій pi-acp (prelude-банер pi v0.79.9 одразу після session/new, ще до першого prompt).
  • Живою сесією з pi-acp@0.0.31 підтверджено: банер більше не приліплюється до першої реальної відповіді ходу.
  • Дорогою виправлено доку crates/agent-core/src/docs/acp.md, зіпсовану локальним omlx-прогоном (score 0, витік тексту відмови моделі — CRC-гейт цього не ловить).

Test plan

  • cargo build --workspace — чисто
  • cargo test -p agent-core -p agent-server -q — 25 passed, 1 pre-existing fail (failing_check_blocks_done_until_fixed, відтворюється й на чистому main, не повʼязаний з цим PR)
  • Живі сесії: pi-acp — банер відсутній у першій відповіді
  • npx @7n/rules lint — exit 0

🤖 Generated with Claude Code

vitaliytv and others added 4 commits July 17, 2026 13:58
initialize/session/new через pi-acp@0.0.31 (той самий пакет, що його
використовує офіційний ACP Registry Zed для Pi) проходять успішно.
Повний хід (prompt → відповідь) не підтверджено: дефолтна модель сесії —
локальна omlx/gemma-4-e4b-it-OptiQ-4bit, а omlx-сервер у середовищі
перевірки не піднятий.

Окремо задокументовано протокольну особливість адаптера: pi-acp одразу
після session/new, ще до першого prompt, шле agent_message_chunk з
банером самого pi ("pi v0.79.9") — клієнт без фільтрації відрендерить
це як фейкову відповідь агента.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…банера

Живою сесією з піднятим локальним omlx: prompt → відповідь через pi-acp
працює (4/4 CLI підтверджено). Пояснено, чому банер pi опиняється в
першій відповіді: pi-acp навмисно surface-ить нерозпарсюваний prelude
з stdout pi як agent_message_chunk одразу після session/new — до
першого prompt. Zed із цим не плутається (persistent-лістенер
нотифікацій на всю сесію + сесія відкривається до першого повідомлення
користувача). agent-core::AcpClient::call() читає нотифікації лише
всередині циклу конкретного виклику; initialize()/new_session() мають
no-op emit, а банер приходить асинхронно вже після відповіді на
session/new — лежить нечитаним у пайпі, поки не почнеться цикл
наступного call(), яким завжди є перший prompt() користувача. Не
виправлено в цьому PR — потребує дренування pending-нотифікацій в
AcpTurnRunner::open_room.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e-банер

Читання ACP-стріму більше не прив'язане до конкретного call() — фоновий
tokio-таск живе разом із клієнтом і класифікує кадри (відповіді/
нотифікації) у канал; зустрічні session/request_permission обробляє
теж він, незалежно від того, який виклик зараз активний (так само, як
persistent-лістенер у Zed). session/new додатково дренує нотифікації,
що осіли в черзі протягом SETTLE_TIMEOUT (150мс), перш ніж повернути
керування — тому prelude-банер CLI, який pi-acp навмисно шле одразу
після session/new (ще до першого prompt), більше не приліплюється до
першої реальної відповіді ходу.

AcpClient<R, W> → AcpClient<W> (reader живе лише всередині фонового
таска, не зберігається в структурі); AcpTurnRunner::client type
оновлено відповідно. Новий тест
session_new_drains_prelude_before_first_prompt відтворює сценарій
pi-acp. Живою сесією з pi-acp@0.0.31 перевірено: перша відповідь —
лише текст ходу, без банера.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vitaliytv
vitaliytv merged commit 6a44466 into main Jul 17, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant