tool format hardening

This commit is contained in:
Luxferre
2026-08-09 15:19:36 +03:00
parent 88dd9dfef5
commit accd1fc75c
4 changed files with 92 additions and 21 deletions
+24 -2
View File
@@ -94,10 +94,27 @@ sub shell_exec {
return trim($res) . "\n\nexit: $code";
}
sub sanitize_msgs {
my ($msgs) = @_;
return unless $msgs && ref($msgs) eq 'ARRAY';
for my $m (@$msgs) {
next unless ref($m) eq 'HASH' && ($m->{role} // '') eq 'assistant' && $m->{tool_calls};
for my $tc (@{$m->{tool_calls}}) {
next unless ref($tc) eq 'HASH' && $tc->{function};
my $astr = $tc->{function}{arguments} // '{}';
my $a = eval { decode_json($astr) };
if ($@ || ref($a) ne 'HASH') {
$tc->{function}{arguments} = encode_json({ invalid_raw => $astr // '' });
}
}
}
}
my @fib = (1, 1, 2, 3, 5, 8, 13, 21, 34);
sub llm {
my ($cfg, $msgs, $tools) = @_;
sanitize_msgs($msgs);
my $ep = $cfg->{endpoint} =~ s/\/+$//r;
my $url = "$ep/chat/completions";
my %h = ('Content-Type' => 'application/json', 'User-Agent' => 'Mozilla/5.0 (compatible; Bantam/1.0)');
@@ -119,8 +136,10 @@ sub llm {
my $d = eval { decode_json($res->{content}) };
return $d->{choices}[0]{message} if $d && $d->{choices} && @{$d->{choices}};
}
my $err = $res->{reason} || $res->{content} || "HTTP status $res->{status}";
my $status = $res->{status} // 0;
my $err = $res->{reason} || $res->{content} || "HTTP status $status";
print "\r\e[K" if $_col; STDOUT->flush();
die "[HTTP error: $err]\n" if $status >= 400 && $status < 500 && $status != 408 && $status != 429;
if ($i <= $#fib) { print c("[network error: $err, retrying in ${dly}s...]", 31), "\n"; sleep($dly); next; }
die "[network error: $err]\n";
} else {
@@ -175,8 +194,10 @@ sub llm {
$msg{tool_calls} = [map { $tcs{$_} } @order] if @order;
return \%msg;
}
my $err = $res->{reason} || $res->{content} || "HTTP status $res->{status}";
my $status = $res->{status} // 0;
my $err = $res->{reason} || $res->{content} || "HTTP status $status";
print "\r\e[K" if $_col; STDOUT->flush();
die "[HTTP error: $err]\n" if $status >= 400 && $status < 500 && $status != 408 && $status != 429;
if ($i <= $#fib) { print c("[network error: $err, retrying in ${dly}s...]", 31), "\n"; sleep($dly); next; }
die "[network error: $err]\n";
}
@@ -208,6 +229,7 @@ sub AL {
my ($res, $sty) = ('', 2);
my $a = eval { decode_json($astr) };
if ($@ || ref($a) ne 'HASH') {
$tc->{function}{arguments} = encode_json({ invalid_raw => $astr });
$res = "[tool error: invalid JSON args for $fn: " . ($@ || 'not a JSON object') . ". Raw: '$astr']"; $sty = 31;
} elsif ($fn eq 'shell_exec') {
$res = shell_exec($a->{command} // '', $stime);