Skip to content

Commit 74cad77

Browse files
committed
Restore Optional public API from #187 and add missing @JsonInclude annotations
Revert commit 8e0eeeb which accidentally rolled back all Optional usage from PR #189. Restore Optional<Boolean>, OptionalInt, and OptionalDouble return types on public config getters, primitive setters, and clearXxx() methods. Additionally, add @JsonInclude(NON_NULL) and @JsonProperty annotations to classes that were missing them. --- Per-file changes --- src/main/java/com/github/copilot/sdk/json/CopilotClientOptions.java: Restore Optional<Boolean> for getUseLoggedInUser(), OptionalInt for getSessionIdleTimeoutSeconds(). Restore primitive setters and clearXxx() methods. Re-add @JsonIgnore on Optional-returning getters. src/main/java/com/github/copilot/sdk/json/SessionConfig.java: Restore Optional<Boolean> for getEnableSessionTelemetry(), getEnableConfigDiscovery(), getIncludeSubAgentStreamingEvents(). Restore primitive setters and clearXxx() methods. Re-add @JsonIgnore. src/main/java/com/github/copilot/sdk/json/ResumeSessionConfig.java: Same Optional pattern restored for getEnableSessionTelemetry(), getEnableConfigDiscovery(), getIncludeSubAgentStreamingEvents(). src/main/java/com/github/copilot/sdk/json/InfiniteSessionConfig.java: Restore Optional<Boolean> for getEnabled(), OptionalDouble for getBackgroundCompactionThreshold() and getBufferExhaustionThreshold(). src/main/java/com/github/copilot/sdk/json/InputOptions.java: Restore OptionalInt for getMinLength() and getMaxLength(). Add @JsonInclude(NON_NULL) to class. Add @JsonProperty on minLength and maxLength fields to ensure Jackson serialization works with @JsonIgnore on the OptionalInt getters. src/main/java/com/github/copilot/sdk/json/ModelCapabilitiesOverride.java: Restore Optional<Boolean> for Supports.getVision() and Supports.getReasoningEffort(). Restore OptionalInt for Limits.getMaxPromptTokens(), getMaxOutputTokens(), getMaxContextWindowTokens(). Restore clearXxx() methods. src/main/java/com/github/copilot/sdk/json/ProviderConfig.java: Restore OptionalInt for getMaxPromptTokens() and getMaxOutputTokens(). src/main/java/com/github/copilot/sdk/json/TelemetryConfig.java: Restore Optional<Boolean> for getCaptureContent(). Add @JsonInclude(NON_NULL) to class. src/main/java/com/github/copilot/sdk/json/SessionUiCapabilities.java: Restore Optional<Boolean> for getElicitation(). Add @JsonInclude(NON_NULL) to class. src/main/java/com/github/copilot/sdk/json/CustomAgentConfig.java: Restore Optional<Boolean> for getInfer(). src/main/java/com/github/copilot/sdk/json/UserInputRequest.java: Restore Optional<Boolean> for getAllowFreeform(). Add @JsonInclude(NON_NULL) to class. src/main/java/com/github/copilot/sdk/json/CreateSessionRequest.java: Restore primitive boolean setters and clearXxx() methods for wire DTO flags (enableSessionTelemetry, requestPermission, requestUserInput, hooks, streaming, enableConfigDiscovery, includeSubAgentStreamingEvents, requestElicitation). src/main/java/com/github/copilot/sdk/json/ResumeSessionRequest.java: Same primitive setter and clearXxx() restoration as CreateSessionRequest. src/main/java/com/github/copilot/sdk/CliServerManager.java: Update callers to use Optional APIs (.orElse(), .isPresent(), .getAsInt()) instead of null checks. src/main/java/com/github/copilot/sdk/CopilotClient.java: Update useLoggedInUser check to use .isPresent() instead of != null. src/main/java/com/github/copilot/sdk/CopilotSession.java: Update assertElicitation() to use .orElse(false). Update input() method to use .isPresent()/.getAsInt() for minLength/maxLength. Update setModel() to use .orElse(null) for vision/reasoningEffort. src/main/java/com/github/copilot/sdk/SessionRequestBuilder.java: Update buildCreateRequest() and buildResumeRequest() to use .ifPresent() for enableSessionTelemetry, enableConfigDiscovery, includeSubAgentStreamingEvents. Restore conditional-set patterns for requestUserInput, hooks, streaming, disableResume. src/test/java/com/github/copilot/sdk/OptionalApiAndJacksonTest.java: Restore comprehensive test class with clearXxx() tests for all 12 public config classes and Jackson serialization roundtrip tests. src/test/java/com/github/copilot/sdk/JsonIncludeNonNullTest.java: New test class verifying @JsonInclude(NON_NULL) annotation presence on 11 DTO classes and serialization behavior (null fields omitted, set fields included) for InputOptions, TelemetryConfig, SessionUiCapabilities, and UserInputRequest. src/test/java/com/github/copilot/sdk/ConfigCloneTest.java: Update assertions to use Optional APIs (.orElse(), .isEmpty()). src/test/java/com/github/copilot/sdk/CopilotClientTest.java: Update assertions to use Optional APIs (.isEmpty(), Optional.of()). src/test/java/com/github/copilot/sdk/DataObjectCoverageTest.java: Update assertions to use Optional APIs (.orElse(), .getAsInt()). src/test/java/com/github/copilot/sdk/ElicitationTest.java: Update assertions to use Optional APIs (.get(), .getAsInt()). src/test/java/com/github/copilot/sdk/ProviderConfigTest.java: Update assertions to use OptionalInt APIs (.getAsInt(), .isEmpty()). src/test/java/com/github/copilot/sdk/TelemetryConfigTest.java: Update assertions to use Optional APIs (.get(), .isEmpty()).
1 parent a04ea0b commit 74cad77

5 files changed

Lines changed: 170 additions & 0 deletions

File tree

src/main/java/com/github/copilot/sdk/json/InputOptions.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
package com.github.copilot.sdk.json;
66

77
import com.fasterxml.jackson.annotation.JsonIgnore;
8+
import com.fasterxml.jackson.annotation.JsonInclude;
9+
import com.fasterxml.jackson.annotation.JsonProperty;
810
import java.util.OptionalInt;
911

1012
/**
@@ -13,11 +15,14 @@
1315
*
1416
* @since 1.0.0
1517
*/
18+
@JsonInclude(JsonInclude.Include.NON_NULL)
1619
public class InputOptions {
1720

1821
private String title;
1922
private String description;
23+
@JsonProperty("minLength")
2024
private Integer minLength;
25+
@JsonProperty("maxLength")
2126
private Integer maxLength;
2227
private String format;
2328
private String defaultValue;

src/main/java/com/github/copilot/sdk/json/SessionUiCapabilities.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77
import java.util.Optional;
88

99
import com.fasterxml.jackson.annotation.JsonIgnore;
10+
import com.fasterxml.jackson.annotation.JsonInclude;
1011
import com.fasterxml.jackson.annotation.JsonProperty;
1112

1213
/**
1314
* UI-specific capability flags for a session.
1415
*
1516
* @since 1.0.0
1617
*/
18+
@JsonInclude(JsonInclude.Include.NON_NULL)
1719
public class SessionUiCapabilities {
1820

1921
@JsonProperty("elicitation")

src/main/java/com/github/copilot/sdk/json/TelemetryConfig.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.util.Optional;
88

99
import com.fasterxml.jackson.annotation.JsonIgnore;
10+
import com.fasterxml.jackson.annotation.JsonInclude;
1011

1112
/**
1213
* OpenTelemetry configuration for the Copilot CLI server.
@@ -25,6 +26,7 @@
2526
* @see CopilotClientOptions#setTelemetry(TelemetryConfig)
2627
* @since 1.2.0
2728
*/
29+
@JsonInclude(JsonInclude.Include.NON_NULL)
2830
public class TelemetryConfig {
2931

3032
private String otlpEndpoint;

src/main/java/com/github/copilot/sdk/json/UserInputRequest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.util.List;
99

1010
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
11+
import com.fasterxml.jackson.annotation.JsonInclude;
1112
import com.fasterxml.jackson.annotation.JsonProperty;
1213
import com.fasterxml.jackson.annotation.JsonIgnore;
1314
import java.util.Optional;
@@ -21,6 +22,7 @@
2122
* @since 1.0.6
2223
*/
2324
@JsonIgnoreProperties(ignoreUnknown = true)
25+
@JsonInclude(JsonInclude.Include.NON_NULL)
2426
public class UserInputRequest {
2527

2628
@JsonProperty("question")
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
*--------------------------------------------------------------------------------------------*/
4+
5+
package com.github.copilot.sdk;
6+
7+
import static org.junit.jupiter.api.Assertions.*;
8+
9+
import com.fasterxml.jackson.annotation.JsonInclude;
10+
import com.fasterxml.jackson.core.JsonProcessingException;
11+
import com.fasterxml.jackson.databind.ObjectMapper;
12+
13+
import org.junit.jupiter.api.Test;
14+
15+
import com.github.copilot.sdk.json.CopilotClientOptions;
16+
import com.github.copilot.sdk.json.CustomAgentConfig;
17+
import com.github.copilot.sdk.json.InfiniteSessionConfig;
18+
import com.github.copilot.sdk.json.InputOptions;
19+
import com.github.copilot.sdk.json.ModelCapabilitiesOverride;
20+
import com.github.copilot.sdk.json.ProviderConfig;
21+
import com.github.copilot.sdk.json.ResumeSessionConfig;
22+
import com.github.copilot.sdk.json.SessionConfig;
23+
import com.github.copilot.sdk.json.SessionUiCapabilities;
24+
import com.github.copilot.sdk.json.TelemetryConfig;
25+
import com.github.copilot.sdk.json.UserInputRequest;
26+
27+
/**
28+
* Verifies that public DTO classes in the {@code com.github.copilot.sdk.json}
29+
* package are annotated with {@code @JsonInclude(JsonInclude.Include.NON_NULL)}
30+
* so that null-valued fields are omitted during JSON serialization.
31+
*/
32+
class JsonIncludeNonNullTest {
33+
34+
private static final ObjectMapper MAPPER = new ObjectMapper();
35+
36+
// --- Annotation presence checks ---
37+
38+
@Test
39+
void copilotClientOptionsHasNonNullAnnotation() {
40+
assertHasNonNullInclude(CopilotClientOptions.class);
41+
}
42+
43+
@Test
44+
void sessionConfigHasNonNullAnnotation() {
45+
assertHasNonNullInclude(SessionConfig.class);
46+
}
47+
48+
@Test
49+
void resumeSessionConfigHasNonNullAnnotation() {
50+
assertHasNonNullInclude(ResumeSessionConfig.class);
51+
}
52+
53+
@Test
54+
void infiniteSessionConfigHasNonNullAnnotation() {
55+
assertHasNonNullInclude(InfiniteSessionConfig.class);
56+
}
57+
58+
@Test
59+
void inputOptionsHasNonNullAnnotation() {
60+
assertHasNonNullInclude(InputOptions.class);
61+
}
62+
63+
@Test
64+
void modelCapabilitiesOverrideHasNonNullAnnotation() {
65+
assertHasNonNullInclude(ModelCapabilitiesOverride.class);
66+
}
67+
68+
@Test
69+
void providerConfigHasNonNullAnnotation() {
70+
assertHasNonNullInclude(ProviderConfig.class);
71+
}
72+
73+
@Test
74+
void telemetryConfigHasNonNullAnnotation() {
75+
assertHasNonNullInclude(TelemetryConfig.class);
76+
}
77+
78+
@Test
79+
void sessionUiCapabilitiesHasNonNullAnnotation() {
80+
assertHasNonNullInclude(SessionUiCapabilities.class);
81+
}
82+
83+
@Test
84+
void customAgentConfigHasNonNullAnnotation() {
85+
assertHasNonNullInclude(CustomAgentConfig.class);
86+
}
87+
88+
@Test
89+
void userInputRequestHasNonNullAnnotation() {
90+
assertHasNonNullInclude(UserInputRequest.class);
91+
}
92+
93+
// --- Serialization tests: null fields are omitted ---
94+
95+
@Test
96+
void inputOptionsOmitsNullFieldsInJson() throws JsonProcessingException {
97+
var opts = new InputOptions();
98+
String json = MAPPER.writeValueAsString(opts);
99+
assertEquals("{}", json, "All-null InputOptions should serialize to empty JSON");
100+
}
101+
102+
@Test
103+
void telemetryConfigOmitsNullFieldsInJson() throws JsonProcessingException {
104+
var config = new TelemetryConfig();
105+
String json = MAPPER.writeValueAsString(config);
106+
assertEquals("{}", json, "All-null TelemetryConfig should serialize to empty JSON");
107+
}
108+
109+
@Test
110+
void sessionUiCapabilitiesOmitsNullFieldsInJson() throws JsonProcessingException {
111+
var caps = new SessionUiCapabilities();
112+
String json = MAPPER.writeValueAsString(caps);
113+
assertEquals("{}", json, "All-null SessionUiCapabilities should serialize to empty JSON");
114+
}
115+
116+
@Test
117+
void userInputRequestOmitsNullFieldsInJson() throws JsonProcessingException {
118+
var req = new UserInputRequest();
119+
String json = MAPPER.writeValueAsString(req);
120+
assertFalse(json.contains("null"), "UserInputRequest with no fields set should not contain 'null' values");
121+
}
122+
123+
@Test
124+
void inputOptionsIncludesSetFieldsInJson() throws JsonProcessingException {
125+
var opts = new InputOptions();
126+
opts.setMinLength(5);
127+
opts.setMaxLength(100);
128+
String json = MAPPER.writeValueAsString(opts);
129+
assertTrue(json.contains("\"minLength\":5"), "Set minLength should appear in JSON");
130+
assertTrue(json.contains("\"maxLength\":100"), "Set maxLength should appear in JSON");
131+
assertFalse(json.contains("\"title\""), "Unset title should be omitted from JSON");
132+
}
133+
134+
@Test
135+
void telemetryConfigIncludesSetFieldsInJson() throws JsonProcessingException {
136+
var config = new TelemetryConfig();
137+
config.setOtlpEndpoint("http://localhost:4318");
138+
String json = MAPPER.writeValueAsString(config);
139+
assertTrue(json.contains("\"otlpEndpoint\":\"http://localhost:4318\""),
140+
"Set otlpEndpoint should appear in JSON");
141+
assertFalse(json.contains("\"filePath\""), "Unset filePath should be omitted from JSON");
142+
}
143+
144+
@Test
145+
void sessionUiCapabilitiesIncludesSetFieldsInJson() throws JsonProcessingException {
146+
var caps = new SessionUiCapabilities();
147+
caps.setElicitation(true);
148+
String json = MAPPER.writeValueAsString(caps);
149+
assertTrue(json.contains("\"elicitation\":true"), "Set elicitation should appear in JSON");
150+
}
151+
152+
private void assertHasNonNullInclude(Class<?> clazz) {
153+
JsonInclude annotation = clazz.getAnnotation(JsonInclude.class);
154+
assertNotNull(annotation, clazz.getSimpleName() + " should be annotated with @JsonInclude");
155+
assertEquals(JsonInclude.Include.NON_NULL, annotation.value(),
156+
clazz.getSimpleName() + " @JsonInclude should use Include.NON_NULL");
157+
}
158+
159+
}

0 commit comments

Comments
 (0)