From b2a3d8cbd99ea16c38ba367e3fa893e5836bc03f Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Thu, 1 Oct 2026 16:07:09 +0200 Subject: [PATCH] Agent Host changes for lszomoru/agents/add-changes-summary-to-session-chat --- .../Generated/State.generated.cs | 8 +++ clients/go/ahptypes/state.generated.go | 6 ++ .../generated/State.generated.kt | 10 ++- clients/rust/crates/ahp-types/src/state.rs | 7 ++ .../Generated/State.generated.swift | 10 ++- ...20261001-session-chat-summary-changes.json | 4 ++ schema/actions.schema.json | 4 ++ schema/commands.schema.json | 4 ++ schema/errors.schema.json | 4 ++ schema/notifications.schema.json | 4 ++ schema/state.schema.json | 4 ++ types/channels-session/state.ts | 8 +++ ...ssion-chat-summary-changes-round-trip.json | 66 +++++++++++++++++++ 13 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 docs/.changes/20261001-session-chat-summary-changes.json create mode 100644 types/test-cases/round-trips/051-session-chat-summary-changes-round-trip.json diff --git a/clients/dotnet/src/AgentHostProtocol.Abstractions/Generated/State.generated.cs b/clients/dotnet/src/AgentHostProtocol.Abstractions/Generated/State.generated.cs index 73079cc04..c2f7fa83d 100644 --- a/clients/dotnet/src/AgentHostProtocol.Abstractions/Generated/State.generated.cs +++ b/clients/dotnet/src/AgentHostProtocol.Abstractions/Generated/State.generated.cs @@ -2011,6 +2011,14 @@ public sealed record SessionChatSummary /// chat is not archived. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public bool? Archived { get; init; } + + /// Aggregate summary of file changes associated with this chat. + /// + /// Servers may populate this so session lists can show per-chat change + /// counts without subscribing to the session or chat channel. Updates travel + /// with the rest of the catalog in `root/sessionSummaryChanged`. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public ChangesSummary? Changes { get; init; } } /// Aggregate counts describing the file changes associated with a session or diff --git a/clients/go/ahptypes/state.generated.go b/clients/go/ahptypes/state.generated.go index fb84f5630..5516b942b 100644 --- a/clients/go/ahptypes/state.generated.go +++ b/clients/go/ahptypes/state.generated.go @@ -1219,6 +1219,12 @@ type SessionChatSummary struct { // lists without subscribing to the session channel. Absence means the // chat is not archived. Archived *bool `json:"archived,omitempty"` + // Aggregate summary of file changes associated with this chat. + // + // Servers may populate this so session lists can show per-chat change + // counts without subscribing to the session or chat channel. Updates travel + // with the rest of the catalog in `root/sessionSummaryChanged`. + Changes *ChangesSummary `json:"changes,omitempty"` } // Aggregate counts describing the file changes associated with a session or 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 8fb7f0a42..55ee9ffd8 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 @@ -2179,7 +2179,15 @@ data class SessionChatSummary( * lists without subscribing to the session channel. Absence means the * chat is not archived. */ - val archived: Boolean? = null + val archived: Boolean? = null, + /** + * Aggregate summary of file changes associated with this chat. + * + * Servers may populate this so session lists can show per-chat change + * counts without subscribing to the session or chat channel. Updates travel + * with the rest of the catalog in `root/sessionSummaryChanged`. + */ + val changes: ChangesSummary? = null ) @Serializable diff --git a/clients/rust/crates/ahp-types/src/state.rs b/clients/rust/crates/ahp-types/src/state.rs index 99547d09d..6175e8615 100644 --- a/clients/rust/crates/ahp-types/src/state.rs +++ b/clients/rust/crates/ahp-types/src/state.rs @@ -2470,6 +2470,13 @@ pub struct SessionChatSummary { /// chat is not archived. #[serde(default, skip_serializing_if = "Option::is_none")] pub archived: Option, + /// Aggregate summary of file changes associated with this chat. + /// + /// Servers may populate this so session lists can show per-chat change + /// counts without subscribing to the session or chat channel. Updates travel + /// with the rest of the catalog in `root/sessionSummaryChanged`. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub changes: Option, } /// Aggregate counts describing the file changes associated with a session or diff --git a/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/State.generated.swift b/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/State.generated.swift index 6293a123b..3a23761d9 100644 --- a/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/State.generated.swift +++ b/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/State.generated.swift @@ -2297,19 +2297,27 @@ public struct SessionChatSummary: Codable, Sendable { /// lists without subscribing to the session channel. Absence means the /// chat is not archived. public var archived: Bool? + /// Aggregate summary of file changes associated with this chat. + /// + /// Servers may populate this so session lists can show per-chat change + /// counts without subscribing to the session or chat channel. Updates travel + /// with the rest of the catalog in `root/sessionSummaryChanged`. + public var changes: ChangesSummary? public init( resource: String, title: String, origin: ChatOrigin? = nil, interactivity: ChatInteractivity? = nil, - archived: Bool? = nil + archived: Bool? = nil, + changes: ChangesSummary? = nil ) { self.resource = resource self.title = title self.origin = origin self.interactivity = interactivity self.archived = archived + self.changes = changes } } diff --git a/docs/.changes/20261001-session-chat-summary-changes.json b/docs/.changes/20261001-session-chat-summary-changes.json new file mode 100644 index 000000000..ba2e78d31 --- /dev/null +++ b/docs/.changes/20261001-session-chat-summary-changes.json @@ -0,0 +1,4 @@ +{ + "type": "added", + "message": "`SessionChatSummary.changes` exposes per-chat change counts in the lightweight chat catalog without requiring a session subscription." +} diff --git a/schema/actions.schema.json b/schema/actions.schema.json index 61ca03d6e..d964ec9ec 100644 --- a/schema/actions.schema.json +++ b/schema/actions.schema.json @@ -3698,6 +3698,10 @@ "archived": { "type": "boolean", "description": "Whether this chat has been archived independently of its owning session\n(see `chat/isArchivedChanged`).\n\nGeneric clients use this to group or filter archived chats in session\nlists without subscribing to the session channel. Absence means the\nchat is not archived." + }, + "changes": { + "$ref": "#/$defs/ChangesSummary", + "description": "Aggregate summary of file changes associated with this chat.\n\nServers may populate this so session lists can show per-chat change\ncounts without subscribing to the session or chat channel. Updates travel\nwith the rest of the catalog in `root/sessionSummaryChanged`." } }, "required": [ diff --git a/schema/commands.schema.json b/schema/commands.schema.json index 177cf3998..62a11f8f6 100644 --- a/schema/commands.schema.json +++ b/schema/commands.schema.json @@ -2964,6 +2964,10 @@ "archived": { "type": "boolean", "description": "Whether this chat has been archived independently of its owning session\n(see `chat/isArchivedChanged`).\n\nGeneric clients use this to group or filter archived chats in session\nlists without subscribing to the session channel. Absence means the\nchat is not archived." + }, + "changes": { + "$ref": "#/$defs/ChangesSummary", + "description": "Aggregate summary of file changes associated with this chat.\n\nServers may populate this so session lists can show per-chat change\ncounts without subscribing to the session or chat channel. Updates travel\nwith the rest of the catalog in `root/sessionSummaryChanged`." } }, "required": [ diff --git a/schema/errors.schema.json b/schema/errors.schema.json index 981b450f8..9886f386d 100644 --- a/schema/errors.schema.json +++ b/schema/errors.schema.json @@ -1236,6 +1236,10 @@ "archived": { "type": "boolean", "description": "Whether this chat has been archived independently of its owning session\n(see `chat/isArchivedChanged`).\n\nGeneric clients use this to group or filter archived chats in session\nlists without subscribing to the session channel. Absence means the\nchat is not archived." + }, + "changes": { + "$ref": "#/$defs/ChangesSummary", + "description": "Aggregate summary of file changes associated with this chat.\n\nServers may populate this so session lists can show per-chat change\ncounts without subscribing to the session or chat channel. Updates travel\nwith the rest of the catalog in `root/sessionSummaryChanged`." } }, "required": [ diff --git a/schema/notifications.schema.json b/schema/notifications.schema.json index c7b6a1992..608d4840d 100644 --- a/schema/notifications.schema.json +++ b/schema/notifications.schema.json @@ -1414,6 +1414,10 @@ "archived": { "type": "boolean", "description": "Whether this chat has been archived independently of its owning session\n(see `chat/isArchivedChanged`).\n\nGeneric clients use this to group or filter archived chats in session\nlists without subscribing to the session channel. Absence means the\nchat is not archived." + }, + "changes": { + "$ref": "#/$defs/ChangesSummary", + "description": "Aggregate summary of file changes associated with this chat.\n\nServers may populate this so session lists can show per-chat change\ncounts without subscribing to the session or chat channel. Updates travel\nwith the rest of the catalog in `root/sessionSummaryChanged`." } }, "required": [ diff --git a/schema/state.schema.json b/schema/state.schema.json index 74b608dcf..b3a94a4d9 100644 --- a/schema/state.schema.json +++ b/schema/state.schema.json @@ -1147,6 +1147,10 @@ "archived": { "type": "boolean", "description": "Whether this chat has been archived independently of its owning session\n(see `chat/isArchivedChanged`).\n\nGeneric clients use this to group or filter archived chats in session\nlists without subscribing to the session channel. Absence means the\nchat is not archived." + }, + "changes": { + "$ref": "#/$defs/ChangesSummary", + "description": "Aggregate summary of file changes associated with this chat.\n\nServers may populate this so session lists can show per-chat change\ncounts without subscribing to the session or chat channel. Updates travel\nwith the rest of the catalog in `root/sessionSummaryChanged`." } }, "required": [ diff --git a/types/channels-session/state.ts b/types/channels-session/state.ts index d85c824c6..cb3946dd8 100644 --- a/types/channels-session/state.ts +++ b/types/channels-session/state.ts @@ -552,6 +552,14 @@ export interface SessionChatSummary { * chat is not archived. */ archived?: boolean; + /** + * Aggregate summary of file changes associated with this chat. + * + * Servers may populate this so session lists can show per-chat change + * counts without subscribing to the session or chat channel. Updates travel + * with the rest of the catalog in `root/sessionSummaryChanged`. + */ + changes?: ChangesSummary; } /** diff --git a/types/test-cases/round-trips/051-session-chat-summary-changes-round-trip.json b/types/test-cases/round-trips/051-session-chat-summary-changes-round-trip.json new file mode 100644 index 000000000..c7b811240 --- /dev/null +++ b/types/test-cases/round-trips/051-session-chat-summary-changes-round-trip.json @@ -0,0 +1,66 @@ +{ + "name": "session-chat-summary-changes-round-trip", + "group": "A", + "description": "SessionSummary chat catalog entries preserve optional per-chat change counts so list clients can render them without subscribing to the session or chat channel.", + "type": "SessionSummary", + "input": { + "resource": "ahp-session:/s1", + "provider": "demo", + "title": "Agent team", + "status": 1, + "createdAt": "2024-01-01T00:00:00.001Z", + "modifiedAt": "2024-01-01T00:00:00.002Z", + "changes": { + "additions": 15, + "deletions": 4, + "files": 3 + }, + "chats": [ + { + "resource": "ahp-chat:/lead", + "title": "Lead" + }, + { + "resource": "ahp-chat:/worker", + "title": "Worker", + "changes": { + "additions": 12, + "deletions": 3, + "files": 2 + } + } + ], + "defaultChat": "ahp-chat:/lead" + }, + "acceptableOutputs": [ + { + "resource": "ahp-session:/s1", + "provider": "demo", + "title": "Agent team", + "status": 1, + "createdAt": "2024-01-01T00:00:00.001Z", + "modifiedAt": "2024-01-01T00:00:00.002Z", + "changes": { + "additions": 15, + "deletions": 4, + "files": 3 + }, + "chats": [ + { + "resource": "ahp-chat:/lead", + "title": "Lead" + }, + { + "resource": "ahp-chat:/worker", + "title": "Worker", + "changes": { + "additions": 12, + "deletions": 3, + "files": 2 + } + } + ], + "defaultChat": "ahp-chat:/lead" + } + ] +}