Adam
view release on metacpan or search on metacpan
ex/ai-bot.pl view on Meta::CPAN
$answer =~ s/<\s*\@?\s*(\w+)\s*>/$1/g; # mid-text <nick> â Nick
$answer =~ s/<\/?\w+>//g; # strip remaining XML tags
# Strip lines where the AI narrates its tool usage
$answer =~ s/^\*?\s*(save_note|recall_notes|update_note|delete_note|recall_history|stay_silent|set_alarm|whois|send_private_message)\b[^\n]*\n?//mg;
# Check for lines too long
my @lines = grep { length } map { s/^\s+//r =~ s/\s+$//r } split(/\n/, $answer);
my $too_long = grep { length($_) > $MAX_LINE } @lines;
if ($too_long) {
$self->info("Response too long, asking to shorten");
$answer = eval {
my $retry = $self->_raider->raid(
"Your last response had lines over $MAX_LINE characters. "
. "Rewrite it shorter. Every line must be under $MAX_LINE chars."
);
"$retry";
} || $answer;
}
# Store conversations
for my $m (@$messages) {
$self->memory->store_conversation(
nick => $m->{nick}, message => $m->{msg},
response => $answer, channel => $m->{channel},
);
}
$self->_send_to_channel($channel, $answer);
# Process any messages that arrived while we were thinking
$self->_schedule_pending_buffers;
}
event _retry_raid => sub {
my ($self) = $_[OBJECT];
$self->info("Retrying raid...");
$self->_do_raid;
};
event _alarm_fired => sub {
my ( $self, $channel, $reason ) = @_[ OBJECT, ARG0, ARG1 ];
$self->info("Alarm fired: $reason");
$self->_buffer_message($channel, 'system',
"ALARM FIRED: $reason â You set this alarm earlier. Decide what to do now.");
};
event _idle_check => sub {
my ($self) = $_[OBJECT];
my $idle_secs = time() - $self->_last_activity;
if ($idle_secs >= $IDLE_PING && !$self->_processing) {
my $idle_mins = int($idle_secs / 60);
$self->info("Idle ping after ${idle_mins}m");
# Ping first channel only (idle is a global concept)
my $channel = $self->_default_channel;
$self->_buffer_message($channel, 'system',
"No activity for $idle_mins minutes. You can say something if you want, or stay_silent.");
}
POE::Kernel->delay( _idle_check => $IDLE_PING );
};
event irc_public => sub {
my ( $self, $nickstr, $channels, $msg ) = @_[ OBJECT, ARG0, ARG1, ARG2 ];
my ( $nick ) = split /!/, $nickstr;
return if $nick eq $self->get_nickname;
my $channel = ref $channels ? $channels->[0] : $channels;
$self->info("$channel <$nick> $msg");
$self->_last_activity(time());
$self->_buffer_message($channel, $nick, $msg);
};
event irc_join => sub {
my ( $self, $nickstr, $channel ) = @_[ OBJECT, ARG0, ARG1 ];
my ( $nick, $host ) = split /!/, $nickstr, 2;
return if $nick eq $self->get_nickname;
$self->info("$channel $nick ($host) joined");
$self->_last_activity(time());
$self->_buffer_message($channel, 'system',
"$nick ($host) has joined the channel. Greet them if you like!");
};
event irc_part => sub {
my ( $self, $nickstr, $channel, $reason ) = @_[ OBJECT, ARG0, ARG1, ARG2 ];
my ( $nick, $host ) = split /!/, $nickstr, 2;
return if $nick eq $self->get_nickname;
$self->info("$channel $nick ($host) parted" . ($reason ? ": $reason" : ''));
$self->_last_activity(time());
my $msg = "$nick ($host) has left the channel";
$msg .= ": $reason" if $reason;
$self->_buffer_message($channel, 'system', $msg);
};
sub _is_netsplit_reason {
my ($self, $reason) = @_;
return 0 unless $reason;
# Netsplit quit reasons look like "server1.network.org server2.network.org"
return $reason =~ /^\S+\.\S+ \S+\.\S+$/ ? 1 : 0;
}
event irc_quit => sub {
my ( $self, $nickstr, $reason ) = @_[ OBJECT, ARG0, ARG1 ];
my ( $nick, $host ) = split /!/, $nickstr, 2;
return if $nick eq $self->get_nickname;
$self->info("$nick ($host) quit" . ($reason ? ": $reason" : ''));
$self->_last_activity(time());
my $channel = $self->_default_channel;
if ($self->_is_netsplit_reason($reason)) {
push @{$self->_netsplit_quits}, $nick;
# Delay reporting â collect all netsplit quits in a short window
POE::Kernel->delay( _netsplit_report => 3, $channel, $reason );
return;
}
my $msg = "$nick ($host) has quit IRC";
$msg .= ": $reason" if $reason;
$self->_buffer_message($channel, 'system', $msg);
};
event _netsplit_report => sub {
my ( $self, $channel, $split_reason ) = @_[ OBJECT, ARG0, ARG1 ];
my @nicks = @{$self->_netsplit_quits};
( run in 1.461 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )