TUI: fix blank-screen hang on startup from blocking MCP query
ober
47e454dd05a12b32f5ef993d8c420fced79a7cb8
--- a/src/jcode/mcp/client.ss +++ b/src/jcode/mcp/client.ss @@ -29,6 +29,10 @@ (defstruct mcp-conn (name to-stdin from-stdout from-stderr pid next-id)) (def *mcp-servers* '()) +;; Cached tool count per server name. Populated by register-mcp-tools at init. +;; mcp-active-servers reads from here instead of doing a blocking JSON-RPC +;; round-trip, which could hang forever if a server is slow or dead. +(def *mcp-tool-counts* (make-hash-table)) ;; --- subprocess management --- @@ -57,13 +61,17 @@ (def (mcp-stop-all!) (for-each mcp-stop! *mcp-servers*) - (set! *mcp-servers* '())) + (set! *mcp-servers* '()) + (set! *mcp-tool-counts* (make-hash-table))) (def (mcp-active-servers) - "Return list of (name . tool-count) for active MCP servers." + "Return list of (name . tool-count) for active MCP servers. + Reads the cached count populated at init time — never does a + blocking JSON-RPC call, so it's safe to call from the TUI hot + path without risk of hanging on a dead server." (map (lambda (conn) - (cons (mcp-conn-name conn) - (length (try (mcp-list-tools conn) (catch (e) '()))))) + (let ((name (mcp-conn-name conn))) + (cons name (or (hash-get *mcp-tool-counts* name) 0)))) *mcp-servers*)) ;; --- JSON-RPC 2.0 protocol --- @@ -189,6 +197,9 @@ (lambda (args) (mcp-call-tool conn name args)))))) tools) + ;; Cache the count so mcp-active-servers can return it without + ;; doing a blocking JSON-RPC call later. + (hash-put! *mcp-tool-counts* (mcp-conn-name conn) (length tools)) (length tools))) ;; --- config and init --- --- a/src/jcode/ui/tui.ss +++ b/src/jcode/ui/tui.ss @@ -196,14 +196,20 @@ (session (session-create "New session"))) (tui-log "tui-main: terminal ~ax~a, session=~a" w h (session-id session)) (app-state-session-id-set! state (session-id session)) - ;; Populate MCP status on sidebar + ;; Populate MCP status on sidebar (best-effort, time-limited) + (tui-log "tui-main: refresh-mcp-sidebar! (begin)") (refresh-mcp-sidebar! state) + (tui-log "tui-main: refresh-mcp-sidebar! (done)") ;; Welcome message (app-state-messages-set! state (list (msg-block-system (format "jcode ~a — Type your message, /help for commands" *version*)))) + (tui-log "tui-main: reflow-all! (begin)") (reflow-all! state) + (tui-log "tui-main: draw-all! (begin)") (draw-all! state) + (tui-log "tui-main: tb-present! (begin)") (tb-present!) + (tui-log "tui-main: tb-present! (done)") (*main-thread* (current-thread)) (tui-log "tui-main: entering event loop, main-thread=~a" (*main-thread*)) (event-loop state)