File Coverage

blib/lib/WebService/Ollama/Response.pm
Criterion Covered Total %
statement 22 26 84.6
branch 6 10 60.0
condition 6 8 75.0
subroutine 4 5 80.0
pod 3 3 100.0
total 41 52 78.8


line stmt bran cond sub pod time code
1             package WebService::Ollama::Response;
2              
3 5     5   139819 use Moo;
  5         12625  
  5         53  
4              
5 5     5   5251 use JSON::Lines;
  5         48151  
  5         43  
6              
7             has [qw/
8             done
9             context
10             total_duration
11             load_duration
12             model
13             create_at
14             eval_count
15             eval_duration
16             done_reason
17             response
18             prompt_eval_duration
19             prompt_eval_count
20             message
21             status
22             digest
23             total
24             completed
25             version
26             embeddings
27             models
28             /] => (
29             is => 'ro',
30             );
31              
32             sub has_tool_calls {
33 8     8 1 223694 my ($self) = @_;
34 8         26 my $calls = $self->extract_tool_calls;
35 8         50 return scalar @$calls > 0;
36             }
37              
38             sub extract_tool_calls {
39 15     15 1 34 my ($self) = @_;
40 15         40 my @calls;
41            
42             # Ollama returns tool_calls in the message
43 15 100 66     113 if ($self->message && ref($self->message) eq 'HASH') {
44 12 100       45 if (my $tc = $self->message->{tool_calls}) {
45 5         10 push @calls, @$tc;
46             }
47            
48             # Fallback: some models output tool calls as JSON in content
49 12 100 100     58 if (!@calls && $self->message->{content}) {
50 7         19 my $content = $self->message->{content};
51            
52             # Look for JSON tool call patterns - handle both "arguments" and "parameters"
53 7         80 while ($content =~ /\{\s*"name"\s*:\s*"([^"]+)"\s*,\s*"(?:arguments|parameters)"\s*:\s*(\{[^}]*\})\s*\}/g) {
54 4         21 my ($name, $args_json) = ($1, $2);
55 4   50     8 my $args = eval {
56 4         23 JSON::Lines->new->decode($args_json)->[0];
57             } // {};
58 4         889 push @calls, {
59             function => {
60             name => $name,
61             arguments => $args,
62             },
63             };
64             }
65             }
66             }
67            
68 15         46 return \@calls;
69             }
70              
71             sub json_response {
72 0     0 1   my ($self) = shift;
73 0 0         my $aoa = JSON::Lines->new->decode($self->response ? $self->response : $self->message->{content});
74 0 0         return scalar @{$aoa} == 1 ? $aoa->[0] : $aoa;
  0            
75             }
76              
77             1;
78              
79             __END__