Langertha-Knarr
view release on metacpan or search on metacpan
lib/Langertha/Knarr/Protocol.pm view on Meta::CPAN
package Langertha::Knarr::Protocol;
# ABSTRACT: Role for Knarr wire protocols (OpenAI, Anthropic, Ollama, A2A, ACP, AG-UI)
our $VERSION = '1.100';
use Moose::Role;
# Identifier (e.g. 'openai', 'anthropic', 'ollama').
requires 'protocol_name';
# Returns arrayref of route specs:
# [ { method => 'POST', path => '/v1/chat/completions', action => 'chat' }, ... ]
requires 'protocol_routes';
# parse_chat_request($http_req, $body_ref) -> Langertha::Knarr::Request
requires 'parse_chat_request';
# format_chat_response($response, $request) -> ($status, \%headers, $body)
requires 'format_chat_response';
# format_stream_chunk($chunk, $request) -> string (raw bytes for the wire)
# Default: SSE-style "data: {...}\n\n" â protocols may override (Ollama uses NDJSON).
sub format_stream_chunk {
my ($self, $chunk_json) = @_;
return "data: $chunk_json\n\n";
}
sub format_stream_done {
my ($self) = @_;
return "data: [DONE]\n\n";
}
# Optional lifecycle hooks for protocols that need to frame the stream
# (Anthropic message_start/stop, A2A status events, ACP run.created, AGUI RUN_STARTED).
# Default: empty â protocols like OpenAI / Ollama don't need them.
sub format_stream_open { '' }
sub format_stream_close { '' }
# Content-Type for streaming responses. Default is SSE; Ollama overrides.
sub stream_content_type { 'text/event-stream' }
# format_models_response(\@models) -> ($status, \%headers, $body)
sub format_models_response {
my ($self, $models) = @_;
return ( 200, { 'Content-Type' => 'application/json' }, '{"data":[]}' );
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
Langertha::Knarr::Protocol - Role for Knarr wire protocols (OpenAI, Anthropic, Ollama, A2A, ACP, AG-UI)
=head1 VERSION
version 1.100
=head1 DESCRIPTION
The role every Knarr wire protocol must consume. A protocol declares
its routes, parses incoming HTTP bodies into a normalized
L<Langertha::Knarr::Request>, and formats outgoing
L<Langertha::Knarr::Stream> chunks back into the protocol-native wire
format. The Knarr core dispatches each request to the right handler
via the matched protocol's parser/formatter.
Knarr ships with six concrete protocols, all loaded by default:
=over
=item * L<Langertha::Knarr::Protocol::OpenAI> â C</v1/chat/completions>, SSE
=item * L<Langertha::Knarr::Protocol::Anthropic> â C</v1/messages>, named SSE events
=item * L<Langertha::Knarr::Protocol::Ollama> â C</api/chat>, NDJSON streaming
=item * L<Langertha::Knarr::Protocol::A2A> â Google Agent2Agent JSON-RPC
=item * L<Langertha::Knarr::Protocol::ACP> â IBM/BeeAI Agent Communication Protocol
=item * L<Langertha::Knarr::Protocol::AGUI> â CopilotKit AG-UI event protocol
=back
=head2 protocol_name
Required. Returns a short string identifier (e.g. C<'openai'>).
=head2 protocol_routes
Required. Returns an arrayref of route specs of the form
C<< { method => 'POST', path => '/v1/chat/completions', action => 'chat' } >>.
Action names map to C<_action_*> methods on the Knarr core.
=head2 parse_chat_request
my $req = $proto->parse_chat_request($http_request, \$body);
Required. Returns a L<Langertha::Knarr::Request>.
=head2 format_chat_response
my ($status, \%headers, $body) = $proto->format_chat_response($response, $request);
Required. Returns the HTTP response triple for sync mode.
=head2 format_stream_open / format_stream_chunk / format_stream_close / format_stream_done
Lifecycle hooks for streaming responses. Defaults are no-ops where the
protocol doesn't need framing â Anthropic/A2A/ACP/AG-UI override these
to emit their named events around the chunk stream.
=head2 stream_content_type
Returns the HTTP C<Content-Type> for streaming responses. Default
C<text/event-stream>; Ollama overrides to C<application/x-ndjson>.
=head1 SUPPORT
=head2 Issues
Please report bugs and feature requests on GitHub at
L<https://github.com/Getty/langertha-knarr/issues>.
=head2 IRC
Join C<#langertha> on C<irc.perl.org> or message Getty directly.
=head1 CONTRIBUTING
Contributions are welcome! Please fork the repository and submit a pull request.
=head1 AUTHOR
Torsten Raudssus <torsten@raudssus.de> L<https://raudssus.de/>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2026 by Torsten Raudssus.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut
( run in 0.494 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )