Skip to content

Commit bceded2

Browse files
committed
refactor(core): route remote exec through runtime port
1 parent 85f8407 commit bceded2

33 files changed

Lines changed: 1099 additions & 109 deletions

File tree

‎docs/plans/core-decomposition-completed.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
- `bitfun-events` 已承接 backend event DTO、agentic event DTO、framework-neutral Agentic frontend event projection 和 platform-neutral `EventEmitter` trait;Tauri/WebSocket transport 只负责 delivery。
2222
- `services-integrations` 已承接 remote-connect primitives、wire command routing / response assembly、LAN IP/URL 探测、ngrok 进程/tunnel lifecycle、mobile-web relay upload manifest / incremental upload / fallback upload、IM bot provider-neutral config / persistence / file auto-push / locale / menu / state / command parsing、Weixin provider client、workspace search concrete owner、remote SSH/SFTP/PTY owner、Remote SSH disabled runtime surface、Remote SSH workspace/session identity helper、remote workspace-search disabled surface、DeepResearch report IO / display-map sidecar、MiniApp host dispatch / storage / worker / import IO、announcement remote fetch/cache、browser CDP endpoint HTTP probing / page creation、WebFetch / WebSearch concrete HTTP provider、debug-log HTTP ingest posting、review-platform HTTP transport,以及 MCP server registry、connection pool、catalog cache、reconnect retry state、runtime-only config overlay、local command resolution helper 和 lifecycle status policy。
2323
- `tool-contracts` 已承接 provider-neutral tool DTO、manifest/catalog/admission/result presentation、Computer Use DTO/input parser/screenshot payload、confirmation facts、truncation recovery presentation、runtime restriction policy 和 provider-entry materialization;core 只保留 Computer Use 旧 public path re-export / compatibility shim 与产品执行入口。
24-
- `tool-execution` 已承接 local / remote IO helper、Bash shell helper、batching plan、retry policy、state counting、tool state event payload shaping / result redaction、cancellation-state/token-store policy、background exec output capture、ExecCommand provider-neutral 呈现 / 输入默认值 / 结果 shape / shell metadata / shell argv / remote shell probe / remote env snapshot 解析、cache 与 capture policy / lifecycle facts / control facts / completion shape、prompt-safe tool context facts / custom-data materialization、Computer Use loop detection / screenshot hash / verification / retry policy,以及 File tool 的 provider-neutral 结果展示、写入 mode/status/line-count 规则、Edit guardrail 分类和 Delete success 文本;core 只保留 ToolResult 包装、权限、checkpoint、runtime handles、process manager / host adapter 调用、read-state adapter、remote shell/FS 调用和旧工具入口。
25-
- `runtime-ports` / `terminal-core` 已承接本地 ExecCommand 会话执行端口和 concrete provider:`TerminalPort` 暴露本地命令执行、stdin 写入、会话控制和生命周期事件边界,`TerminalRuntimePort` 复用原 `ExecProcessManager` 行为,desktop/server/CLI 等产品入口通过 `CoreRuntimeServicesProvider` 构造 terminal provider 并显式注入 `ConversationCoordinator` / 执行上下文 / `ToolRuntimeHandles`;core 本地 `ExecCommand` / `WriteStdin` / `ExecControl` 只消费端口,不再直接调用全局本地进程 manager。远端 SSH ExecCommand 仍是单独 remote/product command adapter 待迁移项。
24+
- `tool-execution` 已承接 local / remote IO helper、Bash shell helper、batching plan、retry policy、state counting、tool state event payload shaping / result redaction、cancellation-state/token-store policy、background exec output capture、ExecCommand provider-neutral 呈现 / 输入默认值 / 结果 shape / shell metadata / shell argv / remote shell probe / remote env snapshot 解析、cache 与 capture policy / lifecycle facts / control facts / completion shape、prompt-safe tool context facts / custom-data materialization、Computer Use loop detection / screenshot hash / verification / retry policy,以及 File tool 的 provider-neutral 结果展示、写入 mode/status/line-count 规则、Edit guardrail 分类和 Delete success 文本;core 只保留 ToolResult 包装、权限、checkpoint、runtime handles、host adapter 调用、read-state adapter、remote FS 调用和旧工具入口。
25+
- `runtime-ports` / `terminal-core` / `services-integrations` 已承接 ExecCommand 会话执行端口和 concrete provider:`TerminalPort` 暴露本地命令执行、stdin 写入、会话控制和生命周期事件边界,`RemoteExecPort` 暴露远端 SSH 命令执行、bounded one-shot command、stdin、会话控制和生命周期事件边界;`TerminalRuntimePort` 复用原本地 `ExecProcessManager` 行为,`RemoteExecRuntimePort` 复用原 remote exec manager 与旧 SSH one-shot 行为,当前 desktop / CLI 产品入口和保留 server bootstrap 初始化路径通过 `CoreRuntimeServicesProvider` 构造 provider 并显式注入 `ConversationCoordinator` / 执行上下文 / `ToolRuntimeHandles`;core `ExecCommand` / `WriteStdin` / `ExecControl` 只消费端口,不再直接调用全局本地或远端进程 manager。
2626
- `agent-runtime` 已承接 scheduler/background delivery 纯决策、dialog lifecycle port contracts、runtime event queue/router、session management/cancellation port contracts、session/config/summary facts、persisted session state sidecar / processing-state sanitization、session state facts / event-label projection、session state manager / event emission owner、dialog-turn id / stats facts、side-question runtime-only tracking、thread-goal facts、context profile / model capability policy、prompt markup / prompt / prompt-cache facts 与持久化写入决策、remote file delivery prompt facts、turn skill/agent snapshot DTO/diff/render/store、file-read session state / prior-read guardrail / freshness 决策、session evidence ledger 与 compression-contract projection、dialog-turn cancellation token store、tool confirmation gate / wait channel state、user-question wait channel state、custom agent / mode / subagent schema、默认值、discovery/loading、markdown IO、validation、review 工具过滤、skill catalog/root specs、mode policy、selection/shadow/mode-info 规则、assistant payload rendering、post-call hook routing、DeepReview provider-neutral policy/queue/retry/diagnostics shaping 与 queue event payload shaping、DeepResearch citation renumber 与 report post-process gate,并建立不暴露 `bitfun-core` / `product-full` / concrete manager 的内部 SDK facade。SDK facade 已支持注入 fake runtime services、tool registry、harness registry、hook registry 和 agent registry。
2727
- `harness` 已建立 descriptor、route plan 和 legacy provider registry。
2828
- `product-domains` 已承接 MiniApp state/workflow planning、built-in seed orchestration / host adapter contract、compile / permission adaptation、import lifecycle、AI / Agent permission、rate-limit、model/message/session/workspace/turn-text bridge rules、AI / Agent 请求计划、stream / runtime event payload、worker restart / draft key / workspace input 规则、function-agent prompt/parser/response policy 和部分 Git snapshot/fallback 逻辑。

