Skip to content

refactor(cli): decouple TUI runtime from app server - #2307

Open
zvzuola wants to merge 1 commit into
GCWing:mainfrom
zvzuola:refact-embedded
Open

refactor(cli): decouple TUI runtime from app server#2307
zvzuola wants to merge 1 commit into
GCWing:mainfrom
zvzuola:refact-embedded

Conversation

@zvzuola

@zvzuola zvzuola commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Summary

  • 将交互式 CLI/TUI 从嵌入式 App Server 解耦:不再启动 EmbeddedAppServerHost、in-memory transport 或 wire handshake,Startup/Chat controller 直接使用 CliAgentRuntimeClient
  • 删除旧 catch-all 客户端与后端:src/apps/cli/src/embedded_app_server.rsagent/tui_client.rsshared_tui_backend.rstui_backend.rs
  • CliAgentRuntimeClient 统一 Embedded typed API 与 --shared Runtime IPC v17 两个 backend,controller 不按部署复制 Runtime 分支。
  • Model、Skill、Subagent、MCP、External Source、Hook、Account、Worktree 改为直接调用对应 owner/service。
  • 新增稳定契约投影 DTO:core-types::modelproduct-domains::{account, agent_catalog, mcp, native_hooks}runtime-ports::agent_api;不复用 app-server-protocol wire DTO。
  • App Server 管理模块 management/service.rs 重命名为 owner.rs,保留 AppManagementService,与 TUI composition 解耦。
  • Remote workspace 下 controller-local owner/service 调用 fail closed,不回落控制端本机。

Type and Areas

Type: refactor

Areas: CLI/TUI、Rust core、contracts/product-domains、app-server

Motivation / Impact

  • 消除 TUI 通过嵌入式 App Server 的间接层,减少 catch-all TUI backend 与重复 DTO 投影。
  • 对外仍保留 --embedded--shared 两条运行路径,预期无用户可见行为变化。
  • 开发者侧:TUI controller 只依赖 CliAgentRuntimeClient 和稳定 owner/service API,不再接触 Runtime 实现或 private IPC operation。

Verification

pnpm run fmt:rs
cargo check -p bitfun-cli
cargo test -p bitfun-cli --test cli_command_contracts
cargo test -p bitfun-cli
pnpm run check:core-boundaries
git diff --check

@zvzuola
zvzuola force-pushed the refact-embedded branch 3 times, most recently from 77fd90b to cc31054 Compare August 15, 2026 06:39

@limityan limityan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

整体方向认可: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-65
  • src/crates/execution/agent-runtime/src/sdk.rs:11,47-50
  • docs/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-1115
  • src/crates/assembly/core/src/agentic/agents/registry/query.rs:141-153
  • src/apps/cli/src/agent/runtime_client.rs:424-466
  • src/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-274src/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-465
  • docs/plans/tui-app-server-decoupling-refactor-plan.md:26,105-140
  • src/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 和行为等价门槛。

@limityan limityan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复审结论: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 只实现 ListAgentModessrc/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 均通过。

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