Add direct replies for thread settings updates (#47937)

## Why

Callers need to await acceptance or rejection of thread settings without consuming the thread event stream. Acceptance must precede event delivery because the caller may hold a lock needed by the event consumer.

## What changed

- Add `CodexThread::update_thread_settings` and re-export `ThreadSettingsOverrides` from `core-api`.
- Add an optional reply channel to `Op::ThreadSettings`. Return validation failures as `InvalidRequest` through that channel, retaining error events for callers without a reply channel.
- Reply to successful updates before emitting `ThreadSettingsApplied`, while holding the settings persistence lock through notification.

## Testing

Extend settings constraint coverage to direct replies, including rejection without an error event and successful notification. Verify that acceptance and continuation invalidation precede blocked event delivery, while checkpointing waits for notification.

GitOrigin-RevId: e09b0d3cc4b6750709c173371632f19619e5c250
This commit is contained in:
sayan-oai
2026-09-24 20:59:51 +00:00
committed by copyberry
parent 339e981ba7
commit fbd0c0d96c
14 changed files with 150 additions and 42 deletions
+16
View File
@@ -45,6 +45,7 @@ use codex_protocol::protocol::SandboxPolicy;
use codex_protocol::protocol::SessionSource;
use codex_protocol::protocol::ThreadHistoryMode;
use codex_protocol::protocol::ThreadMemoryMode;
use codex_protocol::protocol::ThreadSettingsOverrides;
use codex_protocol::protocol::ThreadSettingsSnapshot;
use codex_protocol::protocol::ThreadSource;
use codex_protocol::protocol::TokenUsageInfo;
@@ -586,6 +587,21 @@ impl CodexThread {
self.session.preview_settings(&updates).await
}
/// Queues settings for future turns and waits for Core to accept or reject them.
/// Rejections are returned to the caller instead of emitted as thread errors.
pub async fn update_thread_settings(
&self,
thread_settings: ThreadSettingsOverrides,
) -> CodexResult<()> {
let (reply, result) = oneshot::channel();
self.submit(Op::ThreadSettings {
thread_settings,
reply: Some(reply),
})
.await?;
result.await.unwrap_or(Err(CodexErr::InternalAgentDied))
}
/// Restores thread-owned mutable settings captured from another loaded runtime.
///
/// Runtime replacement uses this after resume so clients keep their current thread settings