neuro-simulator 0.5.0__py3-none-any.whl → 0.5.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,17 +13,6 @@ from ..utils.process import process_manager
13
13
  router = APIRouter(tags=["System & Utilities"])
14
14
 
15
15
 
16
- # --- Utility function to filter config for frontend ---
17
- def filter_config_for_frontend(settings):
18
- """Filters the full settings object to remove sensitive fields before sending to the frontend."""
19
- # Create a dictionary representation of the settings
20
- config_dict = settings.model_dump()
21
-
22
- # Remove sensitive fields
23
- config_dict.pop('api_keys', None)
24
-
25
- return config_dict
26
-
27
16
 
28
17
  # --- Auth Dependency ---
29
18
 
@@ -39,7 +39,7 @@ class ChatbotLLMClient:
39
39
  if not api_key:
40
40
  raise ValueError("GEMINI_API_KEY is not set in configuration for the chatbot agent.")
41
41
 
42
- genai.configure(api_key=api_key)
42
+ self.client = genai.Client(api_key=api_key)
43
43
  self.model_name = settings.chatbot_agent.agent_model
44
44
  self._generate_func = self._generate_gemini
45
45
 
@@ -62,20 +62,21 @@ class ChatbotLLMClient:
62
62
 
63
63
  async def _generate_gemini(self, prompt: str, max_tokens: int) -> str:
64
64
  """Generates text using the Gemini model."""
