@@ -39,10 +39,15 @@ public enum MessageType : int
39
39
/// </summary>
40
40
RunCommand = 5 ,
41
41
42
+ /// <summary>
43
+ /// A message from AIShell to command-line shell to ask for the result of a previous command run.
44
+ /// </summary>
45
+ AskCommandOutput = 6 ,
46
+
42
47
/// <summary>
43
48
/// A message from command-line shell to AIShell to post the result of a command.
44
49
/// </summary>
45
- PostResult = 6 ,
50
+ PostResult = 7 ,
46
51
}
47
52
48
53
/// <summary>
@@ -239,6 +244,27 @@ public RunCommandMessage(string command, bool blocking)
239
244
}
240
245
}
241
246
247
+ /// <summary>
248
+ /// Message for <see cref="MessageType.AskCommandOutput"/>.
249
+ /// </summary>
250
+ public sealed class AskCommandOutputMessage : PipeMessage
251
+ {
252
+ /// <summary>
253
+ /// Gets the id of the command to retrieve the output for.
254
+ /// </summary>
255
+ public string CommandId { get ; }
256
+
257
+ /// <summary>
258
+ /// Creates an instance of <see cref="AskCommandOutputMessage"/>.
259
+ /// </summary>
260
+ public AskCommandOutputMessage ( string commandId )
261
+ : base ( MessageType . AskCommandOutput )
262
+ {
263
+ ArgumentException . ThrowIfNullOrEmpty ( commandId ) ;
264
+ CommandId = commandId ;
265
+ }
266
+ }
267
+
242
268
/// <summary>
243
269
/// Message for <see cref="MessageType.PostResult"/>.
244
270
/// </summary>
@@ -426,6 +452,7 @@ private static PipeMessage DeserializePayload(int type, ReadOnlySpan<byte> bytes
426
452
( int ) MessageType . PostContext => JsonSerializer . Deserialize < PostContextMessage > ( bytes ) ,
427
453
( int ) MessageType . PostCode => JsonSerializer . Deserialize < PostCodeMessage > ( bytes ) ,
428
454
( int ) MessageType . RunCommand => JsonSerializer . Deserialize < RunCommandMessage > ( bytes ) ,
455
+ ( int ) MessageType . AskCommandOutput => JsonSerializer . Deserialize < AskCommandOutputMessage > ( bytes ) ,
429
456
( int ) MessageType . PostResult => JsonSerializer . Deserialize < PostResultMessage > ( bytes ) ,
430
457
_ => throw new NotSupportedException ( "Unreachable code" ) ,
431
458
} ;
@@ -550,6 +577,11 @@ public async Task StartProcessingAsync(int timeout, CancellationToken cancellati
550
577
SendMessage ( result ) ;
551
578
break ;
552
579
580
+ case MessageType . AskCommandOutput :
581
+ var output = InvokeOnAskCommandOutput ( ( AskCommandOutputMessage ) message ) ;
582
+ SendMessage ( output ) ;
583
+ break ;
584
+
553
585
default :
554
586
// Log: unexpected messages ignored.
555
587
break ;
@@ -622,6 +654,9 @@ private PostContextMessage InvokeOnAskContext(AskContextMessage message)
622
654
return null ;
623
655
}
624
656
657
+ /// <summary>
658
+ /// Helper to invoke the <see cref="OnRunCommand"/> event.
659
+ /// </summary>
625
660
private PostResultMessage InvokeOnRunCommand ( RunCommandMessage message )
626
661
{
627
662
if ( OnRunCommand is null )
@@ -649,6 +684,36 @@ private PostResultMessage InvokeOnRunCommand(RunCommandMessage message)
649
684
}
650
685
}
651
686
687
+ /// <summary>
688
+ /// Helper to invoke the <see cref="OnAskCommandOutput"/> event.
689
+ /// </summary>
690
+ private PostResultMessage InvokeOnAskCommandOutput ( AskCommandOutputMessage message )
691
+ {
692
+ if ( OnAskCommandOutput is null )
693
+ {
694
+ // Log: event handler not set.
695
+ return new PostResultMessage (
696
+ output : "Retrieving command output is not supported." ,
697
+ hadError : true ,
698
+ userCancelled : false ,
699
+ exception : null ) ;
700
+ }
701
+
702
+ try
703
+ {
704
+ return OnAskCommandOutput ( message ) ;
705
+ }
706
+ catch ( Exception e )
707
+ {
708
+ // Log: exception when invoking 'OnAskCommandOutput'
709
+ return new PostResultMessage (
710
+ output : "Failed to retrieve the command output due to an internal error." ,
711
+ hadError : true ,
712
+ userCancelled : false ,
713
+ exception : e . Message ) ;
714
+ }
715
+ }
716
+
652
717
/// <summary>
653
718
/// Event for handling the <see cref="MessageType.PostCode"/> message.
654
719
/// </summary>
@@ -668,6 +733,11 @@ private PostResultMessage InvokeOnRunCommand(RunCommandMessage message)
668
733
/// Event for handling the <see cref="MessageType.RunCommand"/> message.
669
734
/// </summary>
670
735
public event Func < RunCommandMessage , PostResultMessage > OnRunCommand ;
736
+
737
+ /// <summary>
738
+ /// Event for handling the <see cref="MessageType.AskCommandOutput"/> message.
739
+ /// </summary>
740
+ public event Func < AskCommandOutputMessage , PostResultMessage > OnAskCommandOutput ;
671
741
}
672
742
673
743
/// <summary>
@@ -889,6 +959,13 @@ public async Task<PostContextMessage> AskContext(AskContextMessage message, Canc
889
959
return postContext ;
890
960
}
891
961
962
+ /// <summary>
963
+ /// Run a command in the connected PowerShell session.
964
+ /// </summary>
965
+ /// <param name="message">The <see cref="MessageType.RunCommand"/> message.</param>
966
+ /// <param name="cancellationToken">A cancellation token.</param>
967
+ /// <returns>A <see cref="MessageType.PostResult"/> message as the response.</returns>
968
+ /// <exception cref="IOException">Throws when the pipe is closed by the other side.</exception>
892
969
public async Task < PostResultMessage > RunCommand ( RunCommandMessage message , CancellationToken cancellationToken )
893
970
{
894
971
// Send the request message to the shell.
@@ -905,4 +982,28 @@ public async Task<PostResultMessage> RunCommand(RunCommandMessage message, Cance
905
982
906
983
return postResult ;
907
984
}
985
+
986
+ /// <summary>
987
+ /// Ask for the output of a previously run command in the connected PowerShell session.
988
+ /// </summary>
989
+ /// <param name="message">The <see cref="MessageType.AskCommandOutput"/> message.</param>
990
+ /// <param name="cancellationToken">A cancellation token.</param>
991
+ /// <returns>A <see cref="MessageType.PostResult"/> message as the response.</returns>
992
+ /// <exception cref="IOException">Throws when the pipe is closed by the other side.</exception>
993
+ public async Task < PostResultMessage > AskCommandOutput ( AskCommandOutputMessage message , CancellationToken cancellationToken )
994
+ {
995
+ // Send the request message to the shell.
996
+ SendMessage ( message ) ;
997
+
998
+ // Receiving response from the shell.
999
+ var response = await GetMessageAsync ( cancellationToken ) ;
1000
+ if ( response is not PostResultMessage postResult )
1001
+ {
1002
+ // Log: unexpected message. drop connection.
1003
+ _client . Close ( ) ;
1004
+ throw new IOException ( $ "Expecting '{ MessageType . PostResult } ' response, but received '{ message . Type } ' message.") ;
1005
+ }
1006
+
1007
+ return postResult ;
1008
+ }
908
1009
}
0 commit comments