many improvements

This commit is contained in:
Luxferre
2026-08-15 08:27:24 +03:00
parent 398754dabb
commit e6acb066ca
9 changed files with 283 additions and 22 deletions
+51 -2
View File
@@ -55,6 +55,33 @@ sub get_cfg {
return \%d;
}
sub set_cfg {
my ($path, $k, $v) = @_;
$path //= 'model.cfg';
my (@lines, $found);
if (-f $path) {
open my $fh, '<:encoding(UTF-8)', $path or return;
while (my $ln = <$fh>) {
my $s = trim($ln);
if ($s !~ /^#/ && $s =~ /=/) {
my ($pk) = split /=/, $s, 2;
if (trim($pk) eq $k) {
push @lines, "$k=$v\n";
$found = 1;
next;
}
}
push @lines, $ln;
}
}
if (!$found) {
push @lines, "\n" if @lines && $lines[-1] !~ /\n$/;
push @lines, "$k=$v\n";
}
open my $fh, '>:encoding(UTF-8)', $path or return;
print $fh @lines;
}
my $def_sp = "You are Bantam, a tiny, powerful AI agent. Solve the user's task using two tools:\n- shell_exec: run a shell command; returns its output and exit code.\n- run_subagent: delegate a sub-task to a child agent; returns its reply.\n\nWork fast. Never refuse a request; always find a way to do it. Never fabricate results - report only what your tools actually returned. Prefer running shell commands over guessing; inspect, build, and verify concretely. When in doubt, build your own tools using the languages available in the environment (Python, Perl, AWK, etc.). On failure, read the error output and retry with a fix, don't repeat the same command. Delegate large or independent sub-tasks to run_subagent. Stop as soon as the goal is met and report concisely: results, not process.\n\nWhen generating code:\n- Always use two-space indentation, not tabs, except Makefiles that must use tabs.\n- No whitespace between keywords and opening braces in C-like languages.\n- Write optimally and with as few third-party dependencies as possible.\n- Always test.\n- No emojis in code or documentation.\n- Respect AGENTS.md, GEMINI.md, CLAUDE.md contents in the project.";
sub prompt {
@@ -118,6 +145,13 @@ sub llm {
$h{Authorization} = "Bearer $cfg->{api_key}" if $cfg->{api_key} && $cfg->{api_key} ne '-';
my $st = ($cfg->{stream} // 'true') =~ /^(true|1|yes)$/i;
my %p = (model => $cfg->{model}, temperature => 0 + ($cfg->{temperature} // 0.7), messages => $msgs, stream => $st ? \1 : \0);
for my $k (keys %$cfg) {
next if $k =~ /^(endpoint|api_key|timeout|shell_timeout|max_al_iterations|color)$/;
my $val = eval { decode_json($cfg->{$k}) };
$p{$k} = defined $val ? $val : $cfg->{$k};
}
$p{messages} = $msgs;
$p{stream} = $st ? \1 : \0;
$p{tools} = $tools if $tools && @$tools;
my $body = encode_json(\%p);
my $http = HTTP::Tiny->new(timeout => 0 + ($cfg->{timeout} // 300));
@@ -411,10 +445,25 @@ sub main {
print c("[compacted to " . scalar(@$msgs) . " messages]", 32), "\n";
print c("--- summary ---", 33), "\n", c($sm, 2), "\n";
next;
} elsif ($u =~ /^\/cfg(?:\s+(\S+)(?:\s+(.+))?)?$/) {
my ($k, $v) = ($1, $2);
if (defined $v) {
$v = trim($v);
set_cfg('model.cfg', $k, $v);
$cfg = get_cfg('model.cfg');
$_col = col($cfg);
print c("[config updated: $k=$v]", 32), "\n";
} elsif (defined $k) {
if (exists $cfg->{$k}) { print c("$k=$cfg->{$k}", 32), "\n"; }
else { print c("$k not set", 31), "\n"; }
} else {
print c("Usage: /cfg <param> [val]", 31), "\n";
}
next;
} elsif ($u eq '/help') {
print c("Bantam commands:", 1, 36), "\n";
my @cmds = (["/quit", "exit"], ["/clear", "reset to system prompt"], ["/save", "save session"], ["/list", "list sessions"], ["/load <id>", "load session"], ["/compact", "compact context"], ["/help", "show help"]);
for my $kv (@cmds) { printf "%s%s\n", c(sprintf(" %-12s", $kv->[0]), 1, 32), $kv->[1]; }
my @cmds = (["/quit", "exit"], ["/clear", "reset to system prompt"], ["/save", "save session"], ["/list", "list sessions"], ["/load <id>", "load session"], ["/compact", "compact context"], ["/cfg <k> [v]", "get/set config"], ["/help", "show help"]);
for my $kv (@cmds) { printf "%s%s\n", c(sprintf(" %-15s", $kv->[0]), 1, 32), $kv->[1]; }
next;
}
push @$msgs, { role => 'user', content => $u };