Langertha

 view release on metacpan or  search on metacpan

t/61_tool_calling_openai.t  view on Meta::CPAN

#!/usr/bin/env perl
# ABSTRACT: Test MCP tool calling support for OpenAI-compatible engines

use strict;
use warnings;

use Test2::Bundle::More;
use JSON::MaybeXS;

use Langertha::Engine::OpenAI;

my $json = JSON::MaybeXS->new->canonical(1)->utf8(1);

my $openai = Langertha::Engine::OpenAI->new(
  api_key => 'test-key',
  model => 'gpt-4o-mini',
  system_prompt => 'You are a helpful assistant',
);

# Test: mcp_servers defaults to empty
is_deeply($openai->mcp_servers, [], 'mcp_servers defaults to empty');
is($openai->tool_max_iterations, 10, 'tool_max_iterations defaults to 10');

# Test: format_tools converts MCP format to OpenAI function format
{
  my $mcp_tools = [
    {
      name => 'echo',
      description => 'Echo the input text',
      inputSchema => {
        type => 'object',
        properties => { message => { type => 'string' } },
        required => ['message'],
      },
    },
    {
      name => 'add',
      description => 'Add two numbers',
      inputSchema => {
        type => 'object',
        properties => {
          a => { type => 'number' },
          b => { type => 'number' },
        },
        required => ['a', 'b'],
      },
    },
  ];

  my $formatted = $openai->format_tools($mcp_tools);
  is(scalar @$formatted, 2, 'two tools formatted');

  is($formatted->[0]{type}, 'function', 'first tool type is function');
  is($formatted->[0]{function}{name}, 'echo', 'first tool function name');
  is($formatted->[0]{function}{description}, 'Echo the input text', 'first tool description');
  is($formatted->[0]{function}{parameters}{type}, 'object', 'parameters type preserved');
  is_deeply($formatted->[0]{function}{parameters}{required}, ['message'], 'parameters required preserved');
  ok(!exists $formatted->[0]{inputSchema}, 'no inputSchema at top level');

  is($formatted->[1]{type}, 'function', 'second tool type');
  is($formatted->[1]{function}{name}, 'add', 'second tool function name');
}

# Test: response_tool_calls extracts tool calls from OpenAI response
{
  my $data = {
    choices => [{
      message => {
        role => 'assistant',
        content => undef,
        tool_calls => [
          {
            id => 'call_abc123',
            type => 'function',
            function => {
              name => 'echo',
              arguments => '{"message":"hello"}',
            },
          },
        ],
      },
      finish_reason => 'tool_calls',



( run in 0.519 second using v1.01-cache-2.11-cpan-71847e10f99 )