Skip to content

feat(rfc-0027): ACP subagent Zed compatibility - #110

Closed
Million-mo wants to merge 10 commits into
develop/agenticfrom
feat/rfc-0027-acp-subagent-zed
Closed

feat(rfc-0027): ACP subagent Zed compatibility#110
Million-mo wants to merge 10 commits into
develop/agenticfrom
feat/rfc-0027-acp-subagent-zed

Conversation

@Million-mo

Copy link
Copy Markdown
Owner

Summary

RFC-0027 implementation: ACP subagent Zed compatibility support.

Changes

  1. Bug fixes in event_converter.py

    • Fixed duplicate _current_message_id field declaration
    • Fixed duplicated reset() body
    • Fixed double reset() call on StreamCompleteEvent
  2. Zed mode type propagation

    • Added "zed" to subagent_display_mode across 7 files (server, CLI, config, session, agent)
  3. SubagentSessionInfo model and helpers

    • Added SubagentSessionInfo Pydantic model with session_id, message_start_index, message_end_index
    • Added _build_subagent_field_meta() helper for constructing _meta payload
  4. _meta filling in zed mode

    • SpawnSessionStart handler emits ToolCallStart with _meta.subagent_session_info and tool_name="task"
    • SubAgentEvent handler routes inner events and emits ToolCallProgress with _meta
    • Guardrails: _meta never leaks in non-zed modes (legacy/inline/tool_box)
  5. Child session creation and routing

    • SpawnSessionStart creates independent ACP subsession via session_manager.create_child_session()
    • SubAgentEvent inner events routed to child session's event loop
    • StreamCompleteEvent closes child session and emits parent completion
  6. Message index tracking

    • message_start_index=0 on SpawnSessionStart
    • message_end_index=count-1 on StreamCompleteEvent
  7. Independent tool_call_id for zed subagent

    • SpawnSessionStart generates a NEW tool_call_id instead of reusing PydanticAI's
    • Zed sees a distinct tool call bearing _meta.subagent_session_info
  8. Tests and snapshots

    • 29 event_converter tests (bug fixes, _meta, guardrails, index tracking, subsessions)
    • 4 zed snapshot tests with fixtures

Verification

  • pytest tests/test_event_converter.py - 29/29 pass
  • pytest tests/test_acp_event_converter_snapshots.py::TestZedModeSnapshots - 4/4 pass
  • Guardrail tests confirm no _meta leakage in non-zed modes

Related

Zed-side change required for full functionality: dynamic subagent loading via EntryUpdated event handling (separate PR).

备份迁移自 SRC-PR#42 · 作者 @Leoyzen · 创建于 2026-05-29T13:58:51Z · head=feat/rfc-0027-acp-subagent-zed base=develop/agentic
源状态: closed

Leoyzen added 10 commits June 1, 2026 11:04
- SpawnSessionStart in zed mode now generates a NEW tool_call_id
  instead of reusing the PydanticAI-native tool_call_id
- This creates a distinct tool call bearing _meta.subagent_session_info
- Zed can recognize this as a subagent and load the child session
- Original PydanticAI tool call remains untouched

Related Zed-side change: dynamic subagent loading via EntryUpdated
…e providers

- Reverted accidental deletion of get_skills() from ResourceProvider base class
  which broke 18 callers across agent_routes, command_registry, aggregating, etc.
- Restored missing return skill in LocalResourceProvider.get_skill()

Fixes: serve-acp config loading error "Failed to import class"
…fications)

Reverted 50 files that contained:
- ruff auto-fix (import sorting, line length, TYPE_CHECKING moves)
- Exception type changes in tools/base.py (ValueError -> TypeError)
- Import removals in provider_router.py
- Various formatting and style changes

Kept only RFC-0027 core files:
- acp_server/ event_converter, session, session_manager, server, acp_agent
- pool_server config, serve_acp CLI
- Tests and snapshots
- resource_providers base.py and local.py (get_skills fix)
- Fix local.py task_ref garbage collection with _background_tasks set
- Fix zed_provider.py database connection leaks with finally blocks
- Fix event_converter.py child_session_id mismatch using returned ID
- Fix event_converter.py exception handling to catch Exception broadly
- Fix event_converter.py cleanup _subagent_message_counts and _subagent_tool_map on completion
- Fix session.py and event_converter.py _display_mode propagation
- Move RFC-0027 to implemented status
- fix(session_manager): add session.close() on initialization failure to prevent resource leaks
- feat(session_manager): allow passing explicit child_session_id to create_child_session for ID consistency
- fix(event_converter): clean up subagent state on StreamCompleteEvent fallback path to prevent memory accumulation
- fix(sessions/manager): accept optional child_session_id in create_child_session
@Million-mo Million-mo closed this Aug 22, 2026
@Million-mo

Copy link
Copy Markdown
Owner Author

评论 by @Leoyzen 于 2026-05-29T14:31:38Z(备份迁移)

/gemini review

@Million-mo

Copy link
Copy Markdown
Owner Author

评论 by @Leoyzen 于 2026-05-31T03:17:31Z(备份迁移)

/gemini review

@Million-mo

Copy link
Copy Markdown
Owner Author

评论 by @Leoyzen 于 2026-06-01T03:14:40Z(备份迁移)

Review Comments 修复总结

已针对未解决的 review comments 提交修复(dab5d5bb3):

1. event_converter.py — child_converter _display_mode 显式传递 ✅

代码已在 rebase 后的版本中同时传递 _display_mode=self._display_modesubagent_display_mode=self._display_mode,确保子 converter 正确继承父 converter 的显示模式。

2. session.py — 主 converter _display_mode 显式传递 ✅

同上,已同时传递 _display_mode=self.subagent_display_modesubagent_display_mode=self.subagent_display_mode

3. session_manager.py:269create_child_session 接受可选 child_session_id

  • ACPSessionManager.create_child_session() 新增 child_session_id: str | None = None 参数
  • 透传给底层 SessionManager.create_child_session(),确保持久化 session ID 与客户端/事件路由使用的 ID 一致
  • event_converter.py 调用时传入 child_session_id=child_session_id

4. event_converter.py:935 — child session 完成时清理状态 ✅

代码已在 rebase 后版本中清理 _child_sessions_subagent_message_counts_subagent_tool_map 三个字典。

5. session_manager.py:189initialize_mcp_servers 失败时 session.close()

except Exception 块中新增:

if "session" in locals() and session is not None:
    with contextlib.suppress(Exception):
        await session.close()

确保 async environment 在初始化失败时被正确清理。

6. event_converter.py:971 — StreamCompleteEvent fallback 路径清理状态 ✅

在 no-child-session 的 StreamCompleteEvent fallback 分支中,yield ToolCallProgress 后新增:

self._subagent_message_counts.pop(child_session_id, None)
self._subagent_tool_map.pop(child_session_id, None)

防止长时间 stream 中已完成 subagent 的状态累积。


所有修改已通过单元测试验证(209 passed)。

已解决的 comments(如 get_skill return、_background_tasks GC、TypeErrorValueError 等)在 rebase 后的代码中已包含之前的修复。

@Million-mo

Copy link
Copy Markdown
Owner Author

评论 by @Million-mo 于 2026-07-17T09:41:21Z(备份迁移)

状态分析

此 PR 的功能已全部在主分支上实现,PR 已过时。

具体情况

PR #42 实现 RFC-0027 ACP subagent Zed 兼容性,共 8 项核心变更。当前主分支已包含所有功能:

PR 声明的变更 主分支现状
SubagentSessionInfo 模型 event_converter.py:122
_build_subagent_field_meta() helper event_converter.py:235
subagent_display_mode 包含 "zed" ✅ 覆盖 6 个文件,类型 Literal["legacy", "zed", "qwen"],还额外扩展了 "qwen" 模式
SpawnSessionStart 在 zed 模式发 _meta.subagent_session_info event_converter.py 中实现
SubAgentEvent 内部事件路由 handler.py:167 处理 zed 模式子会话
独立 tool_call_id 生成 ✅ event converter 中实现
子会话创建与路由 session_manager.pycreate_child_session
消息索引跟踪 ✅ event converter 中跟踪

原因

2026-06-30 合并的 PR #65("refactor: eliminate pool-level agents, introduce Run/Turn separation, and overhaul EventBus + ACP session lifecycle")在大规模重构中直接将 Zed 兼容性功能整合进了新架构,并扩展了 "qwen" 模式。PR #43(RFC-0042)也进一步扩展了 subagent 协议。

结论

功能已被主分支完全覆盖,关闭此 PR。

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.

2 participants