mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-23 23:18:13 +02:00
Lot 42 : outils web de l'agent exécutés par la façade
Les outils web des tours de la façade (web_search, web_images, web_open,
web_read, web_grep) ne passent plus par /tool/exec du Go : src/webtools.rs
porte chat_internet_tools.go, chat_internet.go et chat_web_images.go. Le
cache des pages (10 min, clé MD5 des options comme le Go) est dans la
façade ; client Crawl4AI au corps près, réponses lues comme json.Unmarshal ;
résultats DuckDuckGo tirés du markdown (uddg, entités, extraits) ;
recherche d'images avec le jeton vqd et les cookies gardés par hôte ;
web_grep sur les regex du Go, erreurs au texte de regexp.
Le moteur intégré lit le HTML avec go-readability et html-to-markdown, que
rien en Rust ne reproduit au caractère près : la conversion d'une page et la
lecture des résultats restent au Go, derrière /internal/v1/web/fetch et
/internal/v1/web/search (sans état). web_screenshot reste au Go.
Le traducteur go_regex refuse la répétition d'une répétition et les comptes
au-delà de 1000, et rend littéral un « { » qui n'ouvre pas de répétition,
comme le Go (motifs retry_patterns compris).
Parité : journal de 74 appels tiré du Go (parity_web_tools_test.go →
tests/parity_web/outils.json : résultats, requêtes reçues par les faux
Crawl4AI et DuckDuckGo, pages demandées au moteur intégré), rejoué par
tests/webtools.rs ; un tour de la façade qui ouvre une page (tests/lot6.rs) ;
TestInternalMoteurWebIntegre côté Go.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
This commit is contained in:
19 files changed
+4561
-7
No files matched your search
@@ -671,6 +671,7 @@ async fn tour_complet_par_le_go() {
|
||||
mcp: None,
|
||||
tasks: None,
|
||||
memory: None,
|
||||
web: Default::default(),
|
||||
go_version: Default::default(),
|
||||
});
|
||||
let cfg = std::collections::HashMap::new();
|
||||
@@ -2746,3 +2747,44 @@ async fn outil_memoire_par_la_facade() {
|
||||
.clone();
|
||||
assert_eq!(tool, serde_json::json!("[ok] page 'chat' créée"));
|
||||
}
|
||||
|
||||
/// Lot 42 : un outil web d'un tour de la façade s'exécute chez elle (cache
|
||||
/// des pages compris) ; seule la conversion du moteur intégré est demandée
|
||||
/// au Go, jamais /tool/exec.
|
||||
#[tokio::test]
|
||||
async fn outil_web_par_la_facade() {
|
||||
let call = sse(&[
|
||||
serde_json::json!({"choices":[{"delta":{"tool_calls":[{"index":0,"id":"w1","type":"function","function":{"name":"web_open","arguments":"{\"url\":\"https://exemple.test/doc\"}"}}]}}]}),
|
||||
serde_json::json!({"choices":[{"delta":{},"finish_reason":"tool_calls"}]}),
|
||||
]);
|
||||
let (url, seen) = fake_engine(vec![call, answer("lu")]).await;
|
||||
let (svc, go, _stop, _t) = service_with(Some(&url), |_| {}).await;
|
||||
go.set("config", "WEB_ENGINE", "go");
|
||||
go.web_fetch.lock().unwrap().insert(
|
||||
"https://exemple.test/doc".into(),
|
||||
serde_json::json!({"markdown": "# Doc\n\n## Partie\ntexte"}),
|
||||
);
|
||||
svc.send(serde_json::json!({"message": "lis la doc", "cid": "w"}))
|
||||
.await
|
||||
.unwrap();
|
||||
until_done(&svc, 1).await;
|
||||
assert!(go.tool_log.lock().unwrap().is_empty(), "{:?}", go.tool_log);
|
||||
assert_eq!(
|
||||
*go.web_log.lock().unwrap(),
|
||||
vec!["fetch https://exemple.test/doc".to_string()]
|
||||
);
|
||||
let seen = seen.lock().unwrap().clone();
|
||||
let tool = seen[1].1["messages"]
|
||||
.as_array()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.rfind(|m| m["role"] == "tool")
|
||||
.unwrap()["content"]
|
||||
.clone();
|
||||
assert_eq!(
|
||||
tool,
|
||||
serde_json::json!(
|
||||
"# Ouvert : https://exemple.test/doc\nTotal : 4 lignes, 23 B (23 caractères)\nEn cache 10 min. Utilise web_read ou web_grep pour lire.\n\n## Plan (n° de ligne des titres)\n```\n 1 | Doc\n 3 | Partie\n```"
|
||||
)
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user