Skip to content

Commit 11da06a

Browse files
committed
Fix Big Risk 1. sendExpandedToolResult() bypasses the typed wrapper (HIGH)
scripts/codegen/java.ts - Remove the special-case `anyOf` rule that picked `String` when exactly 2 non-null branches included a string type. Multi-branch `anyOf` now falls through to `Object`, matching the C# reference generator's behavior. src/generated/java/com/github/copilot/sdk/generated/rpc/SessionToolsHandlePendingToolCallParams.java - Change the `result` field type from `String` to `Object` (regenerated output reflecting the `anyOf` rule fix in `java.ts`). src/main/java/com/github/copilot/sdk/CopilotSession.java - Replace the `sendExpandedToolResult(requestId, toolResult)` call with a direct typed-wrapper call: `getRpc().tools.handlePendingToolCall(new SessionToolsHandlePendingToolCallParams(...))`. - Delete the `sendExpandedToolResult()` private method and its Javadoc block, which are no longer needed now that the `result` field accepts `Object`. Signed-off-by: Ed Burns <edburns@microsoft.com>
1 parent a112b53 commit 11da06a

File tree

3 files changed

+6
-30
lines changed

3 files changed

+6
-30
lines changed

scripts/codegen/java.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -113,15 +113,9 @@ function schemaTypeToJava(
113113
const result = schemaTypeToJava(nonNull[0] as JSONSchema7, required && !hasNull, context, propName, nestedTypes);
114114
return result;
115115
}
116-
// When exactly two non-null types and one of them is string, prefer String
117-
// over Object to avoid unnecessary type erasure on common wire-level unions
118-
// (e.g., string | null, string | boolean). For wider unions keep Object.
119-
if (nonNull.length === 2) {
120-
const hasString = nonNull.some((s) => typeof s === "object" && (s as JSONSchema7).type === "string");
121-
if (hasString) {
122-
return { javaType: "String", imports };
123-
}
124-
}
116+
// Multi-branch anyOf: fall through to Object, matching the C# generator's
117+
// behavior. Java has no union types, so Object is the correct erasure for
118+
// anyOf[string, object] and similar multi-variant schemas.
125119
console.warn(`[codegen] ${context}.${propName}: anyOf with ${nonNull.length} non-null branches — falling back to Object`);
126120
return { javaType: "Object", imports };
127121
}

src/generated/java/com/github/copilot/sdk/generated/rpc/SessionToolsHandlePendingToolCallParams.java

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/java/com/github/copilot/sdk/CopilotSession.java

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,8 @@ private void executeToolAndRespondAsync(String requestId, String toolName, Strin
822822
toolResult = ToolResultObject
823823
.success(result instanceof String s ? s : MAPPER.writeValueAsString(result));
824824
}
825-
sendExpandedToolResult(requestId, toolResult);
825+
getRpc().tools.handlePendingToolCall(
826+
new SessionToolsHandlePendingToolCallParams(sessionId, requestId, toolResult, null));
826827
} catch (Exception e) {
827828
LOG.log(Level.WARNING, "Error sending tool result for requestId=" + requestId, e);
828829
}
@@ -857,25 +858,6 @@ private void executeToolAndRespondAsync(String requestId, String toolName, Strin
857858
}
858859
}
859860

860-
/**
861-
* Sends a {@code ToolResultObject} back via
862-
* {@code session.tools.handlePendingToolCall} using an
863-
* {@link com.fasterxml.jackson.databind.node.ObjectNode} payload.
864-
* <p>
865-
* {@link SessionToolsHandlePendingToolCallParams#result()} is typed as
866-
* {@code String} by the code generator's {@code anyOf[string,object]}
867-
* preference rule, but the protocol requires a JSON object for expanded
868-
* {@code ToolResultObject} results. This helper bypasses the type constraint
869-
* while keeping every other call site on the typed wrapper.
870-
*/
871-
private void sendExpandedToolResult(String requestId, ToolResultObject toolResult) {
872-
var node = MAPPER.createObjectNode();
873-
node.put("sessionId", sessionId);
874-
node.put("requestId", requestId);
875-
node.set("result", MAPPER.valueToTree(toolResult));
876-
rpc.invoke("session.tools.handlePendingToolCall", node, Object.class);
877-
}
878-
879861
/**
880862
* Builds a {@link SessionUiHandlePendingElicitationParams} carrying a
881863
* {@code cancel} action, used when an elicitation handler throws or the handler

0 commit comments

Comments
 (0)