Skip to content

[1 of 4] tui: route primary settings writes through app server#22913

Merged
etraut-openai merged 7 commits into
mainfrom
etraut/tui-config-app-server-1-settings
May 16, 2026
Merged

[1 of 4] tui: route primary settings writes through app server#22913
etraut-openai merged 7 commits into
mainfrom
etraut/tui-config-app-server-1-settings

Conversation

@etraut-openai
Copy link
Copy Markdown
Collaborator

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

Why

The TUI can run against a remote app server, but several high-traffic settings still persisted by editing the local config file. That sends remote sessions' preference writes to the wrong machine and lets local disk state drift from the app-server-owned config.

This is [1 of 4] in a stacked series that moves TUI-owned config mutations onto app-server APIs.

What changed

  • Added a small TUI helper for typed app-server config writes.
  • Routed primary interactive preference writes through config/batchWrite.
  • Preserved existing profile scoping for settings that already support profiles.<profile>.* overrides.

Config keys affected

  • model
  • model_reasoning_effort
  • personality
  • service_tier
  • plan_mode_reasoning_effort
  • approvals_reviewer
  • notice.fast_default_opt_out
  • Profile-scoped equivalents under profiles.<profile>.*

Suggested manual validation

  • Connect the TUI to a remote app server, change model and model_reasoning_effort, reconnect, and confirm the remote config retained both values while the local config.toml did not change.
  • Change personality, plan_mode_reasoning_effort, and the explicit auto-review selection, then reconnect and confirm those choices persist through the app server.
  • Clear the service tier back to default and confirm service_tier is cleared while notice.fast_default_opt_out = true is persisted remotely.
  • Repeat one setting change with an active profile and confirm the write lands under profiles.<profile>.*.

Stack

  1. #22913 [1 of 4] primary settings writes
  2. #22914 [2 of 4] app and skill enablement
  3. #22915 [3 of 4] feature and memory toggles
  4. #22916 [4 of 4] startup and onboarding bookkeeping

Copy link
Copy Markdown
Contributor

@fcoury-oai fcoury-oai left a comment

Choose a reason for hiding this comment

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

Check the issue Codex found. I was able to replicate it.


pub(crate) fn profile_scoped_key_path(profile: Option<&str>, key_path: &str) -> String {
if let Some(profile) = profile {
format!("profiles.{profile}.{key_path}")
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 problem here with the help of Codex. When you write a profile with "a.b" notation, it will write to config.toml as:

[profiles.sample.profile]
model = "..."

The correct way is:

[profiles."sample.profile"]
model = "...""

I created a profile like this:

profile = "team.prod"

[profiles."team.prod"]
model = "gpt-5.3-spark"
model_reasoning_effort = "medium"

And when I changed the model in the TUI I got:

[profiles.team.prod]
model = "gpt-5.5"
model_reasoning_effort = "xhigh"

And sure enough it uses the version with quotes when I start codex:

Image

Suggested fix: reuse the existing segment-based config edit model instead of building profile paths with raw dot concatenation. Core already preserves profile names as one segment via ConfigEdit::SetPath { segments } / ConfigEditsBuilder::with_profile; the lossy part here is the app-server key_path string being parsed with split('.').

A compatible fix would be:

  1. Replace parse_key_path with a small TOML dotted-key parser that supports quoted segments.
  2. Emit quoted profile segments from profile_scoped_key_path, e.g. profiles."team.prod".model.
  3. Add a regression test where both [profiles."team.prod"] and [profiles.team.prod] exist, then assert config/batchWrite updates only the quoted active profile.

That keeps this PR’s app-server write direction while matching the profile resolution behavior used at startup.

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.

Good find. This appears to be an existing bug in the app server layer. I'm going to explore whether it makes sense to fix as part of this PR or whether we should get a fix in place prior to merging this PR.

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.

I was able to fix the app server bug with a relatively surgical fix (plus some regression tests), so I decided to include it as part of this PR.

Copy link
Copy Markdown
Contributor

@fcoury-oai fcoury-oai left a comment

Choose a reason for hiding this comment

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

Approved 👍

Copy link
Copy Markdown
Contributor

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b74ce8d478

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread codex-rs/app-server/src/config_manager_service.rs Outdated
@etraut-openai etraut-openai merged commit 0445b29 into main May 16, 2026
31 checks passed
@etraut-openai etraut-openai deleted the etraut/tui-config-app-server-1-settings branch May 16, 2026 21:27
@github-actions github-actions Bot locked and limited conversation to collaborators May 16, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants