Skip to content

Commit 49515ce

Browse files
Copilotedburns
andcommitted
Port upstream changes: TelemetryConfig, PermissionRequestResultKind.NO_RESULT, skipPermission tools, reasoningEffort, new events
Co-authored-by: edburns <75821+edburns@users.noreply.github.com>
1 parent 015f74d commit 49515ce

23 files changed

+752
-33
lines changed

src/main/java/com/github/copilot/sdk/CliServerManager.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,28 @@ ProcessInfo startCliServer() throws IOException, InterruptedException {
110110
pb.environment().put("COPILOT_SDK_AUTH_TOKEN", options.getGitHubToken());
111111
}
112112

113+
// Set telemetry environment variables if configured
114+
var telemetry = options.getTelemetry();
115+
if (telemetry != null) {
116+
pb.environment().put("COPILOT_OTEL_ENABLED", "true");
117+
if (telemetry.getOtlpEndpoint() != null) {
118+
pb.environment().put("OTEL_EXPORTER_OTLP_ENDPOINT", telemetry.getOtlpEndpoint());
119+
}
120+
if (telemetry.getFilePath() != null) {
121+
pb.environment().put("COPILOT_OTEL_FILE_EXPORTER_PATH", telemetry.getFilePath());
122+
}
123+
if (telemetry.getExporterType() != null) {
124+
pb.environment().put("COPILOT_OTEL_EXPORTER_TYPE", telemetry.getExporterType());
125+
}
126+
if (telemetry.getSourceName() != null) {
127+
pb.environment().put("COPILOT_OTEL_SOURCE_NAME", telemetry.getSourceName());
128+
}
129+
if (telemetry.getCaptureContent() != null) {
130+
pb.environment().put("OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT",
131+
telemetry.getCaptureContent() ? "true" : "false");
132+
}
133+
}
134+
113135
Process process = pb.start();
114136

115137
// Forward stderr to logger in background

