| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package SignalWire::Agents::Skills::SkillBase; |
|
2
|
|
|
|
|
|
|
# Copyright (c) 2025 SignalWire |
|
3
|
|
|
|
|
|
|
# Licensed under the MIT License. |
|
4
|
|
|
|
|
|
|
|
|
5
|
19
|
|
|
19
|
|
358257
|
use strict; |
|
|
19
|
|
|
|
|
48
|
|
|
|
19
|
|
|
|
|
800
|
|
|
6
|
19
|
|
|
19
|
|
101
|
use warnings; |
|
|
19
|
|
|
|
|
39
|
|
|
|
19
|
|
|
|
|
1217
|
|
|
7
|
19
|
|
|
19
|
|
740
|
use Moo; |
|
|
19
|
|
|
|
|
10155
|
|
|
|
19
|
|
|
|
|
137
|
|
|
8
|
19
|
|
|
19
|
|
9476
|
use Carp qw(croak); |
|
|
19
|
|
|
|
|
47
|
|
|
|
19
|
|
|
|
|
16977
|
|
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
# Required class-level constants (subclasses override via 'has' or '+') |
|
11
|
|
|
|
|
|
|
has skill_name => (is => 'ro', required => 1); |
|
12
|
|
|
|
|
|
|
has skill_description => (is => 'ro', required => 1); |
|
13
|
|
|
|
|
|
|
has skill_version => (is => 'ro', default => sub { '1.0.0' }); |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
has supports_multiple_instances => (is => 'ro', default => sub { 0 }); |
|
16
|
|
|
|
|
|
|
has required_packages => (is => 'ro', default => sub { [] }); |
|
17
|
|
|
|
|
|
|
has required_env_vars => (is => 'ro', default => sub { [] }); |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# The agent this skill is attached to |
|
20
|
|
|
|
|
|
|
has agent => (is => 'ro', required => 1, weak_ref => 1); |
|
21
|
|
|
|
|
|
|
# Config params passed at registration |
|
22
|
|
|
|
|
|
|
has params => (is => 'rw', default => sub { {} }); |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
# Extra SWAIG fields to merge into tool definitions |
|
25
|
|
|
|
|
|
|
has swaig_fields => (is => 'rw', default => sub { {} }); |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
sub BUILD { |
|
28
|
131
|
|
|
131
|
0
|
938
|
my ($self) = @_; |
|
29
|
|
|
|
|
|
|
# Extract swaig_fields from params if present |
|
30
|
131
|
100
|
|
|
|
1713
|
if (exists $self->params->{swaig_fields}) { |
|
31
|
1
|
|
|
|
|
15
|
$self->swaig_fields(delete $self->params->{swaig_fields}); |
|
32
|
|
|
|
|
|
|
} |
|
33
|
|
|
|
|
|
|
} |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# --- Abstract interface (subclasses must override) --- |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub setup { |
|
38
|
0
|
|
|
0
|
0
|
0
|
my ($self) = @_; |
|
39
|
0
|
|
|
|
|
0
|
croak(ref($self) . " must implement setup()"); |
|
40
|
|
|
|
|
|
|
} |
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub register_tools { |
|
43
|
0
|
|
|
0
|
0
|
0
|
my ($self) = @_; |
|
44
|
0
|
|
|
|
|
0
|
croak(ref($self) . " must implement register_tools()"); |
|
45
|
|
|
|
|
|
|
} |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
# --- Default implementations --- |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
sub define_tool { |
|
50
|
66
|
|
|
66
|
0
|
345
|
my ($self, %opts) = @_; |
|
51
|
|
|
|
|
|
|
# Merge swaig_fields into the tool definition |
|
52
|
66
|
|
|
|
|
179
|
my %merged = (%{ $self->swaig_fields }, %opts); |
|
|
66
|
|
|
|
|
488
|
|
|
53
|
66
|
|
|
|
|
464
|
return $self->agent->define_tool(%merged); |
|
54
|
|
|
|
|
|
|
} |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
sub get_hints { |
|
57
|
9
|
|
|
9
|
0
|
26
|
return []; |
|
58
|
|
|
|
|
|
|
} |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
sub get_global_data { |
|
61
|
10
|
|
|
10
|
0
|
27
|
return {}; |
|
62
|
|
|
|
|
|
|
} |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
sub get_prompt_sections { |
|
65
|
23
|
|
|
23
|
0
|
166
|
my ($self) = @_; |
|
66
|
23
|
100
|
|
|
|
149
|
return [] if $self->params->{skip_prompt}; |
|
67
|
21
|
|
|
|
|
98
|
return $self->_get_prompt_sections; |
|
68
|
|
|
|
|
|
|
} |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
sub _get_prompt_sections { |
|
71
|
2
|
|
|
2
|
|
5
|
return []; |
|
72
|
|
|
|
|
|
|
} |
|
73
|
|
|
|
|
|
|
|
|
74
|
|
|
|
1
|
0
|
|
sub cleanup { |
|
75
|
|
|
|
|
|
|
# no-op by default |
|
76
|
|
|
|
|
|
|
} |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
sub validate_env_vars { |
|
79
|
10
|
|
|
10
|
0
|
30
|
my ($self) = @_; |
|
80
|
10
|
|
|
|
|
22
|
for my $var (@{ $self->required_env_vars }) { |
|
|
10
|
|
|
|
|
51
|
|
|
81
|
0
|
0
|
|
|
|
0
|
return 0 unless $ENV{$var}; |
|
82
|
|
|
|
|
|
|
} |
|
83
|
10
|
|
|
|
|
40
|
return 1; |
|
84
|
|
|
|
|
|
|
} |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
sub get_parameter_schema { |
|
87
|
|
|
|
|
|
|
return { |
|
88
|
15
|
|
|
15
|
0
|
308
|
swaig_fields => { type => 'object', description => 'Additional SWAIG fields' }, |
|
89
|
|
|
|
|
|
|
skip_prompt => { type => 'boolean', description => 'Skip injecting prompt sections', default => 0 }, |
|
90
|
|
|
|
|
|
|
tool_name => { type => 'string', description => 'Override the default tool name' }, |
|
91
|
|
|
|
|
|
|
}; |
|
92
|
|
|
|
|
|
|
} |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub get_instance_key { |
|
95
|
14
|
|
|
14
|
0
|
59
|
my ($self) = @_; |
|
96
|
14
|
|
|
|
|
51
|
my $base = $self->skill_name; |
|
97
|
14
|
100
|
|
|
|
60
|
if ($self->params->{tool_name}) { |
|
98
|
4
|
|
|
|
|
31
|
return $base . ':' . $self->params->{tool_name}; |
|
99
|
|
|
|
|
|
|
} |
|
100
|
10
|
|
|
|
|
38
|
return $base; |
|
101
|
|
|
|
|
|
|
} |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
1; |