mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-18 12:46:56 +02:00
Lot 6 : la façade reçoit le chat du Go et ses événements
Une requête qui porte le jeton interne vient du Go, qui l'a déjà authentifiée (tunnel du relais) : les routes du chat la servent sans redemander la clé. L'API interne de la façade, réservée à ce jeton, reçoit les événements d'affichage nés au Go (mode Code, critères) et le rechargement après déverrouillage : une discussion chargée vide mémoire verrouillée revient au déverrouillage, jamais par-dessus un fil rempli (sinon le premier message aurait écrasé la discussion chiffrée). Le relais par la façade de /api/chat/mode et /api/chat/criteria et les critères rendus par l'outil disparaissent : le Go pousse ses événements lui-même, une seule source quel que soit le chemin. README : LOKI_CHAT=rust et ce qu'il ne prend pas encore en charge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
This commit is contained in:
9 files changed
+175
-90
No files matched your search
@@ -752,12 +752,6 @@ impl ChatService {
|
||||
kwargs: reasoning.kwargs.clone().unwrap_or_default(),
|
||||
},
|
||||
queued: Box::new(move || me.drain_queued(epoch)),
|
||||
notice: {
|
||||
let conv = conv.clone();
|
||||
Box::new(move |d| {
|
||||
conv.append_delta(epoch, d);
|
||||
})
|
||||
},
|
||||
};
|
||||
|
||||
// Chaque événement devient un delta du journal.
|
||||
|
||||
@@ -312,9 +312,6 @@ pub struct GoTurnHost {
|
||||
pub compact: TurnCompact,
|
||||
/// Messages mis en file par l'utilisateur pendant le tour.
|
||||
pub queued: Box<dyn Fn() -> Vec<Message> + Send + Sync>,
|
||||
/// Événement d'affichage né d'un outil hors du flux du modèle (critères
|
||||
/// changés par l'outil `criteria`), à journaliser.
|
||||
pub notice: Box<dyn Fn(Map<String, Value>) + Send + Sync>,
|
||||
}
|
||||
|
||||
/// `toolResID` : « <discussion>.<24 hex> ».
|
||||
@@ -399,19 +396,7 @@ impl TurnHost for GoTurnHost {
|
||||
.tool_exec(name, &Value::Object(args.clone()), &self.caps)
|
||||
.await
|
||||
{
|
||||
Ok(v) => {
|
||||
if let Some(list) = v.get("criteria").filter(|l| l.is_array()) {
|
||||
let ts = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.map(|d| d.as_millis() as i64)
|
||||
.unwrap_or(0);
|
||||
let mut d = Map::new();
|
||||
d.insert("criteria".into(), list.clone());
|
||||
d.insert("ts".into(), ts.into());
|
||||
(self.notice)(d);
|
||||
}
|
||||
tool_outcome(&v, label)
|
||||
}
|
||||
Ok(v) => tool_outcome(&v, label),
|
||||
Err(e) => ToolOutcome {
|
||||
result: format!("[erreur] exécution de l'outil impossible : {e}"),
|
||||
..Default::default()
|
||||
|
||||
@@ -220,6 +220,24 @@ impl<H: SessionHooks> Sessions<H> {
|
||||
Err(last_err)
|
||||
}
|
||||
|
||||
/// `reloadEncryptedStores` : après le déverrouillage de la mémoire,
|
||||
/// recharge la discussion si elle a été chargée vide (mémoire verrouillée
|
||||
/// au démarrage). Jamais un fil déjà rempli : écraser le tour en cours le
|
||||
/// perdrait. Rend vrai si elle a été rechargée.
|
||||
pub async fn reload_if_empty(&self) -> Result<bool, String> {
|
||||
let _op = self.op.lock().await;
|
||||
if self.conv.is_generating() || !self.conv.with_state(|st| st.log.is_empty()) {
|
||||
return Ok(false);
|
||||
}
|
||||
let id = self.ensure_active_locked().await?;
|
||||
let Some(body) = self.store.get_open(BK_CHAT, &conv_key(&id)).await? else {
|
||||
return Ok(false);
|
||||
};
|
||||
self.conv.load_from(&id, &body);
|
||||
self.hooks.activated(&id).await;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
/// `convEnsureActive` : identifiant de la discussion active, créée au
|
||||
/// besoin (reprise silencieuse du fil unique d'avant les discussions).
|
||||
pub async fn ensure_active(&self) -> Result<String, String> {
|
||||
|
||||
Reference in new issue
Block a user