neuro-simulator 0.3.0__py3-none-any.whl → 0.3.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.
- neuro_simulator/agent/core.py +163 -130
- neuro_simulator/agent/memory/manager.py +26 -26
- neuro_simulator/api/stream.py +1 -55
- neuro_simulator/api/system.py +32 -59
- neuro_simulator/cli.py +3 -2
- neuro_simulator/core/agent_interface.py +1 -1
- neuro_simulator/core/application.py +197 -5
- neuro_simulator/services/builtin.py +34 -4
- neuro_simulator/utils/process.py +8 -0
- neuro_simulator/utils/websocket.py +11 -14
- {neuro_simulator-0.3.0.dist-info → neuro_simulator-0.3.2.dist-info}/METADATA +3 -4
- {neuro_simulator-0.3.0.dist-info → neuro_simulator-0.3.2.dist-info}/RECORD +15 -16
- neuro_simulator/api/agent.py +0 -163
- {neuro_simulator-0.3.0.dist-info → neuro_simulator-0.3.2.dist-info}/WHEEL +0 -0
- {neuro_simulator-0.3.0.dist-info → neuro_simulator-0.3.2.dist-info}/entry_points.txt +0 -0
- {neuro_simulator-0.3.0.dist-info → neuro_simulator-0.3.2.dist-info}/top_level.txt +0 -0
@@ -21,8 +21,6 @@ from ..services.letta import LettaAgent
|
|
21
21
|
from ..services.builtin import BuiltinAgentWrapper
|
22
22
|
|
23
23
|
# --- API Routers ---
|
24
|
-
from ..api.agent import router as agent_router
|
25
|
-
from ..api.stream import router as stream_router
|
26
24
|
from ..api.system import router as system_router
|
27
25
|
|
28
26
|
# --- Services and Utilities ---
|
@@ -60,8 +58,6 @@ app.add_middleware(
|
|
60
58
|
expose_headers=["X-API-Token"],
|
61
59
|
)
|
62
60
|
|
63
|
-
app.include_router(agent_router)
|
64
|
-
app.include_router(stream_router)
|
65
61
|
app.include_router(system_router)
|
66
62
|
|
67
63
|
# --- Background Task Definitions ---
|
@@ -167,7 +163,7 @@ async def neuro_response_cycle():
|
|
167
163
|
if not selected_chats:
|
168
164
|
continue
|
169
165
|
|
170
|
-
response_result = await asyncio.wait_for(agent.
|
166
|
+
response_result = await asyncio.wait_for(agent.process_and_respond(selected_chats), timeout=20.0)
|
171
167
|
|
172
168
|
response_text = response_result.get("final_response", "").strip()
|
173
169
|
if not response_text:
|
@@ -280,7 +276,10 @@ async def websocket_stream_endpoint(websocket: WebSocket):
|
|
280
276
|
@app.websocket("/ws/admin")
|
281
277
|
async def websocket_admin_endpoint(websocket: WebSocket):
|
282
278
|
await websocket.accept()
|
279
|
+
# Add the new admin client to a dedicated list
|
280
|
+
connection_manager.admin_connections.append(websocket)
|
283
281
|
try:
|
282
|
+
# Send initial state
|
284
283
|
for log_entry in list(server_log_queue): await websocket.send_json({"type": "server_log", "data": log_entry})
|
285
284
|
for log_entry in list(agent_log_queue): await websocket.send_json({"type": "agent_log", "data": log_entry})
|
286
285
|
|
@@ -288,15 +287,208 @@ async def websocket_admin_endpoint(websocket: WebSocket):
|
|
288
287
|
initial_context = await agent.get_message_history()
|
289
288
|
await websocket.send_json({"type": "agent_context", "action": "update", "messages": initial_context})
|
290
289
|
|
290
|
+
# Send initial stream status
|
291
|
+
status = {"is_running": process_manager.is_running, "backend_status": "running" if process_manager.is_running else "stopped"}
|
292
|
+
await websocket.send_json({"type": "stream_status", "payload": status})
|
293
|
+
|
294
|
+
# Main loop for receiving messages from the client and pushing log updates
|
291
295
|
while websocket.client_state == WebSocketState.CONNECTED:
|
296
|
+
# Check for incoming messages
|
297
|
+
try:
|
298
|
+
raw_data = await asyncio.wait_for(websocket.receive_text(), timeout=0.01)
|
299
|
+
data = json.loads(raw_data)
|
300
|
+
await handle_admin_ws_message(websocket, data)
|
301
|
+
except asyncio.TimeoutError:
|
302
|
+
pass # No message received, continue to push logs
|
303
|
+
|
304
|
+
# Push log updates
|
292
305
|
if server_log_queue: await websocket.send_json({"type": "server_log", "data": server_log_queue.popleft()})
|
293
306
|
if agent_log_queue: await websocket.send_json({"type": "agent_log", "data": agent_log_queue.popleft()})
|
294
307
|
await asyncio.sleep(0.1)
|
308
|
+
|
295
309
|
except WebSocketDisconnect:
|
296
310
|
pass
|
297
311
|
finally:
|
312
|
+
connection_manager.admin_connections.remove(websocket)
|
298
313
|
logger.info("Admin WebSocket client disconnected.")
|
299
314
|
|
315
|
+
async def handle_admin_ws_message(websocket: WebSocket, data: dict):
|
316
|
+
"""Handles incoming messages from the admin WebSocket."""
|
317
|
+
action = data.get("action")
|
318
|
+
payload = data.get("payload", {})
|
319
|
+
request_id = data.get("request_id")
|
320
|
+
|
321
|
+
agent = await create_agent()
|
322
|
+
response = {"type": "response", "request_id": request_id, "payload": {}}
|
323
|
+
|
324
|
+
try:
|
325
|
+
# Core Memory Actions
|
326
|
+
if action == "get_core_memory_blocks":
|
327
|
+
blocks = await agent.get_memory_blocks()
|
328
|
+
response["payload"] = blocks
|
329
|
+
|
330
|
+
elif action == "create_core_memory_block":
|
331
|
+
block_id = await agent.create_memory_block(**payload)
|
332
|
+
response["payload"] = {"status": "success", "block_id": block_id}
|
333
|
+
# Broadcast the update to all admins
|
334
|
+
updated_blocks = await agent.get_memory_blocks()
|
335
|
+
from ..utils.websocket import connection_manager
|
336
|
+
await connection_manager.broadcast_to_admins({"type": "core_memory_updated", "payload": updated_blocks})
|
337
|
+
|
338
|
+
elif action == "update_core_memory_block":
|
339
|
+
await agent.update_memory_block(**payload)
|
340
|
+
response["payload"] = {"status": "success"}
|
341
|
+
# Broadcast the update to all admins
|
342
|
+
updated_blocks = await agent.get_memory_blocks()
|
343
|
+
from ..utils.websocket import connection_manager
|
344
|
+
await connection_manager.broadcast_to_admins({"type": "core_memory_updated", "payload": updated_blocks})
|
345
|
+
|
346
|
+
elif action == "delete_core_memory_block":
|
347
|
+
await agent.delete_memory_block(**payload)
|
348
|
+
response["payload"] = {"status": "success"}
|
349
|
+
# Broadcast the update to all admins
|
350
|
+
updated_blocks = await agent.get_memory_blocks()
|
351
|
+
from ..utils.websocket import connection_manager
|
352
|
+
await connection_manager.broadcast_to_admins({"type": "core_memory_updated", "payload": updated_blocks})
|
353
|
+
|
354
|
+
# Temp Memory Actions
|
355
|
+
elif action == "get_temp_memory":
|
356
|
+
temp_mem = await agent.get_temp_memory()
|
357
|
+
response["payload"] = temp_mem
|
358
|
+
|
359
|
+
elif action == "add_temp_memory":
|
360
|
+
await agent.add_temp_memory(**payload)
|
361
|
+
response["payload"] = {"status": "success"}
|
362
|
+
updated_temp_mem = await agent.get_temp_memory()
|
363
|
+
from ..utils.websocket import connection_manager
|
364
|
+
await connection_manager.broadcast_to_admins({"type": "temp_memory_updated", "payload": updated_temp_mem})
|
365
|
+
|
366
|
+
elif action == "clear_temp_memory":
|
367
|
+
await agent.clear_temp_memory()
|
368
|
+
response["payload"] = {"status": "success"}
|
369
|
+
updated_temp_mem = await agent.get_temp_memory()
|
370
|
+
await connection_manager.broadcast_to_admins({"type": "temp_memory_updated", "payload": updated_temp_mem})
|
371
|
+
|
372
|
+
# Init Memory Actions
|
373
|
+
elif action == "get_init_memory":
|
374
|
+
init_mem = await agent.get_init_memory()
|
375
|
+
response["payload"] = init_mem
|
376
|
+
|
377
|
+
elif action == "update_init_memory":
|
378
|
+
await agent.update_init_memory(**payload)
|
379
|
+
response["payload"] = {"status": "success"}
|
380
|
+
updated_init_mem = await agent.get_init_memory()
|
381
|
+
from ..utils.websocket import connection_manager
|
382
|
+
await connection_manager.broadcast_to_admins({"type": "init_memory_updated", "payload": updated_init_mem})
|
383
|
+
|
384
|
+
# Tool Actions
|
385
|
+
elif action == "get_tools":
|
386
|
+
tools = await agent.get_available_tools()
|
387
|
+
response["payload"] = {"tools": tools}
|
388
|
+
|
389
|
+
elif action == "execute_tool":
|
390
|
+
result = await agent.execute_tool(**payload)
|
391
|
+
response["payload"] = {"result": result}
|
392
|
+
|
393
|
+
# Stream Control Actions
|
394
|
+
elif action == "start_stream":
|
395
|
+
if not process_manager.is_running:
|
396
|
+
process_manager.start_live_processes()
|
397
|
+
response["payload"] = {"status": "success", "message": "Stream started"}
|
398
|
+
# Broadcast stream status update
|
399
|
+
from ..utils.websocket import connection_manager
|
400
|
+
status = {"is_running": process_manager.is_running, "backend_status": "running" if process_manager.is_running else "stopped"}
|
401
|
+
await connection_manager.broadcast_to_admins({"type": "stream_status", "payload": status})
|
402
|
+
|
403
|
+
elif action == "stop_stream":
|
404
|
+
if process_manager.is_running:
|
405
|
+
await process_manager.stop_live_processes()
|
406
|
+
response["payload"] = {"status": "success", "message": "Stream stopped"}
|
407
|
+
# Broadcast stream status update
|
408
|
+
from ..utils.websocket import connection_manager
|
409
|
+
status = {"is_running": process_manager.is_running, "backend_status": "running" if process_manager.is_running else "stopped"}
|
410
|
+
await connection_manager.broadcast_to_admins({"type": "stream_status", "payload": status})
|
411
|
+
|
412
|
+
elif action == "restart_stream":
|
413
|
+
await process_manager.stop_live_processes()
|
414
|
+
await asyncio.sleep(1)
|
415
|
+
process_manager.start_live_processes()
|
416
|
+
response["payload"] = {"status": "success", "message": "Stream restarted"}
|
417
|
+
# Broadcast stream status update
|
418
|
+
from ..utils.websocket import connection_manager
|
419
|
+
status = {"is_running": process_manager.is_running, "backend_status": "running" if process_manager.is_running else "stopped"}
|
420
|
+
await connection_manager.broadcast_to_admins({"type": "stream_status", "payload": status})
|
421
|
+
|
422
|
+
elif action == "get_stream_status":
|
423
|
+
status = {"is_running": process_manager.is_running, "backend_status": "running" if process_manager.is_running else "stopped"}
|
424
|
+
response["payload"] = status
|
425
|
+
|
426
|
+
# Config Management Actions
|
427
|
+
elif action == "get_configs":
|
428
|
+
from ..api.system import filter_config_for_frontend
|
429
|
+
configs = filter_config_for_frontend(config_manager.settings)
|
430
|
+
response["payload"] = configs
|
431
|
+
|
432
|
+
elif action == "update_configs":
|
433
|
+
from ..api.system import filter_config_for_frontend
|
434
|
+
await config_manager.update_settings(payload)
|
435
|
+
updated_configs = filter_config_for_frontend(config_manager.settings)
|
436
|
+
response["payload"] = updated_configs
|
437
|
+
await connection_manager.broadcast_to_admins({"type": "config_updated", "payload": updated_configs})
|
438
|
+
|
439
|
+
elif action == "reload_configs":
|
440
|
+
await config_manager.update_settings({})
|
441
|
+
response["payload"] = {"status": "success", "message": "Configuration reloaded"}
|
442
|
+
from ..api.system import filter_config_for_frontend
|
443
|
+
updated_configs = filter_config_for_frontend(config_manager.settings)
|
444
|
+
await connection_manager.broadcast_to_admins({"type": "config_updated", "payload": updated_configs})
|
445
|
+
|
446
|
+
# Other Agent Actions
|
447
|
+
elif action == "get_agent_context":
|
448
|
+
context = await agent.get_message_history()
|
449
|
+
response["payload"] = context
|
450
|
+
|
451
|
+
elif action == "get_last_prompt":
|
452
|
+
# Check if the agent supports prompt generation introspection
|
453
|
+
agent_instance = getattr(agent, 'agent_instance', None) if hasattr(agent, 'agent_instance') else agent
|
454
|
+
if not hasattr(agent_instance, 'memory_manager') or not hasattr(agent_instance.memory_manager, 'get_recent_chat') or not hasattr(agent_instance, '_build_neuro_prompt'):
|
455
|
+
response["payload"] = {"status": "error", "message": "The active agent does not support prompt generation introspection."}
|
456
|
+
else:
|
457
|
+
recent_history = await agent_instance.memory_manager.get_recent_chat(entries=10)
|
458
|
+
messages_for_prompt = []
|
459
|
+
for entry in recent_history:
|
460
|
+
if entry.get('role') == 'user':
|
461
|
+
parts = entry.get('content', '').split(':', 1)
|
462
|
+
if len(parts) == 2:
|
463
|
+
messages_for_prompt.append({'username': parts[0].strip(), 'text': parts[1].strip()})
|
464
|
+
else:
|
465
|
+
messages_for_prompt.append({'username': 'user', 'text': entry.get('content', '')})
|
466
|
+
prompt = await agent_instance._build_neuro_prompt(messages_for_prompt)
|
467
|
+
response["payload"] = {"prompt": prompt}
|
468
|
+
|
469
|
+
elif action == "reset_agent_memory":
|
470
|
+
await agent.reset_memory()
|
471
|
+
response["payload"] = {"status": "success"}
|
472
|
+
# Broadcast updates for all memory types
|
473
|
+
await connection_manager.broadcast_to_admins({"type": "core_memory_updated", "payload": await agent.get_memory_blocks()})
|
474
|
+
await connection_manager.broadcast_to_admins({"type": "temp_memory_updated", "payload": await agent.get_temp_memory()})
|
475
|
+
await connection_manager.broadcast_to_admins({"type": "init_memory_updated", "payload": await agent.get_init_memory()})
|
476
|
+
await connection_manager.broadcast_to_admins({"type": "agent_context", "action": "update", "messages": await agent.get_message_history()})
|
477
|
+
|
478
|
+
else:
|
479
|
+
response["payload"] = {"status": "error", "message": f"Unknown action: {action}"}
|
480
|
+
|
481
|
+
# Send the direct response to the requesting client
|
482
|
+
if request_id:
|
483
|
+
await websocket.send_json(response)
|
484
|
+
|
485
|
+
except Exception as e:
|
486
|
+
logger.error(f"Error handling admin WS message (action: {action}): {e}", exc_info=True)
|
487
|
+
if request_id:
|
488
|
+
response["payload"] = {"status": "error", "message": str(e)}
|
489
|
+
await websocket.send_json(response)
|
490
|
+
|
491
|
+
|
300
492
|
# --- Server Entrypoint ---
|
301
493
|
|
302
494
|
def run_server(host: str = None, port: int = None):
|
@@ -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
|
41
|
-
return await self.agent_instance.
|
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
|
-
|
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.
|
117
|
+
return await self.agent_instance.memory_manager.get_recent_chat(limit)
|
neuro_simulator/utils/process.py
CHANGED
@@ -33,6 +33,7 @@ class ProcessManager:
|
|
33
33
|
from ..core.application import generate_audience_chat_task, neuro_response_cycle, broadcast_events_task
|
34
34
|
from ..utils.queue import clear_all_queues
|
35
35
|
from ..core.agent_factory import create_agent
|
36
|
+
from ..utils.websocket import connection_manager
|
36
37
|
|
37
38
|
asyncio.create_task(create_agent())
|
38
39
|
|
@@ -45,6 +46,9 @@ class ProcessManager:
|
|
45
46
|
self._tasks.append(asyncio.create_task(neuro_response_cycle()))
|
46
47
|
|
47
48
|
self._is_running = True
|
49
|
+
# Broadcast stream status update
|
50
|
+
status = {"is_running": self._is_running, "backend_status": "running" if self._is_running else "stopped"}
|
51
|
+
asyncio.create_task(connection_manager.broadcast_to_admins({"type": "stream_status", "payload": status}))
|
48
52
|
logger.info(f"Core processes started: {len(self._tasks)} tasks.")
|
49
53
|
|
50
54
|
async def stop_live_processes(self):
|
@@ -66,6 +70,10 @@ class ProcessManager:
|
|
66
70
|
|
67
71
|
live_stream_manager.reset_stream_state()
|
68
72
|
|
73
|
+
# Broadcast stream status update
|
74
|
+
status = {"is_running": self._is_running, "backend_status": "running" if self._is_running else "stopped"}
|
75
|
+
await connection_manager.broadcast_to_admins({"type": "stream_status", "payload": status})
|
76
|
+
|
69
77
|
logger.info("All core tasks have been stopped.")
|
70
78
|
|
71
79
|
# Global singleton instance
|
@@ -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:
|
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
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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.3.
|
3
|
+
Version: 0.3.2
|
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
|
-
│ │ ├──
|
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
|
-
├──
|
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=
|
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=
|
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=
|
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/
|
14
|
-
neuro_simulator/api/
|
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=W05Q41BYAFrw-MTnJ5YJrBG2S1SmTcByoex77GfUaFQ,1787
|
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=
|
19
|
-
neuro_simulator/core/application.py,sha256=
|
17
|
+
neuro_simulator/core/agent_interface.py,sha256=ZXUCtkQUvsBQ5iCb0gTILJaShn5KmSrEgKhd7PK18HE,2794
|
18
|
+
neuro_simulator/core/application.py,sha256=zQ6QRUU-dyFW2GDKyBxiTO1BKh-Yt6j169YS-MLpalk,23734
|
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=
|
23
|
+
neuro_simulator/services/builtin.py,sha256=nn3sJFPy09JxQkw35icdyGU9hzLTXXazAJkNpdcz6Zs,5848
|
25
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
|
-
neuro_simulator/utils/process.py,sha256=
|
28
|
+
neuro_simulator/utils/process.py,sha256=9OYWx8fzaJZqmFUcjQX37AnBhl7YWvrLxDWBa30vqwU,3192
|
30
29
|
neuro_simulator/utils/queue.py,sha256=vSkh-BrgfsGN_gDAx2mfK44ydmMapdVyLsDG-7LIJZQ,1643
|
31
30
|
neuro_simulator/utils/state.py,sha256=DdBqSAYfjOFtJfB1hEGhYPh32r1ZvFuVlN_-29_-luA,664
|
32
|
-
neuro_simulator/utils/websocket.py,sha256=
|
33
|
-
neuro_simulator-0.3.
|
34
|
-
neuro_simulator-0.3.
|
35
|
-
neuro_simulator-0.3.
|
36
|
-
neuro_simulator-0.3.
|
37
|
-
neuro_simulator-0.3.
|
31
|
+
neuro_simulator/utils/websocket.py,sha256=1gtVoH1hafBUfVYmwkVDAbjwETeqyC3sWx706nQzSRo,2085
|
32
|
+
neuro_simulator-0.3.2.dist-info/METADATA,sha256=HBAqQoRRJmPcm1IxQwderrq7cTO-UhF-ulzqixLNPh8,8643
|
33
|
+
neuro_simulator-0.3.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
34
|
+
neuro_simulator-0.3.2.dist-info/entry_points.txt,sha256=qVd5ypnRRgU8Cw7rWfZ7o0OXyS9P9hgY-cRoN_mgz9g,51
|
35
|
+
neuro_simulator-0.3.2.dist-info/top_level.txt,sha256=V8awSKpcrFnjJDiJxSfy7jtOrnuE2BgAR9hLmfMDWK8,16
|
36
|
+
neuro_simulator-0.3.2.dist-info/RECORD,,
|
neuro_simulator/api/agent.py
DELETED
@@ -1,163 +0,0 @@
|
|
1
|
-
# neuro_simulator/api/agent.py
|
2
|
-
"""Unified API endpoints for agent management, decoupled from implementation."""
|
3
|
-
|
4
|
-
from fastapi import APIRouter, Depends, HTTPException, status, Request
|
5
|
-
from typing import Dict, Any, List, Optional
|
6
|
-
from pydantic import BaseModel
|
7
|
-
|
8
|
-
# Imports for the new structure
|
9
|
-
from ..core.config import config_manager
|
10
|
-
from ..core.agent_factory import create_agent
|
11
|
-
from ..core.agent_interface import BaseAgent
|
12
|
-
|
13
|
-
router = APIRouter(prefix="/api/agent", tags=["Agent Management"])
|
14
|
-
|
15
|
-
# Security dependency (remains the same)
|
16
|
-
async def get_api_token(request: Request):
|
17
|
-
password = config_manager.settings.server.panel_password
|
18
|
-
if not password:
|
19
|
-
return True
|
20
|
-
header_token = request.headers.get("X-API-Token")
|
21
|
-
if header_token and header_token == password:
|
22
|
-
return True
|
23
|
-
raise HTTPException(
|
24
|
-
status_code=status.HTTP_401_UNAUTHORIZED,
|
25
|
-
detail="Invalid API token",
|
26
|
-
headers={"WWW-Authenticate": "Bearer"},
|
27
|
-
)
|
28
|
-
|
29
|
-
# Pydantic models (remains the same)
|
30
|
-
class MessageItem(BaseModel):
|
31
|
-
username: str
|
32
|
-
text: str
|
33
|
-
role: str = "user"
|
34
|
-
|
35
|
-
class ToolExecutionRequest(BaseModel):
|
36
|
-
tool_name: str
|
37
|
-
params: Dict[str, Any]
|
38
|
-
|
39
|
-
class MemoryUpdateRequest(BaseModel):
|
40
|
-
title: Optional[str] = None
|
41
|
-
description: Optional[str] = None
|
42
|
-
content: Optional[List[str]] = None
|
43
|
-
|
44
|
-
class MemoryCreateRequest(BaseModel):
|
45
|
-
title: str
|
46
|
-
description: str
|
47
|
-
content: List[str]
|
48
|
-
|
49
|
-
class InitMemoryUpdateRequest(BaseModel):
|
50
|
-
memory: Dict[str, Any]
|
51
|
-
|
52
|
-
class TempMemoryItem(BaseModel):
|
53
|
-
content: str
|
54
|
-
role: str = "system"
|
55
|
-
|
56
|
-
# Dependency to get the agent instance, making endpoints cleaner
|
57
|
-
async def get_agent() -> BaseAgent:
|
58
|
-
return await create_agent()
|
59
|
-
|
60
|
-
# A single dependency for both auth and agent instance
|
61
|
-
class AgentDeps:
|
62
|
-
def __init__(self, token: bool = Depends(get_api_token), agent: BaseAgent = Depends(get_agent)):
|
63
|
-
self.agent = agent
|
64
|
-
|
65
|
-
# --- Refactored Agent Endpoints ---
|
66
|
-
|
67
|
-
@router.get("/messages", response_model=List[Dict[str, Any]])
|
68
|
-
async def get_agent_messages(deps: AgentDeps = Depends()):
|
69
|
-
"""Get agent's detailed message processing history."""
|
70
|
-
return await deps.agent.get_message_history()
|
71
|
-
|
72
|
-
@router.get("/context", response_model=List[Dict[str, Any]])
|
73
|
-
async def get_agent_context(deps: AgentDeps = Depends()):
|
74
|
-
"""Get agent's recent conversation context (last 20 entries)."""
|
75
|
-
return await deps.agent.get_message_history(limit=20)
|
76
|
-
|
77
|
-
@router.delete("/messages")
|
78
|
-
async def clear_agent_messages(deps: AgentDeps = Depends()):
|
79
|
-
"""Clear agent's message history."""
|
80
|
-
await deps.agent.reset_memory()
|
81
|
-
return {"status": "success", "message": "Agent memory reset successfully"}
|
82
|
-
|
83
|
-
@router.post("/messages")
|
84
|
-
async def send_message_to_agent(message: MessageItem, deps: AgentDeps = Depends()):
|
85
|
-
"""Send a message to the agent."""
|
86
|
-
response = await deps.agent.process_messages([message.dict()])
|
87
|
-
return {"response": response}
|
88
|
-
|
89
|
-
@router.get("/memory/init", response_model=Dict[str, Any])
|
90
|
-
async def get_init_memory(deps: AgentDeps = Depends()):
|
91
|
-
"""Get initialization memory content."""
|
92
|
-
return await deps.agent.get_init_memory()
|
93
|
-
|
94
|
-
@router.put("/memory/init")
|
95
|
-
async def update_init_memory(request: InitMemoryUpdateRequest, deps: AgentDeps = Depends()):
|
96
|
-
"""Update initialization memory content."""
|
97
|
-
await deps.agent.update_init_memory(request.memory)
|
98
|
-
return {"status": "success", "message": "Initialization memory updated"}
|
99
|
-
|
100
|
-
@router.get("/memory/temp", response_model=List[Dict[str, Any]])
|
101
|
-
async def get_temp_memory(deps: AgentDeps = Depends()):
|
102
|
-
"""Get all temporary memory content."""
|
103
|
-
return await deps.agent.get_temp_memory()
|
104
|
-
|
105
|
-
@router.post("/memory/temp")
|
106
|
-
async def add_temp_memory_item(request: TempMemoryItem, deps: AgentDeps = Depends()):
|
107
|
-
"""Add an item to temporary memory."""
|
108
|
-
await deps.agent.add_temp_memory(request.content, request.role)
|
109
|
-
return {"status": "success", "message": "Item added to temporary memory"}
|
110
|
-
|
111
|
-
@router.delete("/memory/temp")
|
112
|
-
async def clear_temp_memory(deps: AgentDeps = Depends()):
|
113
|
-
"""Clear temporary memory."""
|
114
|
-
await deps.agent.clear_temp_memory()
|
115
|
-
return {"status": "success", "message": "Temporary memory cleared"}
|
116
|
-
|
117
|
-
@router.get("/memory/blocks", response_model=List[Dict[str, Any]])
|
118
|
-
async def get_memory_blocks(deps: AgentDeps = Depends()):
|
119
|
-
"""Get all memory blocks."""
|
120
|
-
return await deps.agent.get_memory_blocks()
|
121
|
-
|
122
|
-
@router.get("/memory/blocks/{block_id}", response_model=Dict[str, Any])
|
123
|
-
async def get_memory_block(block_id: str, deps: AgentDeps = Depends()):
|
124
|
-
"""Get a specific memory block."""
|
125
|
-
block = await deps.agent.get_memory_block(block_id)
|
126
|
-
if block is None:
|
127
|
-
raise HTTPException(status_code=404, detail="Memory block not found")
|
128
|
-
return block
|
129
|
-
|
130
|
-
@router.post("/memory/blocks", response_model=Dict[str, str])
|
131
|
-
async def create_memory_block(request: MemoryCreateRequest, deps: AgentDeps = Depends()):
|
132
|
-
"""Create a new memory block."""
|
133
|
-
return await deps.agent.create_memory_block(request.title, request.description, request.content)
|
134
|
-
|
135
|
-
@router.put("/memory/blocks/{block_id}")
|
136
|
-
async def update_memory_block(block_id: str, request: MemoryUpdateRequest, deps: AgentDeps = Depends()):
|
137
|
-
"""Update a memory block."""
|
138
|
-
await deps.agent.update_memory_block(block_id, request.title, request.description, request.content)
|
139
|
-
return {"status": "success"}
|
140
|
-
|
141
|
-
@router.delete("/memory/blocks/{block_id}")
|
142
|
-
async def delete_memory_block(block_id: str, deps: AgentDeps = Depends()):
|
143
|
-
"""Delete a memory block."""
|
144
|
-
await deps.agent.delete_memory_block(block_id)
|
145
|
-
return {"status": "success"}
|
146
|
-
|
147
|
-
@router.post("/reset_memory")
|
148
|
-
async def reset_agent_memory(deps: AgentDeps = Depends()):
|
149
|
-
"""Reset all agent memory types."""
|
150
|
-
await deps.agent.reset_memory()
|
151
|
-
return {"status": "success", "message": "Agent memory reset successfully"}
|
152
|
-
|
153
|
-
@router.get("/tools")
|
154
|
-
async def get_available_tools(deps: AgentDeps = Depends()):
|
155
|
-
"""Get list of available tools."""
|
156
|
-
# Return in the format expected by the frontend
|
157
|
-
return {"tools": await deps.agent.get_available_tools()}
|
158
|
-
|
159
|
-
@router.post("/tools/execute")
|
160
|
-
async def execute_tool(request: ToolExecutionRequest, deps: AgentDeps = Depends()):
|
161
|
-
"""Execute a tool with given parameters."""
|
162
|
-
result = await deps.agent.execute_tool(request.tool_name, request.params)
|
163
|
-
return {"result": result}
|
File without changes
|
File without changes
|
File without changes
|