Skip to content

Commit 0df43f7

Browse files
Copilotedburns
andauthored
refactor: revert Optional usage, use plain nullable fields with @JsonInclude(NON_NULL)
Remove all Optional<T>/OptionalInt/OptionalDouble usage from DTOs. Revert to plain nullable boxed fields (Boolean, Integer, Double) per Java DTO conventions and reference implementation parity. Add @JsonInclude(JsonInclude.Include.NON_NULL) to classes that were missing it: InputOptions, TelemetryConfig, SessionUiCapabilities, UserInputRequest. Add JsonIncludeNonNullTest verifying annotation presence and serialization behavior (null fields omitted, set fields included). Co-authored-by: edburns <75821+edburns@users.noreply.github.com>
1 parent dfc2ada commit 0df43f7

25 files changed

Lines changed: 364 additions & 1297 deletions

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,16 +90,16 @@ ProcessInfo startCliServer() throws IOException, InterruptedException {
9090
}
9191

9292
// Default UseLoggedInUser to false when GitHubToken is provided
93-
boolean useLoggedInUser = options.getUseLoggedInUser()
94-
.orElse(options.getGitHubToken() == null || options.getGitHubToken().isEmpty());
93+
boolean useLoggedInUser = options.getUseLoggedInUser() != null
94+
? options.getUseLoggedInUser()
95+
: (options.getGitHubToken() == null || options.getGitHubToken().isEmpty());
9596
if (!useLoggedInUser) {
9697
args.add("--no-auto-login");
9798
}
9899

99-
if (options.getSessionIdleTimeoutSeconds().isPresent()
100-
&& options.getSessionIdleTimeoutSeconds().getAsInt() > 0) {
100+
if (options.getSessionIdleTimeoutSeconds() != null && options.getSessionIdleTimeoutSeconds() > 0) {
101101
args.add("--session-idle-timeout");
102-
args.add(String.valueOf(options.getSessionIdleTimeoutSeconds().getAsInt()));
102+
args.add(String.valueOf(options.getSessionIdleTimeoutSeconds()));
103103
}
104104

105105
if (options.isRemote()) {
@@ -159,9 +159,9 @@ ProcessInfo startCliServer() throws IOException, InterruptedException {
159159
if (telemetry.getSourceName() != null) {
160160
pb.environment().put("COPILOT_OTEL_SOURCE_NAME", telemetry.getSourceName());
161161
}
162-
if (telemetry.getCaptureContent().isPresent()) {
162+
if (telemetry.getCaptureContent() != null) {
163163
pb.environment().put("OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT",
164-
telemetry.getCaptureContent().get() ? "true" : "false");
164+
telemetry.getCaptureContent() ? "true" : "false");
165165
}
166166
}
167167

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public CopilotClient(CopilotClientOptions options) {
120120

121121
// Validate auth options with external server
122122
if (this.options.getCliUrl() != null && !this.options.getCliUrl().isEmpty()
123-
&& (this.options.getGitHubToken() != null || this.options.getUseLoggedInUser().isPresent())) {
123+
&& (this.options.getGitHubToken() != null || this.options.getUseLoggedInUser() != null)) {
124124
throw new IllegalArgumentException(
125125
"GitHubToken and UseLoggedInUser cannot be used with CliUrl (external server manages its own auth)");
126126
}

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

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,9 +1118,9 @@ private void handleElicitationRequestAsync(ElicitationContext context, String re
11181118
*/
11191119
private void assertElicitation() {
11201120
SessionCapabilities caps = capabilities;
1121-
if (caps == null || caps.getUi() == null || !caps.getUi().getElicitation().orElse(false)) {
1121+
if (caps == null || caps.getUi() == null || !Boolean.TRUE.equals(caps.getUi().getElicitation())) {
11221122
throw new IllegalStateException("Elicitation is not supported by the host. "
1123-
+ "Check session.getCapabilities().getUi().getElicitation().orElse(false) before calling UI methods.");
1123+
+ "Check session.getCapabilities().getUi()?.getElicitation() before calling UI methods.");
11241124
}
11251125
}
11261126

@@ -1201,10 +1201,10 @@ public CompletableFuture<String> input(String message, InputOptions options) {
12011201
field.put("title", options.getTitle());
12021202
if (options.getDescription() != null)
12031203
field.put("description", options.getDescription());
1204-
if (options.getMinLength().isPresent())
1205-
field.put("minLength", options.getMinLength().getAsInt());
1206-
if (options.getMaxLength().isPresent())
1207-
field.put("maxLength", options.getMaxLength().getAsInt());
1204+
if (options.getMinLength() != null)
1205+
field.put("minLength", options.getMinLength());
1206+
if (options.getMaxLength() != null)
1207+
field.put("maxLength", options.getMaxLength());
12081208
if (options.getFormat() != null)
12091209
field.put("format", options.getFormat());
12101210
if (options.getDefaultValue() != null)
@@ -1695,8 +1695,7 @@ public CompletableFuture<Void> setModel(String model, String reasoningEffort,
16951695
ModelCapabilitiesOverrideSupports supports = null;
16961696
if (modelCapabilities.getSupports() != null) {
16971697
var s = modelCapabilities.getSupports();
1698-
supports = new ModelCapabilitiesOverrideSupports(s.getVision().orElse(null),
1699-
s.getReasoningEffort().orElse(null));
1698+
supports = new ModelCapabilitiesOverrideSupports(s.getVision(), s.getReasoningEffort());
17001699
}
17011700
ModelCapabilitiesOverrideLimits limits = null;
17021701
if (modelCapabilities.getLimits() != null) {

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

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -111,18 +111,12 @@ static CreateSessionRequest buildCreateRequest(SessionConfig config, String sess
111111
request.setAvailableTools(config.getAvailableTools());
112112
request.setExcludedTools(config.getExcludedTools());
113113
request.setProvider(config.getProvider());
114-
config.getEnableSessionTelemetry().ifPresent(request::setEnableSessionTelemetry);
115-
if (config.getOnUserInputRequest() != null) {
116-
request.setRequestUserInput(true);
117-
}
118-
if (config.getHooks() != null && config.getHooks().hasHooks()) {
119-
request.setHooks(true);
120-
}
114+
request.setEnableSessionTelemetry(config.getEnableSessionTelemetry());
115+
request.setRequestUserInput(config.getOnUserInputRequest() != null ? true : null);
116+
request.setHooks(config.getHooks() != null && config.getHooks().hasHooks() ? true : null);
121117
request.setWorkingDirectory(config.getWorkingDirectory());
122-
if (config.isStreaming()) {
123-
request.setStreaming(true);
124-
}
125-
config.getIncludeSubAgentStreamingEvents().ifPresent(request::setIncludeSubAgentStreamingEvents);
118+
request.setStreaming(config.isStreaming() ? true : null);
119+
request.setIncludeSubAgentStreamingEvents(config.getIncludeSubAgentStreamingEvents());
126120
request.setMcpServers(config.getMcpServers());
127121
request.setCustomAgents(config.getCustomAgents());
128122
request.setDefaultAgent(config.getDefaultAgent());
@@ -132,7 +126,7 @@ static CreateSessionRequest buildCreateRequest(SessionConfig config, String sess
132126
request.setInstructionDirectories(config.getInstructionDirectories());
133127
request.setDisabledSkills(config.getDisabledSkills());
134128
request.setConfigDir(config.getConfigDir());
135-
config.getEnableConfigDiscovery().ifPresent(request::setEnableConfigDiscovery);
129+
request.setEnableConfigDiscovery(config.getEnableConfigDiscovery());
136130
request.setModelCapabilities(config.getModelCapabilities());
137131

138132
if (config.getCommands() != null && !config.getCommands().isEmpty()) {
@@ -200,23 +194,15 @@ static ResumeSessionRequest buildResumeRequest(String sessionId, ResumeSessionCo
200194
request.setAvailableTools(config.getAvailableTools());
201195
request.setExcludedTools(config.getExcludedTools());
202196
request.setProvider(config.getProvider());
203-
config.getEnableSessionTelemetry().ifPresent(request::setEnableSessionTelemetry);
204-
if (config.getOnUserInputRequest() != null) {
205-
request.setRequestUserInput(true);
206-
}
207-
if (config.getHooks() != null && config.getHooks().hasHooks()) {
208-
request.setHooks(true);
209-
}
197+
request.setEnableSessionTelemetry(config.getEnableSessionTelemetry());
198+
request.setRequestUserInput(config.getOnUserInputRequest() != null ? true : null);
199+
request.setHooks(config.getHooks() != null && config.getHooks().hasHooks() ? true : null);
210200
request.setWorkingDirectory(config.getWorkingDirectory());
211201
request.setConfigDir(config.getConfigDir());
212-
config.getEnableConfigDiscovery().ifPresent(request::setEnableConfigDiscovery);
213-
if (config.isDisableResume()) {
214-
request.setDisableResume(true);
215-
}
216-
if (config.isStreaming()) {
217-
request.setStreaming(true);
218-
}
219-
config.getIncludeSubAgentStreamingEvents().ifPresent(request::setIncludeSubAgentStreamingEvents);
202+
request.setEnableConfigDiscovery(config.getEnableConfigDiscovery());
203+
request.setDisableResume(config.isDisableResume() ? true : null);
204+
request.setStreaming(config.isStreaming() ? true : null);
205+
request.setIncludeSubAgentStreamingEvents(config.getIncludeSubAgentStreamingEvents());
220206
request.setMcpServers(config.getMcpServers());
221207
request.setCustomAgents(config.getCustomAgents());
222208
request.setDefaultAgent(config.getDefaultAgent());

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

Lines changed: 17 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@
1414
import java.util.function.Supplier;
1515

1616
import com.fasterxml.jackson.annotation.JsonInclude;
17-
import com.fasterxml.jackson.annotation.JsonIgnore;
18-
import java.util.Optional;
19-
import java.util.OptionalInt;
2017

2118
/**
2219
* Configuration options for creating a
@@ -502,47 +499,34 @@ public CopilotClientOptions setTelemetry(TelemetryConfig telemetry) {
502499
/**
503500
* Gets the server-wide idle timeout for sessions in seconds.
504501
*
505-
* @return an {@link OptionalInt} containing the session idle timeout in
506-
* seconds, or {@link java.util.OptionalInt#empty()} if not set. Use
507-
* {@link #clearSessionIdleTimeoutSeconds()} to revert to the default.
502+
* @return the session idle timeout in seconds, or {@code null} to disable
503+
* (sessions live indefinitely)
508504
* @since 1.3.0
509505
*/
510-
@JsonIgnore
511-
public OptionalInt getSessionIdleTimeoutSeconds() {
512-
return sessionIdleTimeoutSeconds == null ? OptionalInt.empty() : OptionalInt.of(sessionIdleTimeoutSeconds);
506+
public Integer getSessionIdleTimeoutSeconds() {
507+
return sessionIdleTimeoutSeconds;
513508
}
514509

515510
/**
516511
* Sets the server-wide idle timeout for sessions in seconds.
517512
* <p>
518513
* Sessions without activity for this duration are automatically cleaned up. Set
519-
* to {@code 0} to disable (sessions live indefinitely). Use
520-
* {@link #clearSessionIdleTimeoutSeconds()} to revert to the default.
514+
* to {@code 0} or leave as {@code null} to disable (sessions live
515+
* indefinitely).
521516
* <p>
522517
* This option is only used when the SDK spawns the CLI process; it is ignored
523518
* when connecting to an external server via {@link #setCliUrl(String)}.
524519
*
525520
* @param sessionIdleTimeoutSeconds
526-
* the idle timeout in seconds
521+
* the idle timeout in seconds, or {@code null} to disable
527522
* @return this options instance for method chaining
528523
* @since 1.3.0
529524
*/
530-
public CopilotClientOptions setSessionIdleTimeoutSeconds(int sessionIdleTimeoutSeconds) {
525+
public CopilotClientOptions setSessionIdleTimeoutSeconds(Integer sessionIdleTimeoutSeconds) {
531526
this.sessionIdleTimeoutSeconds = sessionIdleTimeoutSeconds;
532527
return this;
533528
}
534529

535-
/**
536-
* Clears the sessionIdleTimeoutSeconds setting, reverting to the default
537-
* behavior.
538-
*
539-
* @return this instance for method chaining
540-
*/
541-
public CopilotClientOptions clearSessionIdleTimeoutSeconds() {
542-
this.sessionIdleTimeoutSeconds = null;
543-
return this;
544-
}
545-
546530
/**
547531
* Gets the connection token for the headless CLI server (TCP only).
548532
*
@@ -571,11 +555,11 @@ public CopilotClientOptions setTcpConnectionToken(String tcpConnectionToken) {
571555
/**
572556
* Returns whether to use the logged-in user for authentication.
573557
*
574-
* @return an {@link Optional} containing the boolean value, or empty if not set
558+
* @return {@code true} to use logged-in user auth, {@code false} to use only
559+
* explicit tokens, or {@code null} to use default behavior
575560
*/
576-
@JsonIgnore
577-
public Optional<Boolean> getUseLoggedInUser() {
578-
return Optional.ofNullable(useLoggedInUser);
561+
public Boolean getUseLoggedInUser() {
562+
return useLoggedInUser;
579563
}
580564

581565
/**
@@ -585,23 +569,15 @@ public Optional<Boolean> getUseLoggedInUser() {
585569
* auth. When false, only explicit tokens (gitHubToken or environment variables)
586570
* are used. Default: true (but defaults to false when gitHubToken is provided).
587571
* <p>
572+
* Passing {@code null} is equivalent to passing {@link Boolean#FALSE}.
588573
*
589574
* @param useLoggedInUser
590-
* {@code true} to use logged-in user auth, {@code false} otherwise
575+
* {@code true} to use logged-in user auth, {@code false} or
576+
* {@code null} otherwise
591577
* @return this options instance for method chaining
592578
*/
593-
public CopilotClientOptions setUseLoggedInUser(boolean useLoggedInUser) {
594-
this.useLoggedInUser = useLoggedInUser;
595-
return this;
596-
}
597-
598-
/**
599-
* Clears the useLoggedInUser setting, reverting to the default behavior.
600-
*
601-
* @return this instance for method chaining
602-
*/
603-
public CopilotClientOptions clearUseLoggedInUser() {
604-
this.useLoggedInUser = null;
579+
public CopilotClientOptions setUseLoggedInUser(Boolean useLoggedInUser) {
580+
this.useLoggedInUser = useLoggedInUser != null ? useLoggedInUser : Boolean.FALSE;
605581
return this;
606582
}
607583

0 commit comments

Comments
 (0)