diff --git a/.lastmerge b/.lastmerge index 600b63a547..83c87fb55d 100644 --- a/.lastmerge +++ b/.lastmerge @@ -1 +1 @@ -e20f5bef125860accb30c60d1b35109371a77f16 +25b15be86c443c776bc2ab057c698a2ef0b67f35 diff --git a/pom.xml b/pom.xml index be73738041..d251fbce6e 100644 --- a/pom.xml +++ b/pom.xml @@ -94,7 +94,7 @@ reference-impl-sync workflow and deal with the subsequent PR. --> - ^1.0.48 + ^1.0.49-1 diff --git a/scripts/codegen/package-lock.json b/scripts/codegen/package-lock.json index 36d7689a71..cee6f09e64 100644 --- a/scripts/codegen/package-lock.json +++ b/scripts/codegen/package-lock.json @@ -6,7 +6,7 @@ "": { "name": "copilot-sdk-java-codegen", "dependencies": { - "@github/copilot": "^1.0.48", + "@github/copilot": "^1.0.49-1", "json-schema": "^0.4.0", "tsx": "^4.20.6" } @@ -428,26 +428,26 @@ } }, "node_modules/@github/copilot": { - "version": "1.0.48", - "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.48.tgz", - "integrity": "sha512-U5SzyTEq376UU9A4Sd3TEKz+Y2nRUd90cLO4Hc1otaB8yFSy9Ur2UVGcI2/wCoodL3a39k6WbdgNzFxr0gWFRQ==", + "version": "1.0.49-1", + "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.49-1.tgz", + "integrity": "sha512-1euPT6WXtLWnoqz1SXHdcqmktucdkfwfZn/Eo4iQ1FAjZo7awuN86rVb1feDwxY4vlSGbzNmK+GDKDgs9qZCDg==", "license": "SEE LICENSE IN LICENSE.md", "bin": { "copilot": "npm-loader.js" }, "optionalDependencies": { - "@github/copilot-darwin-arm64": "1.0.48", - "@github/copilot-darwin-x64": "1.0.48", - "@github/copilot-linux-arm64": "1.0.48", - "@github/copilot-linux-x64": "1.0.48", - "@github/copilot-win32-arm64": "1.0.48", - "@github/copilot-win32-x64": "1.0.48" + "@github/copilot-darwin-arm64": "1.0.49-1", + "@github/copilot-darwin-x64": "1.0.49-1", + "@github/copilot-linux-arm64": "1.0.49-1", + "@github/copilot-linux-x64": "1.0.49-1", + "@github/copilot-win32-arm64": "1.0.49-1", + "@github/copilot-win32-x64": "1.0.49-1" } }, "node_modules/@github/copilot-darwin-arm64": { - "version": "1.0.48", - "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.48.tgz", - "integrity": "sha512-82MLoMQwPVVFM8EYssihFxSEPUYtZADE8rMzQ3jG9HgRg2qjQSfnHQS1mKe64dlXswZUK/onw6/8kjnW5I4pPg==", + "version": "1.0.49-1", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.49-1.tgz", + "integrity": "sha512-EgHdwlkYSJ+RmHAelGGpQxQe5/dgq3BlvToc0VmYEUCWO93ESEql7XBqCWYeASg3USUp8n87kf3mr2eXIECvLA==", "cpu": [ "arm64" ], @@ -461,9 +461,9 @@ } }, "node_modules/@github/copilot-darwin-x64": { - "version": "1.0.48", - "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.48.tgz", - "integrity": "sha512-1VQ5r5F0h8GwboXmZTcutqcJT+iCpPXAF27QqodmpKEvW9aYfG8g9X2kFJOzDZoX+SA3Uaka9qXdYKF2xT6Uog==", + "version": "1.0.49-1", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.49-1.tgz", + "integrity": "sha512-YPtOW5q3vWB9Covn08jxqIdIjcCuJi/MgIlYk1ulKTINi5uK5a6NlsX2mDaGWL/svhDwDlhFEa3oUV41yOjTkg==", "cpu": [ "x64" ], @@ -477,9 +477,9 @@ } }, "node_modules/@github/copilot-linux-arm64": { - "version": "1.0.48", - "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.48.tgz", - "integrity": "sha512-PmsGnb0DZlI+Bf53l9HM1PAHHkUcMyB4y8v/7tnC/jDOV5dGF124n0HnDNfJLOLiJGiQGodthIif6QtPaAxpeA==", + "version": "1.0.49-1", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.49-1.tgz", + "integrity": "sha512-eEh0ec1UlWg8IdV2/3Zaxr/PAA86GclEFUcGNkwc9JceOgw5nhIdytsjCwXJUcRTzHsGrAoTS+Vad1RSvKSmYQ==", "cpu": [ "arm64" ], @@ -493,9 +493,9 @@ } }, "node_modules/@github/copilot-linux-x64": { - "version": "1.0.48", - "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.48.tgz", - "integrity": "sha512-b2cc4euSlke9fYHXXsS2EL9UYbctN0h4lZvtAcKUDY+RCnpYAQOVBZK+c1R9dQrtsT6Z/yUv7PuFPSs8qdtc2Q==", + "version": "1.0.49-1", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.49-1.tgz", + "integrity": "sha512-9+HxOVAbgCqcoyfAXyfaFxgIbAfHWCh699WuOfWViX2fjoKO3V0ZVHEergR4gVEgvnjvnmD0TZhT7+kTzqPK6A==", "cpu": [ "x64" ], @@ -509,9 +509,9 @@ } }, "node_modules/@github/copilot-win32-arm64": { - "version": "1.0.48", - "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.48.tgz", - "integrity": "sha512-VEEOwddtpJ3DTbXGhnK6K8im4ofl9m08q1m/K++sNvWV8wkkOSOQBTiPdyUsuU/TXAoFhb8tZMIJv+6NnMBtMw==", + "version": "1.0.49-1", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.49-1.tgz", + "integrity": "sha512-nsOz2rdk1Il3KJ24x3Hdv27MvotrKygIC/ok6acvq+xFwsYxR5Kt5bL1veBAGZVEG8K+0r2DfHi9NZHazBYK8A==", "cpu": [ "arm64" ], @@ -525,9 +525,9 @@ } }, "node_modules/@github/copilot-win32-x64": { - "version": "1.0.48", - "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.48.tgz", - "integrity": "sha512-93BzvXLPHTyy1gWBXQY/IWIHor4IAwZuuo7/obG80/Qa6U0WeaN9slz/FBJvrsgVNrrRfEID5Xm3At+S6Kj67Q==", + "version": "1.0.49-1", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.49-1.tgz", + "integrity": "sha512-RZbU3GESkfwd8UC1h5AeceVfCOfXjMA+sDKfIUyk8Pl8EukTNtNSf+WEKK1HzSxbxdbIu9DJyBL375JMwDiH4A==", "cpu": [ "x64" ], diff --git a/scripts/codegen/package.json b/scripts/codegen/package.json index 82454e774e..8726bacc12 100644 --- a/scripts/codegen/package.json +++ b/scripts/codegen/package.json @@ -7,7 +7,7 @@ "generate:java": "tsx java.ts" }, "dependencies": { - "@github/copilot": "^1.0.48", + "@github/copilot": "^1.0.49-1", "json-schema": "^0.4.0", "tsx": "^4.20.6" } diff --git a/src/main/java/com/github/copilot/sdk/json/CustomAgentConfig.java b/src/main/java/com/github/copilot/sdk/json/CustomAgentConfig.java index bb9520055e..8fde15ec86 100644 --- a/src/main/java/com/github/copilot/sdk/json/CustomAgentConfig.java +++ b/src/main/java/com/github/copilot/sdk/json/CustomAgentConfig.java @@ -60,6 +60,9 @@ public class CustomAgentConfig { @JsonProperty("skills") private List skills; + @JsonProperty("model") + private String model; + /** * Gets the unique identifier name for this agent. * @@ -255,4 +258,29 @@ public CustomAgentConfig setSkills(List skills) { this.skills = skills; return this; } + + /** + * Gets the model identifier for this agent. + * + * @return the model identifier (e.g., "claude-haiku-4.5"), or {@code null} if + * not set + */ + public String getModel() { + return model; + } + + /** + * Sets the model identifier for this agent. + *

+ * When set, the runtime will attempt to use this model for the agent, falling + * back to the parent session model if unavailable. + * + * @param model + * the model identifier (e.g., "claude-haiku-4.5") + * @return this config for method chaining + */ + public CustomAgentConfig setModel(String model) { + this.model = model; + return this; + } } diff --git a/src/test/java/com/github/copilot/sdk/PermissionsTest.java b/src/test/java/com/github/copilot/sdk/PermissionsTest.java index 041d8181cb..74b96d8493 100644 --- a/src/test/java/com/github/copilot/sdk/PermissionsTest.java +++ b/src/test/java/com/github/copilot/sdk/PermissionsTest.java @@ -112,6 +112,17 @@ void testDenyPermission(TestInfo testInfo) throws Exception { try (CopilotClient client = ctx.createClient()) { CopilotSession session = client.createSession(config).get(); + // Regression check for https://github.com/github/copilot-sdk/issues/1194: + // the reject decision must round-trip through the CLI with its discriminator + // intact so the agent surfaces the user-rejected error to the model. + final boolean[] userRejectedToolCall = {false}; + session.on(ToolExecutionCompleteEvent.class, evt -> { + if (!evt.getData().success() && evt.getData().error() != null && evt.getData().error().message() != null + && evt.getData().error().message().toLowerCase().contains("user rejected")) { + userRejectedToolCall[0] = true; + } + }); + String originalContent = "protected content"; Path testFile = ctx.getWorkDir().resolve("protected.txt"); Files.writeString(testFile, originalContent); @@ -120,6 +131,9 @@ void testDenyPermission(TestInfo testInfo) throws Exception { new MessageOptions().setPrompt("Edit protected.txt and replace 'protected' with 'hacked'.")) .get(60, TimeUnit.SECONDS); + assertTrue(userRejectedToolCall[0], + "Expected a tool.execution_complete event whose error indicates the user rejected the call."); + // Verify the file was NOT modified String content = Files.readString(testFile); assertEquals(originalContent, content, "File should not have been modified");