mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-19 21:18:20 +02:00
Presets : glisser-déposer, pastilles contexte et capacités, prompt système dans l'éditeur
Repris d'AJEAN et adapté à Loki : - liste réordonnable par glisser-déposer (SortableJS 1.15.6, MIT), ordre gardé côté serveur (/api/presets/order) et suivi par le sélecteur de l'en-tête ; le clic de fin de glissement ne bascule pas de preset - pastille de contexte (32K, 128K, 40K…) et pastille « capacités » : œil quand le preset lit les images (MMPROJ, API externe déclarée multimodale, Strata), ampoule + niveau quand il raisonne - éditeur : prompt système DE CE preset (rangé en base, sysprompt:<id>), projecteur vision sur le CPU (--no-mmproj-offload, visible seulement avec un mmproj) - les projecteurs mmproj ne sont plus proposés comme modèle (éditeur et sélecteur de l'en-tête) - l'aide « ? » reste survolable sur un réglage grisé Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
127013b32b
commit
ecff7de5a3
11 files changed
+412
-27
No files matched your search
@@ -441,9 +441,20 @@ func handlePresets(w http.ResponseWriter, r *http.Request) {
|
||||
if m := strings.TrimSpace(cfg[extKeyModel]); m != "" {
|
||||
item["model"] = m
|
||||
}
|
||||
if strings.TrimSpace(cfg[extKeyVision]) == "1" {
|
||||
item["vision"] = true
|
||||
}
|
||||
out = append(out, item)
|
||||
continue
|
||||
}
|
||||
// Pastilles de la liste : taille de contexte, et l'œil quand le preset
|
||||
// charge un projecteur vision (repris d'AJEAN v0.10.1 / v0.10.9).
|
||||
if c := presetCtx(content); c != "" {
|
||||
item["ctx"] = c
|
||||
}
|
||||
if strings.TrimSpace(parseEnv(content)["MMPROJ"]) != "" {
|
||||
item["vision"] = true
|
||||
}
|
||||
// Strata : réglages dans sa propre fenêtre, pas l'éditeur llama.cpp.
|
||||
if cfg := parseEnv(content); isStrataConfig(cfg) {
|
||||
item["strata"] = true
|
||||
@@ -481,6 +492,26 @@ func handlePresets(w http.ResponseWriter, r *http.Request) {
|
||||
sendJSON(w, 200, out)
|
||||
}
|
||||
|
||||
// handlePresetsOrder (POST {ids}) : l'ordre de la liste choisi par glisser-déposer.
|
||||
func handlePresetsOrder(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
sendJSON(w, 405, map[string]any{"ok": false, "error": "POST attendu"})
|
||||
return
|
||||
}
|
||||
var req struct {
|
||||
IDs []string `json:"ids"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
sendJSON(w, 400, map[string]any{"ok": false, "error": err.Error()})
|
||||
return
|
||||
}
|
||||
if err := savePresetOrder(req.IDs); err != nil {
|
||||
sendJSON(w, 500, map[string]any{"ok": false, "error": err.Error()})
|
||||
return
|
||||
}
|
||||
sendJSON(w, 200, map[string]any{"ok": true})
|
||||
}
|
||||
|
||||
func handlePreset(w http.ResponseWriter, r *http.Request) {
|
||||
id := strings.TrimSpace(r.URL.Query().Get("id"))
|
||||
if id == "" {
|
||||
@@ -492,16 +523,20 @@ func handlePreset(w http.ResponseWriter, r *http.Request) {
|
||||
sendJSON(w, 404, map[string]any{"error": "not found"})
|
||||
return
|
||||
}
|
||||
sendJSON(w, 200, map[string]any{"id": id, "name": presetDisplayName(content, id), "content": content})
|
||||
sendJSON(w, 200, map[string]any{"id": id, "name": presetDisplayName(content, id), "content": content,
|
||||
"sysprompt": getStr(bkState, sysPromptKeyPrefix+id)})
|
||||
}
|
||||
|
||||
// presetSaveReq is the preset editor payload. `id` identifies an existing
|
||||
// preset to update ("" creates a new one); `name` is the display name.
|
||||
// SysPrompt : le prompt système DE CE preset, édité dans l'éditeur (repris
|
||||
// d'AJEAN v0.13.0) ; nil = champ absent, on n'y touche pas.
|
||||
type presetSaveReq struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Content string `json:"content"`
|
||||
DeleteModel bool `json:"deleteModel"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Content string `json:"content"`
|
||||
DeleteModel bool `json:"deleteModel"`
|
||||
SysPrompt *string `json:"sysprompt,omitempty"`
|
||||
}
|
||||
|
||||
// saveReq is the skill editor payload (skills keep name-as-identity + rename).
|
||||
@@ -604,6 +639,12 @@ func handlePresetSave(w http.ResponseWriter, r *http.Request) {
|
||||
sendJSON(w, 400, map[string]any{"ok": false, "error": err.Error()})
|
||||
return
|
||||
}
|
||||
if req.SysPrompt != nil {
|
||||
if err := putStr(bkState, sysPromptKeyPrefix+newID, strings.TrimSpace(*req.SysPrompt)); err != nil {
|
||||
sendJSON(w, 500, map[string]any{"ok": false, "error": err.Error()})
|
||||
return
|
||||
}
|
||||
}
|
||||
if applied {
|
||||
fmt.Printf("%s config.env <- %s (preset actif modifié)\n", green("[ok]"), newID)
|
||||
fmt.Println(dim("[info] redémarrage du service..."))
|
||||
|
||||
Reference in new issue
Block a user