feat(simulation): stabilize IPC layer and verify full workflow
This commit is contained in:
56
api_hooks.py
56
api_hooks.py
@@ -21,11 +21,12 @@ class HookHandler(BaseHTTPRequestHandler):
|
||||
self.end_headers()
|
||||
self.wfile.write(json.dumps({'status': 'ok'}).encode('utf-8'))
|
||||
elif self.path == '/api/project':
|
||||
import project_manager
|
||||
self.send_response(200)
|
||||
self.send_header('Content-Type', 'application/json')
|
||||
self.end_headers()
|
||||
self.wfile.write(
|
||||
json.dumps({'project': app.project}).encode('utf-8'))
|
||||
flat = project_manager.flat_config(app.project)
|
||||
self.wfile.write(json.dumps({'project': flat}).encode('utf-8'))
|
||||
elif self.path == '/api/session':
|
||||
self.send_response(200)
|
||||
self.send_header('Content-Type', 'application/json')
|
||||
@@ -41,16 +42,35 @@ class HookHandler(BaseHTTPRequestHandler):
|
||||
if hasattr(app, 'perf_monitor'):
|
||||
metrics = app.perf_monitor.get_metrics()
|
||||
self.wfile.write(json.dumps({'performance': metrics}).encode('utf-8'))
|
||||
elif self.path.startswith('/api/gui/state/'):
|
||||
tag = self.path.replace('/api/gui/state/', '')
|
||||
import dearpygui.dearpygui as dpg
|
||||
shown = False
|
||||
if dpg.does_item_exist(tag):
|
||||
shown = dpg.is_item_shown(tag)
|
||||
self.send_response(200)
|
||||
self.send_header('Content-Type', 'application/json')
|
||||
self.end_headers()
|
||||
self.wfile.write(json.dumps({'tag': tag, 'shown': shown}).encode('utf-8'))
|
||||
elif self.path == '/api/gui/diagnostics':
|
||||
# Safe way to query multiple states at once via the main thread queue
|
||||
event = threading.Event()
|
||||
result = {}
|
||||
|
||||
def check_all():
|
||||
import dearpygui.dearpygui as dpg
|
||||
try:
|
||||
result["thinking"] = dpg.is_item_shown("thinking_indicator") if dpg.does_item_exist("thinking_indicator") else False
|
||||
result["live"] = dpg.is_item_shown("operations_live_indicator") if dpg.does_item_exist("operations_live_indicator") else False
|
||||
result["prior"] = dpg.is_item_shown("prior_session_indicator") if dpg.does_item_exist("prior_session_indicator") else False
|
||||
finally:
|
||||
event.set()
|
||||
|
||||
with app._pending_gui_tasks_lock:
|
||||
app._pending_gui_tasks.append({
|
||||
"action": "custom_callback",
|
||||
"callback": check_all
|
||||
})
|
||||
|
||||
if event.wait(timeout=2):
|
||||
self.send_response(200)
|
||||
self.send_header('Content-Type', 'application/json')
|
||||
self.end_headers()
|
||||
self.wfile.write(json.dumps(result).encode('utf-8'))
|
||||
else:
|
||||
self.send_response(504)
|
||||
self.end_headers()
|
||||
self.wfile.write(json.dumps({'error': 'timeout'}).encode('utf-8'))
|
||||
else:
|
||||
self.send_response(404)
|
||||
self.end_headers()
|
||||
@@ -80,11 +100,6 @@ class HookHandler(BaseHTTPRequestHandler):
|
||||
self.wfile.write(
|
||||
json.dumps({'status': 'updated'}).encode('utf-8'))
|
||||
elif self.path == '/api/gui':
|
||||
if not hasattr(app, '_pending_gui_tasks'):
|
||||
app._pending_gui_tasks = []
|
||||
if not hasattr(app, '_pending_gui_tasks_lock'):
|
||||
app._pending_gui_tasks_lock = threading.Lock()
|
||||
|
||||
with app._pending_gui_tasks_lock:
|
||||
app._pending_gui_tasks.append(data)
|
||||
|
||||
@@ -115,6 +130,13 @@ class HookServer:
|
||||
def start(self):
|
||||
if not getattr(self.app, 'test_hooks_enabled', False):
|
||||
return
|
||||
|
||||
# Ensure the app has the task queue and lock initialized
|
||||
if not hasattr(self.app, '_pending_gui_tasks'):
|
||||
self.app._pending_gui_tasks = []
|
||||
if not hasattr(self.app, '_pending_gui_tasks_lock'):
|
||||
self.app._pending_gui_tasks_lock = threading.Lock()
|
||||
|
||||
self.server = HookServerInstance(('127.0.0.1', self.port), HookHandler, self.app)
|
||||
self.thread = threading.Thread(target=self.server.serve_forever, daemon=True)
|
||||
self.thread.start()
|
||||
|
||||
Reference in New Issue
Block a user