src/vs/platform/agentHost/common/meta/agentFeedbackAnnotations.ts

135 LOC · 129 covered · 6 uncovered · 11 ranges · 2763 concepts · 3 introducers · 1280 tests

File neighbourhood

The centred file is linked to every concept that introduces one of its ranges, every test that runs code from the file, and the gray connector concepts standing between those tests and the file's own introducer concepts. Undirected links join concepts to every file where they introduce source and concepts to the tests they introduce; arrows show specialization between the displayed concepts and bridge only concepts omitted from this view. Concept colors match the source ranges below; connector concepts have no source color and are shown in gray.

Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the file

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the related-file, concept, and source links on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the related-file, concept, and source links on this page while the interactive map is unavailable.

1 > /*--------------------------------------------------------------------------------------------- agentFeedbackServerTools.ts ×23
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import type { Mutable } from '../../../../base/common/types.js';
7 > import type { Annotation } from '../state/protocol/state.js';
8 >
9 > /**
10 > * Shared convention for carrying agent-feedback semantics inside an
11 > * {@link Annotation._meta} on the agent host annotations channel.
12 > *
13 > * Feedback items round-trip as annotations on `<session>/annotations`; the
14 > * annotation's own fields cover id / resource / range / resolved, and
15 > * everything else (lifecycle state, origin kind, code context, PR linkage)
16 > * lives under {@link FEEDBACK_ANNOTATION_META_KEY}. This module is the single
17 > * place both the server (agent host, which writes feedback annotations from
18 > * its server tools) and the client (agents window, which reads them back)
19 > * agree on the key and shape, so the two sides cannot drift.
20 > */
21 >
22 > /** Namespaced key under {@link Annotation._meta} carrying feedback semantics. */
23 > export const FEEDBACK_ANNOTATION_META_KEY = 'vscode.agentFeedback';
24 >
25 > /**
26 > * Name of the agent host server tool that reveals review comments the user has
27 > * not accepted yet. Shared here (in the layer-neutral `common` module) so the
28 > * node-side server tool implementation and the browser-side chat adapter that
29 > * renders its confirmation agree on the name without drifting. The agent sees
30 > * this name directly (Copilot) or prefixed as `mcp__host__<name>` (Claude).
31 > */
32 > export const VIEW_UNREVIEWED_COMMENTS_TOOL_NAME = 'viewUnreviewedComments';
33 >
34 > /**
35 > * Name of the agent host server tool that adds a comment (agent feedback) to a
36 > * file range. Shared here (in the layer-neutral `common` module) so the
37 > * node-side server tool implementation and the browser-side chat adapter that
38 > * renders its tool call agree on the name without drifting. The agent sees this
39 > * name directly (Copilot) or prefixed as `mcp__host__<name>` (Claude).
40 > */
41 > export const ADD_COMMENT_TOOL_NAME = 'addComment';
42 >
43 > /**
44 > * Whether {@link toolName} (a tool name as seen on a tool call) refers to the
45 > * {@link VIEW_UNREVIEWED_COMMENTS_TOOL_NAME} server tool. Accepts both the bare
46 > * name and the Claude `mcp__<server>__<name>` prefixed form.
47 > */
48 > export function isViewUnreviewedCommentsTool(toolName: string): boolean {
49 return toolName === VIEW_UNREVIEWED_COMMENTS_TOOL_NAME || toolName.endsWith(`__${VIEW_UNREVIEWED_COMMENTS_TOOL_NAME}`);
50 }
52 > /**
53 > * Whether {@link toolName} (a tool name as seen on a tool call) refers to the
54 > * {@link ADD_COMMENT_TOOL_NAME} server tool. Accepts both the bare name and the
55 > * Claude `mcp__<server>__<name>` prefixed form.
56 > */
57 > export function isAddCommentTool(toolName: string): boolean {
58 return toolName === ADD_COMMENT_TOOL_NAME || toolName.endsWith(`__${ADD_COMMENT_TOOL_NAME}`);
59 }
61 > /**
62 > * Origin of a feedback item. String values match the client-side
63 > * `AgentFeedbackKind` enum so a value written by either side decodes on the
64 > * other without translation.
65 > */
66 > export type AgentFeedbackKindValue = 'user' | 'codeReview' | 'prReview';
67 >
68 > /**
69 > * Lifecycle state of a feedback item. String values match the client-side
70 > * `AgentFeedbackState` enum.
71 > */
72 > export type AgentFeedbackStateValue = 'created' | 'accepted' | 'submitted' | 'resolved';
73 >
74 > /**
75 > * Feedback semantics carried in an annotation's {@link Annotation._meta}.
76 > *
77 > * The optional client-only fields ({@link suggestion}, {@link codeSelection},
78 > * {@link diffHunks}, {@link sourcePRReviewCommentId}) are populated when a
79 > * feedback item is converted from a code- or PR-review comment on the client;
80 > * server tools only ever write {@link kind} / {@link state} /
81 > * {@link sessionResource}. {@link suggestion} is typed loosely here because
82 > * its concrete shape lives in the client (sessions) layer.
83 > */
84 > export interface IFeedbackAnnotationMeta {
85 > readonly kind: AgentFeedbackKindValue;
86 > readonly state: AgentFeedbackStateValue;
87 > readonly sessionResource: string;
88 > readonly suggestion?: unknown;
89 > readonly codeSelection?: string;
90 > readonly diffHunks?: string;
91 > readonly sourcePRReviewCommentId?: string;
92 > /**
93 > * Transient marker set by the client when the user reveals this comment to
94 > * the agent via the `viewUnreviewedComments` tool. The server tool returns
95 > * exactly the comments carrying this flag (so the result is scoped to the
96 > * comments selected for that invocation rather than every accepted review
97 > * comment) and clears it once they have been delivered, so a later
98 > * invocation does not re-return them.
99 > */
100 > readonly pendingAgentReveal?: boolean;
101 > }
102 >
103 > function isAgentFeedbackKindValue(value: unknown): value is AgentFeedbackKindValue { agentFeedbackAnnotations.ts ×5
104 > return value === 'user' || value === 'codeReview' || value === 'prReview';
105 > }
107 > function isAgentFeedbackStateValue(value: unknown): value is AgentFeedbackStateValue { agentFeedbackAnnotations.ts ×5
108 > return value === 'created' || value === 'accepted' || value === 'submitted' || value === 'resolved';
109 > }
111 > /**
112 > * Reads the well-known {@link IFeedbackAnnotationMeta} from an annotation's
113 > * `_meta` bag (under {@link FEEDBACK_ANNOTATION_META_KEY}). The annotations
114 > * channel is shared, so this validates the required `kind` / `state` /
115 > * `sessionResource` fields and returns `undefined` for annotations that aren't
116 > * feedback items. Read through this rather than casting the namespaced slot.
117 > */
118 > export function readFeedbackAnnotationMeta(annotation: Annotation): IFeedbackAnnotationMeta | undefined {
119 > const meta = annotation._meta; agentFeedbackAnnotations.ts ×5
120 > const slot = meta?.[FEEDBACK_ANNOTATION_META_KEY];
121 > if (!slot || typeof slot !== 'object' || Array.isArray(slot)) {
122 > return undefined; agentFeedbackServerTools.ts ×3
123 > }
124 > const raw = slot as Record<string, unknown>; agentFeedbackAnnotations.ts ×5
125 > if (!isAgentFeedbackKindValue(raw['kind']) || !isAgentFeedbackStateValue(raw['state']) || typeof raw['sessionResource'] !== 'string') {
126 return undefined;
127 }
128 > const result: Mutable<IFeedbackAnnotationMeta> = { kind: raw['kind'], state: raw['state'], sessionResource: raw['sessionResource'] }; agentFeedbackAnnotations.ts ×5
129 > if (raw['suggestion'] !== undefined) { result.suggestion = raw['suggestion']; }
130 > if (typeof raw['codeSelection'] === 'string') { result.codeSelection = raw['codeSelection']; }
131 > if (typeof raw['diffHunks'] === 'string') { result.diffHunks = raw['diffHunks']; }
132 > if (typeof raw['sourcePRReviewCommentId'] === 'string') { result.sourcePRReviewCommentId = raw['sourcePRReviewCommentId']; }
133 > if (typeof raw['pendingAgentReveal'] === 'boolean') { result.pendingAgentReveal = raw['pendingAgentReveal']; }
134 > return result;
135 > }