fix(hive-mind): ganti gerbang pipeline berbasis jumlah pesan dengan deteksi konvergensi sebelumnya
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
a125f5d440
commit
5498088532
@@ -992,10 +992,19 @@ fn run_agent_turn(
|
|||||||
|
|
||||||
// ── AUTO CEO PIPELINE ──
|
// ── AUTO CEO PIPELINE ──
|
||||||
// Before the main agent starts working, check if the pipeline should run.
|
// Before the main agent starts working, check if the pipeline should run.
|
||||||
let user_msg_count = msgs.iter()
|
// Gated on whether a hive-mind convergence has already happened earlier
|
||||||
.filter(|m| matches!(m.role, crate::dto::chat::message::Role::User))
|
// in this session (detected from message content), not an arbitrary
|
||||||
.count();
|
// message-count cutoff — a complex request in message 5 deserves the
|
||||||
let should_pipeline = if user_msg_count <= 2 {
|
// same treatment as one in message 1, as long as this session hasn't
|
||||||
|
// already converged once.
|
||||||
|
let already_ran_hive_mind = crate::app::workflow::hive_mind::hive_mind_already_ran(
|
||||||
|
msgs.iter()
|
||||||
|
.filter(|m| matches!(m.role, crate::dto::chat::message::Role::System))
|
||||||
|
.filter_map(|m| m.content.as_deref())
|
||||||
|
);
|
||||||
|
let should_pipeline = if already_ran_hive_mind {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
let user_request = msgs.iter()
|
let user_request = msgs.iter()
|
||||||
.rev().find(|m| matches!(m.role, crate::dto::chat::message::Role::User))
|
.rev().find(|m| matches!(m.role, crate::dto::chat::message::Role::User))
|
||||||
.and_then(|m| m.content.as_deref())
|
.and_then(|m| m.content.as_deref())
|
||||||
@@ -1006,8 +1015,6 @@ fn run_agent_turn(
|
|||||||
} else {
|
} else {
|
||||||
crate::app::workflow::hive_mind::is_complex_request(user_request)
|
crate::app::workflow::hive_mind::is_complex_request(user_request)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if should_pipeline {
|
if should_pipeline {
|
||||||
@@ -1112,7 +1119,8 @@ fn run_agent_turn(
|
|||||||
tracing::info!("[hive-mind] convergence completed successfully");
|
tracing::info!("[hive-mind] convergence completed successfully");
|
||||||
|
|
||||||
let pipeline_msg = ChatMessage::system(format!(
|
let pipeline_msg = ChatMessage::system(format!(
|
||||||
"[Hive-Mind Consensus]\n{consensus}",
|
"{}\n{consensus}",
|
||||||
|
crate::app::workflow::hive_mind::HIVE_MIND_CONSENSUS_TAG,
|
||||||
));
|
));
|
||||||
archive_message(tc.db.as_ref(), &tc.session_id, &pipeline_msg);
|
archive_message(tc.db.as_ref(), &tc.session_id, &pipeline_msg);
|
||||||
msgs.push(pipeline_msg);
|
msgs.push(pipeline_msg);
|
||||||
|
|||||||
@@ -69,6 +69,27 @@ pub struct NodeReport {
|
|||||||
pub output: String,
|
pub output: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tag prefixing the system message `run_hive_mind`'s caller pushes into
|
||||||
|
/// the conversation after a successful convergence. Shared between the
|
||||||
|
/// push site (`actions/mod.rs`) and `hive_mind_already_ran` below so the
|
||||||
|
/// two can never drift out of sync.
|
||||||
|
pub const HIVE_MIND_CONSENSUS_TAG: &str = "[Hive-Mind Consensus]";
|
||||||
|
|
||||||
|
/// Detect whether a hive-mind convergence has already run earlier in this
|
||||||
|
/// conversation, by checking prior system-message bodies for the
|
||||||
|
/// consensus tag.
|
||||||
|
///
|
||||||
|
/// Why: gates re-triggering the Core Intelligence pipeline more than once
|
||||||
|
/// per session on message *content* actually observed, rather than an
|
||||||
|
/// arbitrary "first two user messages" cutoff that silently disabled the
|
||||||
|
/// pipeline for any complex request phrased later in a long conversation.
|
||||||
|
///
|
||||||
|
/// Return: `true` if any prior system message starts with
|
||||||
|
/// `HIVE_MIND_CONSENSUS_TAG`.
|
||||||
|
pub fn hive_mind_already_ran<'a>(system_message_bodies: impl Iterator<Item = &'a str>) -> bool {
|
||||||
|
system_message_bodies.into_iter().any(|body| body.starts_with(HIVE_MIND_CONSENSUS_TAG))
|
||||||
|
}
|
||||||
|
|
||||||
/// Build the live-state callback that forwards node status updates to the
|
/// Build the live-state callback that forwards node status updates to the
|
||||||
/// TUI's workflow panel.
|
/// TUI's workflow panel.
|
||||||
fn build_live(
|
fn build_live(
|
||||||
@@ -408,4 +429,19 @@ mod tests {
|
|||||||
let node_id = format!("Node-{}-{}", 2, 1);
|
let node_id = format!("Node-{}-{}", 2, 1);
|
||||||
assert_eq!(node_id, "Node-2-1");
|
assert_eq!(node_id, "Node-2-1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hive_mind_already_ran_detects_prior_consensus_tag() {
|
||||||
|
let bodies = vec![
|
||||||
|
"you are a helpful assistant".to_string(),
|
||||||
|
format!("{HIVE_MIND_CONSENSUS_TAG}\nthe bug is a null check"),
|
||||||
|
];
|
||||||
|
assert!(hive_mind_already_ran(bodies.iter().map(std::string::String::as_str)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hive_mind_already_ran_false_when_no_prior_convergence() {
|
||||||
|
let bodies = vec!["you are a helpful assistant".to_string()];
|
||||||
|
assert!(!hive_mind_already_ran(bodies.iter().map(std::string::String::as_str)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user