Skip to content

Persist per-chat read watermarks through turn IDs #401

Description

Problem

AHP currently represents read state using the session-level SessionStatus.IsRead flag and session/isReadChanged action. This says whether a session is currently considered read, but it does not record how far a reader has read.

Consumers therefore cannot reliably answer:

Has reader X read turn Y or any later turn in this chat?

This is needed for durable workflows that should remain visible until the user has seen a particular agent response. The existing boolean cannot identify a chat or turn, and a timestamp is ambiguous for sessions with multiple independently progressing chats.

Proposal

Add a client-dispatchable session action:

interface SessionReadWatermarkChangedAction {
	type: 'session/readWatermarkChanged';

	/**
	 * Stable opaque identifier chosen by the client.
	 * VS Code initially uses the constant `vscode`.
	 */
	readerId: string;

	/** Chat whose content was read. */
	chat: URI;

	/** Last turn visible to this reader. */
	throughTurnId: string;
}

Persist the watermark in session state:

interface SessionState {
	// ...
	readWatermarks?: Record<
		string, // readerId
		Record<URI, string> // chat -> last read turn ID
	>;
}

readerId extensibility

readerId is deliberately client-determined rather than tied to the current per-connection AHP clientId.

Initially VS Code can always use the constant vscode, giving all VS Code windows one shared read position. The same protocol shape remains useful if clients later need more granular progress:

  • a different ID per client implementation, such as vscode, web, or cli;
  • a stable ID per device or installation;
  • a stable ID per user in a future multi-user host.

Defining authentication, identity, and visibility policy for those future IDs is outside the initial implementation. The protocol only treats readerId as an opaque namespace selected by the client.

Behavior

  • The host validates that chat belongs to the session and that throughTurnId exists in that chat.
  • A watermark advances monotonically according to the chat's turn order; stale updates are no-ops.
  • The host persists watermarks with the session.
  • Updated watermarks are broadcast through the existing action/state mechanism.
  • Multiple clients using the same readerId contribute to the same watermark.
  • New turns do not delete the watermark; they simply make that reader's stored position older than the latest turn.
  • Existing session/isReadChanged and SessionStatus.IsRead behavior remains available for compatibility. VS Code may derive its compatibility flag from whether the vscode watermark covers each relevant chat's latest turn.

Example

{
  "type": "session/readWatermarkChanged",
  "readerId": "vscode",
  "chat": "ahp-chat:/session-123/main",
  "throughTurnId": "turn-42"
}

A consumer can determine whether turn-40 has been read by locating both turns in the chat's ordered turn list and comparing their positions.

Acceptance criteria

  • Read watermarks survive host restart.
  • Watermarks are included in session snapshots.
  • Subscribers receive watermark updates.
  • A watermark cannot move backwards.
  • Invalid session/chat/turn references are rejected or ignored consistently with existing action validation.
  • Two clients using readerId: "vscode" share progress.
  • Different reader IDs retain independent progress.
  • Existing clients using session/isReadChanged continue to work.

Non-goals for the initial implementation

  • Defining user authentication or identity.
  • Choosing IDs for devices or users.
  • Read-receipt UI for collaborators.
  • Cross-reader permission policy.
  • Removing the existing IsRead compatibility flag.

Metadata

Metadata

Labels

feature-requestRequest for new features or functionality

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions