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
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ changes accumulate. Track in-flight protocol changes via PRs touching
- Optional `capabilities` field on `AgentInfo` (`AgentCapabilities` with a
nested `multipleChats` capability carrying `fork`) so clients gate multi-chat
and fork via advertised capabilities instead of provider-id switches.
- Cursor-based pagination for `listSessions`, via new shared `PaginatedParams`
(`limit` + `cursor`) and `PaginatedResult` (`nextCursor`) types:
`ListSessionsParams` now extends `PaginatedParams` and `ListSessionsResult`
extends `PaginatedResult`, letting clients fetch a large session catalogue
incrementally. Fully additive — omitting the fields preserves today's
behaviour.

### Removed

- `filter` field from `ListSessionsParams`. It was an untyped `object`
placeholder with no defined semantics; it will be reintroduced with a concrete
shape once session filtering/sorting is specified.

## [0.5.1] — Unreleased

Expand Down
11 changes: 11 additions & 0 deletions clients/go/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ tag whose matching `## [X.Y.Z]` heading is missing from this file.
- Optional `capabilities` field on `AgentInfo` (`AgentCapabilities` with a
nested `multipleChats` capability carrying `fork`) so clients gate multi-chat
and fork via advertised capabilities instead of provider-id switches.
- Cursor-based pagination for `listSessions`, via new shared `PaginatedParams`
(`Limit` + `Cursor`) and `PaginatedResult` (`NextCursor`) types:
`ListSessionsParams` and `ListSessionsResult` now carry these fields, letting
clients page through a large session catalogue. Fully additive — omitting the
fields preserves prior behaviour.
- `SessionState.InputNeeded` — a session-level aggregate of outstanding input
requests across all chats (`SessionInputRequest` union with
`SessionChatInputRequest`, `SessionToolConfirmationRequest`, and
Expand All @@ -36,6 +41,12 @@ tag whose matching `## [X.Y.Z]` heading is missing from this file.
- Optional `Model` and `Tools` fields on `AgentCustomization` for a custom
agent's pinned model and tool allowlist.

### Removed

- `Filter` field from `ListSessionsParams`. It was an untyped placeholder with
no defined semantics; it will return with a concrete shape once session
filtering/sorting is specified.

### Fixed

- `SnapshotState.UnmarshalJSON` now decodes the `Chat` variant. Variant
Expand Down
25 changes: 22 additions & 3 deletions clients/go/ahptypes/commands.generated.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,16 +313,35 @@ type DisposeChatParams struct {
// The session list is **not** part of the state tree because it can be arbitrarily
// large. Clients fetch it imperatively and maintain a local cache updated by
// `root/sessionAdded` and `root/sessionRemoved` notifications.
//
// A large catalogue can be fetched incrementally via the {@link PaginatedParams}
// `limit`/`cursor` inputs (see that type for the full pagination contract). The
// server SHOULD return most-recently-modified entries first, so the first page
// is the immediately useful one. The `root/session*` notifications keep an
// already-fetched page live; pagination governs only the initial and backfill
// fetches.
type ListSessionsParams struct {
// Channel URI this command targets.
Channel URI `json:"channel"`
// Optional filter criteria
Filter *json.RawMessage `json:"filter,omitempty"`
// Maximum number of entries to return in this page. The server SHOULD respect
// this bound but MAY return fewer entries and MAY impose its own upper cap.
// Omit to let the server choose the page size.
Limit *int64 `json:"limit,omitempty"`
// Opaque pagination cursor from a previous {@link PaginatedResult.nextCursor}.
// Omit to fetch the first page. Cursors are server-defined and MUST be treated
// as opaque — do not parse, modify, or persist them across connections. An
// unrecognised cursor SHOULD be rejected with an `InvalidParams` error.
Cursor *string `json:"cursor,omitempty"`
}

// Result of the `listSessions` command.
type ListSessionsResult struct {
// The list of session summaries.
// Opaque cursor for the next page. Present when more entries exist beyond the
// returned page; absent signals the end of the collection. Pass it back as
// {@link PaginatedParams.cursor} to fetch the following page.
NextCursor *string `json:"nextCursor,omitempty"`
// The list of session summaries. The server SHOULD order them
// most-recently-modified first.
Items []SessionSummary `json:"items"`
}

Expand Down
11 changes: 11 additions & 0 deletions clients/kotlin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ versions (`*-SNAPSHOT`) are explicitly rejected by the publish pipeline; bump
- Optional `capabilities` field on `AgentInfo` (`AgentCapabilities` with a
nested `multipleChats` capability carrying `fork`) so clients gate multi-chat
and fork via advertised capabilities instead of provider-id switches.
- Cursor-based pagination for `listSessions`, via new shared `PaginatedParams`
(`limit` + `cursor`) and `PaginatedResult` (`nextCursor`) types:
`ListSessionsParams` and `ListSessionsResult` now carry these fields, letting
clients page through a large session catalogue. Fully additive — omitting the
fields preserves prior behaviour.
- `SessionState.inputNeeded` — a session-level aggregate of outstanding input
requests across all chats (`SessionInputRequest` sealed interface with
`SessionChatInputRequest`, `SessionToolConfirmationRequest`, and
Expand All @@ -35,6 +40,12 @@ versions (`*-SNAPSHOT`) are explicitly rejected by the publish pipeline; bump
- Optional `model` and `tools` fields on `AgentCustomization` for a custom
agent's pinned model and tool allowlist.

### Removed

- `filter` field from `ListSessionsParams`. It was an untyped placeholder with
no defined semantics; it will return with a concrete shape once session
filtering/sorting is specified.

### Fixed

- `SnapshotState` now decodes the `Chat` variant. Its serializer previously never
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,15 +399,31 @@ data class ListSessionsParams(
*/
val channel: String,
/**
* Optional filter criteria
* Maximum number of entries to return in this page. The server SHOULD respect
* this bound but MAY return fewer entries and MAY impose its own upper cap.
* Omit to let the server choose the page size.
*/
val filter: JsonElement? = null
val limit: Long? = null,
/**
* Opaque pagination cursor from a previous {@link PaginatedResult.nextCursor}.
* Omit to fetch the first page. Cursors are server-defined and MUST be treated
* as opaque — do not parse, modify, or persist them across connections. An
* unrecognised cursor SHOULD be rejected with an `InvalidParams` error.
*/
val cursor: String? = null
)

@Serializable
data class ListSessionsResult(
/**
* The list of session summaries.
* Opaque cursor for the next page. Present when more entries exist beyond the
* returned page; absent signals the end of the collection. Pass it back as
* {@link PaginatedParams.cursor} to fetch the following page.
*/
val nextCursor: String? = null,
/**
* The list of session summaries. The server SHOULD order them
* most-recently-modified first.
*/
val items: List<SessionSummary>
)
Expand Down
11 changes: 11 additions & 0 deletions clients/rust/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ matching `## [X.Y.Z]` heading is missing from this file.
- Optional `capabilities` field on `AgentInfo` (`AgentCapabilities` with a
nested `multipleChats` capability carrying `fork`) so clients gate multi-chat
and fork via advertised capabilities instead of provider-id switches.
- Cursor-based pagination for `listSessions`, via new shared `PaginatedParams`
(`limit` + `cursor`) and `PaginatedResult` (`next_cursor`) types:
`ListSessionsParams` and `ListSessionsResult` now carry these fields, letting
clients page through a large session catalogue. Fully additive — omitting the
fields preserves prior behaviour.
- `SessionState.input_needed` — a session-level aggregate of outstanding input
requests across all chats (`SessionInputRequest` enum with
`SessionChatInputRequest`, `SessionToolConfirmationRequest`, and
Expand All @@ -42,6 +47,12 @@ matching `## [X.Y.Z]` heading is missing from this file.
`delivery: None`; use `SubscribeParams::new(channel)` or
`Client::subscribe` to keep the default delivery behavior.

### Removed

- `filter` field from `ListSessionsParams`. It was an untyped placeholder with
no defined semantics; it will return with a concrete shape once session
filtering/sorting is specified.

## [0.5.0] — 2026-06-26

Implements AHP 0.5.0.
Expand Down
27 changes: 24 additions & 3 deletions clients/rust/crates/ahp-types/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,21 +392,42 @@ pub struct DisposeChatParams {
/// The session list is **not** part of the state tree because it can be arbitrarily
/// large. Clients fetch it imperatively and maintain a local cache updated by
/// `root/sessionAdded` and `root/sessionRemoved` notifications.
///
/// A large catalogue can be fetched incrementally via the {@link PaginatedParams}
/// `limit`/`cursor` inputs (see that type for the full pagination contract). The
/// server SHOULD return most-recently-modified entries first, so the first page
/// is the immediately useful one. The `root/session*` notifications keep an
/// already-fetched page live; pagination governs only the initial and backfill
/// fetches.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ListSessionsParams {
/// Channel URI this command targets.
pub channel: Uri,
/// Optional filter criteria
/// Maximum number of entries to return in this page. The server SHOULD respect
/// this bound but MAY return fewer entries and MAY impose its own upper cap.
/// Omit to let the server choose the page size.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub limit: Option<i64>,
/// Opaque pagination cursor from a previous {@link PaginatedResult.nextCursor}.
/// Omit to fetch the first page. Cursors are server-defined and MUST be treated
/// as opaque — do not parse, modify, or persist them across connections. An
/// unrecognised cursor SHOULD be rejected with an `InvalidParams` error.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub filter: Option<AnyValue>,
pub cursor: Option<String>,
}

/// Result of the `listSessions` command.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ListSessionsResult {
/// The list of session summaries.
/// Opaque cursor for the next page. Present when more entries exist beyond the
/// returned page; absent signals the end of the collection. Pass it back as
/// {@link PaginatedParams.cursor} to fetch the following page.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_cursor: Option<String>,
/// The list of session summaries. The server SHOULD order them
/// most-recently-modified first.
pub items: Vec<SessionSummary>,
}

Expand Down
3 changes: 2 additions & 1 deletion clients/rust/crates/ahp/src/hosts/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,8 @@ impl HostRuntime {
"listSessions",
ListSessionsParams {
channel: ROOT_RESOURCE_URI.to_string(),
filter: None,
limit: None,
cursor: None,
},
)
.await;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,25 +395,41 @@ public struct DisposeChatParams: Codable, Sendable {
public struct ListSessionsParams: Codable, Sendable {
/// Channel URI this command targets.
public var channel: String
/// Optional filter criteria
public var filter: AnyCodable?
/// Maximum number of entries to return in this page. The server SHOULD respect
/// this bound but MAY return fewer entries and MAY impose its own upper cap.
/// Omit to let the server choose the page size.
public var limit: Int?
/// Opaque pagination cursor from a previous {@link PaginatedResult.nextCursor}.
/// Omit to fetch the first page. Cursors are server-defined and MUST be treated
/// as opaque — do not parse, modify, or persist them across connections. An
/// unrecognised cursor SHOULD be rejected with an `InvalidParams` error.
public var cursor: String?

public init(
channel: String,
filter: AnyCodable? = nil
limit: Int? = nil,
cursor: String? = nil
) {
self.channel = channel
self.filter = filter
self.limit = limit
self.cursor = cursor
}
}

public struct ListSessionsResult: Codable, Sendable {
/// The list of session summaries.
/// Opaque cursor for the next page. Present when more entries exist beyond the
/// returned page; absent signals the end of the collection. Pass it back as
/// {@link PaginatedParams.cursor} to fetch the following page.
public var nextCursor: String?
/// The list of session summaries. The server SHOULD order them
/// most-recently-modified first.
public var items: [SessionSummary]

public init(
nextCursor: String? = nil,
items: [SessionSummary]
) {
self.nextCursor = nextCursor
self.items = items
}
}
Expand Down
11 changes: 11 additions & 0 deletions clients/swift/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ the tag matches the version pinned in [`VERSION`](VERSION).
- Optional `capabilities` field on `AgentInfo` (`AgentCapabilities` with a
nested `multipleChats` capability carrying `fork`) so clients gate multi-chat
and fork via advertised capabilities instead of provider-id switches.
- Cursor-based pagination for `listSessions`, via new shared `PaginatedParams`
(`limit` + `cursor`) and `PaginatedResult` (`nextCursor`) types:
`ListSessionsParams` and `ListSessionsResult` now carry these fields, letting
clients page through a large session catalogue. Fully additive — omitting the
fields preserves prior behaviour.
- `SessionState.inputNeeded` — a session-level aggregate of outstanding input
requests across all chats (`SessionInputRequest` enum with
`SessionChatInputRequest`, `SessionToolConfirmationRequest`, and
Expand All @@ -38,6 +43,12 @@ the tag matches the version pinned in [`VERSION`](VERSION).
- Optional `model` and `tools` fields on `AgentCustomization` for a custom
agent's pinned model and tool allowlist.

### Removed

- `filter` field from `ListSessionsParams`. It was an untyped placeholder with
no defined semantics; it will return with a concrete shape once session
filtering/sorting is specified.

### Fixed

- `SnapshotState` now decodes the `chat` variant. Its decoder previously never
Expand Down
11 changes: 11 additions & 0 deletions clients/typescript/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ hotfix escape hatch.
- Optional `capabilities` field on `AgentInfo` (`AgentCapabilities` with a
nested `multipleChats` capability carrying `fork`) so clients gate multi-chat
and fork via advertised capabilities instead of provider-id switches.
- Cursor-based pagination for `listSessions`, via new shared `PaginatedParams`
(`limit` + `cursor`) and `PaginatedResult` (`nextCursor`) types:
`ListSessionsParams` and `ListSessionsResult` now carry these fields, letting
clients page through a large session catalogue. Fully additive — omitting the
fields preserves prior behaviour.
- `SessionState.inputNeeded` — a session-level aggregate of outstanding input
requests across all chats (`SessionInputRequest` union with
`SessionChatInputRequest`, `SessionToolConfirmationRequest`, and
Expand All @@ -42,6 +47,12 @@ hotfix escape hatch.
- Optional `model` and `tools` fields on `AgentCustomization` for a custom
agent's pinned model and tool allowlist.

### Removed

- `filter` field from `ListSessionsParams`. It was an untyped placeholder with
no defined semantics; it will return with a concrete shape once session
filtering/sorting is specified.

## [0.5.0] — 2026-06-26

Implements AHP 0.5.0.
Expand Down
1 change: 0 additions & 1 deletion clients/typescript/src/client/hosts/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,6 @@ export class HostRuntime {
const res = await raceWithAbort(
client.request('listSessions', {
channel: ROOT_RESOURCE_URI as 'ahp-root://',
filter: undefined,
}),
cancelSignal,
);
Expand Down
12 changes: 12 additions & 0 deletions docs/specification/root-channel.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@ RootState {

The session list is **not** part of root state. Clients fetch it imperatively via [`listSessions`](/reference/root#listsessions) and patch it from `root/*` notifications described below.

### Paginating the catalogue

A large catalogue can be fetched incrementally. [`listSessions`](/reference/root#listsessions) accepts an optional `limit` (the maximum number of entries the client wants in the page — the server SHOULD respect it, but MAY return fewer and MAY impose its own upper cap) and an optional opaque `cursor`. The result carries the page in `items` plus an optional `nextCursor`:

- To fetch the first page, omit `cursor`. Supply `limit` to bound the page size.
- If the result includes a `nextCursor`, more entries exist — pass it back as `cursor` on the next call to fetch the following page.
- A missing `nextCursor` signals the end of the catalogue.

The cursor is **opaque and server-defined**: the server picks the ordering and keyset, exactly as `fetchTurns` exposes `before`/`hasMore` without dictating storage. Clients MUST NOT parse, modify, or persist a cursor across connections. An unrecognised cursor SHOULD be rejected with an `InvalidParams` error. The server SHOULD return most-recently-modified entries first, so the first page is the immediately useful one.

Pagination is fully additive. A client that omits `limit`/`cursor` and ignores `nextCursor` sees the pre-pagination behaviour (subject to any server-imposed cap), and a server that does not paginate ignores the inputs and returns everything in one page. Pagination governs only the initial and backfill fetches — the `root/session*` notifications keep an already-loaded page live exactly as before.

## Methods and events on this channel

This section lists wire methods that are interpreted in the context of
Expand Down
Loading
Loading