Add shutdown function to Serena dashboard

This commit is contained in:
Dominik Jain
2025-05-28 00:03:45 +02:00
parent d41789797b
commit d242217c4b
3 changed files with 38 additions and 20 deletions
+26 -17
View File
@@ -39,11 +39,11 @@ class Dashboard {
this.$logContainer = $('#log-container');
this.$errorContainer = $('#error-container');
this.$loadButton = $('#load-logs');
this.$clearButton = $('#clear-logs');
this.$shutdownButton = $('#shutdown');
// register event handlers
this.$loadButton.click(this.loadLogs.bind(this));
this.$clearButton.click(this.clearLogs.bind(this));
this.$shutdownButton.click(this.shutdown.bind(this));
// initialize the application
this.loadToolNames().then(function() {
@@ -63,7 +63,7 @@ class Dashboard {
type: 'GET',
success: function(response) {
self.toolNames = response.tool_names || [];
console.log('Loaded tool names:', toolNames);
console.log('Loaded tool names:', self.toolNames);
},
error: function(xhr, status, error) {
console.error('Error loading tool names:', error);
@@ -72,7 +72,7 @@ class Dashboard {
}
loadLogs() {
console.log("load", this);
console.log("Loading logs");
let self = this;
// Disable button and show loading state
@@ -117,14 +117,14 @@ class Dashboard {
},
complete: function() {
// Re-enable button
self.$loadButton.prop('disabled', false).text('Load Logs');
self.$loadButton.prop('disabled', false).text('Reload Log');
}
});
}
pollForNewLogs() {
let self = this;
console.log("poll", this);
console.log("Polling logs", this.currentMaxIdx);
$.ajax({
url: '/get_log_messages',
type: 'POST',
@@ -176,17 +176,26 @@ class Dashboard {
this.pollInterval = setInterval(this.pollForNewLogs.bind(this), 1000);
}
stopPeriodicPolling() {
if (this.pollInterval) {
clearInterval(this.pollInterval);
this.pollInterval = null;
shutdown() {
const self = this;
const _shutdown = function () {
console.log("Triggering shutdown");
$.ajax({
url: '/shutdown',
type: "PUT",
contentType: 'application/json',
});
self.$errorContainer.html('<div class="error-message">Shutting down ...</div>')
setTimeout(function() {
window.close();
}, 2000);
}
// ask for confirmation using a dialog
if (confirm("This will fully terminate the Serena server.")) {
_shutdown();
} else {
console.log("Shutdown cancelled");
}
}
clearLogs() {
this.stopPeriodicPolling();
this.$logContainer.empty();
this.$errorContainer.empty();
this.currentMaxIdx = -1;
}
}
+3 -3
View File
@@ -102,11 +102,11 @@
</div>
<div class="controls">
<button id="load-logs" class="btn">Load Logs</button>
<button id="clear-logs" class="btn">Clear Display</button>
<button id="load-logs" class="btn">Reload Log</button>
<button id="shutdown" class="btn">Shutdown Server</button>
</div>
<div id="error-container"></div>
<div id="error-container">Fuck you</div>
<div id="log-container" class="log-container"></div>
<script>
+9
View File
@@ -1,6 +1,7 @@
import os
import queue
import socket
import sys
import threading
import uvicorn
@@ -79,6 +80,7 @@ class SerenaDashboardAPI:
self._app.add_api_route("/get_log_messages", self._get_log_messages, methods=["POST"], response_model=ResponseLog)
self._app.add_api_route("/get_tool_names", self._get_tool_names, methods=["GET"], response_model=ResponseToolNames)
self._app.add_api_route("/shutdown", self._shutdown, methods=["PUT"])
async def _get_log_messages(self, request: RequestLog) -> ResponseLog:
all_messages = self._memory_log_handler.get_log_messages()
@@ -88,6 +90,13 @@ class SerenaDashboardAPI:
async def _get_tool_names(self) -> ResponseToolNames:
return ResponseToolNames(tool_names=self._tool_names)
async def _shutdown(self) -> None:
print("Shutdown initiated by dashbaord ...", file=sys.stderr)
log.info("Shutting down Serena")
# noinspection PyUnresolvedReferences
# noinspection PyProtectedMember
os._exit(0)
@staticmethod
def _find_first_free_port(start_port: int) -> int:
port = start_port