Acme-Claude-Shell
view release on metacpan or search on metacpan
lib/Acme/Claude/Shell/Session.pm view on Meta::CPAN
=back
=head2 History
Command history is persisted to C<~/.acme_claude_shell_history> and loaded
on startup. Maximum 1000 lines are kept.
=cut
# Query cursor row position via /dev/tty (works even after Term::ReadLine)
# This avoids Term::ProgressSpinner's STDIN-based query which fails after readline
sub _get_cursor_row {
my $row;
eval {
require Term::ReadKey;
open(my $tty, '+<', '/dev/tty') or return undef;
# Set raw mode on the tty
Term::ReadKey::ReadMode(4, $tty);
# Send cursor position query to STDOUT (terminal sees it)
print STDOUT "\e[6n";
STDOUT->flush();
# Read response from the tty
my $response = '';
while (1) {
my $c = Term::ReadKey::ReadKey(0.1, $tty);
last unless defined $c;
$response .= $c;
last if $c eq 'R';
}
lib/Acme/Claude/Shell/Session.pm view on Meta::CPAN
await $self->_process_input($input);
}
status('info', "Goodbye!") if $self->colorful;
return 1;
}
async sub _process_input {
my ($self, $input) = @_;
# Query cursor position via /dev/tty before starting spinner
# This avoids Term::ProgressSpinner's STDIN query which fails after Term::ReadLine
my $cursor_row = _get_cursor_row();
# Store spinner in session so hooks can stop it before reading STDIN
# Pick a random fun spinner each time
$self->_spinner(start_spinner("Thinking...", $self->loop,
_random_spinner(),
defined $cursor_row ? (terminal_line => $cursor_row) : ()));
# First turn or follow-up
if ($self->_client->session_id) {
$self->_client->send($input);
} else {
$self->_client->connect($input);
}
my $printed_response = 0;
( run in 3.435 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )