app-server: let ephemeral threads report their in-progress turn, so an abandoned turn stays cancellable
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.4k
- PR merge metrics
- PR metrics pending
Description
What variant of Codex are you using?
CLI / app-server (codex-cli 0.151.0, macOS), driven programmatically over the app-server JSON-RPC API.
What feature would you like to see?
Please let a client discover the in-progress turn on an ephemeral thread. Today thread/turns/list refuses:
-32600 ephemeral threads do not support thread/turns/list
Paging historical turns from a thread with no rollout history is meaningfully impossible, so the refusal makes sense as written. But the same call is the only way to recover the id of a turn that is running right now, and that id is live in-memory state the server already has. Either relaxing thread/turns/list to return in-flight turns for ephemeral threads, or adding a narrow read (thread/activeTurn/read, say), would close this.
Why it matters: it is the difference between cancellable and uncancellable work.
The app-server has no transport-level cancellation, so when turn/start exceeds a client's deadline the client must recover the turn id from somewhere else before it can call turn/interrupt. Two facts I measured against a real app-server:
turn/startanswers before it emitsturn/started— consistently, reading raw line order off the JSONL stream rather than promise resolution. So if the response hasn't arrived, the notification hasn't either. The notification is not a usable fallback.thread/turns/listis the working fallback — on a durable thread it names theinProgressturn, interrupting by that recovered id works (statusgoes tointerrupted), and the recovered id matches the oneturn/starteventually returns.
Which means: on a durable thread, an abandoned turn can be stopped. On an ephemeral thread, it cannot be stopped by any means, and keeps consuming tokens until it finishes on its own. The client's only remaining option is to wait for the late response and interrupt then — which helps only if the response ever comes.
That is an odd cost to attach to ephemerality. A caller chooses ephemeral: true to avoid persisting a thread log; they are not asking to give up the ability to stop a runaway turn.
Additional information
Reproducible in about ten seconds with no special setup: start a thread, start a turn, ignore the turn/start response as a timed-out caller would, wait, then call thread/turns/list. Durable threads name the turn; ephemeral ones return -32600. I have this as a standing probe script in an MCP client that orchestrates concurrent app-server workers, and can share it or open a PR if you'd like the change made.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the app-server handlers for thread/turns/list, turn/start, and turn/interrupt, then reproduce the JSONL timing and ephemeral-thread behavior described in the issue. Determine whether listing the in-progress turn or adding a narrow read is consistent with the API design. Done means a timed-out client can recover an ephemeral thread's active turn id and interrupt it without requiring the late turn/start response.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- api, backend-api-design
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100