mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-24 15:38:12 +02:00
v0.8.7 : envoyer et recevoir des fichiers dans le chat
Les fichiers circulent enfin dans les deux sens. Envoi : trombone dans le composeur, glisser-deposer sur toute la fenetre, ou Ctrl+V. Le fichier est depose dans uploads/ du dossier de travail de l'agent et son chemin est annonce au modele, qui en fait ce qu'il veut avec ses outils. Rien n'est interprete au passage, donc tout type de fichier passe. Le depot n'a lieu qu'a l'ENVOI du message : retirer un fichier de la liste ne laisse aucune trace sur le disque. Transport en base64 dans du JSON et non en multipart, seule forme que le tunnel E2E dispatche : l'acces distant marche sans code specifique. Reception : le modele ecrit un lien Markdown ordinaire vers un fichier de son dossier de travail, et le clic telecharge. Il repondait jusqu'ici par un chemin serveur, inutilisable depuis un navigateur. Le clic passe par fetch + blob (la cle de pilotage voyage dans un en-tete qu'une navigation ne porterait pas, et le chemin de base change derriere le tunnel). Markdown refusant les espaces non echappes dans une cible de lien, ils sont encodes avant rendu : sans ca [x](mon rapport.pdf) ne produisait rien du tout. Perimetre du telechargement strictement limite au dossier de travail : '..', chemins absolus et liens symboliques qui en sortent sont refuses, et le fichier est toujours servi en piece jointe avec nosniff — un .html produit par le modele ne doit pas s'executer dans l'origine de l'UI, ou il lirait la cle de pilotage. Preambule du mode agent : ~2350 -> ~1770 tokens, sans perdre une regle. Le poids etait dans les schemas d'outils (le double du prompt), pas dans le prompt. Celui-ci reenumerait des outils que les schemas decrivent deja, et la regle « write, jamais echo » y figurait trois fois. Trois tests gardent le budget : ce prompt a deja regrossi ligne par ligne deux fois. Aussi : l'export mentionne les pieces jointes (un message sans texte donnait une section vide), et le decompte de contexte perd le mot « contexte » au profit du nom du modele.
This commit is contained in:
1 parent
5a4c33661d
commit
6807bad48d
23 files changed
+1363
-104
No files matched your search
@@ -11,14 +11,13 @@ import (
|
||||
func webSearchTool() Tool {
|
||||
return Tool{Type: "function", Function: ToolFunction{
|
||||
Name: "web_search",
|
||||
Description: "Recherche sur le web via DuckDuckGo. Renvoie une liste classée de {title, url, snippet}. " +
|
||||
"À utiliser quand l'utilisateur pose une question sans URL, cherche un outil/une bibliothèque, " +
|
||||
"ou demande une information récente. À enchaîner avec web_open + web_read sur le meilleur résultat.",
|
||||
Description: "Recherche web (DuckDuckGo) → liste classée de {title, url, snippet}. " +
|
||||
"Pour une question sans URL ou une information récente. Enchaîner avec web_open + web_read sur le meilleur résultat.",
|
||||
Parameters: map[string]any{
|
||||
"type": "object",
|
||||
"properties": map[string]any{
|
||||
"query": map[string]any{"type": "string", "description": "Requête (langage naturel ou mots-clés)"},
|
||||
"limit": map[string]any{"type": "integer", "description": "Nb max de résultats (défaut 8, max 20)"},
|
||||
"query": map[string]any{"type": "string", "description": "Requête"},
|
||||
"limit": map[string]any{"type": "integer", "description": "Défaut 8, max 20"},
|
||||
},
|
||||
"required": []string{"query"},
|
||||
},
|
||||
@@ -35,17 +34,15 @@ func webSearchTool() Tool {
|
||||
// donc que ce que le moteur sait réellement faire, et on annonce la limite du JS
|
||||
// dans la description pour que le modèle change de source au lieu d'insister.
|
||||
func webOpenTool() Tool {
|
||||
desc := "Récupère une URL et renvoie SEULEMENT les métadonnées (taille, nb de lignes, plan des titres). " +
|
||||
"Ne renvoie PAS le contenu. Toujours appeler ceci d'abord avant de lire. Résultat en cache 10 min " +
|
||||
"— les web_read / web_grep suivants le réutilisent."
|
||||
desc := "Récupère une URL et renvoie SEULEMENT ses métadonnées (taille, nb de lignes, plan des titres), " +
|
||||
"PAS le contenu. Toujours l'appeler avant de lire ; mis en cache 10 min pour les web_read/web_grep suivants."
|
||||
props := map[string]any{
|
||||
"url": map[string]any{"type": "string", "description": "URL complète à récupérer"},
|
||||
"refresh": map[string]any{"type": "boolean", "description": "Ignore le cache et re-fetch. Défaut false."},
|
||||
"url": map[string]any{"type": "string", "description": "URL complète"},
|
||||
"refresh": map[string]any{"type": "boolean", "description": "Ignore le cache. Défaut false."},
|
||||
}
|
||||
if webEngine() == engineGo {
|
||||
desc += " ⚠ Ce moteur lit le HTML servi SANS exécuter le JavaScript : une page rendue " +
|
||||
"entièrement côté client ressortira vide. Dans ce cas, ne réessaie pas la même URL — " +
|
||||
"cherche une autre source (doc officielle, dépôt, article)."
|
||||
desc += " ⚠ Ce moteur ne lit que le HTML servi, SANS JavaScript : une page rendue côté client " +
|
||||
"ressort vide. Dans ce cas ne réessaie pas la même URL, change de source."
|
||||
} else {
|
||||
props["actions"] = map[string]any{"type": "array", "items": map[string]any{"type": "string"},
|
||||
"description": "Snippets JS à exécuter sur la page AVANT extraction (déplier des sections, cliquer 'voir plus', etc.)."}
|
||||
@@ -65,15 +62,14 @@ func webOpenTool() Tool {
|
||||
|
||||
func webReadTool() Tool {
|
||||
return Tool{Type: "function", Function: ToolFunction{
|
||||
Name: "web_read",
|
||||
Description: "Lit une plage de lignes d'une URL déjà ouverte avec web_open. Coût en tokens prévisible. " +
|
||||
"Lignes 1-indexées, préfixées par leur numéro.",
|
||||
Name: "web_read",
|
||||
Description: "Lit une plage de lignes d'une URL déjà ouverte avec web_open. Lignes 1-indexées, préfixées par leur numéro.",
|
||||
Parameters: map[string]any{
|
||||
"type": "object",
|
||||
"properties": map[string]any{
|
||||
"url": map[string]any{"type": "string", "description": "URL précédemment ouverte avec web_open"},
|
||||
"offset": map[string]any{"type": "integer", "description": "Ligne de départ (1-indexée, défaut 1)"},
|
||||
"limit": map[string]any{"type": "integer", "description": "Nb de lignes (défaut 80, max 500)"},
|
||||
"url": map[string]any{"type": "string", "description": "URL ouverte avec web_open"},
|
||||
"offset": map[string]any{"type": "integer", "description": "Ligne de départ (défaut 1)"},
|
||||
"limit": map[string]any{"type": "integer", "description": "Défaut 80, max 500"},
|
||||
},
|
||||
"required": []string{"url"},
|
||||
},
|
||||
@@ -83,15 +79,15 @@ func webReadTool() Tool {
|
||||
func webGrepTool() Tool {
|
||||
return Tool{Type: "function", Function: ToolFunction{
|
||||
Name: "web_grep",
|
||||
Description: "Recherche regex dans une URL déjà ouverte avec web_open. Renvoie les lignes correspondantes " +
|
||||
"avec contexte et numéros. Idéal quand la page est longue et qu'on connaît un mot-clé.",
|
||||
Description: "Recherche regex dans une URL déjà ouverte avec web_open → lignes correspondantes, " +
|
||||
"avec contexte et numéros. Idéal sur une page longue dont on connaît un mot-clé.",
|
||||
Parameters: map[string]any{
|
||||
"type": "object",
|
||||
"properties": map[string]any{
|
||||
"url": map[string]any{"type": "string", "description": "URL précédemment ouverte avec web_open"},
|
||||
"pattern": map[string]any{"type": "string", "description": "Motif regex (insensible à la casse)"},
|
||||
"context": map[string]any{"type": "integer", "description": "Lignes de contexte autour de chaque match. Défaut 2."},
|
||||
"max_matches": map[string]any{"type": "integer", "description": "Plafond de matches renvoyés. Défaut 30."},
|
||||
"url": map[string]any{"type": "string", "description": "URL ouverte avec web_open"},
|
||||
"pattern": map[string]any{"type": "string", "description": "Regex (insensible à la casse)"},
|
||||
"context": map[string]any{"type": "integer", "description": "Lignes de contexte. Défaut 2."},
|
||||
"max_matches": map[string]any{"type": "integer", "description": "Plafond. Défaut 30."},
|
||||
},
|
||||
"required": []string{"url", "pattern"},
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user