Synced from monorepo

Changes:
- Non-blocking coding-data sharing upsell banner
- Consolidate remediation in Doctor
- Auto mode defers fail-closed gate asks to the classifier
- Coalesce marketplace list fetches
- Allow removing a marketplace source by name
- Contain hung git marketplace sources (timeouts, non-blocking refresh, unbrick modal)
- Label failed workspace RPCs with error_kind
- Drop redundant explicit tonic/prost deps from xai-grok-shell
- Report real exit codes for completed background shells
- Narrow the date-rollover reminder to date-bearing templates
- Wire toolOverrides through the session and agent
- Security: Bash(git:*) allowlist matches whole command chain by prefix
- Split prompt-trigger telemetry and record classifier provenance
- Raise connectors-manager timeout to 60s
- Auto classifier honors recorded approvals for repeat actions
- Apply doctor fixes in the TUI
- Auto-mode classifier timeouts prompt instead of silently denying
- Scope subagent completion drains to the owning session
- Add the toolOverrides wire types
- Set client_identifier=grok-agent-sdk
- Accept both spellings of the workspace-teleport kill switch
- Persist one-shot occurrence journal
- Stop turns that poll the exact same tool call 16x in a row
- Copy compaction checkpoint files when forking sessions
- Auto-focus permission prompt from scrollback
- Esc cancels the running turn in non-vim and minimal modes
- List Ctrl+Z undo and redo in keyboard shortcuts
- Out-of-process macOS mic capture
- Show active auth mode on session-info
- Install the npm binary under $GROK_HOME
- Remove hover/click dead zones between dashboard items
- Route startup warnings to doctor
- Document [feedback.user] author identity config
- Extend bang command timeout
- Close combine-queued edit-hold race
- Integrate relocation recovery
- Expose privacy notice rollout flag
- Break harness discovery ref cycle so connections can idle-evict
- Shift/Alt+Enter inserts newline when editing a queued prompt
- Gate project Claude permissions on folder trust
- Echo response.create.event_id on response.created
- Toast when session creation fails from disk full
- Add shared test process lifecycle
- Enable dynamic workflows by default
- Add relocation transaction state machine
- Add shared test sandbox
- Surface auth failures on model-switch compact
- Persist durable scheduler expiry
- Confirm before removing extensions-modal items
- Re-run compact and prompt after login when compact hit expired auth
- Recap sends hosted tools under backend search
This commit is contained in:
grokkybara[bot] 2026-07-22 19:18:53 +01:00
commit a5727c5960
482 changed files with 37627 additions and 13402 deletions

View file

@ -76,7 +76,12 @@ fn debug_cmd(
home: &Path,
workdir: &Path,
extra: &[&str],
) -> tokio::process::Command {
) -> (tokio::process::Command, TestSandbox) {
let mut sandbox = TestSandbox::builder().mock_url(server.url()).build();
sandbox
.set_env("HOME", home)
.set_env("USERPROFILE", home)
.set_env("GROK_HOME", home.join(".grok"));
let mut cmd = tokio::process::Command::new(grok_binary());
cmd.args(["-p", "say hi", "--yolo", "--output-format", "json"])
.args(extra)
@ -87,14 +92,8 @@ fn debug_cmd(
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.kill_on_drop(true);
xai_grok_test_support::env::test_env_cmd_tokio(&mut cmd, &server.url(), home);
// Pin the home location and drop inherited firehose toggles for determinism.
cmd.env("GROK_HOME", home.join(".grok"));
cmd.env_remove("GROK_DEBUG_LOG");
cmd.env_remove("GROK_LOG_FILE");
cmd.env_remove("GROK_LOG_SAMPLING");
cmd.env_remove("GROK_HOOKS_LOG");
cmd
sandbox.apply_to_tokio_command(&mut cmd);
(cmd, sandbox)
}
/// Poll up to 50×100ms for the per-session firehose at `path` to become non-empty
@ -142,8 +141,8 @@ async fn debug_flag_enables_firehose_without_crashing() {
let workdir = git_workdir();
let home = TempDir::new().expect("create temp home");
let cmd = debug_cmd(&server, home.path(), workdir.path(), &["--debug"]);
let result = run_headless_with_cmd(cmd).await;
let (cmd, sandbox) = debug_cmd(&server, home.path(), workdir.workspace(), &["--debug"]);
let result = run_headless_in_sandbox(cmd, sandbox).await;
assert_headless_success(&result, "grok --debug headless", Some(&server));
assert_no_crashes(&result.stderr);
@ -159,8 +158,8 @@ async fn no_debug_flag_writes_no_debug_dir() {
let workdir = git_workdir();
let home = TempDir::new().expect("create temp home");
let cmd = debug_cmd(&server, home.path(), workdir.path(), &[]);
let result = run_headless_with_cmd(cmd).await;
let (cmd, sandbox) = debug_cmd(&server, home.path(), workdir.workspace(), &[]);
let result = run_headless_in_sandbox(cmd, sandbox).await;
assert_headless_success(&result, "grok headless (no --debug)", Some(&server));
assert!(
@ -182,19 +181,16 @@ async fn agent_session_writes_named_session_file() {
.await
.expect("start mock server");
let workdir = git_workdir();
let home = TempDir::new().expect("create temp home");
let grok_home = home.path().join(".grok");
let grok_home_str = grok_home.to_string_lossy().into_owned();
let mut sandbox = TestSandbox::new();
sandbox.set_env("GROK_DEBUG_LOG", "1");
let grok_home = sandbox.grok_home().to_path_buf();
let client = GrokStdioClient::spawn_with_home_and_env(
&server,
workdir.path(),
home,
&[("GROK_DEBUG_LOG", "1"), ("GROK_HOME", &grok_home_str)],
)
.await;
let client =
GrokStdioClient::spawn_with_sandbox(&server, workdir.workspace(), sandbox).await;
client.initialize_with_timeout().await;
let session_id = client.create_session_with_timeout(workdir.path()).await;
let session_id = client
.create_session_with_timeout(workdir.workspace())
.await;
// New session ids are UUID v7 (filesystem-safe), so the firehose file is
// named verbatim `<sessionId>.txt`.
let sid = session_id.0.to_string();
@ -231,24 +227,25 @@ async fn debug_flag_master_switch_enables_firehose() {
.await
.expect("start mock server");
let workdir = git_workdir();
let home = TempDir::new().expect("create temp home");
let grok_home = home.path().join(".grok");
let grok_home_str = grok_home.to_string_lossy().into_owned();
let sandbox = TestSandbox::new();
let grok_home = sandbox.grok_home().to_path_buf();
// Drive `grok --debug agent stdio`: the master switch (which runs before
// the agent dispatch) must be what enables the firehose — NOT a direct
// GROK_DEBUG_LOG env. The spawn helper clears inherited firehose toggles,
// so the `--debug` flag is the only thing that can enable logging here.
let client = GrokStdioClient::spawn_with_home_env_and_args(
// GROK_DEBUG_LOG env. The sandbox baseline excludes inherited firehose
// toggles, so the `--debug` flag is the only thing enabling logging here.
let client = GrokStdioClient::spawn_with_sandbox_env_and_args(
&server,
workdir.path(),
home,
&[("GROK_HOME", &grok_home_str)],
workdir.workspace(),
sandbox,
&[],
&["--debug"],
)
.await;
client.initialize_with_timeout().await;
let session_id = client.create_session_with_timeout(workdir.path()).await;
let session_id = client
.create_session_with_timeout(workdir.workspace())
.await;
let sid = session_id.0.to_string();
let _ = client.prompt_with_timeout(&session_id, "say hi").await;
@ -284,13 +281,13 @@ async fn debug_file_flag_writes_single_file_and_bypasses_routing() {
let explicit = home.path().join("explicit-firehose.txt");
let explicit_str = explicit.to_string_lossy().into_owned();
let cmd = debug_cmd(
let (cmd, sandbox) = debug_cmd(
&server,
home.path(),
workdir.path(),
workdir.workspace(),
&["--debug-file", &explicit_str],
);
let result = run_headless_with_cmd(cmd).await;
let result = run_headless_in_sandbox(cmd, sandbox).await;
assert_headless_success(&result, "grok --debug-file", Some(&server));
assert_no_crashes(&result.stderr);
@ -318,9 +315,9 @@ async fn grok_log_file_explicit_path_is_written() {
let home = TempDir::new().expect("create temp home");
let custom = home.path().join("custom-log-file.log");
let mut cmd = debug_cmd(&server, home.path(), workdir.path(), &[]);
cmd.env("GROK_LOG_FILE", &custom);
let result = run_headless_with_cmd(cmd).await;
let (cmd, mut sandbox) = debug_cmd(&server, home.path(), workdir.workspace(), &[]);
sandbox.set_env("GROK_LOG_FILE", &custom);
let result = run_headless_in_sandbox(cmd, sandbox).await;
assert_headless_success(&result, "grok GROK_LOG_FILE=path", Some(&server));
assert_no_crashes(&result.stderr);