neuro-simulator 0.2.2__py3-none-any.whl → 0.3.1__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.
@@ -17,10 +17,10 @@ from starlette.websockets import WebSocketState
17
17
  # --- Core Imports ---
18
18
  from .config import config_manager, AppSettings
19
19
  from ..core.agent_factory import create_agent
20
+ from ..services.letta import LettaAgent
21
+ from ..services.builtin import BuiltinAgentWrapper
20
22
 
21
23
  # --- API Routers ---
22
- from ..api.agent import router as agent_router
23
- from ..api.stream import router as stream_router
24
24
  from ..api.system import router as system_router
25
25
 
26
26
  # --- Services and Utilities ---
@@ -58,8 +58,6 @@ app.add_middleware(
58
58
  expose_headers=["X-API-Token"],
59
59
  )
60
60
 
61
- app.include_router(agent_router)
62
- app.include_router(stream_router)
63
61
  app.include_router(system_router)
64
62
 
65
63
  # --- Background Task Definitions ---
@@ -130,18 +128,42 @@ async def neuro_response_cycle():
130
128
 
131
129
  while True:
132
130
  try:
133
- if is_first_response:
134
- add_to_neuro_input_queue({"username": "System", "text": config_manager.settings.neuro_behavior.initial_greeting})
135
- is_first_response = False
136
- elif is_neuro_input_queue_empty():
137
- await asyncio.sleep(1)
138
- continue
131
+ selected_chats = []
132
+ # Superchat logic
133
+ if app_state.superchat_queue and (time.time() - app_state.last_superchat_time > 10):
134
+ sc = app_state.superchat_queue.popleft()
135
+ app_state.last_superchat_time = time.time()
136
+ await connection_manager.broadcast({"type": "processing_superchat", "data": sc})
137
+
138
+ # Agent-specific payload generation for superchats
139
+ if isinstance(agent, LettaAgent):
140
+ selected_chats = [
141
+ {"role": "system", "content": "=== RANDOM 10 MSG IN CHATROOM ===\nNO MSG FETCH DUE TO UNPROCESSED HIGHLIGHTED MESSAGE"},
142
+ {"role": "system", "content": f"=== HIGHLIGHTED MESSAGE ===\n{sc['username']}: {sc['text']}"}
143
+ ]
144
+ else: # For BuiltinAgent and any other future agents
145
+ selected_chats = [{'username': sc['username'], 'text': sc['text']}]
146
+
147
+ # Clear the regular input queue to prevent immediate follow-up with normal chats
148
+ get_all_neuro_input_chats()
149
+ else:
150
+ if is_first_response:
151
+ add_to_neuro_input_queue({"username": "System", "text": config_manager.settings.neuro_behavior.initial_greeting})
152
+ is_first_response = False
153
+ elif is_neuro_input_queue_empty():
154
+ await asyncio.sleep(1)
155
+ continue
156
+
157
+ current_queue_snapshot = get_all_neuro_input_chats()
158
+ if not current_queue_snapshot:
159
+ continue
160
+ sample_size = min(config_manager.settings.neuro_behavior.input_chat_sample_size, len(current_queue_snapshot))
161
+ selected_chats = random.sample(current_queue_snapshot, sample_size)
139
162
 
140
- current_queue_snapshot = get_all_neuro_input_chats()
141
- sample_size = min(config_manager.settings.neuro_behavior.input_chat_sample_size, len(current_queue_snapshot))
142
- selected_chats = random.sample(current_queue_snapshot, sample_size)
163
+ if not selected_chats:
164
+ continue
143
165
 
144
- response_result = await asyncio.wait_for(agent.process_messages(selected_chats), timeout=20.0)
166
+ response_result = await asyncio.wait_for(agent.process_and_respond(selected_chats), timeout=20.0)
145
167
 
146
168
  response_text = response_result.get("final_response", "").strip()
147
169
  if not response_text:
@@ -208,7 +230,7 @@ async def startup_event():
208
230
  logger.info("FastAPI application has started.")
209
231
 
210
232
  @app.on_event("shutdown")
211
- async def shutdown_event():
233
+ def shutdown_event():
212
234
  """Actions to perform on application shutdown."""
213
235
  if process_manager.is_running:
214
236
  process_manager.stop_live_processes()
@@ -232,11 +254,20 @@ async def websocket_stream_endpoint(websocket: WebSocket):
232
254
  raw_data = await websocket.receive_text()
233
255
  data = json.loads(raw_data)
234
256
  if data.get("type") == "user_message":
235
- user_message = {"username": data.get("username", "User"), "text": data.get("message", "").strip()}
257
+ user_message = {"username": data.get("username", "User"), "text": data.get("text", "").strip()}
236
258
  if user_message["text"]:
237
259
  add_to_audience_buffer(user_message)
238
260
  add_to_neuro_input_queue(user_message)
239
261
  await connection_manager.broadcast({"type": "chat_message", **user_message, "is_user_message": True})
262
+ elif data.get("type") == "superchat":
263
+ sc_message = {
264
+ "username": data.get("username", "User"),
265
+ "text": data.get("text", "").strip(),
266
+ "sc_type": data.get("sc_type", "bits")
267
+ }
268
+ if sc_message["text"]:
269
+ app_state.superchat_queue.append(sc_message)
270
+
240
271
  except WebSocketDisconnect:
241
272
  pass
242
273
  finally:
@@ -245,7 +276,10 @@ async def websocket_stream_endpoint(websocket: WebSocket):
245
276
  @app.websocket("/ws/admin")
246
277
  async def websocket_admin_endpoint(websocket: WebSocket):
247
278
  await websocket.accept()
279
+ # Add the new admin client to a dedicated list
280
+ connection_manager.admin_connections.append(websocket)
248
281
  try:
282
+ # Send initial state
249
283
  for log_entry in list(server_log_queue): await websocket.send_json({"type": "server_log", "data": log_entry})
250
284
  for log_entry in list(agent_log_queue): await websocket.send_json({"type": "agent_log", "data": log_entry})
251
285
 
@@ -253,15 +287,174 @@ async def websocket_admin_endpoint(websocket: WebSocket):
253
287
  initial_context = await agent.get_message_history()
254
288
  await websocket.send_json({"type": "agent_context", "action": "update", "messages": initial_context})
255
289
 
290
+ # Main loop for receiving messages from the client and pushing log updates
256
291
  while websocket.client_state == WebSocketState.CONNECTED:
292
+ # Check for incoming messages
293
+ try:
294
+ raw_data = await asyncio.wait_for(websocket.receive_text(), timeout=0.01)
295
+ data = json.loads(raw_data)
296
+ await handle_admin_ws_message(websocket, data)
297
+ except asyncio.TimeoutError:
298
+ pass # No message received, continue to push logs
299
+
300
+ # Push log updates
257
301
  if server_log_queue: await websocket.send_json({"type": "server_log", "data": server_log_queue.popleft()})
258
302
  if agent_log_queue: await websocket.send_json({"type": "agent_log", "data": agent_log_queue.popleft()})
259
303
  await asyncio.sleep(0.1)
304
+
260
305
  except WebSocketDisconnect:
261
306
  pass
262
307
  finally:
308
+ connection_manager.admin_connections.remove(websocket)
263
309
  logger.info("Admin WebSocket client disconnected.")
264
310
 
