Skip to content

Add cursor-based pagination to listSessions#295

Merged
connor4312 merged 2 commits into
mainfrom
paginate-list-sessions
Jul 1, 2026
Merged

Add cursor-based pagination to listSessions#295
connor4312 merged 2 commits into
mainfrom
paginate-list-sessions

Conversation

@connor4312

Copy link
Copy Markdown
Member

Summary

Adds optional cursor + limit pagination to the root listSessions command so a client with a large session catalogue can load it incrementally instead of receiving every SessionSummary in a single response. Modeled on MCP's opaque-cursor pagination, plus an optional limit the server SHOULD respect (but MAY cap).

Fully additive: a caller that omits the new fields, and a host that does not paginate, behave exactly as today.

Closes #275.

Shape

The pagination inputs/outputs are factored into reusable base interfaces in types/common/commands.ts, so future paginated commands can just extend them and the pagination contract lives in one place:

export interface PaginatedParams {
  limit?: number;   // server SHOULD respect; MAY cap
  cursor?: string;  // opaque; omit for the first page
}

export interface PaginatedResult {
  nextCursor?: string; // absent ⇒ no more pages
}

export interface ListSessionsParams extends BaseParams, PaginatedParams {
  channel: 'ahp-root://';
  filter?: object;
}

export interface ListSessionsResult extends PaginatedResult {
  items: SessionSummary[];
}
  • The cursor is opaque and server-defined — ordering and keyset are the host's choice, mirroring how fetchTurns exposes before/hasMore without dictating storage. Clients MUST NOT parse, modify, or persist it; an unrecognised cursor SHOULD be rejected with InvalidParams.
  • The server SHOULD return most-recently-modified first, so the first page is the immediately useful one.
  • The root/session* notifications keep an already-fetched page live exactly as today; pagination governs only the initial and backfill fetches.

Changes

  • types/ — new PaginatedParams / PaginatedResult; ListSessionsParams / ListSessionsResult extend them; both exported from types/index.ts.
  • Generators — added the two base interfaces to the knownSpecial exhaustiveness lists in the rust/go/kotlin/swift generators (like BaseParams, they're flattened via extends, not emitted standalone).
  • Regenerated — JSON Schema and all five client mirrors (Rust, Kotlin, Swift, TypeScript, Go); the native clients flatten limit/cursor/nextCursor into ListSessions*.
  • Docs — a "Paginating the catalogue" section in docs/specification/root-channel.md.
  • CHANGELOGs — an entry in the spec changelog plus every client changelog (a types/** change ripples to all clients).

Open questions from the issue (deliberately out of scope)

  • Sorting/filtering (raised by @roblourens): kept orthogonal — filter stays an untyped object as today. Pagination is additive so a typed filter/sort can land later without reworking this.
  • approximateTotal: omitted for v1.

Validation

  • npm run test → 275 pass, 100% reducer branch coverage, changelog + release-metadata gates green; npm run lint clean.
  • npm run generate produces no generator warnings.
  • cargo build, go build ./..., and the TypeScript client tsc --noEmit all pass.

Introduce optional cursor + limit pagination for the root `listSessions`
command so clients with a large session catalogue can load it
incrementally instead of receiving every `SessionSummary` in one
response. Modeled on MCP's opaque-cursor pagination, plus an optional
`limit` the server SHOULD respect (but MAY cap).

The pagination inputs/outputs are factored into reusable
`PaginatedParams` (`limit` + `cursor`) and `PaginatedResult`
(`nextCursor`) base interfaces in `types/common/commands.ts`, carrying
the canonical pagination contract in one place for future paginated
commands. `ListSessionsParams` now extends `PaginatedParams` and
`ListSessionsResult` extends `PaginatedResult`.

Fully additive: a client that omits `limit`/`cursor` and ignores
`nextCursor` sees today's behaviour, and a server that does not paginate
returns everything in one page.

Regenerates the schema and all five client mirrors, updates the root
channel spec doc, and adds CHANGELOG entries to the spec plus every
client.

Closes #275

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
roblourens
roblourens previously approved these changes Jul 1, 2026
Comment thread types/channels-root/commands.ts Outdated
export interface ListSessionsParams extends BaseParams, PaginatedParams {
channel: 'ahp-root://';
/** Optional filter criteria */
filter?: object;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is filter interpreted? Should we add a sort criteria?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, idk, I forgot this was a thing. I'll just remove it for now

The `filter` field was an untyped `object` placeholder with no defined
semantics. Drop it rather than ship an unspecified field; it will be
reintroduced with a concrete shape once session filtering/sorting is
specified. Updates the two host-runtime call sites (Rust, TypeScript)
that named the field, regenerates all clients + schema, and records the
removal in every CHANGELOG.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@connor4312 connor4312 merged commit 868f4bd into main Jul 1, 2026
9 checks passed
@connor4312 connor4312 deleted the paginate-list-sessions branch July 1, 2026 23:58
@connor4312 connor4312 added this to the 1.128.0 milestone Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Proposal: paginate listSessions for large session catalogs

3 participants