claude-mpm 4.0.31__py3-none-any.whl → 4.0.32__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +33 -25
- claude_mpm/agents/INSTRUCTIONS.md +14 -10
- claude_mpm/core/framework_loader.py +99 -29
- claude_mpm/services/agents/deployment/agent_deployment.py +65 -2
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +72 -0
- claude_mpm/services/agents/memory/agent_memory_manager.py +141 -184
- claude_mpm/services/agents/memory/content_manager.py +83 -126
- claude_mpm/services/agents/memory/template_generator.py +4 -40
- {claude_mpm-4.0.31.dist-info → claude_mpm-4.0.32.dist-info}/METADATA +1 -1
- {claude_mpm-4.0.31.dist-info → claude_mpm-4.0.32.dist-info}/RECORD +14 -14
- {claude_mpm-4.0.31.dist-info → claude_mpm-4.0.32.dist-info}/WHEEL +0 -0
- {claude_mpm-4.0.31.dist-info → claude_mpm-4.0.32.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.0.31.dist-info → claude_mpm-4.0.32.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.0.31.dist-info → claude_mpm-4.0.32.dist-info}/top_level.txt +0 -0
|
@@ -51,18 +51,10 @@ class AgentMemoryManager(MemoryServiceInterface):
|
|
|
51
51
|
# Updated to support 20k tokens (~80KB) for enhanced memory capacity
|
|
52
52
|
DEFAULT_MEMORY_LIMITS = {
|
|
53
53
|
"max_file_size_kb": 80, # Increased from 8KB to 80KB (20k tokens)
|
|
54
|
-
"
|
|
55
|
-
"max_items_per_section": 15,
|
|
54
|
+
"max_items": 100, # Maximum total memory items
|
|
56
55
|
"max_line_length": 120,
|
|
57
56
|
}
|
|
58
57
|
|
|
59
|
-
REQUIRED_SECTIONS = [
|
|
60
|
-
"Project Architecture",
|
|
61
|
-
"Implementation Guidelines",
|
|
62
|
-
"Common Mistakes to Avoid",
|
|
63
|
-
"Current Technical Context",
|
|
64
|
-
]
|
|
65
|
-
|
|
66
58
|
def __init__(
|
|
67
59
|
self, config: Optional[Config] = None, working_directory: Optional[Path] = None
|
|
68
60
|
):
|
|
@@ -138,12 +130,8 @@ class AgentMemoryManager(MemoryServiceInterface):
|
|
|
138
130
|
"max_file_size_kb": config_limits.get(
|
|
139
131
|
"default_size_kb", self.DEFAULT_MEMORY_LIMITS["max_file_size_kb"]
|
|
140
132
|
),
|
|
141
|
-
"
|
|
142
|
-
"
|
|
143
|
-
),
|
|
144
|
-
"max_items_per_section": config_limits.get(
|
|
145
|
-
"max_items_per_section",
|
|
146
|
-
self.DEFAULT_MEMORY_LIMITS["max_items_per_section"],
|
|
133
|
+
"max_items": config_limits.get(
|
|
134
|
+
"max_items", self.DEFAULT_MEMORY_LIMITS["max_items"]
|
|
147
135
|
),
|
|
148
136
|
"max_line_length": config_limits.get(
|
|
149
137
|
"max_line_length", self.DEFAULT_MEMORY_LIMITS["max_line_length"]
|
|
@@ -272,75 +260,41 @@ class AgentMemoryManager(MemoryServiceInterface):
|
|
|
272
260
|
self.logger.info(f"Creating default memory for agent: {agent_id}")
|
|
273
261
|
return self._create_default_memory(agent_id)
|
|
274
262
|
|
|
275
|
-
def update_agent_memory(self, agent_id: str,
|
|
276
|
-
"""Add new learning
|
|
263
|
+
def update_agent_memory(self, agent_id: str, new_items: List[str]) -> bool:
|
|
264
|
+
"""Add new learning items to agent memory as a simple list.
|
|
277
265
|
|
|
278
|
-
WHY:
|
|
279
|
-
|
|
280
|
-
enforcing size limits to prevent unbounded growth.
|
|
266
|
+
WHY: Simplified memory system - all memories are stored as a simple list
|
|
267
|
+
without categorization, making it easier to manage and understand.
|
|
281
268
|
|
|
282
269
|
Args:
|
|
283
270
|
agent_id: The agent identifier
|
|
284
|
-
|
|
285
|
-
new_item: The learning item to add
|
|
271
|
+
new_items: List of new learning items to add
|
|
286
272
|
|
|
287
273
|
Returns:
|
|
288
274
|
bool: True if update succeeded, False otherwise
|
|
289
275
|
"""
|
|
290
276
|
try:
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
current_memory, section, new_item
|
|
294
|
-
)
|
|
295
|
-
|
|
296
|
-
# Enforce limits
|
|
297
|
-
agent_limits = self._get_agent_limits(agent_id)
|
|
298
|
-
if self.content_manager.exceeds_limits(updated_memory, agent_limits):
|
|
299
|
-
self.logger.debug(f"Memory for {agent_id} exceeds limits, truncating")
|
|
300
|
-
updated_memory = self.content_manager.truncate_to_limits(
|
|
301
|
-
updated_memory, agent_limits
|
|
302
|
-
)
|
|
303
|
-
|
|
304
|
-
# Save with timestamp
|
|
305
|
-
return self._save_memory_file(agent_id, updated_memory)
|
|
277
|
+
# Use the simplified _add_learnings_to_memory method
|
|
278
|
+
return self._add_learnings_to_memory(agent_id, new_items)
|
|
306
279
|
except Exception as e:
|
|
307
280
|
self.logger.error(f"Error updating memory for {agent_id}: {e}")
|
|
308
281
|
# Never fail on memory errors
|
|
309
282
|
return False
|
|
310
283
|
|
|
311
|
-
def add_learning(self, agent_id: str,
|
|
312
|
-
"""Add
|
|
284
|
+
def add_learning(self, agent_id: str, content: str) -> bool:
|
|
285
|
+
"""Add a learning to agent memory as a simple list item.
|
|
313
286
|
|
|
314
|
-
WHY:
|
|
315
|
-
|
|
316
|
-
sections automatically.
|
|
287
|
+
WHY: Simplified interface for adding single learnings without categorization.
|
|
288
|
+
This method wraps the batch update for convenience.
|
|
317
289
|
|
|
318
290
|
Args:
|
|
319
291
|
agent_id: The agent identifier
|
|
320
|
-
learning_type: Type of learning (pattern, architecture, guideline, etc.)
|
|
321
292
|
content: The learning content
|
|
322
293
|
|
|
323
294
|
Returns:
|
|
324
295
|
bool: True if learning was added successfully
|
|
325
296
|
"""
|
|
326
|
-
|
|
327
|
-
"pattern": "Coding Patterns Learned",
|
|
328
|
-
"architecture": "Project Architecture",
|
|
329
|
-
"guideline": "Implementation Guidelines",
|
|
330
|
-
"mistake": "Common Mistakes to Avoid",
|
|
331
|
-
"strategy": "Effective Strategies",
|
|
332
|
-
"integration": "Integration Points",
|
|
333
|
-
"performance": "Performance Considerations",
|
|
334
|
-
"domain": "Domain-Specific Knowledge",
|
|
335
|
-
"context": "Current Technical Context",
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
section = section_mapping.get(learning_type, "Recent Learnings")
|
|
339
|
-
success = self.update_agent_memory(agent_id, section, content)
|
|
340
|
-
|
|
341
|
-
# Socket.IO notifications removed - memory manager works independently
|
|
342
|
-
|
|
343
|
-
return success
|
|
297
|
+
return self.update_agent_memory(agent_id, [content])
|
|
344
298
|
|
|
345
299
|
def _create_default_memory(self, agent_id: str) -> str:
|
|
346
300
|
"""Create project-specific default memory file for agent.
|
|
@@ -492,8 +446,8 @@ class AgentMemoryManager(MemoryServiceInterface):
|
|
|
492
446
|
"""Extract memory updates from agent response and update memory file.
|
|
493
447
|
|
|
494
448
|
WHY: Agents provide memory updates in their responses that need to be
|
|
495
|
-
extracted and persisted. This method looks for "remember" field
|
|
496
|
-
|
|
449
|
+
extracted and persisted. This method looks for "remember" field for incremental
|
|
450
|
+
updates or "MEMORIES" field for complete replacement.
|
|
497
451
|
|
|
498
452
|
Args:
|
|
499
453
|
agent_id: The agent identifier
|
|
@@ -517,14 +471,38 @@ class AgentMemoryManager(MemoryServiceInterface):
|
|
|
517
471
|
|
|
518
472
|
if not json_matches:
|
|
519
473
|
# Also try to find inline JSON objects
|
|
520
|
-
json_pattern2 = r'\{[^{}]*"(?:remember|Remember)"[^{}]*\}'
|
|
474
|
+
json_pattern2 = r'\{[^{}]*"(?:remember|Remember|MEMORIES)"[^{}]*\}'
|
|
521
475
|
json_matches = re.findall(json_pattern2, response, re.DOTALL)
|
|
522
476
|
|
|
523
477
|
for json_str in json_matches:
|
|
524
478
|
try:
|
|
525
479
|
data = json.loads(json_str)
|
|
526
480
|
|
|
527
|
-
# Check for memory
|
|
481
|
+
# Check for complete memory replacement in "MEMORIES" field
|
|
482
|
+
if "MEMORIES" in data and data["MEMORIES"] is not None:
|
|
483
|
+
memories = data["MEMORIES"]
|
|
484
|
+
if isinstance(memories, list) and len(memories) > 0:
|
|
485
|
+
# Filter out empty strings and None values
|
|
486
|
+
valid_items = []
|
|
487
|
+
for item in memories:
|
|
488
|
+
if item and isinstance(item, str) and item.strip():
|
|
489
|
+
# Ensure item has bullet point for consistency
|
|
490
|
+
item_text = item.strip()
|
|
491
|
+
if not item_text.startswith("-"):
|
|
492
|
+
item_text = f"- {item_text}"
|
|
493
|
+
valid_items.append(item_text)
|
|
494
|
+
|
|
495
|
+
if valid_items:
|
|
496
|
+
self.logger.info(f"Replacing all memories for {agent_id} with {len(valid_items)} items")
|
|
497
|
+
success = self.replace_agent_memory(agent_id, valid_items)
|
|
498
|
+
if success:
|
|
499
|
+
self.logger.info(f"Successfully replaced memories for {agent_id}")
|
|
500
|
+
return True
|
|
501
|
+
else:
|
|
502
|
+
self.logger.error(f"Failed to replace memories for {agent_id}")
|
|
503
|
+
continue # Skip checking remember field if MEMORIES was processed
|
|
504
|
+
|
|
505
|
+
# Check for incremental memory updates in "remember" field
|
|
528
506
|
memory_items = None
|
|
529
507
|
|
|
530
508
|
# Check both "remember" and "Remember" fields
|
|
@@ -566,11 +544,11 @@ class AgentMemoryManager(MemoryServiceInterface):
|
|
|
566
544
|
return False
|
|
567
545
|
|
|
568
546
|
def _add_learnings_to_memory(self, agent_id: str, learnings: List[str]) -> bool:
|
|
569
|
-
"""Add new learnings to
|
|
547
|
+
"""Add new learnings to agent memory as a simple list.
|
|
570
548
|
|
|
571
|
-
WHY:
|
|
572
|
-
|
|
573
|
-
|
|
549
|
+
WHY: Simplified memory system - all memories are stored as a simple list
|
|
550
|
+
without categorization, making it easier to manage and understand.
|
|
551
|
+
Updates timestamp on every update.
|
|
574
552
|
|
|
575
553
|
Args:
|
|
576
554
|
agent_id: The agent identifier
|
|
@@ -583,13 +561,14 @@ class AgentMemoryManager(MemoryServiceInterface):
|
|
|
583
561
|
# Load existing memory
|
|
584
562
|
current_memory = self.load_agent_memory(agent_id)
|
|
585
563
|
|
|
586
|
-
# Parse existing memory into
|
|
587
|
-
|
|
564
|
+
# Parse existing memory into a simple list
|
|
565
|
+
existing_items = self._parse_memory_list(current_memory)
|
|
588
566
|
|
|
589
|
-
# Clean
|
|
590
|
-
|
|
567
|
+
# Clean template placeholders if this is a fresh memory
|
|
568
|
+
existing_items = self._clean_template_placeholders_list(existing_items)
|
|
591
569
|
|
|
592
|
-
#
|
|
570
|
+
# Add new learnings, avoiding duplicates
|
|
571
|
+
updated = False
|
|
593
572
|
for learning in learnings:
|
|
594
573
|
if not learning or not isinstance(learning, str):
|
|
595
574
|
continue
|
|
@@ -598,35 +577,34 @@ class AgentMemoryManager(MemoryServiceInterface):
|
|
|
598
577
|
if not learning:
|
|
599
578
|
continue
|
|
600
579
|
|
|
601
|
-
#
|
|
602
|
-
section = self._categorize_learning(learning)
|
|
603
|
-
|
|
604
|
-
# Add to appropriate section if not duplicate
|
|
605
|
-
if section not in sections:
|
|
606
|
-
sections[section] = []
|
|
607
|
-
|
|
608
|
-
# Check for duplicates (case-insensitive) - FIXED LOGIC
|
|
580
|
+
# Check for duplicates (case-insensitive)
|
|
609
581
|
normalized_learning = learning.lower()
|
|
610
582
|
# Strip bullet points from existing items for comparison
|
|
611
|
-
existing_normalized = [item.lstrip('- ').strip().lower() for item in
|
|
583
|
+
existing_normalized = [item.lstrip('- ').strip().lower() for item in existing_items]
|
|
612
584
|
|
|
613
585
|
if normalized_learning not in existing_normalized:
|
|
614
586
|
# Add bullet point if not present
|
|
615
587
|
if not learning.startswith("-"):
|
|
616
588
|
learning = f"- {learning}"
|
|
617
|
-
|
|
589
|
+
existing_items.append(learning)
|
|
618
590
|
self.logger.info(f"Added new memory for {agent_id}: {learning[:50]}...")
|
|
591
|
+
updated = True
|
|
619
592
|
else:
|
|
620
593
|
self.logger.debug(f"Skipping duplicate memory for {agent_id}: {learning}")
|
|
621
594
|
|
|
622
|
-
#
|
|
623
|
-
|
|
595
|
+
# Only save if we actually added new items
|
|
596
|
+
if not updated:
|
|
597
|
+
self.logger.debug(f"No new memories to add for {agent_id}")
|
|
598
|
+
return True # Not an error, just nothing new to add
|
|
599
|
+
|
|
600
|
+
# Rebuild memory content as simple list with updated timestamp
|
|
601
|
+
new_content = self._build_simple_memory_content(agent_id, existing_items)
|
|
624
602
|
|
|
625
603
|
# Validate and save
|
|
626
604
|
agent_limits = self._get_agent_limits(agent_id)
|
|
627
605
|
if self.content_manager.exceeds_limits(new_content, agent_limits):
|
|
628
606
|
self.logger.debug(f"Memory for {agent_id} exceeds limits, truncating")
|
|
629
|
-
new_content = self.content_manager.
|
|
607
|
+
new_content = self.content_manager.truncate_simple_list(new_content, agent_limits)
|
|
630
608
|
|
|
631
609
|
# All memories go to project directory
|
|
632
610
|
return self._save_memory_file(agent_id, new_content)
|
|
@@ -635,6 +613,59 @@ class AgentMemoryManager(MemoryServiceInterface):
|
|
|
635
613
|
self.logger.error(f"Error adding learnings to memory for {agent_id}: {e}")
|
|
636
614
|
return False
|
|
637
615
|
|
|
616
|
+
def _parse_memory_list(self, memory_content: str) -> List[str]:
|
|
617
|
+
"""Parse memory content into a simple list.
|
|
618
|
+
|
|
619
|
+
Args:
|
|
620
|
+
memory_content: Raw memory file content
|
|
621
|
+
|
|
622
|
+
Returns:
|
|
623
|
+
List of memory items
|
|
624
|
+
"""
|
|
625
|
+
items = []
|
|
626
|
+
|
|
627
|
+
for line in memory_content.split('\n'):
|
|
628
|
+
line = line.strip()
|
|
629
|
+
# Skip metadata lines and headers
|
|
630
|
+
if line.startswith('<!-- ') or line.startswith('#') or not line:
|
|
631
|
+
continue
|
|
632
|
+
# Collect items (with or without bullet points)
|
|
633
|
+
if line.startswith('- '):
|
|
634
|
+
items.append(line)
|
|
635
|
+
elif line and not line.startswith('##'): # Legacy format without bullets
|
|
636
|
+
items.append(f"- {line}")
|
|
637
|
+
|
|
638
|
+
return items
|
|
639
|
+
|
|
640
|
+
def _clean_template_placeholders_list(self, items: List[str]) -> List[str]:
|
|
641
|
+
"""Remove template placeholder text from item list.
|
|
642
|
+
|
|
643
|
+
Args:
|
|
644
|
+
items: List of memory items
|
|
645
|
+
|
|
646
|
+
Returns:
|
|
647
|
+
List with placeholder text removed
|
|
648
|
+
"""
|
|
649
|
+
# Template placeholder patterns to remove
|
|
650
|
+
placeholders = [
|
|
651
|
+
"Analyze project structure to understand architecture patterns",
|
|
652
|
+
"Observe codebase patterns and conventions during tasks",
|
|
653
|
+
"Extract implementation guidelines from project documentation",
|
|
654
|
+
"Learn from errors encountered during project work",
|
|
655
|
+
"Project analysis pending - gather context during tasks",
|
|
656
|
+
"claude-mpm: Software project requiring analysis"
|
|
657
|
+
]
|
|
658
|
+
|
|
659
|
+
cleaned = []
|
|
660
|
+
for item in items:
|
|
661
|
+
# Remove bullet point for comparison
|
|
662
|
+
item_text = item.lstrip("- ").strip()
|
|
663
|
+
# Keep item if it's not a placeholder
|
|
664
|
+
if item_text and item_text not in placeholders:
|
|
665
|
+
cleaned.append(item)
|
|
666
|
+
|
|
667
|
+
return cleaned
|
|
668
|
+
|
|
638
669
|
def _clean_template_placeholders(self, sections: Dict[str, List[str]]) -> Dict[str, List[str]]:
|
|
639
670
|
"""Remove template placeholder text from sections.
|
|
640
671
|
|
|
@@ -723,12 +754,12 @@ class AgentMemoryManager(MemoryServiceInterface):
|
|
|
723
754
|
else:
|
|
724
755
|
return "Recent Learnings"
|
|
725
756
|
|
|
726
|
-
def
|
|
727
|
-
"""Build memory content
|
|
757
|
+
def _build_simple_memory_content(self, agent_id: str, items: List[str]) -> str:
|
|
758
|
+
"""Build memory content as a simple list with updated timestamp.
|
|
728
759
|
|
|
729
760
|
Args:
|
|
730
761
|
agent_id: The agent identifier
|
|
731
|
-
|
|
762
|
+
items: List of memory items
|
|
732
763
|
|
|
733
764
|
Returns:
|
|
734
765
|
str: The formatted memory content
|
|
@@ -736,119 +767,45 @@ class AgentMemoryManager(MemoryServiceInterface):
|
|
|
736
767
|
lines = []
|
|
737
768
|
|
|
738
769
|
# Add header
|
|
739
|
-
lines.append(f"# {agent_id
|
|
770
|
+
lines.append(f"# Agent Memory: {agent_id}")
|
|
771
|
+
# Always update timestamp when building new content
|
|
772
|
+
lines.append(f"<!-- Last Updated: {datetime.now().isoformat()}Z -->")
|
|
740
773
|
lines.append("")
|
|
741
|
-
lines.append(f"<!-- Last Updated: {datetime.now().isoformat()} -->")
|
|
742
|
-
lines.append("")
|
|
743
|
-
|
|
744
|
-
# Add sections in consistent order
|
|
745
|
-
section_order = [
|
|
746
|
-
"Project Architecture",
|
|
747
|
-
"Implementation Guidelines",
|
|
748
|
-
"Common Mistakes to Avoid",
|
|
749
|
-
"Current Technical Context",
|
|
750
|
-
"Coding Patterns Learned",
|
|
751
|
-
"Effective Strategies",
|
|
752
|
-
"Integration Points",
|
|
753
|
-
"Performance Considerations",
|
|
754
|
-
"Domain-Specific Knowledge",
|
|
755
|
-
"Recent Learnings"
|
|
756
|
-
]
|
|
757
|
-
|
|
758
|
-
for section_name in section_order:
|
|
759
|
-
if section_name in sections and sections[section_name]:
|
|
760
|
-
lines.append(f"## {section_name}")
|
|
761
|
-
lines.append("")
|
|
762
|
-
for item in sections[section_name]:
|
|
763
|
-
if item.strip():
|
|
764
|
-
lines.append(item)
|
|
765
|
-
lines.append("")
|
|
766
774
|
|
|
767
|
-
# Add
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
lines.append(item)
|
|
776
|
-
lines.append("")
|
|
775
|
+
# Add all items as a simple list
|
|
776
|
+
for item in items:
|
|
777
|
+
if item.strip():
|
|
778
|
+
# Ensure item has bullet point
|
|
779
|
+
if not item.strip().startswith("-"):
|
|
780
|
+
lines.append(f"- {item.strip()}")
|
|
781
|
+
else:
|
|
782
|
+
lines.append(item.strip())
|
|
777
783
|
|
|
778
784
|
return '\n'.join(lines)
|
|
779
785
|
|
|
780
|
-
def replace_agent_memory(self, agent_id: str,
|
|
781
|
-
"""Replace agent's memory with new content
|
|
786
|
+
def replace_agent_memory(self, agent_id: str, memory_items: List[str]) -> bool:
|
|
787
|
+
"""Replace agent's memory with new content as a simple list.
|
|
782
788
|
|
|
783
|
-
WHY: When agents provide memory updates
|
|
784
|
-
rather than appending to it.
|
|
789
|
+
WHY: When agents provide complete memory updates through MEMORIES field,
|
|
790
|
+
they replace the existing memory rather than appending to it.
|
|
791
|
+
This ensures memories stay current and relevant.
|
|
785
792
|
|
|
786
793
|
Args:
|
|
787
794
|
agent_id: The agent identifier
|
|
788
|
-
|
|
795
|
+
memory_items: List of memory items to replace existing memories
|
|
789
796
|
|
|
790
797
|
Returns:
|
|
791
798
|
bool: True if memory was successfully replaced
|
|
792
799
|
"""
|
|
793
800
|
try:
|
|
794
|
-
# Build new memory content
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
# Add header
|
|
798
|
-
lines.append(f"# {agent_id.capitalize()} Agent Memory")
|
|
799
|
-
lines.append("")
|
|
800
|
-
lines.append(f"<!-- Last Updated: {datetime.now().isoformat()} -->")
|
|
801
|
-
lines.append("")
|
|
802
|
-
|
|
803
|
-
# Add sections in a consistent order
|
|
804
|
-
section_order = [
|
|
805
|
-
"Project Architecture",
|
|
806
|
-
"Implementation Guidelines",
|
|
807
|
-
"Common Mistakes to Avoid",
|
|
808
|
-
"Current Technical Context",
|
|
809
|
-
"Coding Patterns Learned",
|
|
810
|
-
"Effective Strategies",
|
|
811
|
-
"Integration Points",
|
|
812
|
-
"Performance Considerations",
|
|
813
|
-
"Domain-Specific Knowledge",
|
|
814
|
-
"Recent Learnings"
|
|
815
|
-
]
|
|
816
|
-
|
|
817
|
-
# First add ordered sections that exist in memory_sections
|
|
818
|
-
for section_name in section_order:
|
|
819
|
-
if section_name in memory_sections and memory_sections[section_name]:
|
|
820
|
-
lines.append(f"## {section_name}")
|
|
821
|
-
lines.append("")
|
|
822
|
-
for item in memory_sections[section_name]:
|
|
823
|
-
if item.strip(): # Skip empty items
|
|
824
|
-
# Add bullet point if not already present
|
|
825
|
-
if not item.strip().startswith("-"):
|
|
826
|
-
lines.append(f"- {item.strip()}")
|
|
827
|
-
else:
|
|
828
|
-
lines.append(item.strip())
|
|
829
|
-
lines.append("")
|
|
830
|
-
|
|
831
|
-
# Then add any remaining sections not in the order list
|
|
832
|
-
remaining_sections = set(memory_sections.keys()) - set(section_order)
|
|
833
|
-
for section_name in sorted(remaining_sections):
|
|
834
|
-
if memory_sections[section_name]:
|
|
835
|
-
lines.append(f"## {section_name}")
|
|
836
|
-
lines.append("")
|
|
837
|
-
for item in memory_sections[section_name]:
|
|
838
|
-
if item.strip():
|
|
839
|
-
if not item.strip().startswith("-"):
|
|
840
|
-
lines.append(f"- {item.strip()}")
|
|
841
|
-
else:
|
|
842
|
-
lines.append(item.strip())
|
|
843
|
-
lines.append("")
|
|
844
|
-
|
|
845
|
-
new_content = '\n'.join(lines)
|
|
801
|
+
# Build new memory content as simple list with updated timestamp
|
|
802
|
+
new_content = self._build_simple_memory_content(agent_id, memory_items)
|
|
846
803
|
|
|
847
804
|
# Validate and save
|
|
848
805
|
agent_limits = self._get_agent_limits(agent_id)
|
|
849
806
|
if self.content_manager.exceeds_limits(new_content, agent_limits):
|
|
850
807
|
self.logger.debug(f"Memory for {agent_id} exceeds limits, truncating")
|
|
851
|
-
new_content = self.content_manager.
|
|
808
|
+
new_content = self.content_manager.truncate_simple_list(new_content, agent_limits)
|
|
852
809
|
|
|
853
810
|
# Save the new memory
|
|
854
811
|
return self._save_memory_file(agent_id, new_content)
|