Skip to content

java: add schema attribute to @CopilotToolParam and lambda for custom type schema override#2069

Merged
edburns merged 11 commits into
mainfrom
edburns/review-rinceyuan-pr-1999
Jul 24, 2026
Merged

java: add schema attribute to @CopilotToolParam and lambda for custom type schema override#2069
edburns merged 11 commits into
mainfrom
edburns/review-rinceyuan-pr-1999

Conversation

@edburns

@edburns edburns commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Supercedes #1999

Closes #1794

Summary

Adds an optional schema attribute to @CopilotToolParam that allows users to explicitly specify the JSON Schema for a tool parameter. This enables support for custom/third-party types that the SchemaGenerator cannot automatically map.

Example

@CopilotTool("Schedule a deployment")
public String scheduleDeployment(
        @CopilotToolParam(value = "Deployment time in ISO-8601",
            schema = "{\"type\":\"string\",\"format\":\"date-time\"}")
        com.acme.internal.AcmeDateTime deployTime) {
    return "Scheduled for " + deployTime;
}

Changes

CopilotToolParam.java

  • Added String schema() default "" annotation attribute with Javadoc

CopilotToolProcessor.java

  • In generateSchemaWithParamMetadata(): when schema is non-empty, use it instead of auto-generated schema
  • Added compile-time validation: schema + defaultValue conflict emits error
  • Added compile-time validation: invalid JSON (not starting/ending with braces) emits error
  • Added jsonToMapOfSource() — a minimal recursive-descent JSON parser that converts JSON strings to Map.of(...) source code expressions at compile time (no external JSON library needed)

Param.java

  • Added schema field, fluent schema() mutator, and getter for lambda API parity
  • Updated equals(), hashCode() to include schema

CopilotToolProcessorTest.java (4 new tests)

  1. Schema override — custom schema appears in generated code
  2. Schema + defaultValue conflict — produces compile error
  3. Invalid JSON — produces compile error
  4. Empty schema — falls through to normal type-based generation

Testing

  • All 4 new tests pass
  • The only failing test (generatesNullMetadata_whenAbsent) is a pre-existing failure on main unrelated to this PR

j-zhangyiyuan and others added 4 commits July 16, 2026 10:07
…a override

Closes #1794

Add an optional schema attribute to @CopilotToolParam that allows users
to explicitly specify the JSON Schema for a tool parameter, bypassing
automatic type-based schema generation.

Changes:
- CopilotToolParam.java: add String schema() default ""
- CopilotToolProcessor.java: use custom schema when provided, with
  compile-time JSON validation and schema+defaultValue conflict check.
  Includes a minimal recursive-descent JSON-to-Map.of() converter.
- Param.java: add schema field + fluent mutator for lambda API parity
- CopilotToolProcessorTest.java: 4 new tests
```text
java: honor schema overrides in lambda tool definitions

Parse explicit Param schemas when building runtime tool metadata instead of
always deriving a schema from the Java parameter type. Validate fluent schema
overrides consistently, preserve parameter metadata, and report malformed JSON
with tool and parameter context.

Add focused coverage for direct schema construction, custom-type lambda tools,
and Param validation and copying. Stabilize processor tests across line endings
and make Java test setup quieter and easier to troubleshoot.
```

# Per-file change manifest

- `.vscode/settings.json`: Disable Java autobuild for the workspace to avoid unsolicited background builds.
- `java/pom.xml`: Default npm setup output to `notice` and allow the log level to be overridden with `-Dnpm.loglevel` for troubleshooting.
- `java/src/main/java/com/github/copilot/rpc/ParamSchema.java`: Parse a non-empty `Param.schema()` with the configured `ObjectMapper`, use it as the parameter schema, retain description and required metadata, fall back to type-derived schemas when absent, and include tool and parameter names in invalid-JSON errors.
- `java/src/main/java/com/github/copilot/tool/Param.java`: Validate schema overrides during fluent Param construction, require object-shaped JSON text, and reject combining an explicit schema with `defaultValue`.
- `java/src/test/java/com/github/copilot/rpc/ParamSchemaTest.java`: Cover explicit schema use, description and required metadata preservation, and mixed explicit and type-derived parameters.
- `java/src/test/java/com/github/copilot/rpc/ToolDefinitionLambdaTest.java`: Verify that `ToolDefinition.from(...)` publishes an explicit schema for a custom Java type.
- `java/src/test/java/com/github/copilot/tool/CopilotToolProcessorTest.java`: Normalize generated source line endings before asserting absent metadata, making the test portable across Windows and Unix.
- `java/src/test/java/com/github/copilot/tool/ParamTest.java`: Cover malformed schema text, schema/default conflicts, empty and valid schemas, and schema preservation across fluent copies.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds explicit JSON Schema overrides for Java annotation- and lambda-based tool parameters.

