Adam
view release on metacpan or search on metacpan
1.003 2026-03-11 02:08:02Z
+ Administrative update to cleanup the provides for CPAN
1.002 2026-03-08 05:06:55Z
+ Updated POD: Adam and Moses now document IO::Async support and dual event loop modes
+ ai-bot example: multi-channel support with per-channel message buffers
+ ai-bot example: SYSTEM_PROMPT env var for custom system prompt additions
+ ai-bot example: error messages only shown in main channel
+ ai-bot example: typing delay now happens BEFORE each line for more human-like output
+ ai-bot example: info-level logging for all incoming IRC events (public, join, part, quit, PM) with channel/source
+ Default logger now includes timestamps in [YYYY-MM-DD HH:MM:SS] [level] format
+ Fixed stray =cut in Adam.pm that hid async() and stop() methods from compilation
+ Fixed logger timestamps: log_dispatch_conf callback instead of around log
1.001 2026-03-07 19:44:57Z
1.000 2026-03-07 03:12:40Z
+ Switched to @Author::GETTY Dist::Zilla plugin bundle
+ Added IO::Async support via ->async() method (requires IO::Async::Loop::POE)
+ Added ->stop() method for cleanly stopping both POE and IO::Async event loops
+ Modernized POD documentation to inline format
+ Added cpanfile for dependency management
+ Fix a mistake we accidentally released in 0.07
0.07 2010-06-10
+ Fix _build__irc to pull from the bot configuration (stephan48)
+ Add RT Plugin example and netcat bot example
0.06 2009-10-30
+ Moses::Declare
MooseX::Declare derived syntax for writing Bots, very experimental.
+ Adam::Logger
Refactor of the logging API so that we can use alternate Logging
implementations, ie Log4perl support.
0.05 2009-09-24
+ Add missing build_requires for Test::Deep
0.04 2009-09-23
+ Remove dependency on MooseX::AttributeHelpers in favor of Moose's Native::Attributes
+ Add MooseX::Aliases dependency for nick/nickname
+ refactor code and clean up generally for release to CPAN
lib/Moses.pm
lib/Moses/Declare.pm
lib/Moses/Declare/Syntax/BotKeyword.pm
lib/Moses/Declare/Syntax/EventKeyword.pm
lib/Moses/Declare/Syntax/PluginKeyword.pm
lib/Moses/Plugin.pm
lib/oses.pm
t/00.load.t
t/01.simple.t
t/02.override.t
t/03.logger.t
t/04.declare.t
t/05.async.t
t/author-pod-syntax.t
"Dist::Zilla::Plugin::Git::Commit" : {
"add_files_in" : [],
"commit_msg" : "v%V%n%n%c",
"signoff" : 0
},
"Dist::Zilla::Role::Git::DirtyFiles" : {
"allow_dirty" : [
"Changes"
],
"allow_dirty_match" : [],
"changelog" : "Changes"
},
"Dist::Zilla::Role::Git::Repo" : {
"git_version" : "2.39.5",
"repo_root" : "."
},
"Dist::Zilla::Role::Git::StringFormatter" : {
"time_zone" : "local"
}
},
"name" : "@Author::GETTY/@Git::VersionManager/release snapshot",
"version" : "2.052"
},
{
"class" : "Dist::Zilla::Plugin::Git::Tag",
"config" : {
"Dist::Zilla::Plugin::Git::Tag" : {
"branch" : null,
"changelog" : "Changes",
"signed" : 0,
"tag" : "1.003",
"tag_format" : "%v",
"tag_message" : "v%V"
},
"Dist::Zilla::Role::Git::Repo" : {
"git_version" : "2.39.5",
"repo_root" : "."
},
"Dist::Zilla::Role::Git::StringFormatter" : {
},
"Dist::Zilla::Role::Git::DirtyFiles" : {
"allow_dirty" : [
"Build.PL",
"Changes",
"Makefile.PL"
],
"allow_dirty_match" : [
"(?^:^lib/.*\\.pm$)"
],
"changelog" : "Changes"
},
"Dist::Zilla::Role::Git::Repo" : {
"git_version" : "2.39.5",
"repo_root" : "."
},
"Dist::Zilla::Role::Git::StringFormatter" : {
"time_zone" : "local"
}
},
"name" : "@Author::GETTY/@Git::VersionManager/post-release commit",
class: Dist::Zilla::Plugin::Git::Commit
config:
Dist::Zilla::Plugin::Git::Commit:
add_files_in: []
commit_msg: v%V%n%n%c
signoff: 0
Dist::Zilla::Role::Git::DirtyFiles:
allow_dirty:
- Changes
allow_dirty_match: []
changelog: Changes
Dist::Zilla::Role::Git::Repo:
git_version: 2.39.5
repo_root: .
Dist::Zilla::Role::Git::StringFormatter:
time_zone: local
name: '@Author::GETTY/@Git::VersionManager/release snapshot'
version: '2.052'
-
class: Dist::Zilla::Plugin::Git::Tag
config:
Dist::Zilla::Plugin::Git::Tag:
branch: ~
changelog: Changes
signed: 0
tag: '1.003'
tag_format: '%v'
tag_message: v%V
Dist::Zilla::Role::Git::Repo:
git_version: 2.39.5
repo_root: .
Dist::Zilla::Role::Git::StringFormatter:
time_zone: local
name: '@Author::GETTY/@Git::VersionManager/Git::Tag'
add_files_in: []
commit_msg: 'increment $VERSION after %v release'
signoff: 0
Dist::Zilla::Role::Git::DirtyFiles:
allow_dirty:
- Build.PL
- Changes
- Makefile.PL
allow_dirty_match:
- (?^:^lib/.*\.pm$)
changelog: Changes
Dist::Zilla::Role::Git::Repo:
git_version: 2.39.5
repo_root: .
Dist::Zilla::Role::Git::StringFormatter:
time_zone: local
name: '@Author::GETTY/@Git::VersionManager/post-release commit'
version: '2.052'
-
class: Dist::Zilla::Plugin::Git::Push
config:
__PACKAGE__->run unless caller;
```
## Features
- **Declarative syntax** - Simple DSL for bot configuration
- **Plugin system** - Easy to extend with POE::Component::IRC plugins
- **Multiple event loops** - Supports both POE (default) and IO::Async
- **Command-line options** - Built-in support via MooseX::Getopt
- **Logging** - Configurable logging via MooseX::LogDispatch
## IO::Async Support
You can use IO::Async as the event loop (requires IO::Async::Loop::POE):
```perl
package AsyncBot;
use Moses;
use namespace::autoclean;
ex/ai-bot.pl view on Meta::CPAN
- Silence is your default state. Speaking is the exception.
- You should be silent at LEAST 80% of the time.
HOW TO RESPOND (when you actually should):
- Write plain text. Your messages appear in the channel as-is.
- To address someone, write their nick followed by a colon: Getty: hey there
- Input uses <nick> format but your output is always plain text with nick: format.
- You can address different people on different lines.
- Or say something to the whole channel without any prefix.
- Each newline becomes a separate IRC message with a small delay between them.
- Keep it SHORT. One or two lines is usually enough. This is chat, not a blog.
- NEVER narrate your tool usage in the chat. Tools work silently in the background.
Don't write things like "*save_note: ...*" or "Let me look that up..." â just do it.
IRC LINE CONSTRAINTS:
- Each line has a hard limit of $MAX_LINE characters. Never exceed this.
- Keep lines short and conversational. This is chat, not email.
- No markdown, no bullet points, no code blocks. Plain text only.
- Shorter is always better. Seriously. Less is more.
PRIVATE MESSAGES:
ex/rt-plugin.pl view on Meta::CPAN
has rt => (
isa => 'RT::Client::REST',
is => 'ro',
lazy_build => 1,
handles => { show_ticket => [ 'show', ( type => 'ticket' ) ] },
);
sub _build_rt {
my $rt = RT::Client::REST->new( server => $_[0]->server );
$rt->login( username => $_[0]->user, password => $_[0]->pass, );
return $rt;
}
sub ticket {
my ( $self, $id ) = @_;
try {
if ( my $t = $self->show_ticket( id => $id ) ) {
return "$$t{Status} #${id}: $$t{Subject}";
}
return "Ticket $id not found";
lib/Adam.pm view on Meta::CPAN
use MooseX::Aliases;
use Adam::Logger::Default;
with qw(
MooseX::SimpleConfig
MooseX::Getopt
);
has logger => (
does => 'Adam::Logger::API',
is => 'ro',
traits => ['NoGetopt'],
lazy_build => 1,
handles => 'Adam::Logger::API',
);
sub _build_logger { Adam::Logger::Default->new() }
has nickname => (
isa => 'Str',
reader => 'get_nickname',
alias => 'nick',
traits => ['Getopt'],
cmd_flag => 'nickname',
required => 1,
builder => 'default_nickname',
);
lib/Adam.pm view on Meta::CPAN
The Adam class implements an IRC bot based on L<POE::Component::IRC::State>,
L<Moose>, and L<MooseX::POE>. It supports two event loop modes: the default
L<POE> loop via C<run()>, and an L<IO::Async> mode via C<async()> that allows
integration with other L<IO::Async>-based components through
L<IO::Async::Loop::POE>.
Adam is not meant to be used directly â see L<Moses> for the declarative
sugar layer.
=head2 logger
Logger object that implements the L<Adam::Logger::API> role. Defaults to
L<Adam::Logger::Default>.
=head2 nickname
The IRC nickname for the bot. Defaults to the package name. Required.
=head2 server
lib/Adam/Logger/API.pm view on Meta::CPAN
package Adam::Logger::API;
# ABSTRACT: API Role for the Adam logger
our $VERSION = '1.003';
use Moose::Role;
use namespace::autoclean;
requires qw(
log
debug
info
notice
warning
error
critical
alert
emergency
);
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
Adam::Logger::API - API Role for the Adam logger
=head1 VERSION
version 1.003
=head1 DESCRIPTION
Defines the logging API interface required for Adam bot loggers.
=head1 SUPPORT
=head2 Issues
Please report bugs and feature requests on GitHub at
L<https://github.com/perigrin/adam-bot-framework/issues>.
=head2 IRC
lib/Adam/Logger/Default.pm view on Meta::CPAN
package Adam::Logger::Default;
# ABSTRACT: Default logger for Adam bots
our $VERSION = '1.003';
use Moose;
use POSIX qw( strftime );
sub log_dispatch_conf {
return {
class => 'Log::Dispatch::Screen',
min_level => 'debug',
stderr => 1,
callbacks => sub {
my %p = @_;
my $ts = strftime('%Y-%m-%d %H:%M:%S', localtime);
return "[$ts] [$p{level}] $p{message}\n";
},
};
lib/Adam/Logger/Default.pm view on Meta::CPAN
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
Adam::Logger::Default - Default logger for Adam bots
=head1 VERSION
version 1.003
=head1 DESCRIPTION
Default logging implementation for Adam bots using L<MooseX::LogDispatch::Levels>.
Log messages include timestamps in C<[YYYY-MM-DD HH:MM:SS]> format.
=head1 SUPPORT
=head2 Issues
Please report bugs and feature requests on GitHub at
L<https://github.com/perigrin/adam-bot-framework/issues>.
=head2 IRC
lib/Adam/Plugin.pm view on Meta::CPAN
use Moose;
use namespace::autoclean;
has bot => (
isa => 'Adam',
is => 'ro',
required => 1,
handles => [
qw(
log
owner
irc
yield
privmsg
nick
)
],
);
lib/Adam/Plugin.pm view on Meta::CPAN
sub PCI_unregister {
my ( $self, $irc ) = @_;
return 1;
}
sub _default {
my ( $self, $irc, $event ) = @_;
$self->log->notice("_default called for $event");
}
1;
__END__
=pod
=encoding UTF-8
lib/Adam/Plugin.pm view on Meta::CPAN
version 1.003
=head1 DESCRIPTION
The Adam::Plugin class implements a base class for Adam/Moses IRC bot plugins.
=head2 bot
The L<Adam> bot instance. Required. Handles several methods from the bot
including C<log>, C<owner>, C<irc>, C<yield>, C<privmsg>, and C<nick>.
=head2 default_events
The default events that this plugin will listen to. Returns an ArrayRef of all
methods prefixed with C<S_> (server events) or C<U_> (user events) in the current
class.
=head2 PCI_register
Called when the plugin is registered with the IRC component. Automatically
( run in 1.584 second using v1.01-cache-2.11-cpan-5837b0d9d2c )