refactor(cli): decouple TUI runtime from app server - #2307
Conversation
77fd90b to
cc31054
Compare
limityan
left a comment
There was a problem hiding this comment.
整体方向认可:Embedded TUI 不再为同进程 Runtime 额外建立 App Server/transport,Shared 继续复用 Runtime IPC v17。但当前 head cc31054bbf39657f06eb2d4970f6b54b8946fa60 仍有以下架构阻断,因此请求修改。
1. [P1] Rust Runtime SDK v6 出现源码不兼容变更
问题:bitfun_agent_runtime::sdk 公开导出的 RuntimeError 是可穷尽匹配枚举。本次新增 RuntimeError::MissingModeCatalogPort,但 AGENT_RUNTIME_SDK_API_VERSION 仍为 6。仓内 SDK Host 已经必须增加新的 match arm,这直接证明调用方需要改写代码。
风险:外部 Rust embedder 的 exhaustive match 会在升级后编译失败,与 docs/architecture/agent-runtime-services-design.md 中“需要调用方改写时必须提升接口版本并提供迁移路径”的规则冲突。
建议:优先用现有 RuntimeError::Port(PortErrorKind::NotAvailable) 表达可选 mode catalog 缺失;如果确实需要新增枚举项,则升级到 v7 并补充迁移说明与兼容测试。现在单独添加 #[non_exhaustive] 也会破坏已有 exhaustive match,不能作为无版本迁移的修复。
涉及位置:
src/crates/execution/agent-runtime/src/runtime.rs:63-65src/crates/execution/agent-runtime/src/sdk.rs:11,47-50docs/architecture/agent-runtime-services-design.md:71-74
2. [P1] Shared --agent 仍绕过 Shared Runtime 的权威 mode catalog
问题:Shared client 已在 src/apps/cli/src/main.rs:942-950 建立,但 --agent 随后仍由 resolve_agent_override() 调用 controller-local get_agent_registry().get_modes_info() 校验。该方法实际固定等于 get_modes_info_for_workspace(None, false),不会读取当前 workspace 的 external modes。与此同时,本 PR 已经实现了正确的 CliAgentRuntimeClient::available_agent_modes() -> Shared IPC ListAgentModes -> Shared Runtime Host mode catalog 路径。
风险:bitfun --shared --agent <workspace/external-mode> 会拒绝 Host 实际支持的 mode 并静默回落本机默认值;反向也可能接受仅 controller 进程存在的 mode。执行 authority、workspace scope 和 fail-closed 语义在启动入口处分裂。
建议:在 backend 连接完成后通过 agent.available_agent_modes() 校验 override;Shared Host catalog 不可用时明确失败,不要回退到 controller-local registry/default。
涉及位置:
src/apps/cli/src/main.rs:990-1000,1103-1115src/crates/assembly/core/src/agentic/agents/registry/query.rs:141-153src/apps/cli/src/agent/runtime_client.rs:424-466src/apps/cli/src/shared_runtime.rs:228-253
3. [P1] Phase 5 删除门槛缺少真实行为等价证据
问题:架构文档要求 Embedded direct 与 Shared v17 使用同一行为 fixture,覆盖请求结果、事件顺序、Permission、取消、Remote scope、unsupported、断连与 outcome_unknown 后,才能把 Phase 5 标记为完成并删除旧路径。但 src/apps/cli/src/agent/runtime_client.rs:2320-2555 中标为 “both deployments” 的主要测试只是通过 include_str!("runtime_client.rs") 检查源码字符串;cli_command_contracts 也主要验证源码形状。没有测试构造 CliAgentRuntimeClient::new_shared、真实/测试 IPC server 或一套同时运行 direct/shared backend 的共同 fixture。
同时,部分 owner use case 已在入口层复制。例如 MCP 删除后的 20 x 250 ms stop 生命周期同时存在于 src/apps/cli/src/modes/chat/mcp.rs:254-274 和 src/crates/interfaces/app-server/src/management/owner.rs:812-833,与设计中的“direct adapter 无 owner 复制”门槛不一致。
风险:当前测试只能证明两个分支出现在源码中,不能证明两种部署的状态转换、事件、错误和恢复语义等价;旧路径已经删除且无 rollback adapter,回归会直接进入生产路径。重复 use case 还会使 CLI 与 App Server 后续产生策略漂移。
建议:在声明完成前增加真实双 backend 行为 fixture,至少覆盖 session create/restore、turn/event、cancel、Permission、失败 settlement 和 Remote unsupported;把 MCP 删除、模型默认值等跨入口业务编排收敛到窄 owner API。这里不需要恢复 App Server,也不需要再增加 catch-all TUI 层。
涉及位置:
docs/architecture/app-server-architecture.md:49,56,86-88,403,425-465docs/plans/tui-app-server-decoupling-refactor-plan.md:26,105-140src/apps/cli/src/agent/runtime_client.rs:2320-2555
验证状态
node --test scripts/check-core-boundaries.test.mjs:通过,120/120(最新 head 已修复上一版 Worktree 规则缺口)cargo check --locked -p bitfun-sdk-host:通过git diff --check:通过- 当前精确 head 的 CI 仍在运行;CI 转绿也不能替代以上 SDK 兼容、authority 和行为等价门槛。
cc31054 to
5046c94
Compare
5046c94 to
2505088
Compare
limityan
left a comment
There was a problem hiding this comment.
复审结论:Request changes。本次基于精确 head 25050884daf74677912843c05ddcaa9e3d17a468。
已确认上一轮的 SDK v6 兼容性、Shared 根级 --agent authority/fail-closed、boundary self-test 三项问题均已修复;MCP stop policy 也已下沉到 MCPServerManager。当前 8 项 CI 全绿,但仍有一项迁移门槛级阻断。
[P1] Phase 5 仍缺少声明完成所要求的双 backend 行为等价证据
问题:新增测试虽然会启动真实 RuntimeIpcServer 并构造 CliAgentRuntimeClient::new_shared,但 fixture 只实现 ListAgentModes:src/apps/cli/src/agent/runtime_client.rs:2803-2823 对其他 operation 全部返回 OperationUnsupported,事件订阅是空 channel;唯一的双 backend 断言也只比较 mode catalog(2905-2917)。Session/Turn/Event/Permission/cancel 等其余覆盖仍主要是 include_str!("runtime_client.rs") 的源码形状断言(2338-2569),不是运行时行为验证。
风险:docs/architecture/app-server-architecture.md:425-465 要求在删除旧 Embedded App Server 路径前,用同一行为 fixture 覆盖 direct/Shared 的 session create/restore、turn、事件顺序、permission、cancel、failure settlement、Remote unsupported、断连与 outcome_unknown。当前计划仍把 Phase 5 标为完成,旧路径也已删除;因此这些语义一旦在 Shared transport/handler 上漂移,现有测试和全绿 CI 都无法发现。
建议:增加一个真正复用同一场景和断言的双 backend fixture:Embedded 走 AgentRuntime direct,Shared 走生产 SharedRuntimeHandler -> RuntimeIpcServer,至少覆盖上述迁移门槛行为及错误/断连结算;在这些证据落地前,不应把 Phase 5 标为完成。
[P2] Model add-with-default 用例仍由两个入口重复编排
问题:只读投影已收敛到 model_projection.rs,但“新增模型,并在 primary 未配置时设为默认”的两步业务策略仍分别存在于 CLI src/apps/cli/src/modes/chat/provider_models.rs:39-63 和 App Server src/crates/interfaces/app-server/src/management/owner.rs:1243-1258。
风险/建议:两个入口可能在空值判定、部分失败和并发更新上漂移。建议将该策略收敛为 Config owner 的窄 operation,入口只负责请求/展示。此项可随后处理,不单独阻断本轮。
本地复核:cargo test --locked -p bitfun-cli --bin bitfun dual_backend_behavior_tests 2/2、cargo check --locked -p bitfun-sdk-host、core-boundary self-test 120/120、git diff --check 均通过。
Summary
EmbeddedAppServerHost、in-memory transport 或 wire handshake,Startup/Chat controller 直接使用CliAgentRuntimeClient。src/apps/cli/src/embedded_app_server.rs、agent/tui_client.rs、shared_tui_backend.rs、tui_backend.rs。CliAgentRuntimeClient统一 Embedded typed API 与--sharedRuntime IPC v17 两个 backend,controller 不按部署复制 Runtime 分支。core-types::model、product-domains::{account, agent_catalog, mcp, native_hooks}、runtime-ports::agent_api;不复用app-server-protocolwire DTO。management/service.rs重命名为owner.rs,保留AppManagementService,与 TUI composition 解耦。Type and Areas
Type: refactor
Areas: CLI/TUI、Rust core、contracts/product-domains、app-server
Motivation / Impact
--embedded与--shared两条运行路径,预期无用户可见行为变化。CliAgentRuntimeClient和稳定 owner/service API,不再接触 Runtime 实现或 private IPC operation。Verification