PAX
view release on metacpan or search on metacpan
lib/PAX/StandaloneRuntime.pm view on Meta::CPAN
);
};
return _install_sub_impl($package, $name, $sub->{prototype}, $impl);
}
if (($sub->{op} // '') eq 'skill_dispatcher_dispatch') {
my $command_spec_method = $sub->{command_spec_method} // die 'compiled sub command-spec method missing';
my $execute_hooks_method = $sub->{execute_hooks_method} // die 'compiled sub execute-hooks method missing';
my $skill_layers_method = $sub->{skill_layers_method} // die 'compiled sub skill-layers method missing';
my $skill_env_method = $sub->{skill_env_method} // die 'compiled sub skill-env method missing';
$impl = sub {
my ($self, $skill_name, $command, @args) = @_;
return { error => 'Missing skill name' } if !$skill_name;
return { error => 'Missing command name' } if !$command;
my $skill_path = $self->{manager}->get_skill_path($skill_name, include_disabled => 1);
my $suggest = __PAX_RUNTIME_LEGACY_NAMESPACE__::CLI::Suggest->new(paths => $self->{manager}{paths}, manager => $self->{manager});
return { error => $suggest->unknown_skill_command_message($skill_name, $command) } if !$skill_path;
return { error => $suggest->unknown_skill_command_message($skill_name, $command) } if !$self->{manager}->is_enabled($skill_name);
my $command_spec = _code_for($command_spec_method)->($self, $skill_name, $command);
my $cmd_path = $command_spec ? $command_spec->{cmd_path} : undef;
my $command_skill_path = $command_spec ? $command_spec->{skill_path} : undef;
return { error => $suggest->unknown_skill_command_message($skill_name, $command) } if !$cmd_path;
my $hook_result = _code_for($execute_hooks_method)->($self, $skill_name, $command, @args);
return $hook_result if $hook_result->{error};
my @skill_layers = $command_spec ? @{ $command_spec->{skill_layers} || [] } : _code_for($skill_layers_method)->($self, $skill_name);
my %env = _code_for($skill_env_method)->(
$self,
skill_name => $skill_name,
skill_path => $command_skill_path || $skill_path,
skill_layers => \@skill_layers,
command => $command_spec ? $command_spec->{command_name} : $command,
result_state => $hook_result->{result_state} || {},
);
my @command = __PAX_RUNTIME_LEGACY_NAMESPACE__::Platform::command_argv_for_path($cmd_path);
my ($stdout, $stderr, $exit) = Capture::Tiny::capture {
local %ENV = (%ENV, %env);
__PAX_RUNTIME_LEGACY_NAMESPACE__::Runtime::Result::set_current($hook_result->{result_state} || {});
if (ref($hook_result->{last_result}) eq 'HASH' && %{ $hook_result->{last_result} }) {
__PAX_RUNTIME_LEGACY_NAMESPACE__::Runtime::Result::set_last_result($hook_result->{last_result});
} else {
__PAX_RUNTIME_LEGACY_NAMESPACE__::Runtime::Result::clear_last_result();
}
__PAX_RUNTIME_LEGACY_NAMESPACE__::EnvLoader->load_runtime_layers(paths => $self->{manager}{paths});
__PAX_RUNTIME_LEGACY_NAMESPACE__::EnvLoader->load_skill_layers(skill_layers => \@skill_layers);
system(@command, @args);
};
my $hook_stdout = join '', map { defined $_->{stdout} ? $_->{stdout} : '' } values %{ $hook_result->{hooks} || {} };
my $hook_stderr = join '', map { defined $_->{stderr} ? $_->{stderr} : '' } values %{ $hook_result->{hooks} || {} };
return {
stdout => $hook_stdout . $stdout,
stderr => $hook_stderr . $stderr,
exit_code => $exit,
hooks => $hook_result->{hooks} || {},
};
};
return _install_sub_impl($package, $name, $sub->{prototype}, $impl);
}
if (($sub->{op} // '') eq 'skill_dispatcher_exec_command') {
my $command_spec_method = $sub->{command_spec_method} // die 'compiled sub command-spec method missing';
my $execute_hooks_streaming_method = $sub->{execute_hooks_streaming_method} // die 'compiled sub execute-hooks-streaming method missing';
my $skill_layers_method = $sub->{skill_layers_method} // die 'compiled sub skill-layers method missing';
my $skill_env_method = $sub->{skill_env_method} // die 'compiled sub skill-env method missing';
my $exec_resolved_method = $sub->{exec_resolved_method} // die 'compiled sub exec-resolved method missing';
$impl = sub {
my ($self, $skill_name, $command, @args) = @_;
return { error => 'Missing skill name' } if !$skill_name;
return { error => 'Missing command name' } if !$command;
my $skill_path = $self->{manager}->get_skill_path($skill_name, include_disabled => 1);
my $suggest = __PAX_RUNTIME_LEGACY_NAMESPACE__::CLI::Suggest->new(paths => $self->{manager}{paths}, manager => $self->{manager});
return { error => $suggest->unknown_skill_command_message($skill_name, $command) } if !$skill_path;
return { error => $suggest->unknown_skill_command_message($skill_name, $command) } if !$self->{manager}->is_enabled($skill_name);
my $command_spec = _code_for($command_spec_method)->($self, $skill_name, $command);
my $cmd_path = $command_spec ? $command_spec->{cmd_path} : undef;
my $command_skill_path = $command_spec ? $command_spec->{skill_path} : undef;
return { error => $suggest->unknown_skill_command_message($skill_name, $command) } if !$cmd_path;
my @skill_layers = $command_spec ? @{ $command_spec->{skill_layers} || [] } : _code_for($skill_layers_method)->($self, $skill_name);
my $hook_result = _code_for($execute_hooks_streaming_method)->($self, $skill_name, $command_spec ? $command_spec->{command_name} : $command, \@skill_layers, @args);
return $hook_result if $hook_result->{error};
my %env = _code_for($skill_env_method)->(
$self,
skill_name => $skill_name,
skill_path => $command_skill_path || $skill_path,
skill_layers => \@skill_layers,
command => $command_spec ? $command_spec->{command_name} : $command,
result_state => $hook_result->{result_state} || {},
);
my @command = __PAX_RUNTIME_LEGACY_NAMESPACE__::Platform::command_argv_for_path($cmd_path);
%ENV = (%ENV, %env);
__PAX_RUNTIME_LEGACY_NAMESPACE__::Runtime::Result::set_current($hook_result->{result_state} || {});
if (ref($hook_result->{last_result}) eq 'HASH' && %{ $hook_result->{last_result} }) {
__PAX_RUNTIME_LEGACY_NAMESPACE__::Runtime::Result::set_last_result($hook_result->{last_result});
} else {
__PAX_RUNTIME_LEGACY_NAMESPACE__::Runtime::Result::clear_last_result();
}
__PAX_RUNTIME_LEGACY_NAMESPACE__::EnvLoader->load_runtime_layers(paths => $self->{manager}{paths});
__PAX_RUNTIME_LEGACY_NAMESPACE__::EnvLoader->load_skill_layers(skill_layers => \@skill_layers);
return _code_for($exec_resolved_method)->($self, $cmd_path, \@command, \@args);
};
return _install_sub_impl($package, $name, $sub->{prototype}, $impl);
}
if (($sub->{op} // '') eq 'skill_dispatcher_execute_hooks') {
my $command_spec_method = $sub->{command_spec_method} // die 'compiled sub command-spec method missing';
my $skill_layers_method = $sub->{skill_layers_method} // die 'compiled sub skill-layers method missing';
my $skill_env_method = $sub->{skill_env_method} // die 'compiled sub skill-env method missing';
$impl = sub {
my ($self, $skill_name, $command, @args) = @_;
return { hooks => {}, result_state => {} } if !$skill_name || !$command;
my $skill_path = $self->{manager}->get_skill_path($skill_name, include_disabled => 1);
return { hooks => {}, result_state => {} } if !$skill_path;
return { hooks => {}, result_state => {} } if !$self->{manager}->is_enabled($skill_name);
my $command_spec = _code_for($command_spec_method)->($self, $skill_name, $command);
my @skill_layers = $command_spec ? @{ $command_spec->{skill_layers} || [] } : _code_for($skill_layers_method)->($self, $skill_name);
return { hooks => {}, result_state => {} } if !@skill_layers;
my $resolved_command = $command_spec ? $command_spec->{command_name} : $command;
my %results;
my $last_result = {};
for my $layer_path (@skill_layers) {
my $hooks_dir = File::Spec->catdir($layer_path, 'cli', "$resolved_command.d");
next if !-d $hooks_dir;
opendir(my $dh, $hooks_dir) or die "Unable to read $hooks_dir: $!";
for my $entry (sort grep { $_ ne '.' && $_ ne '..' } readdir($dh)) {
my $hook_path = File::Spec->catfile($hooks_dir, $entry);
next unless __PAX_RUNTIME_LEGACY_NAMESPACE__::Platform::is_runnable_file($hook_path);
my %env = _code_for($skill_env_method)->(
$self,
skill_name => $skill_name,
skill_path => $layer_path,
skill_layers => \@skill_layers,
command => $resolved_command,
result_state => \%results,
);
my @command = __PAX_RUNTIME_LEGACY_NAMESPACE__::Platform::command_argv_for_path($hook_path);
my ($stdout, $stderr, $exit) = Capture::Tiny::capture {
local %ENV = (%ENV, %env);
__PAX_RUNTIME_LEGACY_NAMESPACE__::Runtime::Result::set_current(\%results);
if (%{$last_result}) {
__PAX_RUNTIME_LEGACY_NAMESPACE__::Runtime::Result::set_last_result($last_result);
} else {
__PAX_RUNTIME_LEGACY_NAMESPACE__::Runtime::Result::clear_last_result();
}
__PAX_RUNTIME_LEGACY_NAMESPACE__::EnvLoader->load_runtime_layers(paths => $self->{manager}{paths});
__PAX_RUNTIME_LEGACY_NAMESPACE__::EnvLoader->load_skill_layers(skill_layers => \@skill_layers);
system(@command, @args);
};
my $result_key = $entry;
if (exists $results{$entry}) {
my $leaf = File::Basename::basename(File::Basename::dirname($hook_path));
$result_key = $leaf . '/' . File::Basename::basename($hook_path);
}
$results{$result_key} = { stdout => $stdout, stderr => $stderr, exit_code => $exit };
$last_result = { file => $hook_path, exit => $exit, STDOUT => $stdout, STDERR => $stderr };
}
closedir($dh);
}
my %payload = ( hooks => \%results, result_state => \%results );
$payload{last_result} = $last_result if %{$last_result};
return \%payload;
};
return _install_sub_impl($package, $name, $sub->{prototype}, $impl);
}
if (($sub->{op} // '') eq 'skill_dispatcher_execute_hooks_streaming') {
my $arrayref_or_empty_method = $sub->{arrayref_or_empty_method} // die 'compiled sub arrayref-or-empty method missing';
my $skill_env_method = $sub->{skill_env_method} // die 'compiled sub skill-env method missing';
my $run_child_streaming_method = $sub->{run_child_streaming_method} // die 'compiled sub child-streaming method missing';
$impl = sub {
my ($self, $skill_name, $command, $skill_layers, @args) = @_;
return { hooks => {}, result_state => {} } if !$skill_name || !$command;
my @skill_layers = @{ _code_for($arrayref_or_empty_method)->($self, $skill_layers) };
return { hooks => {}, result_state => {} } if !@skill_layers;
my %results;
my $last_result = {};
for my $layer_path (@skill_layers) {
my $hooks_dir = File::Spec->catdir($layer_path, 'cli', "$command.d");
next if !-d $hooks_dir;
opendir(my $dh, $hooks_dir) or die "Unable to read $hooks_dir: $!";
for my $entry (sort grep { $_ ne '.' && $_ ne '..' } readdir($dh)) {
my $hook_path = File::Spec->catfile($hooks_dir, $entry);
next unless __PAX_RUNTIME_LEGACY_NAMESPACE__::Platform::is_runnable_file($hook_path);
my %env = _code_for($skill_env_method)->(
$self,
skill_name => $skill_name,
skill_path => $layer_path,
skill_layers => \@skill_layers,
command => $command,
result_state => \%results,
);
my @hook_command = __PAX_RUNTIME_LEGACY_NAMESPACE__::Platform::command_argv_for_path($hook_path);
my $run = _code_for($run_child_streaming_method)->(
$self,
command => \@hook_command,
args => \@args,
env => \%env,
skill_layers => \@skill_layers,
result_state => \%results,
last_result => $last_result,
stdin_mode => 'null',
);
my $result_key = $entry;
if (exists $results{$entry}) {
my $leaf = File::Basename::basename(File::Basename::dirname($hook_path));
$result_key = $leaf . '/' . File::Basename::basename($hook_path);
}
$results{$result_key} = {
stdout => $run->{stdout},
stderr => $run->{stderr},
exit_code => $run->{exit_code},
};
$last_result = {
file => $hook_path,
exit => $run->{exit_code},
STDOUT => $run->{stdout},
STDERR => $run->{stderr},
};
}
closedir($dh);
}
my %payload = ( hooks => \%results, result_state => \%results );
$payload{last_result} = $last_result if %{$last_result};
return \%payload;
};
return _install_sub_impl($package, $name, $sub->{prototype}, $impl);
}
if (($sub->{op} // '') eq 'skill_dispatcher_run_child_command_streaming') {
my $arrayref_or_empty_method = $sub->{arrayref_or_empty_method} // die 'compiled sub arrayref-or-empty method missing';
my $hashref_or_empty_method = $sub->{hashref_or_empty_method} // die 'compiled sub hashref-or-empty method missing';
my $defined_or_default_method = $sub->{defined_or_default_method} // die 'compiled sub defined-or-default method missing';
$impl = sub {
my ($self, %args) = @_;
my @command = @{ _code_for($arrayref_or_empty_method)->($self, $args{command}) };
my @argv = @{ _code_for($arrayref_or_empty_method)->($self, $args{args}) };
my %env = %{ _code_for($hashref_or_empty_method)->($self, $args{env}) };
my @skill_layers = @{ _code_for($arrayref_or_empty_method)->($self, $args{skill_layers}) };
my $result_state = _code_for($hashref_or_empty_method)->($self, $args{result_state});
my $last_result = $args{last_result};
my $stdin_mode = _code_for($defined_or_default_method)->($self, $args{stdin_mode}, 'inherit');
my $stdin_spec = '<&STDIN';
my $stdin_fh;
if ($stdin_mode eq 'null') {
open $stdin_fh, '<', File::Spec->devnull() or die "Unable to open " . File::Spec->devnull() . " for streaming skill hook stdin: $!";
$stdin_spec = '<&' . fileno($stdin_fh);
}
my $stderr = Symbol::gensym();
my $stdout;
my ($stdout_text, $stderr_text) = ('', '');
my $pid;
{
local %ENV = (%ENV, %env);
__PAX_RUNTIME_LEGACY_NAMESPACE__::Runtime::Result::set_current($result_state);
if (ref($last_result) eq 'HASH' && %{$last_result}) {
__PAX_RUNTIME_LEGACY_NAMESPACE__::Runtime::Result::set_last_result($last_result);
} else {
__PAX_RUNTIME_LEGACY_NAMESPACE__::Runtime::Result::clear_last_result();
}
__PAX_RUNTIME_LEGACY_NAMESPACE__::EnvLoader->load_runtime_layers(paths => $self->{manager}{paths});
__PAX_RUNTIME_LEGACY_NAMESPACE__::EnvLoader->load_skill_layers(skill_layers => \@skill_layers);
$pid = IPC::Open3::open3($stdin_spec, $stdout, $stderr, @command, @argv);
}
close $stdin_fh if $stdin_fh;
my $selector = IO::Select->new($stdout, $stderr);
my $stdout_fd = fileno($stdout);
my $stderr_fd = fileno($stderr);
local $| = 1;
STDOUT->autoflush(1);
STDERR->autoflush(1);
while (my @ready = $selector->can_read) {
for my $fh (@ready) {
my $buffer = '';
my $read = sysread($fh, $buffer, 8192);
if (!defined $read || $read == 0) {
$selector->remove($fh);
close $fh;
next;
}
if (fileno($fh) == $stdout_fd) {
print STDOUT $buffer;
$stdout_text .= $buffer;
next;
}
if (fileno($fh) == $stderr_fd) {
print STDERR $buffer;
$stderr_text .= $buffer;
next;
}
}
}
waitpid($pid, 0);
return { stdout => $stdout_text, stderr => $stderr_text, exit_code => $? >> 8 };
};
return _install_sub_impl($package, $name, $sub->{prototype}, $impl);
}
if (($sub->{op} // '') eq 'skill_dispatcher_exec_resolved_command') {
my $arrayref_or_empty_method = $sub->{arrayref_or_empty_method} // die 'compiled sub arrayref-or-empty method missing';
my $exec_replacement_method = $sub->{exec_replacement_method} // die 'compiled sub exec-replacement method missing';
$impl = sub {
my ($self, $cmd_path, $command, $args) = @_;
my @command = @{ _code_for($arrayref_or_empty_method)->($self, $command) };
my @args = @{ _code_for($arrayref_or_empty_method)->($self, $args) };
my $error = _code_for($exec_replacement_method)->($self, \@command, \@args);
( run in 0.551 second using v1.01-cache-2.11-cpan-140bd7fdf52 )