Bug fixes

This commit is contained in:
2026-04-09 09:16:07 +02:00
parent a640615d2e
commit 3e34843292
3 changed files with 71 additions and 20 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ LLM backend settings and application constants.
# LLM BACKEND CONFIGURATION — Edit these to match your setup
# ============================================================
LLM_BACKEND = "ollama" # "ollama" or "vllm"
OLLAMA_URL = "http://turd.hem.holck.se:11434"
OLLAMA_URL = "http://localhost:11434"
VLLM_URL = "http://localhost:8000"
MODEL_NAME = "gemma4:e4b"
+11 -5
View File
@@ -106,9 +106,10 @@ def run(args: argparse.Namespace):
llm = LLM(backend=args.backend, model=args.model)
# Start web dashboard if requested
_web_server = None
if args.web:
from .web import start_web_server
start_web_server(args.web, workdir)
_web_server = start_web_server(args.web, workdir)
print(f" \033[36m🌐 Web dashboard: http://localhost:{args.web}\033[0m")
logger.log("startup", f"AutoDev started in {workdir}")
@@ -352,6 +353,15 @@ def run(args: argparse.Namespace):
print(f" Plan: see {config.PLAN_FILE}")
logger.log("complete", "All steps executed successfully")
# Shut down web server
if _web_server:
try:
from .web import stop_web_server
stop_web_server()
_web_server.server_close()
except Exception:
pass
def main():
args = parse_args()
@@ -359,18 +369,14 @@ def main():
run(args)
except KeyboardInterrupt:
print("\n\n Interrupted by user. State saved — restart to resume.")
sys.exit(130)
except SandboxViolation as e:
print(f"\n \033[31m✗ SANDBOX VIOLATION: {e}\033[0m")
sys.exit(1)
except LLMError as e:
print(f"\n \033[31m✗ LLM ERROR: {e}\033[0m")
sys.exit(1)
except Exception as e:
print(f"\n \033[31m✗ UNEXPECTED ERROR: {e}\033[0m")
import traceback
traceback.print_exc()
sys.exit(1)
if __name__ == "__main__":
+59 -14
View File
@@ -12,17 +12,25 @@ import threading
import urllib.parse
from . import config
# Global event queue — logger pushes events, SSE endpoint streams them
_event_queue: queue.Queue = queue.Queue(maxsize=5000)
# Global event system — broadcast to all connected SSE clients
_clients: list = [] # list of queue.Queue, one per connected client
_clients_lock = threading.Lock()
_event_history: list = [] # buffer of all past events for new clients
_workdir: str = ""
_shutdown: bool = False
_server = None
def push_event(event_type: str, data: dict):
"""Push an event to all connected web clients."""
try:
_event_queue.put_nowait({"type": event_type, "data": data})
except queue.Full:
pass
msg = {"type": event_type, "data": data}
_event_history.append(msg)
with _clients_lock:
for q in _clients:
try:
q.put_nowait(msg)
except queue.Full:
pass
class WebHandler(http.server.BaseHTTPRequestHandler):
@@ -62,19 +70,28 @@ class WebHandler(http.server.BaseHTTPRequestHandler):
self.send_header("Connection", "keep-alive")
self.send_header("Access-Control-Allow-Origin", "*")
self.end_headers()
client_queue = queue.Queue(maxsize=5000)
# Replay event history for late-connecting clients
for past_event in _event_history:
client_queue.put_nowait(past_event)
with _clients_lock:
_clients.append(client_queue)
try:
while True:
while not _shutdown:
try:
event = _event_queue.get(timeout=1)
event = client_queue.get(timeout=1)
line = f"data: {json.dumps(event)}\n\n"
self.wfile.write(line.encode("utf-8"))
self.wfile.flush()
except queue.Empty:
# Send keepalive
self.wfile.write(b": keepalive\n\n")
self.wfile.flush()
except (BrokenPipeError, ConnectionResetError, OSError):
pass
finally:
with _clients_lock:
if client_queue in _clients:
_clients.remove(client_queue)
def _serve_file_tree(self):
files = []
@@ -115,14 +132,42 @@ class WebHandler(http.server.BaseHTTPRequestHandler):
self.send_error(404, "File not found or not readable")
def stop_web_server():
global _shutdown
_shutdown = True
if _server:
threading.Thread(target=_server.shutdown, daemon=True).start()
def start_web_server(port: int, workdir: str):
"""Start the web UI server in a background thread."""
"""Start the web UI server in a background daemon thread."""
global _workdir
_workdir = workdir
server = http.server.HTTPServer(("0.0.0.0", port), WebHandler)
server.daemon_threads = True
thread = threading.Thread(target=server.serve_forever, daemon=True)
thread.start()
class ThreadedHTTPServer(http.server.HTTPServer):
allow_reuse_address = True
daemon_threads = True
def process_request(self, request, client_address):
t = threading.Thread(target=self._handle, args=(request, client_address),
daemon=True)
t.start()
def _handle(self, request, client_address):
try:
self.finish_request(request, client_address)
except Exception:
pass
try:
self.shutdown_request(request)
except Exception:
pass
server = ThreadedHTTPServer(("0.0.0.0", port), WebHandler)
global _server
_server = server
t = threading.Thread(target=server.serve_forever, daemon=True)
t.start()
return server