env tweaks
This commit is contained in:
+120
-8
@@ -262,8 +262,20 @@ func TestDefaultSystemPrompt(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func clearBantamEnv(t *testing.T) {
|
||||
for _, k := range []string{
|
||||
"BANTAM_ENDPOINT", "BANTAM_MODEL", "BANTAM_TEMP", "BANTAM_TEMPERATURE",
|
||||
"BANTAM_API_KEY", "BANTAM_STREAM", "BANTAM_COLOR", "BANTAM_NO_COLOR",
|
||||
"BANTAM_TIMEOUT", "BANTAM_SHELL_TIMEOUT", "BANTAM_MAX_AL_ITERATIONS",
|
||||
"BANTAM_CONTEXT_WINDOW", "BANTAM_REASONING_EFFORT", "BANTAM_TOOLS_DIR",
|
||||
"BANTAM_SKILLS_DIR",
|
||||
} {
|
||||
t.Setenv(k, "")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCfgDefaults(t *testing.T) {
|
||||
t.Setenv("BANTAM_API_KEY", "")
|
||||
clearBantamEnv(t)
|
||||
cfg := getCfg(filepath.Join(t.TempDir(), "missing.cfg"))
|
||||
if cfg.Endpoint != defCfg.Endpoint || cfg.Model != defCfg.Model || cfg.APIKey != defCfg.APIKey {
|
||||
t.Errorf("defaults mismatch: %+v", cfg)
|
||||
@@ -280,6 +292,7 @@ func TestGetCfgDefaults(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetCfgParsesFile(t *testing.T) {
|
||||
clearBantamEnv(t)
|
||||
p := writeCfg(t, strings.Join([]string{
|
||||
"endpoint=http://localhost:9999/v1",
|
||||
"model=test-model",
|
||||
@@ -317,6 +330,7 @@ func TestGetCfgParsesFile(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetCfgIgnoresCommentsBlankAndInvalid(t *testing.T) {
|
||||
clearBantamEnv(t)
|
||||
p := writeCfg(t, strings.Join([]string{
|
||||
"# comment",
|
||||
"",
|
||||
@@ -345,6 +359,7 @@ func TestGetCfgIgnoresCommentsBlankAndInvalid(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetCfgStreamTruthyVariants(t *testing.T) {
|
||||
clearBantamEnv(t)
|
||||
for _, tc := range []struct{ v, want string }{
|
||||
{"true", "true"}, {"1", "true"}, {"yes", "true"},
|
||||
{"false", "false"}, {"TRUE", "false"}, {"0", "false"},
|
||||
@@ -359,6 +374,7 @@ func TestGetCfgStreamTruthyVariants(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetCfgAPIKeyEnvFallback(t *testing.T) {
|
||||
clearBantamEnv(t)
|
||||
t.Setenv("BANTAM_API_KEY", "sk-env")
|
||||
t.Setenv("HOME", t.TempDir())
|
||||
|
||||
@@ -389,16 +405,34 @@ func TestGetCfgAPIKeyEnvFallback(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetCfgEnvOverriddenByFile(t *testing.T) {
|
||||
// New env vars BANTAM_ENDPOINT / BANTAM_MODEL / BANTAM_TEMP act as fallbacks
|
||||
// that must yield to any value set in the config file (.bantam.cfg).
|
||||
// File values override environment variables.
|
||||
clearBantamEnv(t)
|
||||
t.Setenv("BANTAM_ENDPOINT", "http://env-endpoint/v1")
|
||||
t.Setenv("BANTAM_MODEL", "env-model")
|
||||
t.Setenv("BANTAM_TEMP", "0.9")
|
||||
t.Setenv("BANTAM_API_KEY", "")
|
||||
t.Setenv("BANTAM_STREAM", "false")
|
||||
t.Setenv("BANTAM_COLOR", "never")
|
||||
t.Setenv("BANTAM_TIMEOUT", "45")
|
||||
t.Setenv("BANTAM_SHELL_TIMEOUT", "15")
|
||||
t.Setenv("BANTAM_MAX_AL_ITERATIONS", "50")
|
||||
t.Setenv("BANTAM_CONTEXT_WINDOW", "100000")
|
||||
t.Setenv("BANTAM_REASONING_EFFORT", "low")
|
||||
t.Setenv("BANTAM_TOOLS_DIR", "/env/tools")
|
||||
t.Setenv("BANTAM_SKILLS_DIR", "/env/skills")
|
||||
|
||||
p := writeCfg(t, strings.Join([]string{
|
||||
"endpoint=http://file-endpoint/v1",
|
||||
"model=file-model",
|
||||
"temperature=0.1",
|
||||
"stream=true",
|
||||
"color=always",
|
||||
"timeout=300",
|
||||
"shell_timeout=120",
|
||||
"max_al_iterations=1000",
|
||||
"context_window=200000",
|
||||
"reasoning_effort=high",
|
||||
"bantam_tools_dir=/file/tools",
|
||||
"bantam_skills_dir=/file/skills",
|
||||
}, "\n"))
|
||||
cfg := getCfg(p)
|
||||
if cfg.Endpoint != "http://file-endpoint/v1" {
|
||||
@@ -410,18 +444,72 @@ func TestGetCfgEnvOverriddenByFile(t *testing.T) {
|
||||
if cfg.Temperature != 0.1 {
|
||||
t.Errorf("temperature: got %v, want file value", cfg.Temperature)
|
||||
}
|
||||
if !cfg.Stream {
|
||||
t.Errorf("stream: got %v, want true from file", cfg.Stream)
|
||||
}
|
||||
if cfg.Color != "always" {
|
||||
t.Errorf("color: got %q, want always from file", cfg.Color)
|
||||
}
|
||||
if cfg.Timeout != 300 {
|
||||
t.Errorf("timeout: got %d, want 300 from file", cfg.Timeout)
|
||||
}
|
||||
if cfg.ShellTimeout != 120 {
|
||||
t.Errorf("shell_timeout: got %d, want 120 from file", cfg.ShellTimeout)
|
||||
}
|
||||
if cfg.MaxALIterations != 1000 {
|
||||
t.Errorf("max_al_iterations: got %d, want 1000 from file", cfg.MaxALIterations)
|
||||
}
|
||||
if cfg.ContextWindow != 200000 {
|
||||
t.Errorf("context_window: got %d, want 200000 from file", cfg.ContextWindow)
|
||||
}
|
||||
if cfg.Raw["reasoning_effort"] != "high" {
|
||||
t.Errorf("reasoning_effort: got %q, want high from file", cfg.Raw["reasoning_effort"])
|
||||
}
|
||||
if toolsDir(&cfg) != "/file/tools" {
|
||||
t.Errorf("toolsDir: got %q, want /file/tools", toolsDir(&cfg))
|
||||
}
|
||||
if skillsDir(&cfg) != "/file/skills" {
|
||||
t.Errorf("skillsDir: got %q, want /file/skills", skillsDir(&cfg))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCfgEnvFallbackWhenNoFile(t *testing.T) {
|
||||
// Without a config file the new env vars supply the values.
|
||||
clearBantamEnv(t)
|
||||
t.Setenv("BANTAM_ENDPOINT", "http://env-endpoint/v1")
|
||||
t.Setenv("BANTAM_MODEL", "env-model")
|
||||
t.Setenv("BANTAM_TEMP", "0.42")
|
||||
t.Setenv("BANTAM_STREAM", "false")
|
||||
t.Setenv("BANTAM_COLOR", "never")
|
||||
t.Setenv("BANTAM_TIMEOUT", "45")
|
||||
t.Setenv("BANTAM_SHELL_TIMEOUT", "15")
|
||||
t.Setenv("BANTAM_MAX_AL_ITERATIONS", "50")
|
||||
t.Setenv("BANTAM_CONTEXT_WINDOW", "100000")
|
||||
t.Setenv("BANTAM_REASONING_EFFORT", "low")
|
||||
t.Setenv("BANTAM_TOOLS_DIR", "/env/tools")
|
||||
t.Setenv("BANTAM_SKILLS_DIR", "/env/skills")
|
||||
t.Setenv("BANTAM_API_KEY", "")
|
||||
cfg := getCfg(filepath.Join(t.TempDir(), "missing.cfg"))
|
||||
if cfg.Endpoint != "http://env-endpoint/v1" || cfg.Model != "env-model" || cfg.Temperature != 0.42 {
|
||||
t.Errorf("env fallback mismatch: %+v", cfg)
|
||||
}
|
||||
if cfg.Stream {
|
||||
t.Errorf("stream: got %v, want false from env", cfg.Stream)
|
||||
}
|
||||
if cfg.Color != "never" {
|
||||
t.Errorf("color: got %q, want never from env", cfg.Color)
|
||||
}
|
||||
if cfg.Timeout != 45 || cfg.ShellTimeout != 15 || cfg.MaxALIterations != 50 || cfg.ContextWindow != 100000 {
|
||||
t.Errorf("numeric env fallback mismatch: %+v", cfg)
|
||||
}
|
||||
if cfg.Raw["reasoning_effort"] != "low" {
|
||||
t.Errorf("reasoning_effort: got %q, want low from env", cfg.Raw["reasoning_effort"])
|
||||
}
|
||||
if toolsDir(&cfg) != "/env/tools" {
|
||||
t.Errorf("toolsDir: got %q, want /env/tools", toolsDir(&cfg))
|
||||
}
|
||||
if skillsDir(&cfg) != "/env/skills" {
|
||||
t.Errorf("skillsDir: got %q, want /env/skills", skillsDir(&cfg))
|
||||
}
|
||||
}
|
||||
|
||||
func TestAtoiD(t *testing.T) {
|
||||
@@ -1446,6 +1534,7 @@ func TestCompactHappyPath(t *testing.T) {
|
||||
// ---------- setCfg and LLM parameter forwarding ----------
|
||||
|
||||
func TestSetCfgUpdatesAndAppends(t *testing.T) {
|
||||
clearBantamEnv(t)
|
||||
p := filepath.Join(t.TempDir(), "model.cfg")
|
||||
if err := os.WriteFile(p, []byte("model=old-model\ntemperature=0.5\n"), 0644); err != nil {
|
||||
t.Fatalf("WriteFile: %v", err)
|
||||
@@ -1471,6 +1560,7 @@ func TestSetCfgUpdatesAndAppends(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLLMForwardsRelevantParameters(t *testing.T) {
|
||||
clearBantamEnv(t)
|
||||
var received map[string]any
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewDecoder(r.Body).Decode(&received)
|
||||
@@ -2575,9 +2665,12 @@ func TestSkills(t *testing.T) {
|
||||
}
|
||||
|
||||
// skillsDir prefers the config key, then the environment variable.
|
||||
t.Setenv("BANTAM_SKILLS_DIR", skillDir)
|
||||
if got := skillsDir(&Cfg{}); got != skillDir {
|
||||
t.Errorf("skillsDir() with env = %q, want %q", got, skillDir)
|
||||
t.Setenv("BANTAM_SKILLS_DIR", "/env/skills")
|
||||
if got := skillsDir(&Cfg{Raw: map[string]string{"bantam_skills_dir": skillDir}}); got != skillDir {
|
||||
t.Errorf("skillsDir() with config overriding env = %q, want %q", got, skillDir)
|
||||
}
|
||||
if got := skillsDir(&Cfg{Raw: map[string]string{}}); got != "/env/skills" {
|
||||
t.Errorf("skillsDir() with env fallback = %q, want %q", got, "/env/skills")
|
||||
}
|
||||
t.Setenv("BANTAM_SKILLS_DIR", "")
|
||||
if got := skillsDir(&Cfg{Raw: map[string]string{"bantam_skills_dir": skillDir}}); got != skillDir {
|
||||
@@ -2623,6 +2716,7 @@ func TestSkills(t *testing.T) {
|
||||
|
||||
// #19: bare /skill lists skills under the configured dir, or reports none.
|
||||
func TestListSkills(t *testing.T) {
|
||||
t.Setenv("BANTAM_SKILLS_DIR", "")
|
||||
base := t.TempDir()
|
||||
skillDir := filepath.Join(base, "skills")
|
||||
if err := os.MkdirAll(filepath.Join(skillDir, "alpha"), 0755); err != nil {
|
||||
@@ -2669,3 +2763,21 @@ func TestListSkills(t *testing.T) {
|
||||
listSkills(&Cfg{})
|
||||
os.Stdout.Close()
|
||||
}
|
||||
|
||||
func TestToolsDir(t *testing.T) {
|
||||
t.Setenv("BANTAM_TOOLS_DIR", "/env/tools")
|
||||
if got := toolsDir(&Cfg{Raw: map[string]string{"bantam_tools_dir": "/config/tools"}}); got != "/config/tools" {
|
||||
t.Errorf("toolsDir() with config overriding env = %q, want /config/tools", got)
|
||||
}
|
||||
if got := toolsDir(&Cfg{Raw: map[string]string{}}); got != "/env/tools" {
|
||||
t.Errorf("toolsDir() with env fallback = %q, want /env/tools", got)
|
||||
}
|
||||
t.Setenv("BANTAM_TOOLS_DIR", "")
|
||||
if got := toolsDir(&Cfg{Raw: map[string]string{"bantam_tools_dir": "/config/tools"}}); got != "/config/tools" {
|
||||
t.Errorf("toolsDir() with config = %q, want /config/tools", got)
|
||||
}
|
||||
if got := toolsDir(&Cfg{}); got != "" {
|
||||
t.Errorf("toolsDir() empty = %q, want empty", got)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user