Synced from monorepo

Synced from monorepo

Changes:
- Temporarily disable session share link creation in the TUI
- Do not approve plan on empty Enter from the revise prompt
- Expose chat product Skills via ACP available_commands_update
- Return immediately from a blocking wait on an already-completed ACP task
- Split headless pager module for clearer structure
- Stop git worktree prune from removing user registrations on resume
- Use compaction sampler tokenizer for item token counts
- Opt-in extra root CAs via GROK_EXTRA_CA_BUNDLE
- Cancel all session subagents when the user stops
- Let the session persistence actor exit when its session ends
- Make fullscreen terminal resize much cheaper on long sessions
- Report honestly from kill_task when an ACP task does not exist
- Hide /usage for external-auth deployments
- Forward the history-load trailer’s computer_reason to the client
- Remove ineffective no-op tool reminder
- Declare slash-command screen-mode support in one place
- Keep settings enum picker on the committed value until Enter
- Reap a PTY’s full process tree
- Stream tool calls from headless mode over ACP
- Bridge gateway task lifecycle to ACP for chat session background tasks
- Don’t warn about truncated history on a suppressed replay
- Fit full-replace summarizer input and recover on context-length errors
- Stop dropping agents over an unrecognized frontmatter color
- Add /undo as a slash alias for /rewind
- Harden sleep/wake token-refresh paths against forced re-login
- Add session/list ACP method
- Give each sampling backend its own conversion module
- Treat an unenrolled child process as a lint error
- Suppress the cancelled marker on send-now wake turns
- Stop tearing down Roslyn on every edit, and read C# diagnostics

Source-Revision: 2a28b4a86cfc4a4c133c35b7fc2a6a9964387c39
This commit is contained in:
grokkybara[bot] 2026-07-30 19:07:40 +00:00
commit dd04f397b1
367 changed files with 29489 additions and 10051 deletions

View file