Changes:

  • Adds schema metadata to CopilotToolParam and Param.
  • Parses overrides in annotation processing and lambda schema generation.
  • Adds validation/tests plus npm and editor configuration updates.
Show a summary per file
File Description
.vscode/settings.json Disables Java autobuild.
java/pom.xml Configures npm log level.
java/src/main/java/com/github/copilot/rpc/ParamSchema.java Parses lambda schema overrides.
java/src/main/java/com/github/copilot/tool/CopilotToolParam.java Adds annotation schema attribute.
java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java Validates and generates override schemas.
java/src/main/java/com/github/copilot/tool/Param.java Adds fluent schema metadata.
java/src/test/java/com/github/copilot/rpc/ParamSchemaTest.java Tests runtime schema construction.
java/src/test/java/com/github/copilot/rpc/ToolDefinitionLambdaTest.java Tests lambda custom-type schemas.
java/src/test/java/com/github/copilot/tool/CopilotToolProcessorTest.java Tests processor validation and generation.
java/src/test/java/com/github/copilot/tool/ParamTest.java Tests Param schema behavior.

Review details

  • Files reviewed: 10/10 changed files
  • Comments generated: 5
  • Review effort level: Medium

Comment thread java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java Outdated
Comment thread java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java Outdated
Comment thread java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java Outdated
Comment thread java/src/test/java/com/github/copilot/rpc/ToolDefinitionLambdaTest.java Outdated
…eyuan-pr-1999

# Conflicts:
#	java/src/test/java/com/github/copilot/tool/CopilotToolProcessorTest.java
Copilot AI review requested due to automatic review settings July 23, 2026 21:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Comments suppressed due to low confidence (5)

java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java:1008

  • Escapes are skipped rather than decoded or validated. Valid JSON escapes such as \n, \t, \b, \f, and \uXXXX silently become ordinary letters, while an invalid escape such as \q is accepted. This can alter schema patterns/descriptions; use a real JSON decoder or implement the complete JSON escape rules.
                if (input.charAt(pos) == '\\') {
                    pos++;
                    if (pos >= input.length()) {
                        throw new IllegalArgumentException("Unterminated string escape at position " + pos);
                    }

java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java:1032

  • Emitting Java null here feeds it into Map.of or List.of, both of which reject null and throw during generated metadata initialization. JSON Schema validly uses null in const, default, and enum, and this method explicitly claims null support. Generate null-tolerant collection expressions or report a compile-time diagnostic instead.
                return "null";

java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java:1045

  • This scanner does not implement JSON number grammar and emits the token as a Java expression. For example, invalid JSON 1+2 is accepted and becomes schema value 3, while valid JSON 2147483648 fails generated-source compilation as an oversized Java int literal. Parse JSON numbers strictly and emit correctly typed Java literals.
            while (pos < input.length()
                    && (Character.isDigit(input.charAt(pos)) || input.charAt(pos) == '.' || input.charAt(pos) == 'e'
                            || input.charAt(pos) == 'E' || input.charAt(pos) == '+' || input.charAt(pos) == '-')) {
                pos++;

java/src/test/java/com/github/copilot/rpc/ToolDefinitionLambdaTest.java:495

  • This test only inspects the schema and never invokes the handler. Issue #1794 explicitly requires proving that ObjectMapper deserializes an argument into the custom type; with a string schema and this property-based record, that path is not exercised. Invoke tool.handler() with a matching argument and assert the handler receives the expected CustomDateTime, adding an appropriate creator/deserializer if needed.
        Param<CustomDateTime> p = Param.of(CustomDateTime.class, "when", "Meeting time")
                .schema("{\"type\":\"string\",\"format\":\"date-time\"}");
        ToolDefinition tool = ToolDefinition.from("schedule", "Schedules a meeting", p, when -> "scheduled");

java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java:958

  • Map.of only supports up to 10 key/value pairs. A valid custom schema object with 11 or more keywords/properties therefore produces generated Java that does not compile. Emit Map.ofEntries/Map.entry, as the existing SchemaGenerator does.
            return "Map.of(" + String.join(", ", entries) + ")";
  • Files reviewed: 10/10 changed files
  • Comments generated: 1
  • Review effort level: Medium

Comment thread .vscode/settings.json
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Comments suppressed due to low confidence (5)

java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java:958

  • Map.of has key/value overloads only through 10 entries. A valid schema object with 11 keywords—or a nested properties object with 11 fields—therefore makes the generated source fail to compile. Emit an arity-independent map expression or builder instead.
            return "Map.of(" + String.join(", ", entries) + ")";

java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java:1008

  • This drops the backslash without decoding or validating the JSON escape. Valid escapes such as \n and \u0061 become n and u0061, while an invalid escape such as \q is accepted and silently altered. Decode every JSON escape and reject unknown escapes/control characters, or use a standards-compliant parser before generating source.
                if (input.charAt(pos) == '\\') {
                    pos++;
                    if (pos >= input.length()) {
                        throw new IllegalArgumentException("Unterminated string escape at position " + pos);
                    }

java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java:1032

  • Emitting Java null here inserts it into the surrounding Map.of or List.of, both of which reject null values. Valid schemas such as {"const":null} or {"enum":[null]} will compile but throw NullPointerException when tool definitions are constructed. Generate null-tolerant collection expressions for parsed JSON.
        private String parseNull() {
            if (input.startsWith("null", pos)) {
                pos += 4;
                return "null";

java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java:1046

  • This accepts an arbitrary run of numeric/operator characters and emits it as a Java expression rather than validating a JSON number. For example, invalid JSON 1+2 becomes the schema value 3, and 010 becomes octal 8; conversely, a valid integer outside Java's int literal range can fail generated-code compilation. Parse the exact JSON number grammar and emit an appropriately typed numeric source expression.
            while (pos < input.length()
                    && (Character.isDigit(input.charAt(pos)) || input.charAt(pos) == '.' || input.charAt(pos) == 'e'
                            || input.charAt(pos) == 'E' || input.charAt(pos) == '+' || input.charAt(pos) == '-')) {
                pos++;
            }

java/src/test/java/com/github/copilot/rpc/ToolDefinitionLambdaTest.java:495

  • The linked issue's gating integration test requires invoking a handler with a custom type, but this test only inspects the generated schema. It never exercises the distinct ParamCoercion.coerce deserialization path, so schema generation can pass while custom-type invocation still fails. Invoke tool.handler() with the schema-shaped value and assert that the lambda receives the expected custom value, using a custom/delegating deserialization fixture.
        Param<CustomDateTime> p = Param.of(CustomDateTime.class, "when", "Meeting time")
                .schema("{\"type\":\"string\",\"format\":\"date-time\"}");
        ToolDefinition tool = ToolDefinition.from("schedule", "Schedules a meeting", p, when -> "scheduled");
  • Files reviewed: 10/10 changed files
  • Comments generated: 1
  • Review effort level: Medium

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Comments suppressed due to low confidence (5)

java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java:958

  • Map.of has overloads for at most ten entries, so an otherwise valid schema object with 11 or more keywords (including a nested object) makes the generated Java fail to compile. Emit an unbounded map expression such as Map.ofEntries instead.
            return "Map.of(" + String.join(", ", entries) + ")";

java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java:1032

  • Emitting the Java null literal into Map.of(...) or List.of(...) breaks valid schemas containing JSON null (for example {"default":null} or {"enum":[null,"x"]}), because both factories reject null at runtime. Use a null-tolerant generated collection representation.
                return "null";

java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java:1008

  • This drops the backslash without decoding or validating the JSON escape. Consequently \n becomes the letter n, \u0061 becomes u0061, and invalid escapes such as \q are accepted, so the generated schema differs from the supplied valid JSON and malformed JSON can pass validation. Decode all RFC 8259 escapes and reject unknown ones.
                if (input.charAt(pos) == '\\') {
                    pos++;
                    if (pos >= input.length()) {
                        throw new IllegalArgumentException("Unterminated string escape at position " + pos);
                    }

java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java:1045

  • This is not the JSON number grammar: values such as +1, 1., and 1-2 are accepted, with 1-2 even emitted as a Java subtraction expression. Conversely, valid large JSON numbers can become uncompilable Java literals. Parse JSON numbers strictly and emit a range-independent numeric representation such as BigDecimal.
            while (pos < input.length()
                    && (Character.isDigit(input.charAt(pos)) || input.charAt(pos) == '.' || input.charAt(pos) == 'e'
                            || input.charAt(pos) == 'E' || input.charAt(pos) == '+' || input.charAt(pos) == '-')) {
                pos++;

java/src/test/java/com/github/copilot/rpc/ToolDefinitionLambdaTest.java:495

  • The linked #1794 gating criterion requires invoking a generated fromObject handler with a custom type to verify ObjectMapper deserialization. This test only inspects lambda schema metadata, while the processor test uses String, so that required end-to-end path remains untested. Add a custom-type fixture with the annotation override and invoke its generated tool handler.
        ToolDefinition tool = ToolDefinition.from("schedule", "Schedules a meeting", p, when -> "scheduled");
  • Files reviewed: 10/10 changed files
  • Comments generated: 1
  • Review effort level: Medium

Comment thread java/src/main/java/com/github/copilot/rpc/ParamSchema.java Outdated
Copilot AI review requested due to automatic review settings July 23, 2026 22:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Comments suppressed due to low confidence (2)

java/src/main/java/com/github/copilot/rpc/ParamSchema.java:91

  • ObjectMapper.readValue does not reject trailing tokens by default, so a value such as {"type":"string"} {"type":"integer"} passes Param's brace check and is silently accepted as the first object even though the public API requires one valid JSON object. Enable FAIL_ON_TRAILING_TOKENS for this parse so the lambda API enforces the documented contract consistently with the annotation processor.
                    Map<String, Object> parsed = mapper.readValue(param.schema(), Map.class);

java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java:1140

  • JSON permits only space, tab, CR, and LF between tokens, while Character.isWhitespace also accepts characters such as form feed and vertical tab. Consequently an invalid annotation value like "{\f\"type\":\"string\"}" passes the promised compile-time JSON validation and is emitted as a schema. Restrict this loop to the four JSON whitespace characters.
            while (pos < input.length() && Character.isWhitespace(input.charAt(pos))) {
  • Files reviewed: 10/10 changed files
  • Comments generated: 2
  • Review effort level: Medium

@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Comments suppressed due to low confidence (3)

java/src/main/java/com/github/copilot/rpc/ParamSchema.java:92

  • The default untyped readValue is not strict or lossless enough for a schema override: it ignores trailing JSON values unless FAIL_ON_TRAILING_TOKENS is enabled (so {"type":"string"}{} is accepted), and decimal constraints are coerced to Double, which can round or overflow values such as 1e400. Use a strict reader that preserves decimal values.
                try {
                    @SuppressWarnings("unchecked")
                    Map<String, Object> parsed = mapper.readValue(param.schema(), Map.class);
                    typeSchema = parsed;

java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java:1065

  • Character.digit(..., 16) also recognizes non-ASCII characters such as full-width hex digits, although JSON \u escapes permit only ASCII 0-9, a-f, and A-F. Such malformed escapes currently pass the promised compile-time JSON validation; restrict this conversion to the JSON hex alphabet.
            for (int i = 0; i < 4; i++) {
                int digit = Character.digit(input.charAt(pos++), 16);
                if (digit < 0) {
                    throw new IllegalArgumentException("Invalid Unicode escape at position " + (pos - 1));

java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java:1125

  • JSON numbers permit only ASCII digits, but Character.isDigit accepts many Unicode numerals. For example, an annotation schema containing {"minimum":1١} can pass this parser and be emitted as a BigDecimal instead of producing the required compile-time error. Use an ASCII digit predicate for the fraction, exponent, and remaining integer digits.
        private void requireDigit(String part) {
            if (pos >= input.length() || !Character.isDigit(input.charAt(pos))) {
                throw new IllegalArgumentException("Expected digit in number " + part + " at position " + pos);
  • Files reviewed: 10/10 changed files
  • Comments generated: 1
  • Review effort level: Medium

Copilot AI review requested due to automatic review settings July 23, 2026 22:24
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 10/10 changed files
  • Comments generated: 2
  • Review effort level: Medium

Comment thread java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java Outdated
Copilot AI review requested due to automatic review settings July 23, 2026 22:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Comments suppressed due to low confidence (1)

java/src/main/java/com/github/copilot/rpc/ParamSchema.java:93

  • Untyped Jackson parsing converts JSON decimals to Double, so an explicit schema can be changed before it is sent. For example, {"maximum":1e400} becomes Double.POSITIVE_INFINITY (and Jackson later serializes that as the string "Infinity"), while ordinary high-precision decimals are rounded. Parse floating-point values as BigDecimal, matching the annotation-processor path, so valid schema numbers retain their JSON value.
                    Map<String, Object> parsed = mapper.readerFor(Map.class)
                            .with(DeserializationFeature.FAIL_ON_TRAILING_TOKENS).readValue(param.schema());
  • Files reviewed: 10/10 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Comments suppressed due to low confidence (1)

java/src/main/java/com/github/copilot/rpc/ParamSchema.java:93

  • Untyped floating-point values are deserialized as Double here, so valid schema numbers outside the double range are not preserved. For example, schema("{\"maximum\":1e400}") becomes positive infinity; when the tool definition is serialized, Jackson emits a string such as "Infinity" (or invalid non-finite JSON), changing the numeric schema keyword. Parse floating values as BigDecimal, matching the annotation-processor path, so explicit schemas retain valid large/exact JSON numbers.
                    Map<String, Object> parsed = mapper.readerFor(Map.class)
                            .with(DeserializationFeature.FAIL_ON_TRAILING_TOKENS).readValue(param.schema());
  • Files reviewed: 10/10 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

Copilot AI review requested due to automatic review settings July 23, 2026 23:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 10/10 changed files
  • Comments generated: 1
  • Review effort level: Medium

Comment thread java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java Outdated
@github-actions

This comment has been minimized.

Copilot AI review requested due to automatic review settings July 23, 2026 23:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 10/10 changed files
  • Comments generated: 1
  • Review effort level: Medium

Comment thread java/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java Outdated
@github-actions

This comment has been minimized.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 24, 2026 15:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 10/10 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

@github-actions

Copy link
Copy Markdown
Contributor

Cross-SDK Consistency Review ✅

PR #2069 adds per-parameter JSON Schema override support to the Java SDK only (@CopilotToolParam(schema="...") annotation and Param.schema(String) lambda API).

Cross-SDK parity assessment

SDK Status Notes
Java ✅ Updated New schema override on @CopilotToolParam and Param
Python ✅ Equivalent exists python/copilot/tools.py accepts custom parameters dict / Pydantic schema
Rust ✅ Equivalent exists tool_parameters(...) / try_tool_parameters(...) in rust/src/tool.rs
Node.js/TypeScript ✅ N/A Tool definitions are manual schema objects; no auto-generation to override
.NET i️ Minor gap (pre-existing) CopilotTool.DefineTool has no convenience per-parameter schema override; users must drop to lower-level AIFunction APIs
Go i️ Minor gap (pre-existing) go/definetool.go auto-generates from struct type with no escape hatch beyond hand-constructing Tool

Findings

No new inconsistencies introduced by this PR. The annotation-processor approach is Java-specific and does not require parallel syntax in other SDKs.

The minor gaps in .NET and Go are pre-existing — this PR did not create them. They may be worth separate follow-up issues if explicit schema override convenience APIs are desired there.

Optional follow-up

The new public API surface (CopilotToolParam.schema and Param.schema(String)) does not appear to have corresponding documentation updates in java/README.md. Updating the README to document the new per-parameter schema override capability would improve discoverability.


Automated cross-SDK consistency review

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • awmgmcpg

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

Generated by SDK Consistency Review Agent for #2069 · 35.8 AIC · ⌖ 5.29 AIC · ⊞ 5.2K ·

@edburns edburns left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Self approve.

@edburns
edburns merged commit 2ab2aa5 into main Jul 24, 2026
28 of 29 checks passed
@edburns
edburns deleted the edburns/review-rinceyuan-pr-1999 branch July 24, 2026 17:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Java] @CopilotTool ergonomics: Add schema attribute to @Param for custom type schema override

2 participants