Add reliable execution reporting and coordinated dashboard views

This commit is contained in:
aiagent
2026-10-19 04:29:33 -07:00
parent 547f62fa53
commit c2dfe311f7
41 changed files with 3867 additions and 107 deletions
+60 -2
View File
@@ -5,6 +5,7 @@ import ipaddress
import json
import mimetypes
import os
import re
import stat
import threading
import time
@@ -84,6 +85,29 @@ class MetricsCache:
return self.value
class EtaClock:
def __init__(self, store, interval=15):
self.store = store
self.interval = interval
self.stop = threading.Event()
self.status = {'status':'waiting','last_tick':None}
self.thread = threading.Thread(target=self.run, name='eta-clock', daemon=True)
self.thread.start()
def run(self):
while not self.stop.is_set():
try:
self.store.eta_tick()
self.status = {'status':'ok','last_tick':time.time()}
except Exception:
self.status = {'status':'unavailable','last_tick':self.status['last_tick']}
self.stop.wait(self.interval)
def close(self):
self.stop.set()
self.thread.join(timeout=16)
class Server(ThreadingHTTPServer):
daemon_threads = True
@@ -117,8 +141,11 @@ class Server(ThreadingHTTPServer):
if any(not isinstance(host,str) or not host or '/' in host or '@' in host or any(c.isspace() for c in host) for host in self.allowed_hosts):
raise ValueError('invalid allowed_hosts')
self.metrics = MetricsCache(config.get('metrics', {}))
self.eta_clock = EtaClock(self.store)
def server_close(self):
if hasattr(self, 'eta_clock'):
self.eta_clock.close()
if hasattr(self, 'metrics'):
self.metrics.stop.set()
super().server_close()
@@ -157,7 +184,12 @@ class Handler(BaseHTTPRequestHandler):
if origins and origins != ['http://' + hosts[0]]:
self.output(403, {'error':'origin rejected'})
return False
if self.headers.get('Sec-Fetch-Site') == 'cross-site':
public_navigation = (
not write and self.command == 'GET'
and not urlsplit(self.path).path.startswith('/api/')
and self.headers.get('Sec-Fetch-Mode') == 'navigate'
and self.headers.get('Sec-Fetch-Dest') == 'document')
if self.headers.get('Sec-Fetch-Site') == 'cross-site' and not public_navigation:
self.output(403, {'error':'cross-site request rejected'})
return False
if write and self.headers.get('X-CSRF-Token') != '1':
@@ -185,7 +217,25 @@ class Handler(BaseHTTPRequestHandler):
state['title'] = self.server.title
state['primary_session_id'] = self.server.primary_session_id
state['metrics'] = self.server.metrics.snapshot()
state['eta_clock'] = dict(self.server.eta_clock.status)
self.output(200, state)
elif parts.path == '/api/queue-health' and not parts.query:
self.output(200,self.server.store.queue_health())
elif parts.path == '/api/task-reports':
query = parse_qs(parts.query,strict_parsing=True,keep_blank_values=True)
if set(query) != {'task_id'} or len(query['task_id']) != 1:
raise Invalid('invalid report query')
self.output(200,self.server.store.task_reports(query['task_id'][0]))
elif parts.path == '/api/logs':
query = parse_qs(parts.query,strict_parsing=True,keep_blank_values=True) if parts.query else {}
if set(query)-{'level','status'} or any(len(v)!=1 for v in query.values()):
raise Invalid('invalid log query')
self.output(200,self.server.store.logs(
level=query.get('level',[None])[0],status=query.get('status',[None])[0]))
elif parts.path == '/api/eta-notifications' and not parts.query:
self.output(200, self.server.store.eta_notifications())
elif parts.path == '/api/decision-notifications' and not parts.query:
self.output(200, self.server.store.decision_notifications())
elif parts.path == '/api/hook-notifications' and not parts.query:
self.output(200, self.server.store.hook_notifications())
elif parts.path in ('/api/messages','/api/conversation'):
@@ -246,7 +296,9 @@ class Handler(BaseHTTPRequestHandler):
if not isinstance(data, dict):
raise Invalid('object required')
store = self.server.store
routes = {'/api/hooks':store.hook, '/api/hooks/ack':store.hook_ack,
routes = {'/api/task-reports':store.task_report, '/api/attention':store.attention, '/api/eta-notifications/ack':store.eta_ack, '/api/decisions':store.decision, '/api/decision-notifications/ack':store.decision_ack,
'/api/hook-notifications/submitting':store.hook_submitting,
'/api/hook-notifications/coalesce':store.hook_coalesce, '/api/hooks':store.hook, '/api/hooks/escalate':store.hook_escalate, '/api/hooks/ack':store.hook_ack,
'/api/sessions':store.session, '/api/session-requests':store.request,
'/api/tasks':store.task, '/api/messages':store.send,
'/api/worker/claim':store.claim, '/api/worker/renew':store.renew, '/api/worker/complete':store.complete,
@@ -254,6 +306,12 @@ class Handler(BaseHTTPRequestHandler):
'/api/worker/submission':store.submission, '/api/worker/uncertain':store.uncertain, '/api/messages/reconcile':store.reconcile}
if self.command == 'PATCH' and self.path.startswith('/api/tasks/'):
result = store.task(data, self.path[len('/api/tasks/'):])
elif self.command == 'POST' and re.fullmatch(r'/api/tasks/[A-Za-z0-9_.:-]+/integrate',self.path):
result = store.integrate(self.path.split('/')[3],data)
elif self.command == 'POST' and re.fullmatch(r'/api/eta-reviews/[A-Za-z0-9_.:-]+/complete',self.path):
result = store.eta_complete(self.path.split('/')[3],data)
elif self.command == 'POST' and re.fullmatch(r'/api/decisions/[A-Za-z0-9_.:-]+/respond',self.path):
result = store.decision_respond(self.path.split('/')[3],data)
elif self.command == 'POST' and self.path in routes:
result = routes[self.path](data)
else: