@@ -3052,7 +3052,19 @@ impl CoreRemoteSessionRuntimeHost {
30523052 pub ( crate ) fn new ( ) -> Result < Self , String > {
30533053 let coordinator = get_global_coordinator ( )
30543054 . ok_or_else ( || "Desktop session system not ready" . to_string ( ) ) ?;
3055- let runtime = CoreServiceAgentRuntime :: agent_runtime ( coordinator. clone ( ) ) ?;
3055+ let scheduler = get_global_scheduler ( )
3056+ . ok_or_else ( || "Dialog scheduler is not initialized" . to_string ( ) ) ?;
3057+ Self :: from_owners ( coordinator, scheduler)
3058+ }
3059+
3060+ fn from_owners (
3061+ coordinator : Arc < ConversationCoordinator > ,
3062+ scheduler : Arc < DialogScheduler > ,
3063+ ) -> Result < Self , String > {
3064+ let runtime = CoreServiceAgentRuntime :: agent_runtime_with_lifecycle_delivery (
3065+ coordinator. clone ( ) ,
3066+ scheduler,
3067+ ) ?;
30563068 Ok ( Self {
30573069 coordinator,
30583070 runtime,
@@ -3921,6 +3933,89 @@ mod tests {
39213933 } ;
39223934 use crate :: OpenBitFunError ;
39233935
3936+ #[ tokio:: test]
3937+ async fn remote_session_host_registers_targeted_rollback_port ( ) {
3938+ use crate :: agentic:: events:: { EventQueue , EventQueueConfig , EventRouter } ;
3939+ use crate :: agentic:: execution:: {
3940+ ExecutionEngine , ExecutionEngineConfig , RoundExecutor , StreamProcessor ,
3941+ } ;
3942+ use crate :: agentic:: persistence:: PersistenceManager ;
3943+ use crate :: agentic:: session:: { ContextCompressor , SessionContextStore , SessionManager } ;
3944+ use crate :: agentic:: tools:: { registry:: ToolRegistry , ToolPipeline , ToolStateManager } ;
3945+
3946+ let directory = tempfile:: tempdir ( ) . expect ( "runtime fixture" ) ;
3947+ let paths = Arc :: new (
3948+ crate :: infrastructure:: PathManager :: with_user_root_for_tests (
3949+ directory. path ( ) . join ( "user-root" ) ,
3950+ ) ,
3951+ ) ;
3952+ let sessions = Arc :: new ( SessionManager :: new (
3953+ Arc :: new ( SessionContextStore :: new ( ) ) ,
3954+ Arc :: new ( PersistenceManager :: new ( paths) . expect ( "persistence manager" ) ) ,
3955+ Default :: default ( ) ,
3956+ ) ) ;
3957+ let events = Arc :: new ( EventQueue :: new ( EventQueueConfig :: default ( ) ) ) ;
3958+ let tools = Arc :: new ( ToolPipeline :: new (
3959+ Arc :: new ( tokio:: sync:: RwLock :: new ( ToolRegistry :: new ( ) ) ) ,
3960+ Arc :: new ( ToolStateManager :: new ( events. clone ( ) ) ) ,
3961+ None ,
3962+ ) ) ;
3963+ let engine = Arc :: new ( ExecutionEngine :: new (
3964+ Arc :: new ( RoundExecutor :: new (
3965+ Arc :: new ( StreamProcessor :: new ( events. clone ( ) ) ) ,
3966+ events. clone ( ) ,
3967+ tools. clone ( ) ,
3968+ ) ) ,
3969+ events. clone ( ) ,
3970+ sessions. clone ( ) ,
3971+ Arc :: new ( ContextCompressor :: new ( ) ) ,
3972+ ExecutionEngineConfig :: default ( ) ,
3973+ ) ) ;
3974+ let coordinator = Arc :: new ( ConversationCoordinator :: new (
3975+ sessions. clone ( ) ,
3976+ engine,
3977+ tools,
3978+ events,
3979+ Arc :: new ( EventRouter :: new ( ) ) ,
3980+ Arc :: new (
3981+ crate :: runtime_ownership:: CoreRuntimeOwnership :: embedded_with_facts (
3982+ directory. path ( ) . join ( "ownership" ) ,
3983+ "openbitfun" . to_string ( ) ,
3984+ "test" ,
3985+ ) ,
3986+ ) ,
3987+ ) ) ;
3988+ let scheduler = DialogScheduler :: new ( coordinator. clone ( ) , sessions) ;
3989+ let host = CoreRemoteSessionRuntimeHost :: from_owners ( coordinator, scheduler)
3990+ . expect ( "remote session host" ) ;
3991+
3992+ // Invalid identity must reach the registered revert provider's validation.
3993+ let error = host
3994+ . runtime
3995+ . rollback_session_to_turn ( AgentSessionRollbackToTurnRequest {
3996+ workspace_path : String :: new ( ) ,
3997+ workspace_id : None ,
3998+ workspace_hostname : None ,
3999+ session_id : "../invalid-session" . to_string ( ) ,
4000+ target_turn_id : "turn-1" . to_string ( ) ,
4001+ require_idle : true ,
4002+ expected_storage_turn_index : None ,
4003+ expected_catalog_revision : None ,
4004+ remote_connection_id : None ,
4005+ remote_ssh_host : None ,
4006+ } )
4007+ . await
4008+ . expect_err ( "invalid session identity" ) ;
4009+ assert ! (
4010+ matches!(
4011+ error,
4012+ openbitfun_agent_runtime:: sdk:: RuntimeError :: Port ( ref port)
4013+ if port. kind == openbitfun_runtime_ports:: PortErrorKind :: InvalidRequest
4014+ ) ,
4015+ "expected revert provider validation, got {error}"
4016+ ) ;
4017+ }
4018+
39244019 #[ test]
39254020 fn local_workspace_marker_is_not_remote_routing_authority ( ) {
39264021 use crate :: service:: workspace:: WorkspaceKind ;
0 commit comments