Claude-Agent
view release on metacpan or search on metacpan
lib/Claude/Agent.pm view on Meta::CPAN
=head1 EXPORTED FUNCTIONS
=head2 query
my $iter = query(
prompt => $prompt,
options => $options,
loop => $loop, # optional, for async integration
);
Creates a new query and returns an iterator for streaming messages.
=head3 Arguments
=over 4
=item * prompt - The prompt string to send to Claude
=item * options - A L<Claude::Agent::Options> object (optional)
=item * loop - An L<IO::Async::Loop> object (optional, for async integration)
lib/Claude/Agent/Options.pm view on Meta::CPAN
# Structured output
'output_format?', # JSON schema for structured outputs
# Settings sources
'setting_sources?' => ArrayRef[Str], # 'user', 'project', 'local'
# Sandbox settings
'sandbox?', # Sandbox configuration
# Include partial messages during streaming
'include_partial_messages?' => Bool,
# Continue conversation from previous messages
'continue_conversation?' => Bool,
# Query timeout in seconds (default 600 = 10 minutes)
'query_timeout?' => Int,
# Dry-run mode - preview tool calls without executing writes
'dry_run?' => Bool,
lib/Claude/Agent/Options.pm view on Meta::CPAN
ArrayRef specifying which settings files to load. Valid values:
'user', 'project', 'local'.
=head2 sandbox
Sandbox configuration settings.
=head2 include_partial_messages
Boolean. If true, include partial messages during streaming.
=head2 continue_conversation
Boolean. If true, continue from previous conversation messages.
=head2 query_timeout
Timeout in seconds for the C<next()> method to wait for messages.
Defaults to 600 seconds (10 minutes). Set to a lower value for
interactive applications, or higher for complex long-running queries.
lib/Claude/Agent/Query.pm view on Meta::CPAN
'_hook_executor==.', # Hook executor for Perl callbacks
'_pending_tool_uses==.' => sub { {} }, # Track tool uses awaiting results
'_processing_message==.' => sub { 0 }, # Guard against concurrent message processing
'_cleaned_up==.' => sub { 0 }, # Track if cleanup() has been called
'_jsonl==.' => sub {
JSON::Lines->new(
utf8 => 1,
error_cb => sub {
my ($action, $error, $data) = @_;
# Only log at trace level since parse errors are common
# with streaming JSON and partial data
$log->trace("JSON::Lines $action error: $error");
return;
},
)
};
use IO::Async::Loop;
use IO::Async::Process;
use Future;
use Future::AsyncAwait;
lib/Claude/Agent/Query.pm view on Meta::CPAN
# This catches any escape sequences not matched above
$sanitized_prompt =~ s/\x1b.//g;
# Ultimate safety: strip any remaining bare ESC (0x1B) bytes entirely
# This handles edge cases with multi-byte sequences in exotic terminal emulators
$sanitized_prompt =~ s/\x1b//g;
push @cmd, '--print', '--', $sanitized_prompt;
}
else {
# For streaming input (async generator), use stream-json input format
push @cmd, '--input-format', 'stream-json';
}
return @cmd;
}
sub _start_process {
my ($self) = @_;
my @cmd = $self->_build_command();
lib/Claude/Agent/Query.pm view on Meta::CPAN
$self->_process($process);
$self->_stdin($process->stdin);
$self->_loop->add($process);
# For --print mode, prompt is in argv, stdin can be closed
if (!ref($self->prompt)) {
$self->_loop->later(sub {
$self->_stdin->close_when_empty if $self->_stdin;
});
}
# For ref prompts (streaming input), caller will send messages via send_user_message
return;
}
sub _handle_line {
my ($self, $line) = @_;
return unless defined $line && length $line;
# Use JSON::Lines decode method for single line
my @decoded = $self->_jsonl->decode($line);
lib/Claude/Agent/Query.pm view on Meta::CPAN
my $msg = $self->_jsonl->encode([{ type => 'interrupt' }]);
return unless defined $msg && length $msg;
$self->_stdin->write($msg);
return;
}
=head2 send_user_message
$query->send_user_message("Continue with the next step");
Send a follow-up user message during streaming.
=cut
sub send_user_message {
my ($self, $content) = @_;
return unless $self->_stdin && !$self->_finished;
my $msg = $self->_jsonl->encode([{
type => 'user',
lib/Claude/Agent/Query.pm view on Meta::CPAN
$log->debug(sprintf("send_user_message write error: %s", $_));
$result = 0;
};
return $result;
}
=head2 set_permission_mode
$query->set_permission_mode('acceptEdits');
Change permission mode during streaming.
=cut
sub set_permission_mode {
my ($self, $mode) = @_;
return unless $self->_stdin && !$self->_finished;
my $msg = $self->_jsonl->encode([{
type => 'set_permission_mode',
( run in 0.843 second using v1.01-cache-2.11-cpan-140bd7fdf52 )