introduced .bantam.cfg in addition to model.cfg
This commit is contained in:
@@ -35,9 +35,9 @@ The Go port is a single `main.go` plus four platform files (`term_linux.go`, `te
|
|||||||
|
|
||||||
### Running Bantam
|
### Running Bantam
|
||||||
|
|
||||||
All implementations read the same `model.cfg` and `system.txt` from the current working directory.
|
All implementations read `model.cfg` (or `.bantam.cfg`, which takes priority if present) and `system.txt` from the current working directory.
|
||||||
|
|
||||||
1. Configure `model.cfg` with your API settings:
|
1. Configure `model.cfg` (or `.bantam.cfg`, which takes priority) with your API settings:
|
||||||
```ini
|
```ini
|
||||||
endpoint=https://opencode.ai/zen/v1
|
endpoint=https://opencode.ai/zen/v1
|
||||||
model=deepseek-v4-flash-free
|
model=deepseek-v4-flash-free
|
||||||
@@ -65,7 +65,7 @@ All implementations read the same `model.cfg` and `system.txt` from the current
|
|||||||
- `/list` — list saved sessions (newest first) with their ids, timestamps, message counts and summaries
|
- `/list` — list saved sessions (newest first) with their ids, timestamps, message counts and summaries
|
||||||
- `/load <id>` — load a saved session (exact id or unique prefix) and continue from there
|
- `/load <id>` — load a saved session (exact id or unique prefix) and continue from there
|
||||||
- `/compact` — compact context down to the system message and a concise summary using the LLM; the compaction prompt is appended to the conversation to derive the summary, then the conversation is reset to `[system, summary-user-message]` (a fresh prefix, so downstream prompt-cache hits depend on the provider and are not guaranteed)
|
- `/compact` — compact context down to the system message and a concise summary using the LLM; the compaction prompt is appended to the conversation to derive the summary, then the conversation is reset to `[system, summary-user-message]` (a fresh prefix, so downstream prompt-cache hits depend on the provider and are not guaranteed)
|
||||||
- `/cfg <param> [val]` — inspect or update a configuration parameter in `model.cfg` live
|
- `/cfg <param> [val]` — inspect or update a configuration parameter live (writes to `.bantam.cfg`)
|
||||||
- `/models` — query the `/models` path on the current inference endpoint and print a plain list of supported model IDs, marking the currently configured model with a leading `* ` (Go port)
|
- `/models` — query the `/models` path on the current inference endpoint and print a plain list of supported model IDs, marking the currently configured model with a leading `* ` (Go port)
|
||||||
- `!<cmd>` — execute a shell command directly through `shell_exec` without adding the result to the conversation context (Go port)
|
- `!<cmd>` — execute a shell command directly through `shell_exec` without adding the result to the conversation context (Go port)
|
||||||
- `/help` — show all supported commands
|
- `/help` — show all supported commands
|
||||||
@@ -93,7 +93,7 @@ Using these rules, everyone can build their own copy of Bantam from scratch in l
|
|||||||
|
|
||||||
### High-Level Overview
|
### High-Level Overview
|
||||||
|
|
||||||
1. **Initialization**: Read `system.txt` and `model.cfg`. Discover context window size from the `/models` endpoint (or fallback to `context_window` from `model.cfg` or 200,000 tokens). Prepare an array of messages starting with the system prompt `{"role": "system", "content": system_prompt}`.
|
1. **Initialization**: Read `system.txt` and the config file (`.bantam.cfg` if present, else `model.cfg`). Discover context window size from the `/models` endpoint (or fallback to `context_window` from `model.cfg` or 200,000 tokens). Prepare an array of messages starting with the system prompt `{"role": "system", "content": system_prompt}`.
|
||||||
2. **Input Processing**: Take user prompt (via command-line file parameter or interactive stdin). If prefixed with `!`, execute the command directly via `shell_exec` without appending to conversation context. Otherwise, append `{"role": "user", "content": prompt}`, and invoke `AL(cfg, messages)`.
|
2. **Input Processing**: Take user prompt (via command-line file parameter or interactive stdin). If prefixed with `!`, execute the command directly via `shell_exec` without appending to conversation context. Otherwise, append `{"role": "user", "content": prompt}`, and invoke `AL(cfg, messages)`.
|
||||||
3. **Agentic Loop (`AL`)**:
|
3. **Agentic Loop (`AL`)**:
|
||||||
- Send `messages` and tool definitions to the OpenAI-compatible `/chat/completions` API endpoint with custom `User-Agent` headers and `stream_options: {"include_usage": true}`.
|
- Send `messages` and tool definitions to the OpenAI-compatible `/chat/completions` API endpoint with custom `User-Agent` headers and `stream_options: {"include_usage": true}`.
|
||||||
@@ -110,10 +110,10 @@ Using these rules, everyone can build their own copy of Bantam from scratch in l
|
|||||||
### Main program
|
### Main program
|
||||||
|
|
||||||
1. Read system prompt from `system.txt` (default if missing).
|
1. Read system prompt from `system.txt` (default if missing).
|
||||||
2. Read model parameters from `model.cfg` (`key=value` format) and discover context window size.
|
2. Read model parameters from the config file (`.bantam.cfg` if present, else `model.cfg`) in `key=value` format and discover context window size.
|
||||||
3. Prepare a new message list with the system prompt (`role: "system"`).
|
3. Prepare a new message list with the system prompt (`role: "system"`).
|
||||||
4. Read the first command-line parameter. If non-empty, read user prompt from the specified file. If prefixed with `!`, execute the shell command directly via `shell_exec` and exit. Otherwise, append to `messages` (`role: "user"`), run `AL(cfg, messages)`, display token usage, and exit.
|
4. Read the first command-line parameter. If non-empty, read user prompt from the specified file. If prefixed with `!`, execute the shell command directly via `shell_exec` and exit. Otherwise, append to `messages` (`role: "user"`), run `AL(cfg, messages)`, display token usage, and exit.
|
||||||
5. Read user prompt from standard input (with `readline` line editing and history in `~/.bantam_history`; **Ctrl+J** inserts a real newline into the line being edited). If equal to `/quit` or EOF, exit. If equal to `/clear`, reset `messages` to step 3 and return to step 5. If equal to `/save`, write the whole `messages` array to `~/.bantam/sessions/<id>.json` (with an auto-generated summary) and return to step 5. If equal to `/list`, print saved sessions and their summaries and return to step 5. If starting with `/load`, replace `messages` with the saved session's messages (by exact id or unique prefix) and return to step 5. If equal to `/compact`, ask the LLM to summarize the conversation by appending the compaction prompt to derive the summary, replace `messages` with `[system, summary-user-message]`, and return to step 5. If starting with `/cfg`, display the current value (`/cfg <param>`) or update `model.cfg` live (`/cfg <param> <val>`) and return to step 5. If equal to `/models`, query the `/models` path on the current inference endpoint and print a plain list of supported model IDs (the currently configured model marked with a leading `* `), then return to step 5. If starting with `!`, execute the command directly via `shell_exec` without adding the result to `messages` and return to step 5. If equal to `/help`, print the command list and return to step 5. After every user turn and on exit, auto-save `messages` to `~/.bantam/sessions/autosave.json`.
|
5. Read user prompt from standard input (with `readline` line editing and history in `~/.bantam_history`; **Ctrl+J** inserts a real newline into the line being edited). If equal to `/quit` or EOF, exit. If equal to `/clear`, reset `messages` to step 3 and return to step 5. If equal to `/save`, write the whole `messages` array to `~/.bantam/sessions/<id>.json` (with an auto-generated summary) and return to step 5. If equal to `/list`, print saved sessions and their summaries and return to step 5. If starting with `/load`, replace `messages` with the saved session's messages (by exact id or unique prefix) and return to step 5. If equal to `/compact`, ask the LLM to summarize the conversation by appending the compaction prompt to derive the summary, replace `messages` with `[system, summary-user-message]`, and return to step 5. If starting with `/cfg`, display the current value (`/cfg <param>`) or update the config live by writing to `.bantam.cfg` (`/cfg <param> <val>`) and return to step 5. If equal to `/models`, query the `/models` path on the current inference endpoint and print a plain list of supported model IDs (the currently configured model marked with a leading `* `), then return to step 5. If starting with `!`, execute the command directly via `shell_exec` without adding the result to `messages` and return to step 5. If equal to `/help`, print the command list and return to step 5. After every user turn and on exit, auto-save `messages` to `~/.bantam/sessions/autosave.json`.
|
||||||
6. Append user prompt to `messages` (`role: "user"`), run `AL(cfg, messages)`, display token usage, check 60% context threshold for auto-compaction, and go to step 5.
|
6. Append user prompt to `messages` (`role: "user"`), run `AL(cfg, messages)`, display token usage, check 60% context threshold for auto-compaction, and go to step 5.
|
||||||
|
|
||||||
### Agentic loop (`AL(cfg, messages)`) function
|
### Agentic loop (`AL(cfg, messages)`) function
|
||||||
@@ -137,7 +137,7 @@ If the API rejects the request with an `Invalid assistant message: content or to
|
|||||||
|
|
||||||
### Model configuration parameters
|
### Model configuration parameters
|
||||||
|
|
||||||
(shared by all implementations; `model.cfg` is plain `key=value` with `#` comments)
|
(shared by all implementations; the config file — `.bantam.cfg` takes priority over `model.cfg` when both exist — is plain `key=value` with `#` comments)
|
||||||
|
|
||||||
- `endpoint` (base OpenAI-compatible API URL, default `https://opencode.ai/zen/v1`)
|
- `endpoint` (base OpenAI-compatible API URL, default `https://opencode.ai/zen/v1`)
|
||||||
- `model` (model name, e.g. `gpt-4o`)
|
- `model` (model name, e.g. `gpt-4o`)
|
||||||
@@ -172,7 +172,7 @@ When enabled, the interactive console uses a subtle ANSI palette: the pending-re
|
|||||||
|
|
||||||
## MicroBantam
|
## MicroBantam
|
||||||
|
|
||||||
MicroBantam (`mb`) is a compressed Perl 5 reference implementation of the same agent in **under 100 SLOC**, written to stay readable while keeping the full agentic core. It reads the same `model.cfg` and `system.txt` from the current working directory.
|
MicroBantam (`mb`) is a compressed Perl 5 reference implementation of the same agent in **under 100 SLOC**, written to stay readable while keeping the full agentic core. It reads the config file (`.bantam.cfg` if present, else `model.cfg`) and `system.txt` from the current working directory.
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
@@ -203,14 +203,14 @@ MicroBantam (`mb`) is a compressed Perl 5 reference implementation of the same a
|
|||||||
|
|
||||||
- `main.go`, `term_linux.go`, `term_bsd.go`, `term_windows.go`, `term_other.go` — Go implementation (stdlib only, module `code.luxferre.top/luxferre/bantam`)
|
- `main.go`, `term_linux.go`, `term_bsd.go`, `term_windows.go`, `term_other.go` — Go implementation (stdlib only, module `code.luxferre.top/luxferre/bantam`)
|
||||||
- `mb` — MicroBantam, compressed Perl 5 implementation (core modules only, under 100 SLOC)
|
- `mb` — MicroBantam, compressed Perl 5 implementation (core modules only, under 100 SLOC)
|
||||||
- `model.cfg`, `system.txt` — shared configuration and system prompt
|
- `model.cfg` (or `.bantam.cfg`, which takes priority), `system.txt` — shared configuration and system prompt
|
||||||
- `README.md` — this document
|
- `README.md` — this document
|
||||||
|
|
||||||
## Extra tools
|
## Extra tools
|
||||||
|
|
||||||
The `extras/` directory contains small, dependency-light shell scripts that extend Bantam without changing its core. Because Bantam's only built-in tools are `shell_exec` and `run_subagent`, these helpers can be invoked directly by the agent through `shell_exec` to give it real-world capabilities (web search, live weather) that the base model alone does not have. They are plain `/bin/sh` scripts depending only on `curl` (and `jq` where noted), so the agent can discover and run them just like any other command.
|
The `extras/` directory contains small, dependency-light shell scripts that extend Bantam without changing its core. Because Bantam's only built-in tools are `shell_exec` and `run_subagent`, these helpers can be invoked directly by the agent through `shell_exec` to give it real-world capabilities (web search, live weather) that the base model alone does not have. They are plain `/bin/sh` scripts depending only on `curl` (and `jq` where noted), so the agent can discover and run them just like any other command.
|
||||||
|
|
||||||
If you keep your own collection of helper scripts, point Bantam at them with the `BANTAM_TOOLS_DIR` environment variable or the `bantam_tools_dir` key in `model.cfg`. When either is defined (environment variable taking precedence over the config key), the Go port appends the line `Extra shell tools can be found at <dir>` to the loaded system prompt at startup, so the agent is aware of where to look for them. This hint is propagated to child agents as well (via the `run_subagent` system prompt). The `extras/` scripts shipped here are just examples of what such a directory can contain.
|
If you keep your own collection of helper scripts, point Bantam at them with the `BANTAM_TOOLS_DIR` environment variable or the `bantam_tools_dir` key in the config file (`.bantam.cfg` if present, else `model.cfg`). When either is defined (environment variable taking precedence over the config key), the Go port appends the line `Extra shell tools can be found at <dir>` to the loaded system prompt at startup, so the agent is aware of where to look for them. This hint is propagated to child agents as well (via the `run_subagent` system prompt). The `extras/` scripts shipped here are just examples of what such a directory can contain.
|
||||||
|
|
||||||
### `extras/websearch`
|
### `extras/websearch`
|
||||||
|
|
||||||
@@ -297,11 +297,11 @@ The default system prompt instructs the agent to respect `AGENTS.md`/`GEMINI.md`
|
|||||||
|
|
||||||
### How do I tell Bantam about extra shell tools?
|
### How do I tell Bantam about extra shell tools?
|
||||||
|
|
||||||
Set the `BANTAM_TOOLS_DIR` environment variable (or the `bantam_tools_dir` key in `model.cfg`) to a directory containing your helper scripts. When defined, the Go port appends `Extra shell tools can be found at <dir>` to the system prompt at startup, making the agent aware of them. The environment variable takes precedence over the config key; if neither is set, nothing is appended.
|
Set the `BANTAM_TOOLS_DIR` environment variable (or the `bantam_tools_dir` key in the config file — `.bantam.cfg` if present, else `model.cfg`) to a directory containing your helper scripts. When defined, the Go port appends `Extra shell tools can be found at <dir>` to the system prompt at startup, making the agent aware of them. The environment variable takes precedence over the config key; if neither is set, nothing is appended.
|
||||||
|
|
||||||
### Is there any common config place for Bantam?
|
### Is there any common config place for Bantam?
|
||||||
|
|
||||||
No, loading `model.cfg` and `system.txt` is deliberately only supported from the current working directory. This allows natural separation of configs and system prompts per project. In case there's no `system.txt` inside the project, the concise and sensible default system prompt will be loaded. In case there's no `model.cfg` inside the project, Bantam will use the free Big Pickle model from OpenCode Zen with the temperature 0.7. Big Pickle has been chosen as the default because it has no set expiration date, unlike other OpenCode's keyless tiers.
|
No, loading the config file (`.bantam.cfg` if present, else `model.cfg`) and `system.txt` is deliberately only supported from the current working directory. This allows natural separation of configs and system prompts per project. In case there's no `system.txt` inside the project, the concise and sensible default system prompt will be loaded. In case there's no config file inside the project, Bantam will use the free Big Pickle model from OpenCode Zen with the temperature 0.7. Big Pickle has been chosen as the default because it has no set expiration date, unlike other OpenCode's keyless tiers.
|
||||||
|
|
||||||
### Why no MCP support?
|
### Why no MCP support?
|
||||||
|
|
||||||
|
|||||||
@@ -244,6 +244,15 @@ func setCfg(path, key, val string) error {
|
|||||||
return os.WriteFile(path, []byte(strings.Join(lines, "\n")), 0644)
|
return os.WriteFile(path, []byte(strings.Join(lines, "\n")), 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// configPath returns the configuration file to load: .bantam.cfg takes
|
||||||
|
// priority over model.cfg when both exist in the current working directory,
|
||||||
|
// falling back to model.cfg (which may be absent, triggering defaults).
|
||||||
|
func configPath() string {
|
||||||
|
if _, err := os.Stat(".bantam.cfg"); err == nil {
|
||||||
|
return ".bantam.cfg"
|
||||||
|
}
|
||||||
|
return "model.cfg"
|
||||||
|
}
|
||||||
const defaultSystemPrompt = `You are Bantam, a tiny, powerful AI agent. Solve the user's task using two tools:
|
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.
|
- 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.
|
- run_subagent: delegate a sub-task to a child agent; returns its reply.
|
||||||
@@ -1586,7 +1595,7 @@ func doCompact(cfg *Cfg, msgs []Message) []Message {
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
sp := prompt("system.txt")
|
sp := prompt("system.txt")
|
||||||
cfg := getCfg("model.cfg")
|
cfg := getCfg(configPath())
|
||||||
cfg.ContextWindow = fetchContextWindow(&cfg)
|
cfg.ContextWindow = fetchContextWindow(&cfg)
|
||||||
if td := toolsDir(&cfg); td != "" {
|
if td := toolsDir(&cfg); td != "" {
|
||||||
sp += "\n\nExtra shell tools can be found at " + td
|
sp += "\n\nExtra shell tools can be found at " + td
|
||||||
@@ -1694,11 +1703,11 @@ func main() {
|
|||||||
}
|
}
|
||||||
} else if len(parts) >= 3 {
|
} else if len(parts) >= 3 {
|
||||||
k, v := strings.TrimSpace(parts[1]), strings.TrimSpace(parts[2])
|
k, v := strings.TrimSpace(parts[1]), strings.TrimSpace(parts[2])
|
||||||
if err := setCfg("model.cfg", k, v); err != nil {
|
if err := setCfg(".bantam.cfg", k, v); err != nil {
|
||||||
fmt.Println(c("[cfg error: "+err.Error()+"]", 31))
|
fmt.Println(c("[cfg error: "+err.Error()+"]", 31))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
cfg = getCfg("model.cfg")
|
cfg = getCfg(configPath())
|
||||||
if k == "model" || k == "endpoint" || k == "api_key" {
|
if k == "model" || k == "endpoint" || k == "api_key" {
|
||||||
cfg.ContextWindow = fetchContextWindow(&cfg)
|
cfg.ContextWindow = fetchContextWindow(&cfg)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user