Skip to content

Commit 256de73

Browse files
committed
Java SDK: sync reference implementation to ^1.0.52-1, add preMcpToolCall hook, fix PingResponse timestamp type
## XL — Regenerated RPC types from `@github/copilot schema` update (288 files) Upgrading the reference implementation version from `^1.0.49-1` to `^1.0.52-1` required updating the `@github/copilot` npm package in `scripts/codegen/`, which brought in schema changes. The Java code generator (`java.ts`) was updated to handle these schema changes, and all generated types were regenerated. - 222 new generated RPC types under `src/generated/java/` (new API surfaces: `SessionEventLogApi`, `SessionMetadataApi`, `SessionQueueApi`, `SessionTasksApi`, `SessionUiApi`, `SessionOptionsApi`, `SessionLspApi`, `SessionMcpApi`, `SessionScheduleApi`, permission `location/path/URL` config types, and more) - 66 modified generated files (field type changes, new fields, new enum values) - Updated `scripts/codegen/java.ts` to handle new schema patterns - Updated `scripts/codegen/package.json` and `package-lock.json` These are all machine-generated. Human review should focus on the `java.ts` codegen script changes; the generated output can be spot-checked. ## M — Port `preMcpToolCall` hook (6 files) New hook that fires before an MCP tool call is dispatched to an MCP server, giving SDK consumers the ability to inspect or modify the call. - New: `PreMcpToolCallHandler.java` (functional interface) - New: `PreMcpToolCallHookInput.java` (input DTO with server name, tool name, arguments) - New: `PreMcpToolCallHookOutput.java` (output DTO with allow/deny/modify) - Modified: `SessionHooks.java` (added onPreMcpToolCall field, getter, setter, hasHooks check) - Modified: `CopilotSession.java` (dispatch "preMcpToolCall" hook name to handler) - New test: `PreMcpToolCallHookTest.java` (unit tests for the new hook) ## S — Fix `PingResponse` timestamp type (2 files) The CLI server changed the ping response timestamp from a numeric epoch (long) to an ISO 8601 string. Updated `PingResponse` record field from `long timestamp` to `String timestamp`, and updated `CopilotClientTest` accordingly. ## S — `SessionLogParams` constructor change (1 file) `SessionLogParams` gained new nullable fields in the schema. Updated the call site in `CopilotSession.log()` to pass the additional null parameters. ## S — Test maintenance (4 files) - `McpAndAgentsTest`: new E2E test for MCP and agents scenario - `PermissionsTest`: minor test adjustment - `SessionEventDeserializationTest`: updated assertions to match new generated types - `GeneratedRpcRecordsCoverageTest`: updated coverage list for new generated types ## S — Infra / metadata (3 files) - `.lastmerge`: updated to `f4d22d70016c377881d86e4c77f8a3f93746ffae` - `pom.xml`: ref-impl version property updated to `^1.0.52-1` - `.github/workflows/copilot-setup-steps.yml`: bump gh-aw setup-cli to `v0.74.8`
1 parent 217db5f commit 256de73

308 files changed

Lines changed: 8885 additions & 235 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/copilot-setup-steps.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ jobs:
7676

7777
# Install gh-aw extension for advanced GitHub CLI features
7878
- name: Install gh-aw extension
79-
uses: github/gh-aw/actions/setup-cli@4d44d0e89851a877f4ddc0cb6c0197e42b1016c5 # v0.73.0
79+
uses: github/gh-aw/actions/setup-cli@0feed75a980b06f247abbbf80127f8eb2c19e2c5 # v0.74.8
8080
with:
8181
version: v0.74.4
8282

java/.lastmerge

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
f6c1adf8329ad4206e5ed2e8d12fb8082bc841a2
1+
f4d22d70016c377881d86e4c77f8a3f93746ffae

java/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@
9494
reference-impl-sync workflow and deal with the subsequent
9595
PR.
9696
-->
97-
<readonly-copilot-sdk-ref-impl-version-from-lastmerge-file-updated-by-reference-impl-sync>^1.0.49-1</readonly-copilot-sdk-ref-impl-version-from-lastmerge-file-updated-by-reference-impl-sync>
97+
<readonly-copilot-sdk-ref-impl-version-from-lastmerge-file-updated-by-reference-impl-sync>^1.0.52-1</readonly-copilot-sdk-ref-impl-version-from-lastmerge-file-updated-by-reference-impl-sync>
9898

9999
</properties>
100100

@@ -321,7 +321,7 @@
321321
CompactionTest) where snapshot matching can be sensitive
322322
to non-deterministic compaction behaviour.
323323
Revisit this once this issue is successfully resolved.
324-
https://github.com/github/copilot-sdk/issues/1227
324+
https://github.com/github/copilot-sdk/issues/1227
325325
-->
326326
<rerunFailingTestsCount>2</rerunFailingTestsCount>
327327
<systemPropertyVariables>

java/scripts/codegen/java.ts

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,25 @@ function toJavaClassName(typeName: string): string {
3737
return typeName.split(/[._]/).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join("");
3838
}
3939

40+
/** Java reserved keywords and Object method names that cannot be used as record component names. */
41+
const JAVA_RESERVED_IDENTIFIERS = new Set([
42+
"abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const",
43+
"continue", "default", "do", "double", "else", "enum", "extends", "final", "finally", "float",
44+
"for", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native",
45+
"new", "package", "private", "protected", "public", "return", "short", "static", "strictfp",
46+
"super", "switch", "synchronized", "this", "throw", "throws", "transient", "try", "void",
47+
"volatile", "while",
48+
// Object methods that conflict with record component accessor names
49+
"wait", "notify", "notifyAll", "getClass", "clone", "finalize", "toString", "hashCode", "equals",
50+
]);
51+
4052
function toCamelCase(name: string): string {
4153
const pascal = toPascalCase(name);
42-
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
54+
let result = pascal.charAt(0).toLowerCase() + pascal.slice(1);
55+
if (JAVA_RESERVED_IDENTIFIERS.has(result)) {
56+
result = result + "_";
57+
}
58+
return result;
4359
}
4460

4561
function toEnumConstant(value: string): string {
@@ -102,6 +118,11 @@ interface JavaTypeResult {
102118
let currentDefinitions: Record<string, JSONSchema7> = {};
103119
const pendingStandaloneTypes = new Map<string, JSONSchema7>();
104120

121+
// Cross-schema definitions: keyed by schema filename (e.g. "session-events.schema.json"),
122+
// value is the definitions map from that schema. Populated by generateRpcTypes so that
123+
// cross-schema $ref values like "session-events.schema.json#/definitions/Foo" can be resolved.
124+
const crossSchemaDefinitions = new Map<string, Record<string, JSONSchema7>>();
125+
105126
/**
106127
* Resolve a $ref in a JSON Schema against the current definitions.
107128
* Returns the resolved schema, or the original if no $ref is present.
@@ -131,6 +152,28 @@ function schemaTypeToJava(
131152

132153
// Resolve $ref first — register standalone types for generation
133154
if (schema.$ref) {
155+
// Handle cross-schema $ref (e.g. "session-events.schema.json#/definitions/Foo")
156+
const crossSchemaMatch = schema.$ref.match(/^([^#]+)#\/definitions\/(.+)$/);
157+
if (crossSchemaMatch) {
158+
const [, schemaFile, typeName] = crossSchemaMatch;
159+
const externalDefs = crossSchemaDefinitions.get(schemaFile);
160+
if (externalDefs) {
161+
const resolved = externalDefs[typeName];
162+
if (resolved) {
163+
// Save and swap currentDefinitions so recursive calls resolve against
164+
// the external schema's definitions.
165+
const savedDefs = currentDefinitions;
166+
currentDefinitions = externalDefs;
167+
const result = schemaTypeToJava(resolved, required, context, propName, nestedTypes);
168+
currentDefinitions = savedDefs;
169+
return result;
170+
}
171+
}
172+
// Fallback: extract just the type name and warn
173+
console.warn(`[codegen] Unresolved cross-schema $ref: ${schema.$ref}`);
174+
return { javaType: typeName, imports };
175+
}
176+
134177
const name = schema.$ref.replace(/^#\/definitions\//, "");
135178
const resolved = currentDefinitions[name];
136179
if (resolved) {
@@ -883,6 +926,19 @@ async function generateRpcTypes(schemaPath: string): Promise<void> {
883926
// Set module-level definitions for $ref resolution
884927
currentDefinitions = (schema.definitions ?? {}) as Record<string, JSONSchema7>;
885928
pendingStandaloneTypes.clear();
929+
crossSchemaDefinitions.clear();
930+
931+
// Load cross-schema definitions (session-events) so that cross-schema $ref values
932+
// like "session-events.schema.json#/definitions/Foo" can be resolved.
933+
try {
934+
const sessionEventsSchemaPath = await getSessionEventsSchemaPath();
935+
const sessionEventsContent = await fs.readFile(sessionEventsSchemaPath, "utf-8");
936+
const sessionEventsSchema = JSON.parse(sessionEventsContent) as JSONSchema7;
937+
crossSchemaDefinitions.set("session-events.schema.json",
938+
(sessionEventsSchema.definitions ?? {}) as Record<string, JSONSchema7>);
939+
} catch (e) {
940+
console.warn(`[codegen] Could not load session-events schema for cross-ref resolution: ${e}`);
941+
}
886942

887943
const packageName = "com.github.copilot.sdk.generated.rpc";
888944
const packageDir = `src/generated/java/com/github/copilot/sdk/generated/rpc`;

java/scripts/codegen/package-lock.json

Lines changed: 100 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

java/scripts/codegen/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"generate:java": "tsx java.ts"
88
},
99
"dependencies": {
10-
"@github/copilot": "^1.0.49-1",
10+
"@github/copilot": "^1.0.52-1",
1111
"json-schema": "^0.4.0",
1212
"tsx": "^4.20.6"
1313
}

java/src/generated/java/com/github/copilot/sdk/generated/AssistantMessageEvent.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public record AssistantMessageEventData(
5353
/** Generation phase for phased-output models (e.g., thinking vs. response phases) */
5454
@JsonProperty("phase") String phase,
5555
/** Actual output token count from the API response (completion_tokens), used for accurate token accounting */
56-
@JsonProperty("outputTokens") Double outputTokens,
56+
@JsonProperty("outputTokens") Long outputTokens,
5757
/** CAPI interaction ID for correlating this message with upstream telemetry */
5858
@JsonProperty("interactionId") String interactionId,
5959
/** GitHub request tracing ID (x-github-request-id header) for correlating with server-side logs */

java/src/generated/java/com/github/copilot/sdk/generated/AssistantStreamingDeltaEvent.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public final class AssistantStreamingDeltaEvent extends SessionEvent {
3636
@JsonInclude(JsonInclude.Include.NON_NULL)
3737
public record AssistantStreamingDeltaEventData(
3838
/** Cumulative total bytes received from the streaming response so far */
39-
@JsonProperty("totalResponseSizeBytes") Double totalResponseSizeBytes
39+
@JsonProperty("totalResponseSizeBytes") Long totalResponseSizeBytes
4040
) {
4141
}
4242
}

java/src/generated/java/com/github/copilot/sdk/generated/AssistantUsageCopilotUsageTokenDetail.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@
2222
@JsonIgnoreProperties(ignoreUnknown = true)
2323
public record AssistantUsageCopilotUsageTokenDetail(
2424
/** Number of tokens in this billing batch */
25-
@JsonProperty("batchSize") Double batchSize,
25+
@JsonProperty("batchSize") Long batchSize,
2626
/** Cost per batch of tokens */
27-
@JsonProperty("costPerBatch") Double costPerBatch,
27+
@JsonProperty("costPerBatch") Long costPerBatch,
2828
/** Total token count for this entry */
29-
@JsonProperty("tokenCount") Double tokenCount,
29+
@JsonProperty("tokenCount") Long tokenCount,
3030
/** Token category (e.g., "input", "output") */
3131
@JsonProperty("tokenType") String tokenType
3232
) {

java/src/generated/java/com/github/copilot/sdk/generated/AssistantUsageEvent.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,21 @@ public record AssistantUsageEventData(
3939
/** Model identifier used for this API call */
4040
@JsonProperty("model") String model,
4141
/** Number of input tokens consumed */
42-
@JsonProperty("inputTokens") Double inputTokens,
42+
@JsonProperty("inputTokens") Long inputTokens,
4343
/** Number of output tokens produced */
44-
@JsonProperty("outputTokens") Double outputTokens,
44+
@JsonProperty("outputTokens") Long outputTokens,
4545
/** Number of tokens read from prompt cache */
46-
@JsonProperty("cacheReadTokens") Double cacheReadTokens,
46+
@JsonProperty("cacheReadTokens") Long cacheReadTokens,
4747
/** Number of tokens written to prompt cache */
48-
@JsonProperty("cacheWriteTokens") Double cacheWriteTokens,
48+
@JsonProperty("cacheWriteTokens") Long cacheWriteTokens,
4949
/** Number of output tokens used for reasoning (e.g., chain-of-thought) */
50-
@JsonProperty("reasoningTokens") Double reasoningTokens,
50+
@JsonProperty("reasoningTokens") Long reasoningTokens,
5151
/** Model multiplier cost for billing purposes */
5252
@JsonProperty("cost") Double cost,
5353
/** Duration of the API call in milliseconds */
54-
@JsonProperty("duration") Double duration,
54+
@JsonProperty("duration") Long duration,
5555
/** Time to first token in milliseconds. Only available for streaming requests */
56-
@JsonProperty("ttftMs") Double ttftMs,
56+
@JsonProperty("timeToFirstTokenMs") Long timeToFirstTokenMs,
5757
/** Average inter-token latency in milliseconds. Only available for streaming requests */
5858
@JsonProperty("interTokenLatencyMs") Double interTokenLatencyMs,
5959
/** What initiated this API call (e.g., "sub-agent", "mcp-sampling"); absent for user-initiated calls */

0 commit comments

Comments
 (0)