Skip to content

Support for adding, editing, and deleting comments#195

Merged
benibenj merged 13 commits into
mainfrom
benibenj/prepared-rhinoceros
Jun 8, 2026
Merged

Support for adding, editing, and deleting comments#195
benibenj merged 13 commits into
mainfrom
benibenj/prepared-rhinoceros

Conversation

@benibenj

@benibenj benibenj commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

@benibenj benibenj enabled auto-merge June 4, 2026 19:56
@benibenj benibenj requested a review from connor4312 June 4, 2026 19:56
@roblourens

Copy link
Copy Markdown
Member

This is a lot to add to add to the protocol. Why do it this way vs as attachments?

@benibenj

benibenj commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

@roblourens Good question. I looked at modelling this as attachments, and I don't think they fit. (AI helped me generate this message as I didn't find it easy to explain)

The feature needs a shared, mutable review surface:

  1. A user can add comments on files and submit them.
  2. The agent can add comments; the user can review, delete some, and submit the rest.
  3. Comments are pinned to a turn, so once a new turn lands the old anchors are stale.
  4. Comments need to live in AHP state so another client connected to the same session sees the same draft/review buffer. That also leaves room for multiple chats/agents in one session sharing the same comments surface.

I don't think we need to model "accepted by the user" in the protocol, that can stay client-side. The protocol piece is the shared mutable comment state.

Attachments are message-scoped input payloads. They live on Message.attachments, are associated with one message/turn, and don't have stable per-entry ids, attachment-specific edit/delete operations, threading, or an attachment-scoped subscription. They can carry a resource/selection, and completions can suggest attachments, but once accepted they are still folded into the composed message rather than becoming independent server-owned state.

To make attachments satisfy the requirements above, we'd effectively have to add stable ids, server-owned/mutable attachment state, add/edit/delete/re-anchor commands, threading, and an attachment-specific subscription. At that point we've turned attachments into a second channel while also overloading Message with two jobs: submitted prompt payload and shared multi-client file-review buffer.

Requirements 2 and 4: agent-authored entries and cross-client sync need a server-owned, subscribable state surface. Attachments are the right shape for the submitted payload, not for the editing/sharing surface.

So the two models can still compose: at submission time, the client can turn the accepted comments into attachments on the outgoing message. The comments channel is the editing and sharing surface, attachments remain the submitted payload surface.

The proposed channel follows the same state-bearing pattern as changeset/*: a separate URI, snapshot on subscribe, server-echoed actions, and lightweight session summary state. That keeps the new behavior parallel to existing protocol structure instead of making Message.attachments do unrelated work.

@benibenj benibenj marked this pull request as draft June 5, 2026 10:00
auto-merge was automatically disabled June 5, 2026 10:00

Pull request was converted to draft

@benibenj benibenj left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I don't think attachements make sense for this use case. But I do agree that the AHP shouldn't be talking about "comments" but rather some more generalised primitive. Maybe something like a "anchored coordination item" which has some message and an anchor like for exampe:

  • session
  • session turn
  • file
  • file range
  • tool call

These items could be created, read, (edited ?) and removed by both client and agents

currently discussing with connor

@roblourens

Copy link
Copy Markdown
Member

Oh ok, the feature is more sophisticated than I thought. What's the scenario for the agent adding comments?

@benibenj

benibenj commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

The most basic scenario would likely be a code review agent.

Comment thread types/channels-comments/state.ts Outdated
* interpreted by the protocol.
*/
_meta?: Record<string, unknown>;
}

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.

I'd suggest we can also use this surface area to surface GH review comments as well, in the future. Or at least GH-review like experiences. To that end I suggest we have:

  • A notion of author?: CommentAgentAuthor | CommentUserAuthor on the Comment. Doesn't need to be in this PR, an optional thing here could be added as non-breaking in the future.
  • A notion of resolved threads / thread state
  • Thread/comment severity?:
  • Would be only allow comments on ranges or also files? Maybe the text range is optional.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The plan is to surface GH review comments at some point, but I think it make sense to add properties like author and resolved state when we tackle that in the future. I have no strong opinions regarding making range optional. I guess it might allow more use cases in the future so I'll do that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Actually, resolved state will also make sense in the non PR review scenario, so the model knows which comments it has acted on already

Comment thread types/channels-session/state.ts Outdated
* thread / comment counts without subscribing. Absent when the session
* does not expose a comments channel.
*/
comments?: CommentsSummary;

@connor4312 connor4312 Jun 5, 2026

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.

As a user how do I say "I made all these comments, now action on them."?

Imo a natural thing to do would be a new comment attachment type, which could reference either all comments by URI or a comments URI + an array of thread IDs to send to the model and have them address. Especially thinking in an orchestrating/multi-chat world, I may not necessarily want comments implicitly attached to whatever message I send next.

We can then say that an agent host SHOULD provide tools to the harness for the harness to respond to or resolve comments associated with a chat message.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm also planning on adding tools to the server which allows the agent to act on the comments (listing, resolving, responding...). But, your right that having an attachment type to be able to reference them would also be very useful to add.

Comment thread types/channels-comments/actions.ts Outdated
@roblourens

Copy link
Copy Markdown
Member

Is this the point where we should maybe add a server capability to make this an optional part of the spec? Maybe per-agent? It just seems like a lot to require every host to implement this for every agent.

I don't think there would be a "client capability" for this because it can ignore messages and the server is going to independently either have this data or not.

@connor4312

connor4312 commented Jun 5, 2026

Copy link
Copy Markdown
Member

@roblourens I think an AH that doesn't support this would not advertise SessionSummary.comments. I'm not sure if there's a case where a client would need additional signal beyond that.

@benibenj benibenj left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I moved to calling it Annotations

  • Added resolved state
  • Made range optional
  • Annotations can be referenced as attachments
  • I'm trying to keep this as simple as possible for the start, so I did not add author, severity or kind.

Comment thread types/channels-annotations/commands.ts Outdated
@benibenj benibenj marked this pull request as ready for review June 8, 2026 21:02
@benibenj benibenj enabled auto-merge June 8, 2026 21:02
@benibenj

benibenj commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

I removed the commands and added the actions, making them client dispatchable.

export interface AnnotationsSetAction {
type: ActionType.AnnotationsSet;
/** The new or replacement annotation. MUST contain at least one entry. */
annotation: Annotation;

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.

For a consumer to resolve an annotation, it has to replace the entire annotation and all its comments. I suggest having an action that would do a partial update of its properties like you had in the command before

@benibenj benibenj merged commit d49307c into main Jun 8, 2026
8 checks passed
@benibenj benibenj deleted the benibenj/prepared-rhinoceros branch June 8, 2026 21:38
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.

4 participants