diff --git a/docs/getting-started.md b/docs/getting-started.md
index f615e923b..56c6a9c46 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -1193,14 +1193,14 @@ Once the CLI is running in server mode, configure your SDK client to connect to
Node.js / TypeScript
```typescript
-import { CopilotClient } from "@github/copilot-sdk";
+import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient({
cliUrl: "localhost:4321"
});
// Use the client normally
-const session = await client.createSession();
+const session = await client.createSession({ onPermissionRequest: approveAll });
// ...
```
@@ -1210,7 +1210,7 @@ const session = await client.createSession();
Python
```python
-from copilot import CopilotClient
+from copilot import CopilotClient, PermissionHandler
client = CopilotClient({
"cli_url": "localhost:4321"
@@ -1218,7 +1218,7 @@ client = CopilotClient({
await client.start()
# Use the client normally
-session = await client.create_session()
+session = await client.create_session({"on_permission_request": PermissionHandler.approve_all})
# ...
```
@@ -1241,7 +1241,9 @@ if err := client.Start(ctx); err != nil {
defer client.Stop()
// Use the client normally
-session, err := client.CreateSession(ctx, nil)
+session, err := client.CreateSession(ctx, &copilot.SessionConfig{
+ OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
+})
// ...
```
@@ -1260,7 +1262,10 @@ using var client = new CopilotClient(new CopilotClientOptions
});
// Use the client normally
-await using var session = await client.CreateSessionAsync();
+await using var session = await client.CreateSessionAsync(new()
+{
+ OnPermissionRequest = PermissionHandler.ApproveAll
+});
// ...
```
diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs
index cf29dd116..1f3a7fb43 100644
--- a/dotnet/src/Client.cs
+++ b/dotnet/src/Client.cs
@@ -38,7 +38,7 @@ namespace GitHub.Copilot.SDK;
/// await using var client = new CopilotClient();
///
/// // Create a session
-/// await using var session = await client.CreateSessionAsync(new SessionConfig { Model = "gpt-4" });
+/// await using var session = await client.CreateSessionAsync(new() { OnPermissionRequest = PermissionHandler.ApproveAll, Model = "gpt-4" });
///
/// // Handle events
/// using var subscription = session.On(evt =>
@@ -340,10 +340,9 @@ private async Task CleanupConnectionAsync(List? errors)
///
/// Creates a new Copilot session with the specified configuration.
///
- /// Configuration for the session. If null, default settings are used.
+ /// Configuration for the session, including the required handler.
/// A that can be used to cancel the operation.
/// A task that resolves to provide the .
- /// Thrown when the client is not connected and AutoStart is disabled, or when a session with the same ID already exists.
///
/// Sessions maintain conversation state, handle events, and manage tool execution.
/// If the client is not connected and is enabled (default),
@@ -352,21 +351,29 @@ private async Task CleanupConnectionAsync(List? errors)
///
///
/// // Basic session
- /// var session = await client.CreateSessionAsync();
+ /// var session = await client.CreateSessionAsync(new() { OnPermissionRequest = PermissionHandler.ApproveAll });
///
/// // Session with model and tools
- /// var session = await client.CreateSessionAsync(new SessionConfig
+ /// var session = await client.CreateSessionAsync(new()
/// {
+ /// OnPermissionRequest = PermissionHandler.ApproveAll,
/// Model = "gpt-4",
/// Tools = [AIFunctionFactory.Create(MyToolMethod)]
/// });
///
///
- public async Task CreateSessionAsync(SessionConfig? config = null, CancellationToken cancellationToken = default)
+ public async Task CreateSessionAsync(SessionConfig config, CancellationToken cancellationToken = default)
{
+ if (config.OnPermissionRequest == null)
+ {
+ throw new ArgumentException(
+ "An OnPermissionRequest handler is required when creating a session. " +
+ "For example, to allow all permissions, use CreateSessionAsync(new() { OnPermissionRequest = PermissionHandler.ApproveAll });");
+ }
+
var connection = await EnsureConnectedAsync(cancellationToken);
- var hasHooks = config?.Hooks != null && (
+ var hasHooks = config.Hooks != null && (
config.Hooks.OnPreToolUse != null ||
config.Hooks.OnPostToolUse != null ||
config.Hooks.OnUserPromptSubmitted != null ||
@@ -375,42 +382,39 @@ public async Task CreateSessionAsync(SessionConfig? config = nul
config.Hooks.OnErrorOccurred != null);
var request = new CreateSessionRequest(
- config?.Model,
- config?.SessionId,
- config?.ClientName,
- config?.ReasoningEffort,
- config?.Tools?.Select(ToolDefinition.FromAIFunction).ToList(),
- config?.SystemMessage,
- config?.AvailableTools,
- config?.ExcludedTools,
- config?.Provider,
+ config.Model,
+ config.SessionId,
+ config.ClientName,
+ config.ReasoningEffort,
+ config.Tools?.Select(ToolDefinition.FromAIFunction).ToList(),
+ config.SystemMessage,
+ config.AvailableTools,
+ config.ExcludedTools,
+ config.Provider,
(bool?)true,
- config?.OnUserInputRequest != null ? true : null,
+ config.OnUserInputRequest != null ? true : null,
hasHooks ? true : null,
- config?.WorkingDirectory,
- config?.Streaming == true ? true : null,
- config?.McpServers,
+ config.WorkingDirectory,
+ config.Streaming is true ? true : null,
+ config.McpServers,
"direct",
- config?.CustomAgents,
- config?.ConfigDir,
- config?.SkillDirectories,
- config?.DisabledSkills,
- config?.InfiniteSessions);
+ config.CustomAgents,
+ config.ConfigDir,
+ config.SkillDirectories,
+ config.DisabledSkills,
+ config.InfiniteSessions);
var response = await InvokeRpcAsync(
connection.Rpc, "session.create", [request], cancellationToken);
var session = new CopilotSession(response.SessionId, connection.Rpc, response.WorkspacePath);
- session.RegisterTools(config?.Tools ?? []);
- if (config?.OnPermissionRequest != null)
- {
- session.RegisterPermissionHandler(config.OnPermissionRequest);
- }
- if (config?.OnUserInputRequest != null)
+ session.RegisterTools(config.Tools ?? []);
+ session.RegisterPermissionHandler(config.OnPermissionRequest);
+ if (config.OnUserInputRequest != null)
{
session.RegisterUserInputHandler(config.OnUserInputRequest);
}
- if (config?.Hooks != null)
+ if (config.Hooks != null)
{
session.RegisterHooks(config.Hooks);
}
@@ -427,9 +431,10 @@ public async Task CreateSessionAsync(SessionConfig? config = nul
/// Resumes an existing Copilot session with the specified configuration.
///
/// The ID of the session to resume.
- /// Configuration for the resumed session. If null, default settings are used.
+ /// Configuration for the resumed session, including the required handler.
/// A that can be used to cancel the operation.
/// A task that resolves to provide the .
+ /// Thrown when is not set.
/// Thrown when the session does not exist or the client is not connected.
///
/// This allows you to continue a previous conversation, maintaining all conversation history.
@@ -438,20 +443,28 @@ public async Task CreateSessionAsync(SessionConfig? config = nul
///
///
/// // Resume a previous session
- /// var session = await client.ResumeSessionAsync("session-123");
+ /// var session = await client.ResumeSessionAsync("session-123", new() { OnPermissionRequest = PermissionHandler.ApproveAll });
///
/// // Resume with new tools
- /// var session = await client.ResumeSessionAsync("session-123", new ResumeSessionConfig
+ /// var session = await client.ResumeSessionAsync("session-123", new()
/// {
+ /// OnPermissionRequest = PermissionHandler.ApproveAll,
/// Tools = [AIFunctionFactory.Create(MyNewToolMethod)]
/// });
///
///
- public async Task ResumeSessionAsync(string sessionId, ResumeSessionConfig? config = null, CancellationToken cancellationToken = default)
+ public async Task ResumeSessionAsync(string sessionId, ResumeSessionConfig config, CancellationToken cancellationToken = default)
{
+ if (config.OnPermissionRequest == null)
+ {
+ throw new ArgumentException(
+ "An OnPermissionRequest handler is required when resuming a session. " +
+ "For example, to allow all permissions, use new() { OnPermissionRequest = PermissionHandler.ApproveAll }.");
+ }
+
var connection = await EnsureConnectedAsync(cancellationToken);
- var hasHooks = config?.Hooks != null && (
+ var hasHooks = config.Hooks != null && (
config.Hooks.OnPreToolUse != null ||
config.Hooks.OnPostToolUse != null ||
config.Hooks.OnUserPromptSubmitted != null ||
@@ -461,42 +474,39 @@ public async Task ResumeSessionAsync(string sessionId, ResumeSes
var request = new ResumeSessionRequest(
sessionId,
- config?.ClientName,
- config?.Model,
- config?.ReasoningEffort,
- config?.Tools?.Select(ToolDefinition.FromAIFunction).ToList(),
- config?.SystemMessage,
- config?.AvailableTools,
- config?.ExcludedTools,
- config?.Provider,
+ config.ClientName,
+ config.Model,
+ config.ReasoningEffort,
+ config.Tools?.Select(ToolDefinition.FromAIFunction).ToList(),
+ config.SystemMessage,
+ config.AvailableTools,
+ config.ExcludedTools,
+ config.Provider,
(bool?)true,
- config?.OnUserInputRequest != null ? true : null,
+ config.OnUserInputRequest != null ? true : null,
hasHooks ? true : null,
- config?.WorkingDirectory,
- config?.ConfigDir,
- config?.DisableResume == true ? true : null,
- config?.Streaming == true ? true : null,
- config?.McpServers,
+ config.WorkingDirectory,
+ config.ConfigDir,
+ config.DisableResume is true ? true : null,
+ config.Streaming is true ? true : null,
+ config.McpServers,
"direct",
- config?.CustomAgents,
- config?.SkillDirectories,
- config?.DisabledSkills,
- config?.InfiniteSessions);
+ config.CustomAgents,
+ config.SkillDirectories,
+ config.DisabledSkills,
+ config.InfiniteSessions);
var response = await InvokeRpcAsync(
connection.Rpc, "session.resume", [request], cancellationToken);
var session = new CopilotSession(response.SessionId, connection.Rpc, response.WorkspacePath);
- session.RegisterTools(config?.Tools ?? []);
- if (config?.OnPermissionRequest != null)
- {
- session.RegisterPermissionHandler(config.OnPermissionRequest);
- }
- if (config?.OnUserInputRequest != null)
+ session.RegisterTools(config.Tools ?? []);
+ session.RegisterPermissionHandler(config.OnPermissionRequest);
+ if (config.OnUserInputRequest != null)
{
session.RegisterUserInputHandler(config.OnUserInputRequest);
}
- if (config?.Hooks != null)
+ if (config.Hooks != null)
{
session.RegisterHooks(config.Hooks);
}
@@ -516,7 +526,7 @@ public async Task ResumeSessionAsync(string sessionId, ResumeSes
///
/// if (client.State == ConnectionState.Connected)
/// {
- /// var session = await client.CreateSessionAsync();
+ /// var session = await client.CreateSessionAsync(new() { OnPermissionRequest = PermissionHandler.ApproveAll });
/// }
///
///
@@ -630,7 +640,7 @@ public async Task> ListModelsAsync(CancellationToken cancellatio
/// var lastId = await client.GetLastSessionIdAsync();
/// if (lastId != null)
/// {
- /// var session = await client.ResumeSessionAsync(lastId);
+ /// var session = await client.ResumeSessionAsync(lastId, new() { OnPermissionRequest = PermissionHandler.ApproveAll });
/// }
///
///
diff --git a/dotnet/src/Session.cs b/dotnet/src/Session.cs
index 45f093b10..923b193cc 100644
--- a/dotnet/src/Session.cs
+++ b/dotnet/src/Session.cs
@@ -27,7 +27,7 @@ namespace GitHub.Copilot.SDK;
///
///
///
-/// await using var session = await client.CreateSessionAsync(new SessionConfig { Model = "gpt-4" });
+/// await using var session = await client.CreateSessionAsync(new() { OnPermissionRequest = PermissionHandler.ApproveAll, Model = "gpt-4" });
///
/// // Subscribe to events
/// using var subscription = session.On(evt =>
@@ -557,10 +557,10 @@ await InvokeRpcAsync