src/main/java/com/github/copilot/sdk/CopilotSession.java

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,11 @@ private void executePermissionAndRespondAsync(String requestId, PermissionReques
709709
invocation.setSessionId(sessionId);
710710
handler.handle(permissionRequest, invocation).thenAccept(result -> {
711711
try {
712+
if (PermissionRequestResultKind.NO_RESULT
713+
.equals(new PermissionRequestResultKind(result.getKind()))) {
714+
// "no-result" means leave the request unanswered — no RPC call.
715+
return;
716+
}
712717
rpc.invoke("session.permissions.handlePendingPermissionRequest",
713718
Map.of("sessionId", sessionId, "requestId", requestId, "result", result), Object.class);
714719
} catch (Exception e) {
@@ -801,7 +806,17 @@ CompletableFuture<PermissionRequestResult> handlePermissionRequest(JsonNode perm
801806
PermissionRequest request = MAPPER.treeToValue(permissionRequestData, PermissionRequest.class);
802807
var invocation = new PermissionInvocation();
803808
invocation.setSessionId(sessionId);
804-
return handler.handle(request, invocation).exceptionally(ex -> {
809+
return handler.handle(request, invocation).thenApply(result -> {
810+
if (PermissionRequestResultKind.NO_RESULT.equals(new PermissionRequestResultKind(result.getKind()))) {
811+
throw new IllegalStateException(
812+
"Permission handlers cannot return 'no-result' when connected to a protocol v2 server.");
813+
}
814+
return result;
815+
}).exceptionally(ex -> {
816+
if (ex instanceof IllegalStateException ise && ise.getMessage() != null
817+
&& ise.getMessage().contains("no-result")) {
818+
throw (IllegalStateException) ex;
819+
}
805820
LOG.log(Level.SEVERE, "Permission handler threw an exception", ex);
806821
PermissionRequestResult result = new PermissionRequestResult();
807822
result.setKind("denied-no-approval-rule-and-could-not-request-from-user");
@@ -1000,8 +1015,39 @@ public CompletableFuture<Void> abort() {
10001015
* @since 1.0.11
10011016
*/
10021017
public CompletableFuture<Void> setModel(String model) {
1018+
return setModel(model, null);
1019+
}
1020+
1021+
/**
1022+
* Changes the model and reasoning effort for this session.
1023+
* <p>
1024+
* The new model and reasoning effort take effect for the next message.
1025+
* Conversation history is preserved.
1026+
*
1027+
* <pre>{@code
1028+
* session.setModel("claude-sonnet-4.6", "high").get();
1029+
* }</pre>
1030+
*
1031+
* @param model
1032+
* the model ID to switch to (e.g., {@code "gpt-4.1"})
1033+
* @param reasoningEffort
1034+
* the reasoning effort level ({@code "low"}, {@code "medium"},
1035+
* {@code "high"}, {@code "xhigh"}), or {@code null} to use the
1036+
* model's default
1037+
* @return a future that completes when the model switch is acknowledged
1038+
* @throws IllegalStateException
1039+
* if this session has been terminated
1040+
* @since 1.1.0
1041+
*/
1042+
public CompletableFuture<Void> setModel(String model, String reasoningEffort) {
10031043
ensureNotTerminated();
1004-
return rpc.invoke("session.model.switchTo", Map.of("sessionId", sessionId, "modelId", model), Void.class);
1044+
var params = new java.util.LinkedHashMap<String, Object>();
1045+
params.put("sessionId", sessionId);
1046+
params.put("modelId", model);
1047+
if (reasoningEffort != null) {
1048+
params.put("reasoningEffort", reasoningEffort);
1049+
}
1050+
return rpc.invoke("session.model.switchTo", params, Void.class);
10051051
}
10061052

10071053
/**

src/main/java/com/github/copilot/sdk/events/AbstractSessionEvent.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public abstract sealed class AbstractSessionEvent permits
5555
SessionModelChangeEvent, SessionModeChangedEvent, SessionPlanChangedEvent, SessionWorkspaceFileChangedEvent,
5656
SessionHandoffEvent, SessionTruncationEvent, SessionSnapshotRewindEvent, SessionUsageInfoEvent,
5757
SessionCompactionStartEvent, SessionCompactionCompleteEvent, SessionShutdownEvent, SessionContextChangedEvent,
58-
SessionTaskCompleteEvent,
58+
SessionTaskCompleteEvent, SessionBackgroundTasksChangedEvent, SessionToolsUpdatedEvent,
5959
// Assistant events
6060
AssistantTurnStartEvent, AssistantIntentEvent, AssistantReasoningEvent, AssistantReasoningDeltaEvent,
6161
AssistantMessageEvent, AssistantMessageDeltaEvent, AssistantStreamingDeltaEvent, AssistantTurnEndEvent,

src/main/java/com/github/copilot/sdk/events/AssistantUsageEvent.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ public record AssistantUsageData(@JsonProperty("model") String model,
4444
@JsonProperty("apiCallId") String apiCallId, @JsonProperty("providerCallId") String providerCallId,
4545
@JsonProperty("parentToolCallId") String parentToolCallId,
4646
@JsonProperty("quotaSnapshots") Map<String, Object> quotaSnapshots,
47-
@JsonProperty("copilotUsage") CopilotUsage copilotUsage) {
47+
@JsonProperty("copilotUsage") CopilotUsage copilotUsage,
48+
@JsonProperty("reasoningEffort") String reasoningEffort) {
4849

4950
/** Returns a defensive copy of the quota snapshots map. */
5051
@Override

src/main/java/com/github/copilot/sdk/events/ExternalToolRequestedEvent.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public void setData(ExternalToolRequestedData data) {
3838
@JsonIgnoreProperties(ignoreUnknown = true)
3939
public record ExternalToolRequestedData(@JsonProperty("requestId") String requestId,
4040
@JsonProperty("sessionId") String sessionId, @JsonProperty("toolCallId") String toolCallId,
41-
@JsonProperty("toolName") String toolName, @JsonProperty("arguments") Object arguments) {
41+
@JsonProperty("toolName") String toolName, @JsonProperty("arguments") Object arguments,
42+
@JsonProperty("traceparent") String traceparent, @JsonProperty("tracestate") String tracestate) {
4243
}
4344
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
*--------------------------------------------------------------------------------------------*/
4+
5+
package com.github.copilot.sdk.events;
6+
7+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
8+
import com.fasterxml.jackson.annotation.JsonProperty;
9+
10+
/**
11+
* Event: session.background_tasks_changed
12+
*
13+
* @since 1.1.0
14+
*/
15+
@JsonIgnoreProperties(ignoreUnknown = true)
16+
public final class SessionBackgroundTasksChangedEvent extends AbstractSessionEvent {
17+
18+
@JsonProperty("data")
19+
private SessionBackgroundTasksChangedData data;
20+
21+
@Override
22+
public String getType() {
23+
return "session.background_tasks_changed";
24+
}
25+
26+
public SessionBackgroundTasksChangedData getData() {
27+
return data;
28+
}
29+
30+
public void setData(SessionBackgroundTasksChangedData data) {
31+
this.data = data;
32+
}
33+
34+
@JsonIgnoreProperties(ignoreUnknown = true)
35+
public record SessionBackgroundTasksChangedData() {
36+
}
37+
}

src/main/java/com/github/copilot/sdk/events/SessionEventParser.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ public class SessionEventParser {
6666
TYPE_MAP.put("session.compaction_complete", SessionCompactionCompleteEvent.class);
6767
TYPE_MAP.put("session.context_changed", SessionContextChangedEvent.class);
6868
TYPE_MAP.put("session.task_complete", SessionTaskCompleteEvent.class);
69+
TYPE_MAP.put("session.background_tasks_changed", SessionBackgroundTasksChangedEvent.class);
70+
TYPE_MAP.put("session.tools_updated", SessionToolsUpdatedEvent.class);
6971
TYPE_MAP.put("user.message", UserMessageEvent.class);
7072
TYPE_MAP.put("pending_messages.modified", PendingMessagesModifiedEvent.class);
7173
TYPE_MAP.put("assistant.turn_start", AssistantTurnStartEvent.class);

src/main/java/com/github/copilot/sdk/events/SessionModelChangeEvent.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ public void setData(SessionModelChangeData data) {
3333

3434
@JsonIgnoreProperties(ignoreUnknown = true)
3535
public record SessionModelChangeData(@JsonProperty("previousModel") String previousModel,
36-
@JsonProperty("newModel") String newModel) {
36+
@JsonProperty("newModel") String newModel,
37+
@JsonProperty("previousReasoningEffort") String previousReasoningEffort,
38+
@JsonProperty("reasoningEffort") String reasoningEffort) {
3739
}
3840
}

src/main/java/com/github/copilot/sdk/events/SessionResumeEvent.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public void setData(SessionResumeData data) {
3535

3636
@JsonIgnoreProperties(ignoreUnknown = true)
3737
public record SessionResumeData(@JsonProperty("resumeTime") OffsetDateTime resumeTime,
38-
@JsonProperty("eventCount") double eventCount) {
38+
@JsonProperty("eventCount") double eventCount, @JsonProperty("selectedModel") String selectedModel,
39+
@JsonProperty("reasoningEffort") String reasoningEffort) {
3940
}
4041
}

src/main/java/com/github/copilot/sdk/events/SessionStartEvent.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public void setData(SessionStartData data) {
3636
@JsonIgnoreProperties(ignoreUnknown = true)
3737
public record SessionStartData(@JsonProperty("sessionId") String sessionId, @JsonProperty("version") double version,
3838
@JsonProperty("producer") String producer, @JsonProperty("copilotVersion") String copilotVersion,
39-
@JsonProperty("startTime") OffsetDateTime startTime, @JsonProperty("selectedModel") String selectedModel) {
39+
@JsonProperty("startTime") OffsetDateTime startTime, @JsonProperty("selectedModel") String selectedModel,
40+
@JsonProperty("reasoningEffort") String reasoningEffort) {
4041
}
4142
}

0 commit comments

Comments
 (0)