311
+ async def handle_admin_ws_message(websocket: WebSocket, data: dict):
312
+ """Handles incoming messages from the admin WebSocket."""
313
+ action = data.get("action")
314
+ payload = data.get("payload", {})
315
+ request_id = data.get("request_id")
316
+
317
+ agent = await create_agent()
318
+ response = {"type": "response", "request_id": request_id, "payload": {}}
319
+
320
+ try:
321
+ # Core Memory Actions
322
+ if action == "get_core_memory_blocks":
323
+ blocks = await agent.get_memory_blocks()
324
+ response["payload"] = blocks
325
+
326
+ elif action == "create_core_memory_block":
327
+ block_id = await agent.create_memory_block(**payload)
328
+ response["payload"] = {"status": "success", "block_id": block_id}
329
+ # Broadcast the update to all admins
330
+ updated_blocks = await agent.get_memory_blocks()
331
+ from ..utils.websocket import connection_manager
332
+ await connection_manager.broadcast_to_admins({"type": "core_memory_updated", "payload": updated_blocks})
333
+
334
+ elif action == "update_core_memory_block":
335
+ await agent.update_memory_block(**payload)
336
+ response["payload"] = {"status": "success"}
337
+ # Broadcast the update to all admins
338
+ updated_blocks = await agent.get_memory_blocks()
339
+ from ..utils.websocket import connection_manager
340
+ await connection_manager.broadcast_to_admins({"type": "core_memory_updated", "payload": updated_blocks})
341
+
342
+ elif action == "delete_core_memory_block":
343
+ await agent.delete_memory_block(**payload)
344
+ response["payload"] = {"status": "success"}
345
+ # Broadcast the update to all admins
346
+ updated_blocks = await agent.get_memory_blocks()
347
+ from ..utils.websocket import connection_manager
348
+ await connection_manager.broadcast_to_admins({"type": "core_memory_updated", "payload": updated_blocks})
349
+
350
+ # Temp Memory Actions
351
+ elif action == "get_temp_memory":
352
+ temp_mem = await agent.get_temp_memory()
353
+ response["payload"] = temp_mem
354
+
355
+ elif action == "add_temp_memory":
356
+ await agent.add_temp_memory(**payload)
357
+ response["payload"] = {"status": "success"}
358
+ updated_temp_mem = await agent.get_temp_memory()
359
+ from ..utils.websocket import connection_manager
360
+ await connection_manager.broadcast_to_admins({"type": "temp_memory_updated", "payload": updated_temp_mem})
361
+
362
+ elif action == "clear_temp_memory":
363
+ await agent.clear_temp_memory()
364
+ response["payload"] = {"status": "success"}
365
+ updated_temp_mem = await agent.get_temp_memory()
366
+ await connection_manager.broadcast_to_admins({"type": "temp_memory_updated", "payload": updated_temp_mem})
367
+
368
+ # Init Memory Actions
369
+ elif action == "get_init_memory":
370
+ init_mem = await agent.get_init_memory()
371
+ response["payload"] = init_mem
372
+
373
+ elif action == "update_init_memory":
374
+ await agent.update_init_memory(**payload)
375
+ response["payload"] = {"status": "success"}
376
+ updated_init_mem = await agent.get_init_memory()
377
+ from ..utils.websocket import connection_manager
378
+ await connection_manager.broadcast_to_admins({"type": "init_memory_updated", "payload": updated_init_mem})
379
+
380
+ # Tool Actions
381
+ elif action == "get_tools":
382
+ tools = await agent.get_available_tools()
383
+ response["payload"] = {"tools": tools}
384
+
385
+ elif action == "execute_tool":
386
+ result = await agent.execute_tool(**payload)
387
+ response["payload"] = {"result": result}
388
+
389
+ # Stream Control Actions
390
+ elif action == "start_stream":
391
+ if not process_manager.is_running:
392
+ process_manager.start_live_processes()
393
+ response["payload"] = {"status": "success", "message": "Stream started"}
394
+
395
+ elif action == "stop_stream":
396
+ if process_manager.is_running:
397
+ await process_manager.stop_live_processes()
398
+ response["payload"] = {"status": "success", "message": "Stream stopped"}
399
+
400
+ elif action == "restart_stream":
401
+ await process_manager.stop_live_processes()
402
+ await asyncio.sleep(1)
403
+ process_manager.start_live_processes()
404
+ response["payload"] = {"status": "success", "message": "Stream restarted"}
405
+
406
+ elif action == "get_stream_status":
407
+ status = {"is_running": process_manager.is_running, "backend_status": "running" if process_manager.is_running else "stopped"}
408
+ response["payload"] = status
409
+
410
+ # Config Management Actions
411
+ elif action == "get_configs":
412
+ from ..api.system import filter_config_for_frontend
413
+ configs = filter_config_for_frontend(config_manager.settings)
414
+ response["payload"] = configs
415
+
416
+ elif action == "update_configs":
417
+ from ..api.system import filter_config_for_frontend
418
+ await config_manager.update_settings(payload)
419
+ updated_configs = filter_config_for_frontend(config_manager.settings)
420
+ response["payload"] = updated_configs
421
+ await connection_manager.broadcast_to_admins({"type": "config_updated", "payload": updated_configs})
422
+
423
+ elif action == "reload_configs":
424
+ await config_manager.update_settings({})
425
+ response["payload"] = {"status": "success", "message": "Configuration reloaded"}
426
+ from ..api.system import filter_config_for_frontend
427
+ updated_configs = filter_config_for_frontend(config_manager.settings)
428
+ await connection_manager.broadcast_to_admins({"type": "config_updated", "payload": updated_configs})
429
+
430
+ # Other Agent Actions
431
+ elif action == "get_agent_context":
432
+ context = await agent.get_message_history()
433
+ response["payload"] = context
434
+
435
+ elif action == "reset_agent_memory":
436
+ await agent.reset_memory()
437
+ response["payload"] = {"status": "success"}
438
+ # Broadcast updates for all memory types
439
+ await connection_manager.broadcast_to_admins({"type": "core_memory_updated", "payload": await agent.get_memory_blocks()})
440
+ await connection_manager.broadcast_to_admins({"type": "temp_memory_updated", "payload": await agent.get_temp_memory()})
441
+ await connection_manager.broadcast_to_admins({"type": "init_memory_updated", "payload": await agent.get_init_memory()})
442
+ await connection_manager.broadcast_to_admins({"type": "agent_context", "action": "update", "messages": await agent.get_message_history()})
443
+
444
+ else:
445
+ response["payload"] = {"status": "error", "message": f"Unknown action: {action}"}
446
+
447
+ # Send the direct response to the requesting client
448
+ if request_id:
449
+ await websocket.send_json(response)
450
+
451
+ except Exception as e:
452
+ logger.error(f"Error handling admin WS message (action: {action}): {e}", exc_info=True)
453
+ if request_id:
454
+ response["payload"] = {"status": "error", "message": str(e)}
455
+ await websocket.send_json(response)
456
+
457
+
265
458
  # --- Server Entrypoint ---
