Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions docs/architecture/agent-runtime-services-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ CLI Agent 体验边界见 [`cli-product-line-design.md`](cli-product-line-design
新增公共类型前必须有真实生产调用方、版本边界和验证路径。现有 Agent Runtime SDK 仍是 v1 preview,CLI、ACP、
Desktop 仍保留 `bitfun-core/product-full` 兼容 owner。CLI 与 CLI 托管的 ACP server 已消费各自的产品组装结果;
Desktop 主交互只消费由现有 Core owner 构造的窄口径 SDK 门面,尚未组装完整 Desktop profile。这些接入都不等于
协调器、调度器、持久化或工具执行 owner 已迁移;ACP 的完整持久化历史、模式、模型目录/提供方配置、MCP、客户端路径与
Desktop 的其余入口仍保留明确的兼容边界,活动会话的模型写入已通过 SDK 回到 Core owner。
协调器、调度器、持久化或工具执行 owner 已迁移;ACP 的完整持久化历史、模型/模式目录与提供方配置、MCP、客户端路径与
Desktop 的其余入口仍保留明确的兼容边界,活动会话的模型/模式写入已通过 SDK 回到 Core owner。

阅读路径:第 1 节确认 SDK、内核、产品特性、扩展接口和 crate 边界;第 2-3 节说明稳定接口、
运行时服务、内核、工具和工作流;第 4 节说明产品组装与扩展注册;第 5 节作为质量保护和
Expand Down Expand Up @@ -720,7 +720,7 @@ Core 的 Network、Git 和 MCP Catalog 当前仍含兼容 marker,因此该诊

该切换仍是 `product-full` 兼容组装,不是 owner 迁移。协调器、调度器、持久化、工具管线和 Agentic Event Queue
仍由 Core 唯一持有;CLI 与 ACP 不复制这些状态。ACP 服务端通过 SDK 处理会话创建/列举、轮次、取消、交互响应和事件订阅,
但完整持久化历史回放、模式、模型目录/配置和 MCP 仍走单一 Core 兼容门面;会话模型写入通过 SDK 回到同一 Core owner。ACP stdio、连接和协议投影仍在
但完整持久化历史回放、模型/模式目录与提供方配置和 MCP 仍走单一 Core 兼容门面;会话模型/模式写入通过 SDK 回到同一 Core owner。ACP stdio、连接和协议投影仍在
`interfaces/acp`。Desktop 复用同一 Core owner 构造一个窄口径 SDK 门面,主界面的轮次提交/取消、工具确认/拒绝和
用户问题回答与会话模型更新已通过该门面;会话 CRUD/恢复视图、MCP、MiniApp、Cron、远程连接、Tauri 窗口与平台资源
仍保留在 Desktop/Core 兼容入口。Server 仅提供健康检查、信息与 ping 路由。未接入入口的 profile、枚举分支和
Expand Down Expand Up @@ -796,13 +796,14 @@ Core 的 Network、Git 和 MCP Catalog 当前仍含兼容 marker,因此该诊
| ACP | ACP 协议、客户端生命周期、远端探测 | 外部智能体/工具能力、环境事实、权限桥接 |
| Web UI / mobile web | UI 状态、hydration、配对、会话展示、插件状态视图 | 接口/传输 DTO、运行时事件事实、能力服务读模型 |

当前 Runtime SDK 已提供会话创建、列出、删除、恢复、模型更新、类型化转录读取、本地分支、用量生成,以及
精确轮次结算。模型更新只接受会话 ID 与模型 ID,
不承载模型目录、模式、提供方配置或宿主 UI 选择语义。`AgentSessionRestoreRequest/Result` 与
当前 Runtime SDK 已提供会话创建、列出、删除、恢复、模型/模式更新、类型化转录读取、本地分支、用量生成,以及
精确轮次结算。模型与模式更新只接受会话 ID 和被选择的稳定 ID,
不承载目录、提供方配置、选择策略或宿主 UI 语义。`AgentSessionRestoreRequest/Result` 与
`AgentSessionRestorePort` 归 Agent Runtime SDK,以继续复用 Runtime owner 的完整 `SessionState`;类型化
`SessionTranscript` 归 `runtime-ports`。两者都由 `assembly/core` 注入真实持久化 owner,当前由 CLI/TUI
消费;ACP 为保证模型配置与完整历史来自同一次恢复,继续通过 Core 兼容门面读取协议回放所需的完整轮次,避免为单一协议
扩张通用 transcript。会话分支请求显式携带可选远程身份;当前本地 provider 对远程身份返回 `NotAvailable`,不据本地路径
消费;ACP 的活动会话模式更新也通过窄端口回到同一 Core owner。ACP 为保证模型配置与完整历史来自同一次恢复,继续通过
Core 兼容门面读取协议回放所需的完整轮次,避免为单一协议扩张通用 transcript,也不绕过附件内容所需的独立授权能力。
会话分支请求显式携带可选远程身份;当前本地 provider 对远程身份返回 `NotAvailable`,不据本地路径
推断远程语义。CLI/TUI 的工具确认、拒绝和用户问题回答,以及 ACP 服务端 / Peer Host 的工具确认与拒绝,通过类型化
`AgentInteractionResponsePort` 回到 Core 的工具管线或用户输入 owner,不改变审批策略或交互所有权。
`CoreAgentRuntimeCompatibility` 仍承载未迁移的
Expand Down Expand Up @@ -871,8 +872,8 @@ Provider 装配同样按需增加,不提前为 Memory、Context、Workflow、S

CLI 托管的 ACP 服务端使用 `DeliveryProfile::Acp` 组装一个 Agent Runtime,通过 SDK 处理会话创建/列举、轮次提交/取消、
交互响应和只读 Agent 事件订阅。ACP 只把共享运行时事实映射成协议更新;标准输入输出、连接、权限 RPC 与通知生命周期
不进入 SDK。完整持久化历史恢复、模式、模型目录/提供方配置、MCP 和 ACP 客户端路径仍是明确的 Core 兼容范围;
活动会话的模型写入已经通过 SDK 回到 Core owner,
不进入 SDK。完整持久化历史恢复、模型/模式目录与提供方配置读取、MCP 和 ACP 客户端路径仍是明确的 Core 兼容范围;
活动会话的模型/模式写入已经通过 SDK 回到 Core owner,
不据此扩张通用 runtime DTO。

继续拥有:
Expand Down Expand Up @@ -1086,7 +1087,7 @@ Product 测试:
- 把 embedded relay 的 TCP bind、静态 fallback 和任务生命周期移出 assembly;room/device 状态、account/sync
存储、asset store 与 HTTP/WebSocket router 已归属 `services/relay-service`,Cargo 反向边已删除并由通用边界检查保护。
- 继续缩小 CLI 的 Core 兼容门面;只有稳定端口、真实生产调用方和行为等价测试齐备时才迁移 owner。
- 继续按真实复用需求缩小 ACP 的完整持久化历史、模式、模型目录/提供方配置、MCP 与客户端兼容路径;Desktop 仅继续迁移存在稳定端口和
- 继续按真实复用需求缩小 ACP 的完整持久化历史、模型/模式目录与提供方配置读取、MCP 与客户端兼容路径;Desktop 仅继续迁移存在稳定端口和
行为等价测试的入口。完整 Desktop 产品组装需先补齐真实必需服务与事件消费路径,不以桩实现提前声明能力;ACP 生命周期
和 Desktop 平台资源仍留在各自入口。
- 为 Agent Runtime SDK 增加至少一个非 `bitfun-core` 的真实嵌入方;预览 facade 和单元测试不等于外部可用 SDK。
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture/cli-product-line-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ BitFun CLI 应成为可独立安装和发布的 Agent 产品,而不是 Desktop
`exec --session-id` 和缺失后端会话通过独立固定 ID 方法按原 ID 重建)/列举/删除/恢复、类型化转录、本地分支、
用量生成、轮次提交/取消和精确结算;普通创建
DTO 保持 v1 字段集合,固定 ID 冲突返回 `InvalidRequest`。会话模型更新、工具确认/拒绝和用户问题回答也通过
SDK 的窄端口回到 Core owner;模型目录、模式和提供方配置仍由产品入口解释。TUI 用量卡片持久化、快照及 Peer Host/ACP 维护
SDK 的窄端口回到 Core owner,ACP 的活动会话模式更新也复用同一窄端口;模型/模式目录和提供方配置仍由产品入口解释。TUI 用量卡片持久化、快照及 Peer Host/ACP 维护
等 SDK v1 缺口由一个 Core 兼容门面转发给原 owner。
- Agentic Event Queue 仍是唯一事件 owner;TUI、`exec` 与 Peer Host 使用独立广播订阅,不互相消费事件。
- 有界旧队列只承担兼容存储;达到容量时不得抑制广播。CLI 保持一个后台 drain,订阅方一旦报告 lag/closed,
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture/product-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ flowchart LR
| HarmonyOS PC 原生 CLI/TUI | 未来平台目标,当前未实现 | 目标、问题和风险见平台规约;具体适配另立专题,HAP、手机 Remote App 与远端代执行均不替代 |
| HarmonyOS PC GUI | 完整 HarmonyOS PC 支持的另一目标形态,当前未实现 | 与 CLI/TUI 共享稳定能力和 Runtime 语义,但独立设计宿主、界面与发布验证;Web、Remote 或现有 Tauri Desktop 均不能替代 |
| HarmonyOS 手机 Remote App | `src/apps/mobile/harmonyos` 是 phone-only ArkTS 远程入口,不持有本地 Rust Agent Runtime | 保持当前能力并按移动端专题独立演进;本轮不提前设计移动 Runtime/TUI/GUI,也不能据此宣称 HarmonyOS PC 本地能力 |
| ACP | CLI 托管的服务端仍以 `bitfun-core/product-full` 作为兼容执行层 | 入口已选择 `DeliveryProfile::Acp` 并消费 Runtime Parts;组装层在入队前原子拒绝忙碌会话,不改变其他产品入口的排队行为;活动会话模型写入走 SDK,会话恢复、模式、模型目录/提供方配置、MCP、客户端与协议生命周期仍留在现有 Core/ACP 归属,不据此宣称完整解耦 |
| ACP | CLI 托管的服务端仍以 `bitfun-core/product-full` 作为兼容执行层 | 入口已选择 `DeliveryProfile::Acp` 并消费 Runtime Parts;组装层在入队前原子拒绝忙碌会话,不改变其他产品入口的排队行为;活动会话模型与模式写入走 SDK。会话恢复及完整历史、模型/模式目录与配置读取、MCP、客户端与协议生命周期仍留在现有 Core/ACP 归属,不据此宣称完整解耦 |
| Server / Remote | 当前生产路由没有插件状态消费闭环;Remote 插件执行未实现 | 不在本地替远端项目发现、准备或执行插件;未接入时返回明确不支持 |
| Web / Mobile Web | 依赖现有后端入口,不持有插件执行单元 | 对应 profile 当前为空计划或未接入生产,不能据枚举值宣称独立产品能力 |
| SDK | 仅有 preview 门面、空 profile 计划和测试替身 | 不牵引 `product-full`、具体服务管理器或插件 host ABI;未满足独立嵌入验证前不宣称可发布 |
Expand Down
6 changes: 3 additions & 3 deletions docs/plans/core-decomposition-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ CLI 是首个入口迁移对象,因为它已有独立产品诉求、显式设
当前纵向切片已经完成:入口只提交一次 `DeliveryProfile::Cli`,通过现有 `ProductAssembler` 获得计划、服务可用性、
Harness 和禁用的插件 binding;TUI、Exec、Session 与 Usage 共用一个 `CliRuntimeContext`。主会话客户端的创建(包括
`exec --session-id` 和缺失后端会话通过独立固定 ID 方法按原 ID 重建)/列举/删除/恢复、类型化转录、本地分支、用量生成、
会话模型更新、轮次提交/取消和精确轮次结算均走 Agent Runtime SDK;TUI 用量卡片持久化、快照、Peer Host/ACP 的维护等
会话模型更新、ACP 活动会话模式更新、轮次提交/取消和精确轮次结算均走 Agent Runtime SDK;TUI 用量卡片持久化、快照、Peer Host/ACP 的维护等
未迁移能力继续集中在一个 Core 兼容门面。Agentic Event Queue 仍是唯一
owner,各入口只建立独立广播订阅,有界兼容队列满载不再阻断广播。TUI 与 Exec 审批均为调用级策略,不写全局
配置;CLI 本地路径不获取具体 PersistenceManager。交互、执行和管理入口分别控制 Peer Host/MCP 生命周期,管理查询不启动
Expand All @@ -73,8 +73,8 @@ Peer Host 的 Runtime 接入和跨 Relay/Desktop/Web 的协议切换保持独立

