mirror of
https://github.com/patriceckhart/zot.git
synced 2026-06-26 21:36:31 +02:00
Single Go module, four top-level packages under packages/. Import
paths become github.com/patriceckhart/zot/packages/<name>; downstream
consumers can depend on individual packages without pulling the rest.
Layout:
packages/provider/ LLM clients + catalog
packages/provider/auth/ credential store + OAuth + login server
packages/core/ agent loop, sessions, cost
packages/tui/ terminal toolkit + chat view
packages/agent/ CLI wiring, system prompt
extensions/ extproto/ modes/ tools/ skills/ swarm/
sdk/ (was pkg/zotcore, package renamed zotcore -> sdk)
ext/ (was pkg/zotext, package renamed zotext -> ext)
internal/ and pkg/ removed. The internal/assets logo moved into
packages/provider/auth/assets.
Public Go SDK identifiers renamed:
pkg/zotcore (package zotcore) -> packages/agent/sdk (package sdk)
pkg/zotext (package zotext) -> packages/agent/ext (package ext)
This breaks Go-based extensions and embedders; the JSON wire protocol
for extensions and RPC is unchanged, so non-Go extensions, already-
built extension binaries, and zot rpc consumers are unaffected.
Docs, examples, and the built-in write-zot-extension skill updated
for the new paths and identifiers. Shadow-bug fixes in code samples
(ext := ext.New -> e := ext.New).
121 lines
3.3 KiB
Go
121 lines
3.3 KiB
Go
package agent
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
// TestValidateAndRepairConfig_MismatchedPair simulates the bug from a
|
|
// stale /model switch: provider=anthropic but model=kimi-for-coding
|
|
// (which belongs to provider=kimi). The validator should rewrite the
|
|
// model to anthropic's default and persist.
|
|
func TestValidateAndRepairConfig_MismatchedPair(t *testing.T) {
|
|
home := t.TempDir()
|
|
t.Setenv("ZOT_HOME", home)
|
|
|
|
must := func(c Config) {
|
|
t.Helper()
|
|
b, _ := json.Marshal(c)
|
|
if err := os.WriteFile(filepath.Join(home, "config.json"), b, 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
must(Config{Provider: "anthropic", Model: "kimi-for-coding"})
|
|
|
|
ValidateAndRepairConfig()
|
|
|
|
out, err := LoadConfig()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if out.Provider != "anthropic" {
|
|
t.Errorf("provider not preserved: %q", out.Provider)
|
|
}
|
|
if out.Model == "kimi-for-coding" {
|
|
t.Errorf("model not repaired; still %q", out.Model)
|
|
}
|
|
if out.Model == "" {
|
|
t.Errorf("model not set; expected anthropic default")
|
|
}
|
|
}
|
|
|
|
// TestValidateAndRepairConfig_UnknownProvider resets to anthropic and
|
|
// clears the model when the saved provider id isn't recognised
|
|
// (e.g. user removed it from a previous build).
|
|
func TestValidateAndRepairConfig_UnknownProvider(t *testing.T) {
|
|
home := t.TempDir()
|
|
t.Setenv("ZOT_HOME", home)
|
|
|
|
b, _ := json.Marshal(Config{Provider: "made-up-provider", Model: "some-model"})
|
|
_ = os.WriteFile(filepath.Join(home, "config.json"), b, 0o644)
|
|
|
|
ValidateAndRepairConfig()
|
|
|
|
out, _ := LoadConfig()
|
|
if out.Provider != "anthropic" {
|
|
t.Errorf("provider not reset: %q", out.Provider)
|
|
}
|
|
if out.Model != "" {
|
|
t.Errorf("model not cleared: %q", out.Model)
|
|
}
|
|
}
|
|
|
|
// TestValidateAndRepairConfig_UnknownModel keeps the provider but
|
|
// snaps the model to that provider's default when the saved id is no
|
|
// longer in the catalog.
|
|
func TestValidateAndRepairConfig_UnknownModel(t *testing.T) {
|
|
home := t.TempDir()
|
|
t.Setenv("ZOT_HOME", home)
|
|
|
|
b, _ := json.Marshal(Config{Provider: "anthropic", Model: "claude-deleted-model"})
|
|
_ = os.WriteFile(filepath.Join(home, "config.json"), b, 0o644)
|
|
|
|
ValidateAndRepairConfig()
|
|
|
|
out, _ := LoadConfig()
|
|
if out.Provider != "anthropic" {
|
|
t.Errorf("provider changed: %q", out.Provider)
|
|
}
|
|
if out.Model == "" || out.Model == "claude-deleted-model" {
|
|
t.Errorf("model not repaired: %q", out.Model)
|
|
}
|
|
}
|
|
|
|
func TestValidateAndRepairConfig_DuplicateModelIDValidForConfiguredProvider(t *testing.T) {
|
|
home := t.TempDir()
|
|
t.Setenv("ZOT_HOME", home)
|
|
|
|
b, _ := json.Marshal(Config{Provider: "openai-codex", Model: "gpt-5.5"})
|
|
_ = os.WriteFile(filepath.Join(home, "config.json"), b, 0o644)
|
|
|
|
ValidateAndRepairConfig()
|
|
|
|
out, _ := LoadConfig()
|
|
if out.Provider != "openai-codex" {
|
|
t.Errorf("provider mutated: %q", out.Provider)
|
|
}
|
|
if out.Model != "gpt-5.5" {
|
|
t.Errorf("model mutated: %q", out.Model)
|
|
}
|
|
}
|
|
|
|
// TestValidateAndRepairConfig_HappyPath leaves a valid config alone.
|
|
func TestValidateAndRepairConfig_HappyPath(t *testing.T) {
|
|
home := t.TempDir()
|
|
t.Setenv("ZOT_HOME", home)
|
|
|
|
b, _ := json.Marshal(Config{Provider: "anthropic", Model: "claude-sonnet-4-5"})
|
|
_ = os.WriteFile(filepath.Join(home, "config.json"), b, 0o644)
|
|
|
|
ValidateAndRepairConfig()
|
|
|
|
out, _ := LoadConfig()
|
|
if out.Provider != "anthropic" {
|
|
t.Errorf("provider mutated: %q", out.Provider)
|
|
}
|
|
if out.Model != "claude-sonnet-4-5" {
|
|
t.Errorf("model mutated: %q", out.Model)
|
|
}
|
|
}
|