266
459
 
267
460
  def run_server(host: str = None, port: int = None):
@@ -275,4 +468,4 @@ def run_server(host: str = None, port: int = None):
275
468
  host=server_host,
276
469
  port=server_port,
277
470
  reload=False
278
- )
471
+ )
@@ -37,8 +37,8 @@ class BuiltinAgentWrapper(BaseAgent):
37
37
  async def reset_memory(self):
38
38
  await self.agent_instance.reset_all_memory()
39
39
 
40
- async def process_messages(self, messages: List[Dict[str, str]]) -> Dict[str, Any]:
41
- return await self.agent_instance.process_messages(messages)
40
+ async def process_and_respond(self, messages: List[Dict[str, str]]) -> Dict[str, Any]:
41
+ return await self.agent_instance.process_and_respond(messages)
42
42
 
43
43
  # Memory Block Management
44
44
  async def get_memory_blocks(self) -> List[Dict[str, Any]]:
@@ -50,13 +50,25 @@ class BuiltinAgentWrapper(BaseAgent):
50
50
 
51
51
  async def create_memory_block(self, title: str, description: str, content: List[str]) -> Dict[str, str]:
52
52
  block_id = await self.agent_instance.memory_manager.create_core_memory_block(title, description, content)
53
+ # Broadcast core_memory_updated event
54
+ updated_blocks = await self.get_memory_blocks()
55
+ from ..utils.websocket import connection_manager
56
+ await connection_manager.broadcast_to_admins({"type": "core_memory_updated", "payload": updated_blocks})
53
57
  return {"block_id": block_id}
54
58
 
55
59
  async def update_memory_block(self, block_id: str, title: Optional[str], description: Optional[str], content: Optional[List[str]]):
56
60
  await self.agent_instance.memory_manager.update_core_memory_block(block_id, title, description, content)
61
+ # Broadcast core_memory_updated event
62
+ updated_blocks = await self.get_memory_blocks()
63
+ from ..utils.websocket import connection_manager
64
+ await connection_manager.broadcast_to_admins({"type": "core_memory_updated", "payload": updated_blocks})
57
65
 
58
66
  async def delete_memory_block(self, block_id: str):
59
67
  await self.agent_instance.memory_manager.delete_core_memory_block(block_id)
68
+ # Broadcast core_memory_updated event
69
+ updated_blocks = await self.get_memory_blocks()
70
+ from ..utils.websocket import connection_manager
71
+ await connection_manager.broadcast_to_admins({"type": "core_memory_updated", "payload": updated_blocks})
60
72
 
61
73
  # Init Memory Management
62
74
  async def get_init_memory(self) -> Dict[str, Any]:
@@ -64,6 +76,10 @@ class BuiltinAgentWrapper(BaseAgent):
64
76
 
65
77
  async def update_init_memory(self, memory: Dict[str, Any]):
66
78
  await self.agent_instance.memory_manager.update_init_memory(memory)
79
+ # Broadcast init_memory_updated event
80
+ updated_init_mem = await self.get_init_memory()
81
+ from ..utils.websocket import connection_manager
82
+ await connection_manager.broadcast_to_admins({"type": "init_memory_updated", "payload": updated_init_mem})
67
83
 
68
84
  # Temp Memory Management
69
85
  async def get_temp_memory(self) -> List[Dict[str, Any]]:
@@ -71,17 +87,31 @@ class BuiltinAgentWrapper(BaseAgent):
71
87
 
72
88
  async def add_temp_memory(self, content: str, role: str):
73
89
  await self.agent_instance.memory_manager.add_temp_memory(content, role)
90
+ # Broadcast temp_memory_updated event
91
+ updated_temp_mem = await self.get_temp_memory()
92
+ from ..utils.websocket import connection_manager
93
+ await connection_manager.broadcast_to_admins({"type": "temp_memory_updated", "payload": updated_temp_mem})
74
94
 
75
95
  async def clear_temp_memory(self):
