Skip to content

Commit 88f88c9

Browse files
committed
Add classical code generation workflow for typed event and RPC classes
Introduces a TypeScript-based code generator (scripts/codegen/java.ts) that reads api.schema.json and session-events.schema.json to produce: - Typed session event classes (sealed hierarchy under AbstractSessionEvent) - Typed RPC wrapper classes (ServerRpc, SessionRpc) for JSON-RPC methods - Jackson-annotated records with @JsonCreator, @JsonProperty, @JsonInclude Migrates the hand-written events package to auto-generated types, wires the generated RPC wrappers into CopilotClient and CopilotSession, and adds comprehensive tests including E2E coverage. Also includes: Windows CLI path resolution fixes, shared TestUtil extraction, lazy getRpc() initialization, race condition fix in SessionEventsE2ETest, and a guard preventing agentic sync from modifying src/generated/java/ files.
1 parent d892bdb commit 88f88c9

File tree

329 files changed

+13169
-3483
lines changed

Some content is hidden

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

329 files changed

+13169
-3483
lines changed

.gitattributes

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
.github/workflows/*.lock.yml linguist-generated=true merge=ours
1+
.github/workflows/*.lock.yml linguist-generated=true merge=ours
2+
src/generated/java/** eol=lf linguist-generated=true

.github/copilot-instructions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ mvn test -Dtest=CopilotClientTest
7777

7878
- `com.github.copilot.sdk` - Core classes (CopilotClient, CopilotSession, JsonRpcClient)
7979
- `com.github.copilot.sdk.json` - DTOs, request/response types, handler interfaces (SessionConfig, MessageOptions, ToolDefinition, etc.)
80-
- `com.github.copilot.sdk.events` - Event types for session streaming (AssistantMessageEvent, SessionIdleEvent, ToolExecutionStartEvent, etc.)
80+
- `com.github.copilot.sdk.generated` - Generated event types for session streaming (SessionEvent, AssistantMessageEvent, SessionIdleEvent, ToolExecutionStartEvent, etc.)
8181

8282
### Test Infrastructure
8383

.github/prompts/agentic-merge-reference-impl.prompt.md

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,43 @@
22

33
You are an expert Java developer tasked with porting changes from the reference implementation of the Copilot SDK (primarily the .NET implementation) to this Java SDK.
44

5+
## ❌❌❌ ABSOLUTE PROHIBITION: DO NOT TOUCH GENERATED CODE ❌❌❌
6+
7+
> ### 🚫 THE FILES UNDER `src/generated/java/` ARE FORBIDDEN 🚫
8+
>
9+
> **NEVER, UNDER ANY CIRCUMSTANCES, MODIFY ANY FILE IN `src/generated/java/`.**
10+
>
11+
> These files are AUTO-GENERATED by `scripts/codegen/java.ts` and MUST NOT be hand-edited.
12+
> They are regenerated automatically when the `@github/copilot` npm package version is updated.
13+
>
14+
> ❌ DO NOT edit `src/generated/java/**/*.java`
15+
> ❌ DO NOT create new files in `src/generated/java/`
16+
> ❌ DO NOT delete files from `src/generated/java/`
17+
> ❌ DO NOT "fix" or "improve" generated code — it will be overwritten
18+
>
19+
> **IF ANY CHANGE YOU NEED TO MAKE REQUIRES TOUCHING `src/generated/java/`:**
20+
>
21+
> 1. **STOP IMMEDIATELY** — do not make the change
22+
> 2. **FAIL the agentic sync** — do not attempt to work around this restriction
23+
> 3. **Push an explanatory commit** with a message such as:
24+
> ```
25+
> SYNC BLOCKED: Required change needs generated code update
26+
>
27+
> The reference implementation change '<description>' requires updates
28+
> to the generated RPC/event types in src/generated/java/. These files
29+
> cannot be hand-edited — they must be regenerated.
30+
>
31+
> ACTION REQUIRED: Re-run the update-copilot-dependency.yml workflow
32+
> to update the @github/copilot npm package and regenerate the Java
33+
> source files before this sync can be completed.
34+
> ```
35+
> 4. **Document in the PR body** which reference implementation changes were blocked and why
36+
> 5. **Do NOT attempt to work around this restriction** by making equivalent changes elsewhere
37+
>
38+
> The correct way to update generated code is:
39+
> - Trigger the `update-copilot-dependency.yml` workflow with the new `@github/copilot` version
40+
> - That workflow updates `package.json`, regenerates all files in `src/generated/java/`, and opens a PR
41+
542
## ⚠️ IMPORTANT: Java SDK Design Takes Priority
643
744
**The current design and architecture of the Java SDK is the priority.** When porting changes from the reference implementation:
@@ -101,7 +138,7 @@ For each change in the reference implementation diff, determine:
101138
| `dotnet/src/Client.cs` | `src/main/java/com/github/copilot/sdk/CopilotClient.java` |
102139
| `dotnet/src/Session.cs` | `src/main/java/com/github/copilot/sdk/CopilotSession.java` |
103140
| `dotnet/src/Types.cs` | `src/main/java/com/github/copilot/sdk/types/*.java` |
104-
| `dotnet/src/Generated/*.cs` | `src/main/java/com/github/copilot/sdk/types/*.java` |
141+
| `dotnet/src/Generated/*.cs` | **DO NOT TOUCH** `src/generated/java/**` — see top of this file |
105142
| `dotnet/test/*.cs` | `src/test/java/com/github/copilot/sdk/*Test.java` |
106143
| `docs/getting-started.md` | `README.md` and `src/site/markdown/*.md` |
107144
| `docs/*.md` (new files) | `src/site/markdown/*.md` + update `src/site/site.xml` |
@@ -111,6 +148,10 @@ For each change in the reference implementation diff, determine:
111148
112149
## Step 5: Apply Changes to Java SDK
113150

151+
> ### ❌❌❌ REMINDER: `src/generated/java/` IS FORBIDDEN ❌❌❌
152+
> Any change that requires modifying `src/generated/java/` MUST stop the sync.
153+
> See the **ABSOLUTE PROHIBITION** section at the top of this file for required actions.
154+
114155
When porting changes:
115156

116157
### ⚠️ Priority: Preserve Java SDK Design
@@ -400,6 +441,7 @@ Before finishing:
400441

401442
## Checklist
402443

444+
- [ ]**VERIFIED: No files in `src/generated/java/` were modified** (if any were needed, sync was stopped per ABSOLUTE PROHIBITION above)
403445
- [ ] New branch created from `main`
404446
- [ ] Copilot CLI updated to latest version
405447
- [ ] README.md updated with minimum CLI version requirement
@@ -430,6 +472,7 @@ Before finishing:
430472

431473
## Notes
432474

475+
- ❌❌❌ **`src/generated/java/` IS FORBIDDEN** — NEVER modify generated files; re-run `update-copilot-dependency.yml` instead ❌❌❌
433476
- The reference implementation SDK is at: `https://github.com/github/copilot-sdk.git`
434477
- Primary reference implementation is in `dotnet/` folder
435478
- This Java SDK targets Java 17+

.github/prompts/coding-agent-merge-reference-impl-instructions.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,17 @@ Add the 'reference-impl-sync' label to the existing PR by running this command i
1717
If after analyzing the reference implementation diff there are no relevant changes to port to the Java SDK,
1818
push an empty commit with a message explaining why no changes were needed, so the PR reflects
1919
the analysis outcome. The repository maintainer will close the PR and issue manually.
20+
21+
❌❌❌ ABSOLUTE PROHIBITION ❌❌❌
22+
23+
NEVER MODIFY ANY FILE UNDER src/generated/java/ — THESE FILES ARE AUTO-GENERATED AND FORBIDDEN.
24+
25+
If any change requires modifying src/generated/java/:
26+
1. STOP IMMEDIATELY — do not make the change
27+
2. FAIL the sync with an explanatory commit message
28+
3. Instruct the maintainer to re-run update-copilot-dependency.yml to regenerate these files
29+
30+
See the ABSOLUTE PROHIBITION section in .github/prompts/agentic-merge-reference-impl.prompt.md
31+
for the full required procedure and commit message template.
32+
33+
❌❌❌ END ABSOLUTE PROHIBITION ❌❌❌
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: "Codegen Check"
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
paths:
9+
- 'scripts/codegen/**'
10+
- 'src/generated/java/**'
11+
- '.github/workflows/codegen-check.yml'
12+
workflow_dispatch:
13+
14+
permissions:
15+
contents: read
16+
17+
jobs:
18+
check:
19+
name: "Verify generated files are up-to-date"
20+
runs-on: ubuntu-latest
21+
steps:
22+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
23+
24+
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
25+
with:
26+
node-version: 22
27+
28+
- name: Install codegen dependencies
29+
working-directory: ./scripts/codegen
30+
run: npm ci
31+
32+
- name: Run codegen
33+
working-directory: ./scripts/codegen
34+
run: npm run generate
35+
36+
- name: Check for uncommitted changes
37+
run: |
38+
if [ -n "$(git status --porcelain)" ]; then
39+
echo "::error::Generated files are out of date. Run 'cd scripts/codegen && npm run generate' and commit the changes."
40+
git diff --stat
41+
git diff
42+
exit 1
43+
fi
44+
echo "✅ Generated files are up-to-date"
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
name: "Update @github/copilot Dependency"
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: 'Target version of @github/copilot (e.g. 1.0.24)'
8+
required: true
9+
type: string
10+
11+
permissions:
12+
contents: write
13+
pull-requests: write
14+
15+
jobs:
16+
update:
17+
name: "Update @github/copilot to ${{ inputs.version }}"
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Validate version input
21+
env:
22+
VERSION: ${{ inputs.version }}
23+
run: |
24+
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9._-]+)?$ ]]; then
25+
echo "::error::Invalid version format '$VERSION'. Expected semver (e.g. 1.0.24)."
26+
exit 1
27+
fi
28+
29+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
30+
31+
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
32+
with:
33+
node-version: 22
34+
35+
- name: Update @github/copilot in scripts/codegen
36+
env:
37+
VERSION: ${{ inputs.version }}
38+
working-directory: ./scripts/codegen
39+
# npm install updates package.json and package-lock.json to the new
40+
# version; npm ci (below) then does a clean, reproducible install from
41+
# the updated lock file. Both steps are required: npm install alone
42+
# leaves leftover packages, while npm ci alone cannot change the pinned
43+
# version in the lock file.
44+
run: npm install "@github/copilot@$VERSION"
45+
46+
- name: Install codegen dependencies
47+
working-directory: ./scripts/codegen
48+
run: npm ci
49+
50+
- name: Run codegen
51+
working-directory: ./scripts/codegen
52+
run: npm run generate
53+
54+
- name: Create pull request
55+
env:
56+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
57+
VERSION: ${{ inputs.version }}
58+
run: |
59+
BRANCH="update-copilot-$VERSION"
60+
git config user.name "github-actions[bot]"
61+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
62+
63+
if git rev-parse --verify "origin/$BRANCH" >/dev/null 2>&1; then
64+
git checkout "$BRANCH"
65+
git reset --hard HEAD
66+
else
67+
git checkout -b "$BRANCH"
68+
fi
69+
70+
git add -A
71+
72+
if git diff --cached --quiet; then
73+
echo "No changes detected; skipping commit and PR creation."
74+
exit 0
75+
fi
76+
77+
git commit -m "Update @github/copilot to $VERSION
78+
79+
- Updated @github/copilot in scripts/codegen
80+
- Re-ran Java code generator"
81+
git push origin "$BRANCH" --force-with-lease
82+
83+
if gh pr view "$BRANCH" >/dev/null 2>&1; then
84+
echo "Pull request for branch '$BRANCH' already exists; updated branch only."
85+
else
86+
gh pr create \
87+
--title "Update @github/copilot to $VERSION" \
88+
--body "Automated update of \`@github/copilot\` to version \`$VERSION\`.
89+
90+
### Changes
91+
- Updated \`@github/copilot\` in \`scripts/codegen/package.json\`
92+
- Re-ran Java code generator (\`scripts/codegen\`)
93+
94+
> Created by the **Update @github/copilot Dependency** workflow." \
95+
--base main \
96+
--head "$BRANCH"
97+
fi

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ examples-test/
55
blog-copilotsdk/
66
.claude/worktrees
77
smoke-test
8-
*job-logs.txt
8+
*job-logs.txt*
99
temporary-prompts/
1010
changebundle.txt*
1111
.classpath
1212
.project
1313
.settings
14+
scripts/codegen/node_modules/
1415
*~

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ implementation 'com.github:copilot-sdk-java:0.2.2-java.1'
6767

6868
```java
6969
import com.github.copilot.sdk.CopilotClient;
70-
import com.github.copilot.sdk.events.AssistantMessageEvent;
71-
import com.github.copilot.sdk.events.SessionUsageInfoEvent;
70+
import com.github.copilot.sdk.generated.AssistantMessageEvent;
71+
import com.github.copilot.sdk.generated.SessionUsageInfoEvent;
7272
import com.github.copilot.sdk.json.CopilotClientOptions;
7373
import com.github.copilot.sdk.json.MessageOptions;
7474
import com.github.copilot.sdk.json.PermissionHandler;

config/checkstyle/checkstyle.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
<property name="charset" value="UTF-8"/>
1212
<property name="severity" value="error"/>
1313

14-
<!-- Exclude json package and events package (self-documenting DTOs) -->
14+
<!-- Exclude json package, events package, and generated package (self-documenting DTOs) -->
1515
<module name="BeforeExecutionExclusionFileFilter">
16-
<property name="fileNamePattern" value=".*[\\/](json|events)[\\/].*\.java$"/>
16+
<property name="fileNamePattern" value=".*[\\/](json|events|generated|rpc)[\\/].*\.java$"/>
1717
</module>
1818

1919
<module name="TreeWalker">

config/spotbugs/spotbugs-exclude.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
<!--
33
SpotBugs exclusion filter for the Copilot SDK.
44
5-
The 'events' and 'json' packages contain Jackson-deserialized DTOs where
5+
The 'generated' and 'json' packages contain Jackson-deserialized DTOs where
66
returning mutable internal representations (EI_EXPOSE_REP) and storing
77
references to mutable objects (EI_EXPOSE_REP2) is intentional and expected.
88
Making defensive copies would add overhead without meaningful security
99
benefit for these read-only data transfer objects.
1010
-->
1111
<FindBugsFilter>
1212
<Match>
13-
<Package name="com.github.copilot.sdk.events"/>
13+
<Package name="com.github.copilot.sdk.generated"/>
1414
<Bug pattern="EI_EXPOSE_REP,EI_EXPOSE_REP2"/>
1515
</Match>
1616
<Match>

0 commit comments

Comments
 (0)