Synced from monorepo

Synced from monorepo

Changes:
- Release a shell session's resources in one drop
- Make the tools blocking-wait cap client-configurable and self-describing
- Recognize API "exceeds budget" errors as context overflow
- Retry /btw on model overload
- Carry running background tasks and subagents across compaction
- Require round-trip time for SDK liveness checks
- Background-subagent completion reminders with a selectable delivery surface
- Make a PTY shell reap itself until it reaches the registry
- Recover the OS error code from a TLS-phase connection reset
- Consume the attached-client signal and report why idle is withheld
- Treat `.grok/sandbox.toml` edits as protected so auto mode prompts before writing
- Surface history/search in the Ctrl+. cheatsheet and keep it working in history view
- Delete sessions from the dashboard and welcome list
- Release a session's activity record when the session ends
- Stop charging auth-retry budget for fail-closed 401s; reset it across suspends
- Scope skills watches on project vendor roots
- Make [stop] cancel in-flight compaction
- Make the leader soak measure the leader, not its harness

Source-Revision: 8d69c91f02bcacf01e98d5aebbf2f92547c45738
This commit is contained in:
grokkybara[bot] 2026-07-31 18:08:03 +00:00
commit a422116582
165 changed files with 15161 additions and 1969 deletions

View file

@ -415,6 +415,40 @@ pub fn error_cause_chain(err: &dyn std::error::Error) -> String {
msg
}
/// First OS error code in `err`'s `source()` chain (e.g. 104 `ECONNRESET` on
/// Linux, 10054 on Windows), preferring [`std::io::Error::raw_os_error`] and
/// falling back to the `(os error N)` suffix `io::Error`'s `Display` appends.
///
/// The fallback is load-bearing: a reset during the TLS handshake arrives as a
/// *custom* `io::Error` (kind `Other`, no raw code) whose only record of the
/// code is that suffix, and without it a rustls reset is indistinguishable
/// from an unreachable host.
///
/// `+ 'static` because `downcast_ref` resolves the type through
/// [`std::any::Any`], whose type ids only exist for `'static` types.
pub fn find_os_error_code(err: &(dyn std::error::Error + 'static)) -> Option<i32> {
let mut cur: Option<&(dyn std::error::Error + 'static)> = Some(err);
while let Some(e) = cur {
if let Some(code) = e.downcast_ref::<std::io::Error>().and_then(|ioe| {
ioe.raw_os_error()
.or_else(|| parse_os_error(&ioe.to_string()))
}) {
return Some(code);
}
cur = e.source();
}
None
}
/// Extract `N` from a message ending in `(os error N)`.
fn parse_os_error(msg: &str) -> Option<i32> {
msg.rsplit_once("(os error ")?
.1
.trim_end_matches(')')
.parse()
.ok()
}
/// How a `reqwest` request/send failure should be treated by a retry loop.
#[derive(Debug, PartialEq, Eq)]
pub enum TransportFailureKind {
@ -601,6 +635,104 @@ mod tests {
);
}
#[test]
fn find_os_error_code_walks_source_chain() {
#[derive(Debug)]
struct IoLeaf(std::io::Error);
impl std::fmt::Display for IoLeaf {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "io leaf")
}
}
impl std::error::Error for IoLeaf {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&self.0)
}
}
#[derive(Debug)]
struct Wrapper(IoLeaf);
impl std::fmt::Display for Wrapper {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "wrapper")
}
}
impl std::error::Error for Wrapper {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&self.0)
}
}
let err = Wrapper(IoLeaf(std::io::Error::from_raw_os_error(104)));
assert_eq!(find_os_error_code(&err), Some(104));
assert_eq!(find_os_error_code(&std::io::Error::other("no code")), None);
}
/// A TLS-handshake reset arrives as a custom `io::Error` with no raw code;
/// live reqwest gives the chain `client error (Connect)` →
/// `Connection reset by peer (os error 54)`.
#[test]
fn recovers_code_from_a_custom_io_error() {
let tls_shaped = std::io::Error::other("Connection reset by peer (os error 54)");
assert_eq!(tls_shaped.raw_os_error(), None, "precondition: no raw code");
assert_eq!(find_os_error_code(&tls_shaped), Some(54));
let windows_shaped = std::io::Error::other(
"An existing connection was forcibly closed by the remote host. (os error 10054)",
);
assert_eq!(find_os_error_code(&windows_shaped), Some(10054));
}
/// Over a real socket: a mid-request reset must classify as `Interrupted`
/// *and* surface the OS code, which is what lets a fleet report tell "peer
/// reset us" from "server unreachable".
///
/// Lives here rather than in a caller's crate: a `reqwest` client drags
/// rustls into the test binary, which not every caller's tests tolerate.
#[test]
fn real_connection_reset_classifies_as_interrupted_with_os_code() {
// Closing a socket whose receive queue still holds the request emits
// RST instead of FIN.
let listener = std::net::TcpListener::bind("127.0.0.1:0").expect("bind");
let port = listener.local_addr().expect("addr").port();
std::thread::spawn(move || {
let sock = listener.accept().expect("accept").0;
sock.set_read_timeout(Some(std::time::Duration::from_secs(5)))
.expect("read timeout");
let _ = sock.peek(&mut [0u8; 64]);
drop(sock);
});
let err = reqwest::blocking::Client::new()
.get(format!("http://127.0.0.1:{port}/oauth2/device/code"))
.send()
.expect_err("reset must fail the request");
assert_eq!(
TransportFailure::classify(&err).kind,
TransportFailureKind::Interrupted
);
assert!(
// ECONNRESET: 54 on macOS, 104 on Linux, 10054 on Windows.
matches!(find_os_error_code(&err), Some(54 | 104 | 10054)),
"reset must carry an OS code, got {:?}",
find_os_error_code(&err)
);
}
#[test]
fn parse_os_error_ignores_messages_without_a_code() {
assert_eq!(
parse_os_error("connection closed before message completed"),
None
);
assert_eq!(
parse_os_error("invalid peer certificate (os error oops)"),
None
);
assert_eq!(parse_os_error("broken pipe (os error 32)"), Some(32));
}
#[test]
fn origin_client_info_from_meta_extracts_identifier_and_version() {
let meta = serde_json::json!({