Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions docs/guides/session-persistence.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,37 @@ var session = await client.ResumeSessionAsync("user-123-task-456");
await session.SendAndWaitAsync(new MessageOptions { Prompt = "What did we discuss earlier?" });
```

## Resume Options

When resuming a session, you can optionally reconfigure many settings. This is useful when you need to change the model, update tool configurations, or modify behavior.

| Option | Description |
|--------|-------------|
| `model` | Change the model for the resumed session |
| `systemMessage` | Override or extend the system prompt |
| `availableTools` | Restrict which tools are available |
| `excludedTools` | Disable specific tools |
| `provider` | Re-provide BYOK credentials (required for BYOK sessions) |
| `reasoningEffort` | Adjust reasoning effort level |
| `streaming` | Enable/disable streaming responses |
| `workingDirectory` | Change the working directory |
| `configDir` | Override configuration directory |
| `mcpServers` | Configure MCP servers |
| `customAgents` | Configure custom agents |
| `skillDirectories` | Directories to load skills from |
| `disabledSkills` | Skills to disable |
| `infiniteSessions` | Configure infinite session behavior |

### Example: Changing Model on Resume

```typescript
// Resume with a different model
const session = await client.resumeSession("user-123-task-456", {
model: "claude-sonnet-4", // Switch to a different model
reasoningEffort: "high", // Increase reasoning effort
});
```

## Using BYOK (Bring Your Own Key) with Resumed Sessions

When using your own API keys, you must re-provide the provider configuration when resuming. API keys are never persisted to disk for security reasons.
Expand Down
16 changes: 14 additions & 2 deletions dotnet/src/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -437,19 +437,25 @@ public async Task<CopilotSession> ResumeSessionAsync(string sessionId, ResumeSes

var request = new ResumeSessionRequest(
sessionId,
config?.Model,
config?.ReasoningEffort,
config?.Tools?.Select(ToolDefinition.FromAIFunction).ToList(),
config?.SystemMessage,
config?.AvailableTools,
config?.ExcludedTools,
config?.Provider,
config?.OnPermissionRequest != 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?.CustomAgents,
config?.SkillDirectories,
config?.DisabledSkills);
config?.DisabledSkills,
config?.InfiniteSessions);

var response = await InvokeRpcAsync<ResumeSessionResponse>(
connection.Rpc, "session.resume", [request], cancellationToken);
Expand Down Expand Up @@ -1326,19 +1332,25 @@ internal record CreateSessionResponse(

internal record ResumeSessionRequest(
string SessionId,
string? Model,
string? ReasoningEffort,
List<ToolDefinition>? Tools,
SystemMessageConfig? SystemMessage,
List<string>? AvailableTools,
List<string>? ExcludedTools,
ProviderConfig? Provider,
bool? RequestPermission,
bool? RequestUserInput,
bool? Hooks,
string? WorkingDirectory,
string? ConfigDir,
bool? DisableResume,
bool? Streaming,
Dictionary<string, object>? McpServers,
List<CustomAgentConfig>? CustomAgents,
List<string>? SkillDirectories,
List<string>? DisabledSkills);
List<string>? DisabledSkills,
InfiniteSessionConfig? InfiniteSessions);

internal record ResumeSessionResponse(
string SessionId,
Expand Down
33 changes: 33 additions & 0 deletions dotnet/src/Types.cs
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,30 @@ public class SessionConfig

public class ResumeSessionConfig
{
/// <summary>
/// Model to use for this session. Can change the model when resuming.
/// </summary>
public string? Model { get; set; }

public ICollection<AIFunction>? Tools { get; set; }

/// <summary>
/// System message configuration.
/// </summary>
public SystemMessageConfig? SystemMessage { get; set; }

/// <summary>
/// List of tool names to allow. When specified, only these tools will be available.
/// Takes precedence over ExcludedTools.
/// </summary>
public List<string>? AvailableTools { get; set; }

/// <summary>
/// List of tool names to disable. All other tools remain available.
/// Ignored if AvailableTools is specified.
/// </summary>
public List<string>? ExcludedTools { get; set; }

public ProviderConfig? Provider { get; set; }

/// <summary>
Expand Down Expand Up @@ -801,6 +824,11 @@ public class ResumeSessionConfig
/// </summary>
public string? WorkingDirectory { get; set; }

/// <summary>
/// Override the default configuration directory location.
/// </summary>
public string? ConfigDir { get; set; }

/// <summary>
/// When true, the session.resume event is not emitted.
/// Default: false (resume event is emitted).
Expand Down Expand Up @@ -834,6 +862,11 @@ public class ResumeSessionConfig
/// List of skill names to disable.
/// </summary>
public List<string>? DisabledSkills { get; set; }

/// <summary>
/// Infinite session configuration for persistent workspaces and automatic compaction.
/// </summary>
public InfiniteSessionConfig? InfiniteSessions { get; set; }
}

public class MessageOptions
Expand Down
48 changes: 48 additions & 0 deletions go/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -681,9 +681,39 @@ func (c *Client) ResumeSessionWithOptions(ctx context.Context, sessionID string,
}

if config != nil {
if config.Model != "" {
params["model"] = config.Model
}
if config.ReasoningEffort != "" {
params["reasoningEffort"] = config.ReasoningEffort
}
if config.SystemMessage != nil {
systemMessage := make(map[string]any)

if config.SystemMessage.Mode != "" {
systemMessage["mode"] = config.SystemMessage.Mode
}

if config.SystemMessage.Mode == "replace" {
if config.SystemMessage.Content != "" {
systemMessage["content"] = config.SystemMessage.Content
}
} else {
if config.SystemMessage.Content != "" {
systemMessage["content"] = config.SystemMessage.Content
}
}

if len(systemMessage) > 0 {
params["systemMessage"] = systemMessage
}
}
if len(config.AvailableTools) > 0 {
params["availableTools"] = config.AvailableTools
}
if len(config.ExcludedTools) > 0 {
params["excludedTools"] = config.ExcludedTools
}
if len(config.Tools) > 0 {
toolDefs := make([]map[string]any, 0, len(config.Tools))
for _, tool := range config.Tools {
Expand Down Expand Up @@ -731,6 +761,10 @@ func (c *Client) ResumeSessionWithOptions(ctx context.Context, sessionID string,
if config.WorkingDirectory != "" {
params["workingDirectory"] = config.WorkingDirectory
}
// Add config directory
if config.ConfigDir != "" {
params["configDir"] = config.ConfigDir
}
// Add disable resume flag
if config.DisableResume {
params["disableResume"] = true
Expand Down Expand Up @@ -774,6 +808,20 @@ func (c *Client) ResumeSessionWithOptions(ctx context.Context, sessionID string,
if len(config.DisabledSkills) > 0 {
params["disabledSkills"] = config.DisabledSkills
}
// Add infinite sessions configuration
if config.InfiniteSessions != nil {
infiniteSessions := map[string]any{}
if config.InfiniteSessions.Enabled != nil {
infiniteSessions["enabled"] = *config.InfiniteSessions.Enabled
}
if config.InfiniteSessions.BackgroundCompactionThreshold != nil {
infiniteSessions["backgroundCompactionThreshold"] = *config.InfiniteSessions.BackgroundCompactionThreshold
}
if config.InfiniteSessions.BufferExhaustionThreshold != nil {
infiniteSessions["bufferExhaustionThreshold"] = *config.InfiniteSessions.BufferExhaustionThreshold
}
params["infiniteSessions"] = infiniteSessions
}
}

result, err := c.client.Request("session.resume", params)
Expand Down
14 changes: 14 additions & 0 deletions go/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,8 +399,18 @@ type ToolResult struct {

// ResumeSessionConfig configures options when resuming a session
type ResumeSessionConfig struct {
// Model to use for this session. Can change the model when resuming.
Model string
// Tools exposes caller-implemented tools to the CLI
Tools []Tool
// SystemMessage configures system message customization
SystemMessage *SystemMessageConfig
// AvailableTools is a list of tool names to allow. When specified, only these tools will be available.
// Takes precedence over ExcludedTools.
AvailableTools []string
// ExcludedTools is a list of tool names to disable. All other tools remain available.
// Ignored if AvailableTools is specified.
ExcludedTools []string
// Provider configures a custom model provider
Provider *ProviderConfig
// ReasoningEffort level for models that support it.
Expand All @@ -415,6 +425,8 @@ type ResumeSessionConfig struct {
// WorkingDirectory is the working directory for the session.
// Tool operations will be relative to this directory.
WorkingDirectory string
// ConfigDir overrides the default configuration directory location.
ConfigDir string
// Streaming enables streaming of assistant message and reasoning chunks.
// When true, assistant.message_delta and assistant.reasoning_delta events
// with deltaContent are sent as the response is generated.
Expand All @@ -427,6 +439,8 @@ type ResumeSessionConfig struct {
SkillDirectories []string
// DisabledSkills is a list of skill names to disable
DisabledSkills []string
// InfiniteSessions configures infinite sessions for persistent workspaces and automatic compaction.
InfiniteSessions *InfiniteSessionConfig
// DisableResume, when true, skips emitting the session.resume event.
// Useful for reconnecting to a session without triggering resume-related side effects.
DisableResume bool
Expand Down
56 changes: 28 additions & 28 deletions nodejs/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion nodejs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"author": "GitHub",
"license": "MIT",
"dependencies": {
"@github/copilot": "^0.0.402",
"@github/copilot": "^0.0.403",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.5"
},
Expand Down
Loading
Loading