下一步按独立纵向切片推进:

1. 以真实调用方和行为等价测试逐项缩小快照及 Peer Host/ACP 持久化维护兼容面;远程分支另行定义身份和存储语义,模型目录与配置仍保留在产品入口。
2. 继续迁移 ACP 尚未接入 SDK 的持久化历史、模型目录/模式和 MCP 操作;ACP stdio 与协议投影生命周期保留在接口入口
1. 以真实调用方和行为等价测试逐项缩小快照及 Peer Host 持久化维护兼容面;远程分支另行定义身份和存储语义,模型目录与配置仍保留在产品入口。
2. ACP 完整历史继续使用单次 Core 兼容恢复;在出现第二个真实消费者及经过授权的附件读取能力前,不为协议回放扩张通用 transcript。模型/模式目录与配置读取、MCPACP stdio 和协议投影生命周期继续留在各自现有 owner
3. 继续按真实故障样例拆分 TUI 副作用边界;当前切片已覆盖本地确定性流式模型夹具驱动的 Linux PTY/Windows ConPTY Chat resize/取消、
`exec` Ctrl+C、本地模型 HTTP 403 授权拒绝、流中断后的重试失败、`stream-json` Patch 写入失败和终端恢复错误聚合,
不以大规模重写替代现有回归保护。
Expand Down
2 changes: 1 addition & 1 deletion docs/plans/product-architecture-evolution-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ HarmonyOS 手机 Remote App 不在该平台执行范围内。
类型化转录、本地分支、用量生成、轮次提交/取消与精确结算、活动会话模型更新和 TUI 工具确认/拒绝/用户问题回答
已由真实入口消费 Runtime SDK;交互模式下的 Peer Host 也通过同一 SDK 提交/精确取消 turn、更新活动会话模型并处理工具
确认/拒绝。远程分支保持不支持;TUI 用量卡片持久化、快照和 Peer Host/ACP 维护等产品操作继续由现有单一兼容路径转发。
- ACP:CLI 托管服务端的会话创建/列举、轮次提交/取消、活动会话模型更新、工具确认/拒绝、用户问题回答和事件订阅
- ACP:CLI 托管服务端的会话创建/列举、轮次提交/取消、活动会话模型/模式更新、工具确认/拒绝、用户问题回答和事件订阅
已复用同一 SDK 语义;ACP stdio、连接、权限 RPC 与通知生命周期仍留在接口入口。
- Desktop:主界面轮次提交/取消、活动会话模型更新、工具确认/拒绝和用户问题回答已通过现有协调器与调度器端口构造的窄口径 SDK 门面;
完整产品组装需等待真实必需服务与事件消费路径。会话 CRUD/恢复视图、模型目录/提供方配置、MCP、MiniApp、Cron、远程连接、
Expand Down
83 changes: 83 additions & 0 deletions src/crates/assembly/core/src/agentic/coordination/coordinator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8126,6 +8126,18 @@ impl bitfun_runtime_ports::AgentSessionModelPort for ConversationCoordinator {
}
}