@ -187,6 +187,7 @@ fn write_tmux_buffer(text: &str) -> bool {
.stdout(Stdio::null())
.stderr(Stdio::null());
xai_tty_utils::detach_std_command(&mut cmd);
#[allow(clippy::disallowed_methods)] // short-lived clipboard helper, waited on below
let mut child = cmd.spawn()?;
// Bounded wait: a wedged tmux server must not freeze the UI thread.
let status = xai_grok_shared::clipboard::wait_with_deadline(

View file

@ -482,6 +482,21 @@ pub fn legacy_glyph_fallback(s: &str) -> Cow<'_, str> {
Cow::Owned(to_legacy_glyphs(s))
}
/// Single-row toast sinks: glyph fallback, then map control chars to spaces.
/// Borrows when the input is already clean (common path).
pub fn sanitize_toast_message(msg: &str) -> Cow<'_, str> {
let glyph = legacy_glyph_fallback(msg);
if !glyph.chars().any(char::is_control) {
return glyph;
}
Cow::Owned(
glyph
.chars()
.map(|c| if c.is_control() { ' ' } else { c })
.collect(),
)
}
/// Pure glyph → legacy-safe mapping behind [`legacy_glyph_fallback`], split
/// out so tests can exercise the substitution without faking the host probe.
/// `√` matches [`check_mark`]'s fallback; `x` matches [`ballot_x`]'s.
@ -734,6 +749,22 @@ mod tests {
));
}
#[test]
fn sanitize_toast_message_borrows_when_clean() {
assert!(!is_legacy_windows_console());
assert!(matches!(
sanitize_toast_message("plain toast"),
Cow::Borrowed("plain toast")
));
}
#[test]
fn sanitize_toast_message_maps_controls_to_spaces() {
let out = sanitize_toast_message("a\nb\tc");
assert_eq!(out.as_ref(), "a b c");
assert!(!out.chars().any(char::is_control));
}
#[test]
fn forced_legacy_console_override_parses_known_values() {
assert_eq!(parse_forced_legacy_console(Some("1")), Some(true));

View file

@ -45,10 +45,23 @@ pub fn browser_open_likely_available() -> bool {
browser_open_likely_available_from_env(&env)
}
/// User-facing copy when the browser opener cannot run. Includes the full
/// URL on its own line so it is easy to select/copy in the TUI.
const BROWSER_UNAVAILABLE_NOTICE: &str = "Could not open a browser. Open this URL manually";
/// Multi-line copy for agent scrollback: notice, then the full URL alone
/// so it is easy to select/copy in the TUI.
pub fn browser_unavailable_message(url: &str) -> String {
format!("Could not open a browser. Open this URL manually:\n{url}")
format!("{BROWSER_UNAVAILABLE_NOTICE}:\n{url}")
}
/// Single-line welcome toast: URL first so prefix truncation keeps the
/// destination. `copied` is true only when clipboard delivery reported
/// success — never claim a copy that did not happen.
pub fn browser_unavailable_line(url: &str, copied: bool) -> String {
if copied {
format!("{url}{BROWSER_UNAVAILABLE_NOTICE} (URL copied)")
} else {
format!("{url}{BROWSER_UNAVAILABLE_NOTICE}")
}
}
/// Open a URL in the system's default browser/handler.
@ -59,10 +72,12 @@ pub fn browser_unavailable_message(url: &str) -> String {
///
/// Returns `true` when the opener was launched (or the test seam recorded
/// the URL). Returns `false` when the environment looks headless or spawn
/// fails — callers should show [`browser_unavailable_message`].
/// fails — callers should surface the URL via [`browser_unavailable_message`]
/// (scrollback) or [`browser_unavailable_line`] (welcome toast).
///
/// **Callers handling untrusted input** should call [`is_safe_to_open`]
/// first, or use [`open_url_if_safe`] / [`try_open_url`] which combine both.
#[allow(clippy::disallowed_methods)] // fire and forget; the child is reaped when this process exits
pub fn open_url(url: &str) -> bool {
// Test seam: PTY e2e must observe the open without launching a real
// browser. When set, append the URL to the file and skip the OS opener.
@ -156,6 +171,7 @@ fn build_open_path_command(path: &std::path::Path) -> std::process::Command {
/// expansion corrupts the percent-encoded session-directory segment in
/// imagine media paths (e.g. `…\C%3A%5CUsers…`).
/// - **macOS / Linux**: `open` / `xdg-open` open the file in its default app.
#[allow(clippy::disallowed_methods)] // fire and forget; the child is reaped when this process exits
pub fn open_path(path: &std::path::Path) -> bool {
// Never launch a real GUI app in tests.
#[cfg(test)]
@ -189,6 +205,7 @@ pub fn open_path(path: &std::path::Path) -> bool {
/// Prefer the on-disk path as-is. When the file is missing, open the parent
/// folder (no `/select`) so the user lands near the media instead of Home.
#[cfg(all(not(test), target_os = "windows"))]
#[allow(clippy::disallowed_methods)] // fire and forget; the child is reaped when this process exits
fn reveal_in_explorer(path: &std::path::Path) -> bool {
use std::os::windows::process::CommandExt;
@ -569,11 +586,34 @@ mod tests {
#[test]
fn browser_unavailable_message_includes_full_url() {
let url = "https://grok.com/supergrok?referrer=grok-build";
let msg = browser_unavailable_message(url);
assert!(msg.contains("Could not open a browser"));
assert!(msg.contains(url));
// URL on its own line for easy select/copy in the TUI.
assert!(msg.lines().any(|l| l == url));
assert_eq!(
browser_unavailable_message(url),
format!("{BROWSER_UNAVAILABLE_NOTICE}:\n{url}")
);
}
#[test]
fn browser_unavailable_line_is_url_first_single_line() {
let url = "https://grok.com/supergrok?referrer=grok-build";
let plain = browser_unavailable_line(url, false);
assert!(plain.starts_with(url), "{plain}");
assert!(!plain.contains('\n'), "{plain}");
assert!(
!plain.to_ascii_lowercase().contains("copied"),
"must not claim copy on failure: {plain}"
);
assert!(
plain.contains(BROWSER_UNAVAILABLE_NOTICE),
"shares notice stem with multi-line form: {plain}"
);
let with_copy = browser_unavailable_line(url, true);
assert!(with_copy.starts_with(url), "{with_copy}");
assert!(!with_copy.contains('\n'), "{with_copy}");
assert!(
with_copy.contains("URL copied"),
"copy claim only when copied=true: {with_copy}"
);
}
#[test]

View file

@ -42,6 +42,7 @@ fn run_tmux_bounded(
timeout: Duration,
) -> Result<TmuxCommandOutput, String> {
let mut command = build_tmux_command(command);
#[allow(clippy::disallowed_methods)] // bounded probe, waited on with a timeout
let mut child = command
.spawn()
.map_err(|error| format!("failed to run tmux: {error}"))?;