diff --git a/CHANGELOG.md b/CHANGELOG.md index b4bb82a8..26ad8832 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,8 +38,11 @@ Spec version: `0.3.0` - Removed the `additions`, `deletions`, and `files` fields from `ChangesetSummary`. Aggregate counts now live on `SessionSummary.changes`; per-changeset views derive their own totals from `ChangesetState.files`. -- Renamed the `ChangesetSummary` interface to `Changeset` (catalogue entry - on `SessionSummary.changesets`). The on-the-wire shape is unchanged. +- Moved the `changesets` catalogue from `SessionSummary` to + `SessionState`. The `session/changesetsChanged` action now updates + `state.changesets` directly instead of `state.summary.changesets`. +- Renamed the `ChangesetSummary` interface to `Changeset`. The + on-the-wire shape is unchanged. - Renamed the `UserMessage` type to `Message` and surfaced it consistently across turn state (`Turn.message`, `ActiveTurn.message`, `PendingMessage.message`) and the actions that carry it (`session/turnStarted`, diff --git a/clients/go/CHANGELOG.md b/clients/go/CHANGELOG.md index c9fd35ad..23fd26d1 100644 --- a/clients/go/CHANGELOG.md +++ b/clients/go/CHANGELOG.md @@ -25,7 +25,8 @@ tag whose matching `## [X.Y.Z]` heading is missing from this file. ### Changed -- Renamed the `ChangesetSummary` type to `Changeset` (catalogue entry on `SessionSummary.changesets`). The on-the-wire shape is unchanged. +- Renamed the `ChangesetSummary` type to `Changeset`. The on-the-wire shape is unchanged. +- Moved the `changesets` catalogue from `SessionSummary` to `SessionState`. The `session/changesetsChanged` action now updates `state.changesets` directly instead of `state.summary.changesets`. ### Removed diff --git a/clients/go/ahp/reducers.go b/clients/go/ahp/reducers.go index e081790c..6f6c4eb4 100644 --- a/clients/go/ahp/reducers.go +++ b/clients/go/ahp/reducers.go @@ -499,7 +499,11 @@ func ApplyActionToSession(state *ahptypes.SessionState, action ahptypes.StateAct state.Summary.Activity = a.Activity return ReduceOutcomeApplied case *ahptypes.SessionChangesetsChangedAction: - state.Summary.Changesets = append([]ahptypes.Changeset(nil), a.Changesets...) + if a.Changesets == nil { + state.Changesets = nil + } else { + state.Changesets = append([]ahptypes.Changeset(nil), a.Changesets...) + } return ReduceOutcomeApplied case *ahptypes.SessionConfigChangedAction: if state.Config == nil { diff --git a/clients/go/ahptypes/actions.generated.go b/clients/go/ahptypes/actions.generated.go index 0f13bda5..452aec88 100644 --- a/clients/go/ahptypes/actions.generated.go +++ b/clients/go/ahptypes/actions.generated.go @@ -443,8 +443,9 @@ type SessionActivityChangedAction struct { // The {@link Changeset | catalogue of changesets} the agent host // advertises for this session changed. Replaces -// `state.summary.changesets` entirely (full-replacement semantics) — set -// to `undefined` to clear the catalogue. +// {@link SessionState.changesets | `state.changesets`} entirely +// (full-replacement semantics) — set to `undefined` to clear the +// catalogue. // // Producers dispatch this whenever entries are added or removed. The // fan-out happens through this action so observers see catalogue diff --git a/clients/go/ahptypes/notifications.generated.go b/clients/go/ahptypes/notifications.generated.go index e7b96979..3d37cdc7 100644 --- a/clients/go/ahptypes/notifications.generated.go +++ b/clients/go/ahptypes/notifications.generated.go @@ -70,8 +70,7 @@ type SessionRemovedParams struct { // {@link SessionSummary | `SessionSummary`} changes for a session the // server has surfaced via `listSessions()` or `root/sessionAdded`. // Servers MAY coalesce or debounce updates for noisy fields (for example, -// `modifiedAt` bumps while a turn is streaming, or rapidly changing -// `changesets`) at their discretion. +// `modifiedAt` bumps while a turn is streaming) at their discretion. // - Clients that have no cached entry for `session` MAY ignore the // notification; it is not a substitute for `root/sessionAdded`. type SessionSummaryChangedParams struct { @@ -185,12 +184,6 @@ type PartialSessionSummary struct { Agent *AgentSelection `json:"agent,omitempty"` // The working directory URI for this session WorkingDirectory *URI `json:"workingDirectory,omitempty"` - // Catalogue of changesets the server can produce for this session. Each - // entry advertises a subscribable view of file changes (uncommitted, - // session-wide, per-turn, etc.) and the URI template the client expands - // before subscribing. See {@link Changeset} for the full shape and - // {@link /guide/changesets | Changesets} for an overview of the model. - Changesets []Changeset `json:"changesets,omitempty"` // Aggregate summary of file changes associated with this session. Servers // may populate this to give clients a quick at-a-glance view of the // session's footprint (e.g., for list rendering) without requiring the diff --git a/clients/go/ahptypes/state.generated.go b/clients/go/ahptypes/state.generated.go index 5cde6456..9e8a8354 100644 --- a/clients/go/ahptypes/state.generated.go +++ b/clients/go/ahptypes/state.generated.go @@ -555,6 +555,12 @@ type SessionState struct { // and the host propagates them into this list (typically with the // container's `clientId` set and `children` populated). Customizations []Customization `json:"customizations,omitempty"` + // Catalogue of changesets the server can produce for this session. Each + // entry advertises a subscribable view of file changes (uncommitted, + // session-wide, per-turn, etc.) and the URI template the client expands + // before subscribing. See {@link Changeset} for the full shape and + // {@link /guide/changesets | Changesets} for an overview of the model. + Changesets []Changeset `json:"changesets,omitempty"` // Additional provider-specific metadata for this session. // // Clients MAY look for well-known keys here to provide enhanced UI. @@ -609,12 +615,6 @@ type SessionSummary struct { Agent *AgentSelection `json:"agent,omitempty"` // The working directory URI for this session WorkingDirectory *URI `json:"workingDirectory,omitempty"` - // Catalogue of changesets the server can produce for this session. Each - // entry advertises a subscribable view of file changes (uncommitted, - // session-wide, per-turn, etc.) and the URI template the client expands - // before subscribing. See {@link Changeset} for the full shape and - // {@link /guide/changesets | Changesets} for an overview of the model. - Changesets []Changeset `json:"changesets,omitempty"` // Aggregate summary of file changes associated with this session. Servers // may populate this to give clients a quick at-a-glance view of the // session's footprint (e.g., for list rendering) without requiring the diff --git a/clients/kotlin/CHANGELOG.md b/clients/kotlin/CHANGELOG.md index a1bc4578..365f76eb 100644 --- a/clients/kotlin/CHANGELOG.md +++ b/clients/kotlin/CHANGELOG.md @@ -26,7 +26,8 @@ versions (`*-SNAPSHOT`) are explicitly rejected by the publish pipeline; bump ### Changed -- Renamed the `ChangesetSummary` type to `Changeset` (catalogue entry on `SessionSummary.changesets`). The on-the-wire shape is unchanged. +- Renamed the `ChangesetSummary` type to `Changeset`. The on-the-wire shape is unchanged. +- Moved the `changesets` catalogue from `SessionSummary` to `SessionState`. The `session/changesetsChanged` action now updates `state.changesets` directly instead of `state.summary.changesets`. ### Removed diff --git a/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/Reducers.kt b/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/Reducers.kt index f7c009b1..5c58e74d 100644 --- a/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/Reducers.kt +++ b/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/Reducers.kt @@ -924,9 +924,7 @@ public fun sessionReducer(state: SessionState, action: StateAction): SessionStat ) is StateActionSessionChangesetsChanged -> state.copy( - // Clear the field entirely when no changesets are provided, matching - // TS `{ ...summaryWithoutChangesets }` semantics (omits the key). - summary = state.summary.copy(changesets = action.value.changesets), + changesets = action.value.changesets, ) is StateActionSessionConfigChanged -> { diff --git a/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Notifications.generated.kt b/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Notifications.generated.kt index 9ba67479..425ef812 100644 --- a/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Notifications.generated.kt +++ b/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Notifications.generated.kt @@ -192,14 +192,6 @@ data class PartialSessionSummary( * The working directory URI for this session */ val workingDirectory: String? = null, - /** - * Catalogue of changesets the server can produce for this session. Each - * entry advertises a subscribable view of file changes (uncommitted, - * session-wide, per-turn, etc.) and the URI template the client expands - * before subscribing. See {@link Changeset} for the full shape and - * {@link /guide/changesets | Changesets} for an overview of the model. - */ - val changesets: List? = null, /** * Aggregate summary of file changes associated with this session. Servers * may populate this to give clients a quick at-a-glance view of the diff --git a/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/State.generated.kt b/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/State.generated.kt index ee2b2f84..0ebd79d8 100644 --- a/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/State.generated.kt +++ b/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/State.generated.kt @@ -899,6 +899,14 @@ data class SessionState( * container's `clientId` set and `children` populated). */ val customizations: List? = null, + /** + * Catalogue of changesets the server can produce for this session. Each + * entry advertises a subscribable view of file changes (uncommitted, + * session-wide, per-turn, etc.) and the URI template the client expands + * before subscribing. See {@link Changeset} for the full shape and + * {@link /guide/changesets | Changesets} for an overview of the model. + */ + val changesets: List? = null, /** * Additional provider-specific metadata for this session. * @@ -984,14 +992,6 @@ data class SessionSummary( * The working directory URI for this session */ val workingDirectory: String? = null, - /** - * Catalogue of changesets the server can produce for this session. Each - * entry advertises a subscribable view of file changes (uncommitted, - * session-wide, per-turn, etc.) and the URI template the client expands - * before subscribing. See {@link Changeset} for the full shape and - * {@link /guide/changesets | Changesets} for an overview of the model. - */ - val changesets: List? = null, /** * Aggregate summary of file changes associated with this session. Servers * may populate this to give clients a quick at-a-glance view of the diff --git a/clients/rust/CHANGELOG.md b/clients/rust/CHANGELOG.md index 4ced95cc..399a16ec 100644 --- a/clients/rust/CHANGELOG.md +++ b/clients/rust/CHANGELOG.md @@ -26,7 +26,8 @@ matching `## [X.Y.Z]` heading is missing from this file. ### Changed -- Renamed the `ChangesetSummary` type to `Changeset` (catalogue entry on `SessionSummary.changesets`). The on-the-wire shape is unchanged. +- Renamed the `ChangesetSummary` type to `Changeset`. The on-the-wire shape is unchanged. +- Moved the `changesets` catalogue from `SessionSummary` to `SessionState`. The `session/changesetsChanged` action now updates `state.changesets` directly instead of `state.summary.changesets`. ### Removed diff --git a/clients/rust/crates/ahp-types/src/actions.rs b/clients/rust/crates/ahp-types/src/actions.rs index b0d250a3..49fdd8e9 100644 --- a/clients/rust/crates/ahp-types/src/actions.rs +++ b/clients/rust/crates/ahp-types/src/actions.rs @@ -577,8 +577,9 @@ pub struct SessionActivityChangedAction { /// The {@link Changeset | catalogue of changesets} the agent host /// advertises for this session changed. Replaces -/// `state.summary.changesets` entirely (full-replacement semantics) — set -/// to `undefined` to clear the catalogue. +/// {@link SessionState.changesets | `state.changesets`} entirely +/// (full-replacement semantics) — set to `undefined` to clear the +/// catalogue. /// /// Producers dispatch this whenever entries are added or removed. The /// fan-out happens through this action so observers see catalogue diff --git a/clients/rust/crates/ahp-types/src/notifications.rs b/clients/rust/crates/ahp-types/src/notifications.rs index 06064129..f1a55a22 100644 --- a/clients/rust/crates/ahp-types/src/notifications.rs +++ b/clients/rust/crates/ahp-types/src/notifications.rs @@ -79,8 +79,7 @@ pub struct SessionRemovedParams { /// {@link SessionSummary | `SessionSummary`} changes for a session the /// server has surfaced via `listSessions()` or `root/sessionAdded`. /// Servers MAY coalesce or debounce updates for noisy fields (for example, -/// `modifiedAt` bumps while a turn is streaming, or rapidly changing -/// `changesets`) at their discretion. +/// `modifiedAt` bumps while a turn is streaming) at their discretion. /// - Clients that have no cached entry for `session` MAY ignore the /// notification; it is not a substitute for `root/sessionAdded`. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -218,13 +217,6 @@ pub struct PartialSessionSummary { /// The working directory URI for this session #[serde(default, skip_serializing_if = "Option::is_none")] pub working_directory: Option, - /// Catalogue of changesets the server can produce for this session. Each - /// entry advertises a subscribable view of file changes (uncommitted, - /// session-wide, per-turn, etc.) and the URI template the client expands - /// before subscribing. See {@link Changeset} for the full shape and - /// {@link /guide/changesets | Changesets} for an overview of the model. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub changesets: Option>, /// Aggregate summary of file changes associated with this session. Servers /// may populate this to give clients a quick at-a-glance view of the /// session's footprint (e.g., for list rendering) without requiring the diff --git a/clients/rust/crates/ahp-types/src/state.rs b/clients/rust/crates/ahp-types/src/state.rs index 73447c55..2770b915 100644 --- a/clients/rust/crates/ahp-types/src/state.rs +++ b/clients/rust/crates/ahp-types/src/state.rs @@ -716,6 +716,13 @@ pub struct SessionState { /// container's `clientId` set and `children` populated). #[serde(default, skip_serializing_if = "Option::is_none")] pub customizations: Option>, + /// Catalogue of changesets the server can produce for this session. Each + /// entry advertises a subscribable view of file changes (uncommitted, + /// session-wide, per-turn, etc.) and the URI template the client expands + /// before subscribing. See {@link Changeset} for the full shape and + /// {@link /guide/changesets | Changesets} for an overview of the model. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub changesets: Option>, /// Additional provider-specific metadata for this session. /// /// Clients MAY look for well-known keys here to provide enhanced UI. @@ -782,13 +789,6 @@ pub struct SessionSummary { /// The working directory URI for this session #[serde(default, skip_serializing_if = "Option::is_none")] pub working_directory: Option, - /// Catalogue of changesets the server can produce for this session. Each - /// entry advertises a subscribable view of file changes (uncommitted, - /// session-wide, per-turn, etc.) and the URI template the client expands - /// before subscribing. See {@link Changeset} for the full shape and - /// {@link /guide/changesets | Changesets} for an overview of the model. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub changesets: Option>, /// Aggregate summary of file changes associated with this session. Servers /// may populate this to give clients a quick at-a-glance view of the /// session's footprint (e.g., for list rendering) without requiring the diff --git a/clients/rust/crates/ahp/src/hosts/runtime.rs b/clients/rust/crates/ahp/src/hosts/runtime.rs index a8a2f92d..941bbd85 100644 --- a/clients/rust/crates/ahp/src/hosts/runtime.rs +++ b/clients/rust/crates/ahp/src/hosts/runtime.rs @@ -720,9 +720,6 @@ fn apply_summary_changes( if let Some(v) = &changes.working_directory { existing.working_directory = Some(v.clone()); } - if let Some(v) = &changes.changesets { - existing.changesets = Some(v.clone()); - } } // ─── Random helpers (no external dep on `rand`) ───────────────────────────── diff --git a/clients/rust/crates/ahp/src/reducers.rs b/clients/rust/crates/ahp/src/reducers.rs index 3b680848..5599bb83 100644 --- a/clients/rust/crates/ahp/src/reducers.rs +++ b/clients/rust/crates/ahp/src/reducers.rs @@ -619,7 +619,7 @@ pub fn apply_action_to_session(state: &mut SessionState, action: &StateAction) - ReduceOutcome::Applied } StateAction::SessionChangesetsChanged(a) => { - state.summary.changesets = a.changesets.clone(); + state.changesets = a.changesets.clone(); ReduceOutcome::Applied } StateAction::SessionConfigChanged(a) => { @@ -1219,7 +1219,6 @@ mod tests { model: None, agent: None, working_directory: None, - changesets: None, changes: None, }, lifecycle: SessionLifecycle::Creating, @@ -1233,6 +1232,7 @@ mod tests { input_requests: None, config: None, customizations: None, + changesets: None, meta: None, } } diff --git a/clients/rust/crates/ahp/tests/hosts.rs b/clients/rust/crates/ahp/tests/hosts.rs index 9a6a8afd..cf5e9da7 100644 --- a/clients/rust/crates/ahp/tests/hosts.rs +++ b/clients/rust/crates/ahp/tests/hosts.rs @@ -1032,7 +1032,6 @@ fn make_summary(uri: &str, title: &str, modified_at: i64) -> ahp_types::state::S model: None, agent: None, working_directory: None, - changesets: None, changes: None, } } diff --git a/clients/rust/crates/ahp/tests/multi_host_state_mirror.rs b/clients/rust/crates/ahp/tests/multi_host_state_mirror.rs index 313fba76..5f830bd7 100644 --- a/clients/rust/crates/ahp/tests/multi_host_state_mirror.rs +++ b/clients/rust/crates/ahp/tests/multi_host_state_mirror.rs @@ -56,7 +56,6 @@ fn session_state(title: &str, resource: &str) -> SessionState { model: None, agent: None, working_directory: None, - changesets: None, changes: None, }, lifecycle: SessionLifecycle::Ready, @@ -70,6 +69,7 @@ fn session_state(title: &str, resource: &str) -> SessionState { input_requests: None, config: None, customizations: None, + changesets: None, meta: None, } } @@ -364,7 +364,6 @@ fn non_action_event_is_ignored() { model: None, agent: None, working_directory: None, - changesets: None, changes: None, }, }), diff --git a/clients/swift/AHPApp/AHPApp/Store/AppStore.swift b/clients/swift/AHPApp/AHPApp/Store/AppStore.swift index 0bf3a193..7e01ae47 100644 --- a/clients/swift/AHPApp/AHPApp/Store/AppStore.swift +++ b/clients/swift/AHPApp/AHPApp/Store/AppStore.swift @@ -1283,7 +1283,6 @@ final class AppStore { if let v = changes.project { summary.project = v } if let v = changes.model { summary.model = v } if let v = changes.workingDirectory { summary.workingDirectory = v } - if let v = changes.changesets { summary.changesets = v } sessionSummariesCache[uri] = summary } diff --git a/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Notifications.generated.swift b/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Notifications.generated.swift index cecc034c..e5f9ff00 100644 --- a/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Notifications.generated.swift +++ b/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Notifications.generated.swift @@ -164,12 +164,6 @@ public struct PartialSessionSummary: Codable, Sendable { public var agent: AgentSelection? /// The working directory URI for this session public var workingDirectory: String? - /// Catalogue of changesets the server can produce for this session. Each - /// entry advertises a subscribable view of file changes (uncommitted, - /// session-wide, per-turn, etc.) and the URI template the client expands - /// before subscribing. See {@link Changeset} for the full shape and - /// {@link /guide/changesets | Changesets} for an overview of the model. - public var changesets: [Changeset]? /// Aggregate summary of file changes associated with this session. Servers /// may populate this to give clients a quick at-a-glance view of the /// session's footprint (e.g., for list rendering) without requiring the @@ -188,7 +182,6 @@ public struct PartialSessionSummary: Codable, Sendable { model: ModelSelection? = nil, agent: AgentSelection? = nil, workingDirectory: String? = nil, - changesets: [Changeset]? = nil, changes: ChangesSummary? = nil ) { self.resource = resource @@ -202,7 +195,6 @@ public struct PartialSessionSummary: Codable, Sendable { self.model = model self.agent = agent self.workingDirectory = workingDirectory - self.changesets = changesets self.changes = changes } } diff --git a/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/State.generated.swift b/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/State.generated.swift index de23729c..d6fbd9cb 100644 --- a/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/State.generated.swift +++ b/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/State.generated.swift @@ -687,6 +687,12 @@ public struct SessionState: Codable, Sendable { /// and the host propagates them into this list (typically with the /// container's `clientId` set and `children` populated). public var customizations: [Customization]? + /// Catalogue of changesets the server can produce for this session. Each + /// entry advertises a subscribable view of file changes (uncommitted, + /// session-wide, per-turn, etc.) and the URI template the client expands + /// before subscribing. See {@link Changeset} for the full shape and + /// {@link /guide/changesets | Changesets} for an overview of the model. + public var changesets: [Changeset]? /// Additional provider-specific metadata for this session. /// /// Clients MAY look for well-known keys here to provide enhanced UI. @@ -707,6 +713,7 @@ public struct SessionState: Codable, Sendable { case inputRequests case config case customizations + case changesets case meta = "_meta" } @@ -723,6 +730,7 @@ public struct SessionState: Codable, Sendable { inputRequests: [SessionInputRequest]? = nil, config: SessionConfigState? = nil, customizations: [Customization]? = nil, + changesets: [Changeset]? = nil, meta: [String: AnyCodable]? = nil ) { self.summary = summary @@ -737,6 +745,7 @@ public struct SessionState: Codable, Sendable { self.inputRequests = inputRequests self.config = config self.customizations = customizations + self.changesets = changesets self.meta = meta } } @@ -795,12 +804,6 @@ public struct SessionSummary: Codable, Sendable { public var agent: AgentSelection? /// The working directory URI for this session public var workingDirectory: String? - /// Catalogue of changesets the server can produce for this session. Each - /// entry advertises a subscribable view of file changes (uncommitted, - /// session-wide, per-turn, etc.) and the URI template the client expands - /// before subscribing. See {@link Changeset} for the full shape and - /// {@link /guide/changesets | Changesets} for an overview of the model. - public var changesets: [Changeset]? /// Aggregate summary of file changes associated with this session. Servers /// may populate this to give clients a quick at-a-glance view of the /// session's footprint (e.g., for list rendering) without requiring the @@ -819,7 +822,6 @@ public struct SessionSummary: Codable, Sendable { model: ModelSelection? = nil, agent: AgentSelection? = nil, workingDirectory: String? = nil, - changesets: [Changeset]? = nil, changes: ChangesSummary? = nil ) { self.resource = resource @@ -833,7 +835,6 @@ public struct SessionSummary: Codable, Sendable { self.model = model self.agent = agent self.workingDirectory = workingDirectory - self.changesets = changesets self.changes = changes } } diff --git a/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Reducers.swift b/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Reducers.swift index f6524a86..042af8a3 100644 --- a/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Reducers.swift +++ b/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Reducers.swift @@ -376,7 +376,7 @@ public func sessionReducer(state: SessionState, action: StateAction) -> SessionS case .sessionChangesetsChanged(let a): var next = state - next.summary.changesets = a.changesets + next.changesets = a.changesets return next case .sessionConfigChanged(let a): diff --git a/clients/swift/AgentHostProtocol/Sources/AgentHostProtocolClient/Hosts/HostRuntime.swift b/clients/swift/AgentHostProtocol/Sources/AgentHostProtocolClient/Hosts/HostRuntime.swift index 42d1d0e4..f4d3a463 100644 --- a/clients/swift/AgentHostProtocol/Sources/AgentHostProtocolClient/Hosts/HostRuntime.swift +++ b/clients/swift/AgentHostProtocol/Sources/AgentHostProtocolClient/Hosts/HostRuntime.swift @@ -829,7 +829,6 @@ private func applySummaryChanges( if let v = changes.project { existing.project = v } if let v = changes.model { existing.model = v } if let v = changes.workingDirectory { existing.workingDirectory = v } - if let v = changes.changesets { existing.changesets = v } } /// Protocol version offered on `initialize`. Mirrors the Rust SDK's use of diff --git a/clients/swift/CHANGELOG.md b/clients/swift/CHANGELOG.md index 5617f9fb..4a4408e2 100644 --- a/clients/swift/CHANGELOG.md +++ b/clients/swift/CHANGELOG.md @@ -28,7 +28,8 @@ the tag matches the version pinned in [`VERSION`](VERSION). ### Changed -- Renamed the `ChangesetSummary` type to `Changeset` (catalogue entry on `SessionSummary.changesets`). The on-the-wire shape is unchanged. +- Renamed the `ChangesetSummary` type to `Changeset`. The on-the-wire shape is unchanged. +- Moved the `changesets` catalogue from `SessionSummary` to `SessionState`. The `session/changesetsChanged` action now updates `state.changesets` directly instead of `state.summary.changesets`. ### Removed diff --git a/clients/typescript/CHANGELOG.md b/clients/typescript/CHANGELOG.md index 3e7104d4..5d80d4e7 100644 --- a/clients/typescript/CHANGELOG.md +++ b/clients/typescript/CHANGELOG.md @@ -31,7 +31,8 @@ hotfix escape hatch. ### Changed -- Renamed the `ChangesetSummary` type to `Changeset` (catalogue entry on `SessionSummary.changesets`). The on-the-wire shape is unchanged. +- Renamed the `ChangesetSummary` type to `Changeset`. The on-the-wire shape is unchanged. +- Moved the `changesets` catalogue from `SessionSummary` to `SessionState`. The `session/changesetsChanged` action now updates `state.changesets` directly instead of `state.summary.changesets`. ### Removed diff --git a/clients/typescript/src/client/hosts/runtime.ts b/clients/typescript/src/client/hosts/runtime.ts index 6c98bb44..f1927e24 100644 --- a/clients/typescript/src/client/hosts/runtime.ts +++ b/clients/typescript/src/client/hosts/runtime.ts @@ -882,6 +882,5 @@ function applySummaryChange( if (changes.project !== undefined) merged.project = changes.project; if (changes.model !== undefined) merged.model = changes.model; if (changes.workingDirectory !== undefined) merged.workingDirectory = changes.workingDirectory; - if (changes.changesets !== undefined) merged.changesets = changes.changesets; cache.set(params.session, merged); } diff --git a/docs/guide/changesets.md b/docs/guide/changesets.md index 2113511b..70f55c3b 100644 --- a/docs/guide/changesets.md +++ b/docs/guide/changesets.md @@ -11,13 +11,13 @@ each with its own URI, lifecycle, and update stream. ### Changeset Catalogue -Each session's `SessionSummary` advertises the set of changesets the -server can produce. The summary entry is intentionally lightweight — +Each session's `SessionState` advertises the set of changesets the +server can produce. The catalogue entry is intentionally lightweight — just enough to render a chip or list row without subscribing — and references a full subscribable `ChangesetState` by URI. ```typescript -SessionSummary { +SessionState { // ...existing fields... changesets?: Changeset[] } @@ -148,9 +148,9 @@ a JSON-RPC error. ## Lifecycle -1. The server publishes the catalogue on `SessionSummary.changesets`. - Updates ride on `root/sessionSummaryChanged`. -2. The client picks summary entries whose template variables it can +1. The server publishes the catalogue on `SessionState.changesets`. + Updates ride on the `session/changesetsChanged` action. +2. The client picks catalogue entries whose template variables it can satisfy and subscribes to the resulting URIs. 3. The server returns a `ChangesetState` snapshot (`status: 'computing'` is allowed if scanning is async) and pushes `changeset/*` actions as diff --git a/docs/guide/state-model.md b/docs/guide/state-model.md index 44c59a20..8bb4cd29 100644 --- a/docs/guide/state-model.md +++ b/docs/guide/state-model.md @@ -378,7 +378,7 @@ The session list can be arbitrarily large and is **not** part of the state tree. - Clients fetch the list imperatively via `listSessions()` RPC. - The server sends lightweight **notifications** to keep connected clients' caches in sync without re-fetching: - `root/sessionAdded` and `root/sessionRemoved` signal lifecycle (creation and disposal). - - `root/sessionSummaryChanged` streams partial updates to an existing session's summary (title, status, `modifiedAt`, project, model, working directory, `changesets`) so clients that are displaying a session list can stay in sync without subscribing to every session URI individually. Only fields present in `changes` carry new values; omitted fields are unchanged. The server SHOULD emit this notification whenever any mutable summary field changes, and MAY coalesce or debounce noisy updates (for example, rapid `modifiedAt` bumps while a turn is streaming) at its discretion. + - `root/sessionSummaryChanged` streams partial updates to an existing session's summary (title, status, `modifiedAt`, project, model, working directory) so clients that are displaying a session list can stay in sync without subscribing to every session URI individually. Only fields present in `changes` carry new values; omitted fields are unchanged. The server SHOULD emit this notification whenever any mutable summary field changes, and MAY coalesce or debounce noisy updates (for example, rapid `modifiedAt` bumps while a turn is streaming) at its discretion. Notifications are ephemeral — not processed by reducers, not stored in state, not replayed on reconnect. On reconnect, clients re-fetch the list. diff --git a/plugins/channels-migration-plugin/skills/channels-migration/SKILL.md b/plugins/channels-migration-plugin/skills/channels-migration/SKILL.md index 7e525029..bfaaab3b 100644 --- a/plugins/channels-migration-plugin/skills/channels-migration/SKILL.md +++ b/plugins/channels-migration-plugin/skills/channels-migration/SKILL.md @@ -433,7 +433,7 @@ After the migration, your code should: - [ ] Resolve a session's provider via `SessionSummary.provider`, not via the URI scheme. - [ ] No `SessionDiffsChangedAction` / `summary.diffs` references; consume - `summary.changesets` plus the `changeset/*` action family instead. + `SessionState.changesets` plus the `changeset/*` action family instead. - [ ] Every command's params carries `channel: URI`. Channel-scoped commands (`createSession`, `disposeSession`, `createTerminal`, `disposeTerminal`, `fetchTurns`, `completions`, diff --git a/schema/actions.schema.json b/schema/actions.schema.json index ec8b6508..5eed1229 100644 --- a/schema/actions.schema.json +++ b/schema/actions.schema.json @@ -809,7 +809,7 @@ }, "SessionChangesetsChangedAction": { "type": "object", - "description": "The {@link Changeset | catalogue of changesets} the agent host\nadvertises for this session changed. Replaces\n`state.summary.changesets` entirely (full-replacement semantics) — set\nto `undefined` to clear the catalogue.\n\nProducers dispatch this whenever entries are added or removed. The\nfan-out happens through this action so observers see catalogue\nmutations in the same {@link ChangesetAction | per-changeset} action\nstream they already follow for file-level updates.", + "description": "The {@link Changeset | catalogue of changesets} the agent host\nadvertises for this session changed. Replaces\n{@link SessionState.changesets | `state.changesets`} entirely\n(full-replacement semantics) — set to `undefined` to clear the\ncatalogue.\n\nProducers dispatch this whenever entries are added or removed. The\nfan-out happens through this action so observers see catalogue\nmutations in the same {@link ChangesetAction | per-changeset} action\nstream they already follow for file-level updates.", "properties": { "type": { "$ref": "#/$defs/ActionType.SessionChangesetsChanged" @@ -2173,6 +2173,13 @@ }, "description": "Top-level customizations active in this session.\n\nAlways container customizations — {@link PluginCustomization} or\n{@link DirectoryCustomization}. Children (agents, skills, prompts,\nrules, hooks, MCP servers) live in each container's\n{@link ContainerCustomizationBase.children | `children`} array.\n\nClient-published plugins arrive via\n{@link SessionActiveClient.customizations | `activeClient.customizations`}\nand the host propagates them into this list (typically with the\ncontainer's `clientId` set and `children` populated)." }, + "changesets": { + "type": "array", + "items": { + "$ref": "#/$defs/Changeset" + }, + "description": "Catalogue of changesets the server can produce for this session. Each\nentry advertises a subscribable view of file changes (uncommitted,\nsession-wide, per-turn, etc.) and the URI template the client expands\nbefore subscribing. See {@link Changeset} for the full shape and\n{@link /guide/changesets | Changesets} for an overview of the model." + }, "_meta": { "type": "object", "additionalProperties": {}, @@ -2282,13 +2289,6 @@ "$ref": "#/$defs/URI", "description": "The working directory URI for this session" }, - "changesets": { - "type": "array", - "items": { - "$ref": "#/$defs/Changeset" - }, - "description": "Catalogue of changesets the server can produce for this session. Each\nentry advertises a subscribable view of file changes (uncommitted,\nsession-wide, per-turn, etc.) and the URI template the client expands\nbefore subscribing. See {@link Changeset} for the full shape and\n{@link /guide/changesets | Changesets} for an overview of the model." - }, "changes": { "$ref": "#/$defs/ChangesSummary", "description": "Aggregate summary of file changes associated with this session. Servers\nmay populate this to give clients a quick at-a-glance view of the\nsession's footprint (e.g., for list rendering) without requiring the\nclient to subscribe to a changeset." diff --git a/schema/commands.schema.json b/schema/commands.schema.json index b9ea5bc4..4b2bbac0 100644 --- a/schema/commands.schema.json +++ b/schema/commands.schema.json @@ -1824,6 +1824,13 @@ }, "description": "Top-level customizations active in this session.\n\nAlways container customizations — {@link PluginCustomization} or\n{@link DirectoryCustomization}. Children (agents, skills, prompts,\nrules, hooks, MCP servers) live in each container's\n{@link ContainerCustomizationBase.children | `children`} array.\n\nClient-published plugins arrive via\n{@link SessionActiveClient.customizations | `activeClient.customizations`}\nand the host propagates them into this list (typically with the\ncontainer's `clientId` set and `children` populated)." }, + "changesets": { + "type": "array", + "items": { + "$ref": "#/$defs/Changeset" + }, + "description": "Catalogue of changesets the server can produce for this session. Each\nentry advertises a subscribable view of file changes (uncommitted,\nsession-wide, per-turn, etc.) and the URI template the client expands\nbefore subscribing. See {@link Changeset} for the full shape and\n{@link /guide/changesets | Changesets} for an overview of the model." + }, "_meta": { "type": "object", "additionalProperties": {}, @@ -1933,13 +1940,6 @@ "$ref": "#/$defs/URI", "description": "The working directory URI for this session" }, - "changesets": { - "type": "array", - "items": { - "$ref": "#/$defs/Changeset" - }, - "description": "Catalogue of changesets the server can produce for this session. Each\nentry advertises a subscribable view of file changes (uncommitted,\nsession-wide, per-turn, etc.) and the URI template the client expands\nbefore subscribing. See {@link Changeset} for the full shape and\n{@link /guide/changesets | Changesets} for an overview of the model." - }, "changes": { "$ref": "#/$defs/ChangesSummary", "description": "Aggregate summary of file changes associated with this session. Servers\nmay populate this to give clients a quick at-a-glance view of the\nsession's footprint (e.g., for list rendering) without requiring the\nclient to subscribe to a changeset." @@ -5526,7 +5526,7 @@ }, "SessionChangesetsChangedAction": { "type": "object", - "description": "The {@link Changeset | catalogue of changesets} the agent host\nadvertises for this session changed. Replaces\n`state.summary.changesets` entirely (full-replacement semantics) — set\nto `undefined` to clear the catalogue.\n\nProducers dispatch this whenever entries are added or removed. The\nfan-out happens through this action so observers see catalogue\nmutations in the same {@link ChangesetAction | per-changeset} action\nstream they already follow for file-level updates.", + "description": "The {@link Changeset | catalogue of changesets} the agent host\nadvertises for this session changed. Replaces\n{@link SessionState.changesets | `state.changesets`} entirely\n(full-replacement semantics) — set to `undefined` to clear the\ncatalogue.\n\nProducers dispatch this whenever entries are added or removed. The\nfan-out happens through this action so observers see catalogue\nmutations in the same {@link ChangesetAction | per-changeset} action\nstream they already follow for file-level updates.", "properties": { "type": { "$ref": "#/$defs/ActionType.SessionChangesetsChanged" diff --git a/schema/errors.schema.json b/schema/errors.schema.json index 6d8f9d84..7bfa2977 100644 --- a/schema/errors.schema.json +++ b/schema/errors.schema.json @@ -756,6 +756,13 @@ }, "description": "Top-level customizations active in this session.\n\nAlways container customizations — {@link PluginCustomization} or\n{@link DirectoryCustomization}. Children (agents, skills, prompts,\nrules, hooks, MCP servers) live in each container's\n{@link ContainerCustomizationBase.children | `children`} array.\n\nClient-published plugins arrive via\n{@link SessionActiveClient.customizations | `activeClient.customizations`}\nand the host propagates them into this list (typically with the\ncontainer's `clientId` set and `children` populated)." }, + "changesets": { + "type": "array", + "items": { + "$ref": "#/$defs/Changeset" + }, + "description": "Catalogue of changesets the server can produce for this session. Each\nentry advertises a subscribable view of file changes (uncommitted,\nsession-wide, per-turn, etc.) and the URI template the client expands\nbefore subscribing. See {@link Changeset} for the full shape and\n{@link /guide/changesets | Changesets} for an overview of the model." + }, "_meta": { "type": "object", "additionalProperties": {}, @@ -865,13 +872,6 @@ "$ref": "#/$defs/URI", "description": "The working directory URI for this session" }, - "changesets": { - "type": "array", - "items": { - "$ref": "#/$defs/Changeset" - }, - "description": "Catalogue of changesets the server can produce for this session. Each\nentry advertises a subscribable view of file changes (uncommitted,\nsession-wide, per-turn, etc.) and the URI template the client expands\nbefore subscribing. See {@link Changeset} for the full shape and\n{@link /guide/changesets | Changesets} for an overview of the model." - }, "changes": { "$ref": "#/$defs/ChangesSummary", "description": "Aggregate summary of file changes associated with this session. Servers\nmay populate this to give clients a quick at-a-glance view of the\nsession's footprint (e.g., for list rendering) without requiring the\nclient to subscribe to a changeset." diff --git a/schema/notifications.schema.json b/schema/notifications.schema.json index 9408126b..b93d9cda 100644 --- a/schema/notifications.schema.json +++ b/schema/notifications.schema.json @@ -65,7 +65,7 @@ }, "SessionSummaryChangedParams": { "type": "object", - "description": "Broadcast to all clients subscribed to the root channel when an existing\nsession's summary changes (title, status, `modifiedAt`, model, working\ndirectory, read/done state, or diff statistics).\n\nThis notification lets clients that maintain a cached session list — for\nexample, the result of a previous `listSessions()` call — stay in sync with\nin-flight sessions without having to subscribe to every session URI\nindividually. It is complementary to, not a replacement for,\n`root/sessionAdded` and `root/sessionRemoved`: those signal lifecycle\n(creation/disposal), while this signals summary-level mutations on an\nalready-known session.\n\nSemantics:\n\n- Only fields present in `changes` have new values; omitted fields are\n unchanged on the client's cached summary.\n- Identity fields (`resource`, `provider`, `createdAt`) never change and\n are not carried.\n- Like all protocol notifications, this is ephemeral: it is **not**\n replayed on reconnect. On reconnect, clients should re-fetch the full\n catalog via `listSessions()` as usual.\n- The server SHOULD emit this notification whenever any mutable field on\n {@link SessionSummary | `SessionSummary`} changes for a session the\n server has surfaced via `listSessions()` or `root/sessionAdded`.\n Servers MAY coalesce or debounce updates for noisy fields (for example,\n `modifiedAt` bumps while a turn is streaming, or rapidly changing\n `changesets`) at their discretion.\n- Clients that have no cached entry for `session` MAY ignore the\n notification; it is not a substitute for `root/sessionAdded`.", + "description": "Broadcast to all clients subscribed to the root channel when an existing\nsession's summary changes (title, status, `modifiedAt`, model, working\ndirectory, read/done state, or diff statistics).\n\nThis notification lets clients that maintain a cached session list — for\nexample, the result of a previous `listSessions()` call — stay in sync with\nin-flight sessions without having to subscribe to every session URI\nindividually. It is complementary to, not a replacement for,\n`root/sessionAdded` and `root/sessionRemoved`: those signal lifecycle\n(creation/disposal), while this signals summary-level mutations on an\nalready-known session.\n\nSemantics:\n\n- Only fields present in `changes` have new values; omitted fields are\n unchanged on the client's cached summary.\n- Identity fields (`resource`, `provider`, `createdAt`) never change and\n are not carried.\n- Like all protocol notifications, this is ephemeral: it is **not**\n replayed on reconnect. On reconnect, clients should re-fetch the full\n catalog via `listSessions()` as usual.\n- The server SHOULD emit this notification whenever any mutable field on\n {@link SessionSummary | `SessionSummary`} changes for a session the\n server has surfaced via `listSessions()` or `root/sessionAdded`.\n Servers MAY coalesce or debounce updates for noisy fields (for example,\n `modifiedAt` bumps while a turn is streaming) at their discretion.\n- Clients that have no cached entry for `session` MAY ignore the\n notification; it is not a substitute for `root/sessionAdded`.", "properties": { "channel": { "$ref": "#/$defs/URI", @@ -122,13 +122,6 @@ "$ref": "#/$defs/URI", "description": "The working directory URI for this session" }, - "changesets": { - "type": "array", - "items": { - "$ref": "#/$defs/Changeset" - }, - "description": "Catalogue of changesets the server can produce for this session. Each\nentry advertises a subscribable view of file changes (uncommitted,\nsession-wide, per-turn, etc.) and the URI template the client expands\nbefore subscribing. See {@link Changeset} for the full shape and\n{@link /guide/changesets | Changesets} for an overview of the model." - }, "changes": { "$ref": "#/$defs/ChangesSummary", "description": "Aggregate summary of file changes associated with this session. Servers\nmay populate this to give clients a quick at-a-glance view of the\nsession's footprint (e.g., for list rendering) without requiring the\nclient to subscribe to a changeset." @@ -888,6 +881,13 @@ }, "description": "Top-level customizations active in this session.\n\nAlways container customizations — {@link PluginCustomization} or\n{@link DirectoryCustomization}. Children (agents, skills, prompts,\nrules, hooks, MCP servers) live in each container's\n{@link ContainerCustomizationBase.children | `children`} array.\n\nClient-published plugins arrive via\n{@link SessionActiveClient.customizations | `activeClient.customizations`}\nand the host propagates them into this list (typically with the\ncontainer's `clientId` set and `children` populated)." }, + "changesets": { + "type": "array", + "items": { + "$ref": "#/$defs/Changeset" + }, + "description": "Catalogue of changesets the server can produce for this session. Each\nentry advertises a subscribable view of file changes (uncommitted,\nsession-wide, per-turn, etc.) and the URI template the client expands\nbefore subscribing. See {@link Changeset} for the full shape and\n{@link /guide/changesets | Changesets} for an overview of the model." + }, "_meta": { "type": "object", "additionalProperties": {}, @@ -997,13 +997,6 @@ "$ref": "#/$defs/URI", "description": "The working directory URI for this session" }, - "changesets": { - "type": "array", - "items": { - "$ref": "#/$defs/Changeset" - }, - "description": "Catalogue of changesets the server can produce for this session. Each\nentry advertises a subscribable view of file changes (uncommitted,\nsession-wide, per-turn, etc.) and the URI template the client expands\nbefore subscribing. See {@link Changeset} for the full shape and\n{@link /guide/changesets | Changesets} for an overview of the model." - }, "changes": { "$ref": "#/$defs/ChangesSummary", "description": "Aggregate summary of file changes associated with this session. Servers\nmay populate this to give clients a quick at-a-glance view of the\nsession's footprint (e.g., for list rendering) without requiring the\nclient to subscribe to a changeset." diff --git a/schema/state.schema.json b/schema/state.schema.json index 7da12efb..52e5371f 100644 --- a/schema/state.schema.json +++ b/schema/state.schema.json @@ -667,6 +667,13 @@ }, "description": "Top-level customizations active in this session.\n\nAlways container customizations — {@link PluginCustomization} or\n{@link DirectoryCustomization}. Children (agents, skills, prompts,\nrules, hooks, MCP servers) live in each container's\n{@link ContainerCustomizationBase.children | `children`} array.\n\nClient-published plugins arrive via\n{@link SessionActiveClient.customizations | `activeClient.customizations`}\nand the host propagates them into this list (typically with the\ncontainer's `clientId` set and `children` populated)." }, + "changesets": { + "type": "array", + "items": { + "$ref": "#/$defs/Changeset" + }, + "description": "Catalogue of changesets the server can produce for this session. Each\nentry advertises a subscribable view of file changes (uncommitted,\nsession-wide, per-turn, etc.) and the URI template the client expands\nbefore subscribing. See {@link Changeset} for the full shape and\n{@link /guide/changesets | Changesets} for an overview of the model." + }, "_meta": { "type": "object", "additionalProperties": {}, @@ -776,13 +783,6 @@ "$ref": "#/$defs/URI", "description": "The working directory URI for this session" }, - "changesets": { - "type": "array", - "items": { - "$ref": "#/$defs/Changeset" - }, - "description": "Catalogue of changesets the server can produce for this session. Each\nentry advertises a subscribable view of file changes (uncommitted,\nsession-wide, per-turn, etc.) and the URI template the client expands\nbefore subscribing. See {@link Changeset} for the full shape and\n{@link /guide/changesets | Changesets} for an overview of the model." - }, "changes": { "$ref": "#/$defs/ChangesSummary", "description": "Aggregate summary of file changes associated with this session. Servers\nmay populate this to give clients a quick at-a-glance view of the\nsession's footprint (e.g., for list rendering) without requiring the\nclient to subscribe to a changeset." diff --git a/types/channels-root/notifications.ts b/types/channels-root/notifications.ts index b7f15662..32fea359 100644 --- a/types/channels-root/notifications.ts +++ b/types/channels-root/notifications.ts @@ -103,8 +103,7 @@ export interface SessionRemovedParams { * {@link SessionSummary | `SessionSummary`} changes for a session the * server has surfaced via `listSessions()` or `root/sessionAdded`. * Servers MAY coalesce or debounce updates for noisy fields (for example, - * `modifiedAt` bumps while a turn is streaming, or rapidly changing - * `changesets`) at their discretion. + * `modifiedAt` bumps while a turn is streaming) at their discretion. * - Clients that have no cached entry for `session` MAY ignore the * notification; it is not a substitute for `root/sessionAdded`. * diff --git a/types/channels-session/actions.ts b/types/channels-session/actions.ts index 02be1a5b..4881eca5 100644 --- a/types/channels-session/actions.ts +++ b/types/channels-session/actions.ts @@ -494,8 +494,9 @@ export interface SessionActivityChangedAction { /** * The {@link Changeset | catalogue of changesets} the agent host * advertises for this session changed. Replaces - * `state.summary.changesets` entirely (full-replacement semantics) — set - * to `undefined` to clear the catalogue. + * {@link SessionState.changesets | `state.changesets`} entirely + * (full-replacement semantics) — set to `undefined` to clear the + * catalogue. * * Producers dispatch this whenever entries are added or removed. The * fan-out happens through this action so observers see catalogue diff --git a/types/channels-session/reducer.ts b/types/channels-session/reducer.ts index ea162676..3273ad2a 100644 --- a/types/channels-session/reducer.ts +++ b/types/channels-session/reducer.ts @@ -568,11 +568,10 @@ export function sessionReducer(state: SessionState, action: SessionAction, log?: }; case ActionType.SessionChangesetsChanged: { - const { changesets: _omit, ...summaryWithoutChangesets } = state.summary; - const newSummary = action.changesets - ? { ...summaryWithoutChangesets, changesets: action.changesets } - : summaryWithoutChangesets; - return { ...state, summary: newSummary }; + const { changesets: _omit, ...stateWithoutChangesets } = state; + return action.changesets + ? { ...stateWithoutChangesets, changesets: action.changesets } + : stateWithoutChangesets; } case ActionType.SessionConfigChanged: diff --git a/types/channels-session/state.ts b/types/channels-session/state.ts index d2bf6a42..488ed6d8 100644 --- a/types/channels-session/state.ts +++ b/types/channels-session/state.ts @@ -17,8 +17,8 @@ import type { TextSelection, UsageInfo, } from '../common/state.js'; -import type { Changeset } from '../channels-changeset/state.js'; import type { ModelSelection } from '../channels-root/state.js'; +import type { Changeset } from '../channels-changeset/state.js'; // ─── Pending Message Types ─────────────────────────────────────────────────── @@ -129,6 +129,14 @@ export interface SessionState { * container's `clientId` set and `children` populated). */ customizations?: Customization[]; + /** + * Catalogue of changesets the server can produce for this session. Each + * entry advertises a subscribable view of file changes (uncommitted, + * session-wide, per-turn, etc.) and the URI template the client expands + * before subscribing. See {@link Changeset} for the full shape and + * {@link /guide/changesets | Changesets} for an overview of the model. + */ + changesets?: Changeset[]; /** * Additional provider-specific metadata for this session. * @@ -208,14 +216,6 @@ export interface SessionSummary { agent?: AgentSelection; /** The working directory URI for this session */ workingDirectory?: URI; - /** - * Catalogue of changesets the server can produce for this session. Each - * entry advertises a subscribable view of file changes (uncommitted, - * session-wide, per-turn, etc.) and the URI template the client expands - * before subscribing. See {@link Changeset} for the full shape and - * {@link /guide/changesets | Changesets} for an overview of the model. - */ - changesets?: Changeset[]; /** * Aggregate summary of file changes associated with this session. Servers * may populate this to give clients a quick at-a-glance view of the diff --git a/types/test-cases/reducers/145-session-changesetschanged-sets-catalogue.json b/types/test-cases/reducers/145-session-changesetschanged-sets-catalogue.json index 9f6cb3fc..7bdb0405 100644 --- a/types/test-cases/reducers/145-session-changesetschanged-sets-catalogue.json +++ b/types/test-cases/reducers/145-session-changesetschanged-sets-catalogue.json @@ -1,5 +1,5 @@ { - "description": "session/changesetsChanged replaces summary.changesets with the new catalogue", + "description": "session/changesetsChanged replaces state.changesets with the new catalogue", "reducer": "session", "initial": { "summary": { @@ -31,15 +31,15 @@ "title": "Test Session", "status": 1, "createdAt": 1000, - "modifiedAt": 1000, - "changesets": [ - { - "label": "Session Changes", - "uriTemplate": "copilot:/test-session/changeset/session" - } - ] + "modifiedAt": 1000 }, "lifecycle": "ready", - "turns": [] + "turns": [], + "changesets": [ + { + "label": "Session Changes", + "uriTemplate": "copilot:/test-session/changeset/session" + } + ] } } diff --git a/types/test-cases/reducers/146-session-changesetschanged-clears-catalogue.json b/types/test-cases/reducers/146-session-changesetschanged-clears-catalogue.json index 37d01991..78c6c5b1 100644 --- a/types/test-cases/reducers/146-session-changesetschanged-clears-catalogue.json +++ b/types/test-cases/reducers/146-session-changesetschanged-clears-catalogue.json @@ -1,5 +1,5 @@ { - "description": "session/changesetsChanged with undefined clears summary.changesets", + "description": "session/changesetsChanged with undefined clears state.changesets", "reducer": "session", "initial": { "summary": { @@ -8,16 +8,16 @@ "title": "Test Session", "status": 1, "createdAt": 1000, - "modifiedAt": 1000, - "changesets": [ - { - "label": "Session Changes", - "uriTemplate": "copilot:/test-session/changeset/session" - } - ] + "modifiedAt": 1000 }, "lifecycle": "ready", - "turns": [] + "turns": [], + "changesets": [ + { + "label": "Session Changes", + "uriTemplate": "copilot:/test-session/changeset/session" + } + ] }, "actions": [ {