@@ -245,6 +245,25 @@ pub async fn mountain_ipc_invoke(app_handle:AppHandle, command:String, args:Vec<
245245 "extensions:get" => handle_extensions_get ( runtime. inner ( ) . clone ( ) , args) . await ,
246246 "extensions:isActive" => handle_extensions_is_active ( runtime. inner ( ) . clone ( ) , args) . await ,
247247
248+ // Terminal commands
249+ "terminal:create" => handle_terminal_create ( runtime. inner ( ) . clone ( ) , args) . await ,
250+ "terminal:sendText" => handle_terminal_send_text ( runtime. inner ( ) . clone ( ) , args) . await ,
251+ "terminal:dispose" => handle_terminal_dispose ( runtime. inner ( ) . clone ( ) , args) . await ,
252+ "terminal:show" => handle_terminal_show ( runtime. inner ( ) . clone ( ) , args) . await ,
253+ "terminal:hide" => handle_terminal_hide ( runtime. inner ( ) . clone ( ) , args) . await ,
254+
255+ // Output channel commands
256+ "output:create" => handle_output_create ( app_handle. clone ( ) , args) . await ,
257+ "output:append" => handle_output_append ( app_handle. clone ( ) , args) . await ,
258+ "output:appendLine" => handle_output_append_line ( app_handle. clone ( ) , args) . await ,
259+ "output:clear" => handle_output_clear ( app_handle. clone ( ) , args) . await ,
260+ "output:show" => handle_output_show ( app_handle. clone ( ) , args) . await ,
261+
262+ // TextFile commands
263+ "textFile:read" => handle_textfile_read ( runtime. inner ( ) . clone ( ) , args) . await ,
264+ "textFile:write" => handle_textfile_write ( runtime. inner ( ) . clone ( ) , args) . await ,
265+ "textFile:save" => handle_textfile_save ( runtime. inner ( ) . clone ( ) , args) . await ,
266+
248267 // IPC status commands
249268 "mountain_get_status" => {
250269 let status = json ! ( {
@@ -820,6 +839,188 @@ async fn handle_workbench_configuration(runtime:Arc<ApplicationRunTime>, _args:V
820839 Ok ( config)
821840}
822841
842+ // ============================================================================
843+ // Terminal Handlers
844+ // ============================================================================
845+
846+ /// Create a new PTY terminal via TerminalProvider.
847+ async fn handle_terminal_create ( runtime : Arc < ApplicationRunTime > , args : Vec < Value > ) -> Result < Value , String > {
848+ use CommonLibrary :: Terminal :: TerminalProvider :: TerminalProvider ;
849+
850+ let Options = args. first ( ) . cloned ( ) . unwrap_or ( Value :: Null ) ;
851+ runtime
852+ . Environment
853+ . CreateTerminal ( Options )
854+ . await
855+ . map_err ( |Error | format ! ( "terminal:create failed: {}" , Error ) )
856+ }
857+
858+ /// Write text to PTY stdin via TerminalProvider.
859+ async fn handle_terminal_send_text ( runtime : Arc < ApplicationRunTime > , args : Vec < Value > ) -> Result < Value , String > {
860+ use CommonLibrary :: Terminal :: TerminalProvider :: TerminalProvider ;
861+
862+ let TerminalId = args
863+ . first ( )
864+ . and_then ( |V | V . as_u64 ( ) )
865+ . ok_or_else ( || "terminal:sendText requires terminal_id as first argument" . to_string ( ) ) ?;
866+ let Text = args
867+ . get ( 1 )
868+ . and_then ( |V | V . as_str ( ) )
869+ . unwrap_or ( "" )
870+ . to_string ( ) ;
871+
872+ runtime
873+ . Environment
874+ . SendTextToTerminal ( TerminalId , Text )
875+ . await
876+ . map ( |( ) | Value :: Null )
877+ . map_err ( |Error | format ! ( "terminal:sendText failed: {}" , Error ) )
878+ }
879+
880+ /// Dispose a terminal via TerminalProvider.
881+ async fn handle_terminal_dispose ( runtime : Arc < ApplicationRunTime > , args : Vec < Value > ) -> Result < Value , String > {
882+ use CommonLibrary :: Terminal :: TerminalProvider :: TerminalProvider ;
883+
884+ let TerminalId = args
885+ . first ( )
886+ . and_then ( |V | V . as_u64 ( ) )
887+ . ok_or_else ( || "terminal:dispose requires terminal_id as first argument" . to_string ( ) ) ?;
888+
889+ runtime
890+ . Environment
891+ . DisposeTerminal ( TerminalId )
892+ . await
893+ . map ( |( ) | Value :: Null )
894+ . map_err ( |Error | format ! ( "terminal:dispose failed: {}" , Error ) )
895+ }
896+
897+ /// Show a terminal in the UI.
898+ async fn handle_terminal_show ( runtime : Arc < ApplicationRunTime > , args : Vec < Value > ) -> Result < Value , String > {
899+ use CommonLibrary :: Terminal :: TerminalProvider :: TerminalProvider ;
900+
901+ let TerminalId = args. first ( ) . and_then ( |V | V . as_u64 ( ) ) . unwrap_or ( 0 ) ;
902+ let PreserveFocus = args. get ( 1 ) . and_then ( |V | V . as_bool ( ) ) . unwrap_or ( false ) ;
903+
904+ runtime
905+ . Environment
906+ . ShowTerminal ( TerminalId , PreserveFocus )
907+ . await
908+ . map ( |( ) | Value :: Null )
909+ . map_err ( |Error | format ! ( "terminal:show failed: {}" , Error ) )
910+ }
911+
912+ /// Hide a terminal.
913+ async fn handle_terminal_hide ( runtime : Arc < ApplicationRunTime > , args : Vec < Value > ) -> Result < Value , String > {
914+ use CommonLibrary :: Terminal :: TerminalProvider :: TerminalProvider ;
915+
916+ let TerminalId = args. first ( ) . and_then ( |V | V . as_u64 ( ) ) . unwrap_or ( 0 ) ;
917+
918+ runtime
919+ . Environment
920+ . HideTerminal ( TerminalId )
921+ . await
922+ . map ( |( ) | Value :: Null )
923+ . map_err ( |Error | format ! ( "terminal:hide failed: {}" , Error ) )
924+ }
925+
926+ // ============================================================================
927+ // Output Channel Handlers
928+ // ============================================================================
929+
930+ /// Create a named output channel. Returns the channel name as its handle.
931+ async fn handle_output_create ( _app_handle : AppHandle , args : Vec < Value > ) -> Result < Value , String > {
932+ let ChannelName = args
933+ . first ( )
934+ . and_then ( |V | V . as_str ( ) )
935+ . unwrap_or ( "Output" )
936+ . to_string ( ) ;
937+ info ! ( "[WindServiceHandlers] output:create channel='{}'" , ChannelName ) ;
938+ // Sky/frontend creates the channel panel on the `sky://output/create` event
939+ Ok ( json ! ( { "channelName" : ChannelName } ) )
940+ }
941+
942+ /// Append text to an output channel.
943+ async fn handle_output_append ( app_handle : AppHandle , args : Vec < Value > ) -> Result < Value , String > {
944+ use tauri:: Emitter ;
945+
946+ let ChannelName = args. first ( ) . and_then ( |V | V . as_str ( ) ) . unwrap_or ( "" ) . to_string ( ) ;
947+ let Text = args. get ( 1 ) . and_then ( |V | V . as_str ( ) ) . unwrap_or ( "" ) . to_string ( ) ;
948+
949+ let _ = app_handle. emit ( "sky://output/append" , json ! ( { "channel" : ChannelName , "text" : Text } ) ) ;
950+ Ok ( Value :: Null )
951+ }
952+
953+ /// Append a line to an output channel (text + newline).
954+ async fn handle_output_append_line ( app_handle : AppHandle , args : Vec < Value > ) -> Result < Value , String > {
955+ use tauri:: Emitter ;
956+
957+ let ChannelName = args. first ( ) . and_then ( |V | V . as_str ( ) ) . unwrap_or ( "" ) . to_string ( ) ;
958+ let Text = args. get ( 1 ) . and_then ( |V | V . as_str ( ) ) . unwrap_or ( "" ) . to_string ( ) ;
959+ let Line = format ! ( "{}\n " , Text ) ;
960+
961+ let _ = app_handle. emit ( "sky://output/append" , json ! ( { "channel" : ChannelName , "text" : Line } ) ) ;
962+ Ok ( Value :: Null )
963+ }
964+
965+ /// Clear an output channel.
966+ async fn handle_output_clear ( app_handle : AppHandle , args : Vec < Value > ) -> Result < Value , String > {
967+ use tauri:: Emitter ;
968+
969+ let ChannelName = args. first ( ) . and_then ( |V | V . as_str ( ) ) . unwrap_or ( "" ) . to_string ( ) ;
970+ let _ = app_handle. emit ( "sky://output/clear" , json ! ( { "channel" : ChannelName } ) ) ;
971+ Ok ( Value :: Null )
972+ }
973+
974+ /// Show an output channel panel.
975+ async fn handle_output_show ( app_handle : AppHandle , args : Vec < Value > ) -> Result < Value , String > {
976+ use tauri:: Emitter ;
977+
978+ let ChannelName = args. first ( ) . and_then ( |V | V . as_str ( ) ) . unwrap_or ( "" ) . to_string ( ) ;
979+ let _ = app_handle. emit ( "sky://output/show" , json ! ( { "channel" : ChannelName } ) ) ;
980+ Ok ( Value :: Null )
981+ }
982+
983+ // ============================================================================
984+ // TextFile Handlers
985+ // ============================================================================
986+
987+ /// Read a text file from disk.
988+ async fn handle_textfile_read ( _runtime : Arc < ApplicationRunTime > , args : Vec < Value > ) -> Result < Value , String > {
989+ let Path = args
990+ . first ( )
991+ . and_then ( |V | V . as_str ( ) )
992+ . ok_or_else ( || "textFile:read requires path as first argument" . to_string ( ) ) ?;
993+
994+ tokio:: fs:: read_to_string ( Path ) . await . map ( Value :: String ) . map_err ( |Error | {
995+ format ! ( "textFile:read failed: {}" , Error )
996+ } )
997+ }
998+
999+ /// Write text to a file on disk.
1000+ async fn handle_textfile_write ( _runtime : Arc < ApplicationRunTime > , args : Vec < Value > ) -> Result < Value , String > {
1001+ let Path = args
1002+ . first ( )
1003+ . and_then ( |V | V . as_str ( ) )
1004+ . ok_or_else ( || "textFile:write requires path as first argument" . to_string ( ) ) ?;
1005+ let Content = args
1006+ . get ( 1 )
1007+ . and_then ( |V | V . as_str ( ) )
1008+ . unwrap_or ( "" )
1009+ . to_string ( ) ;
1010+
1011+ tokio:: fs:: write ( Path , Content . as_bytes ( ) ) . await . map ( |( ) | Value :: Null ) . map_err ( |Error | {
1012+ format ! ( "textFile:write failed: {}" , Error )
1013+ } )
1014+ }
1015+
1016+ /// Save a document — forward save intent to Sky frontend.
1017+ async fn handle_textfile_save ( _runtime : Arc < ApplicationRunTime > , args : Vec < Value > ) -> Result < Value , String > {
1018+ // Actual disk write happens via textFile:write; this is a UI-dirty-state hint.
1019+ let _Uri = args. first ( ) . and_then ( |V | V . as_str ( ) ) . unwrap_or ( "" ) . to_string ( ) ;
1020+ info ! ( "[WindServiceHandlers] textFile:save uri={:?}" , _Uri) ;
1021+ Ok ( Value :: Null )
1022+ }
1023+
8231024/// Register all Wind IPC command handlers
8241025pub fn register_wind_ipc_handlers ( app_handle : & tauri:: AppHandle ) -> Result < ( ) , String > {
8251026 info ! ( "[WindServiceHandlers] Registering Wind IPC command handlers" ) ;
0 commit comments