Skip to content

[7 of 7] Sync TUI thread settings#22510

Closed
etraut-openai wants to merge 180 commits into
etraut/next-turn-state-app-serverfrom
etraut/next-turn-state-tui
Closed

[7 of 7] Sync TUI thread settings#22510
etraut-openai wants to merge 180 commits into
etraut/next-turn-state-app-serverfrom
etraut/next-turn-state-tui

Conversation

@etraut-openai

@etraut-openai etraut-openai commented May 13, 2026

Copy link
Copy Markdown
Collaborator

Stack position: [7 of 7]

Summary

Remote TUI clients can currently show stale thread settings when another TUI changes model, plan mode, fast mode, permissions, or related state. This PR wires the TUI to the app-server API and notification so connected clients stay in sync.

Changes

  • Send TUI setting changes through thread/settings/update in app-server mode.
  • Keep turn/start sending full state for compatibility.
  • Emit missing thread settings updates from model/reasoning and collaboration-mode changes.
  • Handle thread/settings/updated without rendering it into the transcript, refreshing active and cached thread state instead.

This stack addresses #20656 and #22090.

Stack

  1. [1 of 7] Add thread settings to UserInput
  2. [2 of 7] Remove UserInputWithTurnContext
  3. [3 of 7] Remove UserTurn
  4. [4 of 7] Placeholder for OverrideTurnContext cleanup
  5. [5 of 7] Replace OverrideTurnContext with ThreadSettings
  6. [6 of 7] Add app-server thread settings API
  7. [7 of 7] Sync TUI thread settings (this PR)

@fcoury-oai fcoury-oai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found a potential issue with the help of Codex: if a user already has a Plan-mode reasoning override, then changes Plan reasoning again from the TUI, the local UI updates but the thread/turnContext/update sent to the app server can still contain the old effort. Other connected TUIs keep showing stale Plan reasoning, which is the sync bug this PR is trying to fix.

Here's how I replicated it with 3 terminals:

  • on terminal A run ./target/debug/codex app-server --listen ws://127.0.0.1:48879
  • on terminal B run ./target/debug/codex --remote ws://127.0.0.1:48879 -C /tmp/codex-next-turn-smoke --enable collaboration_modes -c 'plan_mode_reasoning_effort="low"'
  • send something like Reply exactly: testing plan on terminal B
  • check session id from /status or statusline.
  • on terminal C run ./target/debug/codex resume --remote ws://127.0.0.1:48879 <session-id> --enable collaboration_modes -C /tmp/codex-next-turn-smoke
  • run /plan first then /model, pick the current model and pick High reasoning
  • choose Apply to Plan mode override
  • on terminal B check status or statusline, to show plan High
  • in terminal C run /status

You'll see C still shows reasoning as low from /status or statuline.

From Codex: "That means the app-server-bound OverrideTurnContext.collaboration_mode.settings.reasoning_effort was low even though the UI action selected high."

@etraut-openai etraut-openai left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[codex] Fixed in 399695c. The Plan reasoning override path now sends the explicitly selected effort instead of reapplying the stale stored Plan default.

@etraut-openai etraut-openai requested a review from fcoury-oai May 14, 2026 20:49

@fcoury-oai fcoury-oai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed the code changes, specially the changes after my last review. I also tested the same happy path I tested before with one app server and two terminals, making sure the two clients sync models, reasoning levels, mode (plan/default) and fast on/off.

The problem I found last time was also fixed.

Code looks good and my manual tests all pass.

Approved 👍

@etraut-openai

Copy link
Copy Markdown
Collaborator Author

This PR is superseded by #23507.

etraut-openai added a commit that referenced this pull request May 20, 2026
Builds on #23502.

## Why

#23502 adds the app-server `thread/settings/update` API and matching
`thread/settings/updated` notification. The TUI already lets users
change thread-scoped settings such as model, reasoning effort, service
tier, approvals, permissions, personality, and collaboration mode, but
those updates need to flow through the app server so embedded and
connected clients observe the same thread state.

This is a rework (simplification) of PR
#22510. It has the same
functionality, but the underlying `thread/settings/update` api is now
simpler in that it no longer returns the effective settings as a
response. Now, clients receive the effective settings only through the
`thread/settings/updated` notification.

## What Changed

This updates the TUI to send `thread/settings/update` whenever those
thread-scoped settings change and to treat the RPC response as the
authoritative acknowledgement. It also routes `thread/settings/updated`
notifications back into cached session state and the visible chat widget
so active and inactive threads stay in sync after app-server-originated
changes.

The implementation is kept to the TUI layer: settings conversion and
merge logic live under `codex-rs/tui/src/app/thread_settings.rs`, with
dispatch/routing hooks in the existing app and chat widget paths.

## Verification

I manually tested using `codex app-server --listen unix://` and then
launching two copies of the TUI that use the same local app server. I
then resumed the same thread on both and verified that changes like plan
mode, fast mode, model, reasoning effort, etc. are reflected "live" in
the second client when modified in the first and vice versa.
monkeycode-ai Bot pushed a commit to agogo233/Ecode that referenced this pull request Jun 8, 2026
**Stack position:** [1 of 7]

## Summary

The first three PRs in this stack are a cleanup pass before the actual
thread settings API work.

Today, core has several overlapping "user input" ops: `UserInput`,
`UserInputWithTurnContext`, and `UserTurn`. They differ mostly in how
much next-turn state they carry, which makes the later queued thread
settings update harder to reason about and review.

This PR starts that cleanup by adding the shared
`ThreadSettingsOverrides` payload and allowing `Op::UserInput` to carry
it. Existing variants remain in place here, so this layer is mostly a
behavior-preserving API shape change plus mechanical constructor
updates.

## End State After PR3

By the end of PR3, `Op::UserInput` is the only "user input" core op. It
can carry optional thread settings overrides for callers that need to
update stored defaults with a turn, while callers without updates use
empty settings. `Op::UserInputWithTurnContext` and `Op::UserTurn` are
deleted.

## End State After PR5

By the end of PR5, core will have only two ops for this area:

- `Op::UserInput` for user-input-bearing submissions.
- `Op::ThreadSettings` for settings-only updates.

## Stack

