Skip to content

Fix TUI remote config reads#23625

Closed
etraut-openai wants to merge 3 commits into
mainfrom
etraut/tui-remote-config-reads
Closed

Fix TUI remote config reads#23625
etraut-openai wants to merge 3 commits into
mainfrom
etraut/tui-remote-config-reads

Conversation

@etraut-openai

Copy link
Copy Markdown
Collaborator

Why

PRs #22914-#22916 are moving TUI config writes to the app server. During review, we found a separate class of bugs already present on main: some remote TUI flows still re-read client-local config after plugin, marketplace, or MCP state should be owned by the app server.

In remote mode, that can show stale client-local state after server-side mutations or render MCP inventory from the wrong config source.

What

  • Refresh plugin and marketplace post-mutation config from app-server config/read layers instead of local config.toml.
  • Build plugin mention capabilities from app-server plugin/list and plugin/read, removing client-local plugin config/cache reads.
  • Render /mcp inventory from app-server status plus app-server config, so client/server config divergence does not misrender remote state.
  • Add focused coverage for remote/client config divergence and configured-only MCP inventory rendering.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 167b0ea080

ℹ️ 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".

let mut capabilities = Vec::new();
for read_params in mention_reads {
let plugin_name = read_params.plugin_name.clone();
match fetch_plugin_detail(request_handle.clone(), read_params).await {

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.

P2 Badge Preserve cwd when hydrating plugin mentions

When the active workspace has project-scoped plugin settings, this plugin/read no longer resolves against the same cwd used for plugin/list; the server-side plugin_read_response derives config from the marketplace path parent, or from no cwd for remote plugins. In that context .codex layers for the current thread, such as skills.config disabling a plugin skill in this repo, are ignored and the mention popup can advertise/inject capabilities that are disabled for the active thread. Please carry the current cwd through hydration or use a read API that resolves against the same cwd.

Useful? React with 👍 / 👎.

.collect()
fn plugin_detail_capability_summary(detail: PluginDetail) -> Option<PluginCapabilitySummary> {
let config_name = plugin_mention_config_name(&detail.marketplace_name, &detail.summary)?;
Some(PluginCapabilitySummary {

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.

P2 Badge Skip plugins with no active capabilities

When plugin/read returns an enabled plugin whose skills are all disabled and that has no MCP servers or apps, this still creates a mention candidate. The previous PluginLoadOutcome::capability_summaries() path filtered out summaries unless they had at least one active skill, MCP server, or app, so this regression can surface $plugin suggestions that contribute nothing but still get submitted as UserInput::Mention. Please return None for zero-capability summaries.

Useful? React with 👍 / 👎.

if let Err(err) = self.refresh_in_memory_config_from_disk().await {
tracing::warn!(error = %err, "failed to refresh config after plugin install");
}
self.refresh_config_layer_stack_from_app_server_best_effort(

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.

P1 Badge Avoid reloading stale local config after server refresh

In the remote TUI, this server-side layer refresh is immediately followed by AppCommand::reload_user_config() in the same success branch, and thread_routing handles that command by calling self.refresh_in_memory_config_from_disk(), rebuilding from the client filesystem. When the server just mutated plugin or marketplace config and the client copy diverges, that subsequent local reload overwrites the app-server layer stack that was just fetched, so the stale-state bug returns after these mutation flows. Please keep the TUI refresh on the app-server config path, or skip the local disk rebuild for remote sessions.

Useful? React with 👍 / 👎.

) -> Result<HashMap<String, McpServerConfig>> {
let response =
fetch_app_server_config(request_handle, Some(cwd), /*include_layers*/ false).await?;
mcp_servers_from_app_server_config(response.config)

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.

P2 Badge Preserve requirement-disabled MCP state from server config

For workspaces where managed requirements disable MCP servers, config/read returns the raw effective config layers rather than the materialized Config after requirements are applied, and McpServerConfig.disabled_reason is also skipped during serialization. Decoding response.config here therefore makes requirement-disabled servers look enabled and drops the reason, while mcpServerStatus/list does not carry an enabled flag to correct it, so /mcp verbose can report a disabled server as enabled. Please fetch a materialized MCP config/status from the app server that includes the constrained enabled state and reason.

Useful? React with 👍 / 👎.

…fig-reads

# Conflicts:
#	codex-rs/tui/src/app/config_persistence.rs
@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Closing this pull request because it has had no updates for more than 14 days. If you plan to continue working on it, feel free to reopen or open a new PR.

@github-actions github-actions Bot closed this Jun 5, 2026
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.

1 participant