diff --git a/.github/actions/java-test-report/action.yml b/.github/actions/java-test-report/action.yml index d5f6d2709..7e46c0310 100644 --- a/.github/actions/java-test-report/action.yml +++ b/.github/actions/java-test-report/action.yml @@ -1,6 +1,10 @@ name: "Java Test Report" description: "Generate and publish test reports with summary for Java SDK tests." inputs: + title: + description: "Heading to display in the summary (identifies the JDK variant)" + required: false + default: "Copilot Java SDK :: Test Results" report-path: description: "Path to the test report XML files (glob pattern)" required: false @@ -13,6 +17,10 @@ inputs: description: "Path to the JaCoCo CSV report" required: false default: "java/target/site/jacoco-coverage/jacoco.csv" + show-coverage: + description: "Whether to include JaCoCo coverage in the summary" + required: false + default: "true" check-name: description: "Name for the check run" required: false @@ -23,7 +31,7 @@ runs: - name: Generate Test Summary shell: bash run: | - echo "## 🧪 Copilot Java SDK :: Test Results" >> $GITHUB_STEP_SUMMARY + echo "## 🧪 ${{ inputs.title }}" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY if ls ${{ inputs.report-path }} 1>/dev/null 2>&1; then @@ -81,6 +89,7 @@ runs: fi - name: Generate Coverage Summary + if: inputs.show-coverage == 'true' shell: bash run: | JACOCO_XML="${{ inputs.jacoco-path }}" diff --git a/.github/workflows/java-publish-maven.yml b/.github/workflows/java-publish-maven.yml index 2f150f1b1..20b9b2054 100644 --- a/.github/workflows/java-publish-maven.yml +++ b/.github/workflows/java-publish-maven.yml @@ -54,10 +54,10 @@ jobs: - uses: ./.github/actions/setup-copilot - - name: Set up JDK 17 + - name: Set up JDK 25 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: - java-version: "17" + java-version: "25" distribution: "microsoft" cache: "maven" server-id: central diff --git a/.github/workflows/java-publish-snapshot.yml b/.github/workflows/java-publish-snapshot.yml index 7bc231c73..8c957627f 100644 --- a/.github/workflows/java-publish-snapshot.yml +++ b/.github/workflows/java-publish-snapshot.yml @@ -30,10 +30,10 @@ jobs: - uses: ./.github/actions/setup-copilot - - name: Set up JDK 17 + - name: Set up JDK 25 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: - java-version: "17" + java-version: "25" distribution: "microsoft" cache: "maven" server-id: central diff --git a/.github/workflows/java-sdk-tests.yml b/.github/workflows/java-sdk-tests.yml index 5e9b504fd..7c2223886 100644 --- a/.github/workflows/java-sdk-tests.yml +++ b/.github/workflows/java-sdk-tests.yml @@ -28,6 +28,12 @@ on: - "!**/*.gif" - "!**/*.svg" workflow_dispatch: + inputs: + test-jdk17: + description: "Also run tests on JDK 17 (compatibility check)" + type: boolean + required: false + default: true merge_group: permissions: @@ -52,7 +58,7 @@ jobs: - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: - java-version: "17" + java-version: "25" distribution: "microsoft" cache: "maven" @@ -116,6 +122,8 @@ jobs: - name: Generate Test Report Summary if: always() uses: ./.github/actions/java-test-report + with: + title: "Copilot Java SDK :: Test Results (JDK 25)" - name: Upload test results on failure if: failure() @@ -126,3 +134,28 @@ jobs: java/target/surefire-reports/ java/target/surefire-reports-isolated/ retention-days: 7 + + - name: Switch to JDK 17 + if: inputs.test-jdk17 == true || inputs.test-jdk17 == null + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: "17" + distribution: "microsoft" + + - name: Re-run tests on JDK 17 (no recompilation) + if: inputs.test-jdk17 == true || inputs.test-jdk17 == null + env: + CI: "true" + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_CLI_PATH: ${{ steps.setup-copilot.outputs.cli-path }} + run: | + echo "Running tests against JDK 25-built classes using JDK 17 runtime..." + java -version + mvn antrun:run@print-test-jdk-banner surefire:test -Denforcer.skip=true -DtestExecutionAgentArgs= + + - name: Generate Test Report Summary (JDK 17) + if: always() && (inputs.test-jdk17 == true || inputs.test-jdk17 == null) + uses: ./.github/actions/java-test-report + with: + title: "Copilot Java SDK :: Test Results (JDK 17)" + show-coverage: "false" diff --git a/.vscode/settings.json b/.vscode/settings.json index d0d8465c3..c4ae9c761 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -25,5 +25,6 @@ "[go]": { "editor.defaultFormatter": "golang.go" }, - "java.configuration.updateBuildConfiguration": "automatic" + "java.configuration.updateBuildConfiguration": "automatic", + "java.compile.nullAnalysis.mode": "automatic" } diff --git a/java/20261027-2202-job-logs.txt b/java/20261027-2202-job-logs.txt new file mode 100644 index 000000000..86bf20178 --- /dev/null +++ b/java/20261027-2202-job-logs.txt @@ -0,0 +1,1208 @@ +-*- mode: compilation; default-directory: "~/workareas/copilot-sdk/java/" -*- +Compilation started at Wed May 27 21:55:34 + +mvn clean verify +WARNING: A terminally deprecated method in sun.misc.Unsafe has been called +WARNING: sun.misc.Unsafe::objectFieldOffset has been called by com.google.common.util.concurrent.AbstractFuture$UnsafeAtomicHelper (file:/usr/share/maven/lib/guava.jar) +WARNING: Please consider reporting this to the maintainers of class com.google.common.util.concurrent.AbstractFuture$UnsafeAtomicHelper +WARNING: sun.misc.Unsafe::objectFieldOffset will be removed in a future release +[INFO] Scanning for projects... +[INFO] Inspecting build with total of 1 modules +[INFO] Installing Central Publishing features +[INFO] +[INFO] --------------------< com.github:copilot-sdk-java >--------------------- +[INFO] Building GitHub Copilot SDK :: Java 1.0.0-beta-java.5-SNAPSHOT +[INFO] --------------------------------[ jar ]--------------------------------- +[INFO] +[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ copilot-sdk-java --- +[INFO] Deleting /home/edburns/workareas/copilot-sdk/java/target +[INFO] +[INFO] --- maven-checkstyle-plugin:3.6.0:check (validate) @ copilot-sdk-java --- +[INFO] Starting audit... +Audit done. +[INFO] You have 0 Checkstyle violations. +[INFO] +[INFO] --- maven-enforcer-plugin:3.5.0:enforce (enforce-jdk25) @ copilot-sdk-java --- +Downloading from central: https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-xml/3.0.0/plexus-xml-3.0.0.pom +Downloaded from central: https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-xml/3.0.0/plexus-xml-3.0.0.pom (3.7 kB at 3.9 kB/s) +Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/enforcer/enforcer-api/3.5.0/enforcer-api-3.5.0.pom +Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/maven/enforcer/enforcer-api/3.5.0/enforcer-api-3.5.0.pom (3.8 kB at 34 kB/s) +Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/enforcer/enforcer-rules/3.5.0/enforcer-rules-3.5.0.pom +Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/maven/enforcer/enforcer-rules/3.5.0/enforcer-rules-3.5.0.pom (5.4 kB at 76 kB/s) +Downloading from central: https://repo.maven.apache.org/maven2/commons-codec/commons-codec/1.17.0/commons-codec-1.17.0.pom +Downloaded from central: https://repo.maven.apache.org/maven2/commons-codec/commons-codec/1.17.0/commons-codec-1.17.0.pom (18 kB at 255 kB/s) +Downloading from central: https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-xml/3.0.0/plexus-xml-3.0.0.jar +Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/enforcer/enforcer-api/3.5.0/enforcer-api-3.5.0.jar +Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/enforcer/enforcer-rules/3.5.0/enforcer-rules-3.5.0.jar +Downloading from central: https://repo.maven.apache.org/maven2/commons-codec/commons-codec/1.17.0/commons-codec-1.17.0.jar +Downloaded from central: https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-xml/3.0.0/plexus-xml-3.0.0.jar (93 kB at 782 kB/s) +Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/maven/enforcer/enforcer-api/3.5.0/enforcer-api-3.5.0.jar (15 kB at 91 kB/s) +Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/maven/enforcer/enforcer-rules/3.5.0/enforcer-rules-3.5.0.jar (147 kB at 699 kB/s) +Downloaded from central: https://repo.maven.apache.org/maven2/commons-codec/commons-codec/1.17.0/commons-codec-1.17.0.jar (373 kB at 1.4 MB/s) +[INFO] Rule 0: org.apache.maven.enforcer.rules.version.RequireJavaVersion passed +[INFO] +[INFO] --- jacoco-maven-plugin:0.8.14:prepare-agent (wire-up-coverage-instrumentation) @ copilot-sdk-java --- +[INFO] testExecutionAgentArgs set to -javaagent:/home/edburns/.m2/repository/org/jacoco/org.jacoco.agent/0.8.14/org.jacoco.agent-0.8.14-runtime.jar=destfile=/home/edburns/workareas/copilot-sdk/java/target/jacoco-test-results/sdk-tests.exec,includes=com/github/copilot/**,excludes=com/github/copilot/E2ETestContext*:com/github/copilot/CapiProxy* +[INFO] +[INFO] --- build-helper-maven-plugin:3.6.1:add-source (add-generated-source) @ copilot-sdk-java --- +[INFO] Source directory: /home/edburns/workareas/copilot-sdk/java/src/generated/java added. +[INFO] +[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ copilot-sdk-java --- +[INFO] Using 'UTF-8' encoding to copy filtered resources. +[INFO] skip non existing resourceDirectory /home/edburns/workareas/copilot-sdk/java/src/main/resources +[INFO] +[INFO] --- maven-compiler-plugin:3.15.0:compile (default-compile) @ copilot-sdk-java --- +[INFO] Recompiling the module because of changed source code. +[INFO] Compiling 853 source files with javac [debug release 17 module-path] to target/classes +[INFO] /home/edburns/workareas/copilot-sdk/java/src/main/java/com/github/copilot/CopilotSession.java: Some input files use or override a deprecated API. +[INFO] /home/edburns/workareas/copilot-sdk/java/src/main/java/com/github/copilot/CopilotSession.java: Recompile with -Xlint:deprecation for details. +[INFO] +[INFO] --- maven-compiler-plugin:3.15.0:compile (compile-java25) @ copilot-sdk-java --- +[INFO] Compiling 1 source file with javac [debug release 25] to target/classes/META-INF/versions/25 +[INFO] +[INFO] --- maven-antrun-plugin:3.2.0:run (clone-or-update-copilot-sdk) @ copilot-sdk-java --- +[INFO] Executing tasks +[WARNING] [echo] Cloning copilot-sdk repository at commit 60104052cd914949ddf8c7a31e1856cd6db0a57c... +[INFO] [exec] Cloning into '/home/edburns/workareas/copilot-sdk/java/target/copilot-sdk'... +[INFO] [exec] From https://github.com/github/copilot-sdk +[INFO] [exec] * branch 60104052cd914949ddf8c7a31e1856cd6db0a57c -> FETCH_HEAD +[INFO] [exec] HEAD is now at 6010405 Multitenancy hardening: Client Mode (#1428) +[INFO] Executed tasks +[INFO] +[INFO] --- exec-maven-plugin:3.6.3:exec (install-harness-dependencies) @ copilot-sdk-java --- + +added 146 packages, and audited 147 packages in 24s + +45 packages are looking for funding + run `npm fund` for details + +found 0 vulnerabilities +[INFO] +[INFO] --- exec-maven-plugin:3.6.3:exec (install-nodejs-cli-dependencies) @ copilot-sdk-java --- + +added 203 packages, and audited 204 packages in 15s + +62 packages are looking for funding + run `npm fund` for details + +found 0 vulnerabilities +[INFO] +[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ copilot-sdk-java --- +[INFO] Using 'UTF-8' encoding to copy filtered resources. +[INFO] Copying 2 resources +[INFO] +[INFO] --- maven-compiler-plugin:3.15.0:testCompile (default-testCompile) @ copilot-sdk-java --- +[INFO] Recompiling the module because of changed dependency. +[INFO] Compiling 63 source files with javac [debug release 17 module-path] to target/test-classes +[INFO] /home/edburns/workareas/copilot-sdk/java/src/test/java/com/github/copilot/CommandsTest.java: Some input files use or override a deprecated API. +[INFO] /home/edburns/workareas/copilot-sdk/java/src/test/java/com/github/copilot/CommandsTest.java: Recompile with -Xlint:deprecation for details. +[INFO] +[INFO] --- maven-antrun-plugin:3.2.0:run (print-test-jdk-banner) @ copilot-sdk-java --- +[INFO] Executing tasks +[WARNING] [echo] ⚠⚠⚠ Using Java 25.0.2 (Microsoft) to run tests. +[INFO] Executed tasks +[INFO] +[INFO] --- maven-surefire-plugin:3.5.5:test (default-test) @ copilot-sdk-java --- +[INFO] Using auto detected provider org.apache.maven.surefire.junitplatform.JUnitPlatformProvider +[INFO] +[INFO] ------------------------------------------------------- +[INFO] T E S T S +[INFO] ------------------------------------------------------- +[INFO] Running com.github.copilot.AgentInfoTest +[INFO] Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.146 s -- in com.github.copilot.AgentInfoTest +[INFO] Running com.github.copilot.AgentModeTest +[INFO] Tests run: 10, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.546 s -- in com.github.copilot.AgentModeTest +[INFO] Running com.github.copilot.AskUserTest +May 27, 2026 9:56:52 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'ask_user/should_handle_freeform_user_input_response' expects prompts: [Ask me a question using ask_user and then include my answer in your response. The question should be 'What is] +May 27, 2026 9:56:56 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'ask_user/should_receive_choices_in_user_input_request' expects prompts: ["Use the ask_user tool to ask me to pick between exactly two options: 'Red' and 'Blue'. These should be] +May 27, 2026 9:56:58 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'ask_user/should_invoke_user_input_handler_when_model_uses_ask_user_tool' expects prompts: [Ask me to choose between 'Option A' and 'Option B' using the ask_user tool. Wait for my response before] +[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 10.29 s -- in com.github.copilot.AskUserTest +[INFO] Running com.github.copilot.CliServerManagerTest +[INFO] Tests run: 22, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.166 s -- in com.github.copilot.CliServerManagerTest +[INFO] Running com.github.copilot.ClosedSessionGuardTest +May 27, 2026 9:57:02 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +May 27, 2026 9:57:04 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +May 27, 2026 9:57:06 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +May 27, 2026 9:57:08 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +May 27, 2026 9:57:10 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +May 27, 2026 9:57:12 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +May 27, 2026 9:57:14 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +May 27, 2026 9:57:16 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +May 27, 2026 9:57:18 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +May 27, 2026 9:57:20 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +May 27, 2026 9:57:22 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +May 27, 2026 9:57:25 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +May 27, 2026 9:57:27 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +May 27, 2026 9:57:31 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +May 27, 2026 9:57:34 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +May 27, 2026 9:57:36 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +[INFO] Tests run: 16, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 38.13 s -- in com.github.copilot.ClosedSessionGuardTest +[INFO] Running com.github.copilot.CommandsTest +[INFO] Tests run: 11, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.078 s -- in com.github.copilot.CommandsTest +[INFO] Running com.github.copilot.CompactionTest +May 27, 2026 9:57:41 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'compaction/should_not_emit_compaction_events_when_infinite_sessions_disabled' expects prompts: [What is 2+2?] +[WARNING] Tests run: 2, Failures: 0, Errors: 0, Skipped: 1, Time elapsed: 5.485 s -- in com.github.copilot.CompactionTest +[INFO] Running com.github.copilot.ConfigCloneTest +[INFO] Tests run: 27, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.118 s -- in com.github.copilot.ConfigCloneTest +[INFO] Running com.github.copilot.CopilotClientModeTest +[INFO] Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.020 s -- in com.github.copilot.CopilotClientModeTest +[INFO] Running com.github.copilot.CopilotClientTest +May 27, 2026 9:58:17 PM com.github.copilot.LoggingHelpers logTiming +WARNING: CopilotClient.start failed. Elapsed=PT30.004S +java.util.concurrent.TimeoutException + at java.base/java.util.concurrent.CompletableFuture.timedGet(CompletableFuture.java:1981) + at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2116) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.CopilotClient.verifyProtocolVersion(CopilotClient.java:272) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.CopilotClient.startCoreBody(CopilotClient.java:236) + at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1789) + at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1781) + at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:511) + at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1450) + at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:2019) + at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:187) + +May 27, 2026 9:58:17 PM com.github.copilot.LoggingHelpers logTiming +WARNING: CopilotClient.start failed. Elapsed=PT0.002S +java.io.IOException: Cannot run program "/nonexistent/path/to/cli": Exec failed, error: 2 (No such file or directory) + at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1112) + at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1046) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.CliServerManager.startCliServer(CliServerManager.java:168) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.CopilotClient.startCoreBody(CopilotClient.java:220) + at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1789) + at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1781) + at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:511) + at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1450) + at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:2019) + at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:187) +Caused by: java.io.IOException: Exec failed, error: 2 (No such file or directory) + at java.base/java.lang.ProcessImpl.forkAndExec(Native Method) + at java.base/java.lang.ProcessImpl.(ProcessImpl.java:300) + at java.base/java.lang.ProcessImpl.start(ProcessImpl.java:231) + at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1078) + ... 9 more + +May 27, 2026 9:58:22 PM com.github.copilot.LoggingHelpers logTiming +WARNING: CopilotClient.start failed. Elapsed=PT0.002S +java.io.IOException: Cannot run program "/nonexistent/path/to/cli": Exec failed, error: 2 (No such file or directory) + at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1112) + at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1046) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.CliServerManager.startCliServer(CliServerManager.java:168) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.CopilotClient.startCoreBody(CopilotClient.java:220) + at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1789) + at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1781) + at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:511) + at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1450) + at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:2019) + at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:187) +Caused by: java.io.IOException: Exec failed, error: 2 (No such file or directory) + at java.base/java.lang.ProcessImpl.forkAndExec(Native Method) + at java.base/java.lang.ProcessImpl.(ProcessImpl.java:300) + at java.base/java.lang.ProcessImpl.start(ProcessImpl.java:231) + at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1078) + ... 9 more + +May 27, 2026 9:58:22 PM com.github.copilot.LoggingHelpers logTiming +WARNING: CopilotClient.start failed. Elapsed=PT0.012S +java.io.IOException: Cannot run program "/nonexistent/path/to/cli": Exec failed, error: 2 (No such file or directory) + at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1112) + at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1046) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.CliServerManager.startCliServer(CliServerManager.java:168) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.CopilotClient.startCoreBody(CopilotClient.java:220) + at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1789) + at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1781) + at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:511) + at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1450) + at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:2019) + at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:187) +Caused by: java.io.IOException: Exec failed, error: 2 (No such file or directory) + at java.base/java.lang.ProcessImpl.forkAndExec(Native Method) + at java.base/java.lang.ProcessImpl.(ProcessImpl.java:300) + at java.base/java.lang.ProcessImpl.start(ProcessImpl.java:231) + at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1078) + ... 9 more + +May 27, 2026 9:58:22 PM com.github.copilot.LoggingHelpers logTiming +WARNING: CopilotClient.start failed. Elapsed=PT0.003S +java.io.IOException: Cannot run program "/nonexistent/path/to/cli": Exec failed, error: 2 (No such file or directory) + at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1112) + at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1046) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.CliServerManager.startCliServer(CliServerManager.java:168) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.CopilotClient.startCoreBody(CopilotClient.java:220) + at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1789) + at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1781) + at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:511) + at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1450) + at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:2019) + at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:187) +Caused by: java.io.IOException: Exec failed, error: 2 (No such file or directory) + at java.base/java.lang.ProcessImpl.forkAndExec(Native Method) + at java.base/java.lang.ProcessImpl.(ProcessImpl.java:300) + at java.base/java.lang.ProcessImpl.start(ProcessImpl.java:231) + at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1078) + ... 9 more + +[INFO] Tests run: 38, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 40.30 s -- in com.github.copilot.CopilotClientTest +[INFO] Running com.github.copilot.CopilotSessionTest +May 27, 2026 9:58:26 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_get_session_metadata_by_id' expects prompts: [Say hello] +May 27, 2026 9:58:29 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_create_a_session_with_defaultagent_excludedtools' expects prompts: [What is 1+1?] +May 27, 2026 9:58:31 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +May 27, 2026 9:58:33 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_list_sessions' expects prompts: [Say hello, Say goodbye] +May 27, 2026 9:58:36 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_delete_session' expects prompts: [Hello] +May 27, 2026 9:58:38 PM com.github.copilot.LoggingHelpers logTiming +WARNING: JsonRpc.invoke JSON-RPC request finished. Elapsed=PT0.016S, Method=session.resume, RequestId=5, Status=Failed +java.util.concurrent.CompletionException: com.github.copilot.JsonRpcException: Request session.resume failed with message: Session not found: 6727df67-df52-40ca-8b50-7eb9f21d6f3f + at java.base/java.util.concurrent.CompletableFuture.wrapInCompletionException(CompletableFuture.java:323) + at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:376) + at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:391) + at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:657) + at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:531) + at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2221) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.handleMessage(JsonRpcClient.java:281) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.lambda$startReader$0(JsonRpcClient.java:256) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614) + at java.base/java.lang.Thread.run(Thread.java:1474) +Caused by: com.github.copilot.JsonRpcException: Request session.resume failed with message: Session not found: 6727df67-df52-40ca-8b50-7eb9f21d6f3f + ... 7 more + +May 27, 2026 9:58:38 PM com.github.copilot.LoggingHelpers logTiming +WARNING: CopilotClient.resumeSession failed. Elapsed=PT0.019S, SessionId=6727df67-df52-40ca-8b50-7eb9f21d6f3f +java.util.concurrent.CompletionException: com.github.copilot.JsonRpcException: Request session.resume failed with message: Session not found: 6727df67-df52-40ca-8b50-7eb9f21d6f3f + at java.base/java.util.concurrent.CompletableFuture.wrapInCompletionException(CompletableFuture.java:323) + at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:376) + at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:391) + at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:657) + at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:531) + at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2221) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.handleMessage(JsonRpcClient.java:281) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.lambda$startReader$0(JsonRpcClient.java:256) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614) + at java.base/java.lang.Thread.run(Thread.java:1474) +Caused by: com.github.copilot.JsonRpcException: Request session.resume failed with message: Session not found: 6727df67-df52-40ca-8b50-7eb9f21d6f3f + ... 7 more + +May 27, 2026 9:58:38 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_get_last_session_id' expects prompts: [Say hello] +May 27, 2026 9:58:40 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/sendandwait_blocks_until_session_idle_and_returns_final_assistant_message' expects prompts: [What is 2+2?] +May 27, 2026 9:58:43 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/sendandwait_throws_on_timeout' expects prompts: [Run 'sleep 2 && echo done'] +May 27, 2026 9:58:44 PM com.github.copilot.LoggingHelpers logTiming +WARNING: CopilotSession.sendAndWait failed. Elapsed=PT0.100S, SessionId=94092f76-75c0-4a68-bbb1-c11b78c0f282, CompletedBy=timeout +java.util.concurrent.TimeoutException: sendAndWait timed out after 100ms + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.CopilotSession.lambda$sendAndWait$2(CopilotSession.java:559) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328) + at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:309) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614) + at java.base/java.lang.Thread.run(Thread.java:1474) + +May 27, 2026 9:58:44 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_abort_a_session' expects prompts: [run the shell command 'sleep 100' (note this works on both bash and PowerShell), What is 2+2?] +May 27, 2026 9:58:47 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_create_a_session_with_availabletools' expects prompts: [What is 1+1?] +May 27, 2026 9:58:49 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_list_sessions' expects prompts: [Say hello, Say goodbye] +May 27, 2026 9:58:51 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_create_session_with_custom_config_dir' expects prompts: [What is 1+1?] +May 27, 2026 9:58:53 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_create_a_session_with_appended_systemmessage_config' expects prompts: [What is your full name?] +May 27, 2026 9:58:54 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_create_session_with_custom_tool' expects prompts: [What is the secret number for key ALPHA?] +May 27, 2026 9:58:56 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +May 27, 2026 9:58:58 PM com.github.copilot.LoggingHelpers logTiming +WARNING: JsonRpc.invoke JSON-RPC request finished. Elapsed=PT0.014S, Method=session.resume, RequestId=2, Status=Failed +java.util.concurrent.CompletionException: com.github.copilot.JsonRpcException: Request session.resume failed with message: Session not found: non-existent-session-id + at java.base/java.util.concurrent.CompletableFuture.wrapInCompletionException(CompletableFuture.java:323) + at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:376) + at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:391) + at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:657) + at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:531) + at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2221) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.handleMessage(JsonRpcClient.java:281) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.lambda$startReader$0(JsonRpcClient.java:256) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614) + at java.base/java.lang.Thread.run(Thread.java:1474) +Caused by: com.github.copilot.JsonRpcException: Request session.resume failed with message: Session not found: non-existent-session-id + ... 7 more + +May 27, 2026 9:58:58 PM com.github.copilot.LoggingHelpers logTiming +WARNING: CopilotClient.resumeSession failed. Elapsed=PT0.015S, SessionId=non-existent-session-id +java.util.concurrent.CompletionException: com.github.copilot.JsonRpcException: Request session.resume failed with message: Session not found: non-existent-session-id + at java.base/java.util.concurrent.CompletableFuture.wrapInCompletionException(CompletableFuture.java:323) + at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:376) + at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:391) + at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:657) + at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:531) + at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2221) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.handleMessage(JsonRpcClient.java:281) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.lambda$startReader$0(JsonRpcClient.java:256) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614) + at java.base/java.lang.Thread.run(Thread.java:1474) +Caused by: com.github.copilot.JsonRpcException: Request session.resume failed with message: Session not found: non-existent-session-id + ... 7 more + +May 27, 2026 9:58:58 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_have_stateful_conversation' expects prompts: [What is 1+1?, Now if you double that, what do you get?] +May 27, 2026 9:59:00 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +May 27, 2026 9:59:02 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_resume_a_session_using_the_same_client' expects prompts: [What is 1+1?, Now if you double that, what do you get?] +May 27, 2026 9:59:04 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_create_a_session_with_excludedtools' expects prompts: [What is 1+1?] +May 27, 2026 9:59:06 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_create_a_session_with_replaced_systemmessage_config' expects prompts: [What is your full name?] +May 27, 2026 9:59:08 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_list_sessions' expects prompts: [Say hello, Say goodbye] +May 27, 2026 9:59:09 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/send_returns_immediately_while_events_stream_in_background' expects prompts: [Run 'sleep 2 && echo done'] +May 27, 2026 10:00:11 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'session/should_receive_session_events' expects prompts: [What is 100+200?] +[ERROR] Tests run: 23, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 107.9 s <<< FAILURE! -- in com.github.copilot.CopilotSessionTest +[ERROR] com.github.copilot.CopilotSessionTest.testSendReturnsImmediatelyWhileEventsStreamInBackground -- Time elapsed: 61.59 s <<< ERROR! +java.util.concurrent.TimeoutException + at java.base/java.util.concurrent.CompletableFuture.timedGet(CompletableFuture.java:1981) + at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2116) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.CopilotSessionTest.testSendReturnsImmediatelyWhileEventsStreamInBackground(CopilotSessionTest.java:215) + at java.base/java.lang.reflect.Method.invoke(Method.java:565) + at java.base/java.util.ArrayList.forEach(ArrayList.java:1604) + at java.base/java.util.ArrayList.forEach(ArrayList.java:1604) + +[INFO] Running com.github.copilot.CreateSessionReKeyEntryTest +May 27, 2026 10:00:13 PM com.github.copilot.LoggingHelpers logTiming +WARNING: JsonRpc.invoke JSON-RPC request finished. Elapsed=PT0.085S, Method=session.options.update, RequestId=2, Status=Failed +java.util.concurrent.CompletionException: com.github.copilot.JsonRpcException: simulated options update failure + at java.base/java.util.concurrent.CompletableFuture.wrapInCompletionException(CompletableFuture.java:323) + at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:376) + at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:391) + at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:657) + at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:531) + at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2221) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.handleMessage(JsonRpcClient.java:281) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.lambda$startReader$0(JsonRpcClient.java:256) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614) + at java.base/java.lang.Thread.run(Thread.java:1474) +Caused by: com.github.copilot.JsonRpcException: simulated options update failure + ... 7 more + +May 27, 2026 10:00:13 PM com.github.copilot.CopilotClient lambda$updateSessionOptionsForMode$1 +WARNING: session.options.update failed for session server-returned-id +java.util.concurrent.CompletionException: com.github.copilot.JsonRpcException: simulated options update failure + at java.base/java.util.concurrent.CompletableFuture.wrapInCompletionException(CompletableFuture.java:323) + at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:376) + at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:391) + at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:657) + at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:531) + at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2221) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.handleMessage(JsonRpcClient.java:281) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.lambda$startReader$0(JsonRpcClient.java:256) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614) + at java.base/java.lang.Thread.run(Thread.java:1474) +Caused by: com.github.copilot.JsonRpcException: simulated options update failure + ... 7 more + +May 27, 2026 10:00:18 PM com.github.copilot.LoggingHelpers logTiming +WARNING: CopilotClient.createSession failed. Elapsed=PT5.099S, SessionId=client-supplied-id +java.util.concurrent.CompletionException: com.github.copilot.JsonRpcException: simulated options update failure + at java.base/java.util.concurrent.CompletableFuture.wrapInCompletionException(CompletableFuture.java:323) + at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:376) + at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:391) + at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:657) + at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:531) + at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2221) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.handleMessage(JsonRpcClient.java:281) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.lambda$startReader$0(JsonRpcClient.java:256) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614) + at java.base/java.lang.Thread.run(Thread.java:1474) +Caused by: com.github.copilot.JsonRpcException: simulated options update failure + ... 7 more + +[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 5.303 s -- in com.github.copilot.CreateSessionReKeyEntryTest +[INFO] Running com.github.copilot.DataObjectCoverageTest +[INFO] Tests run: 24, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.055 s -- in com.github.copilot.DataObjectCoverageTest +[INFO] Running com.github.copilot.DocumentationSamplesTest +[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.008 s -- in com.github.copilot.DocumentationSamplesTest +[INFO] Running com.github.copilot.ElicitationTest +[INFO] Tests run: 14, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.052 s -- in com.github.copilot.ElicitationTest +[INFO] Running com.github.copilot.ErrorHandlingTest +May 27, 2026 10:00:19 PM com.github.copilot.ErrorHandlingTest testPermissionHandlerErrors_sessionErrorEventContainsDetails +INFO: Running test: testPermissionHandlerErrors_sessionErrorEventContainsDetails +May 27, 2026 10:00:19 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'permissions/permission_handler_errors' expects prompts: [Run 'echo test'. If you can't, say 'failed'.] +May 27, 2026 10:00:22 PM com.github.copilot.CopilotSession lambda$executePermissionAndRespondAsync$0 +WARNING: Error executing permission handler for requestId=e0603035-c8e3-4d93-813a-ecb5fb1da5e9 +java.lang.RuntimeException: Test error message + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.ErrorHandlingTest.lambda$testPermissionHandlerErrors_sessionErrorEventContainsDetails$0(ErrorHandlingTest.java:178) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.CopilotSession.lambda$executePermissionAndRespondAsync$0(CopilotSession.java:940) + at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1825) + at java.base/java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1817) + at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:511) + at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1450) + at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:2019) + at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:187) + +May 27, 2026 10:00:22 PM com.github.copilot.ErrorHandlingTest testHandlesToolCallingErrors_sessionContinuesAfterToolError +INFO: Running test: testHandlesToolCallingErrors_sessionContinuesAfterToolError +May 27, 2026 10:00:22 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'tools/handles_tool_calling_errors' expects prompts: [What is my location? If you can't find out, just say 'unknown'.] +May 27, 2026 10:00:24 PM com.github.copilot.ErrorHandlingTest testHandlesToolCallingErrors_toolReturnsFailureResult +INFO: Running test: testHandlesToolCallingErrors_toolReturnsFailureResult +May 27, 2026 10:00:24 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'tools/handles_tool_calling_errors' expects prompts: [What is my location? If you can't find out, just say 'unknown'.] +May 27, 2026 10:00:26 PM com.github.copilot.ErrorHandlingTest testHandlesToolCallingErrors_toolErrorDoesNotCrashSession +INFO: Running test: testHandlesToolCallingErrors_toolErrorDoesNotCrashSession +May 27, 2026 10:00:26 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'tools/handles_tool_calling_errors' expects prompts: [What is my location? If you can't find out, just say 'unknown'.] +May 27, 2026 10:00:28 PM com.github.copilot.ErrorHandlingTest testShouldHandlePermissionHandlerErrorsGracefully_deniesPermission +INFO: Running test: testShouldHandlePermissionHandlerErrorsGracefully_deniesPermission +May 27, 2026 10:00:28 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'permissions/should_handle_permission_handler_errors_gracefully' expects prompts: [Run 'echo test'. If you can't, say 'failed'.] +May 27, 2026 10:00:30 PM com.github.copilot.CopilotSession lambda$executePermissionAndRespondAsync$0 +WARNING: Error executing permission handler for requestId=4a93893d-a35e-417c-8892-a7cf926f855f +java.lang.RuntimeException: Permission handler crashed + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.ErrorHandlingTest.lambda$testShouldHandlePermissionHandlerErrorsGracefully_deniesPermission$0(ErrorHandlingTest.java:139) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.CopilotSession.lambda$executePermissionAndRespondAsync$0(CopilotSession.java:940) + at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1825) + at java.base/java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1817) + at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:511) + at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1450) + at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:2019) + at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:187) + +[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 11.89 s -- in com.github.copilot.ErrorHandlingTest +[INFO] Running com.github.copilot.EventFidelityTest +May 27, 2026 10:00:31 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'event_fidelity/should_emit_assistant_usage_event_after_model_call' expects prompts: [What is 5+5? Reply with just the number.] +May 27, 2026 10:00:33 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'event_fidelity/should_emit_session_usage_info_event_after_model_call' expects prompts: [What is 5+5? Reply with just the number.] +[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 5.690 s -- in com.github.copilot.EventFidelityTest +[INFO] Running com.github.copilot.ExecutorWiringTest +May 27, 2026 10:00:37 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'ask_user/should_invoke_user_input_handler_when_model_uses_ask_user_tool' expects prompts: [Ask me to choose between 'Option A' and 'Option B' using the ask_user tool. Wait for my response before] +May 27, 2026 10:00:39 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'tools/invokes_custom_tool' expects prompts: [Use encrypt_string to encrypt this string: Hello] +May 27, 2026 10:00:41 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'hooks/invoke_pre_tool_use_hook_when_model_runs_a_tool' expects prompts: [Read the contents of hello.txt and tell me what it says] +May 27, 2026 10:00:43 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'permissions/permission_handler_for_write_operations' expects prompts: [Edit test.txt and replace 'original' with 'modified'] +May 27, 2026 10:00:46 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'tools/invokes_custom_tool' expects prompts: [Use encrypt_string to encrypt this string: Hello] +May 27, 2026 10:00:48 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'tools/invokes_custom_tool' expects prompts: [Use encrypt_string to encrypt this string: Hello] +[INFO] Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 14.33 s -- in com.github.copilot.ExecutorWiringTest +[INFO] Running com.github.copilot.ForwardCompatibilityTest +[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.017 s -- in com.github.copilot.ForwardCompatibilityTest +[INFO] Running com.github.copilot.HooksTest +May 27, 2026 10:00:51 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'hooks/invoke_both_hooks_for_single_tool_call' expects prompts: [Read the contents of both.txt] +May 27, 2026 10:00:54 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'hooks/invoke_pre_tool_use_hook_when_model_runs_a_tool' expects prompts: [Read the contents of hello.txt and tell me what it says] +May 27, 2026 10:00:56 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'hooks/invoke_post_tool_use_hook_after_model_runs_a_tool' expects prompts: [Read the contents of world.txt and tell me what it says] +May 27, 2026 10:00:58 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'hooks/deny_tool_execution_when_pre_tool_use_returns_deny' expects prompts: [Edit protected.txt and replace 'Original' with 'Modified'] +[INFO] Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 10.81 s -- in com.github.copilot.HooksTest +[INFO] Running com.github.copilot.InternalExecutorProviderTest +[INFO] Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.415 s -- in com.github.copilot.InternalExecutorProviderTest +[INFO] Running com.github.copilot.JsonIncludeNonNullTest +[INFO] Tests run: 18, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.041 s -- in com.github.copilot.JsonIncludeNonNullTest +[INFO] Running com.github.copilot.JsonRpcClientTest +May 27, 2026 10:01:01 PM com.github.copilot.LoggingHelpers logTiming +WARNING: JsonRpc.invoke JSON-RPC request finished. Elapsed=PT0.001S, Method=test, RequestId=1, Status=Failed +java.util.concurrent.CompletionException: com.github.copilot.JsonRpcException: Unknown error + at java.base/java.util.concurrent.CompletableFuture.wrapInCompletionException(CompletableFuture.java:323) + at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:376) + at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:391) + at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:657) + at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:531) + at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2221) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.handleMessage(JsonRpcClient.java:281) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.lambda$startReader$0(JsonRpcClient.java:256) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614) + at java.base/java.lang.Thread.run(Thread.java:1474) +Caused by: com.github.copilot.JsonRpcException: Unknown error + ... 7 more + +May 27, 2026 10:01:01 PM com.github.copilot.JsonRpcClient handleMessage +SEVERE: Error handling method fail.method +java.lang.RuntimeException: handler error + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClientTest.lambda$testHandlerThrowsExceptionWithId$0(JsonRpcClientTest.java:317) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.handleMessage(JsonRpcClient.java:299) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.lambda$startReader$0(JsonRpcClient.java:256) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614) + at java.base/java.lang.Thread.run(Thread.java:1474) + +May 27, 2026 10:01:01 PM com.github.copilot.JsonRpcClient handleMessage +SEVERE: Error parsing JSON-RPC message +com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'not': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false') + at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1] + at com.fasterxml.jackson.core@2.21.3/com.fasterxml.jackson.core.JsonParser._constructReadException(JsonParser.java:2675) + at com.fasterxml.jackson.core@2.21.3/com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:3025) + at com.fasterxml.jackson.core@2.21.3/com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2995) + at com.fasterxml.jackson.core@2.21.3/com.fasterxml.jackson.core.json.ReaderBasedJsonParser._matchToken(ReaderBasedJsonParser.java:2760) + at com.fasterxml.jackson.core@2.21.3/com.fasterxml.jackson.core.json.ReaderBasedJsonParser._matchNull(ReaderBasedJsonParser.java:2746) + at com.fasterxml.jackson.core@2.21.3/com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken(ReaderBasedJsonParser.java:750) + at com.fasterxml.jackson.databind@2.21.3/com.fasterxml.jackson.databind.ObjectMapper._readTreeAndClose(ObjectMapper.java:5081) + at com.fasterxml.jackson.databind@2.21.3/com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:3349) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.handleMessage(JsonRpcClient.java:268) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.lambda$startReader$0(JsonRpcClient.java:256) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614) + at java.base/java.lang.Thread.run(Thread.java:1474) + +May 27, 2026 10:01:01 PM com.github.copilot.JsonRpcClient handleMessage +SEVERE: Error handling method fail.notify +java.lang.RuntimeException: notify error + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClientTest.lambda$testHandlerThrowsExceptionWithoutId$0(JsonRpcClientTest.java:336) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.handleMessage(JsonRpcClient.java:299) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.lambda$startReader$0(JsonRpcClient.java:256) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614) + at java.base/java.lang.Thread.run(Thread.java:1474) + +May 27, 2026 10:01:02 PM com.github.copilot.JsonRpcClient lambda$startReader$0 +SEVERE: Error in JSON-RPC reader +java.io.IOException: Stream closed + at java.base/java.io.BufferedInputStream.ensureOpen(BufferedInputStream.java:207) + at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:379) + at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:289) + at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:308) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.lambda$startReader$0(JsonRpcClient.java:211) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614) + at java.base/java.lang.Thread.run(Thread.java:1474) + +May 27, 2026 10:01:02 PM com.github.copilot.JsonRpcClient lambda$startReader$0 +SEVERE: Error in JSON-RPC reader +java.net.SocketException: Socket closed + at java.base/sun.nio.ch.NioSocketImpl.ensureOpenAndConnected(NioSocketImpl.java:162) + at java.base/sun.nio.ch.NioSocketImpl.beginRead(NioSocketImpl.java:225) + at java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:293) + at java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:354) + at java.base/sun.nio.ch.NioSocketImpl$1.read(NioSocketImpl.java:798) + at java.base/java.net.Socket$SocketInputStream.implRead(Socket.java:974) + at java.base/java.net.Socket$SocketInputStream.read(Socket.java:964) + at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:289) + at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:308) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.lambda$startReader$0(JsonRpcClient.java:211) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614) + at java.base/java.lang.Thread.run(Thread.java:1474) + +May 27, 2026 10:01:02 PM com.github.copilot.LoggingHelpers logTiming +WARNING: JsonRpc.invoke JSON-RPC request finished. Elapsed=PT0.000S, Method=test, RequestId=1, Status=Failed +java.util.concurrent.CompletionException: java.net.SocketException: Socket closed + at java.base/java.util.concurrent.CompletableFuture.wrapInCompletionException(CompletableFuture.java:323) + at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:376) + at java.base/java.util.concurrent.CompletableFuture.uniApplyNow(CompletableFuture.java:695) + at java.base/java.util.concurrent.CompletableFuture.uniApplyStage(CompletableFuture.java:683) + at java.base/java.util.concurrent.CompletableFuture.thenApply(CompletableFuture.java:2227) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.invoke(JsonRpcClient.java:125) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClientTest.testInvokeWithSendFailure(JsonRpcClientTest.java:204) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) + at java.base/java.lang.reflect.Method.invoke(Method.java:565) + at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:786) + at org.junit.platform.commons.support.ReflectionSupport.invokeMethod(ReflectionSupport.java:514) + at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131) + at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:161) + at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:152) + at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:91) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:112) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:94) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:93) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:87) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$4(TestMethodTestDescriptor.java:221) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:217) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:159) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:70) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:157) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:147) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:145) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:144) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:101) + at java.base/java.util.ArrayList.forEach(ArrayList.java:1604) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:161) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:147) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:145) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:144) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:101) + at java.base/java.util.ArrayList.forEach(ArrayList.java:1604) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:161) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:147) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:145) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:144) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:101) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35) + at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) + at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.executeEngine(EngineExecutionOrchestrator.java:230) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.failOrExecuteEngine(EngineExecutionOrchestrator.java:204) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:172) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:101) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:64) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:150) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:63) + at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:109) + at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:91) + at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:47) + at org.junit.platform.launcher.core.InterceptingLauncher.lambda$execute$1(InterceptingLauncher.java:39) + at org.junit.platform.launcher.core.ClasspathAlignmentCheckingLauncherInterceptor.intercept(ClasspathAlignmentCheckingLauncherInterceptor.java:25) + at org.junit.platform.launcher.core.InterceptingLauncher.execute(InterceptingLauncher.java:38) + at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:47) + at org.apache.maven.surefire.junitplatform.LauncherAdapter.executeWithoutCancellationToken(LauncherAdapter.java:60) + at org.apache.maven.surefire.junitplatform.LauncherAdapter.execute(LauncherAdapter.java:52) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.execute(JUnitPlatformProvider.java:203) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:168) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:136) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385) + at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162) + at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495) +Caused by: java.net.SocketException: Socket closed + at java.base/sun.nio.ch.NioSocketImpl.ensureOpenAndConnected(NioSocketImpl.java:162) + at java.base/sun.nio.ch.NioSocketImpl.beginWrite(NioSocketImpl.java:370) + at java.base/sun.nio.ch.NioSocketImpl.implWrite(NioSocketImpl.java:415) + at java.base/sun.nio.ch.NioSocketImpl.write(NioSocketImpl.java:448) + at java.base/sun.nio.ch.NioSocketImpl$2.write(NioSocketImpl.java:821) + at java.base/java.net.Socket$SocketOutputStream.implWrite(Socket.java:1086) + at java.base/java.net.Socket$SocketOutputStream.write(Socket.java:1076) + at java.base/java.io.OutputStream.write(OutputStream.java:124) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.sendMessage(JsonRpcClient.java:189) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.invoke(JsonRpcClient.java:119) + ... 77 more + +May 27, 2026 10:01:02 PM com.github.copilot.LoggingHelpers logTiming +WARNING: JsonRpc.invoke JSON-RPC request finished. Elapsed=PT0.000S, Method=test, RequestId=1, Status=Failed +java.util.concurrent.CompletionException: java.io.IOException: Client closed + at java.base/java.util.concurrent.CompletableFuture.wrapInCompletionException(CompletableFuture.java:323) + at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:376) + at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:391) + at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:657) + at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:531) + at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2221) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.lambda$close$0(JsonRpcClient.java:332) + at java.base/java.util.concurrent.ConcurrentHashMap.forEach(ConcurrentHashMap.java:1619) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.close(JsonRpcClient.java:332) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClientTest.testCloseWithPendingRequests(JsonRpcClientTest.java:449) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) + at java.base/java.lang.reflect.Method.invoke(Method.java:565) + at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:786) + at org.junit.platform.commons.support.ReflectionSupport.invokeMethod(ReflectionSupport.java:514) + at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131) + at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:161) + at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:152) + at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:91) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:112) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:94) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:93) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:87) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$4(TestMethodTestDescriptor.java:221) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:217) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:159) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:70) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:157) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:147) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:145) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:144) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:101) + at java.base/java.util.ArrayList.forEach(ArrayList.java:1604) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:161) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:147) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:145) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:144) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:101) + at java.base/java.util.ArrayList.forEach(ArrayList.java:1604) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:161) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:147) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:145) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:144) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:101) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35) + at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) + at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.executeEngine(EngineExecutionOrchestrator.java:230) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.failOrExecuteEngine(EngineExecutionOrchestrator.java:204) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:172) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:101) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:64) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:150) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:63) + at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:109) + at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:91) + at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:47) + at org.junit.platform.launcher.core.InterceptingLauncher.lambda$execute$1(InterceptingLauncher.java:39) + at org.junit.platform.launcher.core.ClasspathAlignmentCheckingLauncherInterceptor.intercept(ClasspathAlignmentCheckingLauncherInterceptor.java:25) + at org.junit.platform.launcher.core.InterceptingLauncher.execute(InterceptingLauncher.java:38) + at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:47) + at org.apache.maven.surefire.junitplatform.LauncherAdapter.executeWithoutCancellationToken(LauncherAdapter.java:60) + at org.apache.maven.surefire.junitplatform.LauncherAdapter.execute(LauncherAdapter.java:52) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.execute(JUnitPlatformProvider.java:203) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:168) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:136) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385) + at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162) + at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495) +Caused by: java.io.IOException: Client closed + ... 80 more + +May 27, 2026 10:01:02 PM com.github.copilot.LoggingHelpers logTiming +WARNING: JsonRpc.invoke JSON-RPC request finished. Elapsed=PT0.001S, Method=test, RequestId=1, Status=Failed +java.util.concurrent.CompletionException: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.lang.Integer` from Object value (token `JsonToken.START_OBJECT`) + at [Source: UNKNOWN; byte offset: #UNKNOWN] + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.lambda$invoke$0(JsonRpcClient.java:137) + at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:667) + at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:531) + at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2206) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.handleMessage(JsonRpcClient.java:283) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.lambda$startReader$0(JsonRpcClient.java:256) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614) + at java.base/java.lang.Thread.run(Thread.java:1474) +Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.lang.Integer` from Object value (token `JsonToken.START_OBJECT`) + at [Source: UNKNOWN; byte offset: #UNKNOWN] + at com.fasterxml.jackson.databind@2.21.3/com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:72) + at com.fasterxml.jackson.databind@2.21.3/com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1814) + at com.fasterxml.jackson.databind@2.21.3/com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1588) + at com.fasterxml.jackson.databind@2.21.3/com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1535) + at com.fasterxml.jackson.databind@2.21.3/com.fasterxml.jackson.databind.deser.std.StdDeserializer._parseInteger(StdDeserializer.java:867) + at com.fasterxml.jackson.databind@2.21.3/com.fasterxml.jackson.databind.deser.std.NumberDeserializers$IntegerDeserializer.deserialize(NumberDeserializers.java:543) + at com.fasterxml.jackson.databind@2.21.3/com.fasterxml.jackson.databind.deser.std.NumberDeserializers$IntegerDeserializer.deserialize(NumberDeserializers.java:518) + at com.fasterxml.jackson.databind@2.21.3/com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:342) + at com.fasterxml.jackson.databind@2.21.3/com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:5023) + at com.fasterxml.jackson.databind@2.21.3/com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3104) + at com.fasterxml.jackson.databind@2.21.3/com.fasterxml.jackson.databind.ObjectMapper.treeToValue(ObjectMapper.java:3572) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.lambda$invoke$0(JsonRpcClient.java:129) + ... 10 more + +May 27, 2026 10:01:02 PM com.github.copilot.LoggingHelpers logTiming +WARNING: JsonRpc.invoke JSON-RPC request finished. Elapsed=PT0.000S, Method=test, RequestId=1, Status=Failed +java.util.concurrent.CompletionException: com.github.copilot.JsonRpcException: bad request + at java.base/java.util.concurrent.CompletableFuture.wrapInCompletionException(CompletableFuture.java:323) + at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:376) + at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:391) + at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:657) + at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:531) + at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2221) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.handleMessage(JsonRpcClient.java:281) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.JsonRpcClient.lambda$startReader$0(JsonRpcClient.java:256) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614) + at java.base/java.lang.Thread.run(Thread.java:1474) +Caused by: com.github.copilot.JsonRpcException: bad request + ... 7 more + +[INFO] Tests run: 23, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.433 s -- in com.github.copilot.JsonRpcClientTest +[INFO] Running com.github.copilot.LifecycleEventManagerTest +May 27, 2026 10:01:02 PM com.github.copilot.LifecycleEventManager dispatch +WARNING: Lifecycle handler error +java.lang.RuntimeException: wildcard handler error + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.LifecycleEventManagerTest.lambda$wildcardHandlerExceptionDoesNotPreventOtherHandlers$0(LifecycleEventManagerTest.java:147) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.LifecycleEventManager.dispatch(LifecycleEventManager.java:98) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.LifecycleEventManagerTest.lambda$wildcardHandlerExceptionDoesNotPreventOtherHandlers$1(LifecycleEventManagerTest.java:151) + at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:49) + at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:36) + at org.junit.jupiter.api.Assertions.assertDoesNotThrow(Assertions.java:3199) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.LifecycleEventManagerTest.wildcardHandlerExceptionDoesNotPreventOtherHandlers(LifecycleEventManagerTest.java:151) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) + at java.base/java.lang.reflect.Method.invoke(Method.java:565) + at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:786) + at org.junit.platform.commons.support.ReflectionSupport.invokeMethod(ReflectionSupport.java:514) + at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131) + at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:161) + at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:152) + at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:91) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:112) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:94) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:93) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:87) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$4(TestMethodTestDescriptor.java:221) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:217) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:159) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:70) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:157) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:147) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:145) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:144) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:101) + at java.base/java.util.ArrayList.forEach(ArrayList.java:1604) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:161) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:147) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:145) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:144) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:101) + at java.base/java.util.ArrayList.forEach(ArrayList.java:1604) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:161) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:147) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:145) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:144) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:101) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35) + at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) + at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.executeEngine(EngineExecutionOrchestrator.java:230) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.failOrExecuteEngine(EngineExecutionOrchestrator.java:204) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:172) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:101) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:64) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:150) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:63) + at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:109) + at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:91) + at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:47) + at org.junit.platform.launcher.core.InterceptingLauncher.lambda$execute$1(InterceptingLauncher.java:39) + at org.junit.platform.launcher.core.ClasspathAlignmentCheckingLauncherInterceptor.intercept(ClasspathAlignmentCheckingLauncherInterceptor.java:25) + at org.junit.platform.launcher.core.InterceptingLauncher.execute(InterceptingLauncher.java:38) + at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:47) + at org.apache.maven.surefire.junitplatform.LauncherAdapter.executeWithoutCancellationToken(LauncherAdapter.java:60) + at org.apache.maven.surefire.junitplatform.LauncherAdapter.execute(LauncherAdapter.java:52) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.execute(JUnitPlatformProvider.java:203) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:168) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:136) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385) + at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162) + at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495) + +May 27, 2026 10:01:02 PM com.github.copilot.LifecycleEventManager dispatch +WARNING: Lifecycle handler error +java.lang.RuntimeException: typed error + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.LifecycleEventManagerTest.lambda$typedAndWildcardErrorsDoNotAffectEachOther$0(LifecycleEventManagerTest.java:161) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.LifecycleEventManager.dispatch(LifecycleEventManager.java:90) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.LifecycleEventManagerTest.lambda$typedAndWildcardErrorsDoNotAffectEachOther$1(LifecycleEventManagerTest.java:166) + at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:49) + at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:36) + at org.junit.jupiter.api.Assertions.assertDoesNotThrow(Assertions.java:3199) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.LifecycleEventManagerTest.typedAndWildcardErrorsDoNotAffectEachOther(LifecycleEventManagerTest.java:166) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) + at java.base/java.lang.reflect.Method.invoke(Method.java:565) + at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:786) + at org.junit.platform.commons.support.ReflectionSupport.invokeMethod(ReflectionSupport.java:514) + at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131) + at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:161) + at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:152) + at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:91) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:112) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:94) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:93) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:87) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$4(TestMethodTestDescriptor.java:221) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:217) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:159) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:70) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:157) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:147) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:145) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:144) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:101) + at java.base/java.util.ArrayList.forEach(ArrayList.java:1604) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:161) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:147) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:145) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:144) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:101) + at java.base/java.util.ArrayList.forEach(ArrayList.java:1604) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:161) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:147) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:145) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:144) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:101) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35) + at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) + at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.executeEngine(EngineExecutionOrchestrator.java:230) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.failOrExecuteEngine(EngineExecutionOrchestrator.java:204) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:172) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:101) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:64) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:150) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:63) + at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:109) + at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:91) + at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:47) + at org.junit.platform.launcher.core.InterceptingLauncher.lambda$execute$1(InterceptingLauncher.java:39) + at org.junit.platform.launcher.core.ClasspathAlignmentCheckingLauncherInterceptor.intercept(ClasspathAlignmentCheckingLauncherInterceptor.java:25) + at org.junit.platform.launcher.core.InterceptingLauncher.execute(InterceptingLauncher.java:38) + at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:47) + at org.apache.maven.surefire.junitplatform.LauncherAdapter.executeWithoutCancellationToken(LauncherAdapter.java:60) + at org.apache.maven.surefire.junitplatform.LauncherAdapter.execute(LauncherAdapter.java:52) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.execute(JUnitPlatformProvider.java:203) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:168) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:136) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385) + at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162) + at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495) + +May 27, 2026 10:01:02 PM com.github.copilot.LifecycleEventManager dispatch +WARNING: Lifecycle handler error +java.lang.RuntimeException: typed handler error + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.LifecycleEventManagerTest.lambda$typedHandlerExceptionDoesNotPreventOtherHandlers$0(LifecycleEventManagerTest.java:133) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.LifecycleEventManager.dispatch(LifecycleEventManager.java:90) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.LifecycleEventManagerTest.lambda$typedHandlerExceptionDoesNotPreventOtherHandlers$1(LifecycleEventManagerTest.java:138) + at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:49) + at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:36) + at org.junit.jupiter.api.Assertions.assertDoesNotThrow(Assertions.java:3199) + at com.github.copilot.java@1.0.0-beta-java.5-SNAPSHOT/com.github.copilot.LifecycleEventManagerTest.typedHandlerExceptionDoesNotPreventOtherHandlers(LifecycleEventManagerTest.java:138) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) + at java.base/java.lang.reflect.Method.invoke(Method.java:565) + at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:786) + at org.junit.platform.commons.support.ReflectionSupport.invokeMethod(ReflectionSupport.java:514) + at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131) + at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:161) + at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:152) + at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:91) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:112) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:94) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45) + at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:93) + at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:87) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$4(TestMethodTestDescriptor.java:221) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:217) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:159) + at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:70) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:157) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:147) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:145) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:144) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:101) + at java.base/java.util.ArrayList.forEach(ArrayList.java:1604) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:161) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:147) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:145) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:144) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:101) + at java.base/java.util.ArrayList.forEach(ArrayList.java:1604) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:161) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:147) + at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:145) + at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:144) + at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:101) + at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35) + at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) + at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.executeEngine(EngineExecutionOrchestrator.java:230) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.failOrExecuteEngine(EngineExecutionOrchestrator.java:204) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:172) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:101) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:64) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:150) + at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:63) + at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:109) + at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:91) + at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:47) + at org.junit.platform.launcher.core.InterceptingLauncher.lambda$execute$1(InterceptingLauncher.java:39) + at org.junit.platform.launcher.core.ClasspathAlignmentCheckingLauncherInterceptor.intercept(ClasspathAlignmentCheckingLauncherInterceptor.java:25) + at org.junit.platform.launcher.core.InterceptingLauncher.execute(InterceptingLauncher.java:38) + at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:47) + at org.apache.maven.surefire.junitplatform.LauncherAdapter.executeWithoutCancellationToken(LauncherAdapter.java:60) + at org.apache.maven.surefire.junitplatform.LauncherAdapter.execute(LauncherAdapter.java:52) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.execute(JUnitPlatformProvider.java:203) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:168) + at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:136) + at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385) + at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162) + at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507) + at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495) + +[INFO] Tests run: 12, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.038 s -- in com.github.copilot.LifecycleEventManagerTest +[INFO] Running com.github.copilot.McpAndAgentsTest +May 27, 2026 10:01:04 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'mcp_and_agents/should_accept_mcp_server_configuration_on_session_resume' expects prompts: [What is 1+1?] +May 27, 2026 10:01:07 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'mcp_and_agents/should_accept_mcp_server_configuration_on_session_create' expects prompts: [What is 2+2?] +May 27, 2026 10:01:10 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'mcp_and_agents/should_accept_mcp_server_configuration_on_session_create' expects prompts: [What is 2+2?] +May 27, 2026 10:01:14 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'mcp_and_agents/should_accept_custom_agent_configuration_on_session_create' expects prompts: [What is 5+5?] +May 27, 2026 10:01:16 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'mcp_and_agents/should_accept_custom_agent_configuration_on_session_create' expects prompts: [What is 5+5?] +May 27, 2026 10:01:18 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'mcp_and_agents/should_accept_both_mcp_servers_and_custom_agents' expects prompts: [What is 7+7?] +May 27, 2026 10:01:20 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'mcp_and_agents/should_accept_custom_agent_configuration_on_session_resume' expects prompts: [What is 1+1?, What is 6+6?] +May 27, 2026 10:01:23 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'mcp_and_agents/should_accept_custom_agent_configuration_on_session_create' expects prompts: [What is 5+5?] +May 27, 2026 10:01:24 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'mcp_and_agents/should_accept_both_mcp_servers_and_custom_agents' expects prompts: [What is 7+7?] +May 27, 2026 10:01:27 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'mcp_and_agents/should_accept_defaultagent_configuration_on_session_resume' expects prompts: [What is 3+3?, What is 4+4?] +May 27, 2026 10:01:29 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'mcp_and_agents/should_hide_excluded_tools_from_default_agent' expects prompts: [Do you have access to a tool called secret_tool? Answer yes or no.] +May 27, 2026 10:01:31 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'mcp_and_agents/should_accept_mcp_server_configuration_on_session_create' expects prompts: [What is 2+2?] +[INFO] Tests run: 12, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 30.27 s -- in com.github.copilot.McpAndAgentsTest +[INFO] Running com.github.copilot.MessageAttachmentTest +[INFO] Tests run: 12, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.029 s -- in com.github.copilot.MessageAttachmentTest +[INFO] Running com.github.copilot.MetadataApiTest +[INFO] Tests run: 11, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 5.999 s -- in com.github.copilot.MetadataApiTest +[INFO] Running com.github.copilot.ModeHandlersTest +May 27, 2026 10:01:40 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'mode_handlers/should_invoke_exit_plan_mode_handler_when_model_uses_tool' expects prompts: [Create a brief implementation plan for adding a greeting.txt file, then request approval with exit_plan_mode.] +May 27, 2026 10:01:42 PM com.github.copilot.E2ETestContext configureForTest +INFO: Configured snapshot 'mode_handlers/should_invoke_auto_mode_switch_handler_when_rate_limited' expects prompts: [Explain that auto mode recovered from a rate limit in one short sentence.] +[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 12.15 s -- in com.github.copilot.ModeHandlersTest +[INFO] Running com.github.copilot.ModelInfoTest +[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.007 s -- in com.github.copilot.ModelInfoTest +[INFO] Running com.github.copilot.ModuleDescriptorTest +[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.005 s -- in com.github.copilot.ModuleDescriptorTest +[INFO] Running com.github.copilot.OptionalApiAndJacksonTest +[INFO] Tests run: 51, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.067 s -- in com.github.copilot.OptionalApiAndJacksonTest +[INFO] Running com.github.copilot.PerSessionAuthTest +[CapiProxy stderr] Error in proxying request: Error: ReplayingCapiProxy not yet initialized. Either pass filePath and workDir to the constructor, or post configuration to /config before making other HTTP requests. +[CapiProxy stderr] at (/home/edburns/workareas/copilot-sdk/java/target/copilot-sdk/test/harness/replayingCapiProxy.ts:244:17) +[CapiProxy stderr] at iife (/home/edburns/workareas/copilot-sdk/java/target/copilot-sdk/test/harness/util.ts:6:10) +[CapiProxy stderr] at ReplayingCapiProxy.performRequest (/home/edburns/workareas/copilot-sdk/java/target/copilot-sdk/test/harness/replayingCapiProxy.ts:172:10) +[CapiProxy stderr] at IncomingMessage. (/home/edburns/workareas/copilot-sdk/java/target/copilot-sdk/test/harness/capturingHttpProxy.ts:58:14) +[CapiProxy stderr] at IncomingMessage.emit (node:events:508:28) +[CapiProxy stderr] at endReadableNT (node:internal/streams/readable:1729:12) +[CapiProxy stderr] at process.processTicksAndRejections (node:internal/process/task_queues:90:21) diff --git a/java/README.md b/java/README.md index 61e59c8d6..9b23400eb 100644 --- a/java/README.md +++ b/java/README.md @@ -21,7 +21,7 @@ Java SDK for programmatic control of GitHub Copilot CLI, enabling you to build A ### Requirements -- Java 17 or later. **JDK 25 recommended**. Selecting JDK 25 enables the use of virtual threads, as shown in the [Quick Start](#quick-start). +- Java 17 or later. **JDK 25 recommended**. On JDK 25 and later, the SDK automatically uses virtual threads for its default internal executor. - GitHub Copilot CLI 1.0.17 or later installed and in `PATH` (or provide custom `cliPath`) ### Maven @@ -66,23 +66,16 @@ implementation 'com.github:copilot-sdk-java:1.0.0-beta-java.4' import com.github.copilot.CopilotClient; import com.github.copilot.generated.AssistantMessageEvent; import com.github.copilot.generated.SessionUsageInfoEvent; -import com.github.copilot.rpc.CopilotClientOptions; import com.github.copilot.rpc.MessageOptions; import com.github.copilot.rpc.PermissionHandler; import com.github.copilot.rpc.SessionConfig; -import java.util.concurrent.Executors; - public class CopilotSDK { public static void main(String[] args) throws Exception { var lastMessage = new String[]{null}; // Create and start client - try (var client = new CopilotClient()) { // JDK 25+: comment out this line - // JDK 25+: uncomment the following 3 lines for virtual thread support - // var options = new CopilotClientOptions() - // .setExecutor(Executors.newVirtualThreadPerTaskExecutor()); - // try (var client = new CopilotClient(options)) { + try (var client = new CopilotClient()) { client.start().get(); // Create a session diff --git a/java/pom.xml b/java/pom.xml index a21ae9013..9ab34b022 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -245,6 +245,18 @@ + + print-test-jdk-banner + process-test-classes + + run + + + + + + + @@ -307,6 +319,33 @@ + + + org.apache.maven.plugins + maven-failsafe-plugin + 3.5.5 + + + + integration-test + verify + + + + + + ${project.build.directory} + ${project.build.finalName} + ${project.build.testOutputDirectory} + + + org.apache.maven.plugins maven-surefire-plugin @@ -447,6 +486,10 @@ ${project.build.directory}/jacoco-test-results/sdk-tests.exec ${project.reporting.outputDirectory}/jacoco-coverage + + + META-INF/versions/**/*.class + @@ -489,6 +532,44 @@ true + + org.apache.maven.plugins + maven-enforcer-plugin + 3.5.0 + + + enforce-jdk25 + + enforce + + + + + [25,) + JDK 25+ is required to build the Multi-Release JAR with the virtual-thread overlay. + + + + + + verify-multi-release-overlay + verify + + enforce + + + + + + ${project.build.outputDirectory}/META-INF/versions/25/com/github/copilot/InternalExecutorProvider.class + + Multi-Release JAR overlay missing: META-INF/versions/25/com/github/copilot/InternalExecutorProvider.class was not compiled. Ensure the build runs on JDK 25+. + + + + + + @@ -507,6 +588,88 @@ -XX:+EnableDynamicAgentLoading + + java25-multi-release + + [25,) + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + compile-java25 + compile + + compile + + + 25 + false + + ${project.basedir}/src/main/java25 + + true + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + true + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + + + verify-java25-overlay + package + + run + + + + + + + + + +JDK 25 multi-release overlay class is missing from the packaged JAR. +Expected entry: META-INF/versions/25/com/github/copilot/InternalExecutorProvider.class +JAR: ${project.build.directory}/${project.build.finalName}.jar + +This usually means the 'java25-multi-release' Maven profile did not activate +(e.g. the build is running on a JDK older than 25) or maven-compiler-plugin +did not produce the multi-release output. Re-build on JDK 25+ and verify the +'compile-java25' execution ran during the 'compile' phase. + + + + + + + + + skip-test-harness diff --git a/java/src/main/java/com/github/copilot/CopilotClient.java b/java/src/main/java/com/github/copilot/CopilotClient.java index ff6b3ccb8..2780a481f 100644 --- a/java/src/main/java/com/github/copilot/CopilotClient.java +++ b/java/src/main/java/com/github/copilot/CopilotClient.java @@ -14,6 +14,7 @@ import java.util.concurrent.CompletionException; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeUnit; import java.util.logging.Level; @@ -80,7 +81,24 @@ public final class CopilotClient implements AutoCloseable { */ public static final int AUTOCLOSEABLE_TIMEOUT_SECONDS = 10; private static final int FORCE_KILL_TIMEOUT_SECONDS = 10; + + /** + * One-shot dispatcher used to run the owned-executor shutdown off any caller + * thread that might itself belong to that executor (e.g. the + * {@link #forceStop()} continuation, which is chained off async work scheduled + * on the internal executor). Spawning a fresh daemon thread guarantees + * {@link java.util.concurrent.ExecutorService#awaitTermination(long, TimeUnit)} + * is never called from inside the very executor it is waiting on. + */ + private static final Executor SHUTDOWN_DISPATCHER = runnable -> { + Thread t = new Thread(runnable, "copilot-client-shutdown"); + t.setDaemon(true); + t.start(); + }; + private final CopilotClientOptions options; + private final Executor executor; + private final boolean executorCanBeShutdown; private final CliServerManager serverManager; private final LifecycleEventManager lifecycleManager = new LifecycleEventManager(); private final Map sessions = new ConcurrentHashMap<>(); @@ -168,6 +186,10 @@ public CopilotClient(CopilotClientOptions options) { this.optionsPort = null; } + InternalExecutorProvider executorProvider = new InternalExecutorProvider(this.options.getExecutor()); + this.executor = executorProvider.get(); + this.executorCanBeShutdown = executorProvider.canBeShutdown(); + this.serverManager = new CliServerManager(this.options); this.serverManager.setConnectionToken(this.effectiveConnectionToken); } @@ -191,11 +213,8 @@ public CompletableFuture start() { private CompletableFuture startCore() { LOG.fine("Starting Copilot client"); - Executor exec = options.getExecutor(); try { - return exec != null - ? CompletableFuture.supplyAsync(this::startCoreBody, exec) - : CompletableFuture.supplyAsync(this::startCoreBody); + return CompletableFuture.supplyAsync(this::startCoreBody, executor); } catch (RejectedExecutionException e) { return CompletableFuture.failedFuture(e); } @@ -224,8 +243,7 @@ private Connection startCoreBody() { Connection connection = new Connection(rpc, process, new ServerRpc(rpc::invoke)); // Register handlers for server-to-client calls - RpcHandlerDispatcher dispatcher = new RpcHandlerDispatcher(sessions, lifecycleManager::dispatch, - options.getExecutor()); + RpcHandlerDispatcher dispatcher = new RpcHandlerDispatcher(sessions, lifecycleManager::dispatch, executor); dispatcher.registerHandlers(rpc); // Verify protocol version @@ -323,7 +341,6 @@ private static boolean isUnsupportedConnectMethod(JsonRpcException ex) { */ public CompletableFuture stop() { var closeFutures = new ArrayList>(); - Executor exec = options.getExecutor(); for (CopilotSession session : new ArrayList<>(sessions.values())) { Runnable closeTask = () -> { @@ -335,9 +352,7 @@ public CompletableFuture stop() { }; CompletableFuture future; try { - future = exec != null - ? CompletableFuture.runAsync(closeTask, exec) - : CompletableFuture.runAsync(closeTask); + future = CompletableFuture.runAsync(closeTask, executor); } catch (RejectedExecutionException e) { LOG.log(Level.WARNING, "Executor rejected session close task; closing inline", e); closeTask.run(); @@ -359,7 +374,12 @@ public CompletableFuture stop() { public CompletableFuture forceStop() { disposed = true; sessions.clear(); - return cleanupConnection(); + // Dispatch the blocking shutdownOwnedExecutor() on a dedicated thread: + // cleanupConnection() is chained off async work running on the owned + // executor, so a plain whenComplete(...) here could land the awaitTermination + // call on one of the very threads it is waiting to drain, forcing the full + // AUTOCLOSEABLE_TIMEOUT_SECONDS timeout followed by shutdownNow(). + return cleanupConnection().whenCompleteAsync((ignored, error) -> shutdownOwnedExecutor(), SHUTDOWN_DISPATCHER); } private CompletableFuture cleanupConnection() { @@ -470,9 +490,7 @@ public CompletableFuture createSession(SessionConfig config) { java.util.function.Function initializeSession = sid -> { long setupNanos = System.nanoTime(); var s = new CopilotSession(sid, connection.rpc); - if (options.getExecutor() != null) { - s.setExecutor(options.getExecutor()); - } + s.setExecutor(executor); SessionRequestBuilder.configureSession(s, config); if (extracted.transformCallbacks() != null) { s.registerTransformCallbacks(extracted.transformCallbacks()); @@ -596,9 +614,7 @@ public CompletableFuture resumeSession(String sessionId, ResumeS // Register the session before the RPC call to avoid missing early events. long setupNanos = System.nanoTime(); var session = new CopilotSession(sessionId, connection.rpc); - if (options.getExecutor() != null) { - session.setExecutor(options.getExecutor()); - } + session.setExecutor(executor); SessionRequestBuilder.configureSession(session, config); sessions.put(sessionId, session); LoggingHelpers.logTiming(LOG, Level.FINE, @@ -1142,6 +1158,44 @@ public void close() { stop().get(AUTOCLOSEABLE_TIMEOUT_SECONDS, TimeUnit.SECONDS); } catch (Exception e) { LOG.log(Level.FINE, "Error during close", e); + } finally { + shutdownOwnedExecutor(); + } + } + + private void shutdownOwnedExecutor() { + if (!executorCanBeShutdown) { + return; + } + + ExecutorService serviceToShutdown = executor instanceof ExecutorService es ? es : null; + if (serviceToShutdown == null) { + LOG.log(Level.FINE, "Executor is not an ExecutorService; skipping shutdown"); + return; + } + + // Short-circuit when the owned executor is already shut down. close() and + // forceStop() can each call this method (e.g. forceStop() invoked before a + // subsequent close() in user code), and re-entering shutdown() + + // awaitTermination() + // is redundant. Logging at FINE aids diagnostics without spamming normal + // output. + if (serviceToShutdown.isShutdown()) { + LOG.log(Level.FINE, "Owned executor was already shut down; skipping redundant shutdown call."); + return; + } + + serviceToShutdown.shutdown(); + try { + if (!serviceToShutdown.awaitTermination(AUTOCLOSEABLE_TIMEOUT_SECONDS, TimeUnit.SECONDS)) { + LOG.log(Level.FINE, "Owned executor did not terminate within {0} seconds; forcing shutdown.", + AUTOCLOSEABLE_TIMEOUT_SECONDS); + serviceToShutdown.shutdownNow(); + } + } catch (InterruptedException e) { + serviceToShutdown.shutdownNow(); + Thread.currentThread().interrupt(); + LOG.log(Level.FINE, "Interrupted while waiting for owned executor to terminate", e); } } diff --git a/java/src/main/java/com/github/copilot/InternalExecutorProvider.java b/java/src/main/java/com/github/copilot/InternalExecutorProvider.java new file mode 100644 index 000000000..284965513 --- /dev/null +++ b/java/src/main/java/com/github/copilot/InternalExecutorProvider.java @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------------------------------------------*/ + +package com.github.copilot; + +import java.util.concurrent.Executor; +import java.util.concurrent.ForkJoinPool; + +/** + * Resolves the {@link Executor} used by {@link CopilotClient} for internal + * asynchronous work. + * + *

+ * This is the baseline (JDK 17+) implementation. When no + * user-provided executor is supplied, it falls back to + * {@link ForkJoinPool#commonPool()}, which is shared with the rest of the JVM + * and therefore never owned by the SDK. + * + *

+ * Multi-release JAR contract. This class has a sibling variant + * at {@code src/main/java25/com/github/copilot/InternalExecutorProvider.java} + * that is compiled with {@code --release 25} into {@code META-INF/versions/25/} + * and selected automatically by the JVM on JDK 25+. Any change to the + * package-private surface of this class + * ({@link #InternalExecutorProvider(Executor) constructor}, {@link #get()}, + * {@link #canBeShutdown()}) must be mirrored in both source + * trees. The two implementations must remain behaviourally + * interchangeable from the caller's perspective; only the default-executor + * strategy and ownership semantics differ. + * + * @implNote Maintainers: when editing this file, also edit + * {@code src/main/java25/com/github/copilot/InternalExecutorProvider.java}. + * The packaged JAR is verified at build time (see the + * {@code java25-multi-release} profile in {@code pom.xml}) to ensure + * the JDK 25 overlay is present. + */ +final class InternalExecutorProvider { + + private final Executor executor; + + InternalExecutorProvider(Executor userProvided) { + if (userProvided != null) { + this.executor = userProvided; + } else { + this.executor = ForkJoinPool.commonPool(); + } + } + + Executor get() { + return executor; + } + + boolean canBeShutdown() { + // Since we are using ForkJoinPool.commonPool() or user provided only, + // we should not attempt to shut it down + return false; + } + +} diff --git a/java/src/main/java/com/github/copilot/rpc/CopilotClientOptions.java b/java/src/main/java/com/github/copilot/rpc/CopilotClientOptions.java index 69464aa72..941467059 100644 --- a/java/src/main/java/com/github/copilot/rpc/CopilotClientOptions.java +++ b/java/src/main/java/com/github/copilot/rpc/CopilotClientOptions.java @@ -288,9 +288,11 @@ public CopilotClientOptions setEnvironment(Map environment) { /** * Gets the executor used for internal asynchronous operations. + *

+ * Returns {@code null} if no executor has been explicitly set, indicating that + * the SDK should use its default executor strategy. * - * @return the executor, or {@code null} to use the default - * {@code ForkJoinPool.commonPool()} + * @return the executor, or {@code null} if using SDK defaults */ public Executor getExecutor() { return executor; @@ -300,15 +302,18 @@ public Executor getExecutor() { * Sets the executor used for internal asynchronous operations. *

* When provided, the SDK uses this executor for all internal - * {@code CompletableFuture} combinators instead of the default - * {@code ForkJoinPool.commonPool()}. This allows callers to isolate SDK work - * onto a dedicated thread pool or integrate with container-managed threading. + * {@code CompletableFuture} combinators. This allows callers to isolate SDK + * work onto a dedicated thread pool or integrate with container-managed + * threading. *

- * Passing {@code null} reverts to the default {@code ForkJoinPool.commonPool()} - * behavior. + * The SDK will not shut down a user-provided executor. If you pass a custom + * {@code ExecutorService}, you remain responsible for shutting it down. + *

+ * If not set (or set to {@code null}), the SDK uses its default executor: + * virtual threads on JDK 25+, {@code ForkJoinPool.commonPool()} on older JDKs. * * @param executor - * the executor to use, or {@code null} for the default + * the executor to use, or {@code null} for SDK defaults * @return this options instance for fluent chaining */ public CopilotClientOptions setExecutor(Executor executor) { diff --git a/java/src/main/java25/com/github/copilot/InternalExecutorProvider.java b/java/src/main/java25/com/github/copilot/InternalExecutorProvider.java new file mode 100644 index 000000000..10878bb0c --- /dev/null +++ b/java/src/main/java25/com/github/copilot/InternalExecutorProvider.java @@ -0,0 +1,65 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------------------------------------------*/ + +package com.github.copilot; + +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.ForkJoinPool; + +/** + * Resolves the {@link Executor} used by {@link CopilotClient} for internal + * asynchronous work. + * + *

This is the JDK 25+ multi-release variant. It is + * compiled with {@code --release 25} into + * {@code META-INF/versions/25/com/github/copilot/InternalExecutorProvider.class} + * inside the packaged JAR and is automatically loaded in preference to the + * baseline class when the JVM runtime feature version is 25 or greater. + * When no user-provided executor is supplied, it creates an SDK-owned + * {@link Executors#newVirtualThreadPerTaskExecutor() virtual-thread executor} + * that is shut down by {@link CopilotClient#close()}. + * + *

Multi-release JAR contract. This class is the + * JDK 25 sibling of the baseline implementation at + * {@code src/main/java/com/github/copilot/InternalExecutorProvider.java}. + * The package-private surface of both classes + * ({@link #InternalExecutorProvider(Executor) constructor}, + * {@link #get()}, {@link #canBeShutdown()}) must be kept in + * lock-step; only the default-executor strategy and ownership + * semantics differ. + * + * @implNote + * Maintainers: when editing this file, also edit + * {@code src/main/java/com/github/copilot/InternalExecutorProvider.java}. + * The packaged JAR is verified at build time (see the + * {@code java25-multi-release} profile in {@code pom.xml}) to ensure this + * overlay class is present. + */ +final class InternalExecutorProvider { + + private final Executor executor; + private final boolean owned; + + InternalExecutorProvider(Executor userProvided) { + if (userProvided != null) { + this.executor = userProvided; + this.owned = false; + } else { + this.executor = Executors.newVirtualThreadPerTaskExecutor(); + this.owned = true; + } + } + + Executor get() { + return executor; + } + + boolean canBeShutdown() { + // We can only shut down the executor if we created it (i.e., if it's owned) + // such as when using Executors.newVirtualThreadPerTaskExecutor(), + // which creates an executor that we are responsible for shutting down. + return owned; + } +} diff --git a/java/src/test/java/com/github/copilot/InternalExecutorProviderIT.java b/java/src/test/java/com/github/copilot/InternalExecutorProviderIT.java new file mode 100644 index 000000000..1cc6b482e --- /dev/null +++ b/java/src/test/java/com/github/copilot/InternalExecutorProviderIT.java @@ -0,0 +1,108 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------------------------------------------*/ + +package com.github.copilot; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.junit.jupiter.api.Test; + +/** + * Failsafe integration test that asserts the multi-release behaviour of + * {@link InternalExecutorProvider} against the actually packaged JAR. + *

+ * Runs after {@code package}, when {@code target/${finalName}.jar} exists with + * its real {@code Multi-Release: true} manifest and (on JDK 25+ builds) the + * {@code META-INF/versions/25/} override produced by {@code maven-jar-plugin}. + *

+ * The test spawns a child JVM with the packaged JAR plus {@code test-classes} + * on the classpath, runs {@link InternalExecutorProviderProbe}, and asserts + * that the executor selected for the current runtime matches expectations. + */ +class InternalExecutorProviderIT { + + @Test + void packagedJarSelectsExecutorPerRuntimeVersion() throws Exception { + Path packagedJar = locatePackagedJar(); + Path testClasses = locateTestClassesDir(); + String javaBin = locateJavaBinary(); + + String classpath = packagedJar.toString() + File.pathSeparator + testClasses.toString(); + Process process = new ProcessBuilder(javaBin, "-cp", classpath, + "com.github.copilot.InternalExecutorProviderProbe").redirectErrorStream(true).start(); + + String output; + try { + output = new String(process.getInputStream().readAllBytes(), StandardCharsets.UTF_8); + assertTrue(process.waitFor(30, TimeUnit.SECONDS), "Probe JVM did not exit within 30s. Output:\n" + output); + } finally { + if (process.isAlive()) { + process.destroyForcibly(); + } + } + + assertEquals(0, process.exitValue(), "Probe exited non-zero. Output:\n" + output); + + Map kv = parseKeyValues(output); + String featureRaw = kv.get("feature"); + assertNotNull(featureRaw, "Probe did not report 'feature'. Output:\n" + output); + int feature = Integer.parseInt(featureRaw); + + boolean expectOwnedVirtual = feature >= 25; + assertEquals(String.valueOf(expectOwnedVirtual), kv.get("canBeShutdown"), + "canBeShutdown mismatch for JDK feature=" + feature + ". Output:\n" + output); + assertEquals(String.valueOf(expectOwnedVirtual), kv.get("virtual"), + "virtual mismatch for JDK feature=" + feature + ". Output:\n" + output); + } + + private static Path locatePackagedJar() { + String buildDir = System.getProperty("project.build.directory"); + String finalName = System.getProperty("project.build.finalName"); + assertNotNull(buildDir, "System property 'project.build.directory' must be set by failsafe"); + assertNotNull(finalName, "System property 'project.build.finalName' must be set by failsafe"); + Path jar = Path.of(buildDir, finalName + ".jar"); + assertTrue(Files.isRegularFile(jar), "Packaged JAR must exist: " + jar); + return jar; + } + + private static Path locateTestClassesDir() { + String testOutput = System.getProperty("project.build.testOutputDirectory"); + assertNotNull(testOutput, "System property 'project.build.testOutputDirectory' must be set by failsafe"); + Path dir = Path.of(testOutput); + assertTrue(Files.isDirectory(dir), "test-classes dir must exist: " + dir); + return dir; + } + + private static String locateJavaBinary() { + Path javaHome = Path.of(System.getProperty("java.home")); + Path candidate = javaHome.resolve("bin").resolve(isWindows() ? "java.exe" : "java"); + assertTrue(Files.isExecutable(candidate), "java binary must be executable: " + candidate); + return candidate.toString(); + } + + private static boolean isWindows() { + return System.getProperty("os.name", "").toLowerCase().contains("win"); + } + + private static Map parseKeyValues(String output) { + Map map = new HashMap<>(); + for (String line : output.split("\\R")) { + int eq = line.indexOf('='); + if (eq > 0) { + map.put(line.substring(0, eq).trim(), line.substring(eq + 1).trim()); + } + } + return map; + } +} diff --git a/java/src/test/java/com/github/copilot/InternalExecutorProviderProbe.java b/java/src/test/java/com/github/copilot/InternalExecutorProviderProbe.java new file mode 100644 index 000000000..85d12f14f --- /dev/null +++ b/java/src/test/java/com/github/copilot/InternalExecutorProviderProbe.java @@ -0,0 +1,74 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------------------------------------------*/ + +package com.github.copilot; + +import java.lang.reflect.Method; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Diagnostic main launched as a separate JVM by + * {@code InternalExecutorProviderIT} to inspect the multi-release behaviour of + * {@link InternalExecutorProvider} against the actually packaged JAR. + *

+ * Lives in the same package as {@link InternalExecutorProvider} so it can use + * its package-private API directly, without reflection. + *

+ * Output format (key=value, one per line): + * + *

+ *   feature=<JDK feature version>
+ *   canBeShutdown=<true|false>
+ *   virtual=<true|false>
+ * 
+ */ +final class InternalExecutorProviderProbe { + + private InternalExecutorProviderProbe() { + } + + public static void main(String[] args) throws Exception { + InternalExecutorProvider provider = new InternalExecutorProvider(null); + Executor executor = provider.get(); + boolean canBeShutdown = provider.canBeShutdown(); + + AtomicBoolean virtual = new AtomicBoolean(); + CountDownLatch latch = new CountDownLatch(1); + executor.execute(() -> { + try { + virtual.set(isCurrentThreadVirtual()); + } finally { + latch.countDown(); + } + }); + + try { + if (!latch.await(5, TimeUnit.SECONDS)) { + System.out.println("error=task-timeout"); + System.exit(2); + } + } finally { + if (executor instanceof ExecutorService es) { + es.shutdownNow(); + } + } + + System.out.println("feature=" + Runtime.version().feature()); + System.out.println("canBeShutdown=" + canBeShutdown); + System.out.println("virtual=" + virtual.get()); + } + + private static boolean isCurrentThreadVirtual() { + try { + Method isVirtual = Thread.class.getMethod("isVirtual"); + return (Boolean) isVirtual.invoke(Thread.currentThread()); + } catch (ReflectiveOperationException e) { + return false; + } + } +} diff --git a/java/src/test/java/com/github/copilot/InternalExecutorProviderTest.java b/java/src/test/java/com/github/copilot/InternalExecutorProviderTest.java new file mode 100644 index 000000000..f1d854cb5 --- /dev/null +++ b/java/src/test/java/com/github/copilot/InternalExecutorProviderTest.java @@ -0,0 +1,55 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------------------------------------------*/ + +package com.github.copilot; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertSame; + +import java.lang.reflect.Modifier; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ForkJoinPool; + +import org.junit.jupiter.api.Test; + +import com.github.copilot.rpc.CopilotClientOptions; + +class InternalExecutorProviderTest { + + @Test + void baseProviderReturnsCommonPool() { + Executor executor = new InternalExecutorProvider(null).get(); + + assertSame(ForkJoinPool.commonPool(), executor); + } + + @Test + void userProvidedExecutorIsNotOwned() { + Executor executor = ForkJoinPool.commonPool(); + + assertFalse(new InternalExecutorProvider(executor).canBeShutdown()); + } + + @Test + void providerIsPackagePrivate() { + assertFalse(Modifier.isPublic(InternalExecutorProvider.class.getModifiers())); + } + + @Test + void clientDoesNotShutDownUserProvidedExecutor() { + ExecutorService executor = Executors.newSingleThreadExecutor(); + try { + try (var client = new CopilotClient(new CopilotClientOptions().setAutoStart(false).setExecutor(executor))) { + assertNotNull(client); + } + + assertFalse(executor.isShutdown()); + } finally { + executor.shutdownNow(); + } + } +}