Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
12 changes: 12 additions & 0 deletions rust/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,18 @@ config.infinite_sessions = Some(infinite);

The CLI emits `session.compaction_start` / `session.compaction_complete` events around each compaction. The session id remains stable across compactions; resume with `Client::resume_session` to pick up a prior conversation. Workspace state lives under `~/.copilot/session-state/{sessionId}` by default — override with `workspace_path` to relocate.

### Memory

Configure the runtime memory feature for a session:

Comment thread
Morabbin marked this conversation as resolved.
Comment thread
Morabbin marked this conversation as resolved.
Comment thread
Morabbin marked this conversation as resolved.
```rust,ignore
use github_copilot_sdk::types::MemoryConfiguration;

let config = SessionConfig::default().with_memory(MemoryConfiguration::enabled());
Comment thread
Morabbin marked this conversation as resolved.
Outdated
```

`MemoryConfiguration` is accepted on both `Client::create_session` and `Client::resume_session` (via `ResumeSessionConfig::with_memory`). `enabled` toggles the feature.

### Custom Providers (BYOK)

Route model traffic through your own inference endpoint instead of GitHub's hosted models:
Expand Down
115 changes: 112 additions & 3 deletions rust/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,42 @@ impl InfiniteSessionConfig {
}
}

/// Per-session configuration for the runtime memory feature.
///
/// Supplied via [`SessionConfig::with_memory`] /
/// [`ResumeSessionConfig::with_memory`]. When a session is created or resumed
/// without a memory configuration, the runtime applies its own default for the
/// memory feature.
///
/// The type is extensible: today it carries [`enabled`](Self::enabled), and
/// further tuning knobs can be added as optional fields without a breaking
/// change.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct MemoryConfiguration {
/// Whether the memory feature is enabled for this session.
pub enabled: bool,
}

impl MemoryConfiguration {
/// A configuration with the memory feature enabled.
pub fn enabled() -> Self {
Self { enabled: true }
}

/// A configuration with the memory feature disabled.
pub fn disabled() -> Self {
Self { enabled: false }
}

/// Set whether the memory feature is enabled.
pub fn with_enabled(mut self, enabled: bool) -> Self {
self.enabled = enabled;
self
}
}

