evaluator redesign: response types, silence, structural suppression

new engagement types: Respond (inline), ThreadReply (threaded),
React, Ignore. LLM returns response_type to decide HOW to engage.

silence mechanic: "shut up"/"be quiet" sets a 30min per-room timer.
only direct @mention breaks through.

structural suppression (A+B):
- reply to non-Sol human → capped at React
- 3+ human messages since Sol → forced passive mode

threads have a lower relevance threshold (70% of spontaneous).
time context injected into evaluator prompt.
This commit is contained in:
2026-03-23 01:41:57 +00:00
parent 1058afb635
commit 3b62d86c45
3 changed files with 244 additions and 48 deletions

View File

@@ -28,6 +28,18 @@ pub struct AgentsConfig {
/// Whether to use the Conversations API (vs manual message management).
#[serde(default)]
pub use_conversations_api: bool,
/// Model for research micro-agents.
#[serde(default = "default_research_agent_model")]
pub research_model: String,
/// Max tool calls per research micro-agent.
#[serde(default = "default_research_max_iterations")]
pub research_max_iterations: usize,
/// Max parallel agents per research wave.
#[serde(default = "default_research_max_agents")]
pub research_max_agents: usize,
/// Max recursion depth for research agents spawning sub-agents.
#[serde(default = "default_research_max_depth")]
pub research_max_depth: usize,
}
impl Default for AgentsConfig {
@@ -37,6 +49,10 @@ impl Default for AgentsConfig {
domain_model: default_model(),
compaction_threshold: default_compaction_threshold(),
use_conversations_api: false,
research_model: default_research_agent_model(),
research_max_iterations: default_research_max_iterations(),
research_max_agents: default_research_max_agents(),
research_max_depth: default_research_max_depth(),
}
}
}
@@ -122,12 +138,22 @@ pub struct BehaviorConfig {
pub script_fetch_allowlist: Vec<String>,
#[serde(default = "default_memory_extraction_enabled")]
pub memory_extraction_enabled: bool,
/// Minimum fraction of a source room's members that must also be in the
/// requesting room for cross-room search results to be visible.
/// 0.0 = no restriction, 1.0 = only same room.
#[serde(default = "default_room_overlap_threshold")]
pub room_overlap_threshold: f32,
/// Duration in ms that Sol stays silent after being told to be quiet.
#[serde(default = "default_silence_duration_ms")]
pub silence_duration_ms: u64,
}
#[derive(Debug, Clone, Deserialize, Default)]
pub struct ServicesConfig {
#[serde(default)]
pub gitea: Option<GiteaConfig>,
#[serde(default)]
pub kratos: Option<KratosConfig>,
}
#[derive(Debug, Clone, Deserialize)]
@@ -135,6 +161,11 @@ pub struct GiteaConfig {
pub url: String,
}
#[derive(Debug, Clone, Deserialize)]
pub struct KratosConfig {
pub admin_url: String,
}
#[derive(Debug, Clone, Deserialize)]
pub struct VaultConfig {
/// OpenBao/Vault URL. Default: http://openbao.data.svc.cluster.local:8200
@@ -187,8 +218,14 @@ fn default_script_timeout_secs() -> u64 { 5 }
fn default_script_max_heap_mb() -> usize { 64 }
fn default_memory_index() -> String { "sol_user_memory".into() }
fn default_memory_extraction_enabled() -> bool { true }
fn default_room_overlap_threshold() -> f32 { 0.25 }
fn default_silence_duration_ms() -> u64 { 1_800_000 } // 30 minutes
fn default_db_path() -> String { "/data/sol.db".into() }
fn default_compaction_threshold() -> u32 { 118000 } // ~90% of 131K context window
fn default_research_agent_model() -> String { "ministral-3b-latest".into() }
fn default_research_max_iterations() -> usize { 10 }
fn default_research_max_agents() -> usize { 25 }
fn default_research_max_depth() -> usize { 4 }
impl Config {
pub fn load(path: &str) -> anyhow::Result<Self> {
@@ -322,6 +359,17 @@ state_store_path = "/data/sol/state"
assert!(config.services.gitea.is_none());
}
#[test]
fn test_services_config_with_kratos() {
let with_kratos = format!(
"{}\n[services.kratos]\nadmin_url = \"http://kratos-admin:80\"\n",
MINIMAL_CONFIG
);
let config = Config::from_str(&with_kratos).unwrap();
let kratos = config.services.kratos.unwrap();
assert_eq!(kratos.admin_url, "http://kratos-admin:80");
}
#[test]
fn test_services_config_with_gitea() {
let with_services = format!(