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
@@ -1588,6 +1588,9 @@ impl Session {
previous_permission_profile != updated_permission_profile;
let mcp_inputs_changed =
self.mcp_inputs_differ(&state.session_configuration, &updated, &updates);
if mcp_inputs_changed {
self.mark_mcp_runtime_dirty();
}
let environment_config = updated.turn_environment_config();
if let Some(environments) = &updates.environments {
self.services
@@ -1601,9 +1604,6 @@ impl Session {
state.session_configuration = updated;
let new_config = notify_config_contributors
.then(|| self.build_effective_session_config(&state.session_configuration));
if mcp_inputs_changed {
self.mark_mcp_runtime_dirty();
}
(
previous_config,
new_config,