/// GitHub repository metadata to associate with a cloud session.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
Expand Down Expand Up @@ -1289,6 +1325,8 @@ pub struct SessionConfig {
/// Per-property overrides for model capabilities, deep-merged over
/// runtime defaults.
pub model_capabilities: Option<crate::generated::api_types::ModelCapabilitiesOverride>,
/// Per-session configuration for the runtime memory feature.
pub memory: Option<MemoryConfiguration>,
/// Override the default configuration directory location. When set,
/// the session uses this directory for storing config and state.
pub config_directory: Option<PathBuf>,
Expand Down Expand Up @@ -1431,6 +1469,7 @@ impl std::fmt::Debug for SessionConfig {
.field("provider", &self.provider)
.field("enable_session_telemetry", &self.enable_session_telemetry)
.field("model_capabilities", &self.model_capabilities)
.field("memory", &self.memory)
.field("config_directory", &self.config_directory)
.field("working_directory", &self.working_directory)
.field(
Expand Down Expand Up @@ -1530,6 +1569,7 @@ impl Default for SessionConfig {
provider: None,
enable_session_telemetry: None,
model_capabilities: None,
memory: None,
config_directory: None,
working_directory: None,
github_token: None,
Expand Down Expand Up @@ -1672,6 +1712,7 @@ impl SessionConfig {
provider: self.provider,
enable_session_telemetry: self.enable_session_telemetry,
model_capabilities: self.model_capabilities,
memory: self.memory,
config_dir: self.config_directory,
working_directory: self.working_directory,
github_token: self.github_token,
Expand Down Expand Up @@ -2103,6 +2144,12 @@ impl SessionConfig {
self
}

/// Configure the runtime memory feature for this session.
pub fn with_memory(mut self, memory: MemoryConfiguration) -> Self {
self.memory = Some(memory);
self
}

/// Override the default configuration directory location.
pub fn with_config_directory(mut self, dir: impl Into<PathBuf>) -> Self {
self.config_directory = Some(dir.into());
Expand Down Expand Up @@ -2285,6 +2332,8 @@ pub struct ResumeSessionConfig {
pub enable_session_telemetry: Option<bool>,
/// Per-property model capability overrides on resume.
pub model_capabilities: Option<crate::generated::api_types::ModelCapabilitiesOverride>,
/// Per-session configuration for the runtime memory feature on resume.
pub memory: Option<MemoryConfiguration>,
/// Override the default configuration directory location on resume.
pub config_directory: Option<PathBuf>,
/// Per-session working directory on resume.
Expand Down Expand Up @@ -2408,6 +2457,7 @@ impl std::fmt::Debug for ResumeSessionConfig {
.field("provider", &self.provider)
.field("enable_session_telemetry", &self.enable_session_telemetry)
.field("model_capabilities", &self.model_capabilities)
.field("memory", &self.memory)
.field("config_directory", &self.config_directory)
.field("working_directory", &self.working_directory)
.field(
Expand Down Expand Up @@ -2551,6 +2601,7 @@ impl ResumeSessionConfig {
provider: self.provider,
enable_session_telemetry: self.enable_session_telemetry,
model_capabilities: self.model_capabilities,
memory: self.memory,
config_dir: self.config_directory,
working_directory: self.working_directory,
github_token: self.github_token,
Expand Down Expand Up @@ -2627,6 +2678,7 @@ impl ResumeSessionConfig {
provider: None,
enable_session_telemetry: None,
model_capabilities: None,
memory: None,
config_directory: None,
working_directory: None,
github_token: None,
Expand Down Expand Up @@ -3031,6 +3083,12 @@ impl ResumeSessionConfig {
self
}

/// Configure the runtime memory feature for the resumed session.
pub fn with_memory(mut self, memory: MemoryConfiguration) -> Self {
self.memory = Some(memory);
self
}

/// Override the default configuration directory location on resume.
pub fn with_config_directory(mut self, dir: impl Into<PathBuf>) -> Self {
self.config_directory = Some(dir.into());
Expand Down Expand Up @@ -4271,9 +4329,9 @@ mod tests {
use super::{
AgentMode, Attachment, AttachmentLineRange, AttachmentSelectionPosition,
AttachmentSelectionRange, ConnectionState, CustomAgentConfig, DeliveryMode, ExtensionInfo,
GitHubReferenceType, InfiniteSessionConfig, LargeToolOutputConfig, ProviderConfig,
ReasoningSummary, ResumeSessionConfig, SessionConfig, SessionEvent, SessionId,
SystemMessageConfig, Tool, ToolBinaryResult, ToolResult, ToolResultExpanded,
GitHubReferenceType, InfiniteSessionConfig, LargeToolOutputConfig, MemoryConfiguration,
ProviderConfig, ReasoningSummary, ResumeSessionConfig, SessionConfig, SessionEvent,
SessionId, SystemMessageConfig, Tool, ToolBinaryResult, ToolResult, ToolResultExpanded,
ToolResultResponse, ensure_attachment_display_names,
};
use crate::generated::session_events::TypedSessionEvent;
Expand Down Expand Up @@ -4453,6 +4511,57 @@ mod tests {
assert_eq!(json["requestMcpApps"], serde_json::Value::Bool(true));
}

#[test]
fn memory_configuration_constructors_and_serde() {
assert!(MemoryConfiguration::enabled().enabled);
assert!(!MemoryConfiguration::disabled().enabled);
assert!(MemoryConfiguration::disabled().with_enabled(true).enabled);

let json = serde_json::to_value(MemoryConfiguration::enabled()).unwrap();
assert_eq!(json, serde_json::json!({ "enabled": true }));
}

#[test]
fn session_config_with_memory_serializes() {
let (wire, _runtime) = SessionConfig::default()
.with_memory(MemoryConfiguration::enabled())
.into_wire(Some(SessionId::from("memory-on")))
.expect("no duplicate handlers");
let json = serde_json::to_value(&wire).unwrap();
assert_eq!(json["memory"], serde_json::json!({ "enabled": true }));

let (wire_off, _) = SessionConfig::default()
.with_memory(MemoryConfiguration::disabled())
.into_wire(Some(SessionId::from("memory-off")))
.expect("no duplicate handlers");
let json_off = serde_json::to_value(&wire_off).unwrap();
assert_eq!(json_off["memory"], serde_json::json!({ "enabled": false }));

// Unset memory is omitted on the wire.
let (empty_wire, _) = SessionConfig::default()
.into_wire(Some(SessionId::from("memory-unset")))
.expect("no duplicate handlers");
let empty_json = serde_json::to_value(&empty_wire).unwrap();
assert!(empty_json.get("memory").is_none());
}

#[test]
fn resume_session_config_with_memory_serializes() {
let (wire, _runtime) = ResumeSessionConfig::new(SessionId::from("resume-memory-on"))
.with_memory(MemoryConfiguration::enabled())
.into_wire()
.expect("no duplicate handlers");
let json = serde_json::to_value(&wire).unwrap();
assert_eq!(json["memory"], serde_json::json!({ "enabled": true }));

// Unset memory is omitted on the wire.
let (empty_wire, _) = ResumeSessionConfig::new(SessionId::from("resume-memory-unset"))
.into_wire()
.expect("no duplicate handlers");
let empty_json = serde_json::to_value(&empty_wire).unwrap();
assert!(empty_json.get("memory").is_none());
}

#[test]
#[allow(clippy::field_reassign_with_default)]
fn session_config_into_wire_serializes_bucket_b_fields() {
Expand Down
8 changes: 6 additions & 2 deletions rust/src/wire.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ use crate::generated::api_types::{
use crate::generated::session_events::ReasoningSummary;
use crate::types::{
CloudSessionOptions, CustomAgentConfig, DefaultAgentConfig, ExtensionInfo,
InfiniteSessionConfig, LargeToolOutputConfig, McpServerConfig, ProviderConfig, SessionId,
SystemMessageConfig, Tool,
InfiniteSessionConfig, LargeToolOutputConfig, McpServerConfig, MemoryConfiguration,
ProviderConfig, SessionId, SystemMessageConfig, Tool,
};

/// Wire representation of a slash command (name + description only). The
Expand Down Expand Up @@ -134,6 +134,8 @@ pub(crate) struct SessionCreateWire {
#[serde(skip_serializing_if = "Option::is_none")]
pub model_capabilities: Option<ModelCapabilitiesOverride>,
#[serde(skip_serializing_if = "Option::is_none")]
pub memory: Option<MemoryConfiguration>,
#[serde(skip_serializing_if = "Option::is_none")]
pub config_dir: Option<PathBuf>,
Comment thread
Morabbin marked this conversation as resolved.
Comment thread
Morabbin marked this conversation as resolved.
#[serde(skip_serializing_if = "Option::is_none")]
pub working_directory: Option<PathBuf>,
Expand Down Expand Up @@ -241,6 +243,8 @@ pub(crate) struct SessionResumeWire {
#[serde(skip_serializing_if = "Option::is_none")]
pub model_capabilities: Option<ModelCapabilitiesOverride>,
#[serde(skip_serializing_if = "Option::is_none")]
pub memory: Option<MemoryConfiguration>,
#[serde(skip_serializing_if = "Option::is_none")]
pub config_dir: Option<PathBuf>,
Comment thread
Morabbin marked this conversation as resolved.
#[serde(skip_serializing_if = "Option::is_none")]
pub working_directory: Option<PathBuf>,
Expand Down
Loading