many improvements
This commit is contained in:
@@ -42,9 +42,10 @@ type Cfg struct {
|
||||
MaxALIterations int
|
||||
Stream bool
|
||||
Color string
|
||||
Raw map[string]string
|
||||
}
|
||||
|
||||
var defCfg = Cfg{"https://opencode.ai/zen/v1", "big-pickle", "-", 0.7, 300, 120, 1000, true, "auto"}
|
||||
var defCfg = Cfg{"https://opencode.ai/zen/v1", "big-pickle", "-", 0.7, 300, 120, 1000, true, "auto", nil}
|
||||
|
||||
func atoiD(s string, d int) int {
|
||||
if v, e := strconv.Atoi(strings.TrimSpace(s)); e == nil {
|
||||
@@ -55,12 +56,19 @@ func atoiD(s string, d int) int {
|
||||
|
||||
func getCfg(path string) Cfg {
|
||||
cfg := defCfg
|
||||
cfg.Raw = map[string]string{
|
||||
"endpoint": cfg.Endpoint, "model": cfg.Model, "temperature": fmt.Sprintf("%v", cfg.Temperature),
|
||||
"api_key": cfg.APIKey, "stream": strconv.FormatBool(cfg.Stream), "color": cfg.Color,
|
||||
"timeout": strconv.Itoa(cfg.Timeout), "shell_timeout": strconv.Itoa(cfg.ShellTimeout),
|
||||
"max_al_iterations": strconv.Itoa(cfg.MaxALIterations),
|
||||
}
|
||||
if d, err := os.ReadFile(path); err == nil {
|
||||
for _, ln := range strings.Split(string(d), "\n") {
|
||||
ln = strings.TrimSpace(ln)
|
||||
if ln == "" || ln[0] == '#' || !strings.Contains(ln, "=") { continue }
|
||||
k, v, _ := strings.Cut(ln, "=")
|
||||
k, v = strings.TrimSpace(k), strings.TrimSpace(v)
|
||||
cfg.Raw[k] = v
|
||||
switch k {
|
||||
case "endpoint": cfg.Endpoint = v
|
||||
case "model": cfg.Model = v
|
||||
@@ -74,10 +82,41 @@ func getCfg(path string) Cfg {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cfg.APIKey == "" || cfg.APIKey == "-") && os.Getenv("OPENAI_API_KEY") != "" { cfg.APIKey = os.Getenv("OPENAI_API_KEY") }
|
||||
if (cfg.APIKey == "" || cfg.APIKey == "-") && os.Getenv("OPENAI_API_KEY") != "" {
|
||||
cfg.APIKey = os.Getenv("OPENAI_API_KEY")
|
||||
cfg.Raw["api_key"] = cfg.APIKey
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
func setCfg(path, key, val string) error {
|
||||
var lines []string
|
||||
found := false
|
||||
if d, err := os.ReadFile(path); err == nil {
|
||||
for _, ln := range strings.Split(string(d), "\n") {
|
||||
trimmed := strings.TrimSpace(ln)
|
||||
if !strings.HasPrefix(trimmed, "#") && strings.Contains(trimmed, "=") {
|
||||
k, _, _ := strings.Cut(trimmed, "=")
|
||||
if strings.TrimSpace(k) == key {
|
||||
lines = append(lines, key+"="+val)
|
||||
found = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
lines = append(lines, ln)
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
if len(lines) > 0 && lines[len(lines)-1] == "" {
|
||||
lines[len(lines)-1] = key + "=" + val
|
||||
lines = append(lines, "")
|
||||
} else {
|
||||
lines = append(lines, key+"="+val)
|
||||
}
|
||||
}
|
||||
return os.WriteFile(path, []byte(strings.Join(lines, "\n")), 0644)
|
||||
}
|
||||
|
||||
const defaultSystemPrompt = `You are Bantam, a tiny, powerful AI agent. Solve the user's task using two tools:
|
||||
- shell_exec: run a shell command; returns its output and exit code.
|
||||
- run_subagent: delegate a sub-task to a child agent; returns its reply.
|
||||
@@ -182,6 +221,19 @@ func llm(cfg *Cfg, msgs []Message, tools []map[string]any) (Message, error) {
|
||||
sanitizeMessages(msgs)
|
||||
p := map[string]any{"model": cfg.Model, "temperature": cfg.Temperature, "messages": msgs, "stream": cfg.Stream}
|
||||
if tools != nil { p["tools"] = tools }
|
||||
for k, v := range cfg.Raw {
|
||||
switch k {
|
||||
case "endpoint", "api_key", "timeout", "shell_timeout", "max_al_iterations", "color":
|
||||
continue
|
||||
default:
|
||||
var jv any
|
||||
if err := json.Unmarshal([]byte(v), &jv); err == nil {
|
||||
p[k] = jv
|
||||
} else {
|
||||
p[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
body, _ := json.Marshal(p)
|
||||
client := &http.Client{Transport: &http.Transport{
|
||||
DialContext: (&net.Dialer{Timeout: time.Duration(cfg.Timeout) * time.Second}).DialContext,
|
||||
@@ -669,6 +721,19 @@ func readLine(prompt string) (string, bool) {
|
||||
}
|
||||
switch rn {
|
||||
case '\r':
|
||||
if stdin.Buffered() > 0 {
|
||||
if b, _ := stdin.Peek(1); len(b) > 0 && b[0] == '\n' {
|
||||
stdin.ReadByte()
|
||||
}
|
||||
}
|
||||
W := termWidth()
|
||||
s := string(e.buf)
|
||||
P := visibleLen(e.prompt)
|
||||
er, _ := textPos(P, W, s, len([]rune(s)))
|
||||
pr, _ := textPos(P, W, s, e.pos)
|
||||
if down := er - pr; down > 0 {
|
||||
fmt.Printf("\033[%dB", down)
|
||||
}
|
||||
fmt.Print("\r\n")
|
||||
return string(e.buf), true
|
||||
case '\n':
|
||||
@@ -804,10 +869,32 @@ func main() {
|
||||
fmt.Println(c(fmt.Sprintf("[compacted to %d messages]", len(msgs)), 32))
|
||||
fmt.Println(c("--- summary ---", 33) + "\n" + c(sm, 2))
|
||||
continue
|
||||
case strings.HasPrefix(u, "/cfg"):
|
||||
parts := strings.SplitN(u, " ", 3)
|
||||
if len(parts) == 2 {
|
||||
k := strings.TrimSpace(parts[1])
|
||||
if v, ok := cfg.Raw[k]; ok {
|
||||
fmt.Println(c(k+"="+v, 32))
|
||||
} else {
|
||||
fmt.Println(c(k+" not set", 31))
|
||||
}
|
||||
} else if len(parts) >= 3 {
|
||||
k, v := strings.TrimSpace(parts[1]), strings.TrimSpace(parts[2])
|
||||
if err := setCfg("model.cfg", k, v); err != nil {
|
||||
fmt.Println(c("[cfg error: "+err.Error()+"]", 31))
|
||||
continue
|
||||
}
|
||||
cfg = getCfg("model.cfg")
|
||||
COL = col(cfg)
|
||||
fmt.Println(c(fmt.Sprintf("[config updated: %s=%s]", k, v), 32))
|
||||
} else {
|
||||
fmt.Println(c("Usage: /cfg <param> [val]", 31))
|
||||
}
|
||||
continue
|
||||
case u == "/help":
|
||||
fmt.Println(c("Bantam commands:", 1, 36))
|
||||
for _, kv := range [][2]string{{"/quit", "exit"}, {"/clear", "reset to system prompt"}, {"/save", "save session"}, {"/list", "list sessions"}, {"/load <id>", "load session"}, {"/compact", "compact context"}, {"/help", "show help"}} {
|
||||
fmt.Println(c(fmt.Sprintf(" %-12s", kv[0]), 1, 32) + kv[1])
|
||||
for _, kv := range [][2]string{{"/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"}} {
|
||||
fmt.Println(c(fmt.Sprintf(" %-15s", kv[0]), 1, 32) + kv[1])
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user