Claude-Agent
view release on metacpan or search on metacpan
lib/Claude/Agent/Query.pm view on Meta::CPAN
package Claude::Agent::Query;
use 5.020;
use strict;
use warnings;
use Claude::Agent::Logger '$log';
use Time::HiRes ();
use Types::Common -types;
use Marlin
'prompt!', # Required prompt (string or async generator)
'options' => sub { Claude::Agent::Options->new() },
'loop?', # Optional external IO::Async loop
'_loop==.', # Internal loop reference (rw, no init_arg)
'_process==.', # IO::Async::Process handle
'_stdin==.', # stdin pipe for sending messages
'_messages==.' => sub { [] }, # Message queue
'_pending_futures==.' => sub { [] }, # Futures waiting for messages
'_session_id==.', # Session ID from init message
'_finished==.' => sub { 0 }, # Process finished flag
'_error==.', # Error message if process failed
'_sdk_servers==.' => sub { {} }, # SDK server wrappers (name => SDKServer)
'_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;
use JSON::Lines;
use Try::Tiny;
use File::Which qw(which);
use File::Spec;
use Claude::Agent::Options;
use Claude::Agent::Message;
use Claude::Agent::Error;
use Claude::Agent::MCP::SDKServer;
use Claude::Agent::Hook::Executor;
use Claude::Agent::DryRun qw(create_dry_run_hooks);
=head1 NAME
Claude::Agent::Query - Query iterator for Claude Agent SDK
=head1 SYNOPSIS
use Claude::Agent::Query;
use Claude::Agent::Options;
my $query = Claude::Agent::Query->new(
prompt => "Find all TODO comments",
options => Claude::Agent::Options->new(
allowed_tools => ['Read', 'Glob', 'Grep'],
),
);
# Blocking iteration
while (my $msg = $query->next) {
if ($msg->isa('Claude::Agent::Message::Result')) {
print $msg->result, "\n";
last;
}
}
=head1 DESCRIPTION
This module handles communication with the Claude CLI process and provides
both blocking and async iteration over response messages.
=head1 CONSTRUCTOR
my $query = Claude::Agent::Query->new(
prompt => "Find all TODO comments",
options => $options,
loop => $loop, # optional, for async integration
);
=head2 Arguments
=over 4
=item * prompt - Required. The prompt to send to Claude.
=item * options - Optional. A Claude::Agent::Options object.
=item * loop - Optional. An IO::Async::Loop for async integration.
If not provided, a new loop is created internally.
=back
( run in 2.653 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )