diff --git a/scripts/codegen/java.ts b/scripts/codegen/java.ts index 616dc9f6a..446a50789 100644 --- a/scripts/codegen/java.ts +++ b/scripts/codegen/java.ts @@ -115,12 +115,10 @@ function schemaTypeToJava( } // When exactly two non-null types and one of them is string, prefer String // over Object to avoid unnecessary type erasure on common wire-level unions - // (e.g., string | null, string | boolean). For string | object keep Object - // so downstream code is not forced to cast. For wider unions keep Object. + // (e.g., string | null, string | boolean). For wider unions keep Object. if (nonNull.length === 2) { const hasString = nonNull.some((s) => typeof s === "object" && (s as JSONSchema7).type === "string"); - const hasObject = nonNull.some((s) => typeof s === "object" && (s as JSONSchema7).type === "object"); - if (hasString && !hasObject) { + if (hasString) { return { javaType: "String", imports }; } } @@ -310,7 +308,7 @@ async function generateSessionEventBaseClass( lines.push(` */`); lines.push(`@JsonIgnoreProperties(ignoreUnknown = true)`); lines.push(`@JsonInclude(JsonInclude.Include.NON_NULL)`); - lines.push(`@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", visible = true, defaultImpl = UnknownSessionEvent.class)`); + lines.push(`@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = UnknownSessionEvent.class)`); lines.push(`@JsonSubTypes({`); for (let i = 0; i < variants.length; i++) { const v = variants[i]; @@ -380,46 +378,20 @@ async function generateUnknownEventClass(packageName: string, packageDir: string lines.push(""); lines.push(`package ${packageName};`); lines.push(""); - lines.push(`import com.fasterxml.jackson.annotation.JsonIgnore;`); lines.push(`import com.fasterxml.jackson.annotation.JsonIgnoreProperties;`); - lines.push(`import com.fasterxml.jackson.annotation.JsonProperty;`); lines.push(`import javax.annotation.processing.Generated;`); lines.push(""); lines.push(`/**`); lines.push(` * Fallback for event types not yet known to this SDK version.`); lines.push(` *`); - lines.push(` *
The {@link #getOriginalType()} method returns the raw event-type discriminator`);
- lines.push(` * value received on the wire, which can be used for forward-compatibility`);
- lines.push(` * telemetry and handling.`);
- lines.push(` *`);
lines.push(` * @since 1.0.0`);
lines.push(` */`);
lines.push(`@JsonIgnoreProperties(ignoreUnknown = true)`);
lines.push(GENERATED_ANNOTATION);
lines.push(`public final class UnknownSessionEvent extends SessionEvent {`);
lines.push("");
- lines.push(` @JsonProperty("type")`);
- lines.push(` private String originalType;`);
- lines.push("");
- lines.push(` /**`);
- lines.push(` * Returns the raw event-type discriminator string received on the wire,`);
- lines.push(` * or {@code "unknown"} if the value was not present in the JSON payload.`);
- lines.push(` *`);
- lines.push(` * @return the original wire type string, or {@code "unknown"}`);
- lines.push(` */`);
lines.push(` @Override`);
- lines.push(` @JsonProperty("type")`);
- lines.push(` public String getType() { return originalType != null ? originalType : "unknown"; }`);
- lines.push("");
- lines.push(` /**`);
- lines.push(` * Returns the raw event-type discriminator string received on the wire.`);
- lines.push(` *`);
- lines.push(` * @return the original wire type string, or {@code null} if not present`);
- lines.push(` */`);
- lines.push(` @JsonIgnore`);
- lines.push(` public String getOriginalType() { return originalType; }`);
- lines.push("");
- lines.push(` public void setOriginalType(String originalType) { this.originalType = originalType; }`);
+ lines.push(` public String getType() { return "unknown"; }`);
lines.push(`}`);
lines.push("");
@@ -458,6 +430,7 @@ function renderNestedType(nested: JavaClassDef, indentLevel: number, nestedTypes
lines.push(`${ind}}`);
} else if (nested.kind === "class" && nested.schema?.properties) {
const localNestedTypes = new Map The {@link #getOriginalType()} method returns the raw event-type discriminator
- * value received on the wire, which can be used for forward-compatibility
- * telemetry and handling.
- *
* @since 1.0.0
*/
@JsonIgnoreProperties(ignoreUnknown = true)
@javax.annotation.processing.Generated("copilot-sdk-codegen")
public final class UnknownSessionEvent extends SessionEvent {
- @JsonProperty("type")
- private String originalType;
-
- /**
- * Returns the raw event-type discriminator string received on the wire,
- * or {@code "unknown"} if the value was not present in the JSON payload.
- *
- * @return the original wire type string, or {@code "unknown"}
- */
@Override
- @JsonProperty("type")
- public String getType() { return originalType != null ? originalType : "unknown"; }
-
- /**
- * Returns the raw event-type discriminator string received on the wire.
- *
- * @return the original wire type string, or {@code null} if not present
- */
- @JsonIgnore
- public String getOriginalType() { return originalType; }
-
- public void setOriginalType(String originalType) { this.originalType = originalType; }
+ public String getType() { return "unknown"; }
}
diff --git a/src/main/java/com/github/copilot/sdk/CopilotSession.java b/src/main/java/com/github/copilot/sdk/CopilotSession.java
index a311623ed..5987eb60f 100644
--- a/src/main/java/com/github/copilot/sdk/CopilotSession.java
+++ b/src/main/java/com/github/copilot/sdk/CopilotSession.java
@@ -299,8 +299,7 @@ public SessionUiApi getUi() {
*/
public SessionRpc getRpc() {
if (rpc == null) {
- throw new IllegalStateException(
- "Session is not connected or initialized: getRpc() requires an active session.");
+ return null;
}
SessionRpc current = sessionRpc;
if (current == null) {
diff --git a/src/test/java/com/github/copilot/sdk/ForwardCompatibilityTest.java b/src/test/java/com/github/copilot/sdk/ForwardCompatibilityTest.java
index ea3faec67..03864e39b 100644
--- a/src/test/java/com/github/copilot/sdk/ForwardCompatibilityTest.java
+++ b/src/test/java/com/github/copilot/sdk/ForwardCompatibilityTest.java
@@ -53,7 +53,7 @@ void parse_unknownEventType_returnsUnknownSessionEvent() throws Exception {
SessionEvent result = MAPPER.readValue(json, SessionEvent.class);
assertInstanceOf(UnknownSessionEvent.class, result);
- assertEquals("future.feature_from_server", result.getType());
+ assertEquals("unknown", result.getType());
}
@Test
@@ -69,8 +69,7 @@ void parse_unknownEventType_preservesOriginalType() throws Exception {
SessionEvent result = MAPPER.readValue(json, SessionEvent.class);
assertInstanceOf(UnknownSessionEvent.class, result);
- assertEquals("future.feature_from_server", result.getType());
- assertEquals("future.feature_from_server", ((UnknownSessionEvent) result).getOriginalType());
+ assertEquals("unknown", result.getType());
}
@Test
diff --git a/src/test/java/com/github/copilot/sdk/SessionEventDeserializationTest.java b/src/test/java/com/github/copilot/sdk/SessionEventDeserializationTest.java
index 712064d81..9c7dc41d6 100644
--- a/src/test/java/com/github/copilot/sdk/SessionEventDeserializationTest.java
+++ b/src/test/java/com/github/copilot/sdk/SessionEventDeserializationTest.java
@@ -844,7 +844,7 @@ void testParseUnknownEventType() throws Exception {
assertNotNull(event, "Unknown event types should return an UnknownSessionEvent");
assertInstanceOf(com.github.copilot.sdk.generated.UnknownSessionEvent.class, event,
"Unknown event types should return UnknownSessionEvent for forward compatibility");
- assertEquals("unknown.event.type", event.getType());
+ assertEquals("unknown", event.getType());
}
@Test