Skip to content

Commit 40921e0

Browse files
stephentoubCopilot
andcommitted
Merge main and address cancellation review feedback
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2 parents 571126c + 1a56149 commit 40921e0

106 files changed

Lines changed: 6838 additions & 2360 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/actions/setup-copilot/action.yml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,15 @@ runs:
2323
- name: Set CLI path
2424
id: cli-path
2525
run: |
26-
# As of CLI 1.0.64-1 the @github/copilot package is a thin loader; the
27-
# runnable index.js ships in the installed platform package
28-
# (e.g. @github/copilot-linux-x64). Exactly one is installed.
29-
cli_path=$(ls "$(pwd)"/nodejs/node_modules/@github/copilot-*/index.js 2>/dev/null | head -n1)
26+
cli_path=$(npm --prefix "$(pwd)/nodejs" run --silent prepare:runtime -- --print-path)
3027
if [ -z "$cli_path" ]; then
31-
echo "Could not find @github/copilot platform package (index.js) under nodejs/node_modules" >&2
28+
echo "Could not prepare the Copilot CLI runtime" >&2
3229
exit 1
3330
fi
3431
echo "path=$cli_path" >> $GITHUB_OUTPUT
3532
shell: bash
3633
- name: Verify CLI works
37-
run: node ${{ steps.cli-path.outputs.path }} --version
34+
run: |
35+
legacy_cli=$(npm --prefix "$(pwd)/nodejs" run --silent prepare:runtime -- --print-legacy-path)
36+
node "$legacy_cli" --version
3837
shell: bash

.github/copilot-instructions.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
- Tools: each SDK has helper APIs to expose functions as tools; prefer the language's `DefineTool`/`@define_tool`/`CopilotTool.DefineTool` patterns (see language READMEs).
4848
- Infinite sessions are enabled by default and persist workspace state to `~/.copilot/session-state/{sessionId}`; compaction events are emitted (`session.compaction_start`, `session.compaction_complete`). See language READMEs for usage.
4949
- Streaming: when `streaming`/`Streaming=true` you receive delta events (`assistant.message_delta`, `assistant.reasoning_delta`) and final events (`assistant.message`, `assistant.reasoning`) — tests expect this behavior.
50-
- Type generation is centralized in `nodejs/scripts/generate-session-types.ts` and requires the `@github/copilot` schema to be present (often via `npm link` or installed package).
50+
- Type generation is centralized in `scripts/codegen/` and downloads schemas from the pinned `github/copilot-cli` release.
5151
- Java code style: 4-space indent (Spotless + Eclipse formatter), fluent setter pattern for config classes, Javadoc required on public APIs (enforced by Checkstyle, except `json`/`events` packages).
5252
- Java handlers return `CompletableFuture` (the Java equivalent of C# `async/await`). When porting from .NET: convert properties → getters/fluent setters, use Jackson (`ObjectMapper`, `@JsonProperty`) for serialization.
5353

@@ -64,7 +64,7 @@
6464
- SDK code: `nodejs/src`, `python/copilot`, `go`, `dotnet/src`, `rust/src`, `java/sdk/src/main/java`
6565
- Unit tests: `nodejs/test`, `python/*`, `go/*`, `dotnet/test`, `rust/tests`, `java/sdk/src/test/java`
6666
- E2E tests: `*/e2e/` folders that use the shared replay proxy and `test/snapshots/`, `java/sdk/src/test/java/**/e2e/`
67-
- Generated types: update schema in `@github/copilot` then run `cd nodejs && npm run generate:session-types` and commit generated files in `src/generated` or language generated location. Java generated types: `java/sdk/src/generated/java`
67+
- Generated types: update the pinned Copilot CLI version, run `cd nodejs && npm run generate`, and commit generated files in each language's generated location. Java generated types: `java/sdk/src/generated/java`
6868

6969
## Boundaries — files you must NOT hand-edit ⛔
7070

.github/workflows/dotnet-sdk-tests.yml

Lines changed: 71 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -104,43 +104,65 @@ jobs:
104104
- os: macos-latest
105105
transport: default
106106
backend: capi
107-
shard: "2b1a-permission-provider"
107+
shard: "2b-pending"
108108
- os: macos-latest
109109
transport: default
110110
backend: capi
111-
shard: "2b1a-rewind"
111+
shard: "2b-permission"
112112
- os: macos-latest
113113
transport: default
114114
backend: capi
115-
shard: "2b1a-rpc-a"
115+
shard: "2b-auth"
116116
- os: macos-latest
117117
transport: default
118118
backend: capi
119-
shard: "2b1a-rpc-e"
119+
shard: "2b-hooks"
120120
- os: macos-latest
121121
transport: default
122122
backend: capi
123-
shard: "2b1b-mcp-and-skills"
123+
shard: "2b-unit-p"
124124
- os: macos-latest
125125
transport: default
126126
backend: capi
127-
shard: "2b1b-mcp-config"
127+
shard: "2b-provider"
128128
- os: macos-latest
129129
transport: default
130130
backend: capi
131-
shard: "2b1b-mcp-lifecycle"
131+
shard: "2b-rpc-additional"
132132
- os: macos-latest
133133
transport: default
134134
backend: capi
135-
shard: "2b1b-queue"
135+
shard: "2b-rpc-agent"
136136
- os: macos-latest
137137
transport: default
138138
backend: capi
139-
shard: "2b1b-remote"
139+
shard: "2b-rpc-event-log"
140140
- os: macos-latest
141141
transport: default
142142
backend: capi
143-
shard: "2b2"
143+
shard: "2b-rpc-event-effects"
144+
- os: macos-latest
145+
transport: default
146+
backend: capi
147+
shard: "2b-rpc-mcp-skills"
148+
- os: macos-latest
149+
transport: default
150+
backend: capi
151+
shard: "2b-rpc-mcp-config"
152+
- os: macos-latest
153+
transport: default
154+
backend: capi
155+
shard: "2b-rpc-mcp-lifecycle"
156+
- os: macos-latest
157+
transport: default
158+
backend: capi
159+
shard: "2b-rpc-q-z"
160+
# Standalone extension tests require the legacy JavaScript entrypoint.
161+
# Keep its subprocess tree isolated from the rest of the O/P/R shard.
162+
- os: macos-latest
163+
transport: default
164+
backend: capi
165+
shard: extensions
144166
- os: macos-latest
145167
transport: default
146168
backend: capi
@@ -223,7 +245,6 @@ jobs:
223245
)
224246
225247
filter="$DOTNET_TEST_FILTER"
226-
individual_filters=()
227248
if [[ "$DOTNET_TEST_SHARD" != "full" ]]; then
228249
case "$DOTNET_TEST_SHARD" in
229250
1)
@@ -240,69 +261,72 @@ jobs:
240261
initials=(B E F G)
241262
shard_filter=""
242263
;;
243-
2b1a-permission-provider)
264+
2b-pending)
244265
initials=()
245-
shard_filter=""
246-
individual_filters=(
247-
"FullyQualifiedName~GitHub.Copilot.Test.E2E.PendingWorkResumeE2ETests"
248-
"FullyQualifiedName~GitHub.Copilot.Test.E2E.PerSessionAuthE2ETests"
249-
"FullyQualifiedName~GitHub.Copilot.Test.E2E.PermissionE2ETests"
250-
"FullyQualifiedName~GitHub.Copilot.Test.E2E.PreMcpToolCallHookE2ETests"
251-
"FullyQualifiedName~GitHub.Copilot.Test.E2E.ProviderEndpointE2ETests"
252-
"FullyQualifiedName~GitHub.Copilot.Test.Unit.PermissionHandlerTests"
253-
"FullyQualifiedName~GitHub.Copilot.Test.Unit.PublicDtoTests"
254-
)
266+
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.PendingWorkResumeE2ETests"
255267
;;
256-
2b1a-rewind)
268+
2b-permission)
257269
initials=()
258-
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.Rewind"
270+
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.PermissionE2ETests"
259271
;;
260-
2b1a-rpc-a)
272+
2b-auth)
261273
initials=()
262-
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcA"
274+
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.PerSessionAuthE2ETests"
263275
;;
264-
2b1a-rpc-e)
276+
2b-hooks)
265277
initials=()
266-
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcE"
278+
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.PreMcpToolCallHookE2ETests"
267279
;;
268-
2b1b-mcp-and-skills)
280+
2b-unit-p)
281+
initials=()
282+
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.Unit.P"
283+
;;
284+
2b-provider)
285+
initials=(O)
286+
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.ProviderEndpointE2ETests|FullyQualifiedName~GitHub.Copilot.Test.E2E.RewindE2ETests|FullyQualifiedName~GitHub.Copilot.Test.Unit.R"
287+
;;
288+
2b-rpc-additional)
289+
initials=()
290+
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcAdditionalEdgeCasesE2ETests"
291+
;;
292+
2b-rpc-agent)
293+
initials=()
294+
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcAgentE2ETests"
295+
;;
296+
2b-rpc-event-log)
297+
initials=()
298+
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcEventLogE2ETests"
299+
;;
300+
2b-rpc-event-effects)
301+
initials=()
302+
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcEventSideEffectsE2ETests"
303+
;;
304+
2b-rpc-mcp-skills)
269305
initials=()
270306
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcMcpAndSkillsE2ETests"
271307
;;
272-
2b1b-mcp-config)
308+
2b-rpc-mcp-config)
273309
initials=()
274310
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcMcpConfigE2ETests"
275311
;;
276-
2b1b-mcp-lifecycle)
312+
2b-rpc-mcp-lifecycle)
277313
initials=()
278314
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcMcpLifecycleE2ETests"
279315
;;
280-
2b1b-queue)
316+
2b-rpc-q-z)
281317
initials=()
282-
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcQ"
318+
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcQueueE2ETests|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcRemoteE2ETests|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcScheduleE2ETests|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcServerE2ETests|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcServerMiscE2ETests|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcServerPluginsE2ETests|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcServerRemoteControlE2ETests|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcSessionStateE2ETests|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcSessionStateExtrasE2ETests|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcShellAndFleetE2ETests|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcShellEdgeCaseE2ETests|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcShellUserRequestedE2ETests|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcTasksAndHandlersE2ETests|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcUiEphemeralQueryE2ETests|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcWorkspaceCheckpointsE2ETests"
283319
;;
284-
2b1b-remote)
320+
extensions)
285321
initials=()
286-
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcR"
287-
;;
288-
2b2)
289-
initials=()
290-
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcS|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcT|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcU|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcW|FullyQualifiedName~GitHub.Copilot.Test.Unit.R"
322+
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcExtensionsLoadedE2ETests"
291323
;;
292324
2c)
293325
initials=(T V X Z)
294326
shard_filter=""
295327
;;
296328
esac
297329
298-
if (( ${#individual_filters[@]} > 0 )); then
299-
for individual_filter in "${individual_filters[@]}"; do
300-
combined_filter="${filter:+(${filter})&}(${individual_filter})"
301-
dotnet test test/GitHub.Copilot.SDK.Test.csproj "${args[@]}" --filter "$combined_filter"
302-
done
303-
exit 0
304-
fi
305-
306330
for namespace in E2E Unit; do
307331
for initial in "${initials[@]}"; do
308332
clause="FullyQualifiedName~GitHub.Copilot.Test.${namespace}.${initial}"

.github/workflows/java-sdk-tests.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,12 @@ jobs:
458458
run: mvn javadoc:javadoc -q
459459

460460
- name: Verify CLI works
461-
run: node ../nodejs/node_modules/@github/copilot/npm-loader.js --version
461+
run: |
462+
npm --prefix ../nodejs ci --ignore-scripts
463+
cli_path=$(npm --prefix ../nodejs run --silent prepare:runtime -- --print-path)
464+
test -x "$cli_path"
465+
legacy_cli=$(npm --prefix ../nodejs run --silent prepare:runtime -- --print-legacy-path)
466+
node "$legacy_cli" --version
462467
463468
- name: Run spotless check
464469
if: matrix.test-jdk == '25'

.github/workflows/nodejs-sdk-tests.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ jobs:
4949
- name: Build SDK
5050
run: npm run build
5151

52+
- name: Build and verify release packages
53+
if: runner.os == 'Linux' && matrix.transport == 'default'
54+
run: |
55+
npm run pack:release
56+
npm run verify:release-packages
57+
5258
- name: Install test harness dependencies
5359
working-directory: ./test/harness
5460
run: npm ci --ignore-scripts
@@ -58,6 +64,11 @@ jobs:
5864
working-directory: ./test/harness
5965
run: npm test
6066

67+
- name: Prepare Copilot CLI runtime
68+
run: |
69+
runtime_path=$(npm run --silent prepare:runtime -- --print-path)
70+
echo "COPILOT_CLI_PATH=$runtime_path" >> "$GITHUB_ENV"
71+
6172
- name: Warm up PowerShell
6273
if: runner.os == 'Windows'
6374
run: pwsh.exe -Command "Write-Host 'PowerShell ready'"

.github/workflows/publish.yml

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -107,19 +107,18 @@ jobs:
107107
- name: Build
108108
run: npm run build
109109
- name: Pack
110-
id: pack
111110
run: |
112-
TARBALL="$(npm pack . --json | jq -r '.[0].filename')"
113-
if [ -z "$TARBALL" ] || [ ! -f "$TARBALL" ]; then
114-
echo "::error::npm pack did not produce a tarball."
111+
npm run pack:release
112+
TARBALL_COUNT="$(find . -maxdepth 1 -name 'github-copilot-sdk-*.tgz' | wc -l | tr -d ' ')"
113+
if [ "$TARBALL_COUNT" -ne 9 ]; then
114+
echo "::error::Expected nine Node.js package tarballs, found $TARBALL_COUNT."
115115
exit 1
116116
fi
117-
echo "tarball=$TARBALL" >> "$GITHUB_OUTPUT"
118117
- name: Upload artifact
119118
uses: actions/upload-artifact@v7.0.0
120119
with:
121120
name: nodejs-package
122-
path: nodejs/${{ steps.pack.outputs.tarball }}
121+
path: nodejs/github-copilot-sdk-*.tgz
123122
if-no-files-found: error
124123

125124
publish-nodejs:
@@ -150,12 +149,29 @@ jobs:
150149
set -euo pipefail
151150
shopt -s nullglob
152151
TARBALLS=(./dist/*.tgz)
153-
if [ "${#TARBALLS[@]}" -ne 1 ]; then
154-
echo "::error::Expected exactly one Node.js package tarball, found ${#TARBALLS[@]}."
152+
if [ "${#TARBALLS[@]}" -ne 9 ]; then
153+
echo "::error::Expected nine Node.js package tarballs, found ${#TARBALLS[@]}."
154+
exit 1
155+
fi
156+
MAIN_TARBALL=""
157+
for TARBALL in "${TARBALLS[@]}"; do
158+
PACKAGE_NAME="$(tar -xOf "$TARBALL" package/package.json | jq -r .name)"
159+
if [ "$PACKAGE_NAME" = "@github/copilot-sdk" ]; then
160+
MAIN_TARBALL="$TARBALL"
161+
continue
162+
fi
163+
node nodejs/scripts/npm-release.js publish \
164+
"$TARBALL" \
165+
"$DIST_TAG" \
166+
https://registry.npmjs.org \
167+
public
168+
done
169+
if [ -z "$MAIN_TARBALL" ]; then
170+
echo "::error::Main @github/copilot-sdk tarball not found."
155171
exit 1
156172
fi
157173
node nodejs/scripts/npm-release.js publish \
158-
"${TARBALLS[0]}" \
174+
"$MAIN_TARBALL" \
159175
"$DIST_TAG" \
160176
https://registry.npmjs.org \
161177
public
@@ -209,12 +225,29 @@ jobs:
209225
fi
210226
shopt -s nullglob
211227
TARBALLS=(./dist/*.tgz)
212-
if [ "${#TARBALLS[@]}" -ne 1 ]; then
213-
echo "::error::Expected exactly one Node.js package tarball, found ${#TARBALLS[@]}."
228+
if [ "${#TARBALLS[@]}" -ne 9 ]; then
229+
echo "::error::Expected nine Node.js package tarballs, found ${#TARBALLS[@]}."
230+
exit 1
231+
fi
232+
MAIN_TARBALL=""
233+
for TARBALL in "${TARBALLS[@]}"; do
234+
PACKAGE_NAME="$(tar -xOf "$TARBALL" package/package.json | jq -r .name)"
235+
if [ "$PACKAGE_NAME" = "@github/copilot-sdk" ]; then
236+
MAIN_TARBALL="$TARBALL"
237+
continue
238+
fi
239+
node nodejs/scripts/npm-release.js publish \
240+
"$TARBALL" \
241+
"$DIST_TAG" \
242+
"$FEED_URL" \
243+
azure
244+
done
245+
if [ -z "$MAIN_TARBALL" ]; then
246+
echo "::error::Main @github/copilot-sdk tarball not found."
214247
exit 1
215248
fi
216249
node nodejs/scripts/npm-release.js publish \
217-
"${TARBALLS[0]}" \
250+
"$MAIN_TARBALL" \
218251
"$DIST_TAG" \
219252
"$FEED_URL" \
220253
azure
@@ -327,9 +360,6 @@ jobs:
327360
node-version: "22.x"
328361
- name: Set up uv
329362
uses: astral-sh/setup-uv@v7
330-
- name: Install Node.js dependencies (for CLI version)
331-
working-directory: ./nodejs
332-
run: npm ci --ignore-scripts
333363
- name: Set version
334364
run: sed -i "s/^version = .*/version = \"${{ needs.version.outputs.version }}\"/" pyproject.toml
335365
- name: Inject CLI version

0 commit comments

Comments
 (0)