1. [1 of 7] [Add thread settings to
UserInput](openai/codex#23080) (this PR)
2. [2 of 7] [Remove
UserInputWithTurnContext](openai/codex#23081)
3. [3 of 7] [Remove
UserTurn](openai/codex#23075)
4. [4 of 7] [Placeholder for OverrideTurnContext
cleanup](openai/codex#23087)
5. [5 of 7] [Replace OverrideTurnContext with
ThreadSettings](openai/codex#22508)
6. [6 of 7] [Add app-server thread settings
API](openai/codex#22509)
7. [7 of 7] [Sync TUI thread
settings](openai/codex#22510)
monkeycode-ai Bot pushed a commit to agogo233/Ecode that referenced this pull request Jun 8, 2026
**Stack position:** [2 of 7]

## Summary

This PR removes the overlapping `Op::UserInputWithTurnContext` variant
now that `Op::UserInput` can carry thread settings overrides directly.

## Stack

1. [1 of 7] [Add thread settings to
UserInput](openai/codex#23080)
2. [2 of 7] [Remove
UserInputWithTurnContext](openai/codex#23081)
(this PR)
3. [3 of 7] [Remove
UserTurn](openai/codex#23075)
4. [4 of 7] [Placeholder for OverrideTurnContext
cleanup](openai/codex#23087)
5. [5 of 7] [Replace OverrideTurnContext with
ThreadSettings](openai/codex#22508)
6. [6 of 7] [Add app-server thread settings
API](openai/codex#22509)
7. [7 of 7] [Sync TUI thread
settings](openai/codex#22510)
monkeycode-ai Bot pushed a commit to agogo233/Ecode that referenced this pull request Jun 8, 2026
**Stack position:** [3 of 7]

## Summary

This PR finishes the input-op consolidation by moving the remaining
`Op::UserTurn` callers onto `Op::UserInput` and deleting `Op::UserTurn`.
This touches a lot of files, but it is a low-risk mechanical migration.

## Stack

1. [1 of 7] [Add thread settings to
UserInput](openai/codex#23080)
2. [2 of 7] [Remove
UserInputWithTurnContext](openai/codex#23081)
3. [3 of 7] [Remove
UserTurn](openai/codex#23075) (this PR)
4. [4 of 7] [Placeholder for OverrideTurnContext
cleanup](openai/codex#23087)
5. [5 of 7] [Replace OverrideTurnContext with
ThreadSettings](openai/codex#22508)
6. [6 of 7] [Add app-server thread settings
API](openai/codex#22509)
7. [7 of 7] [Sync TUI thread
settings](openai/codex#22510)
monkeycode-ai Bot pushed a commit to agogo233/Ecode that referenced this pull request Jun 8, 2026
**Stack position:** [5 of 7]

## Summary

This PR adds `Op::ThreadSettings`, a queued settings-only update
mechanism for changing stored thread settings without starting a new
turn. It also removes the legacy `Op::OverrideTurnContext` in the same
layer, so reviewers can see the replacement and deletion together.

## Changes

- Add `Op::ThreadSettings` for settings-only queued updates.
- Emit `ThreadSettingsApplied` with the effective thread settings
snapshot after core applies an update.
- Route settings-only updates through the same submission queue as user
input.
- Migrate remaining `OverrideTurnContext` tests and callers to the
queued `Op::ThreadSettings` path.
- Delete `Op::OverrideTurnContext` from the core protocol and submission
loop.

This stack addresses #20656 and #22090.

## Stack

1. [1 of 7] [Add thread settings to
UserInput](openai/codex#23080)
2. [2 of 7] [Remove
UserInputWithTurnContext](openai/codex#23081)
3. [3 of 7] [Remove
UserTurn](openai/codex#23075)
4. [4 of 7] [Placeholder for OverrideTurnContext
cleanup](openai/codex#23087)
5. [5 of 7] [Replace OverrideTurnContext with
ThreadSettings](openai/codex#22508) (this PR)
6. [6 of 7] [Add app-server thread settings
API](openai/codex#22509)
7. [7 of 7] [Sync TUI thread
settings](openai/codex#22510)
monkeycode-ai Bot pushed a commit to agogo233/Ecode that referenced this pull request Jun 8, 2026
Builds on #23502.

## Why

#23502 adds the app-server `thread/settings/update` API and matching
`thread/settings/updated` notification. The TUI already lets users
change thread-scoped settings such as model, reasoning effort, service
tier, approvals, permissions, personality, and collaboration mode, but
those updates need to flow through the app server so embedded and
connected clients observe the same thread state.

This is a rework (simplification) of PR
openai/codex#22510. It has the same
functionality, but the underlying `thread/settings/update` api is now
simpler in that it no longer returns the effective settings as a
response. Now, clients receive the effective settings only through the
`thread/settings/updated` notification.

## What Changed

This updates the TUI to send `thread/settings/update` whenever those
thread-scoped settings change and to treat the RPC response as the
authoritative acknowledgement. It also routes `thread/settings/updated`
notifications back into cached session state and the visible chat widget
so active and inactive threads stay in sync after app-server-originated
changes.

The implementation is kept to the TUI layer: settings conversion and
merge logic live under `codex-rs/tui/src/app/thread_settings.rs`, with
dispatch/routing hooks in the existing app and chat widget paths.

## Verification

I manually tested using `codex app-server --listen unix://` and then
launching two copies of the TUI that use the same local app server. I
then resumed the same thread on both and verified that changes like plan
mode, fast mode, model, reasoning effort, etc. are reflected "live" in
the second client when modified in the first and vice versa.
dkropachev pushed a commit to dkropachev/codex that referenced this pull request Jun 9, 2026
**Stack position:** [1 of 7]

## Summary

The first three PRs in this stack are a cleanup pass before the actual
thread settings API work.

Today, core has several overlapping "user input" ops: `UserInput`,
`UserInputWithTurnContext`, and `UserTurn`. They differ mostly in how
much next-turn state they carry, which makes the later queued thread
settings update harder to reason about and review.

This PR starts that cleanup by adding the shared
`ThreadSettingsOverrides` payload and allowing `Op::UserInput` to carry
it. Existing variants remain in place here, so this layer is mostly a
behavior-preserving API shape change plus mechanical constructor
updates.

## End State After PR3

By the end of PR3, `Op::UserInput` is the only "user input" core op. It
can carry optional thread settings overrides for callers that need to
update stored defaults with a turn, while callers without updates use
empty settings. `Op::UserInputWithTurnContext` and `Op::UserTurn` are
deleted.

## End State After PR5

By the end of PR5, core will have only two ops for this area:

- `Op::UserInput` for user-input-bearing submissions.
- `Op::ThreadSettings` for settings-only updates.

## Stack

1. [1 of 7] [Add thread settings to
UserInput](openai#23080) (this PR)
2. [2 of 7] [Remove
UserInputWithTurnContext](openai#23081)
3. [3 of 7] [Remove
UserTurn](openai#23075)
4. [4 of 7] [Placeholder for OverrideTurnContext
cleanup](openai#23087)
5. [5 of 7] [Replace OverrideTurnContext with
ThreadSettings](openai#22508)
6. [6 of 7] [Add app-server thread settings
API](openai#22509)
7. [7 of 7] [Sync TUI thread
settings](openai#22510)
dkropachev pushed a commit to dkropachev/codex that referenced this pull request Jun 9, 2026
**Stack position:** [2 of 7]

## Summary

This PR removes the overlapping `Op::UserInputWithTurnContext` variant
now that `Op::UserInput` can carry thread settings overrides directly.

## Stack

1. [1 of 7] [Add thread settings to
UserInput](openai#23080)
2. [2 of 7] [Remove
UserInputWithTurnContext](openai#23081)
(this PR)
3. [3 of 7] [Remove
UserTurn](openai#23075)
4. [4 of 7] [Placeholder for OverrideTurnContext
cleanup](openai#23087)
5. [5 of 7] [Replace OverrideTurnContext with
ThreadSettings](openai#22508)
6. [6 of 7] [Add app-server thread settings
API](openai#22509)
7. [7 of 7] [Sync TUI thread
settings](openai#22510)
dkropachev pushed a commit to dkropachev/codex that referenced this pull request Jun 9, 2026
**Stack position:** [3 of 7]

## Summary

This PR finishes the input-op consolidation by moving the remaining
`Op::UserTurn` callers onto `Op::UserInput` and deleting `Op::UserTurn`.
This touches a lot of files, but it is a low-risk mechanical migration.

## Stack

1. [1 of 7] [Add thread settings to
UserInput](openai#23080)
2. [2 of 7] [Remove
UserInputWithTurnContext](openai#23081)
3. [3 of 7] [Remove
UserTurn](openai#23075) (this PR)
4. [4 of 7] [Placeholder for OverrideTurnContext
cleanup](openai#23087)
5. [5 of 7] [Replace OverrideTurnContext with
ThreadSettings](openai#22508)
6. [6 of 7] [Add app-server thread settings
API](openai#22509)
7. [7 of 7] [Sync TUI thread
settings](openai#22510)
dkropachev pushed a commit to dkropachev/codex that referenced this pull request Jun 9, 2026
**Stack position:** [5 of 7]

## Summary

This PR adds `Op::ThreadSettings`, a queued settings-only update
mechanism for changing stored thread settings without starting a new
turn. It also removes the legacy `Op::OverrideTurnContext` in the same
layer, so reviewers can see the replacement and deletion together.

## Changes

- Add `Op::ThreadSettings` for settings-only queued updates.
- Emit `ThreadSettingsApplied` with the effective thread settings
snapshot after core applies an update.
- Route settings-only updates through the same submission queue as user
input.
- Migrate remaining `OverrideTurnContext` tests and callers to the
queued `Op::ThreadSettings` path.
- Delete `Op::OverrideTurnContext` from the core protocol and submission
loop.

This stack addresses openai#20656 and openai#22090.

## Stack

1. [1 of 7] [Add thread settings to
UserInput](openai#23080)
2. [2 of 7] [Remove
UserInputWithTurnContext](openai#23081)
3. [3 of 7] [Remove
UserTurn](openai#23075)
4. [4 of 7] [Placeholder for OverrideTurnContext
cleanup](openai#23087)
5. [5 of 7] [Replace OverrideTurnContext with
ThreadSettings](openai#22508) (this PR)
6. [6 of 7] [Add app-server thread settings
API](openai#22509)
7. [7 of 7] [Sync TUI thread
settings](openai#22510)
dkropachev pushed a commit to dkropachev/codex that referenced this pull request Jun 9, 2026
Builds on openai#23502.

## Why

openai#23502 adds the app-server `thread/settings/update` API and matching
`thread/settings/updated` notification. The TUI already lets users
change thread-scoped settings such as model, reasoning effort, service
tier, approvals, permissions, personality, and collaboration mode, but
those updates need to flow through the app server so embedded and
connected clients observe the same thread state.

This is a rework (simplification) of PR
openai#22510. It has the same
functionality, but the underlying `thread/settings/update` api is now
simpler in that it no longer returns the effective settings as a
response. Now, clients receive the effective settings only through the
`thread/settings/updated` notification.

## What Changed

This updates the TUI to send `thread/settings/update` whenever those
thread-scoped settings change and to treat the RPC response as the
authoritative acknowledgement. It also routes `thread/settings/updated`
notifications back into cached session state and the visible chat widget
so active and inactive threads stay in sync after app-server-originated
changes.

The implementation is kept to the TUI layer: settings conversion and
merge logic live under `codex-rs/tui/src/app/thread_settings.rs`, with
dispatch/routing hooks in the existing app and chat widget paths.

## Verification

I manually tested using `codex app-server --listen unix://` and then
launching two copies of the TUI that use the same local app server. I
then resumed the same thread on both and verified that changes like plan
mode, fast mode, model, reasoning effort, etc. are reflected "live" in
the second client when modified in the first and vice versa.
dkropachev pushed a commit to dkropachev/codex that referenced this pull request Jun 9, 2026
**Stack position:** [1 of 7]

## Summary

The first three PRs in this stack are a cleanup pass before the actual
thread settings API work.

Today, core has several overlapping "user input" ops: `UserInput`,
`UserInputWithTurnContext`, and `UserTurn`. They differ mostly in how
much next-turn state they carry, which makes the later queued thread
settings update harder to reason about and review.

This PR starts that cleanup by adding the shared
`ThreadSettingsOverrides` payload and allowing `Op::UserInput` to carry
it. Existing variants remain in place here, so this layer is mostly a
behavior-preserving API shape change plus mechanical constructor
updates.

## End State After PR3

By the end of PR3, `Op::UserInput` is the only "user input" core op. It
can carry optional thread settings overrides for callers that need to
update stored defaults with a turn, while callers without updates use
empty settings. `Op::UserInputWithTurnContext` and `Op::UserTurn` are
deleted.

## End State After PR5

By the end of PR5, core will have only two ops for this area:

- `Op::UserInput` for user-input-bearing submissions.
- `Op::ThreadSettings` for settings-only updates.

## Stack

1. [1 of 7] [Add thread settings to
UserInput](openai#23080) (this PR)
2. [2 of 7] [Remove
UserInputWithTurnContext](openai#23081)
3. [3 of 7] [Remove
UserTurn](openai#23075)
4. [4 of 7] [Placeholder for OverrideTurnContext
cleanup](openai#23087)
5. [5 of 7] [Replace OverrideTurnContext with
ThreadSettings](openai#22508)
6. [6 of 7] [Add app-server thread settings
API](openai#22509)
7. [7 of 7] [Sync TUI thread
settings](openai#22510)
dkropachev pushed a commit to dkropachev/codex that referenced this pull request Jun 9, 2026
**Stack position:** [2 of 7]

## Summary

This PR removes the overlapping `Op::UserInputWithTurnContext` variant
now that `Op::UserInput` can carry thread settings overrides directly.

## Stack

1. [1 of 7] [Add thread settings to
UserInput](openai#23080)
2. [2 of 7] [Remove
UserInputWithTurnContext](openai#23081)
(this PR)
3. [3 of 7] [Remove
UserTurn](openai#23075)
4. [4 of 7] [Placeholder for OverrideTurnContext
cleanup](openai#23087)
5. [5 of 7] [Replace OverrideTurnContext with
ThreadSettings](openai#22508)
6. [6 of 7] [Add app-server thread settings
API](openai#22509)
7. [7 of 7] [Sync TUI thread
settings](openai#22510)
dkropachev pushed a commit to dkropachev/codex that referenced this pull request Jun 9, 2026
**Stack position:** [3 of 7]

## Summary

This PR finishes the input-op consolidation by moving the remaining
`Op::UserTurn` callers onto `Op::UserInput` and deleting `Op::UserTurn`.
This touches a lot of files, but it is a low-risk mechanical migration.

## Stack

1. [1 of 7] [Add thread settings to
UserInput](openai#23080)
2. [2 of 7] [Remove
UserInputWithTurnContext](openai#23081)
3. [3 of 7] [Remove
UserTurn](openai#23075) (this PR)
4. [4 of 7] [Placeholder for OverrideTurnContext
cleanup](openai#23087)
5. [5 of 7] [Replace OverrideTurnContext with
ThreadSettings](openai#22508)
6. [6 of 7] [Add app-server thread settings
API](openai#22509)
7. [7 of 7] [Sync TUI thread
settings](openai#22510)
dkropachev pushed a commit to dkropachev/codex that referenced this pull request Jun 9, 2026
**Stack position:** [5 of 7]

## Summary

This PR adds `Op::ThreadSettings`, a queued settings-only update
mechanism for changing stored thread settings without starting a new
turn. It also removes the legacy `Op::OverrideTurnContext` in the same
layer, so reviewers can see the replacement and deletion together.

## Changes

- Add `Op::ThreadSettings` for settings-only queued updates.
- Emit `ThreadSettingsApplied` with the effective thread settings
snapshot after core applies an update.
- Route settings-only updates through the same submission queue as user
input.
- Migrate remaining `OverrideTurnContext` tests and callers to the
queued `Op::ThreadSettings` path.
- Delete `Op::OverrideTurnContext` from the core protocol and submission
loop.

This stack addresses openai#20656 and openai#22090.

## Stack

1. [1 of 7] [Add thread settings to
UserInput](openai#23080)
2. [2 of 7] [Remove
UserInputWithTurnContext](openai#23081)
3. [3 of 7] [Remove
UserTurn](openai#23075)
4. [4 of 7] [Placeholder for OverrideTurnContext
cleanup](openai#23087)
5. [5 of 7] [Replace OverrideTurnContext with
ThreadSettings](openai#22508) (this PR)
6. [6 of 7] [Add app-server thread settings
API](openai#22509)
7. [7 of 7] [Sync TUI thread
settings](openai#22510)
dkropachev pushed a commit to dkropachev/codex that referenced this pull request Jun 9, 2026
Builds on openai#23502.

## Why

openai#23502 adds the app-server `thread/settings/update` API and matching
`thread/settings/updated` notification. The TUI already lets users
change thread-scoped settings such as model, reasoning effort, service
tier, approvals, permissions, personality, and collaboration mode, but
those updates need to flow through the app server so embedded and
connected clients observe the same thread state.

This is a rework (simplification) of PR
openai#22510. It has the same
functionality, but the underlying `thread/settings/update` api is now
simpler in that it no longer returns the effective settings as a
response. Now, clients receive the effective settings only through the
`thread/settings/updated` notification.

## What Changed

This updates the TUI to send `thread/settings/update` whenever those
thread-scoped settings change and to treat the RPC response as the
authoritative acknowledgement. It also routes `thread/settings/updated`
notifications back into cached session state and the visible chat widget
so active and inactive threads stay in sync after app-server-originated
changes.

The implementation is kept to the TUI layer: settings conversion and
merge logic live under `codex-rs/tui/src/app/thread_settings.rs`, with
dispatch/routing hooks in the existing app and chat widget paths.

## Verification

I manually tested using `codex app-server --listen unix://` and then
launching two copies of the TUI that use the same local app server. I
then resumed the same thread on both and verified that changes like plan
mode, fast mode, model, reasoning effort, etc. are reflected "live" in
the second client when modified in the first and vice versa.
dkropachev pushed a commit to dkropachev/codex that referenced this pull request Jun 9, 2026
**Stack position:** [1 of 7]

## Summary

The first three PRs in this stack are a cleanup pass before the actual
thread settings API work.

Today, core has several overlapping "user input" ops: `UserInput`,
`UserInputWithTurnContext`, and `UserTurn`. They differ mostly in how
much next-turn state they carry, which makes the later queued thread
settings update harder to reason about and review.

This PR starts that cleanup by adding the shared
`ThreadSettingsOverrides` payload and allowing `Op::UserInput` to carry
it. Existing variants remain in place here, so this layer is mostly a
behavior-preserving API shape change plus mechanical constructor
updates.

## End State After PR3

By the end of PR3, `Op::UserInput` is the only "user input" core op. It
can carry optional thread settings overrides for callers that need to
update stored defaults with a turn, while callers without updates use
empty settings. `Op::UserInputWithTurnContext` and `Op::UserTurn` are
deleted.

## End State After PR5

By the end of PR5, core will have only two ops for this area:

- `Op::UserInput` for user-input-bearing submissions.
- `Op::ThreadSettings` for settings-only updates.

## Stack

1. [1 of 7] [Add thread settings to
UserInput](openai#23080) (this PR)
2. [2 of 7] [Remove
UserInputWithTurnContext](openai#23081)
3. [3 of 7] [Remove
UserTurn](openai#23075)
4. [4 of 7] [Placeholder for OverrideTurnContext
cleanup](openai#23087)
5. [5 of 7] [Replace OverrideTurnContext with
ThreadSettings](openai#22508)
6. [6 of 7] [Add app-server thread settings
API](openai#22509)
7. [7 of 7] [Sync TUI thread
settings](openai#22510)
dkropachev pushed a commit to dkropachev/codex that referenced this pull request Jun 9, 2026
**Stack position:** [2 of 7]

## Summary

This PR removes the overlapping `Op::UserInputWithTurnContext` variant
now that `Op::UserInput` can carry thread settings overrides directly.

## Stack

1. [1 of 7] [Add thread settings to
UserInput](openai#23080)
2. [2 of 7] [Remove
UserInputWithTurnContext](openai#23081)
(this PR)
3. [3 of 7] [Remove
UserTurn](openai#23075)
4. [4 of 7] [Placeholder for OverrideTurnContext
cleanup](openai#23087)
5. [5 of 7] [Replace OverrideTurnContext with
ThreadSettings](openai#22508)
6. [6 of 7] [Add app-server thread settings
API](openai#22509)
7. [7 of 7] [Sync TUI thread
settings](openai#22510)
dkropachev pushed a commit to dkropachev/codex that referenced this pull request Jun 9, 2026
**Stack position:** [3 of 7]

## Summary

This PR finishes the input-op consolidation by moving the remaining
`Op::UserTurn` callers onto `Op::UserInput` and deleting `Op::UserTurn`.
This touches a lot of files, but it is a low-risk mechanical migration.

## Stack

1. [1 of 7] [Add thread settings to
UserInput](openai#23080)
2. [2 of 7] [Remove
UserInputWithTurnContext](openai#23081)
3. [3 of 7] [Remove
UserTurn](openai#23075) (this PR)
4. [4 of 7] [Placeholder for OverrideTurnContext
cleanup](openai#23087)
5. [5 of 7] [Replace OverrideTurnContext with
ThreadSettings](openai#22508)
6. [6 of 7] [Add app-server thread settings
API](openai#22509)
7. [7 of 7] [Sync TUI thread
settings](openai#22510)
dkropachev pushed a commit to dkropachev/codex that referenced this pull request Jun 9, 2026
**Stack position:** [5 of 7]

## Summary

This PR adds `Op::ThreadSettings`, a queued settings-only update
mechanism for changing stored thread settings without starting a new
turn. It also removes the legacy `Op::OverrideTurnContext` in the same
layer, so reviewers can see the replacement and deletion together.

## Changes

- Add `Op::ThreadSettings` for settings-only queued updates.
- Emit `ThreadSettingsApplied` with the effective thread settings
snapshot after core applies an update.
- Route settings-only updates through the same submission queue as user
input.
- Migrate remaining `OverrideTurnContext` tests and callers to the
queued `Op::ThreadSettings` path.
- Delete `Op::OverrideTurnContext` from the core protocol and submission
loop.

This stack addresses openai#20656 and openai#22090.

## Stack

1. [1 of 7] [Add thread settings to
UserInput](openai#23080)
2. [2 of 7] [Remove
UserInputWithTurnContext](openai#23081)
3. [3 of 7] [Remove
UserTurn](openai#23075)
4. [4 of 7] [Placeholder for OverrideTurnContext
cleanup](openai#23087)
5. [5 of 7] [Replace OverrideTurnContext with
ThreadSettings](openai#22508) (this PR)
6. [6 of 7] [Add app-server thread settings
API](openai#22509)
7. [7 of 7] [Sync TUI thread
settings](openai#22510)
dkropachev pushed a commit to dkropachev/codex that referenced this pull request Jun 9, 2026
Builds on openai#23502.

## Why

openai#23502 adds the app-server `thread/settings/update` API and matching
`thread/settings/updated` notification. The TUI already lets users
change thread-scoped settings such as model, reasoning effort, service
tier, approvals, permissions, personality, and collaboration mode, but
those updates need to flow through the app server so embedded and
connected clients observe the same thread state.

This is a rework (simplification) of PR
openai#22510. It has the same
functionality, but the underlying `thread/settings/update` api is now
simpler in that it no longer returns the effective settings as a
response. Now, clients receive the effective settings only through the
`thread/settings/updated` notification.

## What Changed

This updates the TUI to send `thread/settings/update` whenever those
thread-scoped settings change and to treat the RPC response as the
authoritative acknowledgement. It also routes `thread/settings/updated`
notifications back into cached session state and the visible chat widget
so active and inactive threads stay in sync after app-server-originated
changes.

The implementation is kept to the TUI layer: settings conversion and
merge logic live under `codex-rs/tui/src/app/thread_settings.rs`, with
dispatch/routing hooks in the existing app and chat widget paths.

## Verification

I manually tested using `codex app-server --listen unix://` and then
launching two copies of the TUI that use the same local app server. I
then resumed the same thread on both and verified that changes like plan
mode, fast mode, model, reasoning effort, etc. are reflected "live" in
the second client when modified in the first and vice versa.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants