Skip to content
Closed
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
37 changes: 5 additions & 32 deletions scripts/codegen/java.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
}
}
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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(` * <p>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("");

Expand Down Expand Up @@ -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<string, JavaClassDef>();
const requiredSet = new Set(nested.schema.required || []);
const fields: { jsonName: string; javaName: string; javaType: string; description?: string }[] = [];

for (const [propName, propSchema] of Object.entries(nested.schema.properties)) {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions src/main/java/com/github/copilot/sdk/CopilotSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading