Skip to content

Commit b58904b

Browse files
Copilotbrunoborges
andcommitted
Convert PreToolUseHookOutput to record
Co-authored-by: brunoborges <129743+brunoborges@users.noreply.github.com>
1 parent d4b564a commit b58904b

6 files changed

Lines changed: 31 additions & 146 deletions

File tree

src/main/java/com/github/copilot/sdk/json/PreToolUseHookOutput.java

Lines changed: 15 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -11,128 +11,22 @@
1111
/**
1212
* Output for a pre-tool-use hook.
1313
*
14+
* @param permissionDecision
15+
* "allow", "deny", or "ask"
16+
* @param permissionDecisionReason
17+
* the reason for the permission decision
18+
* @param modifiedArgs
19+
* the modified tool arguments, or {@code null} to use original
20+
* @param additionalContext
21+
* additional context to provide to the model
22+
* @param suppressOutput
23+
* {@code true} to suppress output
1424
* @since 1.0.6
1525
*/
1626
@JsonInclude(JsonInclude.Include.NON_NULL)
17-
public class PreToolUseHookOutput {
18-
19-
@JsonProperty("permissionDecision")
20-
private String permissionDecision;
21-
22-
@JsonProperty("permissionDecisionReason")
23-
private String permissionDecisionReason;
24-
25-
@JsonProperty("modifiedArgs")
26-
private JsonNode modifiedArgs;
27-
28-
@JsonProperty("additionalContext")
29-
private String additionalContext;
30-
31-
@JsonProperty("suppressOutput")
32-
private Boolean suppressOutput;
33-
34-
/**
35-
* Gets the permission decision.
36-
*
37-
* @return "allow", "deny", or "ask"
38-
*/
39-
public String getPermissionDecision() {
40-
return permissionDecision;
41-
}
42-
43-
/**
44-
* Sets the permission decision.
45-
*
46-
* @param permissionDecision
47-
* "allow", "deny", or "ask"
48-
* @return this instance for method chaining
49-
*/
50-
public PreToolUseHookOutput setPermissionDecision(String permissionDecision) {
51-
this.permissionDecision = permissionDecision;
52-
return this;
53-
}
54-
55-
/**
56-
* Gets the reason for the permission decision.
57-
*
58-
* @return the reason text
59-
*/
60-
public String getPermissionDecisionReason() {
61-
return permissionDecisionReason;
62-
}
63-
64-
/**
65-
* Sets the reason for the permission decision.
66-
*
67-
* @param permissionDecisionReason
68-
* the reason text
69-
* @return this instance for method chaining
70-
*/
71-
public PreToolUseHookOutput setPermissionDecisionReason(String permissionDecisionReason) {
72-
this.permissionDecisionReason = permissionDecisionReason;
73-
return this;
74-
}
75-
76-
/**
77-
* Gets the modified tool arguments.
78-
*
79-
* @return the modified arguments, or {@code null} to use original
80-
*/
81-
public JsonNode getModifiedArgs() {
82-
return modifiedArgs;
83-
}
84-
85-
/**
86-
* Sets the modified tool arguments.
87-
*
88-
* @param modifiedArgs
89-
* the modified arguments
90-
* @return this instance for method chaining
91-
*/
92-
public PreToolUseHookOutput setModifiedArgs(JsonNode modifiedArgs) {
93-
this.modifiedArgs = modifiedArgs;
94-
return this;
95-
}
96-
97-
/**
98-
* Gets additional context to provide to the model.
99-
*
100-
* @return the additional context
101-
*/
102-
public String getAdditionalContext() {
103-
return additionalContext;
104-
}
105-
106-
/**
107-
* Sets additional context to provide to the model.
108-
*
109-
* @param additionalContext
110-
* the additional context
111-
* @return this instance for method chaining
112-
*/
113-
public PreToolUseHookOutput setAdditionalContext(String additionalContext) {
114-
this.additionalContext = additionalContext;
115-
return this;
116-
}
117-
118-
/**
119-
* Returns whether to suppress output.
120-
*
121-
* @return {@code true} to suppress output
122-
*/
123-
public Boolean getSuppressOutput() {
124-
return suppressOutput;
125-
}
126-
127-
/**
128-
* Sets whether to suppress output.
129-
*
130-
* @param suppressOutput
131-
* {@code true} to suppress output
132-
* @return this instance for method chaining
133-
*/
134-
public PreToolUseHookOutput setSuppressOutput(Boolean suppressOutput) {
135-
this.suppressOutput = suppressOutput;
136-
return this;
137-
}
27+
public record PreToolUseHookOutput(@JsonProperty("permissionDecision") String permissionDecision,
28+
@JsonProperty("permissionDecisionReason") String permissionDecisionReason,
29+
@JsonProperty("modifiedArgs") JsonNode modifiedArgs,
30+
@JsonProperty("additionalContext") String additionalContext,
31+
@JsonProperty("suppressOutput") Boolean suppressOutput) {
13832
}

src/main/java/com/github/copilot/sdk/json/SessionHooks.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* <pre>{@code
1616
* var hooks = new SessionHooks().setOnPreToolUse((input, invocation) -> {
1717
* System.out.println("Tool being called: " + input.getToolName());
18-
* return CompletableFuture.completedFuture(new PreToolUseHookOutput().setPermissionDecision("allow"));
18+
* return CompletableFuture.completedFuture(new PreToolUseHookOutput("allow", null, null, null, null));
1919
* }).setOnPostToolUse((input, invocation) -> {
2020
* System.out.println("Tool result: " + input.getToolResult());
2121
* return CompletableFuture.completedFuture(null);

src/site/markdown/advanced.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ var hooks = new SessionHooks()
365365
.setOnPreToolUse((input, invocation) -> {
366366
System.out.println("Tool: " + input.getToolName());
367367
return CompletableFuture.completedFuture(
368-
new PreToolUseHookOutput().setPermissionDecision("allow")
368+
new PreToolUseHookOutput("allow", null, null, null, null)
369369
);
370370
})
371371
.setOnPostToolUse((input, invocation) -> {

src/site/markdown/hooks.md

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ var hooks = new SessionHooks()
2727
.setOnPreToolUse((input, invocation) -> {
2828
System.out.println("Tool: " + input.getToolName());
2929
return CompletableFuture.completedFuture(
30-
new PreToolUseHookOutput().setPermissionDecision("allow")
30+
new PreToolUseHookOutput("allow", null, null, null, null)
3131
);
3232
})
3333
.setOnPostToolUse((input, invocation) -> {
@@ -83,23 +83,20 @@ var hooks = new SessionHooks()
8383
// Block file deletion
8484
if (tool.equals("delete_file")) {
8585
return CompletableFuture.completedFuture(
86-
new PreToolUseHookOutput()
87-
.setPermissionDecision("deny")
88-
.setPermissionDecisionReason("File deletion is not allowed")
86+
new PreToolUseHookOutput("deny", "File deletion is not allowed", null, null, null)
8987
);
9088
}
9189

9290
// Require confirmation for shell commands
9391
if (tool.equals("run_terminal_cmd")) {
9492
return CompletableFuture.completedFuture(
95-
new PreToolUseHookOutput()
96-
.setPermissionDecision("ask")
93+
new PreToolUseHookOutput("ask", null, null, null, null)
9794
);
9895
}
9996

10097
// Allow everything else
10198
return CompletableFuture.completedFuture(
102-
new PreToolUseHookOutput().setPermissionDecision("allow")
99+
new PreToolUseHookOutput("allow", null, null, null, null)
103100
);
104101
});
105102
```
@@ -119,13 +116,11 @@ var hooks = new SessionHooks()
119116
modifiedArgs.set("query", input.getToolArgs().get("query"));
120117

121118
return CompletableFuture.completedFuture(
122-
new PreToolUseHookOutput()
123-
.setPermissionDecision("allow")
124-
.setModifiedArgs(modifiedArgs)
119+
new PreToolUseHookOutput("allow", null, modifiedArgs, null, null)
125120
);
126121
}
127122
return CompletableFuture.completedFuture(
128-
new PreToolUseHookOutput().setPermissionDecision("allow")
123+
new PreToolUseHookOutput("allow", null, null, null, null)
129124
);
130125
});
131126
```
@@ -315,14 +310,12 @@ public class HooksExample {
315310
// Deny dangerous operations
316311
if (input.getToolName().contains("delete")) {
317312
return CompletableFuture.completedFuture(
318-
new PreToolUseHookOutput()
319-
.setPermissionDecision("deny")
320-
.setPermissionDecisionReason("Deletion not allowed")
313+
new PreToolUseHookOutput("deny", "Deletion not allowed", null, null, null)
321314
);
322315
}
323316

324317
return CompletableFuture.completedFuture(
325-
new PreToolUseHookOutput().setPermissionDecision("allow")
318+
new PreToolUseHookOutput("allow", null, null, null, null)
326319
);
327320
})
328321

@@ -391,15 +384,13 @@ To handle errors gracefully in your hooks:
391384
try {
392385
// Your logic here
393386
return CompletableFuture.completedFuture(
394-
new PreToolUseHookOutput().setPermissionDecision("allow")
387+
new PreToolUseHookOutput("allow", null, null, null, null)
395388
);
396389
} catch (Exception e) {
397390
logger.error("Hook error", e);
398391
// Fail-safe: deny if something goes wrong
399392
return CompletableFuture.completedFuture(
400-
new PreToolUseHookOutput()
401-
.setPermissionDecision("deny")
402-
.setPermissionDecisionReason("Internal error")
393+
new PreToolUseHookOutput("deny", "Internal error", null, null, null)
403394
);
404395
}
405396
})

src/test/java/com/github/copilot/sdk/HooksTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ void testInvokePreToolUseHookWhenModelRunsATool() throws Exception {
7070
var config = new SessionConfig().setHooks(new SessionHooks().setOnPreToolUse((input, invocation) -> {
7171
preToolUseInputs.add(input);
7272
assertEquals(sessionIdHolder[0], invocation.getSessionId());
73-
return CompletableFuture.completedFuture(new PreToolUseHookOutput().setPermissionDecision("allow"));
73+
return CompletableFuture.completedFuture(new PreToolUseHookOutput("allow", null, null, null, null));
7474
}));
7575

7676
try (CopilotClient client = ctx.createClient()) {
@@ -149,7 +149,7 @@ void testInvokeBothHooksForSingleToolCall() throws Exception {
149149

150150
var config = new SessionConfig().setHooks(new SessionHooks().setOnPreToolUse((input, invocation) -> {
151151
preToolUseInputs.add(input);
152-
return CompletableFuture.completedFuture(new PreToolUseHookOutput().setPermissionDecision("allow"));
152+
return CompletableFuture.completedFuture(new PreToolUseHookOutput("allow", null, null, null, null));
153153
}).setOnPostToolUse((input, invocation) -> {
154154
postToolUseInputs.add(input);
155155
return CompletableFuture.completedFuture(null);
@@ -195,7 +195,7 @@ void testDenyToolExecutionWhenPreToolUseReturnsDeny() throws Exception {
195195
var config = new SessionConfig().setHooks(new SessionHooks().setOnPreToolUse((input, invocation) -> {
196196
preToolUseInputs.add(input);
197197
// Deny all tool calls
198-
return CompletableFuture.completedFuture(new PreToolUseHookOutput().setPermissionDecision("deny"));
198+
return CompletableFuture.completedFuture(new PreToolUseHookOutput("deny", null, null, null, null));
199199
}));
200200

201201
try (CopilotClient client = ctx.createClient()) {

src/test/java/com/github/copilot/sdk/RpcHandlerDispatcherTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ void hooksInvokeWithNullOutput() throws Exception {
469469
void hooksInvokeWithNonNullOutput() throws Exception {
470470
CopilotSession session = createSession("s1");
471471
session.registerHooks(new SessionHooks().setOnPreToolUse((input, invocation) -> CompletableFuture
472-
.completedFuture(new PreToolUseHookOutput().setPermissionDecision("allow"))));
472+
.completedFuture(new PreToolUseHookOutput("allow", null, null, null, null))));
473473

474474
ObjectNode params = MAPPER.createObjectNode();
475475
params.put("sessionId", "s1");

0 commit comments

Comments
 (0)