diff --git a/java/README.md b/java/README.md index 3d1bf7a5b9..dc12887520 100644 --- a/java/README.md +++ b/java/README.md @@ -140,12 +140,12 @@ When you define tools with `@CopilotTool`, parameters of type `ToolInvocation` a ```java import com.github.copilot.rpc.ToolInvocation; import com.github.copilot.tool.CopilotTool; -import com.github.copilot.tool.Param; +import com.github.copilot.tool.CopilotToolParam; class ProgressTools { @CopilotTool("Reports the current phase and session") public String reportProgress( - @Param("Current phase") String phase, + @CopilotToolParam("Current phase") String phase, ToolInvocation invocation) { return "phase=" + phase + ", sessionId=" + invocation.getSessionId(); } @@ -156,13 +156,13 @@ Position examples: ```java @CopilotTool("Invocation first") -public String report(ToolInvocation invocation, @Param("Phase") String phase) { ... } +public String report(ToolInvocation invocation, @CopilotToolParam("Phase") String phase) { ... } @CopilotTool("Invocation only") public String onlyContext(ToolInvocation invocation) { ... } @CopilotTool("Invocation middle") -public String report(@Param("Phase") String phase, ToolInvocation invocation, @Param("Limit") int limit) { ... } +public String report(@CopilotToolParam("Phase") String phase, ToolInvocation invocation, @CopilotToolParam("Limit") int limit) { ... } ``` ## Memory diff --git a/java/docs/adr/adr-005-tool-definition.md b/java/docs/adr/adr-005-tool-definition.md index d389ac134b..e1b4dcc764 100644 --- a/java/docs/adr/adr-005-tool-definition.md +++ b/java/docs/adr/adr-005-tool-definition.md @@ -51,10 +51,10 @@ Explicit `ToolDefinition.create(name, description, schema, handler)` with a hand ### Option 2: Record-as-schema with generic factory -Define a record for the tool's arguments, annotate its components with `@Param`, and use a generic factory method to auto-generate the schema from the record's `RecordComponent[]` metadata: +Define a record for the tool's arguments and use a generic factory method to auto-generate the schema from the record's `RecordComponent[]` metadata. Because `@CopilotToolParam` targets `ElementType.PARAMETER` (method parameters only), it cannot be placed on record components; per-field descriptions are not supported in this option: ```java -record PhaseArgs(@Param("The phase to transition to") Phase phase) {} +record PhaseArgs(Phase phase) {} ToolDefinition.define("set_current_phase", "Sets the current phase of the agent.", @@ -76,18 +76,19 @@ ToolDefinition.define("set_current_phase", - Tool name and description are still explicit string arguments. - Requires a separate record class for every tool's args (even trivial single-param tools). - The handler is still an explicit lambda — the "tool" is not the method itself. +- Per-field descriptions cannot be provided: `@CopilotToolParam` targets method parameters only, not record components. - Nested or complex schemas (arrays of objects, polymorphic types) need additional mapping logic. - No analog in the broader Java ecosystem; Java developers are not accustomed to defining a record per function call. ### Option 3: Annotation-on-method (langchain4j-style) -Annotate existing Java methods with `@Tool` (or a Copilot-specific equivalent) and annotate parameters with `@P`/`@Param`. The framework discovers tools by scanning methods on a given object, auto-generates `ToolSpecification` / `ToolDefinition` from the method signature, and dispatches invocations directly to the annotated method. +Annotate existing Java methods with `@Tool` (or a Copilot-specific equivalent) and annotate parameters with `@P`/`@CopilotToolParam`. The framework discovers tools by scanning methods on a given object, auto-generates `ToolSpecification` / `ToolDefinition` from the method signature, and dispatches invocations directly to the annotated method. ```java class MyTools { @CopilotTool("Sets the current phase of the agent. Use this to report progress.") - String setCurrentPhase(@Param("The phase to transition to") Phase phase) { + String setCurrentPhase(@CopilotToolParam("The phase to transition to") Phase phase) { this.phase = phase; updateUi(); return "Phase set to " + phase; @@ -95,7 +96,7 @@ class MyTools { @CopilotTool(name = "report_intent", value = "Reports the agent's intent", overridesBuiltInTool = true) - String reportIntent(@Param("The intent") String intent) { + String reportIntent(@CopilotToolParam("The intent") String intent) { // ... } } @@ -110,7 +111,7 @@ This is the approach used by [langchain4j](https://github.com/langchain4j/langch **What the framework does automatically:** 1. **Name** — derived from `@CopilotTool(name=...)` or the method name (converted to snake_case). 2. **Description** — from `@CopilotTool("...")` or `@CopilotTool(value="...")`. -3. **Parameter schema** — generated by reflecting on method parameters: types map to JSON Schema types; `@Param` provides descriptions; `Optional` or `@Param(required=false)` marks optional params. +3. **Parameter schema** — generated by reflecting on method parameters: types map to JSON Schema types; `@CopilotToolParam` provides descriptions; `Optional` or `@CopilotToolParam(required=false)` marks optional params. 4. **Handler** — the method itself. The framework deserializes JSON arguments into the method's parameter types and invokes the method reflectively. The return value is serialized back to a string result. **Advantages:** @@ -127,8 +128,8 @@ This is the approach used by [langchain4j](https://github.com/langchain4j/langch - One-time scanning cost at registration time (negligible for typical tool counts). - Return type handling needs a policy: `String` → sent as-is; `void` → "Success"; other types → JSON-serialized. - Async story: methods could return `CompletableFuture` for async tools, or the framework could invoke synchronous methods on a configurable executor. -- New annotation(s) added to the public API surface (`@CopilotTool`, `@Param`). -- Requires `-parameters` javac flag for parameter name preservation (or explicit `@Param(name=...)` — same constraint as langchain4j). +- New annotation(s) added to the public API surface (`@CopilotTool`, `@CopilotToolParam`). +- Requires `-parameters` javac flag for parameter name preservation (or explicit `@CopilotToolParam(name=...)` — same constraint as langchain4j). ## Decision Outcome @@ -141,7 +142,7 @@ This is the approach used by [langchain4j](https://github.com/langchain4j/langch 2. **Minimum viable tool is one annotated method.** With Option 3, the absolute minimum code to define a tool is: ```java @CopilotTool("Gets the weather") - String getWeather(@Param("City") String city) { return weatherApi.get(city); } + String getWeather(@CopilotToolParam("City") String city) { return weatherApi.get(city); } ``` With Option 2, you need a record class *and* a lambda. With Option 1, you need a record class, a Map schema, *and* a lambda. @@ -191,7 +192,7 @@ At runtime, `ToolDefinition.fromObject(myTools)` loads the generated `$$CopilotT ### Compile-time validation Because the processor has full access to the source AST, it can emit compile errors for: -- Missing `@Param` on parameters (when descriptions are required by policy). +- Missing `@CopilotToolParam` on parameters (when descriptions are required by policy). - Unsupported parameter types (types without a clear JSON Schema mapping). - Duplicate tool names within the same class hierarchy. - Invalid annotation combinations (e.g., `overridesBuiltInTool` on a tool with `skipPermission`). @@ -217,14 +218,14 @@ Because the processor has full access to the source AST, it can emit compile err ## Consequences -- New public annotations: `@CopilotTool` and `@Param` (in `com.github.copilot.rpc` or a new `com.github.copilot.tool` package). +- New public annotations: `@CopilotTool` and `@CopilotToolParam` (in `com.github.copilot.rpc` or a new `com.github.copilot.tool` package). - New JSR 269 annotation processor that generates `$$CopilotToolMeta` companion classes at compile time. - New utility: `ToolDefinition.fromObject(Object)` / `ToolDefinition.fromClass(Class)` that loads the generated metadata class (falling back to runtime reflection if the processor was not run). - The existing `ToolDefinition.create(...)` / `ToolDefinition.createOverride(...)` APIs remain unchanged — they become the "low-level" path. - No `-parameters` javac flag requirement for users who run the annotation processor (which happens automatically when the SDK is on the compile classpath). - Async support: methods returning `CompletableFuture` are handled natively; synchronous methods are wrapped in `CompletableFuture.completedFuture(...)` (or dispatched to an executor, TBD). - GraalVM native-image compatibility without additional reflection configuration. -- **Experimental designation:** `@CopilotTool`, `@Param`, `ToolDefinition.fromObject(Object)`, and `ToolDefinition.fromClass(Class)` will all be annotated with `@CopilotExperimental`. This gates adoption behind an explicit opt-in (`-Acopilot.experimental.allowed=true`) until the API surface stabilizes, consistent with the policy established in ADR-004. +- **Experimental designation:** `@CopilotTool`, `@CopilotToolParam`, `ToolDefinition.fromObject(Object)`, and `ToolDefinition.fromClass(Class)` will all be annotated with `@CopilotExperimental`. This gates adoption behind an explicit opt-in (`-Acopilot.experimental.allowed=true`) until the API surface stabilizes, consistent with the policy established in ADR-004. ## Related work items diff --git a/java/src/main/java/com/github/copilot/tool/CopilotTool.java b/java/src/main/java/com/github/copilot/tool/CopilotTool.java index 9cde49b201..0bad327b99 100644 --- a/java/src/main/java/com/github/copilot/tool/CopilotTool.java +++ b/java/src/main/java/com/github/copilot/tool/CopilotTool.java @@ -22,7 +22,8 @@ * *
  * @CopilotTool("Get weather for a location")
- * public CompletableFuture<String> getWeather(@Param(value = "City name", required = true) String location) {
+ * public CompletableFuture<String> getWeather(
+ * 		@CopilotToolParam(value = "City name", required = true) String location) {
  * 	return CompletableFuture.completedFuture("Sunny in " + location);
  * }
  * 
diff --git a/java/src/main/java/com/github/copilot/tool/Param.java b/java/src/main/java/com/github/copilot/tool/CopilotToolParam.java similarity index 82% rename from java/src/main/java/com/github/copilot/tool/Param.java rename to java/src/main/java/com/github/copilot/tool/CopilotToolParam.java index aaef04947f..0b667d9d71 100644 --- a/java/src/main/java/com/github/copilot/tool/Param.java +++ b/java/src/main/java/com/github/copilot/tool/CopilotToolParam.java @@ -21,8 +21,9 @@ * *
  * @CopilotTool("Search for issues")
- * public CompletableFuture<String> searchIssues(@Param(value = "Search query", required = true) String query,
- * 		@Param(value = "Max results", required = false, defaultValue = "10") int limit) {
+ * public CompletableFuture<String> searchIssues(
+ * 		@CopilotToolParam(value = "Search query", required = true) String query,
+ * 		@CopilotToolParam(value = "Max results", required = false, defaultValue = "10") int limit) {
  * 	// ...
  * }
  * 
@@ -33,7 +34,7 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) @CopilotExperimental -public @interface Param { +public @interface CopilotToolParam { /** Parameter description (sent to the model). */ String value() default ""; diff --git a/java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java b/java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java index 3238985aaf..9bf4e99c03 100644 --- a/java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java +++ b/java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java @@ -68,23 +68,23 @@ public boolean process(Set annotations, RoundEnvironment continue; } - // Validate @Param conflicts + // Validate @CopilotToolParam conflicts int toolInvocationParamCount = 0; for (VariableElement param : method.getParameters()) { if (isToolInvocationType(param.asType())) { toolInvocationParamCount++; - if (param.getAnnotation(Param.class) != null) { + if (param.getAnnotation(CopilotToolParam.class) != null) { processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, - "@Param is not supported on ToolInvocation parameters because ToolInvocation is injected runtime context and not part of the tool schema", + "@CopilotToolParam is not supported on ToolInvocation parameters because ToolInvocation is injected runtime context and not part of the tool schema", param); } continue; } - Param paramAnnotation = param.getAnnotation(Param.class); + CopilotToolParam paramAnnotation = param.getAnnotation(CopilotToolParam.class); if (paramAnnotation != null && paramAnnotation.required() && !paramAnnotation.defaultValue().isEmpty()) { processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, - "@Param cannot have both required=true and a non-empty defaultValue", param); + "@CopilotToolParam cannot have both required=true and a non-empty defaultValue", param); } if (paramAnnotation != null && !paramAnnotation.defaultValue().isEmpty()) { String defaultValidationError = validateDefaultValueCompatibility(param.asType(), @@ -96,7 +96,7 @@ public boolean process(Set annotations, RoundEnvironment if (paramAnnotation != null && !paramAnnotation.required() && paramAnnotation.defaultValue().isEmpty() && param.asType().getKind().isPrimitive()) { processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, - "@Param(required=false) primitive parameters must provide defaultValue or use a boxed/Optional type", + "@CopilotToolParam(required=false) primitive parameters must provide defaultValue or use a boxed/Optional type", param); } } @@ -111,17 +111,17 @@ public boolean process(Set annotations, RoundEnvironment if (schemaParameters.size() == 1) { VariableElement singleParam = schemaParameters.get(0); if (isRecord(singleParam.asType())) { - Param paramAnnotation = singleParam.getAnnotation(Param.class); + CopilotToolParam paramAnnotation = singleParam.getAnnotation(CopilotToolParam.class); if (paramAnnotation != null) { if (!paramAnnotation.defaultValue().isEmpty()) { processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, - "@Param(defaultValue=...) is not supported on single-record tool parameters; use record component defaults or a non-record parameter", + "@CopilotToolParam(defaultValue=...) is not supported on single-record tool parameters; use record component defaults or a non-record parameter", singleParam); } if (!paramAnnotation.name().isEmpty() || !paramAnnotation.value().isEmpty() || !paramAnnotation.required()) { processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, - "@Param name/value/required are not supported on single-record tool parameters; annotate record components instead", + "@CopilotToolParam name/value/required are not supported on single-record tool parameters; annotate record components instead", singleParam); } } @@ -235,7 +235,7 @@ private void writeMetaClass(PrintWriter out, String packageName, String simpleCl private boolean needsWithMetaHelper(List methods) { for (ExecutableElement method : methods) { for (VariableElement param : method.getParameters()) { - Param paramAnnotation = param.getAnnotation(Param.class); + CopilotToolParam paramAnnotation = param.getAnnotation(CopilotToolParam.class); if (paramAnnotation != null && (!paramAnnotation.value().isEmpty() || !paramAnnotation.defaultValue().isEmpty())) { return true; @@ -255,7 +255,8 @@ private void writeToolDefinition(PrintWriter out, ExecutableElement method) { boolean skipPermission = annotation.skipPermission(); com.github.copilot.rpc.ToolDefer defer = annotation.defer(); - // Generate schema with @Param metadata (descriptions, names, defaults) + // Generate schema with @CopilotToolParam metadata (descriptions, names, + // defaults) String schemaSource = generateSchemaWithParamMetadata(method.getParameters()); // Generate invocation lambda @@ -296,7 +297,7 @@ private String generateSchemaWithParamMetadata(List p for (VariableElement param : schemaParameters) { String paramName = getParamName(param); TypeMirror paramType = param.asType(); - Param paramAnnotation = param.getAnnotation(Param.class); + CopilotToolParam paramAnnotation = param.getAnnotation(CopilotToolParam.class); // Generate the type schema for this parameter String typeSchema = schemaGenerator.generateSchemaSource(paramType, processingEnv.getTypeUtils(), @@ -338,7 +339,7 @@ private boolean isToolInvocationType(TypeMirror type) { return TOOL_INVOCATION_TYPE.equals(processingEnv.getTypeUtils().erasure(type).toString()); } - private String buildPropertySchema(String typeSchema, Param paramAnnotation, TypeMirror paramType) { + private String buildPropertySchema(String typeSchema, CopilotToolParam paramAnnotation, TypeMirror paramType) { if (paramAnnotation == null) { return typeSchema; } @@ -382,7 +383,7 @@ private String generateLambdaBody(ExecutableElement method) { TypeMirror paramType = param.asType(); // Handle default values - Param paramAnnotation = param.getAnnotation(Param.class); + CopilotToolParam paramAnnotation = param.getAnnotation(CopilotToolParam.class); boolean hasDefault = paramAnnotation != null && !paramAnnotation.defaultValue().isEmpty(); if (hasDefault) { @@ -695,7 +696,7 @@ private String validatePrimitiveDefault(TypeKind kind, String defaultValue) { return null; } } catch (NumberFormatException ex) { - return "@Param defaultValue '" + defaultValue + "' is not valid for " + kind.name().toLowerCase() + return "@CopilotToolParam defaultValue '" + defaultValue + "' is not valid for " + kind.name().toLowerCase() + " parameters"; } } @@ -704,13 +705,13 @@ private String validateBooleanDefault(String defaultValue) { if ("true".equalsIgnoreCase(defaultValue) || "false".equalsIgnoreCase(defaultValue)) { return null; } - return "@Param defaultValue '" + defaultValue + "' is not valid for boolean parameters"; + return "@CopilotToolParam defaultValue '" + defaultValue + "' is not valid for boolean parameters"; } private String validateCharacterDefault(String defaultValue) { return defaultValue != null && defaultValue.length() == 1 ? null - : "@Param defaultValue '" + defaultValue + "' is not valid for char parameters"; + : "@CopilotToolParam defaultValue '" + defaultValue + "' is not valid for char parameters"; } private TypeKind boxedTypeKind(String qualifiedName) { @@ -733,7 +734,7 @@ private TypeKind boxedTypeKind(String qualifiedName) { } private String getParamName(VariableElement param) { - Param paramAnnotation = param.getAnnotation(Param.class); + CopilotToolParam paramAnnotation = param.getAnnotation(CopilotToolParam.class); if (paramAnnotation != null && !paramAnnotation.name().isEmpty()) { return paramAnnotation.name(); } diff --git a/java/src/main/java/com/github/copilot/tool/SchemaGenerator.java b/java/src/main/java/com/github/copilot/tool/SchemaGenerator.java index fb321ae9d2..59336a1e02 100644 --- a/java/src/main/java/com/github/copilot/tool/SchemaGenerator.java +++ b/java/src/main/java/com/github/copilot/tool/SchemaGenerator.java @@ -90,7 +90,7 @@ public String generateParametersSchemaSource(List par propertyEntries.add("Map.entry(\"" + paramName + "\", " + schema + ")"); if (!isOptional) { - Param paramAnnotation = param.getAnnotation(Param.class); + CopilotToolParam paramAnnotation = param.getAnnotation(CopilotToolParam.class); if (paramAnnotation == null || paramAnnotation.required()) { requiredNames.add("\"" + paramName + "\""); } 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 35f191db91..e70e9b4dc2 100644 --- a/java/src/test/java/com/github/copilot/e2e/ErgonomicTestTools.java +++ b/java/src/test/java/com/github/copilot/e2e/ErgonomicTestTools.java @@ -5,7 +5,7 @@ package com.github.copilot.e2e; import com.github.copilot.tool.CopilotTool; -import com.github.copilot.tool.Param; +import com.github.copilot.tool.CopilotToolParam; /** * Tool fixture for the ergonomic {@code @CopilotTool} E2E integration test. @@ -20,13 +20,13 @@ class ErgonomicTestTools { String currentPhase; @CopilotTool("Sets the current phase of the agent") - public String setCurrentPhase(@Param("The phase to transition to") String phase) { + public String setCurrentPhase(@CopilotToolParam("The phase to transition to") String phase) { currentPhase = phase; return "Phase set to " + phase; } @CopilotTool("Search for items by keyword") - public String searchItems(@Param("Search keyword") String keyword) { + public String searchItems(@CopilotToolParam("Search keyword") String keyword) { return "Found: " + keyword + " -> item_alpha, item_beta"; } } diff --git a/java/src/test/java/com/github/copilot/rpc/fixtures/ArgCoercionTools.java b/java/src/test/java/com/github/copilot/rpc/fixtures/ArgCoercionTools.java index 7f85bd2c7b..f19af7bff7 100644 --- a/java/src/test/java/com/github/copilot/rpc/fixtures/ArgCoercionTools.java +++ b/java/src/test/java/com/github/copilot/rpc/fixtures/ArgCoercionTools.java @@ -5,7 +5,7 @@ package com.github.copilot.rpc.fixtures; import com.github.copilot.tool.CopilotTool; -import com.github.copilot.tool.Param; +import com.github.copilot.tool.CopilotToolParam; /** * Fixture testing argument coercion with multiple types including an enum. @@ -17,8 +17,8 @@ public enum Color { } @CopilotTool("Method with mixed argument types") - public String mixedArgs(@Param("Text input") String text, @Param("A count") int count, - @Param("A flag") boolean flag, @Param("A color") Color color) { + public String mixedArgs(@CopilotToolParam("Text input") String text, @CopilotToolParam("A count") int count, + @CopilotToolParam("A flag") boolean flag, @CopilotToolParam("A color") Color color) { return text + "-" + count + "-" + flag + "-" + color.name(); } } diff --git a/java/src/test/java/com/github/copilot/rpc/fixtures/DateTimeTools.java b/java/src/test/java/com/github/copilot/rpc/fixtures/DateTimeTools.java index 541c2c6d8c..f0fdf9fdc8 100644 --- a/java/src/test/java/com/github/copilot/rpc/fixtures/DateTimeTools.java +++ b/java/src/test/java/com/github/copilot/rpc/fixtures/DateTimeTools.java @@ -7,7 +7,7 @@ import java.time.LocalDateTime; import com.github.copilot.tool.CopilotTool; -import com.github.copilot.tool.Param; +import com.github.copilot.tool.CopilotToolParam; /** * Fixture testing java.time argument deserialization via ObjectMapper with @@ -16,7 +16,7 @@ public class DateTimeTools { @CopilotTool("Schedule an event at a given time") - public String scheduleEvent(@Param(value = "When to schedule", required = true) LocalDateTime when) { + public String scheduleEvent(@CopilotToolParam(value = "When to schedule", required = true) LocalDateTime when) { return "Scheduled at " + when.getYear() + "-" + String.format("%02d", when.getMonthValue()) + "-" + String.format("%02d", when.getDayOfMonth()) + "T" + String.format("%02d", when.getHour()) + ":" + String.format("%02d", when.getMinute()); diff --git a/java/src/test/java/com/github/copilot/rpc/fixtures/DefaultValueTools.java b/java/src/test/java/com/github/copilot/rpc/fixtures/DefaultValueTools.java index 6e2c3106ef..942ededd89 100644 --- a/java/src/test/java/com/github/copilot/rpc/fixtures/DefaultValueTools.java +++ b/java/src/test/java/com/github/copilot/rpc/fixtures/DefaultValueTools.java @@ -5,7 +5,7 @@ package com.github.copilot.rpc.fixtures; import com.github.copilot.tool.CopilotTool; -import com.github.copilot.tool.Param; +import com.github.copilot.tool.CopilotToolParam; /** * Fixture testing default parameter values. @@ -13,8 +13,8 @@ public class DefaultValueTools { @CopilotTool("Method with a default value parameter") - public String withDefault(@Param(value = "A label", required = true) String label, - @Param(value = "A count", required = false, defaultValue = "42") int count) { + public String withDefault(@CopilotToolParam(value = "A label", required = true) String label, + @CopilotToolParam(value = "A count", required = false, defaultValue = "42") int count) { return label + ":" + count; } } diff --git a/java/src/test/java/com/github/copilot/rpc/fixtures/InvocationAwareTools.java b/java/src/test/java/com/github/copilot/rpc/fixtures/InvocationAwareTools.java index b3d1ace74d..ac9c9bc78d 100644 --- a/java/src/test/java/com/github/copilot/rpc/fixtures/InvocationAwareTools.java +++ b/java/src/test/java/com/github/copilot/rpc/fixtures/InvocationAwareTools.java @@ -9,7 +9,7 @@ import com.github.copilot.rpc.RecordInvocationArgs; import com.github.copilot.rpc.ToolInvocation; import com.github.copilot.tool.CopilotTool; -import com.github.copilot.tool.Param; +import com.github.copilot.tool.CopilotToolParam; /** * Tool fixture for {@link ToolInvocation} runtime context injection. @@ -17,20 +17,20 @@ public class InvocationAwareTools { @CopilotTool("Reports progress with invocation context") - public String reportProgress(@Param("Current phase") String phase, ToolInvocation invocation) { + public String reportProgress(@CopilotToolParam("Current phase") String phase, ToolInvocation invocation) { return "phase=" + phase + ",sessionId=" + invocation.getSessionId() + ",toolCallId=" + invocation.getToolCallId() + ",toolName=" + invocation.getToolName(); } @CopilotTool("Reports progress asynchronously with invocation context") - public CompletableFuture reportProgressAsync(@Param("Current phase") String phase, + public CompletableFuture reportProgressAsync(@CopilotToolParam("Current phase") String phase, ToolInvocation invocation) { return CompletableFuture.completedFuture("async phase=" + phase + ",sessionId=" + invocation.getSessionId() + ",toolCallId=" + invocation.getToolCallId() + ",toolName=" + invocation.getToolName()); } @CopilotTool("Reports progress with invocation first") - public String reportProgressFirst(ToolInvocation invocation, @Param("Current phase") String phase) { + public String reportProgressFirst(ToolInvocation invocation, @CopilotToolParam("Current phase") String phase) { return "first phase=" + phase + ",sessionId=" + invocation.getSessionId() + ",toolCallId=" + invocation.getToolCallId() + ",toolName=" + invocation.getToolName(); } @@ -42,8 +42,8 @@ public String onlyContext(ToolInvocation invocation) { } @CopilotTool("Reports progress with invocation in the middle") - public String reportProgressMiddle(@Param("Current phase") String phase, ToolInvocation invocation, - @Param("Maximum items") int limit) { + public String reportProgressMiddle(@CopilotToolParam("Current phase") String phase, ToolInvocation invocation, + @CopilotToolParam("Maximum items") int limit) { return "middle phase=" + phase + ",limit=" + limit + ",sessionId=" + invocation.getSessionId() + ",toolCallId=" + invocation.getToolCallId() + ",toolName=" + invocation.getToolName(); } diff --git a/java/src/test/java/com/github/copilot/rpc/fixtures/OptionalParamTools.java b/java/src/test/java/com/github/copilot/rpc/fixtures/OptionalParamTools.java index 98e7dda62a..2986cb1c7c 100644 --- a/java/src/test/java/com/github/copilot/rpc/fixtures/OptionalParamTools.java +++ b/java/src/test/java/com/github/copilot/rpc/fixtures/OptionalParamTools.java @@ -10,7 +10,7 @@ import java.util.OptionalLong; import com.github.copilot.tool.CopilotTool; -import com.github.copilot.tool.Param; +import com.github.copilot.tool.CopilotToolParam; /** * Tool fixture with Optional parameter types for testing correct argument @@ -19,22 +19,25 @@ public class OptionalParamTools { @CopilotTool("Greet with optional title") - public String greetWithTitle(@Param("Name") String name, @Param("Optional title") Optional title) { + public String greetWithTitle(@CopilotToolParam("Name") String name, + @CopilotToolParam("Optional title") Optional title) { return title.map(t -> t + " " + name).orElse(name); } @CopilotTool("Multiply with optional factor") - public String multiply(@Param("Base value") int base, @Param("Optional factor") OptionalInt factor) { + public String multiply(@CopilotToolParam("Base value") int base, + @CopilotToolParam("Optional factor") OptionalInt factor) { return String.valueOf(base * factor.orElse(1)); } @CopilotTool("Scale with optional ratio") - public String scale(@Param("Value") double value, @Param("Optional ratio") OptionalDouble ratio) { + public String scale(@CopilotToolParam("Value") double value, + @CopilotToolParam("Optional ratio") OptionalDouble ratio) { return String.valueOf(value * ratio.orElse(1.0)); } @CopilotTool("Offset with optional delta") - public String offset(@Param("Base") long base, @Param("Optional delta") OptionalLong delta) { + public String offset(@CopilotToolParam("Base") long base, @CopilotToolParam("Optional delta") OptionalLong delta) { return String.valueOf(base + delta.orElse(0L)); } } diff --git a/java/src/test/java/com/github/copilot/rpc/fixtures/OverrideTools.java b/java/src/test/java/com/github/copilot/rpc/fixtures/OverrideTools.java index 5fbb432f92..9900830661 100644 --- a/java/src/test/java/com/github/copilot/rpc/fixtures/OverrideTools.java +++ b/java/src/test/java/com/github/copilot/rpc/fixtures/OverrideTools.java @@ -5,7 +5,7 @@ package com.github.copilot.rpc.fixtures; import com.github.copilot.tool.CopilotTool; -import com.github.copilot.tool.Param; +import com.github.copilot.tool.CopilotToolParam; /** * Fixture testing tool override flag. @@ -13,7 +13,7 @@ public class OverrideTools { @CopilotTool(value = "Custom grep implementation", name = "grep", overridesBuiltInTool = true) - public String customGrep(@Param(value = "Search pattern", required = true) String pattern) { + public String customGrep(@CopilotToolParam(value = "Search pattern", required = true) String pattern) { return "Found: " + pattern; } } diff --git a/java/src/test/java/com/github/copilot/rpc/fixtures/SimpleTools.java b/java/src/test/java/com/github/copilot/rpc/fixtures/SimpleTools.java index 5bdee36e59..5bc3d841e5 100644 --- a/java/src/test/java/com/github/copilot/rpc/fixtures/SimpleTools.java +++ b/java/src/test/java/com/github/copilot/rpc/fixtures/SimpleTools.java @@ -5,7 +5,7 @@ package com.github.copilot.rpc.fixtures; import com.github.copilot.tool.CopilotTool; -import com.github.copilot.tool.Param; +import com.github.copilot.tool.CopilotToolParam; /** * Simple tool fixture with basic String-returning methods. @@ -13,12 +13,13 @@ public class SimpleTools { @CopilotTool("Greets a user by name") - public String greetUser(@Param(value = "The user's name", required = true) String name) { + public String greetUser(@CopilotToolParam(value = "The user's name", required = true) String name) { return "Hello, " + name + "!"; } @CopilotTool("Adds two numbers together") - public String addNumbers(@Param(value = "First number") int a, @Param(value = "Second number") int b) { + public String addNumbers(@CopilotToolParam(value = "First number") int a, + @CopilotToolParam(value = "Second number") int b) { return String.valueOf(a + b); } } diff --git a/java/src/test/java/com/github/copilot/rpc/fixtures/StaticInvocationTools.java b/java/src/test/java/com/github/copilot/rpc/fixtures/StaticInvocationTools.java index cb57290798..a5cba003c1 100644 --- a/java/src/test/java/com/github/copilot/rpc/fixtures/StaticInvocationTools.java +++ b/java/src/test/java/com/github/copilot/rpc/fixtures/StaticInvocationTools.java @@ -6,7 +6,7 @@ import com.github.copilot.rpc.ToolInvocation; import com.github.copilot.tool.CopilotTool; -import com.github.copilot.tool.Param; +import com.github.copilot.tool.CopilotToolParam; /** * Static tool fixture for {@link ToolInvocation} runtime context injection. @@ -14,7 +14,7 @@ public class StaticInvocationTools { @CopilotTool("Returns invocation context from a static tool") - public static String reportStatic(@Param("Current phase") String phase, ToolInvocation invocation) { + public static String reportStatic(@CopilotToolParam("Current phase") String phase, ToolInvocation invocation) { return "phase=" + phase + ",sessionId=" + invocation.getSessionId() + ",toolCallId=" + invocation.getToolCallId() + ",toolName=" + invocation.getToolName(); } diff --git a/java/src/test/java/com/github/copilot/rpc/fixtures/StaticTools.java b/java/src/test/java/com/github/copilot/rpc/fixtures/StaticTools.java index 7e681aa469..9caef593df 100644 --- a/java/src/test/java/com/github/copilot/rpc/fixtures/StaticTools.java +++ b/java/src/test/java/com/github/copilot/rpc/fixtures/StaticTools.java @@ -5,7 +5,7 @@ package com.github.copilot.rpc.fixtures; import com.github.copilot.tool.CopilotTool; -import com.github.copilot.tool.Param; +import com.github.copilot.tool.CopilotToolParam; /** * Tool fixture with a static {@code @CopilotTool} method, used to test @@ -14,7 +14,7 @@ public class StaticTools { @CopilotTool("Returns a greeting for the given name") - public static String greet(@Param(value = "The name to greet", required = true) String name) { + public static String greet(@CopilotToolParam(value = "The name to greet", required = true) String name) { return "Hi, " + name + "!"; } } diff --git a/java/src/test/java/com/github/copilot/tool/CopilotToolAnnotationTest.java b/java/src/test/java/com/github/copilot/tool/CopilotToolAnnotationTest.java index 9052c6b1c9..649a4bd6c4 100644 --- a/java/src/test/java/com/github/copilot/tool/CopilotToolAnnotationTest.java +++ b/java/src/test/java/com/github/copilot/tool/CopilotToolAnnotationTest.java @@ -22,7 +22,7 @@ import com.github.copilot.rpc.ToolDefer; /** - * Unit tests for {@link CopilotTool} and {@link Param} annotations. + * Unit tests for {@link CopilotTool} and {@link CopilotToolParam} annotations. */ public class CopilotToolAnnotationTest { @@ -81,34 +81,34 @@ void copilotToolDefaultValues() throws Exception { assertEquals(ToolDefer.NONE, deferMethod.getDefaultValue()); } - // --- @Param attribute verification --- + // --- @CopilotToolParam attribute verification --- @Test void paramHasRuntimeRetention() { - Retention retention = Param.class.getAnnotation(Retention.class); + Retention retention = CopilotToolParam.class.getAnnotation(Retention.class); assertNotNull(retention); assertEquals(RetentionPolicy.RUNTIME, retention.value()); } @Test void paramTargetsParameter() { - Target target = Param.class.getAnnotation(Target.class); + Target target = CopilotToolParam.class.getAnnotation(Target.class); assertNotNull(target); assertArrayEquals(new ElementType[]{ElementType.PARAMETER}, target.value()); } @Test void paramDefaultValues() throws Exception { - Method valueMethod = Param.class.getDeclaredMethod("value"); + Method valueMethod = CopilotToolParam.class.getDeclaredMethod("value"); assertEquals("", valueMethod.getDefaultValue()); - Method nameMethod = Param.class.getDeclaredMethod("name"); + Method nameMethod = CopilotToolParam.class.getDeclaredMethod("name"); assertEquals("", nameMethod.getDefaultValue()); - Method requiredMethod = Param.class.getDeclaredMethod("required"); + Method requiredMethod = CopilotToolParam.class.getDeclaredMethod("required"); assertEquals(true, requiredMethod.getDefaultValue()); - Method defaultValueMethod = Param.class.getDeclaredMethod("defaultValue"); + Method defaultValueMethod = CopilotToolParam.class.getDeclaredMethod("defaultValue"); assertEquals("", defaultValueMethod.getDefaultValue()); } @@ -118,8 +118,9 @@ void paramDefaultValues() throws Exception { static class SampleToolHolder { @CopilotTool(value = "Get weather for a location", name = "get_weather", defer = ToolDefer.AUTO) - public CompletableFuture getWeather(@Param(value = "City name", required = true) String location, - @Param(value = "Temperature unit", required = false, defaultValue = "celsius") String unit) { + public CompletableFuture getWeather( + @CopilotToolParam(value = "City name", required = true) String location, + @CopilotToolParam(value = "Temperature unit", required = false, defaultValue = "celsius") String unit) { return CompletableFuture.completedFuture("Sunny in " + location); } } @@ -139,13 +140,13 @@ void annotationsAreAccessibleViaReflection() throws Exception { Parameter[] params = method.getParameters(); assertEquals(2, params.length); - Param locationParam = params[0].getAnnotation(Param.class); + CopilotToolParam locationParam = params[0].getAnnotation(CopilotToolParam.class); assertNotNull(locationParam); assertEquals("City name", locationParam.value()); assertTrue(locationParam.required()); assertEquals("", locationParam.defaultValue()); - Param unitParam = params[1].getAnnotation(Param.class); + CopilotToolParam unitParam = params[1].getAnnotation(CopilotToolParam.class); assertNotNull(unitParam); assertEquals("Temperature unit", unitParam.value()); assertFalse(unitParam.required()); diff --git a/java/src/test/java/com/github/copilot/tool/CopilotToolProcessorTest.java b/java/src/test/java/com/github/copilot/tool/CopilotToolProcessorTest.java index fefef6714b..c2bda9f9ad 100644 --- a/java/src/test/java/com/github/copilot/tool/CopilotToolProcessorTest.java +++ b/java/src/test/java/com/github/copilot/tool/CopilotToolProcessorTest.java @@ -55,18 +55,18 @@ void generatesMetaClass_withCorrectToolNames() { String source = """ package test; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; public class MyTools { @CopilotTool("Sets the current phase") - public String setCurrentPhase(@Param("The phase") String phase) { + public String setCurrentPhase(@CopilotToolParam("The phase") String phase) { return "done"; } @CopilotTool("Search for items") - public String searchItems(@Param("Keyword") String keyword) { + public String searchItems(@CopilotToolParam("Keyword") String keyword) { return "found"; } @CopilotTool(value = "Custom grep", name = "grep") - public String grepOverride(@Param("Query") String query) { + public String grepOverride(@CopilotToolParam("Query") String query) { return "result"; } } @@ -111,10 +111,10 @@ void emitsError_forRequiredWithDefaultValue() { String source = """ package test; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; public class ConflictTools { @CopilotTool("Conflicting params") - public String doSomething(@Param(value = "desc", required = true, defaultValue = "hello") String param) { + public String doSomething(@CopilotToolParam(value = "desc", required = true, defaultValue = "hello") String param) { return "done"; } } @@ -131,10 +131,10 @@ void emitsError_forOptionalPrimitiveWithoutDefaultValue() { String source = """ package test; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; public class OptionalPrimitiveTools { @CopilotTool("Optional primitive") - public String doSomething(@Param(value = "Limit", required = false) int limit) { + public String doSomething(@CopilotToolParam(value = "Limit", required = false) int limit) { return "done"; } } @@ -151,11 +151,11 @@ void emitsError_forSingleRecordWrapperDefaultValue() { String source = """ package test; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; public class SingleRecordDefaultTools { public record SearchArgs(String query, int limit) {} @CopilotTool("Single record") - public String search(@Param(defaultValue = "fallback") SearchArgs req) { + public String search(@CopilotToolParam(defaultValue = "fallback") SearchArgs req) { return req.query(); } } @@ -173,11 +173,11 @@ void emitsError_forSingleRecordWrapperMetadataOverrides() { String source = """ package test; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; public class SingleRecordMetaTools { public record SearchArgs(String query, int limit) {} @CopilotTool("Single record") - public String search(@Param(value = "Search input", required = false, name = "input") SearchArgs req) { + public String search(@CopilotToolParam(value = "Search input", required = false, name = "input") SearchArgs req) { return req.query(); } } @@ -196,10 +196,10 @@ void generatesCorrectCode_forStringReturnType() { String source = """ package test; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; public class StringReturn { @CopilotTool("Returns string") - public String doSomething(@Param("Input") String input) { + public String doSomething(@CopilotToolParam("Input") String input) { return input; } } @@ -217,10 +217,10 @@ void generatesCorrectCode_forVoidReturnType() { String source = """ package test; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; public class VoidReturn { @CopilotTool("Void method") - public void doSomething(@Param("Input") String input) { + public void doSomething(@CopilotToolParam("Input") String input) { } } """; @@ -238,11 +238,11 @@ void generatesCorrectCode_forCompletableFutureStringReturnType() { String source = """ package test; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; import java.util.concurrent.CompletableFuture; public class AsyncReturn { @CopilotTool("Async method") - public CompletableFuture doSomething(@Param("Input") String input) { + public CompletableFuture doSomething(@CopilotToolParam("Input") String input) { return CompletableFuture.completedFuture(input); } } @@ -262,10 +262,10 @@ void generatesCorrectCode_forIntReturnType() { String source = """ package test; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; public class IntReturn { @CopilotTool("Returns int") - public int doSomething(@Param("Input") String input) { + public int doSomething(@CopilotToolParam("Input") String input) { return 42; } } @@ -285,13 +285,13 @@ void generatesCorrectArgExtraction_forPrimitiveAndStringTypes() { String source = """ package test; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; public class ArgTypes { @CopilotTool("Mixed args") public String doSomething( - @Param("Name") String name, - @Param("Count") int count, - @Param("Flag") boolean flag) { + @CopilotToolParam("Name") String name, + @CopilotToolParam("Count") int count, + @CopilotToolParam("Flag") boolean flag) { return "done"; } } @@ -313,10 +313,10 @@ void generatesTypeReferenceConversion_forArrayParameters() { String source = """ package test; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; public class ArrayArgs { @CopilotTool("Array tool") - public String doSomething(@Param("Ids") String[] ids) { + public String doSomething(@CopilotToolParam("Ids") String[] ids) { return String.valueOf(ids.length); } } @@ -340,14 +340,14 @@ void generatesTypeReferenceConversion_forGenericDeclaredParameters() { String source = """ package test; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; public class GenericArgTypes { public record MyRecord(String name) {} @CopilotTool("Generic args") public String doSomething( - @Param("Ids") java.util.List ids, - @Param("Values") java.util.Map values, - @Param("Records") java.util.List records) { + @CopilotToolParam("Ids") java.util.List ids, + @CopilotToolParam("Values") java.util.Map values, + @CopilotToolParam("Records") java.util.List records) { return "done"; } } @@ -405,12 +405,12 @@ void generatesCorrectSchema() { String source = """ package test; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; public class SchemaTools { @CopilotTool("Search items") public String search( - @Param(value = "Query", required = true) String query, - @Param(value = "Limit", required = false) Integer limit) { + @CopilotToolParam(value = "Query", required = true) String query, + @CopilotToolParam(value = "Limit", required = false) Integer limit) { return "done"; } } @@ -486,10 +486,10 @@ void supportsInjectedToolInvocation_forSchemaAndMethodCall() { package test; import com.github.copilot.rpc.ToolInvocation; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; public class InvocationAwareTools { @CopilotTool("Reports progress") - public String report(@Param("Phase") String phase, ToolInvocation toolInvocation) { + public String report(@CopilotToolParam("Phase") String phase, ToolInvocation toolInvocation) { return phase + ":" + toolInvocation.getSessionId(); } } @@ -520,15 +520,15 @@ void supportsInjectedToolInvocation_forStaticAndAsyncMethods() { package test; import com.github.copilot.rpc.ToolInvocation; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; import java.util.concurrent.CompletableFuture; public class StaticInvocationAwareTools { @CopilotTool("Reports progress statically") - public static String report(@Param("Phase") String phase, ToolInvocation toolInvocation) { + public static String report(@CopilotToolParam("Phase") String phase, ToolInvocation toolInvocation) { return phase + ":" + toolInvocation.getToolCallId(); } @CopilotTool("Reports progress asynchronously") - public CompletableFuture reportAsync(@Param("Phase") String phase, ToolInvocation toolInvocation) { + public CompletableFuture reportAsync(@CopilotToolParam("Phase") String phase, ToolInvocation toolInvocation) { return CompletableFuture.completedFuture(phase + ":" + toolInvocation.getToolCallId()); } } @@ -579,14 +579,14 @@ void supportsInjectedToolInvocation_whenItAppearsFirstOrMiddle() { package test; import com.github.copilot.rpc.ToolInvocation; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; public class InvocationPositionTools { @CopilotTool("Invocation first") - public String reportFirst(ToolInvocation invocation, @Param("Phase") String phase) { + public String reportFirst(ToolInvocation invocation, @CopilotToolParam("Phase") String phase) { return phase + ":" + invocation.getToolCallId(); } @CopilotTool("Invocation middle") - public String reportMiddle(@Param("Phase") String phase, ToolInvocation invocation, @Param("Limit") int limit) { + public String reportMiddle(@CopilotToolParam("Phase") String phase, ToolInvocation invocation, @CopilotToolParam("Limit") int limit) { return phase + ":" + limit + ":" + invocation.getToolCallId(); } } @@ -670,10 +670,10 @@ void emitsError_forParamAnnotatedToolInvocationParameter() { package test; import com.github.copilot.rpc.ToolInvocation; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; public class AnnotatedInvocationTools { - @CopilotTool("Invalid @Param on ToolInvocation") - public String report(@Param("Invocation context") ToolInvocation invocation) { + @CopilotTool("Invalid @CopilotToolParam on ToolInvocation") + public String report(@CopilotToolParam("Invocation context") ToolInvocation invocation) { return invocation.getToolName(); } } @@ -682,8 +682,8 @@ public String report(@Param("Invocation context") ToolInvocation invocation) { CompilationResult result = compileWithProcessor( List.of(inMemorySource("test.AnnotatedInvocationTools", source))); - assertTrue(hasErrorContaining(result, "@Param is not supported on ToolInvocation parameters"), - "Expected compile error for @Param ToolInvocation parameter, got: " + result.diagnostics); + assertTrue(hasErrorContaining(result, "@CopilotToolParam is not supported on ToolInvocation parameters"), + "Expected compile error for @CopilotToolParam ToolInvocation parameter, got: " + result.diagnostics); } // ── Test: Typed default values in schema ──────────────────────────────────── @@ -693,13 +693,13 @@ void emitsTypedDefaultValuesInSchema() { String source = """ package test; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; public class DefaultTools { @CopilotTool("Tool with defaults") public String doWork( - @Param(value = "Limit", required = false, defaultValue = "10") int limit, - @Param(value = "Enabled", required = false, defaultValue = "true") boolean enabled, - @Param(value = "Label", required = false, defaultValue = "hello") String label) { + @CopilotToolParam(value = "Limit", required = false, defaultValue = "10") int limit, + @CopilotToolParam(value = "Enabled", required = false, defaultValue = "true") boolean enabled, + @CopilotToolParam(value = "Label", required = false, defaultValue = "hello") String label) { return "done"; } } @@ -726,10 +726,10 @@ void rejectsMismatchedNumericDefaultForIntegralParameters() { String source = """ package test; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; public class MismatchedDefaults { @CopilotTool("Tool with bad default") - public String doWork(@Param(value = "Limit", required = false, defaultValue = "1.5") int limit) { + public String doWork(@CopilotToolParam(value = "Limit", required = false, defaultValue = "1.5") int limit) { return String.valueOf(limit); } } @@ -785,10 +785,10 @@ void generatesCreateOverride_whenOverridesBuiltInTool() { String source = """ package test; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; public class OverrideTools { @CopilotTool(value = "Custom grep", name = "grep", overridesBuiltInTool = true) - public String grep(@Param("Query") String query) { + public String grep(@CopilotToolParam("Query") String query) { return "result"; } } @@ -889,26 +889,26 @@ void generatesCorrectOptionalExtraction() { String source = """ package test; import com.github.copilot.tool.CopilotTool; - import com.github.copilot.tool.Param; + import com.github.copilot.tool.CopilotToolParam; import java.util.Optional; import java.util.OptionalInt; import java.util.OptionalLong; import java.util.OptionalDouble; public class OptionalTools { @CopilotTool("Tool with optional string") - public String withOptionalString(@Param("A name") Optional name) { + public String withOptionalString(@CopilotToolParam("A name") Optional name) { return name.orElse("default"); } @CopilotTool("Tool with optional int") - public String withOptionalInt(@Param("A count") OptionalInt count) { + public String withOptionalInt(@CopilotToolParam("A count") OptionalInt count) { return String.valueOf(count.orElse(0)); } @CopilotTool("Tool with optional long") - public String withOptionalLong(@Param("A timestamp") OptionalLong ts) { + public String withOptionalLong(@CopilotToolParam("A timestamp") OptionalLong ts) { return String.valueOf(ts.orElse(0L)); } @CopilotTool("Tool with optional double") - public String withOptionalDouble(@Param("A ratio") OptionalDouble ratio) { + public String withOptionalDouble(@CopilotToolParam("A ratio") OptionalDouble ratio) { return String.valueOf(ratio.orElse(0.0)); } }