Adam

 view release on metacpan or  search on metacpan

ex/ai-bot.pl  view on Meta::CPAN

  );

  $server->tool(
    name         => 'recall_notes',
    description  => 'List or search your saved notes. Provide nick to see all notes about a person, query to search by keyword, or both.',
    input_schema => {
      type       => 'object',
      properties => {
        query => { type => 'string', description => 'Optional: keyword to search for in notes' },
        nick  => { type => 'string', description => 'Optional: only notes about this nick' },
      },
    },
    code => sub {
      my ($tool, $args) = @_;
      my $result = $self->memory->recall_notes($args->{nick}, $args->{query} || '');
      return $tool->text_result($result || 'No matching notes found.');
    },
  );

  $server->tool(
    name         => 'update_note',
    description  => 'Update an existing note by its ID. Use recall_notes first to find the ID.',
    input_schema => {
      type       => 'object',
      properties => {
        id      => { type => 'number', description => 'The note ID (shown as #N in recall_notes output)' },
        content => { type => 'string', description => 'The new content for this note' },
      },
      required => ['id', 'content'],
    },
    code => sub {
      my ($tool, $args) = @_;
      if ($self->memory->update_note($args->{id}, $args->{content})) {
        return $tool->text_result("Note #$args->{id} updated.");
      }
      return $tool->text_result("Note #$args->{id} not found.");
    },
  );

  $server->tool(
    name         => 'delete_note',
    description  => 'Delete a note by its ID. Use recall_notes first to find the ID.',
    input_schema => {
      type       => 'object',
      properties => {
        id => { type => 'number', description => 'The note ID to delete (shown as #N in recall_notes output)' },
      },
      required => ['id'],
    },
    code => sub {
      my ($tool, $args) = @_;
      if ($self->memory->delete_note($args->{id})) {
        return $tool->text_result("Note #$args->{id} deleted.");
      }
      return $tool->text_result("Note #$args->{id} not found.");
    },
  );

  $server->tool(
    name         => 'send_private_message',
    description  => 'Send a private message (PM) to a user. You MUST provide a reason that explicitly states who asked you to send this message. Be transparent — never pretend a PM is your own idea if someone else told you to send it.',
    input_schema => {
      type       => 'object',
      properties => {
        nick    => { type => 'string', description => 'The nick to send the private message to' },
        message => { type => 'string', description => 'The message to send' },
        reason  => { type => 'string', description => 'Who asked you to send this and why. Leave empty if the recipient themselves asked you to PM them.' },
      },
      required => ['nick', 'message'],
    },
    code => sub {
      my ($tool, $args) = @_;
      my $reason = $args->{reason} || '';
      $self->info("PM to $args->{nick}: $args->{message}" . ($reason ? " (reason: $reason)" : ''));
      $self->privmsg($args->{nick} => $args->{message});
      $self->privmsg($args->{nick} => "(reason: $reason)") if $reason;
      return $tool->text_result("Private message sent to $args->{nick}.");
    },
  );

  $server->tool(
    name         => 'whois',
    description  => 'Look up information about an IRC user (real name, host, channels, idle time, etc.). The result arrives asynchronously — you will see it as a system message shortly after calling this.',
    input_schema => {
      type       => 'object',
      properties => {
        nick => { type => 'string', description => 'The nick to look up' },
      },
      required => ['nick'],
    },
    code => sub {
      my ($tool, $args) = @_;
      $self->irc->yield(whois => $args->{nick});
      return $tool->text_result("WHOIS request sent for $args->{nick}. Results will arrive shortly as a system message.");
    },
  );

  return $server;
}

async sub _setup_raider {
  my ($self) = @_;

  my $mcp_server = $self->_build_mcp_server;
  my $loop = IO::Async::Loop::POE->new;
  my $mcp = Net::Async::MCP->new(server => $mcp_server);
  $loop->add($mcp);
  await $mcp->initialize;
  $self->_mcp($mcp);

  my $engine_class = 'Langertha::Engine::' . ($ENV{ENGINE} || 'Groq');
  use_module($engine_class);

  my %engine_args = ( mcp_servers => [$mcp] );
  $engine_args{model} = $ENV{MODEL} || 'llama-3.3-70b-versatile';
  $engine_args{api_key} = $ENV{API_KEY} if $ENV{API_KEY};

  my $engine = $engine_class->new(%engine_args);

  my $nick = $self->get_nickname;
  my $model = $engine->model;



( run in 2.247 seconds using v1.01-cache-2.11-cpan-f56aa216473 )