@@ -38,7 +38,7 @@ namespace GitHub.Copilot.SDK;
3838/// await using var client = new CopilotClient();
3939///
4040/// // Create a session
41- /// await using var session = await client.CreateSessionAsync(new SessionConfig { Model = "gpt-4" });
41+ /// await using var session = await client.CreateSessionAsync(new() { OnPermissionRequest = PermissionHandler.ApproveAll, Model = "gpt-4" });
4242///
4343/// // Handle events
4444/// using var subscription = session.On(evt =>
@@ -340,10 +340,9 @@ private async Task CleanupConnectionAsync(List<Exception>? errors)
340340 /// <summary>
341341 /// Creates a new Copilot session with the specified configuration.
342342 /// </summary>
343- /// <param name="config">Configuration for the session. If null, default settings are used .</param>
343+ /// <param name="config">Configuration for the session, including the required <see cref="SessionConfig.OnPermissionRequest"/> handler .</param>
344344 /// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel the operation.</param>
345345 /// <returns>A task that resolves to provide the <see cref="CopilotSession"/>.</returns>
346- /// <exception cref="InvalidOperationException">Thrown when the client is not connected and AutoStart is disabled, or when a session with the same ID already exists.</exception>
347346 /// <remarks>
348347 /// Sessions maintain conversation state, handle events, and manage tool execution.
349348 /// If the client is not connected and <see cref="CopilotClientOptions.AutoStart"/> is enabled (default),
@@ -352,21 +351,29 @@ private async Task CleanupConnectionAsync(List<Exception>? errors)
352351 /// <example>
353352 /// <code>
354353 /// // Basic session
355- /// var session = await client.CreateSessionAsync();
354+ /// var session = await client.CreateSessionAsync(new() { OnPermissionRequest = PermissionHandler.ApproveAll } );
356355 ///
357356 /// // Session with model and tools
358- /// var session = await client.CreateSessionAsync(new SessionConfig
357+ /// var session = await client.CreateSessionAsync(new()
359358 /// {
359+ /// OnPermissionRequest = PermissionHandler.ApproveAll,
360360 /// Model = "gpt-4",
361361 /// Tools = [AIFunctionFactory.Create(MyToolMethod)]
362362 /// });
363363 /// </code>
364364 /// </example>
365- public async Task < CopilotSession > CreateSessionAsync ( SessionConfig ? config = null , CancellationToken cancellationToken = default )
365+ public async Task < CopilotSession > CreateSessionAsync ( SessionConfig config , CancellationToken cancellationToken = default )
366366 {
367+ if ( config . OnPermissionRequest == null )
368+ {
369+ throw new ArgumentException (
370+ "An OnPermissionRequest handler is required when creating a session. " +
371+ "For example, to allow all permissions, use CreateSessionAsync(new() { OnPermissionRequest = PermissionHandler.ApproveAll });" ) ;
372+ }
373+
367374 var connection = await EnsureConnectedAsync ( cancellationToken ) ;
368375
369- var hasHooks = config ? . Hooks != null && (
376+ var hasHooks = config . Hooks != null && (
370377 config . Hooks . OnPreToolUse != null ||
371378 config . Hooks . OnPostToolUse != null ||
372379 config . Hooks . OnUserPromptSubmitted != null ||
@@ -375,42 +382,39 @@ public async Task<CopilotSession> CreateSessionAsync(SessionConfig? config = nul
375382 config . Hooks . OnErrorOccurred != null ) ;
376383
377384 var request = new CreateSessionRequest (
378- config ? . Model ,
379- config ? . SessionId ,
380- config ? . ClientName ,
381- config ? . ReasoningEffort ,
382- config ? . Tools ? . Select ( ToolDefinition . FromAIFunction ) . ToList ( ) ,
383- config ? . SystemMessage ,
384- config ? . AvailableTools ,
385- config ? . ExcludedTools ,
386- config ? . Provider ,
385+ config . Model ,
386+ config . SessionId ,
387+ config . ClientName ,
388+ config . ReasoningEffort ,
389+ config . Tools ? . Select ( ToolDefinition . FromAIFunction ) . ToList ( ) ,
390+ config . SystemMessage ,
391+ config . AvailableTools ,
392+ config . ExcludedTools ,
393+ config . Provider ,
387394 ( bool ? ) true ,
388- config ? . OnUserInputRequest != null ? true : null ,
395+ config . OnUserInputRequest != null ? true : null ,
389396 hasHooks ? true : null ,
390- config ? . WorkingDirectory ,
391- config ? . Streaming == true ? true : null ,
392- config ? . McpServers ,
397+ config . WorkingDirectory ,
398+ config . Streaming is true ? true : null ,
399+ config . McpServers ,
393400 "direct" ,
394- config ? . CustomAgents ,
395- config ? . ConfigDir ,
396- config ? . SkillDirectories ,
397- config ? . DisabledSkills ,
398- config ? . InfiniteSessions ) ;
401+ config . CustomAgents ,
402+ config . ConfigDir ,
403+ config . SkillDirectories ,
404+ config . DisabledSkills ,
405+ config . InfiniteSessions ) ;
399406
400407 var response = await InvokeRpcAsync < CreateSessionResponse > (
401408 connection . Rpc , "session.create" , [ request ] , cancellationToken ) ;
402409
403410 var session = new CopilotSession ( response . SessionId , connection . Rpc , response . WorkspacePath ) ;
404- session . RegisterTools ( config ? . Tools ?? [ ] ) ;
405- if ( config ? . OnPermissionRequest != null )
406- {
407- session . RegisterPermissionHandler ( config . OnPermissionRequest ) ;
408- }
409- if ( config ? . OnUserInputRequest != null )
411+ session . RegisterTools ( config . Tools ?? [ ] ) ;
412+ session . RegisterPermissionHandler ( config . OnPermissionRequest ) ;
413+ if ( config . OnUserInputRequest != null )
410414 {
411415 session . RegisterUserInputHandler ( config . OnUserInputRequest ) ;
412416 }
413- if ( config ? . Hooks != null )
417+ if ( config . Hooks != null )
414418 {
415419 session . RegisterHooks ( config . Hooks ) ;
416420 }
@@ -427,9 +431,10 @@ public async Task<CopilotSession> CreateSessionAsync(SessionConfig? config = nul
427431 /// Resumes an existing Copilot session with the specified configuration.
428432 /// </summary>
429433 /// <param name="sessionId">The ID of the session to resume.</param>
430- /// <param name="config">Configuration for the resumed session. If null, default settings are used .</param>
434+ /// <param name="config">Configuration for the resumed session, including the required <see cref="ResumeSessionConfig.OnPermissionRequest"/> handler .</param>
431435 /// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel the operation.</param>
432436 /// <returns>A task that resolves to provide the <see cref="CopilotSession"/>.</returns>
437+ /// <exception cref="ArgumentException">Thrown when <see cref="ResumeSessionConfig.OnPermissionRequest"/> is not set.</exception>
433438 /// <exception cref="InvalidOperationException">Thrown when the session does not exist or the client is not connected.</exception>
434439 /// <remarks>
435440 /// This allows you to continue a previous conversation, maintaining all conversation history.
@@ -438,20 +443,28 @@ public async Task<CopilotSession> CreateSessionAsync(SessionConfig? config = nul
438443 /// <example>
439444 /// <code>
440445 /// // Resume a previous session
441- /// var session = await client.ResumeSessionAsync("session-123");
446+ /// var session = await client.ResumeSessionAsync("session-123", new() { OnPermissionRequest = PermissionHandler.ApproveAll } );
442447 ///
443448 /// // Resume with new tools
444- /// var session = await client.ResumeSessionAsync("session-123", new ResumeSessionConfig
449+ /// var session = await client.ResumeSessionAsync("session-123", new()
445450 /// {
451+ /// OnPermissionRequest = PermissionHandler.ApproveAll,
446452 /// Tools = [AIFunctionFactory.Create(MyNewToolMethod)]
447453 /// });
448454 /// </code>
449455 /// </example>
450- public async Task < CopilotSession > ResumeSessionAsync ( string sessionId , ResumeSessionConfig ? config = null , CancellationToken cancellationToken = default )
456+ public async Task < CopilotSession > ResumeSessionAsync ( string sessionId , ResumeSessionConfig config , CancellationToken cancellationToken = default )
451457 {
458+ if ( config . OnPermissionRequest == null )
459+ {
460+ throw new ArgumentException (
461+ "An OnPermissionRequest handler is required when resuming a session. " +
462+ "For example, to allow all permissions, use new() { OnPermissionRequest = PermissionHandler.ApproveAll }." ) ;
463+ }
464+
452465 var connection = await EnsureConnectedAsync ( cancellationToken ) ;
453466
454- var hasHooks = config ? . Hooks != null && (
467+ var hasHooks = config . Hooks != null && (
455468 config . Hooks . OnPreToolUse != null ||
456469 config . Hooks . OnPostToolUse != null ||
457470 config . Hooks . OnUserPromptSubmitted != null ||
@@ -461,42 +474,39 @@ public async Task<CopilotSession> ResumeSessionAsync(string sessionId, ResumeSes
461474
462475 var request = new ResumeSessionRequest (
463476 sessionId ,
464- config ? . ClientName ,
465- config ? . Model ,
466- config ? . ReasoningEffort ,
467- config ? . Tools ? . Select ( ToolDefinition . FromAIFunction ) . ToList ( ) ,
468- config ? . SystemMessage ,
469- config ? . AvailableTools ,
470- config ? . ExcludedTools ,
471- config ? . Provider ,
477+ config . ClientName ,
478+ config . Model ,
479+ config . ReasoningEffort ,
480+ config . Tools ? . Select ( ToolDefinition . FromAIFunction ) . ToList ( ) ,
481+ config . SystemMessage ,
482+ config . AvailableTools ,
483+ config . ExcludedTools ,
484+ config . Provider ,
472485 ( bool ? ) true ,
473- config ? . OnUserInputRequest != null ? true : null ,
486+ config . OnUserInputRequest != null ? true : null ,
474487 hasHooks ? true : null ,
475- config ? . WorkingDirectory ,
476- config ? . ConfigDir ,
477- config ? . DisableResume == true ? true : null ,
478- config ? . Streaming == true ? true : null ,
479- config ? . McpServers ,
488+ config . WorkingDirectory ,
489+ config . ConfigDir ,
490+ config . DisableResume is true ? true : null ,
491+ config . Streaming is true ? true : null ,
492+ config . McpServers ,
480493 "direct" ,
481- config ? . CustomAgents ,
482- config ? . SkillDirectories ,
483- config ? . DisabledSkills ,
484- config ? . InfiniteSessions ) ;
494+ config . CustomAgents ,
495+ config . SkillDirectories ,
496+ config . DisabledSkills ,
497+ config . InfiniteSessions ) ;
485498
486499 var response = await InvokeRpcAsync < ResumeSessionResponse > (
487500 connection . Rpc , "session.resume" , [ request ] , cancellationToken ) ;
488501
489502 var session = new CopilotSession ( response . SessionId , connection . Rpc , response . WorkspacePath ) ;
490- session . RegisterTools ( config ? . Tools ?? [ ] ) ;
491- if ( config ? . OnPermissionRequest != null )
492- {
493- session . RegisterPermissionHandler ( config . OnPermissionRequest ) ;
494- }
495- if ( config ? . OnUserInputRequest != null )
503+ session . RegisterTools ( config . Tools ?? [ ] ) ;
504+ session . RegisterPermissionHandler ( config . OnPermissionRequest ) ;
505+ if ( config . OnUserInputRequest != null )
496506 {
497507 session . RegisterUserInputHandler ( config . OnUserInputRequest ) ;
498508 }
499- if ( config ? . Hooks != null )
509+ if ( config . Hooks != null )
500510 {
501511 session . RegisterHooks ( config . Hooks ) ;
502512 }
@@ -516,7 +526,7 @@ public async Task<CopilotSession> ResumeSessionAsync(string sessionId, ResumeSes
516526 /// <code>
517527 /// if (client.State == ConnectionState.Connected)
518528 /// {
519- /// var session = await client.CreateSessionAsync();
529+ /// var session = await client.CreateSessionAsync(new() { OnPermissionRequest = PermissionHandler.ApproveAll } );
520530 /// }
521531 /// </code>
522532 /// </example>
@@ -630,7 +640,7 @@ public async Task<List<ModelInfo>> ListModelsAsync(CancellationToken cancellatio
630640 /// var lastId = await client.GetLastSessionIdAsync();
631641 /// if (lastId != null)
632642 /// {
633- /// var session = await client.ResumeSessionAsync(lastId);
643+ /// var session = await client.ResumeSessionAsync(lastId, new() { OnPermissionRequest = PermissionHandler.ApproveAll } );
634644 /// }
635645 /// </code>
636646 /// </example>
0 commit comments