76
96
  await self.agent_instance.memory_manager.reset_temp_memory()
97
+ # Broadcast temp_memory_updated event
98
+ updated_temp_mem = await self.get_temp_memory()
99
+ from ..utils.websocket import connection_manager
100
+ await connection_manager.broadcast_to_admins({"type": "temp_memory_updated", "payload": updated_temp_mem})
77
101
 
78
102
  # Tool Management
79
103
  async def get_available_tools(self) -> str:
80
104
  return self.agent_instance.tool_manager.get_tool_descriptions()
81
105
 
82
106
  async def execute_tool(self, tool_name: str, params: Dict[str, Any]) -> Any:
83
- return await self.agent_instance.execute_tool(tool_name, params)
107
+ result = await self.agent_instance.execute_tool(tool_name, params)
108
+ # If the tool was add_temp_memory, broadcast temp_memory_updated event
109
+ if tool_name == "add_temp_memory":
110
+ updated_temp_mem = await self.get_temp_memory()
111
+ from ..utils.websocket import connection_manager
112
+ await connection_manager.broadcast_to_admins({"type": "temp_memory_updated", "payload": updated_temp_mem})
113
+ return result
84
114
 
85
115
  # Context/Message History
86
116
  async def get_message_history(self, limit: int = 20) -> List[Dict[str, Any]]:
87
- return await self.agent_instance.memory_manager.get_recent_context(limit)
117
+ return await self.agent_instance.memory_manager.get_recent_chat(limit)
@@ -74,8 +74,38 @@ class LettaAgent(BaseAgent):
74
74
  logger.warning(f"Failed to reset Letta Agent message history: {e}")
75
75
 
76
76
  async def process_messages(self, messages: List[Dict[str, str]]) -> Dict[str, Any]:
