a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
144 lines
4.2 KiB
Go
144 lines
4.2 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/zzet/gortex/internal/llm"
|
|
)
|
|
|
|
func TestLoadGlobal_LLMSectionRoundTrip(t *testing.T) {
|
|
dir := t.TempDir()
|
|
cfgPath := filepath.Join(dir, "config.yaml")
|
|
require.NoError(t, os.WriteFile(cfgPath, []byte(`active_project: ""
|
|
repos: []
|
|
llm:
|
|
provider: local
|
|
max_steps: 12
|
|
local:
|
|
model: /opt/models/qwen.gguf
|
|
template: chatml
|
|
ctx: 4096
|
|
gpu_layers: 999
|
|
anthropic:
|
|
model: claude-sonnet-4-6
|
|
`), 0o644))
|
|
|
|
gc, err := LoadGlobal(cfgPath)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, gc)
|
|
assert.Equal(t, "local", gc.LLM.Provider)
|
|
assert.Equal(t, 12, gc.LLM.MaxSteps)
|
|
assert.Equal(t, "/opt/models/qwen.gguf", gc.LLM.Local.Model)
|
|
assert.Equal(t, "chatml", gc.LLM.Local.Template)
|
|
assert.Equal(t, 4096, gc.LLM.Local.Ctx)
|
|
assert.Equal(t, 999, gc.LLM.Local.GPULayers)
|
|
assert.Equal(t, "claude-sonnet-4-6", gc.LLM.Anthropic.Model)
|
|
}
|
|
|
|
func TestGlobalConfig_MergeLLMInto_FillsZeroFields(t *testing.T) {
|
|
gc := &GlobalConfig{LLM: llm.Config{
|
|
Provider: "local",
|
|
MaxSteps: 16,
|
|
Local: llm.LocalConfig{
|
|
Model: "/global/qwen.gguf",
|
|
Template: "chatml",
|
|
Ctx: 4096,
|
|
GPULayers: 999,
|
|
},
|
|
}}
|
|
|
|
got := gc.MergeLLMInto(llm.Config{})
|
|
assert.Equal(t, "local", got.Provider)
|
|
assert.Equal(t, 16, got.MaxSteps)
|
|
assert.Equal(t, "/global/qwen.gguf", got.Local.Model)
|
|
assert.Equal(t, "chatml", got.Local.Template)
|
|
assert.Equal(t, 4096, got.Local.Ctx)
|
|
assert.Equal(t, 999, got.Local.GPULayers)
|
|
}
|
|
|
|
func TestGlobalConfig_MergeLLMInto_LocalWinsPerField(t *testing.T) {
|
|
gc := &GlobalConfig{LLM: llm.Config{
|
|
Provider: "local",
|
|
MaxSteps: 16,
|
|
Local: llm.LocalConfig{
|
|
Model: "/global/qwen.gguf",
|
|
Template: "chatml",
|
|
Ctx: 4096,
|
|
},
|
|
}}
|
|
|
|
got := gc.MergeLLMInto(llm.Config{
|
|
Local: llm.LocalConfig{
|
|
Model: "/repo/override.gguf", // local wins
|
|
Ctx: 8192, // local wins
|
|
},
|
|
})
|
|
assert.Equal(t, "/repo/override.gguf", got.Local.Model)
|
|
assert.Equal(t, 8192, got.Local.Ctx)
|
|
// Unset locals fall through to global.
|
|
assert.Equal(t, "chatml", got.Local.Template)
|
|
assert.Equal(t, 16, got.MaxSteps)
|
|
assert.Equal(t, "local", got.Provider)
|
|
}
|
|
|
|
func TestGlobalConfig_MergeLLMInto_PerProviderSubBlocks(t *testing.T) {
|
|
gc := &GlobalConfig{LLM: llm.Config{
|
|
Anthropic: llm.AnthropicConfig{RemoteConfig: llm.RemoteConfig{Model: "claude-sonnet-4-6", APIKeyEnv: "ANTHROPIC_API_KEY"}},
|
|
Ollama: llm.OllamaConfig{Host: "http://localhost:11434"},
|
|
}}
|
|
|
|
// Repo selects a different provider and overrides only one field.
|
|
got := gc.MergeLLMInto(llm.Config{
|
|
Provider: "anthropic",
|
|
Anthropic: llm.AnthropicConfig{RemoteConfig: llm.RemoteConfig{Model: "claude-opus-4-7"}},
|
|
})
|
|
assert.Equal(t, "anthropic", got.Provider)
|
|
assert.Equal(t, "claude-opus-4-7", got.Anthropic.Model) // local wins
|
|
assert.Equal(t, "ANTHROPIC_API_KEY", got.Anthropic.APIKeyEnv) // global fills
|
|
assert.Equal(t, "http://localhost:11434", got.Ollama.Host) // unrelated block still merges
|
|
}
|
|
|
|
func TestGlobalConfig_MergeLLMInto_NilReceiver(t *testing.T) {
|
|
var gc *GlobalConfig // nil
|
|
local := llm.Config{Local: llm.LocalConfig{Model: "/repo/x.gguf"}}
|
|
got := gc.MergeLLMInto(local)
|
|
assert.Equal(t, "/repo/x.gguf", got.Local.Model)
|
|
}
|
|
|
|
func TestGlobalConfig_MergeLLMInto_ExpandsHomeInModelPath(t *testing.T) {
|
|
home, err := os.UserHomeDir()
|
|
require.NoError(t, err)
|
|
|
|
gc := &GlobalConfig{LLM: llm.Config{Local: llm.LocalConfig{Model: "~/models/qwen.gguf"}}}
|
|
got := gc.MergeLLMInto(llm.Config{})
|
|
assert.Equal(t, filepath.Join(home, "models/qwen.gguf"), got.Local.Model)
|
|
|
|
// Local override also gets expanded.
|
|
got = gc.MergeLLMInto(llm.Config{Local: llm.LocalConfig{Model: "~/repo-override.gguf"}})
|
|
assert.Equal(t, filepath.Join(home, "repo-override.gguf"), got.Local.Model)
|
|
}
|
|
|
|
func TestExpandHome(t *testing.T) {
|
|
home, err := os.UserHomeDir()
|
|
require.NoError(t, err)
|
|
|
|
cases := []struct {
|
|
in, want string
|
|
}{
|
|
{"", ""},
|
|
{"/abs/path", "/abs/path"},
|
|
{"relative/path", "relative/path"},
|
|
{"~", home},
|
|
{"~/models/foo.gguf", filepath.Join(home, "models/foo.gguf")},
|
|
{"~weird", "~weird"}, // only `~/` form is expanded
|
|
}
|
|
for _, tc := range cases {
|
|
assert.Equal(t, tc.want, expandHome(tc.in), "in=%q", tc.in)
|
|
}
|
|
}
|