Skip to content

Commit 36a1a32

Browse files
committed
feat - LSP data layer + confirmationService skeleton (Auto-approve Part 1 ) (#132)
1 parent 790bff8 commit 36a1a32

8 files changed

Lines changed: 408 additions & 5 deletions

File tree

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
4+
package com.microsoft.copilot.eclipse.core.chat;
5+
6+
import com.microsoft.copilot.eclipse.core.lsp.protocol.InvokeClientToolConfirmationParams;
7+
8+
/**
9+
* Evaluates whether a tool confirmation request can be auto-approved.
10+
* Each implementation handles a specific category of tool (terminal, file operations, MCP, etc.).
11+
*/
12+
public interface ConfirmationHandler {
13+
14+
/**
15+
* Evaluates whether the given confirmation request should be auto-approved.
16+
*
17+
* @param params the confirmation request parameters from CLS
18+
* @return ConfirmationResult.AUTO_APPROVED if the tool call can proceed without user
19+
* confirmation, or ConfirmationResult.NEEDS_CONFIRMATION if the user must approve
20+
*/
21+
ConfirmationResult evaluate(InvokeClientToolConfirmationParams params);
22+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
4+
package com.microsoft.copilot.eclipse.core.chat;
5+
6+
/**
7+
* Result of evaluating an auto-approve confirmation request.
8+
*/
9+
public enum ConfirmationResult {
10+
/**
11+
* The tool invocation is automatically approved and no user confirmation is needed.
12+
*/
13+
AUTO_APPROVED,
14+
15+
/**
16+
* The tool invocation requires user confirmation before proceeding.
17+
*/
18+
NEEDS_CONFIRMATION
19+
}

com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/lsp/protocol/CopilotAgentSettings.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ public class CopilotAgentSettings {
1919

2020
private String transcriptDirectory;
2121

22+
// Control if the editor handles all confirmation requests from CLS.
23+
@SerializedName("editorHandlesAllConfirmation")
24+
private boolean editorHandlesAllConfirmation;
25+
2226
public int getAgentMaxRequests() {
2327
return agentMaxRequests;
2428
}
@@ -50,9 +54,18 @@ public void setTranscriptDirectory(String transcriptDirectory) {
5054
this.transcriptDirectory = transcriptDirectory;
5155
}
5256

57+
public boolean isEditorHandlesAllConfirmation() {
58+
return editorHandlesAllConfirmation;
59+
}
60+
61+
public void setEditorHandlesAllConfirmation(boolean editorHandlesAllConfirmation) {
62+
this.editorHandlesAllConfirmation = editorHandlesAllConfirmation;
63+
}
64+
5365
@Override
5466
public int hashCode() {
55-
return Objects.hash(agentMaxRequests, enableSkills, transcriptDirectory);
67+
return Objects.hash(agentMaxRequests, enableSkills, transcriptDirectory,
68+
editorHandlesAllConfirmation);
5669
}
5770

5871
@Override
@@ -68,7 +81,8 @@ public boolean equals(Object obj) {
6881
}
6982
CopilotAgentSettings other = (CopilotAgentSettings) obj;
7083
return agentMaxRequests == other.agentMaxRequests && enableSkills == other.enableSkills
71-
&& Objects.equals(transcriptDirectory, other.transcriptDirectory);
84+
&& Objects.equals(transcriptDirectory, other.transcriptDirectory)
85+
&& editorHandlesAllConfirmation == other.editorHandlesAllConfirmation;
7286
}
7387

7488
@Override
@@ -77,6 +91,7 @@ public String toString() {
7791
builder.append("agentMaxRequests", agentMaxRequests);
7892
builder.append("enableSkills", enableSkills);
7993
builder.append("transcriptDirectory", transcriptDirectory);
94+
builder.append("editorHandlesAllConfirmation", editorHandlesAllConfirmation);
8095
return builder.toString();
8196
}
8297

com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/lsp/protocol/InvokeClientToolConfirmationParams.java

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@ public class InvokeClientToolConfirmationParams {
5252
*/
5353
private String toolCallId;
5454

55+
/**
56+
* The MCP tool annotations describing tool behavior hints.
57+
*/
58+
private ToolAnnotations annotations;
59+
60+
/**
61+
* Additional metadata associated with the tool invocation.
62+
*/
63+
private ToolMetadata toolMetadata;
64+
5565
public String getName() {
5666
return name;
5767
}
@@ -116,9 +126,26 @@ public void setToolCallId(String toolCallId) {
116126
this.toolCallId = toolCallId;
117127
}
118128

129+
public ToolAnnotations getAnnotations() {
130+
return annotations;
131+
}
132+
133+
public void setAnnotations(ToolAnnotations annotations) {
134+
this.annotations = annotations;
135+
}
136+
137+
public ToolMetadata getToolMetadata() {
138+
return toolMetadata;
139+
}
140+
141+
public void setToolMetadata(ToolMetadata toolMetadata) {
142+
this.toolMetadata = toolMetadata;
143+
}
144+
119145
@Override
120146
public int hashCode() {
121-
return Objects.hash(conversationId, input, message, name, roundId, title, toolCallId, turnId);
147+
return Objects.hash(annotations, conversationId, input, message, name, roundId, title, toolCallId, toolMetadata,
148+
turnId);
122149
}
123150

124151
@Override
@@ -133,10 +160,11 @@ public boolean equals(Object obj) {
133160
return false;
134161
}
135162
InvokeClientToolConfirmationParams other = (InvokeClientToolConfirmationParams) obj;
136-
return Objects.equals(conversationId, other.conversationId) && Objects.equals(input, other.input)
163+
return Objects.equals(annotations, other.annotations)
164+
&& Objects.equals(conversationId, other.conversationId) && Objects.equals(input, other.input)
137165
&& Objects.equals(message, other.message) && Objects.equals(name, other.name) && roundId == other.roundId
138166
&& Objects.equals(title, other.title) && Objects.equals(toolCallId, other.toolCallId)
139-
&& Objects.equals(turnId, other.turnId);
167+
&& Objects.equals(toolMetadata, other.toolMetadata) && Objects.equals(turnId, other.turnId);
140168
}
141169

142170
@Override
@@ -150,6 +178,8 @@ public String toString() {
150178
builder.append("turnId", turnId);
151179
builder.append("roundId", roundId);
152180
builder.append("toolCallId", toolCallId);
181+
builder.append("annotations", annotations);
182+
builder.append("toolMetadata", toolMetadata);
153183
return builder.toString();
154184
}
155185
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
4+
package com.microsoft.copilot.eclipse.core.lsp.protocol;
5+
6+
import java.util.Objects;
7+
8+
import org.apache.commons.lang3.builder.ToStringBuilder;
9+
10+
/**
11+
* MCP tool annotations describing tool behavior hints (e.g., readOnly, destructive).
12+
* Provided by CLS, originally sourced from the MCP server's tool definition.
13+
*/
14+
public class ToolAnnotations {
15+
private boolean readOnlyHint;
16+
private boolean destructiveHint;
17+
private boolean idempotentHint;
18+
private boolean openWorldHint;
19+
20+
public boolean isReadOnlyHint() {
21+
return readOnlyHint;
22+
}
23+
24+
public void setReadOnlyHint(boolean readOnlyHint) {
25+
this.readOnlyHint = readOnlyHint;
26+
}
27+
28+
public boolean isDestructiveHint() {
29+
return destructiveHint;
30+
}
31+
32+
public void setDestructiveHint(boolean destructiveHint) {
33+
this.destructiveHint = destructiveHint;
34+
}
35+
36+
public boolean isIdempotentHint() {
37+
return idempotentHint;
38+
}
39+
40+
public void setIdempotentHint(boolean idempotentHint) {
41+
this.idempotentHint = idempotentHint;
42+
}
43+
44+
public boolean isOpenWorldHint() {
45+
return openWorldHint;
46+
}
47+
48+
public void setOpenWorldHint(boolean openWorldHint) {
49+
this.openWorldHint = openWorldHint;
50+
}
51+
52+
@Override
53+
public int hashCode() {
54+
return Objects.hash(readOnlyHint, destructiveHint, idempotentHint, openWorldHint);
55+
}
56+
57+
@Override
58+
public boolean equals(Object obj) {
59+
if (this == obj) {
60+
return true;
61+
}
62+
if (obj == null) {
63+
return false;
64+
}
65+
if (getClass() != obj.getClass()) {
66+
return false;
67+
}
68+
ToolAnnotations other = (ToolAnnotations) obj;
69+
return readOnlyHint == other.readOnlyHint
70+
&& destructiveHint == other.destructiveHint
71+
&& idempotentHint == other.idempotentHint
72+
&& openWorldHint == other.openWorldHint;
73+
}
74+
75+
@Override
76+
public String toString() {
77+
ToStringBuilder builder = new ToStringBuilder(this);
78+
builder.append("readOnlyHint", readOnlyHint);
79+
builder.append("destructiveHint", destructiveHint);
80+
builder.append("idempotentHint", idempotentHint);
81+
builder.append("openWorldHint", openWorldHint);
82+
return builder.toString();
83+
}
84+
}

0 commit comments

Comments
 (0)