77
- if messages:
78
- injected_chat_lines = [f"{chat['username']}: {chat['text']}" for chat in messages]
77
+ # Check if this is a superchat message based on the specific structure
78
+ # from neuro_response_cycle
79
+ is_superchat = (
80
+ len(messages) == 2 and
81
+ messages[0].get("role") == "system" and
82
+ messages[1].get("role") == "system" and
83
+ "HIGHLIGHTED MESSAGE" in messages[1].get("content", "")
84
+ )
85
+
86
+ if is_superchat:
87
+ try:
88
+ # Extract username and text from the superchat message
89
+ # Format is "=== HIGHLIGHTED MESSAGE ===\n{username}: {text}"
90
+ content_lines = messages[1]["content"].split('\n', 1)
91
+ user_and_text = content_lines[1]
92
+ parts = user_and_text.split(':', 1)
93
+ sc_username = parts[0].strip()
94
+ sc_text = parts[1].strip()
95
+ injected_chat_lines = [f"{sc_username}: {sc_text}"]
96
+ injected_chat_text = (
97
+ "Here is a highlighted message from my Twitch chat:\n---\n" +
98
+ "\n".join(injected_chat_lines) +
99
+ "\n---\nNow, as the streamer Neuro-Sama, please continue the conversation naturally."
100
+ )
101
+ logger.info(f"Processing highlighted message for Letta: {injected_chat_lines[0]}")
102
+ except (IndexError, AttributeError) as e:
103
+ logger.error(f"Failed to parse superchat for Letta, falling back. Error: {e}")
104
+ # Fallback to default empty prompt if parsing fails
105
+ injected_chat_text = "My chat is quiet right now. As Neuro-Sama, what should I say to engage them?"
106
+
107
+ elif messages:
108
+ injected_chat_lines = [f"{chat['username']}: {chat['text']}" for chat in messages if 'username' in chat and 'text' in chat]
79
109
  injected_chat_text = (
80
110
  "Here are some recent messages from my Twitch chat:\n---\n" +
81
111
  "\n".join(injected_chat_lines) +
@@ -6,6 +6,7 @@ from collections import deque
6
6
  from pathlib import Path
7
7
 
8
8
  from ..core.config import config_manager
9
+ from ..utils.state import app_state
9
10
 
10
11
  logger = logging.getLogger(__name__.replace("neuro_simulator", "server", 1))
11
12
 
@@ -17,7 +18,8 @@ def clear_all_queues():
17
18
  """Clears all chat queues."""
18
19
  audience_chat_buffer.clear()
19
20
  neuro_input_queue.clear()
20
- logger.info("All chat queues have been cleared.")
21
+ app_state.superchat_queue.clear()
22
+ logger.info("All chat queues (including superchats) have been cleared.")
21
23
 
22
24
  def add_to_audience_buffer(chat_item: dict):
23
25
  """Adds a chat item to the audience buffer."""
@@ -2,6 +2,8 @@
2
2
  """Manages the shared state of the application using a singleton class."""
3
3
 
4
4
  import asyncio
5
+ import time
6
+ from collections import deque
5
7
 
6
8
  class AppState:
7
9
  """A singleton class to hold all shared application state."""
@@ -9,6 +11,8 @@ class AppState:
9
11
  self.live_phase_started_event = asyncio.Event()
10
12
  self.neuro_last_speech_lock = asyncio.Lock()
11
13
  self.neuro_last_speech: str = "Neuro-Sama has just started the stream and hasn't said anything yet."
14
+ self.superchat_queue = deque()
15
+ self.last_superchat_time: float = 0.0
12
16
 
13
17
  # Create a single, globally accessible instance of the AppState.
14
- app_state = AppState()
18
+ app_state = AppState()
@@ -12,7 +12,8 @@ logger = logging.getLogger(__name__.replace("neuro_simulator", "server", 1))
12
12
  class WebSocketManager:
13
13
  """Manages all active WebSocket connections and provides broadcasting capabilities."""
14
14
  def __init__(self):
15
- self.active_connections: deque[WebSocket] = deque()
15
+ self.active_connections: list[WebSocket] = []
16
+ self.admin_connections: list[WebSocket] = []
16
17
  logger.info("WebSocketManager initialized.")
17
18
 
18
19
  async def connect(self, websocket: WebSocket):
@@ -37,19 +38,15 @@ class WebSocketManager:
37
38
  self.disconnect(websocket)
38
39
 
39
40
  async def broadcast(self, message: dict):
40
- disconnected_sockets = []
41
- for connection in list(self.active_connections):
42
- if connection.client_state == WebSocketState.CONNECTED:
43
- try:
44
- await connection.send_json(message)
45
- except Exception as e:
46
- logger.warning(f"Could not broadcast message to client {connection}, it may have disconnected: {e}")
47
- disconnected_sockets.append(connection)
48
- else:
49
- disconnected_sockets.append(connection)
50
-
51
- for disconnected_socket in disconnected_sockets:
52
- self.disconnect(disconnected_socket)
41
+ for connection in self.active_connections:
42
+ await connection.send_json(message)
43
+
44
+ async def broadcast_to_admins(self, message: dict):
45
+ for connection in self.admin_connections:
46
+ try:
47
+ await connection.send_json(message)
48
+ except Exception as e:
49
+ logger.error(f"Failed to send message to admin connection: {e}")
53
50
 
54
51
  # Global singleton instance
55
52
  connection_manager = WebSocketManager()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: neuro_simulator
3
- Version: 0.2.2
3
+ Version: 0.3.1
4
4
  Summary: Neuro Simulator Server
5
5
  Author-email: Moha-Master <hongkongreporter@outlook.com>
6
6
  License-Expression: MIT
@@ -69,7 +69,7 @@ neuro_simulator/
69
69
  │ ├── memory/ # 记忆管理模块
70
70
  │ │ ├── __init__.py
71
71
  │ │ ├── manager.py # 记忆管理器
72
- │ │ ├── context.json # 上下文记忆文件
72
+ │ │ ├── chat_history.json # 上下文记忆文件
73
73
  │ │ ├── core_memory.json # 核心记忆文件
74
74
  │ │ ├── init_memory.json # 初始化记忆文件
75
75
  │ │ └── temp_memory.json # 临时记忆文件
@@ -109,7 +109,7 @@ working_dir_example/ # 工作目录结构,请将这个目录重命名和
109
109
  ├── config.yaml.example # 自动生成的配置文件模板,必须手动重命名和填写
110
110
  └── agent/ # Agent相关文件夹
111
111
  └── memory/ # Agent记忆文件夹
112
- ├── context.json # 上下文记忆文件
112
+ ├── chat_history.json # 上下文记忆文件
113
113
  ├── core_memory.json # 核心记忆文件
114
114
  ├── init_memory.json # 初始化记忆文件
115
115
  └── temp_memory.json # 临时记忆文件
@@ -191,7 +191,6 @@ neuro -D /path/to/your/config -H 0.0.0.0 -P 8080
191
191
  - `/api/configs/*` - 配置管理接口(获取/更新/重载配置)
192
192
  - `api_keys` `server` 等敏感配置项无法从接口获取和修改
193
193
  - `/api/logs` - 日志获取接口
194
- - `/api/tts/synthesize` - TTS 合成接口
195
194
  - `/api/system/health` - 健康检查接口
196
195
  - `/ws/stream` - 客户端使用的直播接口
197
196
  - `/ws/admin` - 日志和内建 Agent的 Context 流接口
@@ -1,37 +1,36 @@
1
1
  neuro_simulator/__init__.py,sha256=-tposzyvg6UckPcfSvtc03UjxBa9oCe_zRvlKf8splk,31
2
- neuro_simulator/cli.py,sha256=p2jSNbMsQ2HYau-EX3ygmTRhECU9dbSg0v53xgYjOZ4,3894
2
+ neuro_simulator/cli.py,sha256=Nc-udO0jdRVZjlbebKBjDVOIUzd6tJr13ApBGeBEg2k,3967
3
3
  neuro_simulator/agent/__init__.py,sha256=t52CZlyTGWqcGjMs90qvpFpRckY2WSSlO7r_H3K_mSY,32
4
4
  neuro_simulator/agent/base.py,sha256=6v2ZO5UpGCwJEkJ23Oe96Rs510tK4ZOEpZ2DB49IZmM,1262
5
- neuro_simulator/agent/core.py,sha256=CJv0We7ZjW_EKQB54Xq-y3wDu2a2HmoaOAdYR057HOg,8941
5
+ neuro_simulator/agent/core.py,sha256=2mPVCcNKZDRsyYd6L8RzQYlm8LwzoKoP9FJg0W4qcbc,10702
6
6
  neuro_simulator/agent/factory.py,sha256=e0IBnqJQM7OuKtglrf-pWwqwmg98wh7tOq5LxF2rV-w,1146
7
7
  neuro_simulator/agent/llm.py,sha256=vLz8hp2h2R0JaNfS1RLGYGkri_YoUdlEdNfFVbxeEuI,4261
8
8
  neuro_simulator/agent/memory/__init__.py,sha256=YJ7cynQJI6kD7vjyv3rKc-CZqmoYSuGQtRZl_XdGEps,39
9
- neuro_simulator/agent/memory/manager.py,sha256=z5ZI1agkuOev5gtuGA_g6MS3atB7ufdPRVNZZ89yg1w,9259
9
+ neuro_simulator/agent/memory/manager.py,sha256=UiUJgjiTV7SHCmb3V5sc4OUa_ksEeXBOyvl-WBQviqs,9266
10
10
  neuro_simulator/agent/tools/__init__.py,sha256=1WZy6PADfi6o1avyy1y-ThWBFAPJ_bBqtkobyYpf5ao,38
11
11
  neuro_simulator/agent/tools/core.py,sha256=o6Oyis-HFD-g6Z_u3T--tkmr9ylKJvybKqMRSMUwi1Q,5555
12
12
  neuro_simulator/api/__init__.py,sha256=5LWyDSayPGdQS8Rv13nmAKLyhPnMVPyTYDdvoMPB4xw,56
13
- neuro_simulator/api/agent.py,sha256=ABl_JoIxB4wW_J2J52bWndmTXkfGJBS5LZmbGuh7zv8,6343
14
- neuro_simulator/api/stream.py,sha256=Yg-cwjVI2HTLAt7moWbDQ1ZbbP6QE1ZB8LrW6A3tcQk,2081
15
- neuro_simulator/api/system.py,sha256=hXznMcThuFhwopYWgpzrRxwtBuFnF_b_vinkOaE5XOs,3712
13
+ neuro_simulator/api/stream.py,sha256=hM66flSUygpE-NH9X-ZOV6SiGipBzN1-wjd_wZRpQm4,94
14
+ neuro_simulator/api/system.py,sha256=TV_3DzP-VgLnHdue0pKYFFQNOV_V7tr4aMuxL802vQg,1783
16
15
  neuro_simulator/core/__init__.py,sha256=-ojq25c8XA0CU25b0OxcGjH4IWFEDHR-HXSRSZIuKe8,57
17
16
  neuro_simulator/core/agent_factory.py,sha256=qMFidwT5IrOkyNHwmpO8_fRv20KLbaIBfWF-VTFCLNA,1742
18
- neuro_simulator/core/agent_interface.py,sha256=r58Opcgs7SWVovYTjMWuxF8AiTy9QfRz276_YGmSei0,2791
19
- neuro_simulator/core/application.py,sha256=zN8KOR_nwsYsR1ZcyZU1GlW3-ijFLbjw5lz1g8DYVIU,11578
17
+ neuro_simulator/core/agent_interface.py,sha256=ZXUCtkQUvsBQ5iCb0gTILJaShn5KmSrEgKhd7PK18HE,2794
18
+ neuro_simulator/core/application.py,sha256=lhTn5KR7ek8-kuyD1qWtppImUUz8pOExH9KRNW1SQ3M,21115
20
19
  neuro_simulator/core/config.py,sha256=brA8kiekV_995mpz04JiGj1swIWbZZuWWLNYtbroMyE,14884
21
20
  neuro_simulator/services/__init__.py,sha256=s3ZrAHg5TpJakadAAGY1h0wDw_xqN4Je4aJwJyRBmk4,61
22
21
  neuro_simulator/services/audience.py,sha256=0phlhsujh_GMXm_UMiyOntY-ZMtoseRa_FroIfc5A6w,5028
23
22
  neuro_simulator/services/audio.py,sha256=ZscQA25wVYpm9FUl4Hya7tKH8t0TjR3th9-OEZ0G7xk,2934
24
- neuro_simulator/services/builtin.py,sha256=7ePxEom5HIK6wGto_H5M8JOnAjyiHqUuE381DEGgzjE,3821
25
- neuro_simulator/services/letta.py,sha256=iXyzFyPVty3SjYCHOJAF1QqhUFmxTQbqk8lYJOwB5pc,9415
23
+ neuro_simulator/services/builtin.py,sha256=nn3sJFPy09JxQkw35icdyGU9hzLTXXazAJkNpdcz6Zs,5848
24
+ neuro_simulator/services/letta.py,sha256=6jBvOTsLMlRILDv-fvX9fhHMONSYeu-ImJGFcKU00kc,11067
26
25
  neuro_simulator/services/stream.py,sha256=dG7RuNI_ICohPkqKZ-zlBppo54BgWm_KYBs-ezzc73E,5907
27
26
  neuro_simulator/utils/__init__.py,sha256=xSEFzjT827W81mNyQ_DLtr00TgFlttqfFgpz9pSxFXQ,58
28
27
  neuro_simulator/utils/logging.py,sha256=BO-q_cCcoeamsc8eJqq2-L3Z8nhApze_v6LnmD-O8Ww,3411
29
28
  neuro_simulator/utils/process.py,sha256=9w2JQH59Wy6L8ADrig2QF88iajdykGPZIYJVJe6Al2Y,2603
30
- neuro_simulator/utils/queue.py,sha256=7SSnUnrqxHkqSeYVjp1S5kpr8qlo4IVdU2NsGwFQAVw,1546
31
- neuro_simulator/utils/state.py,sha256=E1ilecgMTOAhiw_kNvLG0akkhdZKhzKLrA3oB4NNVTA,538
32
- neuro_simulator/utils/websocket.py,sha256=yOdFvJzbNhcUn5EAuyS55G_R8q-snas5OvkOtS8g19E,2292
33
- neuro_simulator-0.2.2.dist-info/METADATA,sha256=lBjb1G0VhfbDCQhRWQOxJzlt9Ut07XL6zApn6X6G_jo,8676
34
- neuro_simulator-0.2.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
35
- neuro_simulator-0.2.2.dist-info/entry_points.txt,sha256=qVd5ypnRRgU8Cw7rWfZ7o0OXyS9P9hgY-cRoN_mgz9g,51
36
- neuro_simulator-0.2.2.dist-info/top_level.txt,sha256=V8awSKpcrFnjJDiJxSfy7jtOrnuE2BgAR9hLmfMDWK8,16
37
- neuro_simulator-0.2.2.dist-info/RECORD,,
29
+ neuro_simulator/utils/queue.py,sha256=vSkh-BrgfsGN_gDAx2mfK44ydmMapdVyLsDG-7LIJZQ,1643
30
+ neuro_simulator/utils/state.py,sha256=DdBqSAYfjOFtJfB1hEGhYPh32r1ZvFuVlN_-29_-luA,664
31
+ neuro_simulator/utils/websocket.py,sha256=1gtVoH1hafBUfVYmwkVDAbjwETeqyC3sWx706nQzSRo,2085
32
+ neuro_simulator-0.3.1.dist-info/METADATA,sha256=lQv9x0KvOZJAA8NwZ8byIaHYTVnSxuHRPyhUyqLC6vw,8643
33
+ neuro_simulator-0.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
34
+ neuro_simulator-0.3.1.dist-info/entry_points.txt,sha256=qVd5ypnRRgU8Cw7rWfZ7o0OXyS9P9hgY-cRoN_mgz9g,51
35
+ neuro_simulator-0.3.1.dist-info/top_level.txt,sha256=V8awSKpcrFnjJDiJxSfy7jtOrnuE2BgAR9hLmfMDWK8,16
36
+ neuro_simulator-0.3.1.dist-info/RECORD,,