Claude-Agent

 view release on metacpan or  search on metacpan

lib/Claude/Agent/Hook/Executor.pm  view on Meta::CPAN

package Claude::Agent::Hook::Executor;

use 5.020;
use strict;
use warnings;

use Claude::Agent::Logger '$log';
use Types::Common -types;
use Scalar::Util qw(blessed);
use Try::Tiny;
use Future;

use Claude::Agent::Hook;
use Claude::Agent::Hook::Context;
use Claude::Agent::Hook::Result;

use Marlin
    'hooks'       => sub { {} },      # Event name => arrayref of matchers
    'session_id==.',                  # Read-write, set after init message
    'cwd?',
    'loop?';                          # Optional IO::Async::Loop for async hooks

=head1 NAME

Claude::Agent::Hook::Executor - Executes Perl hooks for Claude Agent SDK

=head1 SYNOPSIS

    use Claude::Agent::Hook::Executor;
    use Claude::Agent::Hook::Matcher;

    my $executor = Claude::Agent::Hook::Executor->new(
        hooks => {
            PreToolUse => [
                Claude::Agent::Hook::Matcher->new(
                    matcher => 'Bash',
                    hooks   => [sub {
                        my ($input, $tool_use_id, $context) = @_;
                        if ($input->{tool_input}{command} =~ /rm -rf/) {
                            return Claude::Agent::Hook::Result->deny(
                                reason => 'Dangerous command blocked',
                            );
                        }
                        return Claude::Agent::Hook::Result->proceed();
                    }],
                ),
            ],
        },
        session_id => $session_id,
    );

    # Execute pre-tool-use hooks
    my $result = $executor->run_pre_tool_use($tool_name, $tool_input, $tool_use_id);

    if ($result->{decision} eq 'deny') {
        # Block the tool
    }

=head1 DESCRIPTION

This module executes Perl hook callbacks when tool use events occur.
It intercepts tool calls in the Query layer and runs matching hooks.

=head1 ATTRIBUTES

=head2 hooks

HashRef of hook event names to arrayrefs of L<Claude::Agent::Hook::Matcher> objects.

=head2 session_id

Current session ID (set after init message).

=head2 cwd

Current working directory.

=head2 loop

Optional IO::Async::Loop for async hook execution.

=head1 METHODS

=head2 run_pre_tool_use

    my $future = $executor->run_pre_tool_use($tool_name, $tool_input, $tool_use_id);

Execute PreToolUse hooks for a tool call. Returns a Future that resolves to a hashref with:

    {
        decision      => 'continue' | 'allow' | 'deny',
        reason        => 'optional reason',
        updated_input => { ... },  # for 'allow' decision
    }

=cut

sub run_pre_tool_use {
    my ($self, $tool_name, $tool_input, $tool_use_id) = @_;

    return $self->_run_hooks(



( run in 0.735 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )