Rebaptise AJEAN en Loki (fork, lignée conservée)

- module github.com/R0m1k3/Loki, cmd/loki, internal/loki (package loki)
- LOKI_HOME, LOKI_MODEL_DIRS, LOKI_SERVICE, LOKI_DL_CONNS ; /etc/loki ;
  units loki-engine / loki-ui ; binaire et aide CLI
- updateRepo pointe sur R0m1k3/Loki (l'auto-update ne tirera plus les
  binaires AJEAN amont)

Conservé à l'identique : le domaine ajean.link (service de tunnel amont),
les littéraux de migration 0.7.x (migrate_07.go), RELEASE_NOTES.md et
LICENSE (historique et licence de l'amont).

go build/vet/test : verts.
This commit is contained in:
Loki committed 2026-08-14 21:33:15 +00:00
1 parent 2164b46319
commit de6551a153
157 files changed
+928 -928

No files matched your search

+120
View File
@@ -0,0 +1,120 @@
package loki
import (
"os"
"path/filepath"
"reflect"
"testing"
)
func TestShardInfo(t *testing.T) {
cases := []struct {
name string
idx, total int
ok bool
}{
{"Laguna-S-2.1-UD-IQ4_XS-00001-of-00003.gguf", 1, 3, true},
{"Laguna-S-2.1-UD-IQ4_XS-00002-of-00003.gguf", 2, 3, true},
{"m-01-of-03.gguf", 1, 3, true},
{"Qwen2.5-7B-Instruct-Q4_K_M.gguf", 0, 0, false},
{"bidon-00004-of-00003.gguf", 0, 0, false}, // numérotation incohérente
{"pas-un-gguf-00001-of-00002.bin", 0, 0, false},
}
for _, c := range cases {
idx, total, ok := shardInfo(c.name)
if idx != c.idx || total != c.total || ok != c.ok {
t.Errorf("shardInfo(%q) = %d,%d,%v ; attendu %d,%d,%v", c.name, idx, total, ok, c.idx, c.total, c.ok)
}
}
}
func TestShardFamilyGardeLaLargeur(t *testing.T) {
got := shardFamily("Laguna-00002-of-00003.gguf")
want := []string{
"Laguna-00001-of-00003.gguf",
"Laguna-00002-of-00003.gguf",
"Laguna-00003-of-00003.gguf",
}
if !reflect.DeepEqual(got, want) {
t.Fatalf("famille = %v ; attendu %v", got, want)
}
if solo := shardFamily("simple.gguf"); !reflect.DeepEqual(solo, []string{"simple.gguf"}) {
t.Fatalf("fichier simple = %v", solo)
}
}
// Le lien collé peut désigner n'importe quelle tranche : on remonte toujours à la
// première, et on ne réécrit QUE le nom de fichier final (le même libellé peut
// apparaître plus haut dans le chemin du dépôt).
func TestShardURLSet(t *testing.T) {
base := "https://huggingface.co/unsloth/Laguna-S-2.1-GGUF/resolve/main/UD-IQ4_XS/"
in := base + "Laguna-UD-IQ4_XS-00002-of-00003.gguf"
urls, names := shardURLSet(in, "Laguna-UD-IQ4_XS-00002-of-00003.gguf")
if len(urls) != 3 || len(names) != 3 {
t.Fatalf("attendu 3 tranches, got %d/%d", len(urls), len(names))
}
if names[0] != "Laguna-UD-IQ4_XS-00001-of-00003.gguf" {
t.Fatalf("première tranche = %q", names[0])
}
if urls[0] != base+"Laguna-UD-IQ4_XS-00001-of-00003.gguf" {
t.Fatalf("URL de la première tranche = %q", urls[0])
}
if urls[2] != base+"Laguna-UD-IQ4_XS-00003-of-00003.gguf" {
t.Fatalf("URL de la dernière tranche = %q", urls[2])
}
// Fichier simple : une seule URL, inchangée.
u, n := shardURLSet(base+"m.gguf", "m.gguf")
if len(u) != 1 || u[0] != base+"m.gguf" || n[0] != "m.gguf" {
t.Fatalf("fichier simple mal traité : %v %v", u, n)
}
}
func TestShardFamilyTailleEtManquantes(t *testing.T) {
dir := t.TempDir()
write := func(n string, size int) {
if err := os.WriteFile(filepath.Join(dir, n), make([]byte, size), 0o644); err != nil {
t.Fatal(err)
}
}
write("m-00001-of-00003.gguf", 100)
write("m-00003-of-00003.gguf", 300)
if got := shardFamilySize(dir, "m-00001-of-00003.gguf"); got != 400 {
t.Fatalf("taille de la famille = %d ; attendu 400", got)
}
missing := shardFamilyMissing(dir, "m-00001-of-00003.gguf")
if !reflect.DeepEqual(missing, []string{"m-00002-of-00003.gguf"}) {
t.Fatalf("tranches manquantes = %v", missing)
}
write("m-00002-of-00003.gguf", 200)
if m := shardFamilyMissing(dir, "m-00001-of-00003.gguf"); len(m) != 0 {
t.Fatalf("famille complète signalée incomplète : %v", m)
}
}
// Supprimer un modèle découpé doit emporter TOUTES ses tranches, sinon des
// dizaines de Go restent sur le disque sans que rien ne sache plus les effacer.
func TestDeleteModelFileEmporteLesTranches(t *testing.T) {
testHome(t)
dir := modelsDir()
if err := os.MkdirAll(dir, 0o755); err != nil {
t.Fatal(err)
}
names := []string{"m-00001-of-00002.gguf", "m-00002-of-00002.gguf", "autre.gguf"}
for _, n := range names {
if err := os.WriteFile(filepath.Join(dir, n), []byte("x"), 0o644); err != nil {
t.Fatal(err)
}
}
if err := deleteModelFile("m-00001-of-00002.gguf"); err != nil {
t.Fatal(err)
}
for _, n := range names[:2] {
if _, err := os.Stat(filepath.Join(dir, n)); !os.IsNotExist(err) {
t.Fatalf("tranche %s non supprimée", n)
}
}
if _, err := os.Stat(filepath.Join(dir, "autre.gguf")); err != nil {
t.Fatal("un modèle sans rapport a été supprimé")
}
}