Modified the initSandboxV2 function to return a per-request copy of the SandboxConfig, ensuring that concurrent requests to the same assistant have their own mutable configuration. Updated related logging and cleanup processes to utilize the new configuration structure. Additionally, introduced a DefaultOneShotMaxAge constant to manage the lifecycle of OneShot containers more effectively.
Three related bugs caused oneshot containers to run indefinitely:
1. watcher.go: switch b.policy had no case OneShot, so even when the
idle timeout fired, no remove action was emitted.
2. watcher.go + manager.go/recoverBoxes: idleTimeoutD was only set for
Session and LongRunning on recovery; OneShot defaulted to 0, which
caused the watcher to hit the `timeout <= 0` early-return and skip
all checks entirely.
3. agent/sandbox/v2/options.go: same gap — opts.IdleTimeout == 0 guard
only filled defaults for Session and LongRunning.
Fix: add DefaultOneShotIdleTimeout (30 min), wire it in recoverBoxes
and options.go, and add case OneShot → Remove in watcher.go.
Made-with: Cursor
- Renamed `buildInput` to `buildLastUserMessageJSONL` to better reflect its purpose of constructing JSONL from the last user message.
- Updated test cases to use the new function, ensuring they accurately verify the behavior of skipping system messages and only including the last user message.
- Removed the now redundant `buildFirstRequestJSONL` function, streamlining the input building process in the Claude command tests.
- Updated BuildIdentifier to include assistant ID in session identifiers for better uniqueness.
- Implemented automatic starting of stopped boxes in resolveBox, improving recovery processes.
- Introduced status management for boxes, allowing for accurate tracking of their state (running, exited, stopped).
- Added idle timeout defaults based on lifecycle policy in BuildCreateOptions, enhancing configuration flexibility.
- Refactored tests to validate new box status behavior and lifecycle management improvements.
Made-with: Cursor