mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-12 01:37:06 +02:00
mode agent : toggle web pour désactiver la limite d'appels d'outils (config TOOL_LIMIT)
La limite iter<8 (message [stop: trop d'appels d'outils]) est désormais pilotée par TOOL_LIMIT dans config.env, exposée par un interrupteur sous Mode agent. Activée par défaut ; désactivée => plafond quasi illimité (l'anti-boucle sur appels répétés reste actif). Lu à chaque tour, pas de restart nécessaire. Tunnelé tel quel via /api/e2e/req pour ajean.link.
This commit is contained in:
1 parent
cc24074f69
commit
5ef02672d2
4 files changed
+55
-2
No files matched your search
@@ -139,6 +139,27 @@ func SetConfigKey(key, value string) error {
|
||||
return os.WriteFile(confPath(), []byte(content), 0o644)
|
||||
}
|
||||
|
||||
// toolLimitEnabled reports whether the per-turn tool-call cap is active.
|
||||
// Default: true (limité). Only an explicit "off"/"false"/"0"/"no" in config.env
|
||||
// (TOOL_LIMIT) disables it — anything else keeps the safety cap on.
|
||||
func toolLimitEnabled() bool {
|
||||
switch strings.ToLower(strings.TrimSpace(ReadConfig()["TOOL_LIMIT"])) {
|
||||
case "off", "false", "0", "no", "non":
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// toolCallLimit returns the max number of agentic tool-call iterations per turn.
|
||||
// 8 when the limit is on (default), a very high ceiling when the user disabled it
|
||||
// from the web UI — the repeated-call anti-loop still guards against runaways.
|
||||
func toolCallLimit() int {
|
||||
if toolLimitEnabled() {
|
||||
return 8
|
||||
}
|
||||
return 1000
|
||||
}
|
||||
|
||||
// LLMPort returns the configured server port (config.env PORT), default 8080.
|
||||
func LLMPort() int {
|
||||
if p, ok := ReadConfig()["PORT"]; ok {
|
||||
|
||||
@@ -356,7 +356,12 @@ func runChat(ctx context.Context, messages []Message, temperature float64, caps
|
||||
// (ni réponse, ni tool_call). On relance alors UNE fois le tour avec un nudge
|
||||
// explicite au lieu d'afficher « pas de réponse ».
|
||||
nudged := false
|
||||
for iter := 0; iter < 8; iter++ {
|
||||
// Plafond d'itérations d'appels d'outils. Activé par défaut (8) pour éviter
|
||||
// qu'un modèle parti en vrille n'enchaîne les appels indéfiniment ; l'anti-
|
||||
// boucle (lastSig) protège toujours même quand la limite est désactivée via
|
||||
// l'UI (TOOL_LIMIT=off → plafond très haut, quasi illimité).
|
||||
maxIter := toolCallLimit()
|
||||
for iter := 0; iter < maxIter; iter++ {
|
||||
payload := map[string]any{
|
||||
"model": "jean",
|
||||
"messages": messages,
|
||||
|
||||
@@ -186,6 +186,8 @@ button:disabled{opacity:.5;cursor:not-allowed}
|
||||
<details><summary>Mode agent <span id="agent-badge" style="margin-left:auto;font-size:10px"></span></summary>
|
||||
<label class="switchrow"><span class="switch"><input type="checkbox" id="agent-toggle" onchange="toggleAgent()"><span class="slider"></span></span> activer le mode agent</label>
|
||||
<div class="muted" style="font-size:11px">⚠️ active l'<b>accès machine</b> (shell complet via <b>bash</b> sur le serveur) <b>et</b> la <b>mémoire</b> — l'IA peut inspecter, lancer des scripts et lire/écrire ses pages mémoire (timeout 30s, max 300s)</div>
|
||||
<label class="switchrow"><span class="switch"><input type="checkbox" id="toollimit-toggle" onchange="toggleToolLimit()"><span class="slider"></span></span> limiter les appels d'outils par tour</label>
|
||||
<div class="muted" style="font-size:11px">activé par défaut : coupe l'IA après ~8 appels d'outils (message <code>[stop: trop d'appels d'outils]</code>). Désactive-le si tu veux la laisser enchaîner sans plafond (l'anti-boucle reste actif).</div>
|
||||
<div class="skillshead"><span>Mémoire</span><button class="addbtn" onclick="event.preventDefault();event.stopPropagation();openMem('')" title="ajouter une page mémoire">+ ajouter</button></div>
|
||||
<div id="mem-list" class="muted" style="font-size:12px"></div>
|
||||
</details>
|
||||
@@ -414,6 +416,7 @@ async function loadAgent(){
|
||||
const s=await jget('/api/agent');
|
||||
const on = s.enabled;
|
||||
document.getElementById('agent-toggle').checked = on;
|
||||
document.getElementById('toollimit-toggle').checked = (s.tool_limit !== false);
|
||||
document.getElementById('agent-badge').innerHTML = on
|
||||
? '<span class="tag ok">on</span>' : '<span class="tag" style="opacity:.6">off</span>';
|
||||
document.getElementById('brand').classList.toggle('agent', on);
|
||||
@@ -430,6 +433,11 @@ async function toggleAgent(){
|
||||
await jpost('/api/agent/toggle',{on});
|
||||
loadAgent();
|
||||
}
|
||||
async function toggleToolLimit(){
|
||||
const on=document.getElementById('toollimit-toggle').checked;
|
||||
await jpost('/api/agent/tool-limit',{on});
|
||||
loadAgent();
|
||||
}
|
||||
async function loadAll(){ await Promise.all([loadStatus(),loadVram(),loadCfg(),loadPresets(),loadAgent()]); }
|
||||
async function act(a){ toast(a+'…'); await jpost('/api/'+a); setTimeout(loadAll,1500); }
|
||||
function openBenchModal(){ document.getElementById('bench-modal').style.display = 'flex'; }
|
||||
|
||||
@@ -85,6 +85,7 @@ func newWebMux() *http.ServeMux {
|
||||
api("/api/preset/delete", handlePresetDelete)
|
||||
api("/api/agent", handleAgent)
|
||||
api("/api/agent/toggle", handleAgentToggle)
|
||||
api("/api/agent/tool-limit", handleToolLimitToggle)
|
||||
// Alias rétro-compat : l'ancien portail ajean.link (dépôt jean-relay) pilote
|
||||
// encore l'agent via /api/tools* et /api/skills/toggle à travers le tunnel E2E.
|
||||
// On les mappe sur le mode agent unifié le temps que le portail soit mis à jour.
|
||||
@@ -436,7 +437,25 @@ func handleAgent(w http.ResponseWriter, r *http.Request) {
|
||||
for _, p := range pages {
|
||||
out = append(out, map[string]any{"name": p.Name, "desc": p.Title})
|
||||
}
|
||||
sendJSON(w, 200, map[string]any{"enabled": agentEnabled(), "pages": out, "skills": out})
|
||||
sendJSON(w, 200, map[string]any{"enabled": agentEnabled(), "tool_limit": toolLimitEnabled(), "pages": out, "skills": out})
|
||||
}
|
||||
|
||||
// handleToolLimitToggle active/désactive le plafond d'appels d'outils par tour
|
||||
// (config.env TOOL_LIMIT). On=limité (défaut), off=quasi illimité.
|
||||
func handleToolLimitToggle(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
On bool `json:"on"`
|
||||
}
|
||||
_ = json.NewDecoder(r.Body).Decode(&req)
|
||||
val := ""
|
||||
if !req.On {
|
||||
val = "off"
|
||||
}
|
||||
if err := SetConfigKey("TOOL_LIMIT", val); err != nil {
|
||||
sendJSON(w, 500, map[string]any{"ok": false, "error": err.Error()})
|
||||
return
|
||||
}
|
||||
sendJSON(w, 200, map[string]any{"ok": true, "tool_limit": toolLimitEnabled()})
|
||||
}
|
||||
|
||||
func handleAgentToggle(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
Reference in new issue
Block a user