Support pending environment attachment configuration (#38684)

## Why

An environment connection can be available before its owner has supplied the
configuration for a particular thread attachment. Threads need to start without
blocking while ensuring turns do not use that attachment prematurely.

## What changed

- Accept `Pending` environment configuration and resolve each attachment only
  after both its shared executor connection and owner configuration are ready.
- Add a `Failed` configuration state and `environment_failed` callback so an
  owner can fail one thread's attachment without affecting other threads.
- Keep pending and failed attachments out of capability-root inspection and turn
  environments, and allow failed attachments to recover through a ready update.
- Apply owner configuration before waking a waiting turn so its permission
  profile, login-shell policy, capability roots, and tools are immediately
  consistent.

## Testing

Add an integration test covering non-blocking thread startup, independent ready
and failed callbacks, waiting-turn resumption, installed capability and tool
configuration, and recovery from failure.

GitOrigin-RevId: d587e2025d584c867d782d470b18bf5a1a27b76c
This commit is contained in:
sayan-oai authored and copyberry committed 2026-08-15 01:39:04 +00:00
1 parent eb147c0db3
commit 2ca575026c
7 files changed
+378 -85

No files matched your search

+3 -3
View File
@@ -693,6 +693,9 @@ impl Session {
Ok(next) => {
let mcp_inputs_changed =
self.mcp_inputs_differ(&state.session_configuration, &next, &updates);
if mcp_inputs_changed {
self.mark_mcp_runtime_dirty();
}
let previous_permission_profile =
state.session_configuration.permission_profile();
let next_permission_profile = next.permission_profile();
@@ -712,9 +715,6 @@ impl Session {
.turn_environments
.update_thread_config(&environment_config);
}
if mcp_inputs_changed {
self.mark_mcp_runtime_dirty();
}
state.session_configuration = next.clone();
let new_config = notify_config_contributors
.then(|| self.build_effective_session_config(&state.session_configuration));