fix(opencode): answer a failed TUI worker request instead of hanging
Issue for this PR
Closes #54934
Type of change
- Bug fix
- New feature
- Refactor / code improvement
- Documentation
What does this PR do?
The TUI talks to its server worker over a small RPC channel and waits on it before it draws anything, for example to start the listener for --port. When the worker's handler threw, Rpc.listen never posted a reply (the worker's unhandledRejection handler swallows the error), so the TUI's client.call() never settled. With opencode --port 4096 and the port already taken, that is a blank terminal forever, with no hint why.
Now Rpc.listen answers a failed request with the error's message and Rpc.client rejects the pending call with it. The failure reaches the TUI's existing error handling, and opencode exits with Failed to start server. Is port 4096 in use?. Server.listen rejects with a ServeError that has no message of its own and names the port in its cause, so when an error has no message, the cause's is sent instead.
Related: #34981 and #42885 cover a worker that dies with calls pending. This covers a worker that stays up but whose handler throws.
How did you verify your code works?
- New
test/util/rpc.test.tsdrives a real worker whose methods return, throw, reject, and throw with only a cause. Onv1without the change, 3 of the 4 tests fail because those calls get no reply; with it, all 4 pass. opencode --port <port>while another process holds the port: before, the screen is still blank 20 s later; after, opencode exits with code 1 and the message above.bun typecheckinpackages/opencodeis clean, andtest/cli/tui/thread.test.tspasses.
Screenshots / recordings
Not a UI change; the visible difference is the error message above.
Checklist
- I have tested my changes locally
- I have not included unrelated changes in this PR
This PR is AI generated, but under direct supervision and on request of @Nowaker.