#!/usr/bin/env jimsh # MicroBantam (mb): the Bantam agent in Jim Tcl (under 100 SLOC) # Created by Luxferre in 2026, released into the public domain set 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." set SDIR "[expr {[info exists env(HOME)] ? $env(HOME) : ([info exists env(USERPROFILE)] ? $env(USERPROFILE) : ".")} ]/.bantam/sessions" proc is_dict {d} { return [expr {![catch {dict keys $d}] && [llength $d] % 2 == 0}] } proc safe_get {d args} { foreach k $args { if {![is_dict $d] || ![dict exists $d $k]} { return "" }; set d [dict get $d $k] }; return $d } proc is_tool_call {tc} { return [expr {[is_dict $tc] && [dict exists $tc function] && [is_dict [dict get $tc function]] && [dict exists [dict get $tc function] name]}] } proc jesc {s} { set map [list \\ \\\\ \" \\" \n \\n \r \\r \t \\t \f \\f \b \\b]; set s [string map $map $s]; set res ""; for {set i 0} {$i < [string length $s]} {incr i} { set c [string index $s $i]; scan $c %c k; append res [expr {$k < 32 ? [format "\\u%04x" $k] : $c}] }; return "\"$res\"" } proc cfg {} { global env; set d [dict create endpoint https://opencode.ai/zen/v1 model big-pickle temperature 0.7 api_key - timeout 300 shell_timeout 120 max_al_iterations 1000]; if {[file exists model.cfg] && ![catch {open model.cfg r} f]} { while {[gets $f l] >= 0} { if {[regexp {^(\w+)\s*=\s*(.+)$} $l -> k v]} { dict set d $k $v } }; close $f }; if {[dict get $d api_key] eq "-" && [info exists env(OPENAI_API_KEY)]} { dict set d api_key $env(OPENAI_API_KEY) }; return $d } proc sp {} { global DEF_SP; set p ""; if {[file exists system.txt] && ![catch {open system.txt r} f]} { set p [string trim [read $f]]; close $f }; return [expr {[string length $p] ? $p : $DEF_SP}] } proc decode_chunked {b} { set res ""; set pos 0; while {$pos < [string length $b]} { set idx [string first "\r\n" $b $pos]; if {$idx == -1} break; scan [lindex [split [string range $b $pos [expr {$idx - 1}]] ";"] 0] "%x" clen; if {$clen == 0} break; set st [expr {$idx + 2}]; append res [string range $b $st [expr {$st + $clen - 1}]]; set pos [expr {$st + $clen + 2}] }; return $res } proc http_request {m url hdrs body {t 300}} { set proto http; set host ""; set port 80; set path "/"; if {[regexp {^(https?)://([^/]+)(/.*)?$} $url -> proto hp reqp]} { set port [expr {$proto eq "https" ? 443 : 80}]; if {$reqp ne ""} { set path $reqp } }; if {![regexp {^([^:]+):(\d+)$} $hp -> host port]} { set host $hp }; set s [socket stream $host:$port]; $s timeout [expr {$t * 1000}]; if {$proto eq "https"} { $s ssl -sni $host }; set req "$m $path HTTP/1.1\r\nHost: $host\r\n"; dict for {k v} $hdrs { append req "$k: $v\r\n" }; append req "Content-Length: [string length $body]\r\nConnection: close\r\n\r\n$body"; $s puts -nonewline $req; $s flush; set resp [$s read]; $s close; set sep [string first "\r\n\r\n" $resp]; set hlen 4; if {$sep == -1} { set sep [string first "\n\n" $resp]; set hlen 2 }; if {$sep == -1} { error "invalid HTTP response" }; set htxt [string range $resp 0 [expr {$sep - 1}]]; set rbody [string range $resp [expr {$sep + $hlen}] end]; set status 0; set reason ""; set chunked 0; regexp {^HTTP/\d\.\d\s+(\d+)(?:\s+(.*))?$} [string trim [lindex [split $htxt "\n"] 0]] -> status reason; foreach l [lrange [split $htxt "\n"] 1 end] { if {[regexp -nocase {^transfer-encoding:\s*chunked$} [string trim $l]]} { set chunked 1 } }; return [dict create status $status reason $reason body [expr {$chunked ? [decode_chunked $rbody] : $rbody}]] } proc clean_msg_for_api {m} { if {![is_dict $m]} { return "" }; set r [safe_get $m role]; if {$r eq ""} { return "" }; set c [safe_get $m content]; set res [dict create role $r]; if {$r eq "system" || $r eq "user"} { dict set res content $c } elseif {$r eq "assistant"} { dict set res content $c; set vtcs [list]; set raw_tcs [safe_get $m tool_calls]; if {[is_tool_call $raw_tcs]} { set raw_tcs [list $raw_tcs] }; foreach tc $raw_tcs { if {[is_tool_call $tc]} { set fn [dict get [dict get $tc function] name]; set a "\{\}"; if {[dict exists $tc function arguments]} { set a [dict get [dict get $tc function] arguments] }; set tcid [safe_get $tc id]; if {$tcid eq ""} { set tcid "call_0" }; set tp "function"; if {[dict exists $tc type]} { set tp [dict get $tc type] }; lappend vtcs [dict create id $tcid type $tp function [dict create name $fn arguments $a]] } }; if {[llength $vtcs]} { dict set res tool_calls $vtcs } } elseif {$r eq "tool"} { set tcid [safe_get $m tool_call_id]; if {$tcid eq ""} { set tcid "call_0" }; dict set res tool_call_id $tcid; dict set res content $c }; return $res } proc encode_json_msg {m} { if {![is_dict $m]} { return "\{\}" }; set parts [list]; dict for {k v} $m { if {$k eq "tool_calls"} { set raw_tcs $v; if {[is_tool_call $raw_tcs]} { set raw_tcs [list $raw_tcs] }; set tcs [list]; foreach tc $raw_tcs { if {[is_tool_call $tc]} { set tcp [list]; dict for {tck tcv} $tc { if {$tck eq "function" && [is_dict $tcv]} { set fnp [list]; dict for {fk fv} $tcv { lappend fnp "[jesc $fk]:[jesc $fv]" }; lappend tcp "[jesc $tck]:\{ [join $fnp ", "] \}" } else { lappend tcp "[jesc $tck]:[jesc $tcv]" } }; lappend tcs "\{ [join $tcp ", "] \}" } }; lappend parts "[jesc $k]:\[ [join $tcs ", "] \]" } else { lappend parts [expr {$v eq "null" ? "[jesc $k]:null" : "[jesc $k]:[jesc $v]"}] } }; return "\{ [join $parts ", "] \}" } proc sanitize_msgs {msgs_var} { upvar 1 $msgs_var msgs; set new [list]; foreach m $msgs { if {[is_dict $m] && [dict exists $m tool_calls] && [set tcs [dict get $m tool_calls]] ne "null" && $tcs ne ""} { if {[is_tool_call $tcs]} { set tcs [list $tcs] }; set ntcs [list]; foreach tc $tcs { if {[is_tool_call $tc]} { set raw [dict get [dict get $tc function] arguments]; if {[catch {json::decode $raw} p] || ![is_dict $p]} { dict set tc function arguments [encode_json_msg [dict create invalid_raw $raw]] } }; lappend ntcs $tc }; dict set m tool_calls $ntcs }; lappend new $m }; set msgs $new } proc encode_payload {c msgs} { set mjs [list]; foreach m $msgs { set cm [clean_msg_for_api $m]; if {$cm ne ""} { lappend mjs [encode_json_msg $cm] } }; set tools {[{"type":"function","function":{"name":"shell_exec","description":"Run a shell command, return output and exit code.","parameters":{"type":"object","properties":{"command":{"type":"string"}},"required":["command"]}}},{"type":"function","function":{"name":"run_subagent","description":"Run a child agent with a prompt.","parameters":{"type":"object","properties":{"prompt":{"type":"string"}},"required":["prompt"]}}}]}; return "\{ \"model\": [jesc [dict get $c model]], \"temperature\": [expr {[dict get $c temperature] + 0}], \"messages\": \[ [join $mjs ", "] \], \"tools\": $tools \}" } proc llm {c msgs_var} { upvar 1 $msgs_var msgs; sanitize_msgs msgs set ep [string trimright [dict get $c endpoint] "/"] set payload [encode_payload $c $msgs] if {[catch {json::decode $payload}]} { error "API error: Local JSON validation failed" } set is_tty [expr {[catch {exec sh -c "test -t 1" >@stdout}] == 0}] set hdrs [dict create "Content-Type" "application/json" "User-Agent" "Mozilla/5.0 (compatible; MicroBantam/1.0)"]; if {[dict get $c api_key] ne "-"} { dict set $hdrs "Authorization" "Bearer [dict get $c api_key]" } set last "" for {set a 1} {$a <= 3} {incr a} { if {$a > 1} { after [expr {($a - 1) * 2000}] }; puts -nonewline [expr {$is_tty ? "\r...requesting ($a/3)..." : "...requesting ($a/3)...\n"}]; flush stdout set code [catch {http_request POST "$ep/chat/completions" $hdrs $payload [dict get $c timeout]} res]; if {$is_tty} { puts -nonewline "\r\u001b\[K"; flush stdout } if {$code == 0 && [dict get $res status] == 200} { set body [dict get $res body] if {![catch {json::decode $body} data] && [is_dict $data] && [dict exists $data choices] && [llength [set choices [dict get $data choices]]] > 0} { return [dict get [lindex $choices 0] message] } set last "invalid response body" } else { set st [expr {$code != 0 ? 0 : [dict get $res status]}]; set detail [safe_get $res body] if {[string length $detail] > 400} { set detail [string range $detail 0 399] } set last [expr {$code != 0 ? $res : ([string length $detail] ? "$detail (HTTP $st)" : ([safe_get $res reason] ne "" ? [safe_get $res reason] : "HTTP $st"))}] if {$st != 0 && $st != 403 && $st != 429 && $st < 500} { error "API error: $last" } } } error "API error: $last (after 3 attempts)" } proc shell_exec_cmd {cmd t} { catch {exec timeout $t sh -c "$cmd 2>&1"} out opts; set exit_code 0; if {[dict get $opts -code] != 0} { set errcode [dict get $opts -errorcode]; set exit_code [expr {[lindex $errcode 0] eq "CHILDSTATUS" ? [lindex $errcode 2] : -1}] }; set out [string trimright [string map [list "\u0000" "\n"] $out] " \t\n\r\v\f"]; return [expr {$exit_code == 124 ? "$out\n\[timeout after ${t}s\]\nexit: -1" : "$out\nexit: $exit_code"}] } proc last_assistant {msgs} { for {set i [expr {[llength $msgs] - 1}]} {$i >= 0} {incr i -1} { set m [lindex $msgs $i]; if {[is_dict $m] && [safe_get $m role] eq "assistant"} { set cnt [safe_get $m content]; if {$cnt ne "" && $cnt ne "null"} { return $cnt } } }; return "" } proc AL {c msgs_var sp depth} { upvar 1 $msgs_var msgs for {set iter 0} {$iter < [dict get $c max_al_iterations]} {incr iter} { if {[catch {llm $c msgs} m]} { if {[string match "*Invalid assistant message*" $m] || [string match "*content or tool_calls must be set*" $m]} { set stripped 0 for {set j [expr {[llength $msgs] - 1}]} {$j >= 0} {incr j -1} { set mm [lindex $msgs $j]; if {[is_dict $mm] && [safe_get $mm role] eq "assistant"} { set msgs [lreplace $msgs $j $j]; puts "\[stripped malformed assistant message\]"; set stripped 1; break } } if {$stripped} { continue } } puts $m; return $msgs } lappend msgs $m; set cnt [safe_get $m content]; if {$cnt ne "" && $cnt ne "null"} { puts $cnt } if {[set tcs [safe_get $m tool_calls]] eq "" || $tcs eq "null"} break if {[is_tool_call $tcs]} { set tcs [list $tcs] } foreach tc $tcs { if {![is_tool_call $tc]} continue set fn [dict get [dict get $tc function] name]; set args_raw "\{\}" if {[dict exists $tc function arguments]} { set args_raw [dict get [dict get $tc function] arguments] } if {[catch {json::decode $args_raw} a] || ![is_dict $a]} { set bad [encode_json_msg [dict create invalid_raw $args_raw]]; dict set tc function arguments $bad; set res "bad JSON args for $fn: $bad" } elseif {$fn eq "shell_exec"} { set cmd [safe_get $a command]; set res [shell_exec_cmd $cmd [dict get $c shell_timeout]] } elseif {$fn eq "run_subagent"} { set prompt [safe_get $a prompt]; set child [list [dict create role system content "$sp\n\nImportant: this is a child agent"] [dict create role user content $prompt]]; set res [expr {$depth >= 5 ? "\[subagent depth limit (5) reached, child not spawned\]" : [last_assistant [AL $c child $sp [expr {$depth + 1}]]]}] } else { set res "unknown tool: $fn" } puts "\[tool\] $fn: $res"; lappend msgs [dict create role tool tool_call_id [safe_get $tc id] content $res] } } return $msgs } proc sdir {} { global SDIR; if {![file isdirectory $SDIR]} { file mkdir $SDIR }; return $SDIR } proc sessions {} { global SDIR; set s [list]; foreach f [glob -nocomplain "$SDIR/*.json"] { if {![catch {open $f r} fh]} { set c [read $fh]; close $fh; if {![catch {json::decode $c} d] && [is_dict $d]} { lappend s $d } } }; return [lsort -command {apply {{a b} { string compare [safe_get $b id] [safe_get $a id] }}} $s] } proc save {msgs} { set sd [sdir]; set base [clock format [clock seconds] -format "%Y%m%d-%H%M%S"]; set id $base; set i 0; while {[file exists "$sd/$id.json"]} { incr i; set id "$base-$i" }; set mjs [list]; foreach m $msgs { lappend mjs [encode_json_msg $m] }; set f [open "$sd/$id.json" w]; puts $f "\{\n \"id\": [jesc $id],\n \"messages\": \[\n [join $mjs ",\n "]\n \]\n\}"; close $f; return $id } proc load_session {want} { foreach s [sessions] { if {[safe_get $s id] eq $want} { return [dict get $s messages] } }; error "no session: $want" } proc autosave {msgs} { set sd [sdir]; set mjs [list]; foreach m $msgs { lappend mjs [encode_json_msg $m] }; if {![catch {open "$sd/autosave.json" w} f]} { puts $f "\{\n \"id\": \"autosave\",\n \"messages\": \[\n [join $mjs ",\n "]\n \]\n\}"; close $f } } proc list_sessions {} { set res [list]; foreach s [sessions] { lappend res [list [safe_get $s id] [llength [expr {[dict exists $s messages] ? [dict get $s messages] : {}}]]] }; return $res } proc main {argv} { set c [cfg]; set sp_text [sp]; set msgs [list [dict create role system content $sp_text]] if {[llength $argv] > 0} { if {[catch {open [lindex $argv 0] r} f]} { puts stderr "cannot open [lindex $argv 0]: $f"; exit 1 } set content [read $f]; close $f; lappend msgs [dict create role user content $content]; AL $c msgs $sp_text 0; autosave $msgs; return } puts "MicroBantam ready ([dict get $c model]). Commands: /quit /clear /save /list /load /help" while {1} { puts -nonewline "> "; flush stdout; if {[gets stdin u] < 0} break if {[set u [string trim $u]] eq ""} continue if {$u eq "/quit"} { break } \ elseif {$u eq "/clear"} { set msgs [list [dict create role system content $sp_text]]; autosave $msgs } \ elseif {$u eq "/save"} { puts "session saved: [save $msgs]" } \ elseif {$u eq "/list"} { foreach item [list_sessions] { puts "[lindex $item 0] \[[lindex $item 1] msgs\]" } } \ elseif {[regexp {^\/load(?:\s+(\S+))?$} $u -> want_id]} { if {$want_id eq ""} { puts "usage: /load " } elseif {[catch {load_session $want_id} loaded]} { puts $loaded } else { set msgs $loaded; autosave $msgs; puts "loaded: $want_id" } } \ elseif {$u eq "/help"} { puts "Commands: /quit /clear /save /list /load /help" } \ else { lappend msgs [dict create role user content $u]; AL $c msgs $sp_text 0; autosave $msgs } } autosave $msgs } if {[info exists argv0] && [file tail $argv0] eq "mb.tcl"} { main $argv }