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
This commit is contained in:
Brooklyn Nicholson 2026-04-29 00:04:12 -05:00
parent a2819e1820
commit 72a3af63d4

View File

@ -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")