feat(java): implement ToolDefinition.from* lambda overloads (Phase 4.2)#1857
Conversation
…ed tools (Phase 4.2) Co-authored-by: edburns <75821+edburns@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
…copilot/edburns-1810-java-tool-ergonomics-tool-as-lambda
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
Adds a new Java ergonomic API for defining Copilot tools inline using JDK lambdas (sync/async, with/without ToolInvocation), plus fluent “copy” modifiers to set tool flags on ToolDefinition records. This expands the Java SDK’s tool-definition options beyond annotation processing while keeping schema generation and argument/result coercion inside the runtime.
Changes:
- Added 10 new
ToolDefinition.from*static factory overloads to define tools via lambdas (sync/async, with/withoutToolInvocation, 0–2 args). - Added fluent copy-style modifiers on
ToolDefinitionto setoverridesBuiltInTool,skipPermission, anddefer. - Implemented runtime JSON schema generation (
buildSchemaFromParams/schemaForClass) and argument/default/result coercion helpers.
Show a summary per file
| File | Description |
|---|---|
| java/src/main/java/com/github/copilot/rpc/ToolDefinition.java | Adds lambda-based tool factory overloads, fluent modifiers, and runtime schema/coercion helpers for Param<?>-described tool arguments. |
Review details
- Files reviewed: 1/1 changed files
- Comments generated: 3
- Review effort level: Low
- buildSchemaFromParams: parse default values to declared type before placing in JSON schema (avoids String defaults for numeric/boolean) - schemaForClass: emit items schema for Java array types using getComponentType() for schema fidelity - coerceDefaultValue: use boxed valueOf() instead of type.cast() for primitive types to avoid ClassCastException Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
- formatResult: pass ToolResultObject through directly instead of JSON-serializing, preserving structured result semantics - schemaForClass: add OptionalInt/OptionalLong/OptionalDouble support to match compile-time SchemaGenerator behavior Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
- Return OptionalInt.empty()/OptionalLong.empty()/OptionalDouble.empty() for missing non-required params instead of null - Construct Optional*.of(...) from Number when value is present - Avoids NPE and aligns with annotation-processor behavior Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
…tags - All async fromAsync*/fromAsyncWithToolInvocation handlers now check for null future and return failedFuture with clear NPE message - Optional* coercion catches ClassCastException for non-numeric values and throws IllegalArgumentException with diagnostic message - Fixed @SInCE 1.0.2 -> 1.0.6 on all new API entries (15 in ToolDefinition, 1 in Param) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
✅ Cross-SDK Consistency ReviewSummary: This PR brings Java to feature parity with the other five SDKs. No cross-SDK consistency issues found. What this PR adds
Cross-SDK feature matrix (post-PR)
The API naming is consistent with each language's conventions:
|
14826ad
into
edburns/1810-java-tool-ergonomics-tool-as-lambda
Phase 4.2 of #1810: adds typed
ToolDefinition.from*factory methods so tools can be defined inline at the call site using standard JDK lambdas, without annotation processing.New API surface
ToolDefinitionfactory overloads — 10 new@CopilotExperimentalstatic methods:from(name, desc, …)Supplier<R>, 1-argFunction<T1,R>, 2-argBiFunction<T1,T2,R>fromAsync(name, desc, …)CompletableFuture<R>fromWithToolInvocation(name, desc, …)Function<ToolInvocation,R>, 1-argBiFunction<T1,ToolInvocation,R>fromAsyncWithToolInvocation(name, desc, …)Fluent copy-style modifiers on
ToolDefinition(return a new record copy):overridesBuiltInTool(boolean),skipPermission(boolean),defer(ToolDefer)Param<T>(from Phase 4.1 base branch) — runtime parameter metadata mirroring@CopilotToolParamsemantics.Example
Internals
buildSchemaFromParams(Param<?>...)— runtime JSON Schema generation fromParam<T>descriptors, mirroring the compile-timeSchemaGeneratorcoerceArg()/coerceDefaultValue()— type-safe argument extraction viaObjectMapper; default values are parsed explicitly (integers, booleans, enums, etc.) rather than relying on Jackson string coercionformatResult()— enforces existing result contract:Stringpassthrough,null → "Success", anything else JSON-serialized