Skip to content

Commit 0f88715

Browse files
committed
figured out big miscalc in token estimation from memories and where summaries were sometimes being lost.
1 parent 7462589 commit 0f88715

File tree

6 files changed

+52
-77
lines changed

6 files changed

+52
-77
lines changed

crates/pattern_core/src/context/compression.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ impl MessageCompressor {
447447
// No compression needed
448448
return Ok(CompressionResult {
449449
active_batches: batches,
450-
summary: None,
450+
summary: self.existing_archive_summary.clone(),
451451
archived_batches: Vec::new(),
452452
metadata: CompressionMetadata {
453453
strategy_used: "recursive_summarization_no_compression".to_string(),
@@ -520,7 +520,7 @@ impl MessageCompressor {
520520
// Nothing to summarize
521521
return Ok(CompressionResult {
522522
active_batches,
523-
summary: None,
523+
summary: self.existing_archive_summary.clone(),
524524
archived_batches: Vec::new(),
525525
metadata: CompressionMetadata {
526526
strategy_used: "recursive_summarization".to_string(),
@@ -537,6 +537,10 @@ impl MessageCompressor {
537537
const MAX_TOKENS_PER_REQUEST: usize = 128_000; // Conservative limit for safety
538538

539539
let mut accumulated_summaries = Vec::new();
540+
if let Some(ref summary) = self.existing_archive_summary {
541+
accumulated_summaries.push(super::clip_archive_summary(&summary, 4, 8));
542+
}
543+
540544
let mut batch_index = 0;
541545

542546
while batch_index < archived_batches.len() {

crates/pattern_core/src/context/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ impl MemoryContext {
118118
/// Clip a delimited archive summary to show the first N and last M blocks.
119119
/// Blocks are separated by two-or-more consecutive newlines. If there are not
120120
/// enough blocks, return the original summary.
121-
fn clip_archive_summary(summary: &str, head: usize, tail: usize) -> String {
121+
pub fn clip_archive_summary(summary: &str, head: usize, tail: usize) -> String {
122122
// Split on two-or-more newlines (treat multiple blank lines as block separators)
123123
// Compiling each time is acceptable here due to infrequent calls.
124124
let delim_re = Regex::new(r"\n{2,}").expect("valid delimiter regex");

crates/pattern_core/src/context/state.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,7 +1602,7 @@ impl AgentContext {
16021602
let needs_token_compression =
16031603
if let Some(max_tokens) = self.context_config.max_context_tokens {
16041604
// Estimate current token usage
1605-
let memory_blocks = self.handle.memory.get_all_blocks();
1605+
let memory_blocks = self.handle.memory.get_all_non_recall();
16061606
let system_tokens = self.estimate_system_prompt_tokens(&memory_blocks);
16071607
let message_tokens: usize = history
16081608
.batches
@@ -2019,7 +2019,7 @@ impl AgentContext {
20192019
let mut history = self.history.write().await;
20202020

20212021
// Calculate system prompt tokens (including memory blocks)
2022-
let memory_blocks = self.handle.memory.get_all_blocks();
2022+
let memory_blocks = self.handle.memory.get_all_non_recall();
20232023
let system_prompt_tokens = self.estimate_system_prompt_tokens(&memory_blocks);
20242024

20252025
let mut compressor = MessageCompressor::new(history.compression_strategy.clone())

crates/pattern_core/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//! and tool execution system that powers Pattern's multi-agent
55
//! cognitive support system.
66
7-
#![recursion_limit = "256"]
7+
//#![recursion_limit = "256"]
88

99
pub mod agent;
1010
pub mod atproto_identity;

crates/pattern_core/src/memory.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,19 @@ impl Memory {
328328
self.blocks.iter().map(|e| e.value().clone()).collect()
329329
}
330330

331+
pub fn get_all_non_recall(&self) -> Vec<MemoryBlock> {
332+
self.blocks
333+
.iter()
334+
.filter_map(|e| {
335+
if e.value().memory_type != MemoryType::Archival {
336+
Some(e.value().clone())
337+
} else {
338+
None
339+
}
340+
})
341+
.collect()
342+
}
343+
331344
/// List all block labels
332345
pub fn list_blocks(&self) -> Vec<CompactString> {
333346
self.blocks.iter().map(|e| e.key().clone()).collect()

crates/pattern_discord/src/bot.rs

Lines changed: 29 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -689,56 +689,30 @@ impl EventHandler for DiscordEventHandler {
689689
{
690690
Ok(mut stream) => {
691691
use futures::StreamExt;
692-
let mut response_text = String::new();
693692

694693
while let Some(event) = stream.next().await {
695694
match event {
696-
pattern_core::coordination::groups::GroupResponseEvent::TextChunk { text, is_final, .. } => {
697-
if text.len() > 1 {
698-
response_text.push_str(&text);
699-
700-
// Send complete chunks as they arrive
701-
if is_final || text.ends_with('\n') || response_text.len() > 1000 {
702-
if !response_text.trim().is_empty() {
703-
// Send the response to Discord
704-
if let Err(e) = channel_id.say(&ctx_clone.http, &response_text).await {
705-
warn!("Failed to send reaction response to Discord: {}", e);
706-
}
707-
response_text.clear();
708-
}
695+
pattern_core::coordination::groups::GroupResponseEvent::TextChunk { .. } => {
696+
697+
}
698+
pattern_core::coordination::groups::GroupResponseEvent::ToolCallStarted { fn_name, .. } => {
699+
// Show tool activity for reactions too
700+
let tool_msg = match fn_name.as_str() {
701+
"context" => "💭 Processing reaction context...".to_string(),
702+
"recall" => "🔍 Searching reaction history...".to_string(),
703+
"send_message" => {continue;},
704+
_ => format!("🔧 Processing with {}...", fn_name)
705+
};
706+
if let Err(e) = channel_id.say(&ctx_clone.http, tool_msg).await {
707+
debug!("Failed to send tool activity: {}", e);
709708
}
710709
}
711-
}
712-
pattern_core::coordination::groups::GroupResponseEvent::ToolCallStarted { fn_name, .. } => {
713-
// Show tool activity for reactions too
714-
let tool_msg = match fn_name.as_str() {
715-
"context" => "💭 Processing reaction context...".to_string(),
716-
"recall" => "🔍 Searching reaction history...".to_string(),
717-
_ => format!("🔧 Processing with {}...", fn_name)
718-
};
719-
if let Err(e) = channel_id.say(&ctx_clone.http, tool_msg).await {
720-
debug!("Failed to send tool activity: {}", e);
710+
pattern_core::coordination::groups::GroupResponseEvent::Error { message, .. } => {
711+
warn!("Error processing reaction: {}", message);
721712
}
713+
_ => {}
722714
}
723-
pattern_core::coordination::groups::GroupResponseEvent::Error { message, .. } => {
724-
warn!("Error processing reaction: {}", message);
725-
}
726-
_ => {}
727715
}
728-
}
729-
730-
// Send any remaining text
731-
// if !response_text.trim().is_empty() {
732-
// if let Err(e) = channel_id
733-
// .say(&ctx_clone.http, &response_text)
734-
// .await
735-
// {
736-
// warn!(
737-
// "Failed to send final reaction response: {}",
738-
// e
739-
// );
740-
// }
741-
// }
742716
}
743717
Err(e) => {
744718
warn!(
@@ -1059,44 +1033,28 @@ impl DiscordBot {
10591033
} else {
10601034
stream
10611035
};
1062-
let mut response = String::new();
10631036
let mut has_response = false;
10641037

1038+
let ctx_clone = ctx.clone();
10651039
while let Some(event) = stream.next().await {
1040+
has_response = true;
10661041
match event {
1067-
pattern_core::coordination::groups::GroupResponseEvent::TextChunk { text, is_final, .. } => {
1068-
if !text.is_empty() && text.trim() != "." {
1069-
response.push_str(&text);
1070-
has_response = true;
1071-
1072-
// Send complete chunks
1073-
if is_final || text.ends_with('\n') || response.len() > 1500 {
1074-
if !response.trim().is_empty() {
1075-
for chunk in split_message(&response, 2000) {
1076-
if let Err(e) = ChannelId::new(channel_id).say(&ctx.http, chunk).await {
1077-
warn!("Failed to send batch response: {}", e);
1078-
}
1079-
}
1080-
response.clear();
1081-
}
1082-
}
1083-
}
1042+
pattern_core::coordination::groups::GroupResponseEvent::ToolCallStarted { fn_name, .. } => {
1043+
// // Show tool activity for reactions too
1044+
// let tool_msg = match fn_name.as_str() {
1045+
// "context" => "💭 Processing reaction context...".to_string(),
1046+
// "recall" => "🔍 Searching reaction history...".to_string(),
1047+
// "send_message" => {continue;},
1048+
// _ => format!("🔧 Processing with {}...", fn_name)
1049+
// };
1050+
// if let Err(e) = channel_id.say(&ctx_clone.http, tool_msg).await {
1051+
// debug!("Failed to send tool activity: {}", e);
1052+
// }
10841053
}
10851054
_ => {} // Ignore other events for batch processing
10861055
}
10871056
}
10881057

1089-
// Send any remaining response
1090-
if !response.trim().is_empty() {
1091-
for chunk in split_message(&response, 2000) {
1092-
if let Err(e) =
1093-
ChannelId::new(channel_id).say(&ctx.http, chunk).await
1094-
{
1095-
warn!("Failed to send final batch response: {}", e);
1096-
}
1097-
}
1098-
}
1099-
11001058
if !has_response {
11011059
// No response to batch, send indicator
11021060
let _ = ChannelId::new(channel_id).say(&ctx.http, "💭 ...").await;

0 commit comments

Comments
 (0)