use crate::cm_types::Message;
use std::collections::HashMap;
use crate::cm_agent::plan_rewrite;
#[derive(Debug, Clone, Default)]
pub(crate) struct OuterLoopReflectMemo {
pub(crate) build_idle_streak: u32,
pub(crate) build_idle_feedback_injected: u32,
pub(crate) missing_final_answer_feedback_injected: u32,
}
impl OuterLoopReflectMemo {
pub(crate) fn new() -> Self {
Self::default()
}
pub(crate) fn record_build_idle_round(&mut self) -> u32 {
self.build_idle_streak = self.build_idle_streak.saturating_add(1);
self.build_idle_streak
}
pub(crate) fn reset_build_idle_streak(&mut self) {
self.build_idle_streak = 0;
}
pub(crate) fn record_build_idle_feedback_injected(&mut self) {
self.build_idle_feedback_injected = self.build_idle_feedback_injected.saturating_add(1);
}
pub(crate) fn build_idle_feedback_injected(&self) -> u32 {
self.build_idle_feedback_injected
}
pub(crate) fn record_missing_final_answer_feedback_injected(&mut self) {
self.missing_final_answer_feedback_injected = self
.missing_final_answer_feedback_injected
.saturating_add(1);
}
pub(crate) fn missing_final_answer_feedback_injected(&self) -> u32 {
self.missing_final_answer_feedback_injected
}
}
#[derive(Debug, Clone)]
pub(crate) struct PerTurnCounters {
pub(crate) plan_rewrite_attempts: usize,
pub(crate) outer_loop_reflect: OuterLoopReflectMemo,
}
impl PerTurnCounters {
pub(crate) fn new() -> Self {
Self {
plan_rewrite_attempts: 0,
outer_loop_reflect: OuterLoopReflectMemo::new(),
}
}
pub(crate) fn record_outer_loop_build_idle_round(&mut self) -> u32 {
self.outer_loop_reflect.record_build_idle_round()
}
pub(crate) fn reset_outer_loop_build_idle_streak(&mut self) {
self.outer_loop_reflect.reset_build_idle_streak();
}
pub(crate) fn record_outer_loop_build_idle_feedback_injected(&mut self) {
self.outer_loop_reflect
.record_build_idle_feedback_injected();
}
pub(crate) fn outer_loop_build_idle_feedback_injected(&self) -> u32 {
self.outer_loop_reflect.build_idle_feedback_injected()
}
pub(crate) fn record_outer_loop_missing_final_answer_feedback_injected(&mut self) {
self.outer_loop_reflect
.record_missing_final_answer_feedback_injected();
}
pub(crate) fn outer_loop_missing_final_answer_feedback_injected(&self) -> u32 {
self.outer_loop_reflect
.missing_final_answer_feedback_injected()
}
}
#[derive(Debug, Clone)]
pub(crate) struct WorkflowValidateLayerCache {
cached_workflow_validate_layer_count: Option<usize>,
layer_count_cache_at_message_len: usize,
}
impl WorkflowValidateLayerCache {
pub(crate) fn new() -> Self {
Self {
cached_workflow_validate_layer_count: None,
layer_count_cache_at_message_len: 0,
}
}
pub(crate) fn invalidate_after_context_mutation(&mut self) {
self.cached_workflow_validate_layer_count = None;
self.layer_count_cache_at_message_len = 0;
}
#[cfg(test)]
pub(crate) fn snapshot(&self) -> (Option<usize>, usize) {
(
self.cached_workflow_validate_layer_count,
self.layer_count_cache_at_message_len,
)
}
pub(crate) fn workflow_validate_layer_need(&mut self, messages: &[Message]) -> Option<usize> {
let len = messages.len();
if len != self.layer_count_cache_at_message_len {
let n = plan_rewrite::last_workflow_validate_layer_count(messages);
self.cached_workflow_validate_layer_count = n;
self.layer_count_cache_at_message_len = len;
return n;
}
if self.cached_workflow_validate_layer_count.is_some() {
return self.cached_workflow_validate_layer_count;
}
let n = plan_rewrite::last_workflow_validate_layer_count(messages);
self.cached_workflow_validate_layer_count = n;
self.layer_count_cache_at_message_len = len;
n
}
pub(crate) fn refresh_after_messages_append(
&mut self,
messages_len: usize,
messages: &[Message],
) {
self.layer_count_cache_at_message_len = messages_len;
self.cached_workflow_validate_layer_count =
plan_rewrite::last_workflow_validate_layer_count(messages);
}
}
#[derive(Debug, Clone)]
pub(crate) struct RepeatedToolFailureMemo {
repeated_failed_tool_signatures: HashMap<(String, String), String>,
repeated_failed_tool_families: HashMap<(String, String), String>,
}
impl RepeatedToolFailureMemo {
pub(crate) fn new() -> Self {
Self {
repeated_failed_tool_signatures: HashMap::new(),
repeated_failed_tool_families: HashMap::new(),
}
}
pub(crate) fn repeated_tool_failure_error_marker(
&self,
tool_name: &str,
tool_args_json: &str,
) -> Option<&str> {
self.repeated_failed_tool_signatures
.get(&(tool_name.to_string(), tool_args_json.to_string()))
.map(|s| s.as_str())
}
pub(crate) fn mark_tool_failure_signature(
&mut self,
tool_name: &str,
tool_args_json: &str,
error_marker: String,
) {
self.repeated_failed_tool_signatures.insert(
(tool_name.to_string(), tool_args_json.to_string()),
error_marker,
);
}
pub(crate) fn repeated_tool_failure_family_marker(
&self,
tool_name: &str,
failure_family: &str,
) -> Option<&str> {
self.repeated_failed_tool_families
.get(&(tool_name.to_string(), failure_family.to_string()))
.map(|s| s.as_str())
}
pub(crate) fn mark_tool_failure_family(
&mut self,
tool_name: &str,
failure_family: &str,
error_marker: String,
) {
self.repeated_failed_tool_families.insert(
(tool_name.to_string(), failure_family.to_string()),
error_marker,
);
}
pub(crate) fn clear_tool_failure_signature(&mut self, tool_name: &str, tool_args_json: &str) {
self.repeated_failed_tool_signatures
.remove(&(tool_name.to_string(), tool_args_json.to_string()));
}
pub(crate) fn clear_tool_failure_families_for_tool(&mut self, tool_name: &str) {
self.repeated_failed_tool_families
.retain(|(name, _), _| name != tool_name);
}
pub(crate) fn clear_all_tool_failure_state_for_tool(&mut self, tool_name: &str) {
self.repeated_failed_tool_signatures
.retain(|(name, _), _| name != tool_name);
self.clear_tool_failure_families_for_tool(tool_name);
}
}
#[derive(Debug, Clone, Default)]
pub(crate) struct SuccessfulRunCommandDedupeMemo {
outputs: HashMap<String, String>,
}
impl SuccessfulRunCommandDedupeMemo {
pub(crate) fn new() -> Self {
Self {
outputs: HashMap::new(),
}
}
pub(crate) fn cached_output(&self, suppress_key: &str) -> Option<&str> {
self.outputs.get(suppress_key).map(|s| s.as_str())
}
pub(crate) fn record_success(&mut self, suppress_key: String, output: String) {
self.outputs.insert(suppress_key, output);
}
pub(crate) fn clear_all(&mut self) {
self.outputs.clear();
}
}