Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

package com.microsoft.copilot.eclipse.core.chat;

import com.microsoft.copilot.eclipse.core.lsp.protocol.InvokeClientToolConfirmationParams;

/**
* Evaluates whether a tool confirmation request can be auto-approved.
* Each implementation handles a specific category of tool (terminal, file operations, MCP, etc.).
*/
public interface ConfirmationHandler {
Comment thread
xinyi-gong marked this conversation as resolved.

/**
* Evaluates whether the given confirmation request should be auto-approved.
*
* @param params the confirmation request parameters from CLS
* @return ConfirmationResult.AUTO_APPROVED if the tool call can proceed without user
* confirmation, or ConfirmationResult.NEEDS_CONFIRMATION if the user must approve
*/
ConfirmationResult evaluate(InvokeClientToolConfirmationParams params);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

package com.microsoft.copilot.eclipse.core.chat;

/**
* Result of evaluating an auto-approve confirmation request.
*/
public enum ConfirmationResult {
/**
* The tool invocation is automatically approved and no user confirmation is needed.
*/
AUTO_APPROVED,

/**
* The tool invocation requires user confirmation before proceeding.
*/
NEEDS_CONFIRMATION
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ public class CopilotAgentSettings {
@SerializedName("maxToolCallingLoop")
private int agentMaxRequests;

// Control if the editor handles all confirmation requests from CLS.
@SerializedName("editorHandlesAllConfirmation")
private boolean editorHandlesAllConfirmation;

public int getAgentMaxRequests() {
return agentMaxRequests;
}
Expand All @@ -24,9 +28,17 @@ public void setAgentMaxRequests(int agentMaxRequests) {
this.agentMaxRequests = agentMaxRequests;
}

public boolean isEditorHandlesAllConfirmation() {
return editorHandlesAllConfirmation;
}

public void setEditorHandlesAllConfirmation(boolean editorHandlesAllConfirmation) {
this.editorHandlesAllConfirmation = editorHandlesAllConfirmation;
}

@Override
public int hashCode() {
return Objects.hash(agentMaxRequests);
return Objects.hash(agentMaxRequests, editorHandlesAllConfirmation);
}

@Override
Expand All @@ -38,13 +50,15 @@ public boolean equals(Object obj) {
return false;
}
CopilotAgentSettings other = (CopilotAgentSettings) obj;
return agentMaxRequests == other.agentMaxRequests;
return agentMaxRequests == other.agentMaxRequests
&& editorHandlesAllConfirmation == other.editorHandlesAllConfirmation;
}

@Override
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this);
builder.append("agentMaxRequests", agentMaxRequests);
builder.append("editorHandlesAllConfirmation", editorHandlesAllConfirmation);
return builder.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ public class InvokeClientToolConfirmationParams {
*/
private String toolCallId;

/**
* The MCP tool annotations describing tool behavior hints.
*/
private ToolAnnotations annotations;

/**
* Additional metadata associated with the tool invocation.
*/
private ToolMetadata toolMetadata;

public String getName() {
return name;
}
Expand Down Expand Up @@ -116,9 +126,26 @@ public void setToolCallId(String toolCallId) {
this.toolCallId = toolCallId;
}

public ToolAnnotations getAnnotations() {
return annotations;
}

public void setAnnotations(ToolAnnotations annotations) {
this.annotations = annotations;
}

public ToolMetadata getToolMetadata() {
return toolMetadata;
}

public void setToolMetadata(ToolMetadata toolMetadata) {
this.toolMetadata = toolMetadata;
}

@Override
public int hashCode() {
return Objects.hash(conversationId, input, message, name, roundId, title, toolCallId, turnId);
return Objects.hash(annotations, conversationId, input, message, name, roundId, title, toolCallId, toolMetadata,
turnId);
}

@Override
Expand All @@ -133,10 +160,11 @@ public boolean equals(Object obj) {
return false;
}
InvokeClientToolConfirmationParams other = (InvokeClientToolConfirmationParams) obj;
return Objects.equals(conversationId, other.conversationId) && Objects.equals(input, other.input)
return Objects.equals(annotations, other.annotations)
&& Objects.equals(conversationId, other.conversationId) && Objects.equals(input, other.input)
&& Objects.equals(message, other.message) && Objects.equals(name, other.name) && roundId == other.roundId
&& Objects.equals(title, other.title) && Objects.equals(toolCallId, other.toolCallId)
&& Objects.equals(turnId, other.turnId);
&& Objects.equals(toolMetadata, other.toolMetadata) && Objects.equals(turnId, other.turnId);
}

@Override
Expand All @@ -150,6 +178,8 @@ public String toString() {
builder.append("turnId", turnId);
builder.append("roundId", roundId);
builder.append("toolCallId", toolCallId);
builder.append("annotations", annotations);
builder.append("toolMetadata", toolMetadata);
return builder.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

package com.microsoft.copilot.eclipse.core.lsp.protocol;

import java.util.Objects;

import org.apache.commons.lang3.builder.ToStringBuilder;

/**
* MCP tool annotations describing tool behavior hints (e.g., readOnly, destructive).
* Provided by CLS, originally sourced from the MCP server's tool definition.
*/
public class ToolAnnotations {
private boolean readOnlyHint;
private boolean destructiveHint;
private boolean idempotentHint;
private boolean openWorldHint;

public boolean isReadOnlyHint() {
return readOnlyHint;
}

public void setReadOnlyHint(boolean readOnlyHint) {
this.readOnlyHint = readOnlyHint;
}

public boolean isDestructiveHint() {
return destructiveHint;
}

public void setDestructiveHint(boolean destructiveHint) {
this.destructiveHint = destructiveHint;
}

public boolean isIdempotentHint() {
return idempotentHint;
}

public void setIdempotentHint(boolean idempotentHint) {
this.idempotentHint = idempotentHint;
}

public boolean isOpenWorldHint() {
return openWorldHint;
}

public void setOpenWorldHint(boolean openWorldHint) {
this.openWorldHint = openWorldHint;
}

@Override
public int hashCode() {
return Objects.hash(readOnlyHint, destructiveHint, idempotentHint, openWorldHint);
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ToolAnnotations other = (ToolAnnotations) obj;
return readOnlyHint == other.readOnlyHint
&& destructiveHint == other.destructiveHint
&& idempotentHint == other.idempotentHint
&& openWorldHint == other.openWorldHint;
}

@Override
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this);
builder.append("readOnlyHint", readOnlyHint);
builder.append("destructiveHint", destructiveHint);
builder.append("idempotentHint", idempotentHint);
builder.append("openWorldHint", openWorldHint);
return builder.toString();
}
}
Loading