Skip to content

fix(agent-server): абсолютний cwd у AcpTurnRunner; звірка ACP-адаптерів (m1-acp-adapters) - #51

Merged
vitaliytv merged 1 commit into
mainfrom
claude/m1-acp-adapters-live-check
Jul 16, 2026
Merged

fix(agent-server): абсолютний cwd у AcpTurnRunner; звірка ACP-адаптерів (m1-acp-adapters)#51
vitaliytv merged 1 commit into
mainfrom
claude/m1-acp-adapters-live-check

Conversation

@vitaliytv

Copy link
Copy Markdown
Member

Summary

  • m1-acp-adapters: живою сесією (agent-cli serve --acp-cmd … + attach) перевірено ACP-адаптери трьох з чотирьох agent_clicursor (нативний agent acp), codex (@agentclientprotocol/codex-acp), claude (@agentclientprotocol/claude-agent-acp, наступник задеприкейченого @zed-industries/claude-code-acp).
  • Знайдено й виправлено розбіжність: ACP-спека (NewSessionRequest.cwd) вимагає абсолютний шлях. AcpTurnRunner::open_room без workdir (M1 CLI без графа/worktree) підставляв літеральне "."agent acp і codex-acp це прощають, claude-agent-acp строго валідує і відкидає запит (Invalid params: cwd must be an absolute path). Виправлено: без workdir тепер береться std::env::current_dir().
  • pi — задокументовано, що офіційного нативного ACP-режиму ще немає (обговорення в upstream ще на стадії дизайну); єдиний адаптер — сторонній pi-acp (svkozak/pi-acp@0.0.31), у цьому PR лишений неперевіреним (окремий трек).
  • Таблиця адаптерів і опис розбіжності — npm/docs/architecture/runtime.md.

Test plan

  • cargo build --workspace — чисто
  • cargo test -p agent-core -p agent-server -q — 22 passed, 1 pre-existing fail (failing_check_blocks_done_until_fixed, підтверджено відтворюється й на чистому main, не повʼязаний з цим PR)
  • Живі сесії: cursor / codex / claude — agent-cli serve --acp-cmd … + attach, промпт → відповідь стрімом
  • npx @7n/rules lint (дельта, у lint-worktree) — exit 0

🤖 Generated with Claude Code

… ACP-адаптерів

m1-acp-adapters: живою сесією (agent-cli serve --acp-cmd + attach) перевірено
ACP-адаптери трьох CLI — cursor (нативний `agent acp`), codex
(@agentclientprotocol/codex-acp), claude (@agentclientprotocol/claude-agent-acp,
наступник задеприкейченого @zed-industries/claude-code-acp). pi покритий лише
неофіційним стороннім pi-acp (svkozak/pi-acp@0.0.31) — не запускав, потребує
окремого рішення про довіру.

Знайдено й виправлено розбіжність: ACP-спека вимагає абсолютний cwd у
session/new. AcpTurnRunner::open_room без workdir підставляв літеральне "." —
agent acp і codex-acp це прощають, claude-agent-acp строго валідує і відкидає
запит. Тепер без workdir береться std::env::current_dir().

Таблиця адаптерів і опис розбіжності — npm/docs/architecture/runtime.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vitaliytv
vitaliytv merged commit f3f737f into main Jul 16, 2026
3 of 4 checks passed
vitaliytv added a commit that referenced this pull request Jul 17, 2026
)

* docs(mt): pi-acp живою сесією — handshake ok, повний хід не підтверджено

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>

* docs(mt): pi-acp повний хід підтверджено (omlx піднятий); root cause банера

Живою сесією з піднятим локальним 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>

* fix(agent-core): фоновий читач стріму AcpClient — не приліплює prelude-банер

Читання 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>

* chore(changes): change-файл для фонового читача AcpClient

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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