#[async_trait::async_trait]
impl bitfun_runtime_ports::AgentSessionModePort for ConversationCoordinator {
async fn update_session_mode(
&self,
request: bitfun_runtime_ports::AgentSessionModeUpdateRequest,
) -> bitfun_runtime_ports::PortResult<()> {
self.update_session_agent_type(&request.session_id, &request.mode_id)
.await
.map_err(runtime_port_error_preserving_message)
}
}

#[async_trait::async_trait]
impl bitfun_agent_runtime::sdk::AgentSessionRestorePort for ConversationCoordinator {
async fn restore_session(
Expand Down Expand Up @@ -8648,6 +8660,77 @@ mod tests {
assert!(error.message.contains("missing-session"));
}

#[tokio::test]
async fn session_mode_port_preserves_core_not_found_errors() {
use bitfun_agent_runtime::sdk::{AgentSessionModePort, AgentSessionModeUpdateRequest};

let (coordinator, _) = test_coordinator();
let error = AgentSessionModePort::update_session_mode(
&coordinator,
AgentSessionModeUpdateRequest {
session_id: "missing-session".to_string(),
mode_id: "agentic".to_string(),
},
)
.await
.expect_err("missing session must remain a typed not-found error");

assert_eq!(error.kind, bitfun_runtime_ports::PortErrorKind::NotFound);
assert!(error.message.contains("missing-session"));
}

#[tokio::test]
async fn session_mode_runtime_updates_the_real_core_session() {
use bitfun_agent_runtime::sdk::{AgentRuntimeBuilder, AgentSessionModeUpdateRequest};

let (coordinator, session_manager) = test_coordinator();
let coordinator = Arc::new(coordinator);
let workspace_path = std::env::temp_dir().join(format!(
"bitfun-session-mode-runtime-test-{}",
uuid::Uuid::new_v4()
));
std::fs::create_dir_all(&workspace_path).expect("workspace dir should exist");
let workspace_path_string = workspace_path.to_string_lossy().into_owned();
let session = TEST_AGENT_MODEL_DEFAULTS
.scope(
AgentModelDefaultsConfig::default(),
coordinator.create_session_with_workspace(
None,
"Runtime mode update".to_string(),
"agentic".to_string(),
SessionConfig {
workspace_path: Some(workspace_path_string.clone()),
..Default::default()
},
workspace_path_string,
),
)
.await
.expect("real Core session should be created");
let runtime = AgentRuntimeBuilder::new()
.with_submission_port(coordinator.clone())
.with_session_mode_port(coordinator)
.build()
.expect("assembled agent runtime");

runtime
.update_session_mode(AgentSessionModeUpdateRequest {
session_id: session.session_id.clone(),
mode_id: " plan ".to_string(),
})
.await
.expect("runtime mode port should update the Core owner");

assert_eq!(
session_manager
.get_session(&session.session_id)
.map(|session| session.agent_type.clone())
.as_deref(),
Some("plan")
);
let _ = std::fs::remove_dir_all(workspace_path);
}

#[tokio::test]
async fn session_model_runtime_updates_the_real_core_session() {
use bitfun_agent_runtime::sdk::{AgentRuntimeBuilder, AgentSessionModelUpdateRequest};
Expand Down
Loading
Loading