diff --git a/java/src/test/java/com/github/copilot/e2e/ErgonomicTestTools$$CopilotToolMeta.java b/java/src/test/java/com/github/copilot/e2e/ErgonomicTestTools$$CopilotToolMeta.java index 703a6b010..3e6291984 100644 --- a/java/src/test/java/com/github/copilot/e2e/ErgonomicTestTools$$CopilotToolMeta.java +++ b/java/src/test/java/com/github/copilot/e2e/ErgonomicTestTools$$CopilotToolMeta.java @@ -44,6 +44,25 @@ public List definitions(ErgonomicTestTools instance, ObjectMappe Map args = invocation.getArguments(); String keyword = (String) args.get("keyword"); return CompletableFuture.completedFuture(instance.searchItems(keyword)); + }, null, null, null), + new ToolDefinition("get_status", "Returns the current status", + Map.of("type", "object", "properties", Map.of(), "required", List.of()), invocation -> { + return CompletableFuture.completedFuture(instance.getStatus()); + }, null, null, null), + new ToolDefinition("combine_values", "Combines two values into a single string", Map.of( + "type", "object", "properties", Map + .ofEntries( + Map.entry("value1", + (Map) (Map) withMeta(Map.of("type", "string"), + "First value", null)), + Map.entry("value2", + (Map) (Map) withMeta(Map.of("type", "string"), + "Second value", null))), + "required", List.of("value1", "value2")), invocation -> { + Map args = invocation.getArguments(); + String value1 = (String) args.get("value1"); + String value2 = (String) args.get("value2"); + return CompletableFuture.completedFuture(instance.combineValues(value1, value2)); }, null, null, null)); } } diff --git a/java/src/test/java/com/github/copilot/e2e/ErgonomicTestTools.java b/java/src/test/java/com/github/copilot/e2e/ErgonomicTestTools.java index e70e9b4dc..15b2c087a 100644 --- a/java/src/test/java/com/github/copilot/e2e/ErgonomicTestTools.java +++ b/java/src/test/java/com/github/copilot/e2e/ErgonomicTestTools.java @@ -29,4 +29,15 @@ public String setCurrentPhase(@CopilotToolParam("The phase to transition to") St public String searchItems(@CopilotToolParam("Search keyword") String keyword) { return "Found: " + keyword + " -> item_alpha, item_beta"; } + + @CopilotTool("Returns the current status") + public String getStatus() { + return "Status: OK"; + } + + @CopilotTool("Combines two values into a single string") + public String combineValues(@CopilotToolParam("First value") String value1, + @CopilotToolParam("Second value") String value2) { + return "combined: " + value1 + " + " + value2; + } } diff --git a/java/src/test/java/com/github/copilot/e2e/ErgonomicToolDefinitionIT.java b/java/src/test/java/com/github/copilot/e2e/ErgonomicToolDefinitionIT.java index df031f354..412acd4c4 100644 --- a/java/src/test/java/com/github/copilot/e2e/ErgonomicToolDefinitionIT.java +++ b/java/src/test/java/com/github/copilot/e2e/ErgonomicToolDefinitionIT.java @@ -84,6 +84,120 @@ void ergonomicToolDefinition() throws Exception { } } + @Test + void ergonomicToolArity0() throws Exception { + ctx.configureForTest("tools", "ergonomic_tool_arity0"); + + ErgonomicTestTools tools = new ErgonomicTestTools(); + List toolDefs = ToolDefinition.fromObject(tools); + + try (CopilotClient client = ctx.createClient()) { + CopilotSession session = client + .createSession(new SessionConfig().setOnPermissionRequest(PermissionHandler.APPROVE_ALL) + .setAvailableTools(new ToolSet().addCustom("*")).setTools(toolDefs)) + .get(30, TimeUnit.SECONDS); + + try { + AssistantMessageEvent response = session + .sendAndWait(new MessageOptions().setPrompt("Call get_status and tell me the result."), 60_000) + .get(90, TimeUnit.SECONDS); + + assertNotNull(response, "Expected a response from the assistant"); + String content = response.getData().content().toLowerCase(); + assertTrue(content.contains("ok"), + "Response should mention the status: " + response.getData().content()); + } finally { + session.close(); + } + } + } + + @Test + void ergonomicToolArity2() throws Exception { + ctx.configureForTest("tools", "ergonomic_tool_arity2"); + + ErgonomicTestTools tools = new ErgonomicTestTools(); + List toolDefs = ToolDefinition.fromObject(tools); + + try (CopilotClient client = ctx.createClient()) { + CopilotSession session = client + .createSession(new SessionConfig().setOnPermissionRequest(PermissionHandler.APPROVE_ALL) + .setAvailableTools(new ToolSet().addCustom("*")).setTools(toolDefs)) + .get(30, TimeUnit.SECONDS); + + try { + AssistantMessageEvent response = session.sendAndWait( + new MessageOptions().setPrompt( + "Call combine_values with 'alpha' and 'beta', then report the combined result."), + 60_000).get(90, TimeUnit.SECONDS); + + assertNotNull(response, "Expected a response from the assistant"); + String content = response.getData().content().toLowerCase(); + assertTrue(content.contains("alpha") && content.contains("beta"), + "Response should contain the combined values: " + response.getData().content()); + } finally { + session.close(); + } + } + } + + @Test + void lambdaToolArity0() throws Exception { + ctx.configureForTest("tools", "ergonomic_tool_arity0"); + + ToolDefinition getStatus = ToolDefinition.from("get_status", "Returns the current status", () -> "Status: OK"); + + try (CopilotClient client = ctx.createClient()) { + CopilotSession session = client + .createSession(new SessionConfig().setOnPermissionRequest(PermissionHandler.APPROVE_ALL) + .setAvailableTools(new ToolSet().addCustom("*")).setTools(List.of(getStatus))) + .get(30, TimeUnit.SECONDS); + + try { + AssistantMessageEvent response = session + .sendAndWait(new MessageOptions().setPrompt("Call get_status and tell me the result."), 60_000) + .get(90, TimeUnit.SECONDS); + + assertNotNull(response, "Expected a response from the assistant"); + String content = response.getData().content().toLowerCase(); + assertTrue(content.contains("ok"), + "Response should mention the status: " + response.getData().content()); + } finally { + session.close(); + } + } + } + + @Test + void lambdaToolArity2() throws Exception { + ctx.configureForTest("tools", "ergonomic_tool_arity2"); + + ToolDefinition combineValues = ToolDefinition.from("combine_values", "Combines two values into a single string", + Param.of(String.class, "value1", "First value"), Param.of(String.class, "value2", "Second value"), + (v1, v2) -> "combined: " + v1 + " + " + v2); + + try (CopilotClient client = ctx.createClient()) { + CopilotSession session = client + .createSession(new SessionConfig().setOnPermissionRequest(PermissionHandler.APPROVE_ALL) + .setAvailableTools(new ToolSet().addCustom("*")).setTools(List.of(combineValues))) + .get(30, TimeUnit.SECONDS); + + try { + AssistantMessageEvent response = session.sendAndWait( + new MessageOptions().setPrompt( + "Call combine_values with 'alpha' and 'beta', then report the combined result."), + 60_000).get(90, TimeUnit.SECONDS); + + assertNotNull(response, "Expected a response from the assistant"); + String content = response.getData().content().toLowerCase(); + assertTrue(content.contains("alpha") && content.contains("beta"), + "Response should contain the combined values: " + response.getData().content()); + } finally { + session.close(); + } + } + } + @Test void lambdaToolDefinition() throws Exception { ctx.configureForTest("tools", "ergonomic_tool_definition"); diff --git a/test/snapshots/tools/ergonomic_tool_arity0.yaml b/test/snapshots/tools/ergonomic_tool_arity0.yaml new file mode 100644 index 000000000..a55f48681 --- /dev/null +++ b/test/snapshots/tools/ergonomic_tool_arity0.yaml @@ -0,0 +1,21 @@ +models: + - claude-sonnet-4.5 +conversations: + - messages: + - role: system + content: ${system} + - role: user + content: Call get_status and tell me the result. + - role: assistant + content: I'll call get_status now. + tool_calls: + - id: toolcall_0 + type: function + function: + name: get_status + arguments: '{}' + - role: tool + tool_call_id: toolcall_0 + content: "Status: OK" + - role: assistant + content: "The status is: OK" diff --git a/test/snapshots/tools/ergonomic_tool_arity2.yaml b/test/snapshots/tools/ergonomic_tool_arity2.yaml new file mode 100644 index 000000000..e34c695bd --- /dev/null +++ b/test/snapshots/tools/ergonomic_tool_arity2.yaml @@ -0,0 +1,21 @@ +models: + - claude-sonnet-4.5 +conversations: + - messages: + - role: system + content: ${system} + - role: user + content: Call combine_values with 'alpha' and 'beta', then report the combined result. + - role: assistant + content: I'll call combine_values with those arguments. + tool_calls: + - id: toolcall_0 + type: function + function: + name: combine_values + arguments: '{"value1":"alpha","value2":"beta"}' + - role: tool + tool_call_id: toolcall_0 + content: "combined: alpha + beta" + - role: assistant + content: "The combined result is: alpha + beta"