-
Notifications
You must be signed in to change notification settings - Fork 0
feat: implement command hook system (#32) #41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
dd6c388
feat: implement command hook system (#32)
c5706b1
fix: read stdout/stderr concurrently to prevent pipe deadlock on Linux
b9dceb7
fix: start stdout/stderr readers before stdin write to prevent data loss
ccb7a85
refactor: address CodeRabbit review feedback on PR #41
77d4e9a
fix: guard against null in hook merge and PostToolUseFailure
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
65 changes: 65 additions & 0 deletions
65
aceclaw-core/src/main/java/dev/aceclaw/core/agent/HookEvent.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| package dev.aceclaw.core.agent; | ||
|
|
||
| import com.fasterxml.jackson.databind.JsonNode; | ||
|
|
||
| /** | ||
| * Events that trigger hook execution at different points in the tool lifecycle. | ||
| * | ||
| * <p>Three event types correspond to Claude Code's hook events: | ||
| * <ul> | ||
| * <li>{@link PreToolUse} — fired before tool execution (blocking; can modify input or block)</li> | ||
| * <li>{@link PostToolUse} — fired after successful tool execution (non-blocking)</li> | ||
| * <li>{@link PostToolUseFailure} — fired after failed tool execution (non-blocking)</li> | ||
| * </ul> | ||
| */ | ||
| public sealed interface HookEvent { | ||
|
|
||
| /** The session ID of the current agent session. */ | ||
| String sessionId(); | ||
|
|
||
| /** The current working directory. */ | ||
| String cwd(); | ||
|
|
||
| /** The name of the tool being invoked. */ | ||
| String toolName(); | ||
|
|
||
| /** The tool input as a JSON object. */ | ||
| JsonNode toolInput(); | ||
|
|
||
| /** | ||
| * The event type name used in config matching and JSON serialization | ||
| * (e.g. "PreToolUse", "PostToolUse", "PostToolUseFailure"). | ||
| */ | ||
| String eventName(); | ||
|
|
||
| /** | ||
| * Fired before a tool is executed. The hook can block execution or modify the input. | ||
| */ | ||
| record PreToolUse(String sessionId, String cwd, String toolName, JsonNode toolInput) | ||
| implements HookEvent { | ||
| @Override | ||
| public String eventName() { return "PreToolUse"; } | ||
| } | ||
|
|
||
| /** | ||
| * Fired after a tool executes successfully. Non-blocking — hooks run but cannot alter the result. | ||
| * | ||
| * @param toolOutput the textual output of the tool execution | ||
| */ | ||
| record PostToolUse(String sessionId, String cwd, String toolName, JsonNode toolInput, | ||
| String toolOutput) implements HookEvent { | ||
| @Override | ||
| public String eventName() { return "PostToolUse"; } | ||
| } | ||
|
|
||
| /** | ||
| * Fired after a tool execution fails. Non-blocking — hooks run for auditing/logging. | ||
| * | ||
| * @param error the error message from the failed execution | ||
| */ | ||
| record PostToolUseFailure(String sessionId, String cwd, String toolName, JsonNode toolInput, | ||
| String error) implements HookEvent { | ||
| @Override | ||
| public String eventName() { return "PostToolUseFailure"; } | ||
| } | ||
| } |
21 changes: 21 additions & 0 deletions
21
aceclaw-core/src/main/java/dev/aceclaw/core/agent/HookExecutor.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package dev.aceclaw.core.agent; | ||
|
|
||
| /** | ||
| * Executes hooks for a given hook event. | ||
| * | ||
| * <p>Implementations run one or more hook commands (shell scripts, binaries, etc.) | ||
| * and return the aggregate result. For {@link HookEvent.PreToolUse} events, | ||
| * the first {@link HookResult.Block} stops further hook execution. | ||
| * For post-execution events, all hooks always run. | ||
| */ | ||
| @FunctionalInterface | ||
| public interface HookExecutor { | ||
|
|
||
| /** | ||
| * Executes all matching hooks for the given event. | ||
| * | ||
| * @param event the hook event describing the tool invocation context | ||
| * @return the result of hook execution | ||
| */ | ||
| HookResult execute(HookEvent event); | ||
| } |
44 changes: 44 additions & 0 deletions
44
aceclaw-core/src/main/java/dev/aceclaw/core/agent/HookResult.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| package dev.aceclaw.core.agent; | ||
|
|
||
| import com.fasterxml.jackson.databind.JsonNode; | ||
|
|
||
| /** | ||
| * Result of a hook execution, determining whether tool execution should proceed. | ||
| * | ||
| * <p>Exit code semantics (matching Claude Code): | ||
| * <ul> | ||
| * <li>0 → {@link Proceed} — allow execution, optionally with modified input</li> | ||
| * <li>2 → {@link Block} — block execution with a reason</li> | ||
| * <li>other → {@link Error} — non-blocking error, log and continue</li> | ||
| * </ul> | ||
| */ | ||
| public sealed interface HookResult { | ||
|
|
||
| /** | ||
| * Hook permits execution to proceed. | ||
| * | ||
| * @param stdout raw stdout from the hook process | ||
| * @param updatedInput optional modified tool input (null = no modification) | ||
| * @param additionalContext optional context string to append to tool description | ||
| */ | ||
| record Proceed(String stdout, JsonNode updatedInput, String additionalContext) implements HookResult { | ||
| /** Convenience constructor for a simple proceed with no modifications. */ | ||
| public Proceed() { this(null, null, null); } | ||
| } | ||
|
|
||
| /** | ||
| * Hook blocks execution. | ||
| * | ||
| * @param reason human-readable reason for blocking | ||
| */ | ||
| record Block(String reason) implements HookResult {} | ||
|
|
||
| /** | ||
| * Hook encountered a non-blocking error (exit code != 0 and != 2). | ||
| * Execution should continue; the error is logged. | ||
| * | ||
| * @param exitCode the process exit code | ||
| * @param message stderr or error description | ||
| */ | ||
| record Error(int exitCode, String message) implements HookResult {} | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.