From 72a3af63d4f14dcb986290a0b9d0ec53abbbd68c Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Wed, 29 Apr 2026 00:04:12 -0500 Subject: [PATCH] fix(tui): keep prompt submit off the RPC pool A cleanup review found that adding prompt.submit to _LONG_HANDLERS made the RPC pool own the full first-turn wait even though the handler itself already spawns a turn thread. Keep prompt.submit inline and make it return immediately: - look up the session without waiting - kick the lazy agent build - spawn a short waiter thread that blocks on agent_ready, then starts the existing turn dispatcher This keeps stdin dispatch responsive, avoids occupying a bounded pool worker for a normal chat turn, and preserves the lazy-start hydration behavior. Tests: - python -m py_compile tui_gateway/server.py - cd ui-tui && npm run type-check && npm run build - scripts/run_tests.sh tests/tui_gateway/test_protocol.py::test_sess_found tests/tools/test_code_execution_modes.py tests/tools/test_code_execution.py - cd ui-tui && npm test -- --run src/__tests__/useSessionLifecycle.test.ts src/__tests__/useConfigSync.test.ts --- tui_gateway/server.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/tui_gateway/server.py b/tui_gateway/server.py index 6ece5da2..ad07ce97 100644 --- a/tui_gateway/server.py +++ b/tui_gateway/server.py @@ -141,7 +141,6 @@ _SLASH_WORKER_TIMEOUT_S = max( _LONG_HANDLERS = frozenset( { "cli.exec", - "prompt.submit", "session.branch", "session.resume", "shell.exec", @@ -2426,12 +2425,28 @@ def _(rid, params: dict) -> dict: @method("prompt.submit") def _(rid, params: dict) -> dict: sid, text = params.get("session_id", ""), params.get("text", "") - session, err = _sess(params, rid) + session, err = _sess_nowait(params, rid) if err: return err + + _start_agent_build(sid, session) + + def run_after_agent_ready() -> None: + err = _wait_agent(session, rid) + if err: + session.get("transport", current_transport() or _stdio_transport).write(err) + return + _run_prompt_submit(rid, sid, session, text) + + threading.Thread(target=run_after_agent_ready, daemon=True).start() + return _ok(rid, {"status": "streaming"}) + + +def _run_prompt_submit(rid, sid: str, session: dict, text: Any) -> None: with session["history_lock"]: if session.get("running"): - return _err(rid, 4009, "session busy") + _emit("error", sid, {"message": "session busy"}) + return session["running"] = True history = list(session["history"]) history_version = int(session.get("history_version", 0)) @@ -2671,7 +2686,6 @@ def _(rid, params: dict) -> dict: session["running"] = False threading.Thread(target=run, daemon=True).start() - return _ok(rid, {"status": "streaming"}) @method("clipboard.paste")