65
- generation_config = types.GenerationConfig(
65
+ generation_config = types.GenerateContentConfig(
66
66
  max_output_tokens=max_tokens,
67
67
  )
68
- model = genai.GenerativeModel(self.model_name)
69
68
  try:
70
- response = await model.generate_content_async(
69
+ # Run the synchronous SDK call in a thread to avoid blocking asyncio
70
+ response = await asyncio.to_thread(
71
+ self.client.models.generate_content,
72
+ model=self.model_name,
71
73
  contents=prompt,
72
- generation_config=generation_config
74
+ config=generation_config
73
75
  )
74
76
  return response.text
75
77
  except Exception as e:
76
78
  logger.error(f"Error in chatbot _generate_gemini: {e}", exc_info=True)
77
79
  return ""
78
-
79
80
  async def _generate_openai(self, prompt: str, max_tokens: int) -> str:
80
81
  """Generates text using the OpenAI model."""
81
82
  try:
neuro_simulator/cli.py CHANGED
@@ -19,7 +19,7 @@ def main():
19
19
 
20
20
  args = parser.parse_args()
21
21
 
22
- # 1. Set working directory
22
+ # --- 1. Setup Working Directory ---
23
23
  if args.dir:
24
24
  work_dir = Path(args.dir).resolve()
25
25
  if not work_dir.exists():
@@ -32,83 +32,70 @@ def main():
32
32
  os.chdir(work_dir)
33
33
  logging.info(f"Using working directory: {work_dir}")
34
34
 
35
- # 2. Initialize paths and load configuration
35
+ # --- 2. Initialize Path Manager ---
36
36
  from neuro_simulator.core import path_manager
37
- from neuro_simulator.core.config import config_manager
38
- import uvicorn
39
-
40
37
  path_manager.initialize_path_manager(os.getcwd())
41
38
 
42
- # Define example_path early for config loading
43
- example_path = Path(__file__).parent / "config.yaml.example"
44
-
45
- # 2.2. Copy default config.yaml.example if it doesn't exist
39
+ # --- 3. First-Run Environment Initialization ---
40
+ # This block ensures that a new user has all the necessary default files.
46
41
  try:
47
- source_config_example = example_path
48
- destination_config_example = path_manager.path_manager.working_dir / "config.yaml.example"
49
- if not destination_config_example.exists():
50
- shutil.copy(source_config_example, destination_config_example)
51
- logging.info(f"Copyed default config.yaml.example to {destination_config_example}")
42
+ package_source_path = Path(__file__).parent
43
+
44
+ # Helper to copy files if they don't exist
45
+ def copy_if_not_exists(src: Path, dest: Path):
46
+ if not dest.exists():
47
+ dest.parent.mkdir(parents=True, exist_ok=True)
48
+ shutil.copy(src, dest)
49
+ logging.info(f"Copied default file to {dest}")
50
+
51
+ # Copy config.yaml.example
52
+ copy_if_not_exists(package_source_path / "config.yaml.example", work_dir / "config.yaml.example")
53
+
54
+ # Copy prompts
55
+ copy_if_not_exists(package_source_path / "agent" / "neuro_prompt.txt", path_manager.path_manager.neuro_prompt_path)
56
+ copy_if_not_exists(package_source_path / "agent" / "memory_prompt.txt", path_manager.path_manager.memory_agent_prompt_path)
57
+
58
+ # Copy default memory JSON files
59
+ copy_if_not_exists(package_source_path / "agent" / "memory" / "core_memory.json", path_manager.path_manager.core_memory_path)
60
+ copy_if_not_exists(package_source_path / "agent" / "memory" / "init_memory.json", path_manager.path_manager.init_memory_path)
61
+ copy_if_not_exists(package_source_path / "agent" / "memory" / "temp_memory.json", path_manager.path_manager.temp_memory_path)
62
+
63
+ # Copy default assets directory
64
+ source_assets_dir = package_source_path / "assets"
65
+ destination_assets_dir = path_manager.path_manager.assets_dir
66
+ if not destination_assets_dir.exists():
67
+ shutil.copytree(source_assets_dir, destination_assets_dir)
68
+ logging.info(f"Copied default asset directory to {destination_assets_dir}")
69
+
52
70
  except Exception as e:
53
- logging.warning(f"Could not copy default config.yaml.example: {e}")
71
+ logging.warning(f"Could not copy all default files: {e}")
54
72
 
55
- main_config_path = path_manager.path_manager.working_dir / "config.yaml"
56
- config_manager.load_and_validate(str(main_config_path), str(example_path))
73
+ # --- 4. Load Configuration ---
74
+ from neuro_simulator.core.config import config_manager
75
+ from pydantic import ValidationError
76
+ import uvicorn
57
77
 
58
- # 2.5. Copy default prompt templates if they don't exist
78
+ main_config_path = path_manager.path_manager.working_dir / "config.yaml"
59
79
  try:
60
- # Use Path(__file__).parent for robust path resolution
61
- base_path = Path(__file__).parent
62
- neuro_prompt_example = base_path / "agent" / "neuro_prompt.txt"
63
- memory_prompt_example = base_path / "agent" / "memory_prompt.txt"
64
-
65
- if not path_manager.path_manager.neuro_prompt_path.exists():
66
- shutil.copy(neuro_prompt_example, path_manager.path_manager.neuro_prompt_path)
67
- logging.info(f"Copied default neuro prompt to {path_manager.path_manager.neuro_prompt_path}")
68
- if not path_manager.path_manager.memory_agent_prompt_path.exists():
69
- shutil.copy(memory_prompt_example, path_manager.path_manager.memory_agent_prompt_path)
70
- logging.info(f"Copied default memory prompt to {path_manager.path_manager.memory_agent_prompt_path}")
71
-
72
- # Copy default memory JSON files if they don't exist
73
- memory_files = {
74
- "core_memory.json": path_manager.path_manager.core_memory_path,
75
- "init_memory.json": path_manager.path_manager.init_memory_path,
76
- "temp_memory.json": path_manager.path_manager.temp_memory_path,
77
- }
78
- for filename, dest_path in memory_files.items():
79
- src_path = base_path / "agent" / "memory" / filename
80
- if not dest_path.exists():
81
- shutil.copy(src_path, dest_path)
82
- logging.info(f"Copied default {filename} to {dest_path}")
83
-
84
- # Copy default assets directory if it doesn't exist
85
- source_assets_dir = base_path / "assets"
86
- destination_assets_dir = path_manager.path_manager.assets_dir
87
-
88
- # Ensure the destination assets directory exists
89
- destination_assets_dir.mkdir(parents=True, exist_ok=True)
90
-
91
- # Copy individual files from source assets to destination assets
92
- for item in source_assets_dir.iterdir():
93
- if item.is_file():
94
- dest_file = destination_assets_dir / item.name
95
- if not dest_file.exists():
96
- shutil.copy(item, dest_file)
97
- logging.info(f"Copied asset {item.name} to {dest_file}")
98
- elif item.is_dir():
99
- # Recursively copy subdirectories if they don't exist
100
- dest_subdir = destination_assets_dir / item.name
101
- if not dest_subdir.exists():
102
- shutil.copytree(item, dest_subdir)
103
- logging.info(f"Copied asset directory {item.name} to {dest_subdir}")
80
+ config_manager.load(str(main_config_path))
81
+ except FileNotFoundError:
82
+ logging.error(f"FATAL: Configuration file '{main_config_path.name}' not found.")
83
+ logging.error(f"If this is your first time, please rename 'config.yaml.example' to 'config.yaml' after filling it out.")
84
+ sys.exit(1)
85
+ except ValidationError as e:
86
+ logging.error(f"FATAL: Configuration error in '{main_config_path.name}':")
87
+ logging.error(e)
88
+ sys.exit(1)
104
89
  except Exception as e:
105
- logging.warning(f"Could not copy default prompt templates, memory files, or assets: {e}")
90
+ logging.error(f"FATAL: An unexpected error occurred while loading the configuration: {e}")
91
+ sys.exit(1)
106
92
 
107
- # 3. Determine server host and port
93
+ # --- 5. Determine Server Host and Port ---
94
+ # Command-line arguments override config file settings
108
95
  server_host = args.host or config_manager.settings.server.host
109
96
  server_port = args.port or config_manager.settings.server.port
110
97
 
111
- # 4. Run the server
98
+ # --- 6. Run the Server ---
112
99
  logging.info(f"Starting Neuro-Simulator server on {server_host}:{server_port}...")
113
100
  try:
114
101
  uvicorn.run(
@@ -482,23 +482,22 @@ async def handle_admin_ws_message(websocket: WebSocket, data: dict):
482
482
  response["payload"] = status
483
483
 
484
484
  # Config Management Actions
485
+ elif action == "get_settings_schema":
486
+ response["payload"] = config_manager.settings.model_json_schema()
487
+
485
488
  elif action == "get_configs":
486
- from ..api.system import filter_config_for_frontend
487
- configs = filter_config_for_frontend(config_manager.settings)
488
- response["payload"] = configs
489
+ response["payload"] = config_manager.settings.model_dump()
489
490
 
490
491
  elif action == "update_configs":
491
- from ..api.system import filter_config_for_frontend
492
492
  await config_manager.update_settings(payload)
493
- updated_configs = filter_config_for_frontend(config_manager.settings)
493
+ updated_configs = config_manager.settings.model_dump()
494
494
  response["payload"] = updated_configs
495
495
  await connection_manager.broadcast_to_admins({"type": "config_updated", "payload": updated_configs})
496
496
 
497
497
  elif action == "reload_configs":
498
498
  await config_manager.update_settings({})
499
499
  response["payload"] = {"status": "success", "message": "Configuration reloaded"}
500
- from ..api.system import filter_config_for_frontend
501
- updated_configs = filter_config_for_frontend(config_manager.settings)
500
+ updated_configs = config_manager.settings.model_dump()
502
501
  await connection_manager.broadcast_to_admins({"type": "config_updated", "payload": updated_configs})
503
502
 
504
503
  # Other Agent Actions
@@ -110,56 +110,29 @@ class ConfigManager:
110
110
  self._update_callbacks = []
111
111
  self._initialized = True
112
112
 
113
- def load_and_validate(self, config_path_str: str, example_path_str: str):
114
- """Loads the main config file, handling first-run scenarios, and validates it."""
113
+ def load(self, config_path_str: str):
114
+ """
115
+ Loads the configuration from the given path, validates it, and sets it
116
+ on the manager instance.
117
+
118
+ Raises:
119
+ FileNotFoundError: If the config file does not exist.
120
+ ValueError: If the config file is empty.
121
+ pydantic.ValidationError: If the config file content does not match the AppSettings schema.
122
+ """
115
123
  config_path = Path(config_path_str)
116
- example_path = Path(example_path_str)
117
-
118
- # Scenario 1: Both config and example are missing in the working directory.
119
- if not config_path.exists() and not example_path.exists():
120
- try:
121
- import importlib.resources
122
- # For Python 3.9+, prefer importlib.resources.files
123
- ref = importlib.resources.files('neuro_simulator') / 'config.yaml.example'
124
- with importlib.resources.as_file(ref) as package_example_path:
125
- shutil.copy(package_example_path, example_path)
126
- logging.info(f"Created '{example_path}' from package resource.")
127
- logging.error(f"Configuration file '{config_path.name}' not found. A new '{example_path.name}' has been created. Please configure it and rename it to '{config_path.name}'.")
128
- sys.exit(1)
129
- except Exception as e:
130
- logging.error(f"FATAL: Could not create config from package resources: {e}")
131
- sys.exit(1)
132
-
133
- # Scenario 2: Config is missing, but example exists.
134
- elif not config_path.exists() and example_path.exists():
135
- logging.error(f"Configuration file '{config_path.name}' not found, but '{example_path.name}' exists. Please rename it to '{config_path.name}' after configuration.")
136
- sys.exit(1)
137
-
138
- # Scenario 3: Config exists, but example is missing.
139
- elif config_path.exists() and not example_path.exists():
140
- try:
141
- import importlib.resources
142
- # For Python 3.9+, prefer importlib.resources.files
143
- ref = importlib.resources.files('neuro_simulator') / 'config.yaml.example'
144
- with importlib.resources.as_file(ref) as package_example_path:
145
- shutil.copy(package_example_path, example_path)
146
- logging.info(f"Created missing '{example_path.name}' from package resource.")
147
- except Exception as e:
148
- logging.warning(f"Could not create missing '{example_path.name}': {e}")
149
-
150
- # Proceed with loading the config if it exists.
151
- try:
152
- with open(config_path, 'r', encoding='utf-8') as f:
153
- yaml_config = yaml.safe_load(f)
154
- if yaml_config is None:
155
- raise ValueError(f"Configuration file '{config_path}' is empty.")
156
-
157
- self.settings = AppSettings.model_validate(yaml_config)
158
- logging.info("Main configuration loaded successfully.")
159
124
 
160
- except Exception as e:
161
- logging.error(f"Error loading or parsing {config_path}: {e}")
162
- sys.exit(1) # Exit if the main config is invalid
125
+ if not config_path.exists():
126
+ raise FileNotFoundError(f"Configuration file '{config_path}' not found.")
127
+
128
+ with open(config_path, 'r', encoding='utf-8') as f:
129
+ yaml_config = yaml.safe_load(f)
130
+ if yaml_config is None:
131
+ raise ValueError(f"Configuration file '{config_path}' is empty.")
132
+
133
+ # This will raise ValidationError on failure
134
+ self.settings = AppSettings.model_validate(yaml_config)
135
+ logging.info("Configuration loaded and validated successfully.")
163
136
 
164
137
  def save_settings(self):
165
138
  """Saves the current configuration to config.yaml while preserving comments and formatting."""
@@ -312,9 +285,6 @@ class ConfigManager:
312
285
  model to ensure sub-models are correctly instantiated, and then
313
286
  notifying callbacks.
314
287
  """
315
- # Prevent API keys from being updated from the panel
316
- new_settings_data.pop('api_keys', None)
317
-
318
288
  try:
319
289
  # 1. Dump the current settings model to a dictionary.
320
290
  current_settings_dict = self.settings.model_dump()
@@ -3,6 +3,7 @@ import asyncio
3
3
  import base64
4
4
  import html
5
5
  import logging
6
+ import re
6
7
 
7
8
  import azure.cognitiveservices.speech as speechsdk
8
9
 
@@ -10,11 +11,40 @@ from ..core.config import config_manager
10
11
 
11
12
  logger = logging.getLogger(__name__.replace("neuro_simulator", "server", 1))
12
13
 
14
+ def _remove_emoji(text: str) -> str:
15
+ """Removes emoji characters from a string."""
16
+ if not text:
17
+ return ""
18
+ # This regex pattern covers a wide range of Unicode emoji characters.
19
+ emoji_pattern = re.compile(
20
+ "["
21
+ "\U0001F600-\U0001F64F" # emoticons
22
+ "\U0001F300-\U0001F5FF" # symbols & pictographs
23
+ "\U0001F680-\U0001F6FF" # transport & map symbols
24
+ "\U0001F700-\U0001F77F" # alchemical symbols
25
+ "\U0001F780-\U0001F7FF" # Geometric Shapes Extended
26
+ "\U0001F800-\U0001F8FF" # Supplemental Arrows-C
27
+ "\U0001F900-\U0001F9FF" # Supplemental Symbols and Pictographs
28
+ "\U0001FA00-\U0001FA6F" # Chess Symbols
29
+ "\U0001FA70-\U0001FAFF" # Symbols and Pictographs Extended-A
30
+ "\U00002702-\U000027B0" # Dingbats
31
+ "\U000024C2-\U0001F251"
32
+ "]+",
33
+ flags=re.UNICODE,
34
+ )
35
+ return emoji_pattern.sub(r'', text).strip()
36
+
13
37
  async def synthesize_audio_segment(text: str, voice_name: str = None, pitch: float = None) -> tuple[str, float]:
14
38
  """
15
39
  Synthesizes audio using Azure TTS.
16
40
  Returns a Base64 encoded audio string and the audio duration in seconds.
17
41
  """
42
+ # Clean emojis from the text before synthesis
43
+ text = _remove_emoji(text)
44
+ if not text:
45
+ # If text is empty after cleaning, no need to synthesize.
46
+ return "", 0.0
47
+
18
48
  azure_key = config_manager.settings.api_keys.azure_speech_key
19
49
  azure_region = config_manager.settings.api_keys.azure_speech_region
20
50
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: neuro_simulator
3
- Version: 0.5.0
3
+ Version: 0.5.2
4
4
  Summary: Neuro Simulator Server
5
5
  Author-email: Moha-Master <hongkongreporter@outlook.com>
6
6
  License-Expression: MIT
@@ -1,5 +1,5 @@
1
1
  neuro_simulator/__init__.py,sha256=-tposzyvg6UckPcfSvtc03UjxBa9oCe_zRvlKf8splk,31
2
- neuro_simulator/cli.py,sha256=gtmZZ7Y-lZqEtz9AIA4TuJ4vJw5pNFvPrqpxxIaDnl4,5455
2
+ neuro_simulator/cli.py,sha256=nkSqM4TEEiWJU0jL0pjo7qtVGYtSCpFMYwogBH5WNXY,4683
3
3
  neuro_simulator/config.yaml.example,sha256=M-uCuDj-0XvM6BuFNQT9rsFHL_t71UK0jWVSuF6nL6Q,4732
4
4
  neuro_simulator/agent/__init__.py,sha256=t52CZlyTGWqcGjMs90qvpFpRckY2WSSlO7r_H3K_mSY,32
5
5
  neuro_simulator/agent/core.py,sha256=_UkxMV1S33VHjD1JFlKz17GpaDhHQGNA9s9dsRgd3j0,9561
@@ -23,11 +23,11 @@ neuro_simulator/agent/tools/remove_from_core_memory_block.py,sha256=uiY69y2iIJYp
23
23
  neuro_simulator/agent/tools/speak.py,sha256=7vPbfWjllxSz39HmOUbKRPwPx64q2vsYrqDu-JsfZJk,1870
24
24
  neuro_simulator/agent/tools/update_core_memory_block.py,sha256=CQgimyPNLmOuK_pDAiAxV9qEf3Tx6u7OKludlIR08BA,2272
25
25
  neuro_simulator/api/__init__.py,sha256=5LWyDSayPGdQS8Rv13nmAKLyhPnMVPyTYDdvoMPB4xw,56
26
- neuro_simulator/api/system.py,sha256=OJT6m6HIYATMCAKrgeBRhficaiUjIDl9f-WyUT-RoBw,1874
26
+ neuro_simulator/api/system.py,sha256=JPAAULdNks39GC7Be3VxnPOzTTE32jV62Ybd9_OM4s8,1474
27
27
  neuro_simulator/assets/neuro_start.mp4,sha256=xCLnNzv4THnzRYwkdV6EiqXc-XtFd867R2ZVLDvNp0Y,8226418
28
28
  neuro_simulator/chatbot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
29
  neuro_simulator/chatbot/core.py,sha256=jddeOZDYcEcWpEryMVOlLFCq1YqIZGnqQi7VV_sPnRU,11314
30
- neuro_simulator/chatbot/llm.py,sha256=UgiAq8aqmuSaf3poX_QIZHPxKPZpr_Xn4aHrhTlESPE,4204
30
+ neuro_simulator/chatbot/llm.py,sha256=SDFgPG4SU7CC--IYHyUHjUPK4no4vkzckIi47JZ6Vz4,4315
31
31
  neuro_simulator/chatbot/memory/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
32
  neuro_simulator/chatbot/memory/manager.py,sha256=K84EEH-gRPksgt7GcNxvEVo60aHxaOTC3dZMf2rR9bQ,3827
33
33
  neuro_simulator/chatbot/nickname_gen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -41,11 +41,11 @@ neuro_simulator/chatbot/tools/post_chat_message.py,sha256=lchGCSQKzPZgb1z__MIDkG
41
41
  neuro_simulator/core/__init__.py,sha256=-ojq25c8XA0CU25b0OxcGjH4IWFEDHR-HXSRSZIuKe8,57
42
42
  neuro_simulator/core/agent_factory.py,sha256=p3IKT6sNzSpUojQjvbZJu0pbmyyb258sGn_YNSJlqwI,1717
43
43
  neuro_simulator/core/agent_interface.py,sha256=ZXUCtkQUvsBQ5iCb0gTILJaShn5KmSrEgKhd7PK18HE,2794
44
- neuro_simulator/core/application.py,sha256=TxqDz4buITapVwgtO6Pv5-JlG--8JPk5IQraaTFW8oQ,26566
45
- neuro_simulator/core/config.py,sha256=BszgxKFtHyoYUYUjJmY-kc-X0H7LQencJFKzt56j_hQ,15068
44
+ neuro_simulator/core/application.py,sha256=_MIFL7sGUsHNziwf2wW1iqyIrmUhtSmKr4_Q5DxAHYg,26424
45
+ neuro_simulator/core/config.py,sha256=c_H_nf9gH9-oYZRaZkPfnirkgqY2PHSnLNO5zH-HP08,13073
46
46
  neuro_simulator/core/path_manager.py,sha256=fQZ5RLdiWYeWXbmnhmgCoBEMWXtnPEGtZ6dhtpyXRCI,4339
47
47
  neuro_simulator/services/__init__.py,sha256=s3ZrAHg5TpJakadAAGY1h0wDw_xqN4Je4aJwJyRBmk4,61
48
- neuro_simulator/services/audio.py,sha256=EElBue80njZY8_CKQhVtZEcGchJUdmS4EDOvJEEu_LY,2909
48
+ neuro_simulator/services/audio.py,sha256=eMC-rb6R7S2ndJ3o2Ti4gWCc4aiyNzJ8kWPJXIgFtu8,4043
49
49
  neuro_simulator/services/builtin.py,sha256=7b5F2StGX2ZT1jMiAAuqov0mx5OMHvUYheo8E1c9fjQ,6097
50
50
  neuro_simulator/services/letta.py,sha256=OEM4qYeRRPoj8qY645YZwCHmMfg1McLp0eTbSAu3KL0,11976
51
51
  neuro_simulator/services/stream.py,sha256=9k8bNnQu237WMf1qX8OMfItAPEZkaZ4NEiI4FQ_7Ww4,6058
@@ -55,8 +55,8 @@ neuro_simulator/utils/process.py,sha256=9OYWx8fzaJZqmFUcjQX37AnBhl7YWvrLxDWBa30v
55
55
  neuro_simulator/utils/queue.py,sha256=pyBiFSSO1ocUF0kZfXvOywVcyYAwk8XDBXR8jJLkgSI,2701
56
56
  neuro_simulator/utils/state.py,sha256=DdBqSAYfjOFtJfB1hEGhYPh32r1ZvFuVlN_-29_-luA,664
57
57
  neuro_simulator/utils/websocket.py,sha256=fjC-qipzjgM_e7XImP12DFmLhvxkMOSr2GnUWws7esE,2058
58
- neuro_simulator-0.5.0.dist-info/METADATA,sha256=yaElYaysfpSen1W2igb9eR8eTZWHF2N7F-O-4w1Ig3c,7675
59
- neuro_simulator-0.5.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
60
- neuro_simulator-0.5.0.dist-info/entry_points.txt,sha256=qVd5ypnRRgU8Cw7rWfZ7o0OXyS9P9hgY-cRoN_mgz9g,51
61
- neuro_simulator-0.5.0.dist-info/top_level.txt,sha256=V8awSKpcrFnjJDiJxSfy7jtOrnuE2BgAR9hLmfMDWK8,16
62
- neuro_simulator-0.5.0.dist-info/RECORD,,
58
+ neuro_simulator-0.5.2.dist-info/METADATA,sha256=Ps0u0IN-WzAtex7Vr5mn0yEKsagSgINZ8e01zppD-gM,7675
59
+ neuro_simulator-0.5.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
60
+ neuro_simulator-0.5.2.dist-info/entry_points.txt,sha256=qVd5ypnRRgU8Cw7rWfZ7o0OXyS9P9hgY-cRoN_mgz9g,51
61
+ neuro_simulator-0.5.2.dist-info/top_level.txt,sha256=V8awSKpcrFnjJDiJxSfy7jtOrnuE2BgAR9hLmfMDWK8,16
62
+ neuro_simulator-0.5.2.dist-info/RECORD,,