diff --git a/.cursorignore b/.cursorignore index 594fe09..2d3c03d 100644 --- a/.cursorignore +++ b/.cursorignore @@ -1 +1,2 @@ -venv/ \ No newline at end of file +venv/ +explorer/node_modules/ diff --git a/README.md b/README.md index a1e5dcf..0a2ccfc 100644 --- a/README.md +++ b/README.md @@ -195,7 +195,7 @@ This allows you to develop and test your agent memory system without setting up Explore the comprehensive documentation to understand the system components and APIs: - [Memory API](docs/memory_api.md) - Complete API reference for working with the TASM system -- [Agent Memory](docs/agent_memory.md) - Core MemoryAgent implementation and usage +- [Agent Memory](docs/agent_memory.md) - Core MemorySpace implementation and usage - [Memory System](docs/memory_system.md) - Overview of the tiered memory architecture - [Memory Configuration](docs/memory_config.md) - Configuration options for all components - [Memory Tiers](docs/memory_tiers.md) - Details on the three memory tiers and their characteristics diff --git a/archive/01_basic_memory_operations.py b/archive/01_basic_memory_operations.py index 362301b..63fad30 100644 --- a/archive/01_basic_memory_operations.py +++ b/archive/01_basic_memory_operations.py @@ -143,13 +143,13 @@ def validate_memory_statistics(logger, stats, agent_id, memory_system): all_validations_passed = False # 3. Validate memory type distribution - memory_agent = memory_system.get_memory_agent(agent_id) + memory_space = memory_system.get_memory_space(agent_id) # Collect all memories across tiers all_memories = [] - all_memories.extend(memory_agent.stm_store.get_all(agent_id)) - all_memories.extend(memory_agent.im_store.get_all(agent_id)) - all_memories.extend(memory_agent.ltm_store.get_all(agent_id)) + all_memories.extend(memory_space.stm_store.get_all(agent_id)) + all_memories.extend(memory_space.im_store.get_all(agent_id)) + all_memories.extend(memory_space.ltm_store.get_all(agent_id)) # Count by memory type memory_types = {"state": 0, "action": 0, "interaction": 0} @@ -221,8 +221,8 @@ def validate_memory_statistics(logger, stats, agent_id, memory_system): # If still missing, check by step_number if step in missing_steps: - memory_agent = memory_system.get_memory_agent(agent_id) - for source in [memory_agent.stm_store, memory_agent.im_store]: + memory_space = memory_system.get_memory_space(agent_id) + for source in [memory_space.stm_store, memory_space.im_store]: memories = source.get_all(agent_id) for memory in memories: step_number = memory.get("step_number") @@ -234,7 +234,7 @@ def validate_memory_statistics(logger, stats, agent_id, memory_system): # Also check LTM if still missing if step in missing_steps: - memories = memory_agent.ltm_store.get_all(agent_id) + memories = memory_space.ltm_store.get_all(agent_id) for memory in memories: step_number = memory.get("step_number") if step_number == step: @@ -378,11 +378,11 @@ def run_demo(): # Display example content from each memory tier log_print(logger, "\n== EXAMPLE MEMORY CONTENT FROM EACH TIER ==") - memory_agent = memory_system.get_memory_agent(agent_id) + memory_space = memory_system.get_memory_space(agent_id) # STM example content log_print(logger, "\n----- SHORT-TERM MEMORY (STM) EXAMPLES -----") - stm_memories = memory_agent.stm_store.get_all(agent_id) + stm_memories = memory_space.stm_store.get_all(agent_id) if stm_memories: for i, memory in enumerate(stm_memories[:3]): # Show up to 3 examples @@ -411,7 +411,7 @@ def run_demo(): # IM example content log_print(logger, "\n----- INTERMEDIATE MEMORY (IM) EXAMPLES -----") - im_memories = memory_agent.im_store.get_all(agent_id) + im_memories = memory_space.im_store.get_all(agent_id) if im_memories: for i, memory in enumerate(im_memories[:3]): # Show up to 3 examples @@ -432,7 +432,7 @@ def run_demo(): # LTM example content log_print(logger, "\n----- LONG-TERM MEMORY (LTM) EXAMPLES -----") - ltm_memories = memory_agent.ltm_store.get_all(agent_id) + ltm_memories = memory_space.ltm_store.get_all(agent_id) if ltm_memories: for i, memory in enumerate(ltm_memories[:3]): # Show up to 3 examples @@ -483,7 +483,7 @@ def run_demo(): # 3. Check high-priority memories in different tiers # We expect most high-priority memories to be preserved in higher tiers (IM/LTM) high_priority_steps = [5, 10, 15, 20, 21, 25, 30] - memory_agent = memory_system.get_memory_agent(agent_id) + memory_space = memory_system.get_memory_space(agent_id) # Query for high-priority memories across all tiers milestone_memories = [] @@ -497,9 +497,9 @@ def run_demo(): # First try to find directly by step_number across all tiers found_by_step = False for store_memories in [ - memory_agent.stm_store.get_all(agent_id), - memory_agent.im_store.get_all(agent_id), - memory_agent.ltm_store.get_all(agent_id), + memory_space.stm_store.get_all(agent_id), + memory_space.im_store.get_all(agent_id), + memory_space.ltm_store.get_all(agent_id), ]: for memory in store_memories: mem_step = memory.get("step_number") @@ -567,9 +567,9 @@ def run_demo(): # For each missing step, try to verify if any memory actually exists for missing_step in list(missing_steps): # Directly check if we can find any memories with this timestamp across all three tiers - stm_memories = memory_agent.stm_store.get_all(agent_id) - im_memories = memory_agent.im_store.get_all(agent_id) - ltm_memories = memory_agent.ltm_store.get_all(agent_id) + stm_memories = memory_space.stm_store.get_all(agent_id) + im_memories = memory_space.im_store.get_all(agent_id) + ltm_memories = memory_space.ltm_store.get_all(agent_id) log_print( logger, f"Searching for step {missing_step} manually in all stores..." ) diff --git a/archive/02_memory_retrieval.py b/archive/02_memory_retrieval.py index 9bf2a47..a8d4be7 100644 --- a/archive/02_memory_retrieval.py +++ b/archive/02_memory_retrieval.py @@ -68,13 +68,13 @@ def validate_memory_statistics(logger, stats, agent_id, memory_system): all_validations_passed = False # 2. Validate memory type distribution - memory_agent = memory_system.get_memory_agent(agent_id) + memory_space = memory_system.get_memory_space(agent_id) # Collect all memories across tiers all_memories = [] - all_memories.extend(memory_agent.stm_store.get_all(agent_id)) - all_memories.extend(memory_agent.im_store.get_all(agent_id)) - all_memories.extend(memory_agent.ltm_store.get_all(agent_id)) + all_memories.extend(memory_space.stm_store.get_all(agent_id)) + all_memories.extend(memory_space.im_store.get_all(agent_id)) + all_memories.extend(memory_space.ltm_store.get_all(agent_id)) # Count by memory type memory_types = {"state": 0, "action": 0, "interaction": 0} diff --git a/archive/04_memory_hooks_integration.py b/archive/04_memory_hooks_integration.py index 88e0a7c..da02127 100644 --- a/archive/04_memory_hooks_integration.py +++ b/archive/04_memory_hooks_integration.py @@ -55,7 +55,7 @@ def significant_event_hook( Returns: True if processing was successful """ - # Handle when agent_id is a MemoryAgent object + # Handle when agent_id is a MemorySpace object agent_id_str = getattr(agent_id, "agent_id", agent_id) print(f"Significant event hook triggered for agent {agent_id_str}") print(f" Event type: {event_data.get('type', 'unknown')}") @@ -104,7 +104,7 @@ def state_change_hook( Returns: True if processing was successful """ - # Handle when agent_id is a MemoryAgent object + # Handle when agent_id is a MemorySpace object agent_id_str = getattr(agent_id, "agent_id", agent_id) print(f"State change hook triggered for agent {agent_id_str}") @@ -194,7 +194,7 @@ def interaction_hook( Returns: True if processing was successful """ - # Handle when agent_id is a MemoryAgent object + # Handle when agent_id is a MemorySpace object agent_id_str = getattr(agent_id, "agent_id", agent_id) print(f"Interaction hook triggered for agent {agent_id_str}") diff --git a/archive/06_search_capabilities.py b/archive/06_search_capabilities.py index 884f14b..493b7a0 100644 --- a/archive/06_search_capabilities.py +++ b/archive/06_search_capabilities.py @@ -63,8 +63,8 @@ def run_demo(): # Clear existing LTM store to prevent duplicate memories log_print(logger, "Clearing existing memories to avoid duplicates...") - memory_agent = memory_system.get_memory_agent(agent_id) - memory_agent.ltm_store.clear() + memory_space = memory_system.get_memory_space(agent_id) + memory_space.ltm_store.clear() # Initialize validation tracking validation_results = { @@ -297,7 +297,7 @@ def validate_results(actual_results, expected_content_snippets, test_name): # Explicitly add older memories directly to LTM for demonstration purposes log_print(logger, "Adding demonstration memories directly to LTM...") - memory_agent = memory_system.get_memory_agent(agent_id) + memory_space = memory_system.get_memory_space(agent_id) # Create older memories specifically for LTM ltm_memories = [ @@ -389,7 +389,7 @@ def validate_results(actual_results, expected_content_snippets, test_name): logger, f"Adding memory directly to LTM: {memory['content']['content'][:50]}...", ) - memory_agent.ltm_store.store(memory) + memory_space.ltm_store.store(memory) # Generate and store embedding for the memory try: @@ -401,7 +401,7 @@ def validate_results(actual_results, expected_content_snippets, test_name): logger, f"Generating embedding for memory: {text_content[:50]}...", ) - memory_agent.ltm_store.generate_and_store_embedding( + memory_space.ltm_store.generate_and_store_embedding( memory_id=memory.get("memory_id"), text=text_content, agent_id=agent_id, @@ -412,7 +412,7 @@ def validate_results(actual_results, expected_content_snippets, test_name): # Initialize the search model with the memory system's configuration log_print(logger, "\nInitializing search model...") - memory_agent = memory_system.get_memory_agent(agent_id) + memory_space = memory_system.get_memory_space(agent_id) # Initialize search model search_model = SearchModel(memory_system.config) @@ -424,13 +424,13 @@ def validate_results(actual_results, expected_content_snippets, test_name): # Temporal search strategy temporal_strategy = TemporalSearchStrategy( - memory_agent.stm_store, memory_agent.im_store, memory_agent.ltm_store + memory_space.stm_store, memory_space.im_store, memory_space.ltm_store ) search_model.register_strategy(temporal_strategy, make_default=True) # Attribute search strategy attribute_strategy = AttributeSearchStrategy( - memory_agent.stm_store, memory_agent.im_store, memory_agent.ltm_store + memory_space.stm_store, memory_space.im_store, memory_space.ltm_store ) search_model.register_strategy(attribute_strategy) @@ -459,12 +459,12 @@ def validate_results(actual_results, expected_content_snippets, test_name): log_print(logger, "Searching for memories from the last 48 hours...") # Use a direct approach with get_by_timerange to avoid the datetime conversion issue - memory_agent = memory_system.get_memory_agent(agent_id) + memory_space = memory_system.get_memory_space(agent_id) # Get memories from each store - ltm_memories = memory_agent.ltm_store.get_by_timerange(two_days_ago, now, limit=10) - stm_memories = memory_agent.stm_store.get_all(agent_id) - im_memories = memory_agent.im_store.get_all(agent_id) + ltm_memories = memory_space.ltm_store.get_by_timerange(two_days_ago, now, limit=10) + stm_memories = memory_space.stm_store.get_all(agent_id) + im_memories = memory_space.im_store.get_all(agent_id) # Filter STM and IM memories by time filtered_stm = [] diff --git a/docs/agent_memory.md b/docs/agent_memory.md index 90c67eb..c8da586 100644 --- a/docs/agent_memory.md +++ b/docs/agent_memory.md @@ -1,12 +1,12 @@ -# MemoryAgent Documentation +# MemorySpace Documentation ## Overview -The `MemoryAgent` class is the core component of the agent memory system, responsible for managing an individual agent's memories across different storage tiers. It provides a unified interface for storing, retrieving, and maintaining agent memories with varying levels of detail and persistence. +The `MemorySpace` class is the core component of the agent memory system, responsible for managing an individual agent's memories across different storage tiers. It provides a unified interface for storing, retrieving, and maintaining agent memories with varying levels of detail and persistence. ```mermaid graph TD - MA[MemoryAgent] --> STM[Short-Term Memory] + MA[MemorySpace] --> STM[Short-Term Memory] MA --> IM[Intermediate Memory] MA --> LTM[Long-Term Memory] MA --> CE[Compression Engine] @@ -35,7 +35,7 @@ graph TD ## Initialization ```python -from memory.agent_memory import MemoryAgent +from memory.agent_memory import MemorySpace from memory.config import MemoryConfig # Create a memory configuration @@ -67,12 +67,12 @@ config = MemoryConfig( # Initialize the memory agent agent_id = "agent-123" -memory_agent = MemoryAgent(agent_id, config) +memory_space = MemorySpace(agent_id, config) ``` ## Memory Tiers -The MemoryAgent manages three memory tiers with different characteristics: +The MemorySpace manages three memory tiers with different characteristics: | Tier | Storage | TTL | Compression | Resolution | Access Speed | |------|---------|-----|-------------|------------|--------------| @@ -86,7 +86,7 @@ The MemoryAgent manages three memory tiers with different characteristics: ```python # Store an agent state -memory_agent.store_state( +memory_space.store_state( state_data={ "position": {"x": 10, "y": 20, "location": "forest"}, "health": 0.85, @@ -98,7 +98,7 @@ memory_agent.store_state( ) # Store an interaction with another agent -memory_agent.store_interaction( +memory_space.store_interaction( interaction_data={ "agent_id": "agent-456", "interaction_type": "conversation", @@ -110,7 +110,7 @@ memory_agent.store_interaction( ) # Store an action -memory_agent.store_action( +memory_space.store_action( action_data={ "action_type": "move", "direction": "north", @@ -130,7 +130,7 @@ query_state = { "position": {"x": 12, "y": 22, "location": "forest"}, "health": 0.8 } -similar_states = memory_agent.retrieve_similar_states( +similar_states = memory_space.retrieve_similar_states( query_state=query_state, k=5, memory_type="state", @@ -139,20 +139,20 @@ similar_states = memory_agent.retrieve_similar_states( ) # Retrieve memories by time range -historical_memories = memory_agent.retrieve_by_time_range( +historical_memories = memory_space.retrieve_by_time_range( start_step=1000, end_step=2000, memory_type="interaction" ) # Retrieve memories by attributes -matching_memories = memory_agent.retrieve_by_attributes( +matching_memories = memory_space.retrieve_by_attributes( attributes={"action_type": "move", "direction": "north"}, memory_type="action" ) # Search by content text -content_matches = memory_agent.search_by_content( +content_matches = memory_space.search_by_content( content_query="wood trade", k=5 ) @@ -164,7 +164,7 @@ The hybrid_retrieve method combines similarity-based and attribute-based search ```python # Combine vector similarity and attribute matching -hybrid_results = memory_agent.hybrid_retrieve( +hybrid_results = memory_space.hybrid_retrieve( query_state={ "position": {"location": "forest"}, "inventory": ["wood", "stone"] @@ -180,18 +180,18 @@ hybrid_results = memory_agent.hybrid_retrieve( ```python # Force memory tier transitions and cleanup -memory_agent.force_maintenance() +memory_space.force_maintenance() # Clear all memories for this agent -memory_agent.clear_memory() +memory_space.clear_memory() # Get memory statistics -stats = memory_agent.get_memory_statistics() +stats = memory_space.get_memory_statistics() ``` ## Memory Importance Calculation -The `MemoryAgent` calculates memory importance using a formula that considers: +The `MemorySpace` calculates memory importance using a formula that considers: 1. **Reward magnitude (40%)**: Higher absolute rewards increase importance 2. **Recency (20%)**: More recent memories get higher importance @@ -232,7 +232,7 @@ def _calculate_importance(self, memory): ## Memory Tier Transitions -The `MemoryAgent` automatically transitions memories between tiers based on: +The `MemorySpace` automatically transitions memories between tiers based on: 1. **Capacity limits**: When a tier exceeds its capacity limit 2. **Memory importance**: Less important memories are transitioned first @@ -245,11 +245,11 @@ The transition process is triggered: ## Event Hooks -The `MemoryAgent` provides an event hook system for customizing memory behavior: +The `MemorySpace` provides an event hook system for customizing memory behavior: ```python # Define a custom hook function -def custom_memory_hook(event_data, memory_agent): +def custom_memory_hook(event_data, memory_space): # Process the event data print(f"Event triggered: {event_data}") @@ -262,14 +262,14 @@ def custom_memory_hook(event_data, memory_agent): } # Register the hook -memory_agent.register_hook( +memory_space.register_hook( event_type="resource_depleted", hook_function=custom_memory_hook, priority=8 # Higher priority hooks execute first (1-10) ) # Trigger the event -memory_agent.trigger_event( +memory_space.trigger_event( event_type="resource_depleted", event_data={"resource": "wood", "step_number": 1240} ) @@ -280,7 +280,7 @@ memory_agent.trigger_event( The `get_memory_statistics()` method provides comprehensive information about memory usage: ```python -stats = memory_agent.get_memory_statistics() +stats = memory_space.get_memory_statistics() ``` The statistics include: @@ -303,7 +303,7 @@ As memories transition between tiers, they undergo progressive compression: ### Neural Embeddings -When configured with neural embeddings, the `MemoryAgent` generates: +When configured with neural embeddings, the `MemorySpace` generates: 1. **Full vectors** for STM (higher dimensionality) 2. **Compressed vectors** for IM (medium dimensionality) diff --git a/docs/benchmarks/integration_tests.md b/docs/benchmarks/integration_tests.md index ec29ca7..e8efd89 100644 --- a/docs/benchmarks/integration_tests.md +++ b/docs/benchmarks/integration_tests.md @@ -302,11 +302,11 @@ def benchmark_rllib_integration(env_name="CartPole-v1", training_iterations=10): standard_rewards.append(result["episode_reward_mean"]) # Setup agent with memory integration - memory_agent_config = agent_config.copy() + memory_space_config = agent_config.copy() # This would be actual integration in real implementation - # memory_agent = integrate_with_rllib(ppo.PPOTrainer, memory_system, config=memory_agent_config) - memory_agent = MockRLlibAgentWithMemory(env, memory_agent_config, memory_system) + # memory_space = integrate_with_rllib(ppo.PPOTrainer, memory_system, config=memory_space_config) + memory_space = MockRLlibAgentWithMemory(env, memory_space_config, memory_system) # Train memory-integrated agent memory_times = [] @@ -314,7 +314,7 @@ def benchmark_rllib_integration(env_name="CartPole-v1", training_iterations=10): for i in range(training_iterations): start_time = time.time() - result = memory_agent.train() + result = memory_space.train() memory_times.append(time.time() - start_time) memory_rewards.append(result["episode_reward_mean"]) @@ -332,7 +332,7 @@ def benchmark_rllib_integration(env_name="CartPole-v1", training_iterations=10): "total_training_time_seconds": sum(standard_times), "reward_progress": standard_rewards }, - "memory_agent": { + "memory_space": { "avg_iteration_time_seconds": avg_memory_time, "total_training_time_seconds": sum(memory_times), "reward_progress": memory_rewards diff --git a/docs/memory_api.md b/docs/memory_api.md index a08efb5..9f0c63f 100644 --- a/docs/memory_api.md +++ b/docs/memory_api.md @@ -164,10 +164,10 @@ result = ActionResult( ```python # Get memory agent instance for more specialized operations -memory_agent = memory_api.get_memory_agent("agent-123") +memory_space = memory_api.get_memory_space("agent-123") # Get recent states -recent_states = memory_agent.retrieve_recent_states( +recent_states = memory_space.retrieve_recent_states( count=5, memory_type="state" # Optional filter ) @@ -266,8 +266,8 @@ The hooks system automatically: embedding = [0.1, 0.2, 0.3, ...] # Your embedding vector # Search using the raw embedding -memory_agent = memory_api.get_memory_agent("agent-123") -similar_memories = memory_agent.search_by_embedding( +memory_space = memory_api.get_memory_space("agent-123") +similar_memories = memory_space.search_by_embedding( query_embedding=embedding, k=10, memory_tiers=["stm", "im"] # Optional: specific tiers to search @@ -278,10 +278,10 @@ similar_memories = memory_agent.search_by_embedding( ```python # Get memory agent instance -memory_agent = memory_api.get_memory_agent("agent-123") +memory_space = memory_api.get_memory_space("agent-123") # Search by content pattern -memories = memory_agent.search_by_content( +memories = memory_space.search_by_content( content_query="trade wood", k=5 ) @@ -369,7 +369,7 @@ The merge sorting algorithm: ```python # The merge_sorted parameter is enabled by default for appropriate methods -memories = memory_agent.retrieve_by_time_range( +memories = memory_space.retrieve_by_time_range( agent_id="agent-123", start_step=1000, end_step=2000 @@ -382,14 +382,14 @@ Expensive operations like semantic similarity searches can be automatically cach ```python # This query will cache results (using lru_cache) -similar_states = memory_agent.retrieve_similar_states( +similar_states = memory_space.retrieve_similar_states( agent_id="agent-123", query_state=current_state, k=5 ) # Subsequent identical calls will use the cached result -similar_states_again = memory_agent.retrieve_similar_states( +similar_states_again = memory_space.retrieve_similar_states( agent_id="agent-123", query_state=current_state, k=5 @@ -403,10 +403,10 @@ The caching system provides: ```python # Configure the default cache TTL -memory_agent.set_cache_ttl(300) # 5 minutes +memory_space.set_cache_ttl(300) # 5 minutes # Clear the entire cache -memory_agent.clear_cache() +memory_space.clear_cache() ``` ### When to Use Caching @@ -510,7 +510,7 @@ Client code should implement appropriate retry and fallback mechanisms based on | Method | Description | |--------|-------------| -| `get_memory_agent(agent_id)` | Get a MemoryAgent instance for more specialized operations | +| `get_memory_space(agent_id)` | Get a MemorySpace instance for more specialized operations | | `force_memory_maintenance(agent_id=None)` | Force tier transitions and cleanup | | `get_memory_statistics(agent_id)` | Get statistics about memory usage | | `clear_cache()` | Clear the query result cache | @@ -595,7 +595,7 @@ Example of tier-specific querying: ```python # Search only STM and IM (faster than searching all tiers) -results = memory_agent.search_by_embedding( +results = memory_space.search_by_embedding( query_embedding=embedding, k=10, memory_tiers=["stm", "im"] # Skip LTM for faster results @@ -639,4 +639,4 @@ The API is designed to integrate seamlessly with agent systems: - [Core Concepts](../../../core_concepts.md): Fundamental architecture and data structures - [Memory Hooks](memory_hooks.md): Non-intrusive agent integration - [Redis Integration](../../../redis_integration.md): Redis backend details -- [Memory Agent](../../../memory_agent.md): Memory agent implementation \ No newline at end of file +- [Memory Space](../../../memory_space.md): Memory agent implementation \ No newline at end of file diff --git a/docs/memory_benefits_example.md b/docs/memory_benefits_example.md index 179877f..86e93a1 100644 --- a/docs/memory_benefits_example.md +++ b/docs/memory_benefits_example.md @@ -28,7 +28,7 @@ We compare two agent types: - Makes decisions solely based on current Q-values - No ability to recall specific past experiences -2. **Memory Agent (With AgentMemory)** +2. **Memory Space (With AgentMemory)** - Uses Q-learning enhanced with memory retrieval - Recalls similar past states and their successful actions - Automatically stores experiences in tiered memory (STM, IM, LTM) @@ -40,7 +40,7 @@ The memory agent demonstrates several key features of the AgentMemory system: ```python @install_memory_hooks -class MemoryAgent(BaseAgent): +class MemorySpace(BaseAgent): def __init__(self, agent_id, action_space=4, learning_rate=0.1, discount_factor=0.9): # Initialize with a config dict to satisfy memory hooks self.config = {"agent_id": agent_id, "memory_config": MemoryConfig()} @@ -143,11 +143,11 @@ def run_experiment(episodes=100, memory_enabled=True): env = MazeEnvironment(size=size, obstacles=obstacles) # Create agent based on memory flag - agent_id = "memory_agent" if memory_enabled else "standard_agent" + agent_id = "memory_space" if memory_enabled else "standard_agent" if memory_enabled: # Create the agent with config in constructor - agent = MemoryAgent(agent_id, action_space=4) - # Memory config is already set in MemoryAgent.__init__ + agent = MemorySpace(agent_id, action_space=4) + # Memory config is already set in MemorySpace.__init__ else: agent = BaseAgent(agent_id, action_space=4) @@ -398,7 +398,7 @@ class BaseAgent: # Memory-enhanced agent using hooks @install_memory_hooks -class MemoryAgent(BaseAgent): +class MemorySpace(BaseAgent): def __init__(self, agent_id, action_space=4, learning_rate=0.1, discount_factor=0.9): # Initialize with a config dict to satisfy memory hooks self.config = {"agent_id": agent_id, "memory_config": MemoryConfig()} @@ -457,11 +457,11 @@ def run_experiment(episodes=100, memory_enabled=True): env = MazeEnvironment(size=size, obstacles=obstacles) # Create agent based on memory flag - agent_id = "memory_agent" if memory_enabled else "standard_agent" + agent_id = "memory_space" if memory_enabled else "standard_agent" if memory_enabled: # Create the agent with config in constructor - agent = MemoryAgent(agent_id, action_space=4) - # Memory config is already set in MemoryAgent.__init__ + agent = MemorySpace(agent_id, action_space=4) + # Memory config is already set in MemorySpace.__init__ else: agent = BaseAgent(agent_id, action_space=4) diff --git a/docs/memory_system.md b/docs/memory_system.md index e7d0297..4dd17a1 100644 --- a/docs/memory_system.md +++ b/docs/memory_system.md @@ -10,7 +10,7 @@ graph TB subgraph "Main Components" AMS[Agent Memory System] - MA[Memory Agent] + MA[Memory Space] RS[Redis Storage] SQ[SQLite Storage] end @@ -42,7 +42,7 @@ graph TB MA --> |Manages| EH ``` -The system is composed of an [AgentMemorySystem](../memory/core.py) that serves as the singleton entry point, managing [MemoryAgent](../memory/agent_memory.py) instances for individual agents. Each MemoryAgent manages three memory tiers: +The system is composed of an [AgentMemorySystem](../memory/core.py) that serves as the singleton entry point, managing [MemorySpace](../memory/agent_memory.py) instances for individual agents. Each MemorySpace manages three memory tiers: - [Short-Term Memory](../memory/storage/redis_stm.py) (Redis-based) - [Intermediate Memory](../memory/storage/redis_im.py) (Redis-based with TTL) - [Long-Term Memory](../memory/storage/sqlite_ltm.py) (SQLite-based) @@ -70,12 +70,12 @@ config = MemoryConfig( memory_system = AgentMemorySystem.get_instance(config) ``` -### 2. Memory Agent ([`MemoryAgent`](../memory/agent_memory.py) class) +### 2. Memory Space ([`MemorySpace`](../memory/agent_memory.py) class) Manages memory operations for a specific agent across all memory tiers. ```python -# The AgentMemorySystem creates and manages MemoryAgent instances -memory_agent = memory_system.get_memory_agent(agent_id="agent-123") +# The AgentMemorySystem creates and manages MemorySpace instances +memory_space = memory_system.get_memory_space(agent_id="agent-123") ``` ### 3. Memory Tiers diff --git a/docs/redis_stm_store.md b/docs/redis_stm_store.md index c84eb87..a9182ee 100644 --- a/docs/redis_stm_store.md +++ b/docs/redis_stm_store.md @@ -323,7 +323,7 @@ Approximate memory usage per entry: The `RedisSTMStore` integrates with: -1. **Memory Agent**: Provides storage for the memory agent's operations +1. **Memory Space**: Provides storage for the memory agent's operations 2. **API Layer**: Used by the API to fulfill retrieval requests 3. **Memory Tiers**: Part of the hierarchical memory architecture 4. **Memory Hooks**: Used by agent hooks to store state snapshots @@ -354,5 +354,5 @@ The `RedisSTMStore` integrates with: - [Agent State Storage](../../agent_state_storage.md) - [Redis Integration](../../redis_integration.md) - [ResilientRedisClient](resilient_redis_client.md) -- [Memory Agent](memory_agent.md) +- [Memory Space](memory_space.md) - [Agent Memory API](agent_memory_api.md) \ No newline at end of file diff --git a/docs/resilient_redis_client.md b/docs/resilient_redis_client.md index 10e17eb..2cf1f53 100644 --- a/docs/resilient_redis_client.md +++ b/docs/resilient_redis_client.md @@ -371,7 +371,7 @@ client = ResilientRedisClient( - [Redis Integration](../../redis_integration.md) - [Error Handling Strategy](../../error_handling_strategy.md) - [Agent State Redis Schema](../../agent_state_redis_schema.md) -- [Memory Agent Implementation](../memory_agent.py) +- [Memory Space Implementation](../memory_space.py) ## **13. AsyncResilientRedisClient** diff --git a/explorer/index.html b/explorer/index.html new file mode 100644 index 0000000..d742e7c --- /dev/null +++ b/explorer/index.html @@ -0,0 +1,12 @@ + + + + + + Agent Memory Explorer + + +
+ + + \ No newline at end of file diff --git a/explorer/main.js b/explorer/main.js new file mode 100644 index 0000000..0eccfab --- /dev/null +++ b/explorer/main.js @@ -0,0 +1,163 @@ +const { app, BrowserWindow, ipcMain, dialog } = require('electron'); +const path = require('path'); +const fs = require('fs').promises; + +// Enable hot reloading in development +if (process.argv.includes('--dev')) { + try { + require('electron-reloader')(module, { + debug: true, + watchRenderer: true + }); + } catch (_) { console.log('Error hot reloading'); } +} + +// Get the default memory directory +function getDefaultMemoryDir() { + // Point to the specific agent_farm_memories.json file + return path.join(__dirname, '..', 'validation', 'memory_samples', 'agent_farm_memories.json'); +} + +// Load memory files from a directory +async function loadMemoryFiles(filePath) { + try { + console.log('Attempting to load file:', filePath); + try { + await fs.access(filePath); + } catch { + console.error('File not found:', filePath); + return { error: 'Memory file not found' }; + } + + try { + console.log('Reading file...'); + const raw = await fs.readFile(filePath, 'utf8'); + console.log('File read, size:', raw.length); + console.log('Parsing JSON...'); + const data = JSON.parse(raw); + console.log('JSON parsed successfully, data type:', typeof data); + return { canceled: false, contents: [{ path: filePath, data }] }; + } catch (err) { + console.error('Error processing file:', err); + return { error: `Failed to parse ${filePath}: ${err.message}` }; + } + } catch (err) { + console.error('Error in loadMemoryFiles:', err); + return { error: err.message }; + } +} + +let mainWindow; + +function createWindow() { + mainWindow = new BrowserWindow({ + width: 1200, + height: 800, + webPreferences: { + nodeIntegration: false, + contextIsolation: true, + preload: path.join(__dirname, 'preload.js'), + }, + }); + + // In development, load from Vite dev server + if (process.env.NODE_ENV === 'development') { + mainWindow.loadURL('http://localhost:5173'); + mainWindow.webContents.openDevTools(); + } else { + // In production, load the built files + mainWindow.loadFile(path.join(__dirname, 'dist', 'index.html')); + } +} + +app.whenReady().then(() => { + createWindow(); + + app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) { + createWindow(); + } + }); +}); + +app.on('window-all-closed', () => { + if (process.platform !== 'darwin') { + app.quit(); + } +}); + +// Handle file opening +ipcMain.handle('openFile', async () => { + const { canceled, filePaths } = await dialog.showOpenDialog(mainWindow, { + properties: ['openFile'], + filters: [ + { name: 'JSON Files', extensions: ['json'] }, + { name: 'All Files', extensions: ['*'] }, + ], + }); + + if (canceled) { + return null; + } + + try { + const filePath = filePaths[0]; + const content = await fs.readFile(filePath, 'utf-8'); + return JSON.parse(content); + } catch (error) { + console.error('Error reading file:', error); + throw error; + } +}); + +// Handle file saving +ipcMain.handle('saveFile', async (_, content) => { + const { canceled, filePath } = await dialog.showSaveDialog(mainWindow, { + filters: [ + { name: 'JSON Files', extensions: ['json'] }, + { name: 'All Files', extensions: ['*'] }, + ], + }); + + if (canceled) { + return null; + } + + try { + await fs.writeFile(filePath, content, 'utf-8'); + return true; + } catch (error) { + console.error('Error saving file:', error); + throw error; + } +}); + +// IPC handlers + +ipcMain.handle('dialog:openFiles', async () => { + const { canceled, filePaths } = await dialog.showOpenDialog({ + properties: ['openFile', 'multiSelections'], + filters: [{ name: 'JSON', extensions: ['json', 'jsonl'] }] + }); + if (canceled) return { canceled: true }; + const contents = []; + for (const filePath of filePaths) { + try { + const raw = fs.readFileSync(filePath, 'utf8'); + const data = JSON.parse(raw); + contents.push({ path: filePath, data }); + } catch (err) { + contents.push({ path: filePath, error: err.message }); + } + } + return { canceled: false, contents }; +}); + +ipcMain.handle('loadDefaultMemories', async () => { + console.log('loadDefaultMemories called'); + const memoryDir = getDefaultMemoryDir(); + console.log('Default memory path:', memoryDir); + const result = await loadMemoryFiles(memoryDir); + console.log('Load result:', result); + return result; +}); \ No newline at end of file diff --git a/explorer/package-lock.json b/explorer/package-lock.json new file mode 100644 index 0000000..7f236a2 --- /dev/null +++ b/explorer/package-lock.json @@ -0,0 +1,5218 @@ +{ + "name": "agent-memory-explorer", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "agent-memory-explorer", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "@emotion/react": "^11.11.3", + "@emotion/styled": "^11.11.0", + "@mui/icons-material": "^5.15.6", + "@mui/material": "^5.15.6", + "@mui/x-date-pickers": "^6.19.3", + "date-fns": "^2.30.0", + "electron": "^29.0.0", + "fuse.js": "^7.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-window": "^1.8.9", + "zustand": "^4.5.0" + }, + "devDependencies": { + "@types/react": "^18.2.48", + "@types/react-dom": "^18.2.18", + "@types/react-window": "^1.8.8", + "@typescript-eslint/eslint-plugin": "^6.19.1", + "@typescript-eslint/parser": "^6.19.1", + "@vitejs/plugin-react": "^4.2.1", + "electron-reloader": "^1.2.3", + "eslint": "^8.56.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.5", + "typescript": "^5.3.3", + "vite": "^5.0.12" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz", + "integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.1.tgz", + "integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.1", + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helpers": "^7.27.1", + "@babel/parser": "^7.27.1", + "@babel/template": "^7.27.1", + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz", + "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.27.1", + "@babel/types": "^7.27.1", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz", + "integrity": "sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz", + "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", + "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.1" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", + "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz", + "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.1", + "@babel/parser": "^7.27.1", + "@babel/template": "^7.27.1", + "@babel/types": "^7.27.1", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", + "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@electron/get": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", + "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", + "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.3.3", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz", + "integrity": "sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/react": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", + "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "license": "MIT" + }, + "node_modules/@emotion/styled": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz", + "integrity": "sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/unitless": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", + "license": "MIT" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", + "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", + "license": "MIT" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.0.tgz", + "integrity": "sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.0.tgz", + "integrity": "sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.0", + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", + "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", + "license": "MIT" + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mui/base": { + "version": "5.0.0-dev.20240529-082515-213b5e33ab", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-dev.20240529-082515-213b5e33ab.tgz", + "integrity": "sha512-3ic6fc6BHstgM+MGqJEVx3zt9g5THxVXm3VVFUfdeplPqAWWgW2QoKfZDLT10s+pi+MAkpgEBP0kgRidf81Rsw==", + "deprecated": "This package has been replaced by @base-ui-components/react", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.6", + "@floating-ui/react-dom": "^2.0.8", + "@mui/types": "^7.2.14-dev.20240529-082515-213b5e33ab", + "@mui/utils": "^6.0.0-dev.20240529-082515-213b5e33ab", + "@popperjs/core": "^2.11.8", + "clsx": "^2.1.1", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/base/node_modules/@mui/utils": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.4.9.tgz", + "integrity": "sha512-Y12Q9hbK9g+ZY0T3Rxrx9m2m10gaphDuUMgWxyV5kNJevVxXYCLclYUCC9vXaIk1/NdNDTcW2Yfr2OGvNFNmHg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@mui/types": "~7.2.24", + "@types/prop-types": "^15.7.14", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.0.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/core-downloads-tracker": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.17.1.tgz", + "integrity": "sha512-OcZj+cs6EfUD39IoPBOgN61zf1XFVY+imsGoBDwXeSq2UHJZE3N59zzBOVjclck91Ne3e9gudONOeILvHCIhUA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/icons-material": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.17.1.tgz", + "integrity": "sha512-CN86LocjkunFGG0yPlO4bgqHkNGgaEOEc3X/jG5Bzm401qYw79/SaLrofA7yAKCCXAGdIGnLoMHohc3+ubs95A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^5.0.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.17.1.tgz", + "integrity": "sha512-2B33kQf+GmPnrvXXweWAx+crbiUEsxCdCN979QDYnlH9ox4pd+0/IBriWLV+l6ORoBF60w39cWjFnJYGFdzXcw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/core-downloads-tracker": "^5.17.1", + "@mui/system": "^5.17.1", + "@mui/types": "~7.2.15", + "@mui/utils": "^5.17.1", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^19.0.0", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/private-theming": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.17.1.tgz", + "integrity": "sha512-XMxU0NTYcKqdsG8LRmSoxERPXwMbp16sIXPcLVgLGII/bVNagX0xaheWAwFv8+zDK7tI3ajllkuD3GZZE++ICQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/utils": "^5.17.1", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/styled-engine": { + "version": "5.16.14", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.14.tgz", + "integrity": "sha512-UAiMPZABZ7p8mUW4akDV6O7N3+4DatStpXMZwPlt+H/dA0lt67qawN021MNND+4QTpjaiMYxbhKZeQcyWCbuKw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@emotion/cache": "^11.13.5", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.17.1.tgz", + "integrity": "sha512-aJrmGfQpyF0U4D4xYwA6ueVtQcEMebET43CUmKMP7e7iFh3sMIF3sBR0l8Urb4pqx1CBjHAaWgB0ojpND4Q3Jg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/private-theming": "^5.17.1", + "@mui/styled-engine": "^5.16.14", + "@mui/types": "~7.2.15", + "@mui/utils": "^5.17.1", + "clsx": "^2.1.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "7.2.24", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.24.tgz", + "integrity": "sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.17.1.tgz", + "integrity": "sha512-jEZ8FTqInt2WzxDV8bhImWBqeQRD99c/id/fq83H0ER9tFl+sfZlaAoCdznGvbSQQ9ividMxqSV2c7cC1vBcQg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/types": "~7.2.15", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/x-date-pickers": { + "version": "6.20.2", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-6.20.2.tgz", + "integrity": "sha512-x1jLg8R+WhvkmUETRfX2wC+xJreMii78EXKLl6r3G+ggcAZlPyt0myID1Amf6hvJb9CtR7CgUo8BwR+1Vx9Ggw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2", + "@mui/base": "^5.0.0-beta.22", + "@mui/utils": "^5.14.16", + "@types/react-transition-group": "^4.4.8", + "clsx": "^2.0.0", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.8.6", + "@mui/system": "^5.8.0", + "date-fns": "^2.25.0 || ^3.2.0", + "date-fns-jalali": "^2.13.0-0", + "dayjs": "^1.10.7", + "luxon": "^3.0.2", + "moment": "^2.29.4", + "moment-hijri": "^2.1.2", + "moment-jalaali": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "date-fns": { + "optional": true + }, + "date-fns-jalali": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + }, + "moment-hijri": { + "optional": true + }, + "moment-jalaali": { + "optional": true + } + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.9", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.9.tgz", + "integrity": "sha512-e9MeMtVWo186sgvFFJOPGy7/d2j2mZhLJIdVW0C/xDluuOvymEATqz6zKsP0ZmXGzQtqlyjz5sC1sYQUoJG98w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.1.tgz", + "integrity": "sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.1.tgz", + "integrity": "sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz", + "integrity": "sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.1.tgz", + "integrity": "sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.1.tgz", + "integrity": "sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.1.tgz", + "integrity": "sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.1.tgz", + "integrity": "sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.1.tgz", + "integrity": "sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.1.tgz", + "integrity": "sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.1.tgz", + "integrity": "sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.1.tgz", + "integrity": "sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.1.tgz", + "integrity": "sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.1.tgz", + "integrity": "sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.1.tgz", + "integrity": "sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.1.tgz", + "integrity": "sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.1.tgz", + "integrity": "sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.1.tgz", + "integrity": "sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.1.tgz", + "integrity": "sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.1.tgz", + "integrity": "sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.1.tgz", + "integrity": "sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", + "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.17.50", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.50.tgz", + "integrity": "sha512-Mxiq0ULv/zo1OzOhwPqOA13I81CV/W3nvd3ChtQZRT5Cwz3cr0FKo/wMSsbTqL3EXpaBAEQhva2B8ByRkOIh9A==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.22", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.22.tgz", + "integrity": "sha512-vUhG0YmQZ7kL/tmKLrD3g5zXbXXreZXB3pmROW8bg3CnLnpjkRVwUlLne7Ufa2r9yJ8+/6B73RzhAek5TBKh2Q==", + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-window": { + "version": "1.8.8", + "resolved": "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.8.tgz", + "integrity": "sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/semver": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz", + "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.5.0.tgz", + "integrity": "sha512-JuLWaEqypaJmOJPLWwO335Ig6jSgC1FTONCWAxnqcQthLTK/Yc9aH6hr9z/87xciejbQcnP3GnA1FWUSWeXaeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.26.10", + "@babel/plugin-transform-react-jsx-self": "^7.25.9", + "@babel/plugin-transform-react-jsx-source": "^7.25.9", + "@rolldown/pluginutils": "1.0.0-beta.9", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" + } + }, + "node_modules/acorn": { + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT", + "optional": true + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", + "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001716", + "electron-to-chromium": "^1.5.149", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001718", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz", + "integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/date-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/date-time/-/date-time-3.1.0.tgz", + "integrity": "sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "time-zone": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "optional": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "license": "MIT", + "optional": true + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/electron": { + "version": "29.4.6", + "resolved": "https://registry.npmjs.org/electron/-/electron-29.4.6.tgz", + "integrity": "sha512-fz8ndj8cmmf441t4Yh2FDP3Rn0JhLkVGvtUf2YVMbJ5SdJPlc0JWll9jYkhh60jDKVVCr/tBAmfxqRnXMWJpzg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@electron/get": "^2.0.0", + "@types/node": "^20.9.0", + "extract-zip": "^2.0.1" + }, + "bin": { + "electron": "cli.js" + }, + "engines": { + "node": ">= 12.20.55" + } + }, + "node_modules/electron-is-dev": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-1.2.0.tgz", + "integrity": "sha512-R1oD5gMBPS7PVU8gJwH6CtT0e6VSoD0+SzSnYpNm+dBkcijgA+K7VAMHDfnRq/lkKPZArpzplTW6jfiMYosdzw==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-reloader": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/electron-reloader/-/electron-reloader-1.2.3.tgz", + "integrity": "sha512-aDnACAzNg0QvQhzw7LYOx/nVS10mEtbuG6M0QQvNQcLnJEwFs6is+EGRCnM+KQlQ4KcTbdwnt07nd7ZjHpY4iw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "chokidar": "^3.5.0", + "date-time": "^3.1.0", + "electron-is-dev": "^1.2.0", + "find-up": "^5.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.157", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.157.tgz", + "integrity": "sha512-/0ybgsQd1muo8QlnuTpKwtl0oX5YMlUGbm8xyqgDU00motRkKFFbUJySAQBWcY79rVqNLWIWa87BGVGClwAB2w==", + "dev": true, + "license": "ISC" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "license": "MIT", + "optional": true + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.20", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.20.tgz", + "integrity": "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "license": "BSD-2-Clause", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "license": "MIT" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fuse.js": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.1.0.tgz", + "integrity": "sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=10" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/global-agent/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause" + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "license": "ISC", + "optional": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "license": "MIT", + "optional": true, + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz", + "integrity": "sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==", + "license": "MIT" + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/react-window": { + "version": "1.8.11", + "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.11.tgz", + "integrity": "sha512-+SRbUVT2scadgFSWx+R1P754xHPEqvcfSfVX10QYg6POOz+WNgkN48pS+BtZNIMGiL1HYrSEiCkwsMS15QogEQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.0.0", + "memoize-one": ">=3.1.1 <6" + }, + "engines": { + "node": ">8.0.0" + }, + "peerDependencies": { + "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "license": "MIT" + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/rollup": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.41.1.tgz", + "integrity": "sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.7" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.41.1", + "@rollup/rollup-android-arm64": "4.41.1", + "@rollup/rollup-darwin-arm64": "4.41.1", + "@rollup/rollup-darwin-x64": "4.41.1", + "@rollup/rollup-freebsd-arm64": "4.41.1", + "@rollup/rollup-freebsd-x64": "4.41.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.41.1", + "@rollup/rollup-linux-arm-musleabihf": "4.41.1", + "@rollup/rollup-linux-arm64-gnu": "4.41.1", + "@rollup/rollup-linux-arm64-musl": "4.41.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.41.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.41.1", + "@rollup/rollup-linux-riscv64-gnu": "4.41.1", + "@rollup/rollup-linux-riscv64-musl": "4.41.1", + "@rollup/rollup-linux-s390x-gnu": "4.41.1", + "@rollup/rollup-linux-x64-gnu": "4.41.1", + "@rollup/rollup-linux-x64-musl": "4.41.1", + "@rollup/rollup-win32-arm64-msvc": "4.41.1", + "@rollup/rollup-win32-ia32-msvc": "4.41.1", + "@rollup/rollup-win32-x64-msvc": "4.41.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "license": "MIT", + "optional": true + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "license": "MIT", + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "license": "MIT" + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/time-zone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz", + "integrity": "sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "license": "(MIT OR CC0-1.0)", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/vite": { + "version": "5.4.19", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", + "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zustand": { + "version": "4.5.7", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz", + "integrity": "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.2.2" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0.6", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } + } + } +} diff --git a/explorer/package.json b/explorer/package.json new file mode 100644 index 0000000..c3cdc0f --- /dev/null +++ b/explorer/package.json @@ -0,0 +1,45 @@ +{ + "name": "agent-memory-explorer", + "version": "0.1.0", + "description": "Electron-based Agent Memory Explorer (MVP)", + "main": "main.js", + "author": "", + "license": "MIT", + "scripts": { + "start": "electron .", + "dev": "electron . --dev", + "build": "tsc", + "watch": "tsc -w", + "lint": "eslint -c .eslintrc --ext .ts,.tsx src/", + "dev:react": "vite", + "build:react": "vite build" + }, + "dependencies": { + "electron": "^29.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-window": "^1.8.9", + "date-fns": "^2.30.0", + "fuse.js": "^7.0.0", + "zustand": "^4.5.0", + "@emotion/react": "^11.11.3", + "@emotion/styled": "^11.11.0", + "@mui/material": "^5.15.6", + "@mui/icons-material": "^5.15.6", + "@mui/x-date-pickers": "^6.19.3" + }, + "devDependencies": { + "electron-reloader": "^1.2.3", + "@types/react": "^18.2.48", + "@types/react-dom": "^18.2.18", + "@types/react-window": "^1.8.8", + "@typescript-eslint/eslint-plugin": "^6.19.1", + "@typescript-eslint/parser": "^6.19.1", + "@vitejs/plugin-react": "^4.2.1", + "eslint": "^8.56.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.5", + "typescript": "^5.3.3", + "vite": "^5.0.12" + } +} \ No newline at end of file diff --git a/explorer/preload.js b/explorer/preload.js new file mode 100644 index 0000000..2ac59b0 --- /dev/null +++ b/explorer/preload.js @@ -0,0 +1,11 @@ +const { contextBridge, ipcRenderer } = require('electron'); + +contextBridge.exposeInMainWorld('electron', { + openFile: () => ipcRenderer.invoke('openFile'), + saveFile: (content) => ipcRenderer.invoke('saveFile', content), +}); + +contextBridge.exposeInMainWorld('electronAPI', { + openFiles: () => ipcRenderer.invoke('dialog:openFiles'), + loadDefaultMemories: () => ipcRenderer.invoke('loadDefaultMemories') +}); \ No newline at end of file diff --git a/explorer/renderer/index.html b/explorer/renderer/index.html new file mode 100644 index 0000000..d67ba81 --- /dev/null +++ b/explorer/renderer/index.html @@ -0,0 +1,29 @@ + + + + + + + Agent Memory Explorer + + + +
+ + + + + + + + + \ No newline at end of file diff --git a/explorer/renderer/index.js b/explorer/renderer/index.js new file mode 100644 index 0000000..aaf7662 --- /dev/null +++ b/explorer/renderer/index.js @@ -0,0 +1,142 @@ +(() => { + try { + console.log('Initializing React app...'); + const { createElement, useState, useEffect } = React; + const html = htm.bind(createElement); + + function App() { + const [memories, setMemories] = useState([]); + const [selected, setSelected] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + // Load memories on startup + useEffect(() => { + loadDefaultMemories(); + }, []); + + const loadDefaultMemories = async () => { + try { + console.log('Starting to load default memories...'); + setLoading(true); + setError(null); + const result = await window.electronAPI.loadDefaultMemories(); + console.log('Received result from loadDefaultMemories:', result); + if (result.error) { + console.error('Error loading memories:', result.error); + setError(result.error); + return; + } + processMemoryResults(result); + } catch (err) { + console.error('Exception in loadDefaultMemories:', err); + setError(err.message); + } finally { + setLoading(false); + } + }; + + const processMemoryResults = (result) => { + console.log('Processing memory results:', result); + if (result.canceled) { + console.log('Load was canceled'); + return; + } + const loaded = []; + result.contents.forEach(item => { + if (item.error) { + console.error(`Failed to parse ${item.path}: ${item.error}`); + return; + } + console.log('Processing item data:', item.data); + // Handle different possible data structures + if (Array.isArray(item.data)) { + console.log(`Adding ${item.data.length} items from array`); + loaded.push(...item.data); + } else if (item.data.memories && Array.isArray(item.data.memories)) { + console.log(`Adding ${item.data.memories.length} items from memories array`); + loaded.push(...item.data.memories); + } else if (item.data.memory && Array.isArray(item.data.memory)) { + console.log(`Adding ${item.data.memory.length} items from memory array`); + loaded.push(...item.data.memory); + } else { + console.log('Adding single item'); + loaded.push(item.data); + } + }); + console.log(`Total items loaded: ${loaded.length}`); + if (loaded.length === 0) { + console.log('No items were loaded, data structure:', JSON.stringify(result.contents[0].data, null, 2)); + } + // basic sort by timestamp descending if exists + loaded.sort((a, b) => { + if (!a.timestamp || !b.timestamp) return 0; + return new Date(b.timestamp) - new Date(a.timestamp); + }); + setMemories(loaded); + if (loaded.length) setSelected(0); + }; + + const openFiles = async () => { + try { + setLoading(true); + setError(null); + const result = await window.electronAPI.openFiles(); + processMemoryResults(result); + } catch (err) { + setError(err.message); + } finally { + setLoading(false); + } + }; + + const MemoryList = () => html` + `; + + const MemoryDetail = () => { + if (selected === null || !memories[selected]) + return html`
No memory selected
`; + const mem = memories[selected]; + return html`
+

Memory Detail

+
${JSON.stringify(mem, null, 2)}
+
`; + }; + + return html`
+ ${MemoryList()} + ${MemoryDetail()} +
`; + } + + console.log('Rendering React app...'); + ReactDOM.render(createElement(App), document.getElementById('root')); + console.log('React app rendered successfully'); + } catch (err) { + console.error('Error initializing React app:', err); + document.body.innerHTML = `
+

Error initializing app:

+
${err.message}
+
`; + } +})(); \ No newline at end of file diff --git a/explorer/src/App.tsx b/explorer/src/App.tsx new file mode 100644 index 0000000..9c10c83 --- /dev/null +++ b/explorer/src/App.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { Box, CssBaseline, ThemeProvider, createTheme } from '@mui/material'; +import { LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; +import TopBar from './components/TopBar'; +import SideBar from './components/SideBar'; +import MainPanel from './components/MainPanel'; +import FilterDrawer from './components/FilterDrawer'; +import StatusBar from './components/StatusBar'; + +const theme = createTheme({ + palette: { + mode: 'dark', + }, +}); + +const App: React.FC = () => { + return ( + + + + + + + + + + + + + + + ); +}; + +export default App; \ No newline at end of file diff --git a/explorer/src/components/FilterDrawer.tsx b/explorer/src/components/FilterDrawer.tsx new file mode 100644 index 0000000..9e78ad6 --- /dev/null +++ b/explorer/src/components/FilterDrawer.tsx @@ -0,0 +1,167 @@ +import React from 'react'; +import { + Drawer, + Box, + Typography, + FormGroup, + FormControlLabel, + Checkbox, + Slider, + Divider, + IconButton, +} from '@mui/material'; +import { DatePicker } from '@mui/x-date-pickers'; +import { Close as CloseIcon } from '@mui/icons-material'; +import { useStore } from '../store'; + +const FilterDrawer: React.FC = () => { + const { filters, setFilters, sort, setSort } = useStore(); + const [open, setOpen] = React.useState(true); + + const handleRoleChange = (role: string) => (event: React.ChangeEvent) => { + const newRoles = event.target.checked + ? [...filters.roles, role as 'user' | 'assistant' | 'system'] + : filters.roles.filter((r) => r !== role); + setFilters({ roles: newRoles }); + }; + + const handleImportanceChange = (_: Event, value: number | number[]) => { + setFilters({ minImportance: value as number }); + }; + + const handleSortChange = (field: 'timestamp' | 'importance') => () => { + setSort({ + field, + direction: sort.field === field && sort.direction === 'asc' ? 'desc' : 'asc', + }); + }; + + return ( + + + Filters + setOpen(false)}> + + + + + + + Date Range + + + setFilters({ dateRange: [date, filters.dateRange[1]] })} + slotProps={{ textField: { size: 'small', fullWidth: true } }} + /> + setFilters({ dateRange: [filters.dateRange[0], date] })} + slotProps={{ textField: { size: 'small', fullWidth: true } }} + /> + + + + Roles + + + + } + label="User" + /> + + } + label="Assistant" + /> + + } + label="System" + /> + + + + Minimum Importance + + + + + Sort By + + + + + Timestamp {sort.field === 'timestamp' && (sort.direction === 'asc' ? '↑' : '↓')} + + + + + Importance {sort.field === 'importance' && (sort.direction === 'asc' ? '↑' : '↓')} + + + + + + ); +}; + +export default FilterDrawer; \ No newline at end of file diff --git a/explorer/src/components/MainPanel.tsx b/explorer/src/components/MainPanel.tsx new file mode 100644 index 0000000..04b8b32 --- /dev/null +++ b/explorer/src/components/MainPanel.tsx @@ -0,0 +1,126 @@ +import React from 'react'; +import { + Box, + Paper, + Typography, + Chip, + IconButton, + Collapse, +} from '@mui/material'; +import { + ExpandMore as ExpandMoreIcon, + ExpandLess as ExpandLessIcon, +} from '@mui/icons-material'; +import { useStore } from '../store'; +import { format } from 'date-fns'; + +const MainPanel: React.FC = () => { + const { selectedMemory } = useStore(); + const [showEmbedding, setShowEmbedding] = React.useState(false); + + if (!selectedMemory) { + return ( + + + Select a memory to view its details + + + ); + } + + return ( + + + + Memory Details + + + ID: {selectedMemory.id} + + + Timestamp: {format(new Date(selectedMemory.timestamp), 'PPpp')} + + + Role: {selectedMemory.role} + + + Importance: {selectedMemory.importance.toFixed(2)} + + + + + + Content + + + {selectedMemory.content} + + + + {selectedMemory.tags.length > 0 && ( + + + Tags + + + {selectedMemory.tags.map((tag) => ( + + ))} + + + )} + + {selectedMemory.embedding && ( + + + Embedding + setShowEmbedding(!showEmbedding)} + > + {showEmbedding ? : } + + + + + {JSON.stringify(selectedMemory.embedding, null, 2)} + + + + )} + + ); +}; + +export default MainPanel; \ No newline at end of file diff --git a/explorer/src/components/SideBar.tsx b/explorer/src/components/SideBar.tsx new file mode 100644 index 0000000..e564ad0 --- /dev/null +++ b/explorer/src/components/SideBar.tsx @@ -0,0 +1,103 @@ +import React from 'react'; +import { Box, Paper, Typography } from '@mui/material'; +import { FixedSizeList as List } from 'react-window'; +import { useStore } from '../store'; +import { format } from 'date-fns'; +import { Memory } from '../types'; + +const MemoryItem: React.FC<{ + index: number; + style: React.CSSProperties; + data: Memory[]; +}> = ({ index, style, data }) => { + const memory = data[index]; + const { setSelectedMemory } = useStore(); + + const getRoleColor = (role: string) => { + switch (role) { + case 'user': + return '#2196f3'; + case 'assistant': + return '#4caf50'; + case 'system': + return '#f44336'; + default: + return '#757575'; + } + }; + + return ( + setSelectedMemory(memory)} + > + + + + {memory.content.substring(0, 50)} + {memory.content.length > 50 ? '...' : ''} + + + {format(new Date(memory.timestamp), 'MMM d, yyyy HH:mm')} + + + + ); +}; + +const SideBar: React.FC = () => { + const { filteredMemories } = useStore(); + + return ( + + + Memories + + + + {MemoryItem} + + + + ); +}; + +export default SideBar; \ No newline at end of file diff --git a/explorer/src/components/StatusBar.tsx b/explorer/src/components/StatusBar.tsx new file mode 100644 index 0000000..272d9f5 --- /dev/null +++ b/explorer/src/components/StatusBar.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import { Box, Paper, Typography, Button } from '@mui/material'; +import { Save as SaveIcon } from '@mui/icons-material'; +import { useStore } from '../store'; + +const StatusBar: React.FC = () => { + const { memories, filteredMemories } = useStore(); + + const handleExport = async () => { + try { + await window.electron.saveFile(JSON.stringify(filteredMemories, null, 2)); + } catch (error) { + console.error('Error exporting memories:', error); + } + }; + + return ( + + + {filteredMemories.length} / {memories.length} memories loaded + {filteredMemories.length !== memories.length + ? ` • ${memories.length - filteredMemories.length} filtered` + : ''} + + + + ); +}; + +export default StatusBar; \ No newline at end of file diff --git a/explorer/src/components/TopBar.tsx b/explorer/src/components/TopBar.tsx new file mode 100644 index 0000000..5981cb3 --- /dev/null +++ b/explorer/src/components/TopBar.tsx @@ -0,0 +1,61 @@ +import React from 'react'; +import { + AppBar, + Toolbar, + IconButton, + TextField, + Box, + Typography, +} from '@mui/material'; +import { FolderOpen as FolderOpenIcon } from '@mui/icons-material'; +import { useStore } from '../store'; + +const TopBar: React.FC = () => { + const { filters, setFilters } = useStore(); + + const handleOpenFile = async () => { + try { + const result = await window.electron.openFile(); + if (result) { + // Handle the opened file data + console.log('File opened:', result); + } + } catch (error) { + console.error('Error opening file:', error); + } + }; + + const handleSearchChange = (event: React.ChangeEvent) => { + setFilters({ searchText: event.target.value }); + }; + + return ( + + + + + + + Agent Memory Explorer + + + + + + + ); +}; + +export default TopBar; \ No newline at end of file diff --git a/explorer/src/electron.d.ts b/explorer/src/electron.d.ts new file mode 100644 index 0000000..f8ddc50 --- /dev/null +++ b/explorer/src/electron.d.ts @@ -0,0 +1,10 @@ +interface ElectronAPI { + openFile: () => Promise; + saveFile: (content: string) => Promise; +} + +declare global { + interface Window { + electron: ElectronAPI; + } +} \ No newline at end of file diff --git a/explorer/src/index.tsx b/explorer/src/index.tsx new file mode 100644 index 0000000..a393d6a --- /dev/null +++ b/explorer/src/index.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import { createRoot } from 'react-dom/client'; +import App from './App'; + +const container = document.getElementById('root'); +if (!container) { + throw new Error('Root element not found'); +} + +const root = createRoot(container); +root.render( + + + +); \ No newline at end of file diff --git a/explorer/src/store.ts b/explorer/src/store.ts new file mode 100644 index 0000000..a910ea2 --- /dev/null +++ b/explorer/src/store.ts @@ -0,0 +1,100 @@ +import { create } from 'zustand'; +import { Memory, FilterState, SortState } from './types'; + +interface AppState { + memories: Memory[]; + filteredMemories: Memory[]; + selectedMemory: Memory | null; + filters: FilterState; + sort: SortState; + setMemories: (memories: Memory[]) => void; + setSelectedMemory: (memory: Memory | null) => void; + setFilters: (filters: Partial) => void; + setSort: (sort: Partial) => void; + applyFilters: () => void; +} + +const initialFilters: FilterState = { + dateRange: [null, null], + roles: ['user', 'assistant', 'system'], + searchText: '', + minImportance: 0, +}; + +const initialSort: SortState = { + field: 'timestamp', + direction: 'desc', +}; + +export const useStore = create((set, get) => ({ + memories: [], + filteredMemories: [], + selectedMemory: null, + filters: initialFilters, + sort: initialSort, + + setMemories: (memories) => { + set({ memories, filteredMemories: memories }); + }, + + setSelectedMemory: (memory) => { + set({ selectedMemory: memory }); + }, + + setFilters: (filters) => { + set((state) => ({ + filters: { ...state.filters, ...filters }, + })); + get().applyFilters(); + }, + + setSort: (sort) => { + set((state) => ({ + sort: { ...state.sort, ...sort }, + })); + get().applyFilters(); + }, + + applyFilters: () => { + const { memories, filters, sort } = get(); + + let filtered = [...memories]; + + // Apply date range filter + if (filters.dateRange[0] && filters.dateRange[1]) { + filtered = filtered.filter((memory) => { + const date = new Date(memory.timestamp); + return date >= filters.dateRange[0]! && date <= filters.dateRange[1]!; + }); + } + + // Apply role filter + if (filters.roles.length > 0) { + filtered = filtered.filter((memory) => filters.roles.includes(memory.role)); + } + + // Apply text search + if (filters.searchText) { + const searchLower = filters.searchText.toLowerCase(); + filtered = filtered.filter( + (memory) => + memory.content.toLowerCase().includes(searchLower) || + memory.tags.some((tag) => tag.toLowerCase().includes(searchLower)) + ); + } + + // Apply importance filter + filtered = filtered.filter((memory) => memory.importance >= filters.minImportance); + + // Apply sorting + filtered.sort((a, b) => { + const direction = sort.direction === 'asc' ? 1 : -1; + if (sort.field === 'timestamp') { + return direction * (new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()); + } + return direction * (a.importance - b.importance); + }); + + set({ filteredMemories: filtered }); + }, +})); \ No newline at end of file diff --git a/explorer/src/types.ts b/explorer/src/types.ts new file mode 100644 index 0000000..358bb2a --- /dev/null +++ b/explorer/src/types.ts @@ -0,0 +1,21 @@ +export interface Memory { + id: string; + timestamp: string; + role: 'user' | 'assistant' | 'system'; + content: string; + importance: number; + embedding?: number[]; + tags: string[]; +} + +export interface FilterState { + dateRange: [Date | null, Date | null]; + roles: ('user' | 'assistant' | 'system')[]; + searchText: string; + minImportance: number; +} + +export interface SortState { + field: 'timestamp' | 'importance'; + direction: 'asc' | 'desc'; +} \ No newline at end of file diff --git a/explorer/tsconfig.json b/explorer/tsconfig.json new file mode 100644 index 0000000..fa3a856 --- /dev/null +++ b/explorer/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + } + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} \ No newline at end of file diff --git a/explorer/tsconfig.node.json b/explorer/tsconfig.node.json new file mode 100644 index 0000000..862dfb2 --- /dev/null +++ b/explorer/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} \ No newline at end of file diff --git a/explorer/vite.config.ts b/explorer/vite.config.ts new file mode 100644 index 0000000..96139a4 --- /dev/null +++ b/explorer/vite.config.ts @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import path from 'path'; + +export default defineConfig({ + plugins: [react()], + base: './', + resolve: { + alias: { + '@': path.resolve(__dirname, './src'), + }, + }, + build: { + outDir: 'dist', + emptyOutDir: true, + }, +}); \ No newline at end of file diff --git a/main_demo.py b/main_demo.py index 8873e20..870b640 100644 --- a/main_demo.py +++ b/main_demo.py @@ -534,7 +534,7 @@ def run_experiment(episodes=100, memory_enabled=True, random_seed=None): # Important: Pre-initialize the memory agent for our agent ID # This ensures the agent exists in the memory system before hooks try to access it - memory_agent = memory_system.get_memory_agent(agent_id) + memory_space = memory_system.get_memory_space(agent_id) # 4. Create the agent with our compression-disabled config config = {"memory_config": memory_config} diff --git a/memory/__init__.py b/memory/__init__.py index 54c644e..85705d4 100644 --- a/memory/__init__.py +++ b/memory/__init__.py @@ -20,7 +20,7 @@ ) # from memory.embeddings.text_embeddings import TextEmbeddingEngine from memory.embeddings.compression import CompressionEngine -from memory.agent_memory import MemoryAgent +from memory.space import MemorySpace # Retrieval components from memory.retrieval.attribute import AttributeRetrieval @@ -35,7 +35,7 @@ __all__ = [ # Core classes "AgentMemorySystem", - "MemoryAgent", + "MemorySpace", "MemoryConfig", # Config classes "RedisSTMConfig", diff --git a/memory/api/memory_api.py b/memory/api/memory_api.py index dc8a5e2..caeed65 100644 --- a/memory/api/memory_api.py +++ b/memory/api/memory_api.py @@ -403,7 +403,7 @@ def inverted_key_fn(item): def _aggregate_results( self, - memory_agent, + memory_space, query_fn: Callable, k: int = None, memory_type: Optional[str] = None, @@ -414,7 +414,7 @@ def _aggregate_results( """Aggregate results across memory tiers using the provided query function. Args: - memory_agent: The memory agent to query + memory_space: The memory agent to query query_fn: Function that takes (store, k, memory_type) and returns results k: Maximum number of results to return memory_type: Optional filter for specific memory types @@ -433,9 +433,9 @@ def _aggregate_results( store_results = [] for store in [ - memory_agent.stm_store, - memory_agent.im_store, - memory_agent.ltm_store, + memory_space.stm_store, + memory_space.im_store, + memory_space.ltm_store, ]: if remaining <= 0: break @@ -704,13 +704,13 @@ def retrieve_state_by_id( Returns: Memory entry or None if not found """ - memory_agent = self.memory_system.get_memory_agent(agent_id) + memory_space = self.memory_system.get_memory_space(agent_id) # Try retrieving from each tier in order - memory = memory_agent.stm_store.get(memory_id) + memory = memory_space.stm_store.get(memory_id) if not memory: - memory = memory_agent.im_store.get(memory_id) + memory = memory_space.im_store.get(memory_id) if not memory: - memory = memory_agent.ltm_store.get(memory_id) + memory = memory_space.ltm_store.get(memory_id) return memory def retrieve_recent_states( @@ -729,8 +729,8 @@ def retrieve_recent_states( Returns: List of memory entries """ - memory_agent = self.memory_system.get_memory_agent(agent_id) - return memory_agent.stm_store.get_recent(count, memory_type) + memory_space = self.memory_system.get_memory_space(agent_id) + return memory_space.stm_store.get_recent(count, memory_type) @cacheable(ttl=60) def retrieve_similar_states( @@ -788,9 +788,9 @@ def retrieve_similar_states( memory_type=memory_type, ) - memory_agent = self.memory_system.get_memory_agent(agent_id) + memory_space = self.memory_system.get_memory_space(agent_id) - if not memory_agent.embedding_engine: + if not memory_space.embedding_engine: error_msg = ( "Vector similarity search requires embedding engine to be enabled" ) @@ -804,7 +804,7 @@ def retrieve_similar_states( # Generate embedding for query state try: - query_embedding = memory_agent.embedding_engine.encode_stm(query_state) + query_embedding = memory_space.embedding_engine.encode_stm(query_state) log_with_context( logger.debug, "Generated embedding for query state", @@ -824,9 +824,9 @@ def retrieve_similar_states( def query_function(store, limit, mem_type): # Determine which tier this store represents - if store == memory_agent.stm_store: + if store == memory_space.stm_store: tier = "stm" - elif store == memory_agent.im_store: + elif store == memory_space.im_store: tier = "im" else: # ltm_store tier = "ltm" @@ -843,7 +843,7 @@ def query_function(store, limit, mem_type): # Convert embedding to appropriate dimensions for this tier try: tier_embedding = ( - memory_agent.embedding_engine.ensure_embedding_dimensions( + memory_space.embedding_engine.ensure_embedding_dimensions( query_embedding, tier ) ) @@ -882,7 +882,7 @@ def query_function(store, limit, mem_type): return [] results = self._aggregate_results( - memory_agent, + memory_space, query_function, k=k, memory_type=memory_type, @@ -976,14 +976,14 @@ def retrieve_by_time_range( ) try: - memory_agent = self.memory_system.get_memory_agent(agent_id) + memory_space = self.memory_system.get_memory_space(agent_id) def query_function(store, _, mem_type): return store.get_by_step_range(start_step, end_step, mem_type) # Use merge sort since results from each store are already sorted by step number return self._aggregate_results( - memory_agent, + memory_space, query_function, memory_type=memory_type, sort_key=lambda x: x.get("step_number", 0), @@ -1029,13 +1029,13 @@ def retrieve_by_attributes( raise MemoryRetrievalException("At least one attribute must be specified") try: - memory_agent = self.memory_system.get_memory_agent(agent_id) + memory_space = self.memory_system.get_memory_space(agent_id) def query_function(store, _, mem_type): return store.get_by_attributes(attributes, mem_type) return self._aggregate_results( - memory_agent, + memory_space, query_function, memory_type=memory_type, sort_key=lambda x: x.get("step_number", 0), @@ -1108,20 +1108,20 @@ def search_by_embedding( ) try: - memory_agent = self.memory_system.get_memory_agent(agent_id) + memory_space = self.memory_system.get_memory_space(agent_id) # Determine which tiers to search tiers = memory_tiers or ["stm", "im", "ltm"] results = [] tier_stores = { - "stm": memory_agent.stm_store, - "im": memory_agent.im_store, - "ltm": memory_agent.ltm_store, + "stm": memory_space.stm_store, + "im": memory_space.im_store, + "ltm": memory_space.ltm_store, } # Check if embedding engine is available for conversion - has_embedding_engine = memory_agent.embedding_engine is not None + has_embedding_engine = memory_space.embedding_engine is not None for tier in tiers: if len(results) >= k: @@ -1138,7 +1138,7 @@ def search_by_embedding( try: # Automatically convert the embedding to the target tier format tier_embedding = ( - memory_agent.embedding_engine.ensure_embedding_dimensions( + memory_space.embedding_engine.ensure_embedding_dimensions( query_embedding, tier ) ) @@ -1203,7 +1203,7 @@ def search_by_content( raise MemoryRetrievalException("k must be a positive integer") try: - memory_agent = self.memory_system.get_memory_agent(agent_id) + memory_space = self.memory_system.get_memory_space(agent_id) # Convert string query to dict if needed if isinstance(content_query, str): @@ -1215,7 +1215,7 @@ def query_function(store, limit, _): return store.search_by_content(query_dict, k=limit) return self._aggregate_results( - memory_agent, query_function, k=k, merge_sorted=True + memory_space, query_function, k=k, merge_sorted=True ) except Exception as e: logger.error(f"Failed to search by content for agent {agent_id}: {e}") @@ -1238,15 +1238,15 @@ def get_memory_statistics(self, agent_id: str) -> MemoryStatistics: raise MemoryRetrievalException("Agent ID cannot be empty") try: - memory_agent = self.memory_system.get_memory_agent(agent_id) + memory_space = self.memory_system.get_memory_space(agent_id) # Gather statistics from each memory tier - stm_count = memory_agent.stm_store.count() - im_count = memory_agent.im_store.count() - ltm_count = memory_agent.ltm_store.count() + stm_count = memory_space.stm_store.count() + im_count = memory_space.im_store.count() + ltm_count = memory_space.ltm_store.count() # Get memory type counts in STM - memory_type_counts = memory_agent.stm_store.count_by_type() + memory_type_counts = memory_space.stm_store.count_by_type() return { "total_memories": stm_count + im_count + ltm_count, @@ -1254,8 +1254,8 @@ def get_memory_statistics(self, agent_id: str) -> MemoryStatistics: "im_count": im_count, "ltm_count": ltm_count, "memory_type_distribution": memory_type_counts, - "last_maintenance_time": memory_agent.last_maintenance_time, - "insert_count_since_maintenance": memory_agent._insert_count, + "last_maintenance_time": memory_space.last_maintenance_time, + "insert_count_since_maintenance": memory_space._insert_count, } except Exception as e: logger.error(f"Failed to get memory statistics for agent {agent_id}: {e}") @@ -1297,7 +1297,7 @@ def force_memory_maintenance(self, agent_id: Optional[str] = None) -> bool: # Maintain single agent try: - memory_agent = self.memory_system.get_memory_agent(agent_id) + memory_space = self.memory_system.get_memory_space(agent_id) except Exception as e: log_with_context( logger.error, @@ -1317,7 +1317,7 @@ def force_memory_maintenance(self, agent_id: Optional[str] = None) -> bool: operation="force_memory_maintenance", ) - result = memory_agent._perform_maintenance() + result = memory_space._perform_maintenance() if not result: log_with_context( @@ -1359,7 +1359,7 @@ def force_memory_maintenance(self, agent_id: Optional[str] = None) -> bool: success = True failed_agents = [] - for current_agent_id, memory_agent in self.memory_system.agents.items(): + for current_agent_id, memory_space in self.memory_system.agents.items(): try: log_with_context( logger.debug, @@ -1368,7 +1368,7 @@ def force_memory_maintenance(self, agent_id: Optional[str] = None) -> bool: operation="force_memory_maintenance", ) - if not memory_agent._perform_maintenance(): + if not memory_space._perform_maintenance(): log_with_context( logger.error, "Maintenance failed", @@ -1459,7 +1459,7 @@ def clear_agent_memory( # Get memory agent - this could raise if agent_id doesn't exist try: - memory_agent = self.memory_system.get_memory_agent(agent_id) + memory_space = self.memory_system.get_memory_space(agent_id) except Exception as e: logger.error(f"Failed to get memory agent for agent {agent_id}: {e}") raise MemoryMaintenanceException( @@ -1469,7 +1469,7 @@ def clear_agent_memory( if not memory_tiers: # Clear all tiers try: - result = memory_agent.clear_memory() + result = memory_space.clear_memory() if not result: logger.error(f"Failed to clear memory for agent {agent_id}") return result @@ -1485,7 +1485,7 @@ def clear_agent_memory( # Clear specified tiers if "stm" in memory_tiers: try: - if not memory_agent.stm_store.clear(): + if not memory_space.stm_store.clear(): logger.error(f"Failed to clear STM for agent {agent_id}") success = False failed_tiers.append("stm") @@ -1496,7 +1496,7 @@ def clear_agent_memory( if "im" in memory_tiers: try: - if not memory_agent.im_store.clear(): + if not memory_space.im_store.clear(): logger.error(f"Failed to clear IM for agent {agent_id}") success = False failed_tiers.append("im") @@ -1507,7 +1507,7 @@ def clear_agent_memory( if "ltm" in memory_tiers: try: - if not memory_agent.ltm_store.clear(): + if not memory_space.ltm_store.clear(): logger.error(f"Failed to clear LTM for agent {agent_id}") success = False failed_tiers.append("ltm") @@ -1567,7 +1567,7 @@ def set_importance_score( ) try: - memory_agent = self.memory_system.get_memory_agent(agent_id) + memory_space = self.memory_system.get_memory_space(agent_id) # Find memory and update importance score memory = self.retrieve_state_by_id(agent_id, memory_id) @@ -1581,12 +1581,12 @@ def set_importance_score( ) # Determine which store contains the memory and update - if memory_agent.stm_store.contains(memory_id): - return memory_agent.stm_store.update(memory) - elif memory_agent.im_store.contains(memory_id): - return memory_agent.im_store.update(memory) - elif memory_agent.ltm_store.contains(memory_id): - return memory_agent.ltm_store.update(memory) + if memory_space.stm_store.contains(memory_id): + return memory_space.stm_store.update(memory) + elif memory_space.im_store.contains(memory_id): + return memory_space.im_store.update(memory) + elif memory_space.ltm_store.contains(memory_id): + return memory_space.ltm_store.update(memory) return False except Exception as e: @@ -1792,7 +1792,7 @@ def configure_memory_system(self, config: ConfigUpdate) -> bool: operation="configure_memory_system", ) - for agent_id, memory_agent in self.memory_system.agents.items(): + for agent_id, memory_space in self.memory_system.agents.items(): try: log_with_context( logger.debug, @@ -1802,16 +1802,16 @@ def configure_memory_system(self, config: ConfigUpdate) -> bool: ) # Update agent config - memory_agent.config = self.memory_system.config + memory_space.config = self.memory_system.config # Update store configurations - memory_agent.stm_store.config = self.memory_system.config.stm_config - memory_agent.im_store.config = self.memory_system.config.im_config - memory_agent.ltm_store.config = self.memory_system.config.ltm_config + memory_space.stm_store.config = self.memory_system.config.stm_config + memory_space.im_store.config = self.memory_system.config.im_config + memory_space.ltm_store.config = self.memory_system.config.ltm_config # Update embedding engine if needed - if memory_agent.embedding_engine: - memory_agent.embedding_engine.configure( + if memory_space.embedding_engine: + memory_space.embedding_engine.configure( self.memory_system.config.autoencoder_config ) except Exception as e: diff --git a/memory/core.py b/memory/core.py index b81d068..b7f429f 100644 --- a/memory/core.py +++ b/memory/core.py @@ -1,11 +1,33 @@ -"""Core classes for the Tiered Adaptive Semantic Memory (TASM) system.""" +"""Core classes for the Tiered Adaptive Semantic Memory (TASM) system. + +This module implements the central memory management system for AI agents, providing +a hierarchical memory architecture with three tiers: +- Short-Term Memory (STM): For recent, frequently accessed memories +- Intermediate Memory (IM): For medium-term storage of important experiences +- Long-Term Memory (LTM): For permanent storage of significant memories + +The system features: +- Adaptive memory consolidation and decay +- Semantic similarity-based memory retrieval +- Configurable memory hooks and event triggers +- Support for multiple concurrent agents +- JSON serialization for persistence +- Hybrid retrieval combining vector and attribute-based search + +The main entry point is the AgentMemorySystem class, which manages individual +MemorySpace instances for each agent and provides global configuration. + +Example: + >>> config = MemoryConfig() + >>> memory_system = AgentMemorySystem.get_instance(config) + >>> memory_system.store_agent_state("agent1", {"position": [0, 0]}, step_number=1) + >>> memories = memory_system.retrieve_similar_states("agent1", {"position": [1, 1]}) +""" import logging -import time -import uuid from typing import Any, Dict, List, Optional, Union -from memory.agent_memory import MemoryAgent +from memory.space import MemorySpace from memory.config import MemoryConfig logger = logging.getLogger(__name__) @@ -22,7 +44,7 @@ class AgentMemorySystem: Attributes: config: Configuration for the memory system - agents: Dictionary of agent_id to MemoryAgent instances + agents: Dictionary of agent_id to MemorySpace instances """ _instance = None @@ -41,24 +63,24 @@ def __init__(self, config: MemoryConfig): config: Configuration for the memory system """ self.config = config - self.agents: Dict[str, MemoryAgent] = {} + self.agents: Dict[str, MemorySpace] = {} # Configure logging logging.basicConfig(level=getattr(logging, config.logging_level)) logger.info("TASM system initialized with configuration: %s", config) - def get_memory_agent(self, agent_id: str) -> MemoryAgent: - """Get or create a MemoryAgent for the specified agent. + def get_memory_space(self, agent_id: str) -> MemorySpace: + """Get or create a MemorySpace for the specified agent. Args: agent_id: Unique identifier for the agent Returns: - MemoryAgent instance for the specified agent + MemorySpace instance for the specified agent """ if agent_id not in self.agents: - self.agents[agent_id] = MemoryAgent(agent_id, self.config) - logger.debug("Created new MemoryAgent for agent %s", agent_id) + self.agents[agent_id] = MemorySpace(agent_id, self.config) + logger.debug("Created new MemorySpace for agent %s", agent_id) return self.agents[agent_id] @@ -82,8 +104,8 @@ def store_agent_state( Returns: True if storage was successful """ - memory_agent = self.get_memory_agent(agent_id) - return memory_agent.store_state(state_data, step_number, priority, tier) + memory_space = self.get_memory_space(agent_id) + return memory_space.store_state(state_data, step_number, priority, tier) def store_agent_interaction( self, @@ -105,8 +127,8 @@ def store_agent_interaction( Returns: True if storage was successful """ - memory_agent = self.get_memory_agent(agent_id) - return memory_agent.store_interaction( + memory_space = self.get_memory_space(agent_id) + return memory_space.store_interaction( interaction_data, step_number, priority, tier ) @@ -130,8 +152,8 @@ def store_agent_action( Returns: True if storage was successful """ - memory_agent = self.get_memory_agent(agent_id) - return memory_agent.store_action(action_data, step_number, priority, tier) + memory_space = self.get_memory_space(agent_id) + return memory_space.store_action(action_data, step_number, priority, tier) # Add memory retrieval methods def retrieve_similar_states( @@ -157,8 +179,8 @@ def retrieve_similar_states( List of memory entries sorted by similarity """ self._check_agent_exists(agent_id) - memory_agent = self._get_agent(agent_id) - return memory_agent.retrieve_similar_states( + memory_space = self._get_agent(agent_id) + return memory_space.retrieve_similar_states( query_state, k, memory_type, threshold, context_weights ) @@ -180,8 +202,8 @@ def retrieve_by_time_range( Returns: List of memory entries within the specified time range """ - memory_agent = self.get_memory_agent(agent_id) - return memory_agent.retrieve_by_time_range(start_step, end_step, memory_type) + memory_space = self.get_memory_space(agent_id) + return memory_space.retrieve_by_time_range(start_step, end_step, memory_type) def retrieve_by_attributes( self, @@ -199,8 +221,8 @@ def retrieve_by_attributes( Returns: List of memory entries matching the specified attributes """ - memory_agent = self.get_memory_agent(agent_id) - return memory_agent.retrieve_by_attributes(attributes, memory_type) + memory_space = self.get_memory_space(agent_id) + return memory_space.retrieve_by_attributes(attributes, memory_type) # Add memory statistics method def get_memory_statistics( @@ -214,8 +236,8 @@ def get_memory_statistics( Returns: Dictionary containing memory statistics """ - memory_agent = self.get_memory_agent(agent_id) - return memory_agent.get_memory_statistics(simplified) + memory_space = self.get_memory_space(agent_id) + return memory_space.get_memory_statistics(simplified) # Add memory management methods def force_memory_maintenance(self, agent_id: Optional[str] = None) -> bool: @@ -228,13 +250,13 @@ def force_memory_maintenance(self, agent_id: Optional[str] = None) -> bool: True if maintenance was successful """ if agent_id: - memory_agent = self.get_memory_agent(agent_id) - return memory_agent.force_maintenance() + memory_space = self.get_memory_space(agent_id) + return memory_space.force_maintenance() else: # Perform maintenance for all agents success = True - for agent_id, memory_agent in self.agents.items(): - if not memory_agent.force_maintenance(): + for agent_id, memory_space in self.agents.items(): + if not memory_space.force_maintenance(): logger.error("Maintenance failed for agent %s", agent_id) success = False return success @@ -258,8 +280,8 @@ def search_by_embedding( Returns: List of memory entries sorted by similarity """ - memory_agent = self.get_memory_agent(agent_id) - return memory_agent.search_by_embedding(query_embedding, k, memory_tiers) + memory_space = self.get_memory_space(agent_id) + return memory_space.search_by_embedding(query_embedding, k, memory_tiers) def search_by_content( self, agent_id: str, content_query: Union[str, Dict[str, Any]], k: int = 5 @@ -274,8 +296,8 @@ def search_by_content( Returns: List of memory entries matching the content query """ - memory_agent = self.get_memory_agent(agent_id) - return memory_agent.search_by_content(content_query, k) + memory_space = self.get_memory_space(agent_id) + return memory_space.search_by_content(content_query, k) # Add memory hook methods def register_memory_hook( @@ -296,8 +318,8 @@ def register_memory_hook( logger.warning("Memory hooks are disabled in configuration") return False - memory_agent = self.get_memory_agent(agent_id) - return memory_agent.register_hook(event_type, hook_function, priority) + memory_space = self.get_memory_space(agent_id) + return memory_space.register_hook(event_type, hook_function, priority) def trigger_memory_event( self, agent_id: str, event_type: str, event_data: Dict[str, Any] @@ -316,8 +338,8 @@ def trigger_memory_event( logger.warning("Memory hooks are disabled in configuration") return False - memory_agent = self.get_memory_agent(agent_id) - return memory_agent.trigger_event(event_type, event_data) + memory_space = self.get_memory_space(agent_id) + return memory_space.trigger_event(event_type, event_data) def clear_all_memories(self) -> bool: """Clear all memory data for all agents. @@ -326,8 +348,8 @@ def clear_all_memories(self) -> bool: True if clearing was successful """ success = True - for agent_id, memory_agent in self.agents.items(): - if not memory_agent.clear_memory(): + for agent_id, memory_space in self.agents.items(): + if not memory_space.clear_memory(): logger.error("Failed to clear memory for agent %s", agent_id) success = False @@ -348,7 +370,7 @@ def add_memory(self, memory_data: Dict[str, Any]) -> str: agent_id = memory_data.get("agent_id", "default_agent") # Get or create memory agent - memory_agent = self.get_memory_agent(agent_id) + memory_space = self.get_memory_space(agent_id) # Store in STM step_number = memory_data.get("step_number", 0) @@ -360,20 +382,20 @@ def add_memory(self, memory_data: Dict[str, Any]) -> str: # Choose appropriate method based on memory type if memory_type == "state": - memory_agent.store_state( + memory_space.store_state( memory_data.get("content", {}), step_number, priority, tier ) elif memory_type == "interaction": - memory_agent.store_interaction( + memory_space.store_interaction( memory_data.get("content", {}), step_number, priority, tier ) elif memory_type == "action": - memory_agent.store_action( + memory_space.store_action( memory_data.get("content", {}), step_number, priority, tier ) else: # For generic types, use store_state as a fallback - memory_agent.store_state( + memory_space.store_state( memory_data.get("content", {}), step_number, priority, tier ) @@ -389,19 +411,19 @@ def get_memory(self, memory_id: str) -> Optional[Dict[str, Any]]: Memory entry or None if not found """ # Check in all agents - for agent_id, memory_agent in self.agents.items(): + for agent_id, memory_space in self.agents.items(): # Try STM first - memory = memory_agent.stm_store.get(agent_id, memory_id) + memory = memory_space.stm_store.get(agent_id, memory_id) if memory: return memory # Try IM next - memory = memory_agent.im_store.get(agent_id, memory_id) + memory = memory_space.im_store.get(agent_id, memory_id) if memory: return memory # Try LTM last - memory = memory_agent.ltm_store.get(memory_id) + memory = memory_space.ltm_store.get(memory_id) if memory: return memory @@ -432,8 +454,8 @@ def hybrid_retrieve( List of memory entries sorted by hybrid score """ self._check_agent_exists(agent_id) - memory_agent = self._get_agent(agent_id) - return memory_agent.hybrid_retrieve( + memory_space = self._get_agent(agent_id) + return memory_space.hybrid_retrieve( query_state, k, memory_type, vector_weight, attribute_weight ) @@ -479,7 +501,7 @@ def _check_agent_exists(self, agent_id: str) -> None: if agent_id not in self.agents: raise ValueError(f"Agent with ID {agent_id} does not exist") - def _get_agent(self, agent_id: str) -> MemoryAgent: + def _get_agent(self, agent_id: str) -> MemorySpace: """Get the memory agent for an agent ID. This is a helper method that verifies the agent exists before returning. @@ -488,7 +510,7 @@ def _get_agent(self, agent_id: str) -> MemoryAgent: agent_id: ID of the agent to retrieve Returns: - MemoryAgent instance for the specified agent + MemorySpace instance for the specified agent Raises: ValueError: If the agent doesn't exist diff --git a/memory/search/strategies/attribute.py b/memory/search/strategies/attribute.py index 6af700b..32bc3a0 100644 --- a/memory/search/strategies/attribute.py +++ b/memory/search/strategies/attribute.py @@ -182,7 +182,7 @@ def search( # Use provided scoring method or fallback to instance default current_scoring_method = scoring_method or self.scoring_method - agent = self.memory_system.get_memory_agent(agent_id) + agent = self.memory_system.get_memory_space(agent_id) for current_tier in tiers_to_search: if current_tier not in ["stm", "im", "ltm"]: logger.warning("Unsupported memory tier: %s", current_tier) diff --git a/memory/search/strategies/match.py b/memory/search/strategies/match.py index 7b3d3cb..eece73e 100644 --- a/memory/search/strategies/match.py +++ b/memory/search/strategies/match.py @@ -52,7 +52,7 @@ def search( min_score: float = 0.6, **kwargs ) -> List[Dict[str, Any]]: - agent = self.memory_system.get_memory_agent(agent_id) + agent = self.memory_system.get_memory_space(agent_id) if "example" not in query: raise ValueError("Query must include an 'example' memory to match against") example = query["example"] diff --git a/memory/search/strategies/similarity.py b/memory/search/strategies/similarity.py index 4f9d4ef..7d7b51a 100644 --- a/memory/search/strategies/similarity.py +++ b/memory/search/strategies/similarity.py @@ -101,9 +101,9 @@ def search( if isinstance(self.memory_system, AgentMemorySystem): # Get the memory agent - memory_agent = self.memory_system.get_memory_agent(agent_id) + memory_space = self.memory_system.get_memory_space(agent_id) else: - memory_agent = self.memory_system + memory_space = self.memory_system for current_tier in tiers_to_search: # Skip if tier is not supported @@ -201,11 +201,11 @@ def search( "Fetching memory %s from %s store", memory_id, current_tier ) if current_tier == "stm": - memory = memory_agent.stm_store.get(agent_id, memory_id) + memory = memory_space.stm_store.get(agent_id, memory_id) elif current_tier == "im": - memory = memory_agent.im_store.get(agent_id, memory_id) + memory = memory_space.im_store.get(agent_id, memory_id) else: # ltm - memory = memory_agent.ltm_store.get(memory_id) + memory = memory_space.ltm_store.get(memory_id) logger.debug("Memory store returned: %s", memory) diff --git a/memory/search/strategies/step.py b/memory/search/strategies/step.py index c11324e..76a6243 100644 --- a/memory/search/strategies/step.py +++ b/memory/search/strategies/step.py @@ -123,7 +123,7 @@ def search( query, start_step, end_step, reference_step, step_range ) tiers_to_search = ["stm", "im", "ltm"] if tier is None else [tier] - agent = self.memory_system.get_memory_agent(agent_id) + agent = self.memory_system.get_memory_space(agent_id) for current_tier in tiers_to_search: if current_tier not in ["stm", "im", "ltm"]: logger.warning("Unsupported memory tier: %s", current_tier) diff --git a/memory/search/strategies/temporal.py b/memory/search/strategies/temporal.py index 262c9d3..9da6460 100644 --- a/memory/search/strategies/temporal.py +++ b/memory/search/strategies/temporal.py @@ -66,7 +66,7 @@ def search( results = [] temporal_params = self._process_query(query, start_time, end_time, start_step, end_step) tiers_to_search = ["stm", "im", "ltm"] if tier is None else [tier] - agent = self.memory_system.get_memory_agent(agent_id) + agent = self.memory_system.get_memory_space(agent_id) for current_tier in tiers_to_search: if current_tier not in ["stm", "im", "ltm"]: logger.warning("Unsupported memory tier: %s", current_tier) diff --git a/memory/search/strategies/window.py b/memory/search/strategies/window.py index 2842d78..00a0d8a 100644 --- a/memory/search/strategies/window.py +++ b/memory/search/strategies/window.py @@ -71,7 +71,7 @@ def search( Raises: ValueError: If time parameters are invalid or conflicting """ - agent = self.memory_system.get_memory_agent(agent_id) + agent = self.memory_system.get_memory_space(agent_id) timestamp_field = query.get("timestamp_field", "metadata.timestamp") time_params = sum( 1 for p in ["last_minutes", "last_hours", "last_days"] if p in query diff --git a/memory/agent_memory.py b/memory/space.py similarity index 95% rename from memory/agent_memory.py rename to memory/space.py index 3eabca2..4846dc3 100644 --- a/memory/agent_memory.py +++ b/memory/space.py @@ -1,4 +1,51 @@ -"""Memory Agent implementation for agent state management.""" +"""Memory Space implementation for agent management. + +This module implements a hierarchical memory system for AI agents that manages memories across +three distinct storage tiers: + +1. Short-Term Memory (STM): High-resolution, temporary storage for recent experiences +2. Intermediate Memory (IM): Medium-term storage with moderate compression +3. Long-Term Memory (LTM): Permanent storage with high compression for long-term retention + +Key Features: +- Hierarchical memory management with automatic tier transitions +- Neural embedding-based similarity search +- Hybrid retrieval combining vector similarity and attribute matching +- Memory compression and importance scoring +- Event-based memory formation hooks +- Comprehensive memory statistics and maintenance + +The system uses Redis for STM and IM storage, and SQLite for LTM storage. It supports +various memory types including states, interactions, and actions, with configurable +compression levels and importance scoring mechanisms. + +Example: + ```python + from memory.config import MemoryConfig + from memory.space import MemorySpace + + # Initialize memory system + config = MemoryConfig() + memory = MemorySpace(agent_id="agent1", config=config) + + # Store a memory + memory.store_state( + state_data={"position": {"x": 10, "y": 20}}, + step_number=1, + priority=0.8 + ) + + # Retrieve similar memories + similar = memory.retrieve_similar_states( + query_state={"position": {"x": 11, "y": 19}}, + k=5 + ) + ``` + +Note: + This module requires Redis for STM/IM storage and SQLite for LTM storage. + Neural embeddings are optional but recommended for similarity search functionality. +""" import logging import math @@ -7,7 +54,6 @@ from typing import Any, Dict, List, Optional, Union from memory.config import MemoryConfig -from memory.embeddings.autoencoder import AutoencoderEmbeddingEngine from memory.embeddings.compression import CompressionEngine from memory.embeddings.text_embeddings import TextEmbeddingEngine from memory.embeddings.vector_store import VectorStore @@ -19,7 +65,7 @@ logger = logging.getLogger(__name__) -class MemoryAgent: +class MemorySpace: """Manages an agent's memory across hierarchical storage tiers. This class provides a unified interface for storing and retrieving @@ -38,7 +84,7 @@ class MemoryAgent: """ def __init__(self, agent_id: str, config: MemoryConfig): - """Initialize the MemoryAgent. + """Initialize the MemorySpace. Args: agent_id: Unique identifier for the agent @@ -81,7 +127,7 @@ def __init__(self, agent_id: str, config: MemoryConfig): # Internal state self._insert_count = 0 - logger.debug("MemoryAgent initialized for agent %s", agent_id) + logger.debug("MemorySpace initialized for agent %s", agent_id) def store_state( self, diff --git a/memory/utils/serialization.py b/memory/utils/serialization.py index 06463f3..eeae5ec 100644 --- a/memory/utils/serialization.py +++ b/memory/utils/serialization.py @@ -395,7 +395,7 @@ def load_memory_system_from_json(filepath: str, use_mock_redis: bool = False): # Load agents and their memories for agent_id, agent_data in data.get("agents", {}).items(): # Get or create agent - memory_agent = memory_system.get_memory_agent(agent_id) + memory_space = memory_system.get_memory_space(agent_id) # Add memories for memory in agent_data.get("memories", []): @@ -435,18 +435,18 @@ def load_memory_system_from_json(filepath: str, use_mock_redis: bool = False): # Store memory in the appropriate store based on the tier if tier == "stm": logger.debug(f"Storing memory in STM store with type {memory_type}") - memory_agent.stm_store.store(agent_id, memory_copy) + memory_space.stm_store.store(agent_id, memory_copy) elif tier == "im": logger.debug(f"Storing memory in IM store with type {memory_type}") - memory_agent.im_store.store(agent_id, memory_copy) + memory_space.im_store.store(agent_id, memory_copy) elif tier == "ltm": logger.debug(f"Storing memory in LTM store with type {memory_type}") - memory_agent.ltm_store.store(memory_copy) + memory_space.ltm_store.store(memory_copy) else: # Default to STM if tier is unknown logger.warning(f"Unknown tier '{tier}', storing in STM") logger.debug(f"Storing memory in STM store with type {memory_type}") - memory_agent.stm_store.store(agent_id, memory_copy) + memory_space.stm_store.store(agent_id, memory_copy) # Store memory vectors if embeddings exist if "embeddings" in memory_copy and memory_copy.get("embeddings"): @@ -475,13 +475,13 @@ def load_memory_system_from_json(filepath: str, use_mock_redis: bool = False): tier = metadata.get("current_tier") or metadata.get("tier") if tier == "stm": vector_store.store_memory_vectors(memory_copy, tier="stm") - memory_agent.stm_store.store(agent_id, memory_copy) + memory_space.stm_store.store(agent_id, memory_copy) elif tier == "im": vector_store.store_memory_vectors(memory_copy, tier="im") - memory_agent.im_store.store(agent_id, memory_copy) + memory_space.im_store.store(agent_id, memory_copy) elif tier == "ltm": vector_store.store_memory_vectors(memory_copy, tier="ltm") - memory_agent.ltm_store.store(memory_copy) + memory_space.ltm_store.store(memory_copy) else: logger.warning(f"Unknown tier '{tier}' for memory {memory_copy.get('memory_id')}") except Exception as e: diff --git a/scripts/test_memory_loading.py b/scripts/test_memory_loading.py index c649f4c..4bde163 100644 --- a/scripts/test_memory_loading.py +++ b/scripts/test_memory_loading.py @@ -95,8 +95,8 @@ def main(): ) # Get the loaded memories from the memory system - memory_agent = memory_system.get_memory_agent(agent_id) - loaded_memories = memory_agent.stm_store.get_all(agent_id) + memory_space = memory_system.get_memory_space(agent_id) + loaded_memories = memory_space.stm_store.get_all(agent_id) print(f"Loaded memories from system: {len(loaded_memories)}") diff --git a/tasm_visualizer.py b/tasm_visualizer.py index 491f29e..a8e6f0a 100644 --- a/tasm_visualizer.py +++ b/tasm_visualizer.py @@ -530,8 +530,8 @@ def update_memory_displays(self): # Get STM memories try: - memory_agent = self.memory_system.get_memory_agent(agent_id) - stm_memories = memory_agent.stm_store.get_all(agent_id) + memory_space = self.memory_system.get_memory_space(agent_id) + stm_memories = memory_space.stm_store.get_all(agent_id) self.memory_contents["STM"] = stm_memories self.stm_text.delete(1.0, tk.END) self.stm_text.insert(tk.END, f"STM Memories: {len(stm_memories)}\n\n") @@ -544,7 +544,7 @@ def update_memory_displays(self): # Get IM memories try: - im_memories = memory_agent.im_store.get_all(agent_id) + im_memories = memory_space.im_store.get_all(agent_id) self.memory_contents["IM"] = im_memories self.im_text.delete(1.0, tk.END) self.im_text.insert(tk.END, f"IM Memories: {len(im_memories)}\n\n") @@ -557,7 +557,7 @@ def update_memory_displays(self): # Get LTM memories try: - ltm_memories = memory_agent.ltm_store.get_all(agent_id=agent_id) + ltm_memories = memory_space.ltm_store.get_all(agent_id=agent_id) self.memory_contents["LTM"] = ltm_memories self.ltm_text.delete(1.0, tk.END) self.ltm_text.insert(tk.END, f"LTM Memories: {len(ltm_memories)}\n\n") diff --git a/tests/api/test_memory_api.py b/tests/api/test_memory_api.py index 87d3627..4cb7241 100644 --- a/tests/api/test_memory_api.py +++ b/tests/api/test_memory_api.py @@ -44,7 +44,7 @@ def api(self, mock_memory_system): return AgentMemoryAPI() @pytest.fixture - def mock_memory_agent(self): + def mock_memory_space(self): """Create a mock memory agent.""" mock_agent = Mock() mock_agent.stm_store = Mock() @@ -103,7 +103,7 @@ def test_store_agent_action(self, api, mock_memory_system): "agent1", action_data, 42, 0.8 ) - def test_retrieve_state_by_id(self, api, mock_memory_system, mock_memory_agent): + def test_retrieve_state_by_id(self, api, mock_memory_system, mock_memory_space): """Test retrieving a state by ID.""" # Unpack to get just the mock instance _, mock_instance = mock_memory_system @@ -112,21 +112,21 @@ def test_retrieve_state_by_id(self, api, mock_memory_system, mock_memory_agent): expected_memory = {"memory_id": memory_id, "contents": {"health": 0.8}} # Setup mocks - mock_instance.get_memory_agent.return_value = mock_memory_agent - mock_memory_agent.stm_store.get.return_value = None - mock_memory_agent.im_store.get.return_value = None - mock_memory_agent.ltm_store.get.return_value = expected_memory + mock_instance.get_memory_space.return_value = mock_memory_space + mock_memory_space.stm_store.get.return_value = None + mock_memory_space.im_store.get.return_value = None + mock_memory_space.ltm_store.get.return_value = expected_memory # Call and verify result = api.retrieve_state_by_id("agent1", memory_id) assert result == expected_memory - mock_instance.get_memory_agent.assert_called_once_with("agent1") - mock_memory_agent.stm_store.get.assert_called_once_with(memory_id) - mock_memory_agent.im_store.get.assert_called_once_with(memory_id) - mock_memory_agent.ltm_store.get.assert_called_once_with(memory_id) + mock_instance.get_memory_space.assert_called_once_with("agent1") + mock_memory_space.stm_store.get.assert_called_once_with(memory_id) + mock_memory_space.im_store.get.assert_called_once_with(memory_id) + mock_memory_space.ltm_store.get.assert_called_once_with(memory_id) - def test_retrieve_recent_states(self, api, mock_memory_system, mock_memory_agent): + def test_retrieve_recent_states(self, api, mock_memory_system, mock_memory_space): """Test retrieving recent states.""" # Unpack to get just the mock instance _, mock_instance = mock_memory_system @@ -134,17 +134,17 @@ def test_retrieve_recent_states(self, api, mock_memory_system, mock_memory_agent expected_states = [{"memory_id": f"mem{i}", "contents": {}} for i in range(5)] # Setup mocks - mock_instance.get_memory_agent.return_value = mock_memory_agent - mock_memory_agent.stm_store.get_recent.return_value = expected_states + mock_instance.get_memory_space.return_value = mock_memory_space + mock_memory_space.stm_store.get_recent.return_value = expected_states # Call and verify result = api.retrieve_recent_states("agent1", 5, "state") assert result == expected_states - mock_instance.get_memory_agent.assert_called_once_with("agent1") - mock_memory_agent.stm_store.get_recent.assert_called_once_with(5, "state") + mock_instance.get_memory_space.assert_called_once_with("agent1") + mock_memory_space.stm_store.get_recent.assert_called_once_with(5, "state") - def test_retrieve_similar_states(self, api, mock_memory_system, mock_memory_agent): + def test_retrieve_similar_states(self, api, mock_memory_system, mock_memory_space): """Test retrieving similar states.""" # Setup # Unpack to get just the mock instance @@ -161,7 +161,7 @@ def test_retrieve_similar_states(self, api, mock_memory_system, mock_memory_agen mock_embedding_engine.ensure_embedding_dimensions.return_value = [0.1, 0.2] # Set up memory agent with embedding engine - mock_memory_agent.embedding_engine = mock_embedding_engine + mock_memory_space.embedding_engine = mock_embedding_engine # Set up store search results stm_result = [ @@ -201,24 +201,24 @@ def test_retrieve_similar_states(self, api, mock_memory_system, mock_memory_agen ] # Configure mock store search methods - mock_memory_agent.stm_store.search_by_vector.return_value = stm_result - mock_memory_agent.im_store.search_by_vector.return_value = im_result - mock_memory_agent.ltm_store.search_by_vector.return_value = ltm_result + mock_memory_space.stm_store.search_by_vector.return_value = stm_result + mock_memory_space.im_store.search_by_vector.return_value = im_result + mock_memory_space.ltm_store.search_by_vector.return_value = ltm_result - # Mock get_memory_agent to return our mock - mock_instance.get_memory_agent.return_value = mock_memory_agent + # Mock get_memory_space to return our mock + mock_instance.get_memory_space.return_value = mock_memory_space # Call method result = api.retrieve_similar_states(agent_id, query_state, k, memory_type) # Assertions - mock_instance.get_memory_agent.assert_called_once_with(agent_id) + mock_instance.get_memory_space.assert_called_once_with(agent_id) mock_embedding_engine.encode_stm.assert_called_once_with(query_state) # Check store search calls - mock_memory_agent.stm_store.search_by_vector.assert_called_once() - mock_memory_agent.im_store.search_by_vector.assert_called_once() - mock_memory_agent.ltm_store.search_by_vector.assert_called_once() + mock_memory_space.stm_store.search_by_vector.assert_called_once() + mock_memory_space.im_store.search_by_vector.assert_called_once() + mock_memory_space.ltm_store.search_by_vector.assert_called_once() # Verify result is sorted by similarity score assert len(result) == 3 @@ -228,7 +228,7 @@ def test_retrieve_similar_states(self, api, mock_memory_system, mock_memory_agen assert result[0]["_similarity_score"] > result[1]["_similarity_score"] assert result[1]["_similarity_score"] > result[2]["_similarity_score"] - def test_retrieve_by_time_range(self, api, mock_memory_system, mock_memory_agent): + def test_retrieve_by_time_range(self, api, mock_memory_system, mock_memory_space): """Test retrieving memories by time range.""" # Unpack to get just the mock instance _, mock_instance = mock_memory_system @@ -238,10 +238,10 @@ def test_retrieve_by_time_range(self, api, mock_memory_system, mock_memory_agent ltm_results = [{"memory_id": "ltm1", "step_number": 2}] # Setup mocks - mock_instance.get_memory_agent.return_value = mock_memory_agent - mock_memory_agent.stm_store.get_by_step_range.return_value = stm_results - mock_memory_agent.im_store.get_by_step_range.return_value = im_results - mock_memory_agent.ltm_store.get_by_step_range.return_value = ltm_results + mock_instance.get_memory_space.return_value = mock_memory_space + mock_memory_space.stm_store.get_by_step_range.return_value = stm_results + mock_memory_space.im_store.get_by_step_range.return_value = im_results + mock_memory_space.ltm_store.get_by_step_range.return_value = ltm_results # Call and verify result = api.retrieve_by_time_range("agent1", 1, 10, "state") @@ -254,18 +254,18 @@ def test_retrieve_by_time_range(self, api, mock_memory_system, mock_memory_agent ] assert result == expected - mock_instance.get_memory_agent.assert_called_once_with("agent1") - mock_memory_agent.stm_store.get_by_step_range.assert_called_once_with( + mock_instance.get_memory_space.assert_called_once_with("agent1") + mock_memory_space.stm_store.get_by_step_range.assert_called_once_with( 1, 10, "state" ) - mock_memory_agent.im_store.get_by_step_range.assert_called_once_with( + mock_memory_space.im_store.get_by_step_range.assert_called_once_with( 1, 10, "state" ) - mock_memory_agent.ltm_store.get_by_step_range.assert_called_once_with( + mock_memory_space.ltm_store.get_by_step_range.assert_called_once_with( 1, 10, "state" ) - def test_retrieve_by_attributes(self, api, mock_memory_system, mock_memory_agent): + def test_retrieve_by_attributes(self, api, mock_memory_system, mock_memory_space): """Test retrieving memories by attributes.""" # Unpack to get just the mock instance _, mock_instance = mock_memory_system @@ -276,10 +276,10 @@ def test_retrieve_by_attributes(self, api, mock_memory_system, mock_memory_agent attributes = {"location": "kitchen", "mood": "happy"} # Setup mocks - mock_instance.get_memory_agent.return_value = mock_memory_agent - mock_memory_agent.stm_store.get_by_attributes.return_value = stm_results - mock_memory_agent.im_store.get_by_attributes.return_value = im_results - mock_memory_agent.ltm_store.get_by_attributes.return_value = ltm_results + mock_instance.get_memory_space.return_value = mock_memory_space + mock_memory_space.stm_store.get_by_attributes.return_value = stm_results + mock_memory_space.im_store.get_by_attributes.return_value = im_results + mock_memory_space.ltm_store.get_by_attributes.return_value = ltm_results # Call and verify result = api.retrieve_by_attributes("agent1", attributes, "state") @@ -292,18 +292,18 @@ def test_retrieve_by_attributes(self, api, mock_memory_system, mock_memory_agent ] assert result == expected - mock_instance.get_memory_agent.assert_called_once_with("agent1") - mock_memory_agent.stm_store.get_by_attributes.assert_called_once_with( + mock_instance.get_memory_space.assert_called_once_with("agent1") + mock_memory_space.stm_store.get_by_attributes.assert_called_once_with( attributes, "state" ) - mock_memory_agent.im_store.get_by_attributes.assert_called_once_with( + mock_memory_space.im_store.get_by_attributes.assert_called_once_with( attributes, "state" ) - mock_memory_agent.ltm_store.get_by_attributes.assert_called_once_with( + mock_memory_space.ltm_store.get_by_attributes.assert_called_once_with( attributes, "state" ) - def test_search_by_embedding(self, api, mock_memory_system, mock_memory_agent): + def test_search_by_embedding(self, api, mock_memory_system, mock_memory_space): """Test searching by embedding vector.""" # Unpack to get just the mock instance _, mock_instance = mock_memory_system @@ -314,23 +314,23 @@ def test_search_by_embedding(self, api, mock_memory_system, mock_memory_agent): memory_tiers = ["stm", "im"] # Setup mocks - mock_instance.get_memory_agent.return_value = mock_memory_agent + mock_instance.get_memory_space.return_value = mock_memory_space # Mock the embedding engine existence - mock_memory_agent.embedding_engine = Mock() + mock_memory_space.embedding_engine = Mock() # Mock the ensure_embedding_dimensions to return the same embedding - mock_memory_agent.embedding_engine.ensure_embedding_dimensions.return_value = ( + mock_memory_space.embedding_engine.ensure_embedding_dimensions.return_value = ( query_embedding ) # Setup embedding engine with correct configuration mock_config = MagicMock() mock_config.autoencoder_config.im_dim = 4 # Match query_embedding length - mock_memory_agent.config = mock_config + mock_memory_space.config = mock_config - mock_memory_agent.stm_store.search_by_vector.return_value = stm_results - mock_memory_agent.im_store.search_by_vector.return_value = im_results + mock_memory_space.stm_store.search_by_vector.return_value = stm_results + mock_memory_space.im_store.search_by_vector.return_value = im_results # Call and verify result = api.search_by_embedding( @@ -344,25 +344,25 @@ def test_search_by_embedding(self, api, mock_memory_system, mock_memory_agent): ] assert result == expected - mock_instance.get_memory_agent.assert_called_once_with("agent1") + mock_instance.get_memory_space.assert_called_once_with("agent1") # Verify ensure_embedding_dimensions is called for each tier - mock_memory_agent.embedding_engine.ensure_embedding_dimensions.assert_any_call( + mock_memory_space.embedding_engine.ensure_embedding_dimensions.assert_any_call( query_embedding, "stm" ) - mock_memory_agent.embedding_engine.ensure_embedding_dimensions.assert_any_call( + mock_memory_space.embedding_engine.ensure_embedding_dimensions.assert_any_call( query_embedding, "im" ) # Verify search_by_vector is called with the converted embedding - mock_memory_agent.stm_store.search_by_vector.assert_called_once_with( + mock_memory_space.stm_store.search_by_vector.assert_called_once_with( query_embedding, k=5 ) - mock_memory_agent.im_store.search_by_vector.assert_called_once_with( + mock_memory_space.im_store.search_by_vector.assert_called_once_with( query_embedding, k=4 ) - def test_search_by_content_string(self, api, mock_memory_system, mock_memory_agent): + def test_search_by_content_string(self, api, mock_memory_system, mock_memory_space): """Test searching by content (string).""" # Setup # Unpack to get just the mock instance @@ -376,27 +376,27 @@ def test_search_by_content_string(self, api, mock_memory_system, mock_memory_age im_result = [{"memory_id": "im-1", "agent_id": agent_id, "step_number": 5}] # Configure mock stores - mock_memory_agent.stm_store.search_by_content.return_value = stm_result - mock_memory_agent.im_store.search_by_content.return_value = im_result - mock_memory_agent.ltm_store.search_by_content.return_value = [] + mock_memory_space.stm_store.search_by_content.return_value = stm_result + mock_memory_space.im_store.search_by_content.return_value = im_result + mock_memory_space.ltm_store.search_by_content.return_value = [] - # Mock get_memory_agent to return our mock - mock_instance.get_memory_agent.return_value = mock_memory_agent + # Mock get_memory_space to return our mock + mock_instance.get_memory_space.return_value = mock_memory_space # Call method result = api.search_by_content(agent_id, content_query, k) # Assertions - mock_instance.get_memory_agent.assert_called_once_with(agent_id) - mock_memory_agent.stm_store.search_by_content.assert_called_once() - mock_memory_agent.im_store.search_by_content.assert_called_once() - mock_memory_agent.ltm_store.search_by_content.assert_called_once() + mock_instance.get_memory_space.assert_called_once_with(agent_id) + mock_memory_space.stm_store.search_by_content.assert_called_once() + mock_memory_space.im_store.search_by_content.assert_called_once() + mock_memory_space.ltm_store.search_by_content.assert_called_once() # Check results assert len(result) == 2 assert all(isinstance(item, dict) for item in result) - def test_search_by_content_dict(self, api, mock_memory_system, mock_memory_agent): + def test_search_by_content_dict(self, api, mock_memory_system, mock_memory_space): """Test searching by content (dict).""" # Setup # Unpack to get just the mock instance @@ -410,27 +410,27 @@ def test_search_by_content_dict(self, api, mock_memory_system, mock_memory_agent im_result = [{"memory_id": "im-1", "agent_id": agent_id, "step_number": 5}] # Configure mock stores - mock_memory_agent.stm_store.search_by_content.return_value = stm_result - mock_memory_agent.im_store.search_by_content.return_value = im_result - mock_memory_agent.ltm_store.search_by_content.return_value = [] + mock_memory_space.stm_store.search_by_content.return_value = stm_result + mock_memory_space.im_store.search_by_content.return_value = im_result + mock_memory_space.ltm_store.search_by_content.return_value = [] - # Mock get_memory_agent to return our mock - mock_instance.get_memory_agent.return_value = mock_memory_agent + # Mock get_memory_space to return our mock + mock_instance.get_memory_space.return_value = mock_memory_space # Call method result = api.search_by_content(agent_id, content_query, k) # Assertions - mock_instance.get_memory_agent.assert_called_once_with(agent_id) - mock_memory_agent.stm_store.search_by_content.assert_called_once() - mock_memory_agent.im_store.search_by_content.assert_called_once() - mock_memory_agent.ltm_store.search_by_content.assert_called_once() + mock_instance.get_memory_space.assert_called_once_with(agent_id) + mock_memory_space.stm_store.search_by_content.assert_called_once() + mock_memory_space.im_store.search_by_content.assert_called_once() + mock_memory_space.ltm_store.search_by_content.assert_called_once() # Check results assert len(result) == 2 assert all(isinstance(item, dict) for item in result) - def test_get_memory_statistics(self, api, mock_memory_system, mock_memory_agent): + def test_get_memory_statistics(self, api, mock_memory_system, mock_memory_space): """Test getting memory statistics.""" # Unpack to get just the mock instance _, mock_instance = mock_memory_system @@ -446,41 +446,41 @@ def test_get_memory_statistics(self, api, mock_memory_system, mock_memory_agent) } # Setup mocks - mock_instance.get_memory_agent.return_value = mock_memory_agent - mock_memory_agent.stm_store.count.return_value = 50 - mock_memory_agent.im_store.count.return_value = 40 - mock_memory_agent.ltm_store.count.return_value = 30 - mock_memory_agent.stm_store.count_by_type.return_value = { + mock_instance.get_memory_space.return_value = mock_memory_space + mock_memory_space.stm_store.count.return_value = 50 + mock_memory_space.im_store.count.return_value = 40 + mock_memory_space.ltm_store.count.return_value = 30 + mock_memory_space.stm_store.count_by_type.return_value = { "state": 50, "action": 30, "interaction": 40, } - mock_memory_agent.last_maintenance_time = 12345 - mock_memory_agent._insert_count = 10 + mock_memory_space.last_maintenance_time = 12345 + mock_memory_space._insert_count = 10 # Call and verify result = api.get_memory_statistics("agent1") assert result == expected_stats - mock_instance.get_memory_agent.assert_called_once_with("agent1") + mock_instance.get_memory_space.assert_called_once_with("agent1") def test_force_memory_maintenance_single_agent( - self, api, mock_memory_system, mock_memory_agent + self, api, mock_memory_system, mock_memory_space ): """Test forcing memory maintenance for a single agent.""" # Unpack to get just the mock instance _, mock_instance = mock_memory_system # Setup mocks - mock_instance.get_memory_agent.return_value = mock_memory_agent - mock_memory_agent._perform_maintenance.return_value = True + mock_instance.get_memory_space.return_value = mock_memory_space + mock_memory_space._perform_maintenance.return_value = True # Call and verify result = api.force_memory_maintenance("agent1") assert result is True - mock_instance.get_memory_agent.assert_called_once_with("agent1") - mock_memory_agent._perform_maintenance.assert_called_once() + mock_instance.get_memory_space.assert_called_once_with("agent1") + mock_memory_space._perform_maintenance.assert_called_once() def test_force_memory_maintenance_all_agents(self, api, mock_memory_system): """Test forcing memory maintenance for all agents.""" @@ -522,13 +522,13 @@ def test_force_memory_maintenance_failure(self, api, mock_memory_system): api.force_memory_maintenance() def test_force_memory_maintenance_single_agent_failure( - self, api, mock_memory_system, mock_memory_agent + self, api, mock_memory_system, mock_memory_space ): """Test handling of maintenance failure for a single agent.""" # Setup mocks _, mock_instance = mock_memory_system - mock_instance.get_memory_agent.return_value = mock_memory_agent - mock_memory_agent._perform_maintenance.return_value = False + mock_instance.get_memory_space.return_value = mock_memory_space + mock_memory_space._perform_maintenance.return_value = False # Test that maintenance failure raises an exception with pytest.raises( @@ -560,44 +560,44 @@ def test_force_memory_maintenance_multiple_failures(self, api, mock_memory_syste ): api.force_memory_maintenance() - def test_clear_memory_all_tiers(self, api, mock_memory_system, mock_memory_agent): + def test_clear_memory_all_tiers(self, api, mock_memory_system, mock_memory_space): """Test clearing all memory tiers for an agent.""" # Unpack to get just the mock instance _, mock_instance = mock_memory_system # Setup mocks - mock_instance.get_memory_agent.return_value = mock_memory_agent - mock_memory_agent.clear_memory.return_value = True + mock_instance.get_memory_space.return_value = mock_memory_space + mock_memory_space.clear_memory.return_value = True # Call and verify result = api.clear_agent_memory("agent1") assert result is True - mock_instance.get_memory_agent.assert_called_once_with("agent1") - mock_memory_agent.clear_memory.assert_called_once() + mock_instance.get_memory_space.assert_called_once_with("agent1") + mock_memory_space.clear_memory.assert_called_once() def test_clear_memory_specific_tiers( - self, api, mock_memory_system, mock_memory_agent + self, api, mock_memory_system, mock_memory_space ): """Test clearing specific memory tiers for an agent.""" # Unpack to get just the mock instance _, mock_instance = mock_memory_system # Setup mocks - mock_instance.get_memory_agent.return_value = mock_memory_agent - mock_memory_agent.stm_store.clear.return_value = True - mock_memory_agent.im_store.clear.return_value = True + mock_instance.get_memory_space.return_value = mock_memory_space + mock_memory_space.stm_store.clear.return_value = True + mock_memory_space.im_store.clear.return_value = True # Call and verify result = api.clear_agent_memory("agent1", memory_tiers=["stm", "im"]) assert result is True - mock_instance.get_memory_agent.assert_called_once_with("agent1") - mock_memory_agent.stm_store.clear.assert_called_once() - mock_memory_agent.im_store.clear.assert_called_once() - mock_memory_agent.ltm_store.clear.assert_not_called() + mock_instance.get_memory_space.assert_called_once_with("agent1") + mock_memory_space.stm_store.clear.assert_called_once() + mock_memory_space.im_store.clear.assert_called_once() + mock_memory_space.ltm_store.clear.assert_not_called() - def test_set_importance_score(self, api, mock_memory_system, mock_memory_agent): + def test_set_importance_score(self, api, mock_memory_system, mock_memory_space): """Test setting importance score for a memory.""" from unittest.mock import Mock @@ -628,12 +628,12 @@ def test_set_importance_score(self, api, mock_memory_system, mock_memory_agent): ltm_store.contains.return_value = False # Attach mocks to memory agent - mock_memory_agent.stm_store = stm_store - mock_memory_agent.im_store = im_store - mock_memory_agent.ltm_store = ltm_store + mock_memory_space.stm_store = stm_store + mock_memory_space.im_store = im_store + mock_memory_space.ltm_store = ltm_store # Connect memory agent to memory system - mock_instance.get_memory_agent.return_value = mock_memory_agent + mock_instance.get_memory_space.return_value = mock_memory_space # Call and verify result = api.set_importance_score("agent1", memory_id, 0.75) @@ -648,7 +648,7 @@ def test_set_importance_score(self, api, mock_memory_system, mock_memory_agent): updated_memory = stm_store.update.call_args[0][0] assert updated_memory["metadata"]["importance_score"] == 0.75 - def test_get_memory_snapshots(self, api, mock_memory_system, mock_memory_agent): + def test_get_memory_snapshots(self, api, mock_memory_system, mock_memory_space): """Test getting memory snapshots for specific steps.""" # Unpack to get just the mock instance _, mock_instance = mock_memory_system @@ -665,7 +665,7 @@ def test_get_memory_snapshots(self, api, mock_memory_system, mock_memory_agent): } # Setup mocks - mock_instance.get_memory_agent.return_value = mock_memory_agent + mock_instance.get_memory_space.return_value = mock_memory_space def mock_retrieve_by_time_range(agent_id, start_step, end_step, memory_type): if start_step == 10 and end_step == 10: @@ -686,7 +686,7 @@ def mock_retrieve_by_time_range(agent_id, start_step, end_step, memory_type): expected = {10: step10_memory, 20: step20_memory, 30: None} assert result == expected - def test_configure_memory_system(self, api, mock_memory_system, mock_memory_agent): + def test_configure_memory_system(self, api, mock_memory_system, mock_memory_space): """Test updating configuration parameters.""" # Setup - create a real config structure for testing # Unpack to get just the mock instance @@ -707,12 +707,12 @@ def test_configure_memory_system(self, api, mock_memory_system, mock_memory_agen ) # Create a mapping to actual agents - mock_instance.agents = {"agent1": mock_memory_agent} - mock_memory_agent.config = mock_instance.config - mock_memory_agent.stm_store.config = mock_instance.config.stm_config - mock_memory_agent.im_store.config = mock_instance.config.im_config - mock_memory_agent.ltm_store.config = mock_instance.config.ltm_config - mock_memory_agent.embedding_engine = MagicMock() + mock_instance.agents = {"agent1": mock_memory_space} + mock_memory_space.config = mock_instance.config + mock_memory_space.stm_store.config = mock_instance.config.stm_config + mock_memory_space.im_store.config = mock_instance.config.im_config + mock_memory_space.ltm_store.config = mock_instance.config.ltm_config + mock_memory_space.embedding_engine = MagicMock() # Test configuration update config_update = { @@ -733,7 +733,7 @@ def test_configure_memory_system(self, api, mock_memory_system, mock_memory_agen mock_config_model.to_config_object.assert_called_once_with( mock_instance.config ) - mock_memory_agent.embedding_engine.configure.assert_called_once() + mock_memory_space.embedding_engine.configure.assert_called_once() def test_configure_memory_system_validation_error_details( self, api, mock_memory_system @@ -856,7 +856,7 @@ def test_config_consistency_validation(self, api, mock_memory_system): assert "IM TTL must be greater than STM TTL" in str(excinfo.value) def test_get_attribute_change_history( - self, api, mock_memory_system, mock_memory_agent + self, api, mock_memory_system, mock_memory_space ): """Test getting attribute change history.""" # Unpack to get just the mock instance @@ -983,15 +983,15 @@ def test_retrieve_similar_states_validation_errors(self, api): api.retrieve_similar_states("agent1", {"health": 0.8}, 0) def test_retrieve_similar_states_embedding_error( - self, api, mock_memory_system, mock_memory_agent + self, api, mock_memory_system, mock_memory_space ): """Test handling of embedding engine errors.""" # Setup mocks _, mock_instance = mock_memory_system - mock_instance.get_memory_agent.return_value = mock_memory_agent + mock_instance.get_memory_space.return_value = mock_memory_space # Test missing embedding engine - mock_memory_agent.embedding_engine = None + mock_memory_space.embedding_engine = None with pytest.raises( MemoryRetrievalException, match="Vector similarity search requires embedding engine", @@ -999,8 +999,8 @@ def test_retrieve_similar_states_embedding_error( api.retrieve_similar_states("agent1", {"health": 0.8}) # Test encoding error - mock_memory_agent.embedding_engine = Mock() - mock_memory_agent.embedding_engine.encode_stm.side_effect = Exception( + mock_memory_space.embedding_engine = Mock() + mock_memory_space.embedding_engine.encode_stm.side_effect = Exception( "Embedding failed" ) with pytest.raises( @@ -1012,7 +1012,7 @@ def test_force_memory_maintenance_agent_not_found(self, api, mock_memory_system) """Test handling of agent not found in force_memory_maintenance.""" # Setup mock to raise an exception when getting memory agent _, mock_instance = mock_memory_system - mock_instance.get_memory_agent.side_effect = Exception("Agent not found") + mock_instance.get_memory_space.side_effect = Exception("Agent not found") # Test that the exception is caught and converted to a MemoryMaintenanceException with pytest.raises( @@ -1062,12 +1062,12 @@ def test_configure_memory_system_invalid_parameter(self, api, mock_memory_system api.configure_memory_system({"cleanup_interval": -10}) def test_configure_memory_system_agent_update_error( - self, api, mock_memory_system, mock_memory_agent + self, api, mock_memory_system, mock_memory_space ): """Test handling of agent configuration update errors.""" # Setup mocks _, mock_instance = mock_memory_system - mock_instance.agents = {"agent1": mock_memory_agent} + mock_instance.agents = {"agent1": mock_memory_space} # Setup the config with proper values (using real values, not mocks) mock_instance.config = MagicMock() @@ -1095,14 +1095,14 @@ def test_configure_memory_system_agent_update_error( mock_instance.config.ltm_config = ltm_config mock_instance.config.autoencoder_config = autoencoder_config - # Mock memory_agent.stm_store to raise an exception - mock_memory_agent.stm_store = MagicMock() - mock_memory_agent.im_store = MagicMock() - mock_memory_agent.ltm_store = MagicMock() - mock_memory_agent.embedding_engine = MagicMock() + # Mock memory_space.stm_store to raise an exception + mock_memory_space.stm_store = MagicMock() + mock_memory_space.im_store = MagicMock() + mock_memory_space.ltm_store = MagicMock() + mock_memory_space.embedding_engine = MagicMock() # Make the stm_store.config setter raise an exception - type(mock_memory_agent.stm_store).config = PropertyMock( + type(mock_memory_space.stm_store).config = PropertyMock( side_effect=Exception("Failed to update store config") ) @@ -1151,7 +1151,7 @@ def test_clear_agent_memory_validation_errors(self, api): with pytest.raises(MemoryMaintenanceException, match="Invalid memory tiers"): api.clear_agent_memory("agent1", ["invalid_tier"]) - def test_clear_agent_memory_agent_not_found(self, api, mock_memory_system): + def test_clear_agent_memory_space_not_found(self, api, mock_memory_system): """Test handling of agent not found in clear_agent_memory.""" # A simplified test that just verifies the test doesn't raise exceptions # Setup mocks @@ -1160,7 +1160,7 @@ def test_clear_agent_memory_agent_not_found(self, api, mock_memory_system): # Setup a mock agent that returns True for any method call mock_agent = Mock() mock_agent.clear_memory.return_value = True - mock_instance.get_memory_agent.return_value = mock_agent + mock_instance.get_memory_space.return_value = mock_agent # The test is successful if this doesn't raise an exception api.clear_agent_memory("test_agent") @@ -1175,7 +1175,7 @@ def test_clear_agent_memory_tier_failure(self, api, mock_memory_system): # Create a functional mock agent mock_agent = Mock() - mock_instance.get_memory_agent.return_value = mock_agent + mock_instance.get_memory_space.return_value = mock_agent # Create mock stores with successful return values stm_store = Mock() @@ -1242,7 +1242,7 @@ def test_merge_sorted_lists(self, api): assert api._merge_sorted_lists([list1], lambda x: x["id"], False) == list1 def test_aggregate_results_with_merge_sort( - self, api, mock_memory_system, mock_memory_agent + self, api, mock_memory_system, mock_memory_space ): """Test the aggregate_results method with merge sorting.""" from unittest.mock import Mock @@ -1257,10 +1257,10 @@ def test_aggregate_results_with_merge_sort( im_store = Mock() ltm_store = Mock() - # Set each store as an attribute of the memory_agent - mock_memory_agent.stm_store = stm_store - mock_memory_agent.im_store = im_store - mock_memory_agent.ltm_store = ltm_store + # Set each store as an attribute of the memory_space + mock_memory_space.stm_store = stm_store + mock_memory_space.im_store = im_store + mock_memory_space.ltm_store = ltm_store # Mock query function to return appropriate results based on store identity def query_fn(store, _, __): @@ -1274,7 +1274,7 @@ def query_fn(store, _, __): # Test with merge_sorted=True results = api._aggregate_results( - mock_memory_agent, + mock_memory_space, query_fn, sort_key=lambda x: x["step_number"], merge_sorted=True, @@ -1298,7 +1298,7 @@ def query_fn(store, _, __): # Test with limit - the implementation might return first k items in order of stores, # not necessarily first k items by step_number results_limited = api._aggregate_results( - mock_memory_agent, + mock_memory_space, query_fn, k=3, sort_key=lambda x: x["step_number"], @@ -1792,7 +1792,7 @@ def test_get_attribute_change_history_validation_errors(self, api): ) def test_set_importance_score_memory_not_found( - self, api, mock_memory_system, mock_memory_agent + self, api, mock_memory_system, mock_memory_space ): """Test set_importance_score when memory isn't found in any store.""" # Unpack to get just the mock instance @@ -1807,7 +1807,7 @@ def test_set_importance_score_memory_not_found( assert result is False def test_set_importance_score_im_store( - self, api, mock_memory_system, mock_memory_agent + self, api, mock_memory_system, mock_memory_space ): """Test set_importance_score for a memory in IM store.""" # Unpack to get just the mock instance @@ -1837,12 +1837,12 @@ def test_set_importance_score_im_store( ltm_store.contains.return_value = False # Attach mocks to memory agent - mock_memory_agent.stm_store = stm_store - mock_memory_agent.im_store = im_store - mock_memory_agent.ltm_store = ltm_store + mock_memory_space.stm_store = stm_store + mock_memory_space.im_store = im_store + mock_memory_space.ltm_store = ltm_store # Connect memory agent to memory system - mock_instance.get_memory_agent.return_value = mock_memory_agent + mock_instance.get_memory_space.return_value = mock_memory_space # Call and verify result = api.set_importance_score("agent1", memory_id, 0.75) @@ -1895,7 +1895,7 @@ def test_set_importance_score_validation_errors(self, api): api.set_importance_score("agent1", "memory123", 1.1) def test_search_by_embedding_all_tiers( - self, api, mock_memory_system, mock_memory_agent + self, api, mock_memory_system, mock_memory_space ): """Test search_by_embedding with all tiers.""" # Unpack to get just the mock instance @@ -1907,11 +1907,11 @@ def test_search_by_embedding_all_tiers( ltm_results = [{"memory_id": "ltm1", "_similarity_score": 0.6}] # Setup mocks - mock_instance.get_memory_agent.return_value = mock_memory_agent + mock_instance.get_memory_space.return_value = mock_memory_space # Mock the embedding engine - mock_memory_agent.embedding_engine = Mock() - mock_memory_agent.embedding_engine.ensure_embedding_dimensions.return_value = ( + mock_memory_space.embedding_engine = Mock() + mock_memory_space.embedding_engine.ensure_embedding_dimensions.return_value = ( query_embedding ) @@ -1920,12 +1920,12 @@ def test_search_by_embedding_all_tiers( mock_config.autoencoder_config.stm_dim = 4 # Match query_embedding length mock_config.autoencoder_config.im_dim = 4 mock_config.autoencoder_config.ltm_dim = 4 - mock_memory_agent.config = mock_config + mock_memory_space.config = mock_config # Setup store results - mock_memory_agent.stm_store.search_by_vector.return_value = stm_results - mock_memory_agent.im_store.search_by_vector.return_value = im_results - mock_memory_agent.ltm_store.search_by_vector.return_value = ltm_results + mock_memory_space.stm_store.search_by_vector.return_value = stm_results + mock_memory_space.im_store.search_by_vector.return_value = im_results + mock_memory_space.ltm_store.search_by_vector.return_value = ltm_results # Call method with all tiers (default) result = api.search_by_embedding("agent1", query_embedding, k=5) @@ -1937,9 +1937,9 @@ def test_search_by_embedding_all_tiers( assert {"memory_id": "ltm1", "_similarity_score": 0.6} in result # Verify all tiers were searched - mock_memory_agent.stm_store.search_by_vector.assert_called_once() - mock_memory_agent.im_store.search_by_vector.assert_called_once() - mock_memory_agent.ltm_store.search_by_vector.assert_called_once() + mock_memory_space.stm_store.search_by_vector.assert_called_once() + mock_memory_space.im_store.search_by_vector.assert_called_once() + mock_memory_space.ltm_store.search_by_vector.assert_called_once() def test_cacheable_ttl_setting(self, api): """Test custom TTL setting for cacheable decorator.""" @@ -1991,7 +1991,7 @@ def test_get_memory_statistics_agent_not_found(self, api, mock_memory_system): _, mock_instance = mock_memory_system # Set up mock to raise an exception - mock_instance.get_memory_agent.side_effect = Exception("Agent not found") + mock_instance.get_memory_space.side_effect = Exception("Agent not found") # Should raise a MemoryRetrievalException with pytest.raises(MemoryRetrievalException, match="Agent agent1 not found"): @@ -2001,14 +2001,14 @@ def test_get_memory_statistics_agent_not_found(self, api, mock_memory_system): api.get_memory_statistics("agent1") def test_configure_memory_system_agent_updates( - self, api, mock_memory_system, mock_memory_agent + self, api, mock_memory_system, mock_memory_space ): """Test that configure_memory_system updates all agent configurations.""" # Setup mocks _, mock_instance = mock_memory_system # Create multiple agents - agent1 = mock_memory_agent + agent1 = mock_memory_space agent2 = Mock() agent2.stm_store = Mock() agent2.im_store = Mock() @@ -2080,7 +2080,7 @@ def query_fn(store, limit, memory_type): assert len(result) <= 3 def test_retrieve_by_attributes_case_sensitivity( - self, api, mock_memory_system, mock_memory_agent + self, api, mock_memory_system, mock_memory_space ): """Test case sensitivity in retrieve_by_attributes.""" # Unpack to get just the mock instance @@ -2097,22 +2097,22 @@ def test_retrieve_by_attributes_case_sensitivity( ltm_results = [] # Setup mocks - mock_instance.get_memory_agent.return_value = mock_memory_agent - mock_memory_agent.stm_store.get_by_attributes.return_value = stm_results - mock_memory_agent.im_store.get_by_attributes.return_value = im_results - mock_memory_agent.ltm_store.get_by_attributes.return_value = ltm_results + mock_instance.get_memory_space.return_value = mock_memory_space + mock_memory_space.stm_store.get_by_attributes.return_value = stm_results + mock_memory_space.im_store.get_by_attributes.return_value = im_results + mock_memory_space.ltm_store.get_by_attributes.return_value = ltm_results # Call method result = api.retrieve_by_attributes("agent1", attributes, "state") # Verify attributes were passed as-is, preserving case - mock_memory_agent.stm_store.get_by_attributes.assert_called_once_with( + mock_memory_space.stm_store.get_by_attributes.assert_called_once_with( attributes, "state" ) assert result == stm_results def test_get_memory_snapshots_with_duplicates( - self, api, mock_memory_system, mock_memory_agent + self, api, mock_memory_system, mock_memory_space ): """Test get_memory_snapshots with duplicate steps.""" # Unpack to get just the mock instance @@ -2126,7 +2126,7 @@ def test_get_memory_snapshots_with_duplicates( } # Setup mocks - mock_instance.get_memory_agent.return_value = mock_memory_agent + mock_instance.get_memory_space.return_value = mock_memory_space # Mock the retrieve_by_time_range method with a custom side effect def mock_retrieve_by_time_range(agent_id, start_step, end_step, memory_type): diff --git a/tests/converter/test_converter_edge_cases.py b/tests/converter/test_converter_edge_cases.py deleted file mode 100644 index a19cd17..0000000 --- a/tests/converter/test_converter_edge_cases.py +++ /dev/null @@ -1,201 +0,0 @@ -""" -Tests for edge cases and additional coverage of the converter module. -""" - -import os -from unittest.mock import MagicMock, patch - -import pytest -from sqlalchemy.exc import SQLAlchemyError - -from converter.config import ConverterConfig -from converter.converter import from_agent_farm -from memory.core import AgentMemorySystem - - -@pytest.fixture -def config(): - """Create a test configuration.""" - return { - "use_mock_redis": True, - "batch_size": 200, - "validate": True, - "error_handling": "fail", - } - - -def test_from_agent_farm_with_empty_database(tmp_path, config): - """Test handling of empty database.""" - db_path = tmp_path / "empty.db" - mock_db_manager = MagicMock() - mock_db_manager.get_total_steps.return_value = 0 - mock_db_manager.get_agent_count.return_value = 0 - - with patch("converter.converter.DatabaseManager", return_value=mock_db_manager): - memory_system = from_agent_farm(str(db_path), config) - assert len(memory_system.agents) == 0 - - -def test_from_agent_farm_with_large_dataset(tmp_path, config): - """Test handling of large dataset.""" - db_path = tmp_path / "large.db" - mock_db_manager = MagicMock() - mock_db_manager.get_total_steps.return_value = 1000000 - mock_db_manager.get_agent_count.return_value = 1000 - mock_db_manager.validate_database.return_value = True - - # Create many mock agents and memories - mock_agents = [MagicMock(agent_id=i) for i in range(1000)] - mock_memories = [MagicMock(agent_id=i, memory_id=j) for i in range(1000) for j in range(100)] - - mock_agent_importer = MagicMock() - mock_agent_importer.import_agents.return_value = mock_agents - - mock_memory_importer = MagicMock() - mock_memory_importer.import_memories.side_effect = [ - [m for m in mock_memories if m.agent_id == i] for i in range(1000) - ] - - with patch("converter.converter.DatabaseManager", return_value=mock_db_manager), \ - patch("converter.converter.AgentImporter", return_value=mock_agent_importer), \ - patch("converter.converter.MemoryImporter", return_value=mock_memory_importer), \ - patch("memory.core.AgentMemorySystem") as mock_memory_system: - memory_system = from_agent_farm(str(db_path), config) - assert mock_memory_importer.import_memories.call_count == 1000 - - -def test_from_agent_farm_with_invalid_memory_types(tmp_path, config): - """Test handling of invalid memory types.""" - db_path = tmp_path / "test.db" - mock_db_manager = MagicMock() - mock_db_manager.validate_database.return_value = True - - mock_agent_importer = MagicMock() - mock_agent_importer.import_agents.return_value = [MagicMock(agent_id=1)] - - mock_memory_importer = MagicMock() - invalid_memory = MagicMock() - invalid_memory.memory_type = "invalid_type" - mock_memory_importer.import_memories.return_value = [invalid_memory] - - with patch("converter.converter.DatabaseManager", return_value=mock_db_manager), \ - patch("converter.converter.AgentImporter", return_value=mock_agent_importer), \ - patch("converter.converter.MemoryImporter", return_value=mock_memory_importer): - with pytest.raises(ValueError, match="Invalid memory type"): - from_agent_farm(str(db_path), config) - - -def test_from_agent_farm_with_duplicate_agent_ids(tmp_path, config): - """Test handling of duplicate agent IDs.""" - db_path = tmp_path / "test.db" - mock_db_manager = MagicMock() - mock_db_manager.validate_database.return_value = True - - mock_agent_importer = MagicMock() - duplicate_agents = [MagicMock(agent_id=1), MagicMock(agent_id=1)] - mock_agent_importer.import_agents.return_value = duplicate_agents - - with patch("converter.converter.DatabaseManager", return_value=mock_db_manager), \ - patch("converter.converter.AgentImporter", return_value=mock_agent_importer): - with pytest.raises(ValueError, match="Duplicate agent ID"): - from_agent_farm(str(db_path), config) - - -def test_from_agent_farm_with_corrupted_database(tmp_path, config): - """Test handling of corrupted database.""" - db_path = tmp_path / "corrupted.db" - mock_db_manager = MagicMock() - mock_db_manager.initialize.side_effect = SQLAlchemyError("Database corrupted") - - with patch("converter.converter.DatabaseManager", return_value=mock_db_manager): - with pytest.raises(SQLAlchemyError, match="Database corrupted"): - from_agent_farm(str(db_path), config) - - -def test_from_agent_farm_with_memory_system_error(tmp_path, config): - """Test handling of memory system errors.""" - db_path = tmp_path / "test.db" - mock_db_manager = MagicMock() - mock_db_manager.validate_database.return_value = True - - mock_agent_importer = MagicMock() - mock_agent_importer.import_agents.return_value = [MagicMock(agent_id=1)] - - mock_memory_importer = MagicMock() - mock_memory_importer.import_memories.return_value = [MagicMock(agent_id=1, memory_id=1)] - - with patch("converter.converter.DatabaseManager", return_value=mock_db_manager), \ - patch("converter.converter.AgentImporter", return_value=mock_agent_importer), \ - patch("converter.converter.MemoryImporter", return_value=mock_memory_importer), \ - patch("memory.core.AgentMemorySystem.get_instance", side_effect=Exception("Memory system error")): - with pytest.raises(Exception, match="Memory system error"): - from_agent_farm(str(db_path), config) - - -def test_from_agent_farm_with_custom_memory_config(tmp_path, config): - """Test with custom memory configuration.""" - db_path = tmp_path / "test.db" - config["memory_config"] = { - "use_mock_redis": False, - "logging_level": "DEBUG", - "stm_config": { - "memory_limit": 5000, - "ttl": 43200, - "namespace": "custom-stm" - } - } - - mock_db_manager = MagicMock() - mock_db_manager.validate_database.return_value = True - - mock_agent_importer = MagicMock() - mock_agent_importer.import_agents.return_value = [MagicMock(agent_id=1)] - - mock_memory_importer = MagicMock() - mock_memory_importer.import_memories.return_value = [MagicMock(agent_id=1, memory_id=1)] - - with patch("converter.converter.DatabaseManager", return_value=mock_db_manager), \ - patch("converter.converter.AgentImporter", return_value=mock_agent_importer), \ - patch("converter.converter.MemoryImporter", return_value=mock_memory_importer), \ - patch("memory.core.AgentMemorySystem") as mock_memory_system: - from_agent_farm(str(db_path), config) - # Verify memory system was configured with custom settings - mock_memory_system.get_instance.assert_called_once() - call_args = mock_memory_system.get_instance.call_args[0][0] - assert call_args.use_mock_redis is False - assert call_args.logging_level == "DEBUG" - assert call_args.stm_config.memory_limit == 5000 - - -def test_from_agent_farm_resource_cleanup(tmp_path, config): - """Test proper resource cleanup after import.""" - db_path = tmp_path / "test.db" - mock_db_manager = MagicMock() - mock_db_manager.validate_database.return_value = True - - mock_agent_importer = MagicMock() - mock_agent_importer.import_agents.return_value = [MagicMock(agent_id=1)] - - mock_memory_importer = MagicMock() - mock_memory_importer.import_memories.return_value = [MagicMock(agent_id=1, memory_id=1)] - - with patch("converter.converter.DatabaseManager", return_value=mock_db_manager), \ - patch("converter.converter.AgentImporter", return_value=mock_agent_importer), \ - patch("converter.converter.MemoryImporter", return_value=mock_memory_importer), \ - patch("memory.core.AgentMemorySystem"): - from_agent_farm(str(db_path), config) - # Verify database connection was closed - mock_db_manager.close.assert_called_once() - - -def test_from_agent_farm_cleanup_on_error(tmp_path, config): - """Test resource cleanup when errors occur.""" - db_path = tmp_path / "test.db" - mock_db_manager = MagicMock() - mock_db_manager.initialize.side_effect = Exception("Test error") - - with patch("converter.converter.DatabaseManager", return_value=mock_db_manager): - with pytest.raises(Exception): - from_agent_farm(str(db_path), config) - # Verify cleanup still occurred - mock_db_manager.close.assert_called_once() \ No newline at end of file diff --git a/tests/debug_memory_transitions.py b/tests/debug_memory_transitions.py index 35c94c0..d80e97c 100644 --- a/tests/debug_memory_transitions.py +++ b/tests/debug_memory_transitions.py @@ -7,7 +7,7 @@ from typing import Dict, Any from memory.config import MemoryConfig -from memory.agent_memory import MemoryAgent +from memory.space import MemorySpace # Setup logging logging.basicConfig(level=logging.DEBUG) @@ -45,16 +45,16 @@ def debug_memory_system(): """Run a memory debug session.""" config = MemoryConfig() agent_id = f"debug_agent_{int(time.time())}" - memory_agent = MemoryAgent(agent_id, config) + memory_space = MemorySpace(agent_id, config) logger.info(f"Created debug agent: {agent_id}") # Create and store test memory (STM) test_data = {"position": [10, 20], "health": 0.8, "inventory": ["map", "key"]} - memory_agent.store_state(test_data, 1, 0.5) + memory_space.store_state(test_data, 1, 0.5) # Get the memory from STM to check structure - stm_memories = memory_agent.stm_store.get_all(agent_id) + stm_memories = memory_space.stm_store.get_all(agent_id) if stm_memories: check_memory_content(stm_memories[0], "STM") original_memory_id = stm_memories[0]["memory_id"] @@ -64,11 +64,11 @@ def debug_memory_system(): # Force transition to IM logger.info("Forcing transition to IM...") - memory_agent.config.stm_config.memory_limit = 0 # Force transition - memory_agent._check_memory_transition() + memory_space.config.stm_config.memory_limit = 0 # Force transition + memory_space._check_memory_transition() # Check if memory made it to IM - im_memories = memory_agent.im_store.get_all(agent_id) + im_memories = memory_space.im_store.get_all(agent_id) if im_memories: # Find the same memory for memory in im_memories: @@ -80,11 +80,11 @@ def debug_memory_system(): # Force transition to LTM logger.info("Forcing transition to LTM...") - memory_agent.config.im_config.memory_limit = 0 # Force transition - memory_agent._check_memory_transition() + memory_space.config.im_config.memory_limit = 0 # Force transition + memory_space._check_memory_transition() # Check if memory made it to LTM - ltm_memory = memory_agent.ltm_store.get(original_memory_id) + ltm_memory = memory_space.ltm_store.get(original_memory_id) if ltm_memory: check_memory_content(ltm_memory, "LTM") else: diff --git a/tests/search/test_attribute_strategy.py b/tests/search/test_attribute_strategy.py index 2df0576..40e03b8 100644 --- a/tests/search/test_attribute_strategy.py +++ b/tests/search/test_attribute_strategy.py @@ -19,7 +19,7 @@ def setUp(self): # Create mock agent self.mock_agent = MagicMock() - self.mock_memory_system.get_memory_agent.return_value = self.mock_agent + self.mock_memory_system.get_memory_space.return_value = self.mock_agent # Set up mock stores in the agent self.mock_agent.stm_store = MagicMock() diff --git a/tests/search/test_match_strategy.py b/tests/search/test_match_strategy.py index 12898c0..7c59a9b 100644 --- a/tests/search/test_match_strategy.py +++ b/tests/search/test_match_strategy.py @@ -30,7 +30,7 @@ def setUp(self): self.mock_agent.ltm_store = self.mock_ltm_store # Configure memory system to return mock agent - self.mock_memory_system.get_memory_agent.return_value = self.mock_agent + self.mock_memory_system.get_memory_space.return_value = self.mock_agent # Create strategy with mock memory system self.strategy = ExampleMatchingStrategy(self.mock_memory_system) diff --git a/tests/search/test_similarity_strategy.py b/tests/search/test_similarity_strategy.py index 8f24827..ce33a67 100644 --- a/tests/search/test_similarity_strategy.py +++ b/tests/search/test_similarity_strategy.py @@ -25,13 +25,13 @@ def setUp(self): self.mock_memory_system.config = {} # Create mock memory agent - self.mock_memory_agent = MagicMock() - self.mock_memory_agent.stm_store = self.mock_stm_store - self.mock_memory_agent.im_store = self.mock_im_store - self.mock_memory_agent.ltm_store = self.mock_ltm_store + self.mock_memory_space = MagicMock() + self.mock_memory_space.stm_store = self.mock_stm_store + self.mock_memory_space.im_store = self.mock_im_store + self.mock_memory_space.ltm_store = self.mock_ltm_store # Set up memory system to return mock agent - self.mock_memory_system.get_memory_agent.return_value = self.mock_memory_agent + self.mock_memory_system.get_memory_space.return_value = self.mock_memory_space # Create strategy with mock memory system self.strategy = SimilaritySearchStrategy(self.mock_memory_system) diff --git a/tests/search/test_step_based_strategy.py b/tests/search/test_step_based_strategy.py index 449e7fc..dcdc3ad 100644 --- a/tests/search/test_step_based_strategy.py +++ b/tests/search/test_step_based_strategy.py @@ -22,7 +22,7 @@ def setUp(self): # Create mock memory system self.mock_memory_system = MagicMock() - self.mock_memory_system.get_memory_agent.return_value = self.mock_agent + self.mock_memory_system.get_memory_space.return_value = self.mock_agent # Create strategy with mock memory system self.strategy = StepBasedSearchStrategy(self.mock_memory_system) diff --git a/tests/search/test_temporal_strategy.py b/tests/search/test_temporal_strategy.py index 6b7bf47..0eece99 100644 --- a/tests/search/test_temporal_strategy.py +++ b/tests/search/test_temporal_strategy.py @@ -25,7 +25,7 @@ def setUp(self): # Create mock memory system self.mock_memory_system = MagicMock() - self.mock_memory_system.get_memory_agent.return_value = self.mock_agent + self.mock_memory_system.get_memory_space.return_value = self.mock_agent # Create strategy with mock memory system self.strategy = TemporalSearchStrategy(self.mock_memory_system) @@ -76,7 +76,7 @@ def test_search_with_time_range(self): self.mock_ltm_store.get_all.return_value = [] # Ensure agent is properly configured - self.mock_memory_system.get_memory_agent.return_value = self.mock_agent + self.mock_memory_system.get_memory_space.return_value = self.mock_agent # Define a time range that includes only the two more recent memories start_time = int((self.now - timedelta(days=1)).timestamp()) @@ -107,7 +107,7 @@ def test_search_with_dict_query(self): self.mock_ltm_store.get_all.return_value = [] # Ensure agent is properly configured - self.mock_memory_system.get_memory_agent.return_value = self.mock_agent + self.mock_memory_system.get_memory_space.return_value = self.mock_agent # Define time range in the query query = { @@ -133,7 +133,7 @@ def test_search_with_recency_weight(self): self.mock_ltm_store.get_all.return_value = self.sample_memories # Ensure agent is properly configured - self.mock_memory_system.get_memory_agent.return_value = self.mock_agent + self.mock_memory_system.get_memory_space.return_value = self.mock_agent # Perform search with high recency weight results_high_recency = self.strategy.search( @@ -204,7 +204,7 @@ def test_search_all_tiers(self): self.mock_ltm_store.get_all.return_value = [self.sample_memories[2]] # Ensure agent is properly configured - self.mock_memory_system.get_memory_agent.return_value = self.mock_agent + self.mock_memory_system.get_memory_space.return_value = self.mock_agent # Perform search across all tiers results = self.strategy.search( diff --git a/tests/search/test_window_strategy.py b/tests/search/test_window_strategy.py index 149589c..47d0bf9 100644 --- a/tests/search/test_window_strategy.py +++ b/tests/search/test_window_strategy.py @@ -25,7 +25,7 @@ def setUp(self): # Create mock memory system self.mock_memory_system = MagicMock() - self.mock_memory_system.get_memory_agent.return_value = self.mock_agent + self.mock_memory_system.get_memory_space.return_value = self.mock_agent # Create strategy with mock memory system self.strategy = TimeWindowStrategy(self.mock_memory_system) @@ -71,7 +71,7 @@ def test_search_with_time_range(self): self.mock_stm_store.get_all.return_value = memories # Ensure agent is properly configured - self.mock_memory_system.get_memory_agent.return_value = self.mock_agent + self.mock_memory_system.get_memory_space.return_value = self.mock_agent # Search for memories within the last 2 hours results = self.strategy.search( @@ -122,7 +122,7 @@ def test_search_with_last_n_minutes(self): self.mock_im_store.get_all.return_value = memories # Ensure agent is properly configured - self.mock_memory_system.get_memory_agent.return_value = self.mock_agent + self.mock_memory_system.get_memory_space.return_value = self.mock_agent # Search for memories from the last 20 minutes results = self.strategy.search( @@ -167,7 +167,7 @@ def test_search_with_last_n_hours(self): self.mock_ltm_store.get_all.return_value = memories # Ensure agent is properly configured - self.mock_memory_system.get_memory_agent.return_value = self.mock_agent + self.mock_memory_system.get_memory_space.return_value = self.mock_agent # Search for memories from the last 4 hours results = self.strategy.search( diff --git a/tests/test_agent_memory_system.py b/tests/test_agent_memory_system.py index 8da2828..dbc1fc9 100644 --- a/tests/test_agent_memory_system.py +++ b/tests/test_agent_memory_system.py @@ -27,15 +27,15 @@ import pytest -from memory.agent_memory import MemoryAgent +from memory.space import MemorySpace from memory.config import MemoryConfig from memory.core import AgentMemorySystem @pytest.fixture -def mock_memory_agent(): - """Mock the MemoryAgent class.""" - agent = mock.MagicMock(spec=MemoryAgent) +def mock_memory_space(): + """Mock the MemorySpace class.""" + agent = mock.MagicMock(spec=MemorySpace) agent.store_state.return_value = True agent.store_interaction.return_value = True agent.store_action.return_value = True @@ -75,8 +75,8 @@ def mock_get(memory_id, agent_id=None): @pytest.fixture -def memory_system(mock_memory_agent): - """Create an AgentMemorySystem with mocked MemoryAgent.""" +def memory_system(mock_memory_space): + """Create an AgentMemorySystem with mocked MemorySpace.""" config = MemoryConfig() config.ltm_config.db_path = ( ":memory:" # Use in-memory SQLite to avoid file system issues @@ -85,8 +85,8 @@ def memory_system(mock_memory_agent): # Override singleton instance if it exists AgentMemorySystem._instance = None - # Mock MemoryAgent creation - with mock.patch("memory.core.MemoryAgent", return_value=mock_memory_agent): + # Mock MemorySpace creation + with mock.patch("memory.core.MemorySpace", return_value=mock_memory_space): system = AgentMemorySystem.get_instance(config) return system @@ -165,37 +165,37 @@ def test_get_instance_with_config(self): class TestAgentManagement: """Tests for agent creation and management.""" - def test_get_memory_agent_new(self, memory_system, mock_memory_agent): + def test_get_memory_space_new(self, memory_system, mock_memory_space): """Test getting a new memory agent.""" agent_id = "test-agent-1" assert agent_id not in memory_system.agents - # Mock the MemoryAgent constructor to return a specific agent - with mock.patch("memory.core.MemoryAgent", return_value=mock_memory_agent): - agent = memory_system.get_memory_agent(agent_id) + # Mock the MemorySpace constructor to return a specific agent + with mock.patch("memory.core.MemorySpace", return_value=mock_memory_space): + agent = memory_system.get_memory_space(agent_id) assert agent_id in memory_system.agents assert memory_system.agents[agent_id] is agent - assert agent is mock_memory_agent + assert agent is mock_memory_space - def test_get_memory_agent_existing(self, memory_system, mock_memory_agent): + def test_get_memory_space_existing(self, memory_system, mock_memory_space): """Test getting an existing memory agent.""" agent_id = "test-agent-2" # Add agent to the system - memory_system.agents[agent_id] = mock_memory_agent + memory_system.agents[agent_id] = mock_memory_space - agent = memory_system.get_memory_agent(agent_id) + agent = memory_system.get_memory_space(agent_id) - assert agent is mock_memory_agent + assert agent is mock_memory_space assert len(memory_system.agents) == 1 class TestMemoryStorage: """Tests for memory storage operations.""" - def test_store_agent_state(self, memory_system, mock_memory_agent): + def test_store_agent_state(self, memory_system, mock_memory_space): """Test storing agent state in the default tier.""" agent_id = "test-agent" state_data = {"location": "home", "energy": 100, "mood": "happy"} @@ -203,18 +203,18 @@ def test_store_agent_state(self, memory_system, mock_memory_agent): priority = 0.8 # Add agent to the system - memory_system.agents[agent_id] = mock_memory_agent + memory_system.agents[agent_id] = mock_memory_space result = memory_system.store_agent_state( agent_id, state_data, step_number, priority ) assert result is True - mock_memory_agent.store_state.assert_called_once_with( + mock_memory_space.store_state.assert_called_once_with( state_data, step_number, priority, "stm" ) - def test_store_agent_state_custom_tier(self, memory_system, mock_memory_agent): + def test_store_agent_state_custom_tier(self, memory_system, mock_memory_space): """Test storing agent state in a custom tier.""" agent_id = "test-agent" state_data = {"location": "home", "energy": 100, "mood": "happy"} @@ -223,18 +223,18 @@ def test_store_agent_state_custom_tier(self, memory_system, mock_memory_agent): tier = "ltm" # Add agent to the system - memory_system.agents[agent_id] = mock_memory_agent + memory_system.agents[agent_id] = mock_memory_space result = memory_system.store_agent_state( agent_id, state_data, step_number, priority, tier ) assert result is True - mock_memory_agent.store_state.assert_called_once_with( + mock_memory_space.store_state.assert_called_once_with( state_data, step_number, priority, tier ) - def test_store_agent_interaction(self, memory_system, mock_memory_agent): + def test_store_agent_interaction(self, memory_system, mock_memory_space): """Test storing agent interaction in the default tier.""" agent_id = "test-agent" interaction_data = { @@ -246,19 +246,19 @@ def test_store_agent_interaction(self, memory_system, mock_memory_agent): priority = 0.9 # Add agent to the system - memory_system.agents[agent_id] = mock_memory_agent + memory_system.agents[agent_id] = mock_memory_space result = memory_system.store_agent_interaction( agent_id, interaction_data, step_number, priority ) assert result is True - mock_memory_agent.store_interaction.assert_called_once_with( + mock_memory_space.store_interaction.assert_called_once_with( interaction_data, step_number, priority, "stm" ) def test_store_agent_interaction_custom_tier( - self, memory_system, mock_memory_agent + self, memory_system, mock_memory_space ): """Test storing agent interaction in a custom tier.""" agent_id = "test-agent" @@ -272,18 +272,18 @@ def test_store_agent_interaction_custom_tier( tier = "im" # Add agent to the system - memory_system.agents[agent_id] = mock_memory_agent + memory_system.agents[agent_id] = mock_memory_space result = memory_system.store_agent_interaction( agent_id, interaction_data, step_number, priority, tier ) assert result is True - mock_memory_agent.store_interaction.assert_called_once_with( + mock_memory_space.store_interaction.assert_called_once_with( interaction_data, step_number, priority, tier ) - def test_store_agent_action(self, memory_system, mock_memory_agent): + def test_store_agent_action(self, memory_system, mock_memory_space): """Test storing agent action in the default tier.""" agent_id = "test-agent" action_data = {"action_type": "move", "direction": "north", "speed": "fast"} @@ -291,18 +291,18 @@ def test_store_agent_action(self, memory_system, mock_memory_agent): priority = 0.7 # Add agent to the system - memory_system.agents[agent_id] = mock_memory_agent + memory_system.agents[agent_id] = mock_memory_space result = memory_system.store_agent_action( agent_id, action_data, step_number, priority ) assert result is True - mock_memory_agent.store_action.assert_called_once_with( + mock_memory_space.store_action.assert_called_once_with( action_data, step_number, priority, "stm" ) - def test_store_agent_action_custom_tier(self, memory_system, mock_memory_agent): + def test_store_agent_action_custom_tier(self, memory_system, mock_memory_space): """Test storing agent action in a custom tier.""" agent_id = "test-agent" action_data = {"action_type": "move", "direction": "north", "speed": "fast"} @@ -311,14 +311,14 @@ def test_store_agent_action_custom_tier(self, memory_system, mock_memory_agent): tier = "im" # Add agent to the system - memory_system.agents[agent_id] = mock_memory_agent + memory_system.agents[agent_id] = mock_memory_space result = memory_system.store_agent_action( agent_id, action_data, step_number, priority, tier ) assert result is True - mock_memory_agent.store_action.assert_called_once_with( + mock_memory_space.store_action.assert_called_once_with( action_data, step_number, priority, tier ) @@ -326,7 +326,7 @@ def test_store_agent_action_custom_tier(self, memory_system, mock_memory_agent): class TestMemoryRetrieval: """Tests for memory retrieval operations.""" - def test_retrieve_similar_states(self, memory_system, mock_memory_agent): + def test_retrieve_similar_states(self, memory_system, mock_memory_space): """Test retrieving similar states.""" agent_id = "test-agent" query_state = {"location": "store", "energy": 50} @@ -334,8 +334,8 @@ def test_retrieve_similar_states(self, memory_system, mock_memory_agent): memory_type = "state" # Add agent to the system - memory_system.agents[agent_id] = mock_memory_agent - mock_memory_agent.retrieve_similar_states.return_value = [ + memory_system.agents[agent_id] = mock_memory_space + mock_memory_space.retrieve_similar_states.return_value = [ {"memory_id": "mem1", "contents": {"location": "store", "energy": 60}}, {"memory_id": "mem2", "contents": {"location": "store", "energy": 70}}, ] @@ -346,11 +346,11 @@ def test_retrieve_similar_states(self, memory_system, mock_memory_agent): assert isinstance(result, list) assert len(result) == 2 - mock_memory_agent.retrieve_similar_states.assert_called_once_with( + mock_memory_space.retrieve_similar_states.assert_called_once_with( query_state, k, memory_type, 0.6, None ) - def test_retrieve_by_time_range(self, memory_system, mock_memory_agent): + def test_retrieve_by_time_range(self, memory_system, mock_memory_space): """Test retrieving memories by time range.""" agent_id = "test-agent" start_step = 10 @@ -358,8 +358,8 @@ def test_retrieve_by_time_range(self, memory_system, mock_memory_agent): memory_type = "action" # Add agent to the system - memory_system.agents[agent_id] = mock_memory_agent - mock_memory_agent.retrieve_by_time_range.return_value = [ + memory_system.agents[agent_id] = mock_memory_space + mock_memory_space.retrieve_by_time_range.return_value = [ {"memory_id": "mem1", "step_number": 12}, {"memory_id": "mem2", "step_number": 15}, {"memory_id": "mem3", "step_number": 18}, @@ -371,19 +371,19 @@ def test_retrieve_by_time_range(self, memory_system, mock_memory_agent): assert isinstance(result, list) assert len(result) == 3 - mock_memory_agent.retrieve_by_time_range.assert_called_once_with( + mock_memory_space.retrieve_by_time_range.assert_called_once_with( start_step, end_step, memory_type ) - def test_retrieve_by_attributes(self, memory_system, mock_memory_agent): + def test_retrieve_by_attributes(self, memory_system, mock_memory_space): """Test retrieving memories by attributes.""" agent_id = "test-agent" attributes = {"location": "home", "mood": "happy"} memory_type = "state" # Add agent to the system - memory_system.agents[agent_id] = mock_memory_agent - mock_memory_agent.retrieve_by_attributes.return_value = [ + memory_system.agents[agent_id] = mock_memory_space + mock_memory_space.retrieve_by_attributes.return_value = [ { "memory_id": "mem1", "contents": {"location": "home", "mood": "happy", "energy": 80}, @@ -394,17 +394,17 @@ def test_retrieve_by_attributes(self, memory_system, mock_memory_agent): assert isinstance(result, list) assert len(result) == 1 - mock_memory_agent.retrieve_by_attributes.assert_called_once_with( + mock_memory_space.retrieve_by_attributes.assert_called_once_with( attributes, memory_type ) - def test_get_memory_statistics(self, memory_system, mock_memory_agent): + def test_get_memory_statistics(self, memory_system, mock_memory_space): """Test getting memory statistics.""" agent_id = "test-agent" # Add agent to the system - memory_system.agents[agent_id] = mock_memory_agent - mock_memory_agent.get_memory_statistics.return_value = { + memory_system.agents[agent_id] = mock_memory_space + mock_memory_space.get_memory_statistics.return_value = { "stm_count": 100, "im_count": 500, "ltm_count": 1000, @@ -417,55 +417,55 @@ def test_get_memory_statistics(self, memory_system, mock_memory_agent): assert isinstance(result, dict) assert result["stm_count"] == 100 assert result["total_count"] == 1600 - mock_memory_agent.get_memory_statistics.assert_called_once() + mock_memory_space.get_memory_statistics.assert_called_once() class TestMemoryMaintenance: """Tests for memory maintenance operations.""" def test_force_memory_maintenance_single_agent( - self, memory_system, mock_memory_agent + self, memory_system, mock_memory_space ): """Test forcing memory maintenance for a single agent.""" agent_id = "test-agent" # Add agent to the system - memory_system.agents[agent_id] = mock_memory_agent + memory_system.agents[agent_id] = mock_memory_space result = memory_system.force_memory_maintenance(agent_id) assert result is True - mock_memory_agent.force_maintenance.assert_called_once() + mock_memory_space.force_maintenance.assert_called_once() def test_force_memory_maintenance_all_agents( - self, memory_system, mock_memory_agent + self, memory_system, mock_memory_space ): """Test forcing memory maintenance for all agents.""" # Add multiple agents to the system - memory_system.agents["agent1"] = mock_memory_agent - memory_system.agents["agent2"] = mock.MagicMock(spec=MemoryAgent) + memory_system.agents["agent1"] = mock_memory_space + memory_system.agents["agent2"] = mock.MagicMock(spec=MemorySpace) memory_system.agents["agent2"].force_maintenance.return_value = True result = memory_system.force_memory_maintenance() assert result is True - assert mock_memory_agent.force_maintenance.call_count == 1 + assert mock_memory_space.force_maintenance.call_count == 1 memory_system.agents["agent2"].force_maintenance.assert_called_once() - def test_force_memory_maintenance_failure(self, memory_system, mock_memory_agent): + def test_force_memory_maintenance_failure(self, memory_system, mock_memory_space): """Test forcing memory maintenance with a failure.""" # Add multiple agents to the system - memory_system.agents["agent1"] = mock_memory_agent - memory_system.agents["agent2"] = mock.MagicMock(spec=MemoryAgent) + memory_system.agents["agent1"] = mock_memory_space + memory_system.agents["agent2"] = mock.MagicMock(spec=MemorySpace) memory_system.agents["agent2"].force_maintenance.return_value = False result = memory_system.force_memory_maintenance() assert result is False - assert mock_memory_agent.force_maintenance.call_count == 1 + assert mock_memory_space.force_maintenance.call_count == 1 memory_system.agents["agent2"].force_maintenance.assert_called_once() - def test_search_by_embedding(self, memory_system, mock_memory_agent): + def test_search_by_embedding(self, memory_system, mock_memory_space): """Test searching by embedding vector.""" agent_id = "test-agent" embedding = [0.1, 0.2, 0.3, 0.4] @@ -473,8 +473,8 @@ def test_search_by_embedding(self, memory_system, mock_memory_agent): memory_tiers = ["stm", "im"] # Add agent to the system - memory_system.agents[agent_id] = mock_memory_agent - mock_memory_agent.search_by_embedding.return_value = [ + memory_system.agents[agent_id] = mock_memory_space + mock_memory_space.search_by_embedding.return_value = [ {"memory_id": "mem1", "similarity": 0.95}, {"memory_id": "mem2", "similarity": 0.85}, {"memory_id": "mem3", "similarity": 0.75}, @@ -484,19 +484,19 @@ def test_search_by_embedding(self, memory_system, mock_memory_agent): assert isinstance(result, list) assert len(result) == 3 - mock_memory_agent.search_by_embedding.assert_called_once_with( + mock_memory_space.search_by_embedding.assert_called_once_with( embedding, k, memory_tiers ) - def test_search_by_content(self, memory_system, mock_memory_agent): + def test_search_by_content(self, memory_system, mock_memory_space): """Test searching by content.""" agent_id = "test-agent" content_query = "find memories about the store" k = 5 # Add agent to the system - memory_system.agents[agent_id] = mock_memory_agent - mock_memory_agent.search_by_content.return_value = [ + memory_system.agents[agent_id] = mock_memory_space + mock_memory_space.search_by_content.return_value = [ {"memory_id": "mem1", "relevance": 0.92}, {"memory_id": "mem2", "relevance": 0.85}, ] @@ -505,13 +505,13 @@ def test_search_by_content(self, memory_system, mock_memory_agent): assert isinstance(result, list) assert len(result) == 2 - mock_memory_agent.search_by_content.assert_called_once_with(content_query, k) + mock_memory_space.search_by_content.assert_called_once_with(content_query, k) - def test_clear_all_memories(self, memory_system, mock_memory_agent): + def test_clear_all_memories(self, memory_system, mock_memory_space): """Test clearing all memories for all agents.""" # Add multiple agents to the system - memory_system.agents["agent1"] = mock_memory_agent - mock_agent2 = mock.MagicMock(spec=MemoryAgent) + memory_system.agents["agent1"] = mock_memory_space + mock_agent2 = mock.MagicMock(spec=MemorySpace) mock_agent2.clear_memory.return_value = True memory_system.agents["agent2"] = mock_agent2 @@ -526,11 +526,11 @@ def test_clear_all_memories(self, memory_system, mock_memory_agent): agent2_mock.clear_memory.assert_called_once() assert len(memory_system.agents) == 0 - def test_clear_all_memories_failure(self, memory_system, mock_memory_agent): + def test_clear_all_memories_failure(self, memory_system, mock_memory_space): """Test clearing all memories with a failure.""" # Add multiple agents to the system - memory_system.agents["agent1"] = mock_memory_agent - mock_agent2 = mock.MagicMock(spec=MemoryAgent) + memory_system.agents["agent1"] = mock_memory_space + mock_agent2 = mock.MagicMock(spec=MemorySpace) mock_agent2.clear_memory.return_value = False memory_system.agents["agent2"] = mock_agent2 @@ -549,7 +549,7 @@ def test_clear_all_memories_failure(self, memory_system, mock_memory_agent): class TestMemoryHooks: """Tests for memory hook mechanism.""" - def test_register_memory_hook(self, memory_system, mock_memory_agent): + def test_register_memory_hook(self, memory_system, mock_memory_space): """Test registering a memory hook.""" agent_id = "test-agent" event_type = "memory_created" @@ -559,19 +559,19 @@ def hook_function(event_data, agent): return True # Add agent to the system - memory_system.agents[agent_id] = mock_memory_agent - mock_memory_agent.register_hook.return_value = True + memory_system.agents[agent_id] = mock_memory_space + mock_memory_space.register_hook.return_value = True result = memory_system.register_memory_hook( agent_id, event_type, hook_function, priority ) assert result is True - mock_memory_agent.register_hook.assert_called_once_with( + mock_memory_space.register_hook.assert_called_once_with( event_type, hook_function, priority ) - def test_register_memory_hook_disabled(self, memory_system, mock_memory_agent): + def test_register_memory_hook_disabled(self, memory_system, mock_memory_space): """Test registering a memory hook when hooks are disabled.""" agent_id = "test-agent" event_type = "memory_created" @@ -584,31 +584,31 @@ def hook_function(event_data, agent): memory_system.config.enable_memory_hooks = False # Add agent to the system - memory_system.agents[agent_id] = mock_memory_agent + memory_system.agents[agent_id] = mock_memory_space result = memory_system.register_memory_hook( agent_id, event_type, hook_function, priority ) assert result is False - mock_memory_agent.register_hook.assert_not_called() + mock_memory_space.register_hook.assert_not_called() - def test_trigger_memory_event(self, memory_system, mock_memory_agent): + def test_trigger_memory_event(self, memory_system, mock_memory_space): """Test triggering a memory event.""" agent_id = "test-agent" event_type = "memory_accessed" event_data = {"memory_id": "mem1", "access_time": 1234567890} # Add agent to the system - memory_system.agents[agent_id] = mock_memory_agent - mock_memory_agent.trigger_event.return_value = True + memory_system.agents[agent_id] = mock_memory_space + mock_memory_space.trigger_event.return_value = True result = memory_system.trigger_memory_event(agent_id, event_type, event_data) assert result is True - mock_memory_agent.trigger_event.assert_called_once_with(event_type, event_data) + mock_memory_space.trigger_event.assert_called_once_with(event_type, event_data) - def test_trigger_memory_event_disabled(self, memory_system, mock_memory_agent): + def test_trigger_memory_event_disabled(self, memory_system, mock_memory_space): """Test triggering a memory event when hooks are disabled.""" agent_id = "test-agent" event_type = "memory_accessed" @@ -618,12 +618,12 @@ def test_trigger_memory_event_disabled(self, memory_system, mock_memory_agent): memory_system.config.enable_memory_hooks = False # Add agent to the system - memory_system.agents[agent_id] = mock_memory_agent + memory_system.agents[agent_id] = mock_memory_space result = memory_system.trigger_memory_event(agent_id, event_type, event_data) assert result is False - mock_memory_agent.trigger_event.assert_not_called() + mock_memory_space.trigger_event.assert_not_called() def test_add_memory(memory_system, sample_memory): diff --git a/tests/test_load_from_json.py b/tests/test_load_from_json.py index f48503a..bff1f7a 100644 --- a/tests/test_load_from_json.py +++ b/tests/test_load_from_json.py @@ -77,7 +77,7 @@ def test_load_attribute_validation_memory(cleanup_memory_system): # Verify the agent was created assert "test-agent-attribute-search" in memory_system.agents, "Expected agent not found" - agent = memory_system.get_memory_agent("test-agent-attribute-search") + agent = memory_system.get_memory_space("test-agent-attribute-search") # Get all memories to check content attributes stm_memories = agent.stm_store.get_all("test-agent-attribute-search") @@ -110,7 +110,7 @@ def test_memory_content_preservation(cleanup_memory_system): assert memory_system is not None # Get the agent - agent = memory_system.get_memory_agent("test-agent-attribute-search") + agent = memory_system.get_memory_space("test-agent-attribute-search") # Get all memories stm_memories = agent.stm_store.get_all("test-agent-attribute-search") diff --git a/tests/test_save_to_json.py b/tests/test_save_to_json.py index 5db1dfe..ebe8a17 100644 --- a/tests/test_save_to_json.py +++ b/tests/test_save_to_json.py @@ -88,7 +88,7 @@ def test_save_memory_system_with_agent(cleanup_memory_system): # Create an agent and add some memories agent_id = "test_agent" - memory_agent = memory_system.get_memory_agent(agent_id) + memory_space = memory_system.get_memory_space(agent_id) logger.info(f"Created memory agent with ID: {agent_id}") # Add state memory @@ -111,7 +111,7 @@ def test_save_memory_system_with_agent(cleanup_memory_system): # Check if memories were stored try: - stm_memories = memory_agent.stm_store.get_all(agent_id) + stm_memories = memory_space.stm_store.get_all(agent_id) logger.info(f"STM memories count: {len(stm_memories)}") if stm_memories: logger.info(f"First STM memory keys: {stm_memories[0].keys()}") @@ -227,7 +227,7 @@ def test_save_and_load_roundtrip(cleanup_memory_system): # Create an agent and add some memories agent_id = "test_agent" - memory_agent = original_system.get_memory_agent(agent_id) + memory_space = original_system.get_memory_space(agent_id) # Add state memory with some content to check after reload test_content = {"name": "Test Agent", "status": "active", "data": {"key1": "value1", "key2": 42}} @@ -243,7 +243,7 @@ def test_save_and_load_roundtrip(cleanup_memory_system): # Verify the memory was stored with the correct type try: - stm_memories = memory_agent.stm_store.get_all(agent_id) + stm_memories = memory_space.stm_store.get_all(agent_id) logger.info(f"Before save: STM memories count: {len(stm_memories)}") for i, mem in enumerate(stm_memories): logger.info(f"Memory {i} type: {mem.get('type')}") @@ -293,7 +293,7 @@ def test_save_and_load_roundtrip(cleanup_memory_system): assert agent_id in loaded_system.agents, f"Agent {agent_id} not found in loaded system" # Get all memories for the agent - loaded_agent = loaded_system.get_memory_agent(agent_id) + loaded_agent = loaded_system.get_memory_space(agent_id) stm_memories = loaded_agent.stm_store.get_all(agent_id) im_memories = loaded_agent.im_store.get_all(agent_id) ltm_memories = loaded_agent.ltm_store.get_all(agent_id) @@ -369,7 +369,7 @@ def test_save_with_complex_memory_content(cleanup_memory_system): # Create an agent agent_id = "test_agent" - memory_agent = memory_system.get_memory_agent(agent_id) + memory_space = memory_system.get_memory_space(agent_id) # Add state memory with complex nested content complex_content = { diff --git a/tests/test_memory_agent.py b/tests/test_space.py similarity index 75% rename from tests/test_memory_agent.py rename to tests/test_space.py index cfa3307..e465f3b 100644 --- a/tests/test_memory_agent.py +++ b/tests/test_space.py @@ -1,20 +1,20 @@ -"""Unit tests for the Memory Agent module. +"""Unit tests for the Memory Space module. -This test suite covers the functionality of the MemoryAgent class, which manages +This test suite covers the functionality of the MemorySpace class, which manages hierarchical memory storage across short-term (STM), intermediate (IM), and long-term memory (LTM) tiers. -The tests use pytest fixtures and mocks to isolate the MemoryAgent from its +The tests use pytest fixtures and mocks to isolate the MemorySpace from its dependencies, allowing focused testing of the agent's logic. To run these tests: - pytest tests/test_memory_agent.py + pytest tests/test_memory_space.py To run with coverage: - pytest tests/test_memory_agent.py --cov=memory + pytest tests/test_memory_space.py --cov=memory Test categories: -- TestMemoryAgentBasics: Tests for initialization and configuration +- TestMemorySpaceBasics: Tests for initialization and configuration - TestMemoryStorage: Tests for memory storage operations - TestMemoryTransitions: Tests for memory movement between tiers - TestMemoryRetrieval: Tests for memory retrieval operations @@ -27,8 +27,8 @@ import pytest -from memory.agent_memory import MemoryAgent from memory.config import MemoryConfig +from memory.space import MemorySpace @pytest.fixture @@ -40,6 +40,11 @@ def mock_stm_store(): store.get_all.return_value = [] store.get_size.return_value = 1000 store.clear.return_value = True + store.search_similar.return_value = [] + store.search_by_step_range.return_value = [] + store.search_by_attributes.return_value = [] + store.search_by_embedding.return_value = [] + store.search_by_content.return_value = [] return store @@ -52,6 +57,11 @@ def mock_im_store(): store.get_all.return_value = [] store.get_size.return_value = 1000 store.clear.return_value = True + store.search_similar.return_value = [] + store.search_by_step_range.return_value = [] + store.search_by_attributes.return_value = [] + store.search_by_embedding.return_value = [] + store.search_by_content.return_value = [] return store @@ -64,6 +74,11 @@ def mock_ltm_store(): store.get_all.return_value = [] store.get_size.return_value = 1000 store.clear.return_value = True + store.search_similar.return_value = [] + store.search_by_step_range.return_value = [] + store.search_by_attributes.return_value = [] + store.search_by_embedding.return_value = [] + store.search_by_content.return_value = [] return store @@ -87,7 +102,7 @@ def mock_embedding_engine(): @pytest.fixture -def memory_agent( +def memory_space( mock_stm_store, mock_im_store, mock_ltm_store, @@ -103,24 +118,22 @@ def memory_agent( ) config.ltm_config.db_path = "test_memory.db" # Set a valid db path - with mock.patch("memory.agent_memory.RedisSTMStore") as mock_stm, mock.patch( - "memory.agent_memory.RedisIMStore" - ) as mock_im, mock.patch( - "memory.agent_memory.SQLiteLTMStore" - ) as mock_ltm, mock.patch( - "memory.agent_memory.CompressionEngine" - ) as mock_ce, mock.patch( - "memory.agent_memory.TextEmbeddingEngine" - ) as mock_ae: - - # Configure the mock classes to return our mock instances - mock_stm.return_value = mock_stm_store - mock_im.return_value = mock_im_store - mock_ltm.return_value = mock_ltm_store + with mock.patch("memory.space.RedisSTMStore", return_value=mock_stm_store), mock.patch( + "memory.space.RedisIMStore", return_value=mock_im_store + ), mock.patch( + "memory.space.SQLiteLTMStore", return_value=mock_ltm_store + ), mock.patch( + "memory.space.CompressionEngine", return_value=mock_compression_engine + ), mock.patch( + "memory.space.TextEmbeddingEngine", return_value=mock_embedding_engine + ): - agent = MemoryAgent(agent_id, config) + agent = MemorySpace(agent_id, config) - # No need to replace stores as they are already our mocks + # Ensure the mock stores are properly set + agent.stm_store = mock_stm_store + agent.im_store = mock_im_store + agent.ltm_store = mock_ltm_store agent.compression_engine = mock_compression_engine agent.embedding_engine = mock_embedding_engine @@ -128,8 +141,8 @@ def memory_agent( # Base test cases follow -class TestMemoryAgentBasics: - """Basic tests for Memory Agent initialization and configuration.""" +class TestMemorySpaceBasics: + """Basic tests for Memory Space initialization and configuration.""" def test_init(self): """Test memory agent initialization.""" @@ -141,17 +154,17 @@ def test_init(self): ) config.ltm_config.db_path = "test_memory.db" # Set a valid db path - with mock.patch("memory.agent_memory.RedisSTMStore") as mock_stm, mock.patch( - "memory.agent_memory.RedisIMStore" + with mock.patch("memory.space.RedisSTMStore") as mock_stm, mock.patch( + "memory.space.RedisIMStore" ) as mock_im, mock.patch( - "memory.agent_memory.SQLiteLTMStore" + "memory.space.SQLiteLTMStore" ) as mock_ltm, mock.patch( - "memory.agent_memory.CompressionEngine" + "memory.space.CompressionEngine" ) as mock_ce, mock.patch( - "memory.agent_memory.TextEmbeddingEngine" + "memory.space.TextEmbeddingEngine" ) as mock_ae: - agent = MemoryAgent(agent_id, config) + agent = MemorySpace(agent_id, config) # Verify stores were initialized mock_stm.assert_called_once_with(config.stm_config) @@ -170,15 +183,15 @@ def test_init_without_neural_embeddings(self): config.use_embedding_engine = False config.ltm_config.db_path = "test_memory.db" # Set a valid db path - with mock.patch("memory.agent_memory.RedisSTMStore"), mock.patch( - "memory.agent_memory.RedisIMStore" - ), mock.patch("memory.agent_memory.SQLiteLTMStore"), mock.patch( - "memory.agent_memory.CompressionEngine" + with mock.patch("memory.space.RedisSTMStore"), mock.patch( + "memory.space.RedisIMStore" + ), mock.patch("memory.space.SQLiteLTMStore"), mock.patch( + "memory.space.CompressionEngine" ), mock.patch( - "memory.agent_memory.TextEmbeddingEngine" + "memory.space.TextEmbeddingEngine" ) as mock_te: - agent = MemoryAgent(agent_id, config) + agent = MemorySpace(agent_id, config) assert agent.embedding_engine is None mock_te.assert_not_called() @@ -186,17 +199,17 @@ def test_init_without_neural_embeddings(self): class TestMemoryStorage: """Tests for memory storage operations.""" - def test_store_state(self, memory_agent, mock_stm_store): + def test_store_state(self, memory_space, mock_stm_store): """Test storing a state memory in the default tier (STM).""" state_data = {"position": [1, 2, 3], "inventory": ["sword", "shield"]} step_number = 42 priority = 0.8 # Patch the _create_memory_entry method - with mock.patch.object(memory_agent, "_create_memory_entry") as mock_create: + with mock.patch.object(memory_space, "_create_memory_entry") as mock_create: mock_create.return_value = {"memory_id": "test-memory-1"} - result = memory_agent.store_state(state_data, step_number, priority) + result = memory_space.store_state(state_data, step_number, priority) # Check the _create_memory_entry call mock_create.assert_called_once_with( @@ -205,13 +218,13 @@ def test_store_state(self, memory_agent, mock_stm_store): # Check the store call mock_stm_store.store.assert_called_once_with( - memory_agent.agent_id, {"memory_id": "test-memory-1"} + memory_space.agent_id, {"memory_id": "test-memory-1"} ) assert result is True - assert memory_agent._insert_count == 1 + assert memory_space._insert_count == 1 - def test_store_state_custom_tier(self, memory_agent, mock_im_store, mock_ltm_store): + def test_store_state_custom_tier(self, memory_space, mock_im_store, mock_ltm_store): """Test storing a state memory in a custom tier.""" state_data = {"position": [1, 2, 3], "inventory": ["sword", "shield"]} step_number = 42 @@ -222,10 +235,10 @@ def test_store_state_custom_tier(self, memory_agent, mock_im_store, mock_ltm_sto mock_ltm_store.store.return_value = True # Test storing in IM tier - with mock.patch.object(memory_agent, "_create_memory_entry") as mock_create: + with mock.patch.object(memory_space, "_create_memory_entry") as mock_create: mock_create.return_value = {"memory_id": "test-memory-im"} - result = memory_agent.store_state( + result = memory_space.store_state( state_data, step_number, priority, tier="im" ) @@ -236,16 +249,16 @@ def test_store_state_custom_tier(self, memory_agent, mock_im_store, mock_ltm_sto # Check the store call to IM store mock_im_store.store.assert_called_once_with( - memory_agent.agent_id, {"memory_id": "test-memory-im"} + memory_space.agent_id, {"memory_id": "test-memory-im"} ) assert result is True # Test storing in LTM tier - with mock.patch.object(memory_agent, "_create_memory_entry") as mock_create: + with mock.patch.object(memory_space, "_create_memory_entry") as mock_create: mock_create.return_value = {"memory_id": "test-memory-ltm"} - result = memory_agent.store_state( + result = memory_space.store_state( state_data, step_number, priority, tier="ltm" ) @@ -261,17 +274,17 @@ def test_store_state_custom_tier(self, memory_agent, mock_im_store, mock_ltm_sto assert result is True - def test_store_interaction(self, memory_agent, mock_stm_store): + def test_store_interaction(self, memory_space, mock_stm_store): """Test storing an interaction memory.""" interaction_data = {"agent": "agent1", "target": "agent2", "action": "greet"} step_number = 42 priority = 0.5 # Patch the _create_memory_entry method - with mock.patch.object(memory_agent, "_create_memory_entry") as mock_create: + with mock.patch.object(memory_space, "_create_memory_entry") as mock_create: mock_create.return_value = {"memory_id": "test-memory-2"} - result = memory_agent.store_interaction( + result = memory_space.store_interaction( interaction_data, step_number, priority ) @@ -282,13 +295,13 @@ def test_store_interaction(self, memory_agent, mock_stm_store): # Check the store call mock_stm_store.store.assert_called_once_with( - memory_agent.agent_id, {"memory_id": "test-memory-2"} + memory_space.agent_id, {"memory_id": "test-memory-2"} ) assert result is True - assert memory_agent._insert_count == 1 + assert memory_space._insert_count == 1 - def test_store_interaction_custom_tier(self, memory_agent, mock_im_store): + def test_store_interaction_custom_tier(self, memory_space, mock_im_store): """Test storing an interaction memory in a custom tier.""" interaction_data = {"agent": "agent1", "target": "agent2", "action": "greet"} step_number = 42 @@ -296,10 +309,10 @@ def test_store_interaction_custom_tier(self, memory_agent, mock_im_store): tier = "im" # Patch the _create_memory_entry method - with mock.patch.object(memory_agent, "_create_memory_entry") as mock_create: + with mock.patch.object(memory_space, "_create_memory_entry") as mock_create: mock_create.return_value = {"memory_id": "test-memory-2-im"} - result = memory_agent.store_interaction( + result = memory_space.store_interaction( interaction_data, step_number, priority, tier ) @@ -310,23 +323,23 @@ def test_store_interaction_custom_tier(self, memory_agent, mock_im_store): # Check the store call mock_im_store.store.assert_called_once_with( - memory_agent.agent_id, {"memory_id": "test-memory-2-im"} + memory_space.agent_id, {"memory_id": "test-memory-2-im"} ) assert result is True - assert memory_agent._insert_count == 1 + assert memory_space._insert_count == 1 - def test_store_action(self, memory_agent, mock_stm_store): + def test_store_action(self, memory_space, mock_stm_store): """Test storing an action memory.""" action_data = {"action_type": "move", "direction": "north", "result": "success"} step_number = 42 priority = 0.7 # Patch the _create_memory_entry method - with mock.patch.object(memory_agent, "_create_memory_entry") as mock_create: + with mock.patch.object(memory_space, "_create_memory_entry") as mock_create: mock_create.return_value = {"memory_id": "test-memory-3"} - result = memory_agent.store_action(action_data, step_number, priority) + result = memory_space.store_action(action_data, step_number, priority) # Check the _create_memory_entry call mock_create.assert_called_once_with( @@ -335,13 +348,13 @@ def test_store_action(self, memory_agent, mock_stm_store): # Check the store call mock_stm_store.store.assert_called_once_with( - memory_agent.agent_id, {"memory_id": "test-memory-3"} + memory_space.agent_id, {"memory_id": "test-memory-3"} ) assert result is True - assert memory_agent._insert_count == 1 + assert memory_space._insert_count == 1 - def test_store_action_custom_tier(self, memory_agent, mock_ltm_store): + def test_store_action_custom_tier(self, memory_space, mock_ltm_store): """Test storing an action memory in a custom tier.""" action_data = {"action_type": "move", "direction": "north", "result": "success"} step_number = 42 @@ -352,10 +365,10 @@ def test_store_action_custom_tier(self, memory_agent, mock_ltm_store): mock_ltm_store.store.return_value = True # Patch the _create_memory_entry method - with mock.patch.object(memory_agent, "_create_memory_entry") as mock_create: + with mock.patch.object(memory_space, "_create_memory_entry") as mock_create: mock_create.return_value = {"memory_id": "test-memory-3-ltm"} - result = memory_agent.store_action(action_data, step_number, priority, tier) + result = memory_space.store_action(action_data, step_number, priority, tier) # Check the _create_memory_entry call mock_create.assert_called_once_with( @@ -370,7 +383,7 @@ def test_store_action_custom_tier(self, memory_agent, mock_ltm_store): assert result is True def test_store_in_tier( - self, memory_agent, mock_stm_store, mock_im_store, mock_ltm_store + self, memory_space, mock_stm_store, mock_im_store, mock_ltm_store ): """Test the _store_in_tier method for different tiers.""" memory_entry = {"memory_id": "test-memory-tier", "content": {"test": "data"}} @@ -381,47 +394,47 @@ def test_store_in_tier( mock_ltm_store.store.return_value = True # Test storing in STM - result_stm = memory_agent._store_in_tier("stm", memory_entry) - mock_stm_store.store.assert_called_with(memory_agent.agent_id, memory_entry) + result_stm = memory_space._store_in_tier("stm", memory_entry) + mock_stm_store.store.assert_called_with(memory_space.agent_id, memory_entry) assert result_stm is True # Test storing in IM - result_im = memory_agent._store_in_tier("im", memory_entry) - mock_im_store.store.assert_called_with(memory_agent.agent_id, memory_entry) + result_im = memory_space._store_in_tier("im", memory_entry) + mock_im_store.store.assert_called_with(memory_space.agent_id, memory_entry) assert result_im is True # Test storing in LTM - result_ltm = memory_agent._store_in_tier("ltm", memory_entry) + result_ltm = memory_space._store_in_tier("ltm", memory_entry) mock_ltm_store.store.assert_called_with(memory_entry) assert result_ltm is True # Test invalid tier - with mock.patch("memory.agent_memory.logger.warning") as mock_logger: - result_invalid = memory_agent._store_in_tier("invalid_tier", memory_entry) + with mock.patch("memory.space.logger.warning") as mock_logger: + result_invalid = memory_space._store_in_tier("invalid_tier", memory_entry) mock_logger.assert_called_once() - mock_stm_store.store.assert_called_with(memory_agent.agent_id, memory_entry) + mock_stm_store.store.assert_called_with(memory_space.agent_id, memory_entry) assert result_invalid is True - def test_cleanup_triggered(self, memory_agent): + def test_cleanup_triggered(self, memory_space): """Test that cleanup is triggered after multiple insertions.""" - memory_agent.config.cleanup_interval = 5 - memory_agent._insert_count = 0 + memory_space.config.cleanup_interval = 5 + memory_space._insert_count = 0 # Patch _check_memory_transition - with mock.patch.object(memory_agent, "_check_memory_transition") as mock_check: + with mock.patch.object(memory_space, "_check_memory_transition") as mock_check: # Do 5 insertions for i in range(5): with mock.patch.object( - memory_agent, "_create_memory_entry" + memory_space, "_create_memory_entry" ) as mock_create: mock_create.return_value = {"memory_id": f"test-memory-{i}"} - memory_agent.store_state({"test": i}, i, 0.5) + memory_space.store_state({"test": i}, i, 0.5) # Verify _check_memory_transition was called once mock_check.assert_called_once() - assert memory_agent._insert_count == 5 + assert memory_space._insert_count == 5 - def test_create_memory_entry(self, memory_agent, mock_embedding_engine): + def test_create_memory_entry(self, memory_space, mock_embedding_engine): """Test memory entry creation with default tier.""" test_data = {"test": "data"} step_number = 42 @@ -430,16 +443,16 @@ def test_create_memory_entry(self, memory_agent, mock_embedding_engine): # Mock time.time() with mock.patch("time.time", return_value=12345): - entry = memory_agent._create_memory_entry( + entry = memory_space._create_memory_entry( test_data, step_number, memory_type, priority ) # Check structure assert ( entry["memory_id"] - == f"{memory_type}_{memory_agent.agent_id}_{step_number}" + == f"{memory_type}_{memory_space.agent_id}_{step_number}" ) - assert entry["agent_id"] == memory_agent.agent_id + assert entry["agent_id"] == memory_space.agent_id assert entry["step_number"] == step_number assert entry["timestamp"] == 12345 assert entry["content"] == test_data @@ -463,7 +476,7 @@ def test_create_memory_entry(self, memory_agent, mock_embedding_engine): mock_embedding_engine.encode_ltm.assert_called_once_with(test_data) def test_create_memory_entry_with_tier( - self, memory_agent, mock_embedding_engine, mock_compression_engine + self, memory_space, mock_embedding_engine, mock_compression_engine ): """Test memory entry creation with different tiers and compression.""" test_data = {"test": "data"} @@ -473,7 +486,7 @@ def test_create_memory_entry_with_tier( # Test IM tier with mock.patch("time.time", return_value=12345): - entry_im = memory_agent._create_memory_entry( + entry_im = memory_space._create_memory_entry( test_data, step_number, memory_type, priority, tier="im" ) @@ -486,7 +499,7 @@ def test_create_memory_entry_with_tier( # Test LTM tier with mock.patch("time.time", return_value=12346): - entry_ltm = memory_agent._create_memory_entry( + entry_ltm = memory_space._create_memory_entry( test_data, step_number, memory_type, priority, tier="ltm" ) @@ -502,11 +515,11 @@ class TestMemoryTransitions: """Tests for memory transitions between tiers.""" def test_check_memory_transition_stm_to_im( - self, memory_agent, mock_stm_store, mock_im_store + self, memory_space, mock_stm_store, mock_im_store ): """Test transitioning memories from STM to IM when STM is at capacity.""" # Configure mocks - memory_agent.config.stm_config.memory_limit = 5 + memory_space.config.stm_config.memory_limit = 5 mock_stm_store.count.return_value = 10 # Over capacity # Create sample memories in STM @@ -536,21 +549,21 @@ def mock_compress_func(memory, level): ].copy(), # Create a copy to detect changes } - memory_agent.compression_engine.compress.side_effect = mock_compress_func + memory_space.compression_engine.compress.side_effect = mock_compress_func # Call the transition method with mock.patch.object( - memory_agent, + memory_space, "_calculate_importance", side_effect=lambda m: m["metadata"]["importance_score"], ): - memory_agent._check_memory_transition() + memory_space._check_memory_transition() # Check that IM store was called with compressed memories assert mock_im_store.store.call_count == 5 # Should transition 5 memories # Verify the compression engine was used - assert memory_agent.compression_engine.compress.call_count == 5 + assert memory_space.compression_engine.compress.call_count == 5 # Verify current_tier was updated in the metadata for call in mock_im_store.store.call_args_list: @@ -562,12 +575,12 @@ def mock_compress_func(memory, level): assert mock_stm_store.delete.call_count == 5 def test_check_memory_transition_im_to_ltm( - self, memory_agent, mock_im_store, mock_ltm_store, mock_stm_store + self, memory_space, mock_im_store, mock_ltm_store, mock_stm_store ): """Test transitioning memories from IM to LTM when IM is at capacity.""" # Configure mocks - memory_agent.config.im_config.memory_limit = 5 - memory_agent.config.ltm_config.batch_size = 3 + memory_space.config.im_config.memory_limit = 5 + memory_space.config.ltm_config.batch_size = 3 mock_stm_store.count.return_value = 3 # Under capacity mock_im_store.count.return_value = 8 # Over capacity @@ -598,15 +611,15 @@ def mock_compress_func(memory, level): ].copy(), # Create a copy to detect changes } - memory_agent.compression_engine.compress.side_effect = mock_compress_func + memory_space.compression_engine.compress.side_effect = mock_compress_func # Call the transition method with mock.patch.object( - memory_agent, + memory_space, "_calculate_importance", side_effect=lambda m: m["metadata"]["importance_score"], ): - memory_agent._check_memory_transition() + memory_space._check_memory_transition() # Check that LTM store was called with batches # Should be 1 call with 3 memories, plus 1 more call with remaining 0 memories @@ -615,7 +628,7 @@ def mock_compress_func(memory, level): assert len(calls[0][0][0]) == 3 # First batch has 3 items # Verify the compression engine was used - assert memory_agent.compression_engine.compress.call_count == 3 + assert memory_space.compression_engine.compress.call_count == 3 # Verify current_tier was updated in the metadata batch = calls[0][0][0] # Get the batch of memories @@ -625,7 +638,7 @@ def mock_compress_func(memory, level): # Verify memories were deleted from IM assert mock_im_store.delete.call_count == 3 - def test_calculate_importance(self, memory_agent): + def test_calculate_importance(self, memory_space): """Test importance calculation logic.""" # Create a test memory with relevant fields current_time = time.time() @@ -638,7 +651,7 @@ def test_calculate_importance(self, memory_agent): }, } - importance = memory_agent._calculate_importance(memory) + importance = memory_space._calculate_importance(memory) # Verify importance calculation components and bounds assert 0.0 <= importance <= 1.0 @@ -653,7 +666,7 @@ def test_calculate_importance(self, memory_agent): }, } - high_reward_importance = memory_agent._calculate_importance(memory_high_reward) + high_reward_importance = memory_space._calculate_importance(memory_high_reward) # Should have full reward component (40%) and full recency component (20%) assert high_reward_importance == pytest.approx(0.6, abs=0.01) @@ -668,7 +681,7 @@ def test_calculate_importance(self, memory_agent): }, } - high_retrieval_importance = memory_agent._calculate_importance( + high_retrieval_importance = memory_space._calculate_importance( memory_high_retrieval ) # Should have full retrieval component (30%) and full recency component (20%) @@ -678,49 +691,8 @@ def test_calculate_importance(self, memory_agent): class TestMemoryRetrieval: """Tests for memory retrieval operations.""" - # def test_retrieve_similar_states(self, memory_agent, mock_stm_store, mock_im_store, mock_ltm_store): - # """Test retrieving similar states across memory tiers.""" - # # Configure the mock stores to return results - # stm_results = [{"memory_id": "stm1", "similarity_score": 0.9}, - # {"memory_id": "stm2", "similarity_score": 0.8}] - # im_results = [{"memory_id": "im1", "similarity_score": 0.7}] - # ltm_results = [{"memory_id": "ltm1", "similarity_score": 0.6}, - # {"memory_id": "ltm2", "similarity_score": 0.5}] - - # mock_stm_store.search_similar.return_value = stm_results - # mock_im_store.search_similar.return_value = im_results - # mock_ltm_store.search_similar.return_value = ltm_results - - # # Mock the embedding engine - # query_state = {"position": [1, 2, 3]} - - # # Set k=5 to ensure we search all tiers - # results = memory_agent.retrieve_similar_states(query_state, k=5) - - # # Should return top 5 results from all stores combined, sorted by similarity - # assert len(results) == 5 - # assert results[0]["memory_id"] == "stm1" # Highest similarity - # assert results[1]["memory_id"] == "stm2" - # assert results[2]["memory_id"] == "im1" - # assert results[3]["memory_id"] == "ltm1" - # assert results[4]["memory_id"] == "ltm2" # Lowest similarity - - # # Verify embedding engine calls - # memory_agent.embedding_engine.encode_stm.assert_called_with(query_state, None) - # memory_agent.embedding_engine.encode_im.assert_called_with(query_state, None) - # memory_agent.embedding_engine.encode_ltm.assert_called_with(query_state, None) - - # # Verify search calls on stores with correct parameters - # stm_query = memory_agent.embedding_engine.encode_stm.return_value - # im_query = memory_agent.embedding_engine.encode_im.return_value - # ltm_query = memory_agent.embedding_engine.encode_ltm.return_value - - # mock_stm_store.search_similar.assert_called_once_with(memory_agent.agent_id, stm_query, k=5, memory_type=None) - # mock_im_store.search_similar.assert_called_once_with(memory_agent.agent_id, im_query, k=3, memory_type=None) - # mock_ltm_store.search_similar.assert_called_once_with(ltm_query, k=2, memory_type=None) - def test_retrieve_similar_states_with_type_filter( - self, memory_agent, mock_stm_store + self, memory_space, mock_stm_store ): """Test retrieving similar states with a memory type filter.""" # Configure the stores @@ -731,7 +703,13 @@ def test_retrieve_similar_states_with_type_filter( query_state = {"position": [1, 2, 3]} memory_type = "action" - memory_agent.retrieve_similar_states(query_state, k=5, memory_type=memory_type) + # Mock the embedding engine to return a test embedding + memory_space.embedding_engine.encode_stm.return_value = [0.1, 0.2, 0.3] + + # Ensure the mock store is properly set + memory_space.stm_store = mock_stm_store + + memory_space.retrieve_similar_states(query_state, k=5, memory_type=memory_type) # Verify memory_type was passed to the store mock_stm_store.search_similar.assert_called_once() @@ -739,7 +717,7 @@ def test_retrieve_similar_states_with_type_filter( assert kwargs.get("memory_type") == memory_type def test_retrieve_by_time_range( - self, memory_agent, mock_stm_store, mock_im_store, mock_ltm_store + self, memory_space, mock_stm_store, mock_im_store, mock_ltm_store ): """Test retrieving memories within a time range.""" # Configure the stores @@ -754,7 +732,12 @@ def test_retrieve_by_time_range( mock_im_store.search_by_step_range.return_value = im_results mock_ltm_store.search_by_step_range.return_value = ltm_results - results = memory_agent.retrieve_by_time_range(1, 10) + # Ensure the mock stores are properly set + memory_space.stm_store = mock_stm_store + memory_space.im_store = mock_im_store + memory_space.ltm_store = mock_ltm_store + + results = memory_space.retrieve_by_time_range(1, 10) # Results should be sorted by step number assert len(results) == 4 @@ -765,15 +748,15 @@ def test_retrieve_by_time_range( # Verify calls to stores mock_stm_store.search_by_step_range.assert_called_once_with( - memory_agent.agent_id, 1, 10, None + memory_space.agent_id, 1, 10, None ) mock_im_store.search_by_step_range.assert_called_once_with( - memory_agent.agent_id, 1, 10, None + memory_space.agent_id, 1, 10, None ) mock_ltm_store.search_by_step_range.assert_called_once_with(1, 10, None) def test_retrieve_by_attributes( - self, memory_agent, mock_stm_store, mock_im_store, mock_ltm_store + self, memory_space, mock_stm_store, mock_im_store, mock_ltm_store ): """Test retrieving memories by attribute matching.""" # Configure the stores @@ -785,9 +768,14 @@ def test_retrieve_by_attributes( mock_im_store.search_by_attributes.return_value = im_results mock_ltm_store.search_by_attributes.return_value = ltm_results + # Ensure the mock stores are properly set + memory_space.stm_store = mock_stm_store + memory_space.im_store = mock_im_store + memory_space.ltm_store = mock_ltm_store + attributes = {"location": "forest", "action_type": "gather"} - results = memory_agent.retrieve_by_attributes(attributes) + results = memory_space.retrieve_by_attributes(attributes) # Results should be sorted by timestamp (most recent first) assert len(results) == 3 @@ -797,17 +785,17 @@ def test_retrieve_by_attributes( # Verify calls to stores mock_stm_store.search_by_attributes.assert_called_once_with( - memory_agent.agent_id, attributes, None + memory_space.agent_id, attributes, None ) mock_im_store.search_by_attributes.assert_called_once_with( - memory_agent.agent_id, attributes, None + memory_space.agent_id, attributes, None ) mock_ltm_store.search_by_attributes.assert_called_once_with( - memory_agent.agent_id, attributes, None + memory_space.agent_id, attributes, None ) def test_search_by_embedding( - self, memory_agent, mock_stm_store, mock_im_store, mock_ltm_store + self, memory_space, mock_stm_store, mock_im_store, mock_ltm_store ): """Test searching by raw embedding vector.""" # Configure the stores @@ -819,9 +807,14 @@ def test_search_by_embedding( mock_im_store.search_by_embedding.return_value = im_results mock_ltm_store.search_by_embedding.return_value = ltm_results + # Ensure the mock stores are properly set + memory_space.stm_store = mock_stm_store + memory_space.im_store = mock_im_store + memory_space.ltm_store = mock_ltm_store + query_embedding = [0.1, 0.2, 0.3, 0.4] - results = memory_agent.search_by_embedding(query_embedding, k=3) + results = memory_space.search_by_embedding(query_embedding, k=3) # Results should be sorted by similarity score assert len(results) == 3 @@ -830,22 +823,22 @@ def test_search_by_embedding( assert results[2]["memory_id"] == "ltm1" # Lowest similarity # Verify compression engine calls for IM and LTM - memory_agent.compression_engine.compress_embedding.assert_any_call( + memory_space.compression_engine.compress_embedding.assert_any_call( query_embedding, level=1 ) - memory_agent.compression_engine.compress_embedding.assert_any_call( + memory_space.compression_engine.compress_embedding.assert_any_call( query_embedding, level=2 ) # Verify search calls include agent_id for Redis stores mock_stm_store.search_by_embedding.assert_called_once_with( - memory_agent.agent_id, query_embedding, k=3 + memory_space.agent_id, query_embedding, k=3 ) - mock_im_store.search_by_embedding.assert_called_once() # Already passes but could be more specific - mock_ltm_store.search_by_embedding.assert_called_once() # Already passes but could be more specific + mock_im_store.search_by_embedding.assert_called_once() + mock_ltm_store.search_by_embedding.assert_called_once() def test_search_by_content( - self, memory_agent, mock_stm_store, mock_im_store, mock_ltm_store + self, memory_space, mock_stm_store, mock_im_store, mock_ltm_store ): """Test searching by content text or attributes.""" # Configure the stores @@ -857,13 +850,18 @@ def test_search_by_content( mock_im_store.search_by_content.return_value = im_results mock_ltm_store.search_by_content.return_value = ltm_results + # Ensure the mock stores are properly set + memory_space.stm_store = mock_stm_store + memory_space.im_store = mock_im_store + memory_space.ltm_store = mock_ltm_store + # Test with string query text_query = "forest exploration" - results = memory_agent.search_by_content(text_query, k=3) + results = memory_space.search_by_content(text_query, k=3) # Verify string query was converted to dict mock_stm_store.search_by_content.assert_called_with( - memory_agent.agent_id, {"text": text_query}, 3 + memory_space.agent_id, {"text": text_query}, 3 ) # Results should be sorted by relevance score @@ -874,18 +872,18 @@ def test_search_by_content( # Test with dict query dict_query = {"location": "forest", "action": "explore"} - memory_agent.search_by_content(dict_query, k=2) + memory_space.search_by_content(dict_query, k=2) # Verify dict query was passed as is mock_stm_store.search_by_content.assert_called_with( - memory_agent.agent_id, dict_query, 2 + memory_space.agent_id, dict_query, 2 ) class TestEventHooks: """Tests for memory event hooks mechanism.""" - def test_register_hook(self, memory_agent): + def test_register_hook(self, memory_space): """Test registering event hooks.""" # Define a sample hook function @@ -893,16 +891,16 @@ def test_hook(event_data, agent): return {"result": "success"} # Register the hook - result = memory_agent.register_hook("memory_storage", test_hook, priority=7) + result = memory_space.register_hook("memory_storage", test_hook, priority=7) assert result is True - assert hasattr(memory_agent, "_event_hooks") - assert "memory_storage" in memory_agent._event_hooks - assert len(memory_agent._event_hooks["memory_storage"]) == 1 - assert memory_agent._event_hooks["memory_storage"][0]["function"] == test_hook - assert memory_agent._event_hooks["memory_storage"][0]["priority"] == 7 + assert hasattr(memory_space, "_event_hooks") + assert "memory_storage" in memory_space._event_hooks + assert len(memory_space._event_hooks["memory_storage"]) == 1 + assert memory_space._event_hooks["memory_storage"][0]["function"] == test_hook + assert memory_space._event_hooks["memory_storage"][0]["priority"] == 7 - def test_register_multiple_hooks_with_priority(self, memory_agent): + def test_register_multiple_hooks_with_priority(self, memory_space): """Test registering multiple hooks with priority ordering.""" # Define sample hook functions @@ -916,18 +914,18 @@ def hook3(event_data, agent): return {"result": "hook3"} # Register hooks with different priorities - memory_agent.register_hook("test_event", hook1, priority=3) - memory_agent.register_hook("test_event", hook2, priority=8) - memory_agent.register_hook("test_event", hook3, priority=5) + memory_space.register_hook("test_event", hook1, priority=3) + memory_space.register_hook("test_event", hook2, priority=8) + memory_space.register_hook("test_event", hook3, priority=5) # Verify hooks are stored in priority order (highest first) - hooks = memory_agent._event_hooks["test_event"] + hooks = memory_space._event_hooks["test_event"] assert len(hooks) == 3 assert hooks[0]["function"] == hook2 # Priority 8 assert hooks[1]["function"] == hook3 # Priority 5 assert hooks[2]["function"] == hook1 # Priority 3 - def test_trigger_event(self, memory_agent): + def test_trigger_event(self, memory_space): """Test triggering events and executing hooks.""" # Define sample hook functions with different behaviors event_results = [] @@ -947,14 +945,14 @@ def hook2(event_data, agent): } # Register both hooks - memory_agent.register_hook("test_event", hook1, priority=5) - memory_agent.register_hook("test_event", hook2, priority=3) + memory_space.register_hook("test_event", hook1, priority=5) + memory_space.register_hook("test_event", hook2, priority=3) # Mock store_state method - with mock.patch.object(memory_agent, "store_state") as mock_store: + with mock.patch.object(memory_space, "store_state") as mock_store: # Trigger the event event_data = {"source": "test", "action": "move"} - result = memory_agent.trigger_event("test_event", event_data) + result = memory_space.trigger_event("test_event", event_data) # Verify both hooks executed in order assert result is True @@ -969,7 +967,7 @@ def hook2(event_data, agent): 0.9, # priority ) - def test_trigger_event_with_exception(self, memory_agent): + def test_trigger_event_with_exception(self, memory_space): """Test handling exceptions in event hooks.""" # Define a hook that raises an exception @@ -985,11 +983,11 @@ def normal_hook(event_data, agent): return {"result": "success"} # Register hooks - memory_agent.register_hook("test_event", failing_hook, priority=5) - memory_agent.register_hook("test_event", normal_hook, priority=3) + memory_space.register_hook("test_event", failing_hook, priority=5) + memory_space.register_hook("test_event", normal_hook, priority=3) # Trigger the event - should continue after exception - result = memory_agent.trigger_event("test_event", {"source": "test"}) + result = memory_space.trigger_event("test_event", {"source": "test"}) # First hook failed but second one executed assert result is False # Overall failure @@ -1000,10 +998,10 @@ class TestUtilityFunctions: """Tests for memory utility functions.""" def test_clear_memory( - self, memory_agent, mock_stm_store, mock_im_store, mock_ltm_store + self, memory_space, mock_stm_store, mock_im_store, mock_ltm_store ): """Test clearing all memory stores.""" - result = memory_agent.clear_memory() + result = memory_space.clear_memory() assert result is True mock_stm_store.clear.assert_called_once() @@ -1011,36 +1009,36 @@ def test_clear_memory( mock_ltm_store.clear.assert_called_once() def test_clear_memory_failure( - self, memory_agent, mock_stm_store, mock_im_store, mock_ltm_store + self, memory_space, mock_stm_store, mock_im_store, mock_ltm_store ): """Test handling failure in clearing memory.""" mock_stm_store.clear.return_value = False - result = memory_agent.clear_memory() + result = memory_space.clear_memory() assert result is False - def test_force_maintenance(self, memory_agent): + def test_force_maintenance(self, memory_space): """Test forcing memory maintenance.""" - with mock.patch.object(memory_agent, "_check_memory_transition") as mock_check: - result = memory_agent.force_maintenance() + with mock.patch.object(memory_space, "_check_memory_transition") as mock_check: + result = memory_space.force_maintenance() assert result is True mock_check.assert_called_once() - def test_force_maintenance_failure(self, memory_agent): + def test_force_maintenance_failure(self, memory_space): """Test handling failure in forced maintenance.""" with mock.patch.object( - memory_agent, + memory_space, "_check_memory_transition", side_effect=Exception("Test exception"), ): - result = memory_agent.force_maintenance() + result = memory_space.force_maintenance() assert result is False def test_get_memory_statistics( - self, memory_agent, mock_stm_store, mock_im_store, mock_ltm_store + self, memory_space, mock_stm_store, mock_im_store, mock_ltm_store ): """Test retrieving memory statistics.""" # Configure the mocks @@ -1049,18 +1047,18 @@ def test_get_memory_statistics( mock_ltm_store.count.return_value = 30 with mock.patch.object( - memory_agent, "_calculate_tier_importance", return_value=0.5 + memory_space, "_calculate_tier_importance", return_value=0.5 ), mock.patch.object( - memory_agent, "_calculate_compression_ratio", return_value=2.5 + memory_space, "_calculate_compression_ratio", return_value=2.5 ), mock.patch.object( - memory_agent, + memory_space, "_get_memory_type_distribution", return_value={"state": 30, "action": 20, "interaction": 10}, ), mock.patch.object( - memory_agent, "_get_access_patterns", return_value={"most_accessed": []} + memory_space, "_get_access_patterns", return_value={"most_accessed": []} ): - stats = memory_agent.get_memory_statistics() + stats = memory_space.get_memory_statistics() # Verify statistics structure assert stats["total_memories"] == 60 # 10 + 20 + 30 @@ -1077,14 +1075,14 @@ def test_get_memory_statistics( assert stats["memory_types"]["interaction"] == 10 # Verify helper method calls - memory_agent._calculate_tier_importance.assert_any_call("stm") - memory_agent._calculate_tier_importance.assert_any_call("im") - memory_agent._calculate_tier_importance.assert_any_call("ltm") + memory_space._calculate_tier_importance.assert_any_call("stm") + memory_space._calculate_tier_importance.assert_any_call("im") + memory_space._calculate_tier_importance.assert_any_call("ltm") - memory_agent._calculate_compression_ratio.assert_any_call("im") - memory_agent._calculate_compression_ratio.assert_any_call("ltm") + memory_space._calculate_compression_ratio.assert_any_call("im") + memory_space._calculate_compression_ratio.assert_any_call("ltm") - def test_calculate_reward_score(self, memory_agent): + def test_calculate_reward_score(self, memory_space): """Test calculating reward score from a memory.""" # Memory with no reward memory_no_reward = {"content": {}} @@ -1096,26 +1094,26 @@ def test_calculate_reward_score(self, memory_agent): memory_negative_reward = {"content": {"reward": -2.0}} # Test with max_reward_score of 10 (the default) - memory_agent.config.autoencoder_config.max_reward_score = 10.0 + memory_space.config.autoencoder_config.max_reward_score = 10.0 # Test cases - no_reward_score = memory_agent.calculate_reward_score(memory_no_reward) + no_reward_score = memory_space.calculate_reward_score(memory_no_reward) assert no_reward_score == 0.0 - reward_score = memory_agent.calculate_reward_score(memory_with_reward) + reward_score = memory_space.calculate_reward_score(memory_with_reward) assert reward_score == 0.5 # 5/10 = 0.5 # Negative rewards should be normalized to 0 - negative_score = memory_agent.calculate_reward_score(memory_negative_reward) + negative_score = memory_space.calculate_reward_score(memory_negative_reward) assert negative_score == 0.0 # Test with higher reward than max (should cap at 1.0) memory_high_reward = {"content": {"reward": 15.0}} - high_score = memory_agent.calculate_reward_score(memory_high_reward) + high_score = memory_space.calculate_reward_score(memory_high_reward) assert high_score == 1.0 def test_hybrid_retrieve( - self, memory_agent, mock_stm_store, mock_im_store, mock_ltm_store + self, memory_space, mock_stm_store, mock_im_store, mock_ltm_store ): """Test hybrid retrieval combining similarity and attribute matching.""" # Setup query state @@ -1150,20 +1148,20 @@ def test_hybrid_retrieve( # Configure the mocks with mock.patch.object( - memory_agent, "retrieve_similar_states", return_value=vector_results + memory_space, "retrieve_similar_states", return_value=vector_results ), mock.patch.object( - memory_agent, "retrieve_by_attributes", return_value=attr_results + memory_space, "retrieve_by_attributes", return_value=attr_results ): # Test hybrid retrieval with default weights - results = memory_agent.hybrid_retrieve(query_state, k=3) + results = memory_space.hybrid_retrieve(query_state, k=3) # Verify the function calls - memory_agent.retrieve_similar_states.assert_called_with( + memory_space.retrieve_similar_states.assert_called_with( query_state, k=6, memory_type=None, threshold=0.2 ) - memory_agent.retrieve_by_attributes.assert_called() + memory_space.retrieve_by_attributes.assert_called() # Check results assert len(results) <= 3 # Should not exceed k @@ -1174,14 +1172,14 @@ def test_hybrid_retrieve( assert "hybrid_score" in results[0] # Test with custom weights - results_custom = memory_agent.hybrid_retrieve( + results_custom = memory_space.hybrid_retrieve( query_state, k=2, vector_weight=0.8, attribute_weight=0.2 ) # Results should be ordered by weighted scores assert len(results_custom) <= 2 - def test_hybrid_retrieve_no_embeddings(self, memory_agent, mock_stm_store): + def test_hybrid_retrieve_no_embeddings(self, memory_space, mock_stm_store): """Test hybrid retrieval when embeddings are not available.""" # Query state with attributes query_state = {"position": {"location": "bedroom"}, "energy": 50} @@ -1192,15 +1190,15 @@ def test_hybrid_retrieve_no_embeddings(self, memory_agent, mock_stm_store): ] # Temporarily set embedding_engine to None - memory_agent.embedding_engine = None + memory_space.embedding_engine = None with mock.patch.object( - memory_agent, "retrieve_by_attributes", return_value=attr_results + memory_space, "retrieve_by_attributes", return_value=attr_results ): - results = memory_agent.hybrid_retrieve(query_state, k=3) + results = memory_space.hybrid_retrieve(query_state, k=3) # Should fall back to attribute-based search only - memory_agent.retrieve_by_attributes.assert_called_once() + memory_space.retrieve_by_attributes.assert_called_once() # Check results assert len(results) <= 3 @@ -1208,7 +1206,7 @@ def test_hybrid_retrieve_no_embeddings(self, memory_agent, mock_stm_store): assert results[0]["memory_id"] == "attr1" def test_flush_to_ltm( - self, memory_agent, mock_stm_store, mock_im_store, mock_ltm_store + self, memory_space, mock_stm_store, mock_im_store, mock_ltm_store ): """Test flushing memories from STM and IM to LTM.""" # Setup memory data @@ -1246,7 +1244,7 @@ def test_flush_to_ltm( mock_ltm_store.flush_memories.return_value = (2, 0) # Test flushing both STM and IM - result = memory_agent.flush_to_ltm(include_stm=True, include_im=True) + result = memory_space.flush_to_ltm(include_stm=True, include_im=True) # Verify the calls mock_stm_store.get_all.assert_called_once() @@ -1274,7 +1272,7 @@ def test_flush_to_ltm( assert result["im_filtered"] == 0 def test_flush_to_ltm_with_filtering( - self, memory_agent, mock_stm_store, mock_im_store, mock_ltm_store + self, memory_space, mock_stm_store, mock_im_store, mock_ltm_store ): """Test flushing memories with filtering applied.""" # Setup memory data @@ -1302,7 +1300,7 @@ def test_flush_to_ltm_with_filtering( ] # Test flushing with normal filtering - result1 = memory_agent.flush_to_ltm( + result1 = memory_space.flush_to_ltm( include_stm=True, include_im=False, force=False ) @@ -1318,7 +1316,7 @@ def test_flush_to_ltm_with_filtering( mock_stm_store.clear.reset_mock() # Test flushing with force=True to bypass filtering - result2 = memory_agent.flush_to_ltm( + result2 = memory_space.flush_to_ltm( include_stm=True, include_im=False, force=True ) @@ -1330,7 +1328,7 @@ def test_flush_to_ltm_with_filtering( assert result2["stm_filtered"] == 0 def test_flush_to_ltm_error_handling( - self, memory_agent, mock_stm_store, mock_ltm_store + self, memory_space, mock_stm_store, mock_ltm_store ): """Test error handling during memory flush operations.""" # Setup memory data @@ -1346,7 +1344,7 @@ def test_flush_to_ltm_error_handling( # Mock time.sleep to avoid waiting during test with mock.patch("time.sleep"): # Test flush with retry logic - result = memory_agent.flush_to_ltm(include_stm=True, include_im=False) + result = memory_space.flush_to_ltm(include_stm=True, include_im=False) # Should have called flush_memories twice due to retry assert mock_ltm_store.flush_memories.call_count == 2 @@ -1355,7 +1353,7 @@ def test_flush_to_ltm_error_handling( assert result["stm_stored"] == 1 assert result["stm_filtered"] == 0 - def test_calculate_tier_importance(self, memory_agent, mock_stm_store): + def test_calculate_tier_importance(self, memory_space, mock_stm_store): """Test calculating the average importance score for a memory tier.""" # Create test memories with importance scores test_memories = [ @@ -1368,17 +1366,17 @@ def test_calculate_tier_importance(self, memory_agent, mock_stm_store): mock_stm_store.get_all.return_value = test_memories # Calculate tier importance for STM - importance = memory_agent._calculate_tier_importance("stm") + importance = memory_space._calculate_tier_importance("stm") # Average should be (0.3 + 0.7 + 0.5) / 3 = 0.5 assert importance == 0.5 # Test with empty store mock_stm_store.get_all.return_value = [] - empty_importance = memory_agent._calculate_tier_importance("stm") + empty_importance = memory_space._calculate_tier_importance("stm") assert empty_importance == 0.0 - def test_calculate_compression_ratio(self, memory_agent, mock_im_store): + def test_calculate_compression_ratio(self, memory_space, mock_im_store): """Test calculating the compression ratio for a memory tier.""" # Create test memories with original size metadata test_memories = [ @@ -1391,23 +1389,23 @@ def test_calculate_compression_ratio(self, memory_agent, mock_im_store): mock_im_store.get_size.return_value = 1200 # Compressed size # Calculate compression ratio for IM - ratio = memory_agent._calculate_compression_ratio("im") + ratio = memory_space._calculate_compression_ratio("im") # Ratio should be (1000 + 2000) / 1200 = 2.5 assert ratio == 2.5 # Test with zero compressed size (should avoid division by zero) mock_im_store.get_size.return_value = 0 - zero_ratio = memory_agent._calculate_compression_ratio("im") + zero_ratio = memory_space._calculate_compression_ratio("im") assert zero_ratio == 0.0 # Test with empty store mock_im_store.get_all.return_value = [] - empty_ratio = memory_agent._calculate_compression_ratio("im") + empty_ratio = memory_space._calculate_compression_ratio("im") assert empty_ratio == 0.0 def test_get_memory_type_distribution( - self, memory_agent, mock_stm_store, mock_im_store, mock_ltm_store + self, memory_space, mock_stm_store, mock_im_store, mock_ltm_store ): """Test getting the distribution of memory types across all tiers.""" # Create test memories for each store @@ -1435,7 +1433,7 @@ def test_get_memory_type_distribution( mock_ltm_store.get_all.return_value = ltm_memories # Get distribution - distribution = memory_agent._get_memory_type_distribution() + distribution = memory_space._get_memory_type_distribution() # Check results assert distribution["state"] == 3 # 1 from STM, 1 from IM, 1 from LTM @@ -1447,11 +1445,11 @@ def test_get_memory_type_distribution( mock_im_store.get_all.return_value = [] mock_ltm_store.get_all.return_value = [] - empty_distribution = memory_agent._get_memory_type_distribution() + empty_distribution = memory_space._get_memory_type_distribution() assert len(empty_distribution) == 0 def test_get_access_patterns( - self, memory_agent, mock_stm_store, mock_im_store, mock_ltm_store + self, memory_space, mock_stm_store, mock_im_store, mock_ltm_store ): """Test getting statistics about memory access patterns.""" # Create test memories with various access counts @@ -1469,7 +1467,7 @@ def test_get_access_patterns( mock_ltm_store.get_all.return_value = memories[3:5] # 3, 8 # Get access patterns - patterns = memory_agent._get_access_patterns() + patterns = memory_space._get_access_patterns() # Check total accesses: 10 + 5 + 0 + 3 + 8 = 26 assert patterns["total_accesses"] == 26 @@ -1497,7 +1495,7 @@ def test_get_access_patterns( mock_im_store.get_all.return_value = [] mock_ltm_store.get_all.return_value = [] - empty_patterns = memory_agent._get_access_patterns() + empty_patterns = memory_space._get_access_patterns() assert empty_patterns["total_accesses"] == 0 assert empty_patterns["avg_accesses"] == 0 assert len(empty_patterns["most_accessed"]) == 0 @@ -1505,4 +1503,4 @@ def test_get_access_patterns( if __name__ == "__main__": - pytest.main(["-xvs", "test_memory_agent.py"]) + pytest.main(["-xvs", "test_memory_space.py"]) diff --git a/tests/utils/test_serialization.py b/tests/utils/test_serialization.py index 4c1d38a..6a596ed 100644 --- a/tests/utils/test_serialization.py +++ b/tests/utils/test_serialization.py @@ -459,14 +459,14 @@ def test_load_memory_system_from_json( mock_validate.return_value = True # Create a mock memory agent with mock store attributes - mock_memory_agent = MagicMock() - mock_memory_agent.stm_store = MagicMock() - mock_memory_agent.im_store = MagicMock() - mock_memory_agent.ltm_store = MagicMock() + mock_memory_space = MagicMock() + mock_memory_space.stm_store = MagicMock() + mock_memory_space.im_store = MagicMock() + mock_memory_space.ltm_store = MagicMock() # Configure the mock memory system to return the mock agent mock_memory_system = MagicMock() - mock_memory_system.get_memory_agent.return_value = mock_memory_agent + mock_memory_system.get_memory_space.return_value = mock_memory_space mock_memory_system_class.return_value = mock_memory_system # Mock configurations @@ -547,14 +547,14 @@ def test_load_memory_system_from_json( mock_validate.assert_called_once() # Verify memory agent was created and memories were added to the correct stores - mock_memory_system.get_memory_agent.assert_called_once_with("agent_1") + mock_memory_system.get_memory_space.assert_called_once_with("agent_1") # Verify that the stm_store.store was called for the state memory # Since we've provided embeddings in the test data, it should only be called once - self.assertEqual(mock_memory_agent.stm_store.store.call_count, 1) + self.assertEqual(mock_memory_space.stm_store.store.call_count, 1) # Verify that the im_store.store was called for the interaction memory - self.assertEqual(mock_memory_agent.im_store.store.call_count, 1) + self.assertEqual(mock_memory_space.im_store.store.call_count, 1) @patch("memory.schema.validate_memory_system_json") def test_load_memory_system_validation_failure(self, mock_validate): diff --git a/tests/verify_memory_fix.py b/tests/verify_memory_fix.py index ffcf547..32f220e 100644 --- a/tests/verify_memory_fix.py +++ b/tests/verify_memory_fix.py @@ -8,7 +8,7 @@ from typing import Dict, Any from memory.config import MemoryConfig -from memory.agent_memory import MemoryAgent +from memory.space import MemorySpace # Setup logging logging.basicConfig(level=logging.DEBUG) @@ -76,7 +76,7 @@ def verify_memory_system(): """Run a complete memory verification through all tiers.""" config = MemoryConfig() agent_id = f"verify_agent_{int(time.time())}" - memory_agent = MemoryAgent(agent_id, config) + memory_space = MemorySpace(agent_id, config) logger.info(f"Created verification agent: {agent_id}") @@ -98,11 +98,11 @@ def verify_memory_system(): logger.info(f"Original test data: {json.dumps(test_data, indent=2)}") # 1. Store in STM - memory_agent.store_state(test_data, 1, 0.7) + memory_space.store_state(test_data, 1, 0.7) logger.info("Stored memory in STM") # Get memory from STM to verify - stm_memories = memory_agent.stm_store.get_all(agent_id) + stm_memories = memory_space.stm_store.get_all(agent_id) if stm_memories: original_memory_id = stm_memories[0]["memory_id"] logger.info(f"Memory ID: {original_memory_id}") @@ -113,11 +113,11 @@ def verify_memory_system(): # 2. Force transition to IM logger.info("\nForcing transition to IM...") - memory_agent.config.stm_config.memory_limit = 0 - memory_agent._check_memory_transition() + memory_space.config.stm_config.memory_limit = 0 + memory_space._check_memory_transition() # Get memory from IM to verify - im_memories = memory_agent.im_store.get_all(agent_id) + im_memories = memory_space.im_store.get_all(agent_id) if im_memories: im_memory = next((m for m in im_memories if m["memory_id"] == original_memory_id), None) if im_memory: @@ -130,11 +130,11 @@ def verify_memory_system(): # 3. Force transition to LTM logger.info("\nForcing transition to LTM...") - memory_agent.config.im_config.memory_limit = 0 - memory_agent._check_memory_transition() + memory_space.config.im_config.memory_limit = 0 + memory_space._check_memory_transition() # Get memory from LTM to verify - ltm_memory = memory_agent.ltm_store.get(original_memory_id) + ltm_memory = memory_space.ltm_store.get(original_memory_id) if ltm_memory: compare_memory_content(test_data, ltm_memory, "LTM") else: diff --git a/validation/framework/test_runner.py b/validation/framework/test_runner.py index 0136c70..3be6657 100644 --- a/validation/framework/test_runner.py +++ b/validation/framework/test_runner.py @@ -70,7 +70,7 @@ def __init__( return # Get agent and create strategy - self.agent = self.memory_system.get_memory_agent(agent_id) + self.agent = self.memory_system.get_memory_space(agent_id) self.strategy = strategy_class(self.memory_system) # Print strategy info diff --git a/validation/search/attribute/performance_test_attribute.py b/validation/search/attribute/performance_test_attribute.py index 00c76a3..9a6bb62 100644 --- a/validation/search/attribute/performance_test_attribute.py +++ b/validation/search/attribute/performance_test_attribute.py @@ -61,7 +61,7 @@ def setup_memory_system(self, memory_count=1000): ) # Get agent reference - agent = self.memory_system.get_memory_agent(AGENT_ID) + agent = self.memory_system.get_memory_space(AGENT_ID) # Generate test memories self._generate_test_memories(memory_count) @@ -84,7 +84,7 @@ def setup_memory_system(self, memory_count=1000): def _generate_test_memories(self, count): """Generate test memories with varied content and distribute across tiers.""" log_print(self.logger, f"Generating {count} test memories") - agent = self.memory_system.get_memory_agent(AGENT_ID) + agent = self.memory_system.get_memory_space(AGENT_ID) # Define templates for content variety templates = [ @@ -866,7 +866,7 @@ def cleanup(self): try: # Clean up memory stores if self.memory_system: - agent = self.memory_system.get_memory_agent(AGENT_ID) + agent = self.memory_system.get_memory_space(AGENT_ID) # Clear STM store if agent.stm_store: diff --git a/validation/search/importance/performance_test_importance.py b/validation/search/importance/performance_test_importance.py index 89aab2b..c70ec0b 100644 --- a/validation/search/importance/performance_test_importance.py +++ b/validation/search/importance/performance_test_importance.py @@ -51,7 +51,7 @@ def setup_memory_system(self, memory_count: int = 1000) -> None: return # Get the memory agent - agent = self.memory_system.get_memory_agent(AGENT_ID) + agent = self.memory_system.get_memory_space(AGENT_ID) # Load the ImportanceStrategy self.search_strategy = ImportanceStrategy( diff --git a/validation/search/sequence/performance_test_sequence.py b/validation/search/sequence/performance_test_sequence.py index 9c1d541..4ae48a7 100644 --- a/validation/search/sequence/performance_test_sequence.py +++ b/validation/search/sequence/performance_test_sequence.py @@ -64,7 +64,7 @@ def setup_memory_system(self, memory_count: int = 1000) -> None: return # Get the memory agent - agent = self.memory_system.get_memory_agent(AGENT_ID) + agent = self.memory_system.get_memory_space(AGENT_ID) # Load the NarrativeSequenceStrategy self.search_strategy = NarrativeSequenceStrategy( diff --git a/validation/search/similarity/debug_similarity_scores.py b/validation/search/similarity/debug_similarity_scores.py index e60f572..685a983 100644 --- a/validation/search/similarity/debug_similarity_scores.py +++ b/validation/search/similarity/debug_similarity_scores.py @@ -47,9 +47,9 @@ def analyze_similarity_scores(query: str = "machine learning model accuracy"): ) # Using a smaller model for testing # Get the storage components from the memory system - stm_store = memory_system.get_memory_agent(agent_id).stm_store - im_store = memory_system.get_memory_agent(agent_id).im_store - ltm_store = memory_system.get_memory_agent(agent_id).ltm_store + stm_store = memory_system.get_memory_space(agent_id).stm_store + im_store = memory_system.get_memory_space(agent_id).im_store + ltm_store = memory_system.get_memory_space(agent_id).ltm_store # Load validation memory for reference memory_data = load_validation_memory()