mirror of
https://github.com/openai/codex.git
synced 2026-11-13 22:47:20 +00:00
Expose model settings in app-server thread metadata (#42151)
## What changed - Add nullable `model` and `reasoningEffort` fields to the shared app-server `Thread` object and generated schemas. - Report current settings for loaded threads and the latest persisted settings for unloaded threads across thread read, list, start, resume, rollback, metadata update, and notification paths. - Keep unavailable legacy or filesystem-only settings nullable, and allow metadata reads without loading a thread or dispatching queued work. ## Testing - Cover live-setting precedence, persisted settings after restart, null legacy values, and model metadata returned by thread lifecycle operations. GitOrigin-RevId: 22ebe8a8d1910a820d90a97730d812a00d8c1372
This commit is contained in:
1 parent
6b59cefcbb
commit
986ff1cc7c
50 files changed
+633
-33
No files matched your search
@@ -164,8 +164,8 @@ pub(super) fn stored_thread_from_rollout_item(
|
||||
.model_provider
|
||||
.filter(|provider| !provider.is_empty())
|
||||
.unwrap_or_else(|| default_provider.to_string()),
|
||||
model: None,
|
||||
reasoning_effort: None,
|
||||
model: item.model,
|
||||
reasoning_effort: item.reasoning_effort,
|
||||
created_at,
|
||||
updated_at,
|
||||
recency_at,
|
||||
|
||||
@@ -32,7 +32,11 @@ pub(super) async fn read_thread(
|
||||
params: ReadThreadParams,
|
||||
) -> ThreadStoreResult<StoredThread> {
|
||||
let thread_id = params.thread_id;
|
||||
if let Some(metadata) = read_sqlite_metadata(store, thread_id).await
|
||||
let sqlite_metadata = read_sqlite_metadata(store, thread_id).await;
|
||||
let persisted_model_settings = sqlite_metadata
|
||||
.as_ref()
|
||||
.map(|metadata| (metadata.model.clone(), metadata.reasoning_effort.clone()));
|
||||
if let Some(metadata) = sqlite_metadata
|
||||
&& (params.include_archived
|
||||
|| (metadata.archived_at.is_none()
|
||||
&& !rollout_path_is_archived(
|
||||
@@ -66,6 +70,8 @@ pub(super) async fn read_thread(
|
||||
rollout_thread.name = thread.name;
|
||||
}
|
||||
rollout_thread.project_id = thread.project_id;
|
||||
rollout_thread.model = thread.model;
|
||||
rollout_thread.reasoning_effort = thread.reasoning_effort;
|
||||
rollout_thread.git_info = thread.git_info;
|
||||
rollout_thread.permission_profile = permission_profile_from_metadata_value(
|
||||
&metadata_sandbox_policy,
|
||||
@@ -91,6 +97,10 @@ pub(super) async fn read_thread(
|
||||
})?;
|
||||
|
||||
let mut thread = read_thread_from_rollout_path(store, path).await?;
|
||||
if let Some((model, reasoning_effort)) = persisted_model_settings {
|
||||
thread.model = model;
|
||||
thread.reasoning_effort = reasoning_effort;
|
||||
}
|
||||
if !params.include_archived && thread.archived_at.is_some() {
|
||||
return Err(ThreadStoreError::InvalidRequest {
|
||||
message: format!("thread {} is archived", thread.thread_id),
|
||||
@@ -141,6 +151,8 @@ pub(super) async fn read_thread_by_rollout_path(
|
||||
thread.section_position = metadata.section_position;
|
||||
thread.section_entered_at = metadata.section_entered_at;
|
||||
thread.project_id = metadata.project_id;
|
||||
thread.model = metadata.model;
|
||||
thread.reasoning_effort = metadata.reasoning_effort;
|
||||
if !metadata.cwd.as_os_str().is_empty()
|
||||
&& resolve_requested_rollout_path(store, metadata.rollout_path.clone())
|
||||
.await
|
||||
@@ -529,6 +541,7 @@ mod tests {
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::items::TurnItem;
|
||||
use codex_protocol::items::UserMessageItem;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::protocol::EventMsg;
|
||||
use codex_protocol::protocol::ItemCompletedEvent;
|
||||
use codex_protocol::protocol::SandboxPolicy;
|
||||
@@ -1266,6 +1279,8 @@ mod tests {
|
||||
builder.model_provider = Some("stale-sqlite-provider".to_string());
|
||||
let mut metadata = builder.build(config.default_model_provider_id.as_str());
|
||||
metadata.first_user_message = Some("stale sqlite preview".to_string());
|
||||
metadata.model = Some("persisted-model".to_string());
|
||||
metadata.reasoning_effort = Some(ReasoningEffort::High);
|
||||
runtime
|
||||
.upsert_thread(&metadata)
|
||||
.await
|
||||
@@ -1284,6 +1299,10 @@ mod tests {
|
||||
assert_eq!(thread.rollout_path, Some(rollout_path));
|
||||
assert_eq!(thread.preview, "Hello from user");
|
||||
assert_eq!(thread.model_provider, config.default_model_provider_id);
|
||||
assert_eq!(
|
||||
(thread.model.as_deref(), thread.reasoning_effort),
|
||||
(Some("persisted-model"), Some(ReasoningEffort::High))
|
||||
);
|
||||
let history = thread.history.expect("history should load");
|
||||
assert_eq!(history.thread_id, thread_id);
|
||||
assert_eq!(history.items.len(), 2);
|
||||
|
||||
Reference in new issue
Block a user