Skip to content

Add session config loader interface#18208

Merged
rasmusrygaard merged 8 commits into
mainfrom
dev/rasmus/session_config_loader_interface
Apr 20, 2026
Merged

Add session config loader interface#18208
rasmusrygaard merged 8 commits into
mainfrom
dev/rasmus/session_config_loader_interface

Conversation

@rasmusrygaard
Copy link
Copy Markdown
Contributor

@rasmusrygaard rasmusrygaard commented Apr 16, 2026

Why

Cloud-hosted sessions need a way for the service that starts or manages a thread to provide session-owned config without treating all config as if it came from the same user/project/workspace TOML stack.

The important boundary is ownership: some values should be controlled by the session/orchestrator, some by the authenticated user, and later some may come from the executor. The earlier broad config-store shape made that boundary too fuzzy and overlapped heavily with the existing filesystem-backed config loader. This PR starts with the smaller piece we need now: a typed session config loader that can feed the existing config layer stack while preserving the normal precedence and merge behavior.

What Changed

  • Added ThreadConfigLoader and related typed payloads in codex-config.

    • SessionThreadConfig currently supports model_provider, model_providers, and feature flags.
    • UserThreadConfig is present as an ownership boundary, but does not yet add TOML-backed fields.
    • NoopThreadConfigLoader preserves existing behavior when no external loader is configured.
    • StaticThreadConfigLoader supports tests and simple callers.
  • Taught thread config sources to produce ordinary ConfigLayerEntry values so the existing ConfigLayerStack remains the place where precedence and merging happen.

  • Wired the loader through ConfigBuilder, the config loader, and app-server startup paths so app-server can provide session-owned config before deriving a thread config.

  • Added coverage for:

    • translating typed thread config into config layers,
    • inserting thread config layers into the stack at the right precedence,
    • applying session-provided model provider and feature settings when app-server derives config from thread params.

Follow-Ups

This intentionally stops short of adding the remote/service transport. The next pieces are expected to be:

  1. Define the proto/API shape for this interface.
  2. Add a client implementation that can source session config from the service side.

Verification

  • Added unit coverage in codex-config for the loader and layer conversion.
  • Added codex-core config loader coverage for thread config layer precedence.
  • Added app-server coverage that verifies session thread config wins over request-provided config for model provider and feature settings.
ThreadConfigSource::User(_) => {}
}
}
Ok(())
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

not sure if this is the best way to actually inject the values, feels a bit dissatisfying that we're merging into two different locations

.outgoing
.send_error(request_id, error)
.await;
return;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

unclear to me what the correct error semantics are here

Copy link
Copy Markdown
Contributor

@wiltzius-openai wiltzius-openai left a comment

Choose a reason for hiding this comment

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

seems reasonable to me!

}
}

/// Derive the effective [`Config`] by layering three override sources.
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.

think this "three" is up to "five" by now

/// Config values owned by the service that starts or manages the session.
#[derive(Clone, Debug, Default, PartialEq)]
pub struct SessionThreadConfig {
pub model_provider: Option<String>,
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.

should this also be a ModelProviderInfo?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

this is the pointer to a default model provider id

@@ -406,8 +405,8 @@ impl InProcessClientStartArgs {
cli_overrides: self.cli_overrides,
loader_overrides: self.loader_overrides,
cloud_requirements: self.cloud_requirements,
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.

this "cloud requirements" value being passed through the config stack is confusingly named -- I think this is like enterprise config requirements sent down from the cloud? But it seems likely we'll trip on it.

@rasmusrygaard rasmusrygaard force-pushed the dev/rasmus/session_config_loader_interface branch from eaef62b to 7033cc3 Compare April 16, 2026 22:16
@rasmusrygaard rasmusrygaard marked this pull request as ready for review April 17, 2026 19:02
@rasmusrygaard rasmusrygaard force-pushed the dev/rasmus/session_config_loader_interface branch from 7033cc3 to 88a3e85 Compare April 17, 2026 20:48
Comment thread codex-rs/core/src/config_loader/mod.rs Outdated

let thread_config_context = ThreadConfigContext {
thread_id: None,
cwd: cwd.as_ref().map(AbsolutePathBuf::to_path_buf),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

use absolute path everywhere

@rasmusrygaard rasmusrygaard requested a review from a team as a code owner April 20, 2026 20:29
@rasmusrygaard rasmusrygaard enabled auto-merge (squash) April 20, 2026 20:32
@rasmusrygaard rasmusrygaard force-pushed the dev/rasmus/session_config_loader_interface branch from 2da432c to 8c0d098 Compare April 20, 2026 21:48
@rasmusrygaard rasmusrygaard force-pushed the dev/rasmus/session_config_loader_interface branch from 8c0d098 to 97f28ff Compare April 20, 2026 21:53
@rasmusrygaard rasmusrygaard merged commit 7b99410 into main Apr 20, 2026
34 of 36 checks passed
@rasmusrygaard rasmusrygaard deleted the dev/rasmus/session_config_loader_interface branch April 20, 2026 23:05
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

3 participants