‎docs/plans/core-decomposition-plan.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@
8787
当前大型 PR 批次:
8888

8989
- Platform Provider Closure 已继续收口具备服务层 owner 的 concrete provider:remote-connect LAN IP/URL 探测、ngrok 进程/tunnel lifecycle、mobile-web relay 上传、announcement remote fetch/cache、browser CDP endpoint HTTP probing / page creation、WebFetch / WebSearch concrete HTTP provider、debug-log HTTP ingest posting 和 review-platform HTTP transport。core 保留兼容 facade、配置读取、产品编排、provider DTO 映射和工具结果 envelope。
90-
- Terminal / ExecCommand 路径已迁出 provider-neutral 输入默认值、结果 shape、shell metadata、shell argv、PowerShell UTF-8 policy、remote shell probe、remote env snapshot 解析/cache/capture policy、remote non-TTY control wrapper 和 lifecycle status facts;本地 concrete execution 已通过 `TerminalPort` / `TerminalRuntimePort` 收口到 desktop/server/CLI 等产品入口显式注入的 terminal provider,并由执行上下文传递到工具 runtime handles。core 本地 `ExecCommand` / `WriteStdin` / `ExecControl` 不再直接调用全局本地进程 manager,只保留工具入口、权限/checkpoint 和结果 envelope。
91-
- 后续仍需迁移 remote ExecCommand/product 命令路径、Computer Use OS action、部分 Git/process/session host adapter、MCP auth URL helper 和 OpenCode/UI extension 的真实消费路径;这些路径必须在具备等价测试、host port 和交付形态矩阵后再迁移。
90+
- Terminal / ExecCommand 路径已迁出 provider-neutral 输入默认值、结果 shape、shell metadata、shell argv、PowerShell UTF-8 policy、remote shell probe、remote env snapshot 解析/cache/capture policy、remote non-TTY control wrapper 和 lifecycle status facts;本地 concrete execution 已通过 `TerminalPort` / `TerminalRuntimePort` 收口到当前 desktop / CLI 产品入口显式注入的 terminal provider,远端 SSH concrete execution 已通过 `RemoteExecPort` / `RemoteExecRuntimePort` 收口到 services-integrations remote owner,bounded shell probe 通过端口保留旧 SSH one-shot stdout/stderr/timeout 语义,并由执行上下文传递到工具 runtime handles。core `ExecCommand` / `WriteStdin` / `ExecControl` 不再直接调用全局本地或远端进程 manager,只保留工具入口、权限/checkpoint 和结果 envelope。
91+
- 后续仍需迁移 Computer Use OS action、部分 Git/process/session host adapter、MCP auth URL helper 和 OpenCode/UI extension 的真实消费路径;这些路径必须在具备等价测试、host port 和交付形态矩阵后再迁移。
9292

9393
保护:
9494

‎scripts/core-boundaries/rules/source/forbidden-rules.mjs‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,6 +1570,21 @@ export const forbiddenContentRules = [
15701570
message:
15711571
'core local ExecCommand adapter must not call the global local process manager; use injected TerminalPort',
15721572
},
1573+
{
1574+
regex: /\bget_global_remote_exec_process_manager\b/,
1575+
message:
1576+
'core remote ExecCommand adapter must not call the global remote process manager; use injected RemoteExecPort',
1577+
},
1578+
{
1579+
regex: /\bSSHConnectionManager\b/,
1580+
message:
1581+
'core remote ExecCommand adapter must not depend on concrete SSH managers; use injected RemoteExecPort',
1582+
},
1583+
{
1584+
regex: /\bSSHCommandOptions\b/,
1585+
message:
1586+
'core remote ExecCommand adapter must not depend on concrete SSH command options; use injected RemoteExecPort',
1587+
},
15731588
{
15741589
regex: /\bLocalExecCommandRequest\b/,
15751590
message:
@@ -1620,6 +1635,16 @@ export const forbiddenContentRules = [
16201635
message:
16211636
'core local WriteStdin adapter must not call the global local process manager; use injected TerminalPort',
16221637
},
1638+
{
1639+
regex: /\bget_global_remote_exec_process_manager\b/,
1640+
message:
1641+
'core remote WriteStdin adapter must not call the global remote process manager; use injected RemoteExecPort',
1642+
},
1643+
{
1644+
regex: /\bRemoteExecError\b/,
1645+
message:
1646+
'core remote WriteStdin adapter must not match concrete remote exec errors; use PortErrorKind',
1647+
},
16231648
{
16241649
regex: /\bLocalWriteStdinRequest\b/,
16251650
message:
@@ -1655,6 +1680,16 @@ export const forbiddenContentRules = [
16551680
message:
16561681
'core local ExecControl adapter must not call the global local process manager; use injected TerminalPort',
16571682
},
1683+
{
1684+
regex: /\bget_global_remote_exec_process_manager\b/,
1685+
message:
1686+
'core remote ExecControl adapter must not call the global remote process manager; use injected RemoteExecPort',
1687+
},
1688+
{
1689+
regex: /\bRemoteExecError\b/,
1690+
message:
1691+
'core remote ExecControl adapter must not match concrete remote exec errors; use PortErrorKind',
1692+
},
16581693
{
16591694
regex: /\bLocalExecControlRequest\b/,
16601695
message:
@@ -1680,6 +1715,11 @@ export const forbiddenContentRules = [
16801715
message:
16811716
'core local ExecCommand input adapter must not call the global local process manager; use injected TerminalPort',
16821717
},
1718+
{
1719+
regex: /\bget_global_remote_exec_process_manager\b/,
1720+
message:
1721+
'core remote ExecCommand input adapter must not call the global remote process manager; use injected RemoteExecPort',
1722+
},
16831723
{
16841724
regex: /\bLocalSendStdinRequest\b/,
16851725
message:
@@ -1745,6 +1785,16 @@ export const forbiddenContentRules = [
17451785
message:
17461786
'core exec_command env snapshot adapter must not own snapshot cache ttl; use tool-runtime exec_command',
17471787
},
1788+
{
1789+
regex: /\bget_global_remote_exec_process_manager\b/,
1790+
message:
1791+
'core exec_command env snapshot adapter must not call the global remote process manager; use injected RemoteExecPort',
1792+
},
1793+
{
1794+
regex: /\bSSHConnectionManager\b/,
1795+
message:
1796+
'core exec_command env snapshot adapter must not depend on concrete SSH managers; use injected RemoteExecPort',
1797+
},
17481798
],
17491799
},
17501800
{

‎scripts/core-boundaries/self-test.mjs‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,9 @@ export function runManifestParserSelfTest({
989989
'command\\s+-v\\s+bash',
990990
'REMOTE_SHELL_PROBE_TIMEOUT_MS',
991991
'get_global_exec_process_manager',
992+
'get_global_remote_exec_process_manager',
993+
'SSHConnectionManager',
994+
'SSHCommandOptions',
992995
'LocalExecCommandRequest',
993996
'CoreRuntimeServicesProvider::terminal_port',
994997
'TerminalRuntimePort',
@@ -1007,6 +1010,8 @@ export function runManifestParserSelfTest({
10071010
'"status"\\s*:\\s*"session_not_found"',
10081011
'No input was sent',
10091012
'get_global_exec_process_manager',
1013+
'get_global_remote_exec_process_manager',
1014+
'RemoteExecError',
10101015
'LocalWriteStdinRequest',
10111016
'CoreRuntimeServicesProvider::terminal_port',
10121017
'TerminalRuntimePort',
@@ -1026,6 +1031,8 @@ export function runManifestParserSelfTest({
10261031
}
10271032
for (const contract of [
10281033
'get_global_exec_process_manager',
1034+
'get_global_remote_exec_process_manager',
1035+
'RemoteExecError',
10291036
'LocalExecControlRequest',
10301037
'CoreRuntimeServicesProvider::terminal_port',
10311038
'TerminalRuntimePort',
@@ -1039,6 +1046,7 @@ export function runManifestParserSelfTest({
10391046
);
10401047
for (const contract of [
10411048
'get_global_exec_process_manager',
1049+
'get_global_remote_exec_process_manager',
10421050
'LocalSendStdinRequest',
10431051
'CoreRuntimeServicesProvider::terminal_port',
10441052
'TerminalRuntimePort',
@@ -1060,6 +1068,8 @@ export function runManifestParserSelfTest({
10601068
'ENV_SNAPSHOT_TIMEOUT_MS',
10611069
'ENV_SNAPSHOT_MAX_OUTPUT_CHARS',
10621070
'ENV_SNAPSHOT_TTL',
1071+
'get_global_remote_exec_process_manager',
1072+
'SSHConnectionManager',
10631073
]) {
10641074
if (!coreExecCommandEnvSnapshotRuleText.includes(contract)) {
10651075
throw new Error(`core exec_command env_snapshot boundary rule must forbid ${contract}`);

‎src/apps/cli/src/agent/agentic_system.rs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ pub async fn init_agentic_system() -> Result<AgenticSystem> {
1313
system
1414
.coordinator
1515
.set_terminal_port(CoreRuntimeServicesProvider::terminal_port());
16+
system
17+
.coordinator
18+
.set_remote_exec_port(CoreRuntimeServicesProvider::remote_exec_port());
1619
Ok(system)
1720
}
1821

‎src/apps/desktop/src/api/agentic_api.rs‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,6 +1534,11 @@ pub async fn control_background_command(
15341534
} else {
15351535
coordinator.inner().terminal_port()
15361536
};
1537+
let remote_exec_port = if remote {
1538+
coordinator.inner().remote_exec_port()
1539+
} else {
1540+
None
1541+
};
15371542

15381543
control_exec_command_session(
15391544
ExecCommandControlRequest {
@@ -1544,6 +1549,7 @@ pub async fn control_background_command(
15441549
yield_time_ms: Some(250),
15451550
},
15461551
terminal_port.as_ref(),
1552+
remote_exec_port.as_ref(),
15471553
)
15481554
.await
15491555
.map(|response| {
@@ -1606,6 +1612,11 @@ pub async fn send_background_command_input(
16061612
} else {
16071613
coordinator.inner().terminal_port()
16081614
};
1615+
let remote_exec_port = if remote {
1616+
coordinator.inner().remote_exec_port()
1617+
} else {
1618+
None
1619+
};
16091620
send_exec_command_input(
16101621
ExecCommandInputRequest {
16111622
session_id,
@@ -1614,6 +1625,7 @@ pub async fn send_background_command_input(
16141625
remote,
16151626
},
16161627
terminal_port.as_ref(),
1628+
remote_exec_port.as_ref(),
16171629
)
16181630
.await
16191631
.map_err(|e| {

‎src/apps/desktop/src/api/tool_api.rs‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use bitfun_core::agentic::{
1212
workspace::{local_workspace_services, remote_workspace_services},
1313
WorkspaceBinding,
1414
};
15+
use bitfun_core::product_runtime::CoreRuntimeServicesProvider;
1516
use bitfun_core::service::remote_ssh::workspace_state::{
1617
get_remote_workspace_manager, lookup_remote_connection, workspace_session_identity,
1718
};
@@ -172,7 +173,16 @@ async fn build_tool_context(workspace_path: Option<&str>) -> ToolUseContext {
172173
None => None,
173174
};
174175

175-
ToolUseContext::for_tool_listing(workspace, workspace_services)
176+
let remote_exec_port = workspace
177+
.as_ref()
178+
.is_some_and(WorkspaceBinding::is_remote)
179+
.then(CoreRuntimeServicesProvider::remote_exec_port);
180+
181+
ToolUseContext::for_tool_listing_with_remote_exec_port(
182+
workspace,
183+
workspace_services,
184+
remote_exec_port,
185+
)
176186
}
177187

178188
fn to_dynamic_mcp_tool_info(

‎src/apps/desktop/src/lib.rs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,6 +1387,9 @@ async fn init_agentic_system() -> anyhow::Result<(
13871387
coordinator.set_terminal_port(
13881388
bitfun_core::product_runtime::CoreRuntimeServicesProvider::terminal_port(),
13891389
);
1390+
coordinator.set_remote_exec_port(
1391+
bitfun_core::product_runtime::CoreRuntimeServicesProvider::remote_exec_port(),
1392+
);
13901393

13911394
coordination::ConversationCoordinator::set_global(coordinator.clone());
13921395

‎src/apps/server/src/bootstrap.rs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ pub async fn initialize(workspace: Option<String>) -> anyhow::Result<Arc<ServerA
104104
coordinator.set_terminal_port(
105105
bitfun_core::product_runtime::CoreRuntimeServicesProvider::terminal_port(),
106106
);
107+
coordinator.set_remote_exec_port(
108+
bitfun_core::product_runtime::CoreRuntimeServicesProvider::remote_exec_port(),
109+
);
107110

108111
coordination::ConversationCoordinator::set_global(coordinator.clone());
109112

0 commit comments

Comments
 (0)